Bug 1724948 [wpt PR 29970] - Change `Tests.prototype.all_done` to require either...
[gecko.git] / image / FrameTimeout.h
blob8cc38e203aab57f533e55ca0b42a6043ca51fdee
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
7 #ifndef mozilla_image_FrameTimeout_h
8 #define mozilla_image_FrameTimeout_h
10 #include <stdint.h>
11 #include "mozilla/Assertions.h"
13 namespace mozilla {
14 namespace image {
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.
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().
29 static FrameTimeout Zero() { return FrameTimeout(0); }
31 /// @return an infinite FrameTimeout.
32 static FrameTimeout Forever() { return FrameTimeout(-1); }
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();
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);
57 // The provided timeout value is OK as-is.
58 return FrameTimeout(aRawMilliseconds);
61 bool operator==(const FrameTimeout& aOther) const {
62 return mTimeout == aOther.mTimeout;
65 bool operator!=(const FrameTimeout& aOther) const {
66 return !(*this == aOther);
69 FrameTimeout operator+(const FrameTimeout& aOther) {
70 if (*this == Forever() || aOther == Forever()) {
71 return Forever();
74 return FrameTimeout(mTimeout + aOther.mTimeout);
77 FrameTimeout& operator+=(const FrameTimeout& aOther) {
78 *this = *this + aOther;
79 return *this;
82 /**
83 * @return this FrameTimeout's value in milliseconds. Illegal to call on a
84 * an infinite FrameTimeout value.
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.
93 return uint32_t(mTimeout);
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.
101 * XXX(seth): This is a backwards compatibility hack that should be removed.
103 int32_t AsEncodedValueDeprecated() const { return mTimeout; }
105 private:
106 explicit FrameTimeout(int32_t aTimeout) : mTimeout(aTimeout) {}
108 int32_t mTimeout;
111 } // namespace image
112 } // namespace mozilla
114 #endif // mozilla_image_FrameTimeout_h