FrameTimeout.h (3709B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_image_FrameTimeout_h 8 #define mozilla_image_FrameTimeout_h 9 10 #include <stdint.h> 11 #include "mozilla/Assertions.h" 12 13 namespace mozilla { 14 namespace image { 15 16 /** 17 * FrameTimeout wraps a frame timeout value (measured in milliseconds) after 18 * first normalizing it. This normalization is necessary because some tools 19 * generate incorrect frame timeout values which we nevertheless have to 20 * support. For this reason, code that deals with frame timeouts should always 21 * use a FrameTimeout value rather than the raw value from the image header. 22 */ 23 struct FrameTimeout { 24 /** 25 * @return a FrameTimeout of zero. This should be used only for math 26 * involving FrameTimeout values. You can't obtain a zero FrameTimeout from 27 * FromRawMilliseconds(). 28 */ 29 static FrameTimeout Zero() { return FrameTimeout(0); } 30 31 /// @return an infinite FrameTimeout. 32 static FrameTimeout Forever() { return FrameTimeout(-1); } 33 34 /// @return a FrameTimeout obtained by normalizing a raw timeout value. 35 static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds) { 36 // Normalize all infinite timeouts to the same value. 37 if (aRawMilliseconds < 0) { 38 return FrameTimeout::Forever(); 39 } 40 41 // Very small timeout values are problematic for two reasons: we don't want 42 // to burn energy redrawing animated images extremely fast, and broken tools 43 // generate these values when they actually want a "default" value, so such 44 // images won't play back right without normalization. For some context, 45 // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical 46 // behavior of IE and Opera was: 47 // IE 6/Win: 48 // 10 - 50ms is normalized to 100ms. 49 // >50ms is used unnormalized. 50 // Opera 7 final/Win: 51 // 10ms is normalized to 100ms. 52 // >10ms is used unnormalized. 53 if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10) { 54 return FrameTimeout(100); 55 } 56 57 // The provided timeout value is OK as-is. 58 return FrameTimeout(aRawMilliseconds); 59 } 60 61 bool operator==(const FrameTimeout& aOther) const { 62 return mTimeout == aOther.mTimeout; 63 } 64 65 bool operator!=(const FrameTimeout& aOther) const { 66 return !(*this == aOther); 67 } 68 69 FrameTimeout operator+(const FrameTimeout& aOther) { 70 if (*this == Forever() || aOther == Forever()) { 71 return Forever(); 72 } 73 74 return FrameTimeout(mTimeout + aOther.mTimeout); 75 } 76 77 FrameTimeout& operator+=(const FrameTimeout& aOther) { 78 *this = *this + aOther; 79 return *this; 80 } 81 82 /** 83 * @return this FrameTimeout's value in milliseconds. Illegal to call on a 84 * an infinite FrameTimeout value. 85 */ 86 uint32_t AsMilliseconds() const { 87 if (*this == Forever()) { 88 MOZ_ASSERT_UNREACHABLE( 89 "Calling AsMilliseconds() on an infinite FrameTimeout"); 90 return 100; // Fail to something sane. 91 } 92 93 return uint32_t(mTimeout); 94 } 95 96 /** 97 * @return this FrameTimeout value encoded so that non-negative values 98 * represent a timeout in milliseconds, and -1 represents an infinite 99 * timeout. 100 * 101 * XXX(seth): This is a backwards compatibility hack that should be removed. 102 */ 103 int32_t AsEncodedValueDeprecated() const { return mTimeout; } 104 105 private: 106 explicit FrameTimeout(int32_t aTimeout) : mTimeout(aTimeout) {} 107 108 int32_t mTimeout; 109 }; 110 111 } // namespace image 112 } // namespace mozilla 113 114 #endif // mozilla_image_FrameTimeout_h