Line data Source code
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 : /**
26 : * @return a FrameTimeout of zero. This should be used only for math
27 : * involving FrameTimeout values. You can't obtain a zero FrameTimeout from
28 : * FromRawMilliseconds().
29 : */
30 33 : static FrameTimeout Zero() { return FrameTimeout(0); }
31 :
32 : /// @return an infinite FrameTimeout.
33 305 : static FrameTimeout Forever() { return FrameTimeout(-1); }
34 :
35 : /// @return a FrameTimeout obtained by normalizing a raw timeout value.
36 144 : static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds)
37 : {
38 : // Normalize all infinite timeouts to the same value.
39 144 : if (aRawMilliseconds < 0) {
40 0 : return FrameTimeout::Forever();
41 : }
42 :
43 : // Very small timeout values are problematic for two reasons: we don't want
44 : // to burn energy redrawing animated images extremely fast, and broken tools
45 : // generate these values when they actually want a "default" value, so such
46 : // images won't play back right without normalization. For some context,
47 : // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical
48 : // behavior of IE and Opera was:
49 : // IE 6/Win:
50 : // 10 - 50ms is normalized to 100ms.
51 : // >50ms is used unnormalized.
52 : // Opera 7 final/Win:
53 : // 10ms is normalized to 100ms.
54 : // >10ms is used unnormalized.
55 144 : if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10 ) {
56 36 : return FrameTimeout(100);
57 : }
58 :
59 : // The provided timeout value is OK as-is.
60 108 : return FrameTimeout(aRawMilliseconds);
61 : }
62 :
63 272 : bool operator==(const FrameTimeout& aOther) const
64 : {
65 272 : return mTimeout == aOther.mTimeout;
66 : }
67 :
68 22 : bool operator!=(const FrameTimeout& aOther) const { return !(*this == aOther); }
69 :
70 48 : FrameTimeout operator+(const FrameTimeout& aOther)
71 : {
72 48 : if (*this == Forever() || aOther == Forever()) {
73 0 : return Forever();
74 : }
75 :
76 48 : return FrameTimeout(mTimeout + aOther.mTimeout);
77 : }
78 :
79 48 : FrameTimeout& operator+=(const FrameTimeout& aOther)
80 : {
81 48 : *this = *this + aOther;
82 48 : return *this;
83 : }
84 :
85 : /**
86 : * @return this FrameTimeout's value in milliseconds. Illegal to call on a
87 : * an infinite FrameTimeout value.
88 : */
89 76 : uint32_t AsMilliseconds() const
90 : {
91 76 : if (*this == Forever()) {
92 0 : MOZ_ASSERT_UNREACHABLE("Calling AsMilliseconds() on an infinite FrameTimeout");
93 : return 100; // Fail to something sane.
94 : }
95 :
96 76 : return uint32_t(mTimeout);
97 : }
98 :
99 : /**
100 : * @return this FrameTimeout value encoded so that non-negative values
101 : * represent a timeout in milliseconds, and -1 represents an infinite
102 : * timeout.
103 : *
104 : * XXX(seth): This is a backwards compatibility hack that should be removed.
105 : */
106 4 : int32_t AsEncodedValueDeprecated() const { return mTimeout; }
107 :
108 : private:
109 530 : explicit FrameTimeout(int32_t aTimeout)
110 530 : : mTimeout(aTimeout)
111 530 : { }
112 :
113 : int32_t mTimeout;
114 : };
115 :
116 : } // namespace image
117 : } // namespace mozilla
118 :
119 : #endif // mozilla_image_FrameTimeout_h
|