Blame image/FrameTimeout.h

Packit f0b94e
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
Packit f0b94e
 *
Packit f0b94e
 * This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#ifndef mozilla_image_FrameTimeout_h
Packit f0b94e
#define mozilla_image_FrameTimeout_h
Packit f0b94e
Packit f0b94e
#include <stdint.h>
Packit f0b94e
#include "mozilla/Assertions.h"
Packit f0b94e
Packit f0b94e
namespace mozilla {
Packit f0b94e
namespace image {
Packit f0b94e
Packit f0b94e
/**
Packit f0b94e
 * FrameTimeout wraps a frame timeout value (measured in milliseconds) after
Packit f0b94e
 * first normalizing it. This normalization is necessary because some tools
Packit f0b94e
 * generate incorrect frame timeout values which we nevertheless have to
Packit f0b94e
 * support. For this reason, code that deals with frame timeouts should always
Packit f0b94e
 * use a FrameTimeout value rather than the raw value from the image header.
Packit f0b94e
 */
Packit f0b94e
struct FrameTimeout {
Packit f0b94e
  /**
Packit f0b94e
   * @return a FrameTimeout of zero. This should be used only for math
Packit f0b94e
   * involving FrameTimeout values. You can't obtain a zero FrameTimeout from
Packit f0b94e
   * FromRawMilliseconds().
Packit f0b94e
   */
Packit f0b94e
  static FrameTimeout Zero() { return FrameTimeout(0); }
Packit f0b94e
Packit f0b94e
  /// @return an infinite FrameTimeout.
Packit f0b94e
  static FrameTimeout Forever() { return FrameTimeout(-1); }
Packit f0b94e
Packit f0b94e
  /// @return a FrameTimeout obtained by normalizing a raw timeout value.
Packit f0b94e
  static FrameTimeout FromRawMilliseconds(int32_t aRawMilliseconds) {
Packit f0b94e
    // Normalize all infinite timeouts to the same value.
Packit f0b94e
    if (aRawMilliseconds < 0) {
Packit f0b94e
      return FrameTimeout::Forever();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    // Very small timeout values are problematic for two reasons: we don't want
Packit f0b94e
    // to burn energy redrawing animated images extremely fast, and broken tools
Packit f0b94e
    // generate these values when they actually want a "default" value, so such
Packit f0b94e
    // images won't play back right without normalization. For some context,
Packit f0b94e
    // see bug 890743, bug 125137, bug 139677, and bug 207059. The historical
Packit f0b94e
    // behavior of IE and Opera was:
Packit f0b94e
    //   IE 6/Win:
Packit f0b94e
    //     10 - 50ms is normalized to 100ms.
Packit f0b94e
    //     >50ms is used unnormalized.
Packit f0b94e
    //   Opera 7 final/Win:
Packit f0b94e
    //     10ms is normalized to 100ms.
Packit f0b94e
    //     >10ms is used unnormalized.
Packit f0b94e
    if (aRawMilliseconds >= 0 && aRawMilliseconds <= 10) {
Packit f0b94e
      return FrameTimeout(100);
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    // The provided timeout value is OK as-is.
Packit f0b94e
    return FrameTimeout(aRawMilliseconds);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  bool operator==(const FrameTimeout& aOther) const {
Packit f0b94e
    return mTimeout == aOther.mTimeout;
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  bool operator!=(const FrameTimeout& aOther) const {
Packit f0b94e
    return !(*this == aOther);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  FrameTimeout operator+(const FrameTimeout& aOther) {
Packit f0b94e
    if (*this == Forever() || aOther == Forever()) {
Packit f0b94e
      return Forever();
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    return FrameTimeout(mTimeout + aOther.mTimeout);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  FrameTimeout& operator+=(const FrameTimeout& aOther) {
Packit f0b94e
    *this = *this + aOther;
Packit f0b94e
    return *this;
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @return this FrameTimeout's value in milliseconds. Illegal to call on a
Packit f0b94e
   * an infinite FrameTimeout value.
Packit f0b94e
   */
Packit f0b94e
  uint32_t AsMilliseconds() const {
Packit f0b94e
    if (*this == Forever()) {
Packit f0b94e
      MOZ_ASSERT_UNREACHABLE(
Packit f0b94e
          "Calling AsMilliseconds() on an infinite FrameTimeout");
Packit f0b94e
      return 100;  // Fail to something sane.
Packit f0b94e
    }
Packit f0b94e
Packit f0b94e
    return uint32_t(mTimeout);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  /**
Packit f0b94e
   * @return this FrameTimeout value encoded so that non-negative values
Packit f0b94e
   * represent a timeout in milliseconds, and -1 represents an infinite
Packit f0b94e
   * timeout.
Packit f0b94e
   *
Packit f0b94e
   * XXX(seth): This is a backwards compatibility hack that should be removed.
Packit f0b94e
   */
Packit f0b94e
  int32_t AsEncodedValueDeprecated() const { return mTimeout; }
Packit f0b94e
Packit f0b94e
 private:
Packit f0b94e
  explicit FrameTimeout(int32_t aTimeout) : mTimeout(aTimeout) {}
Packit f0b94e
Packit f0b94e
  int32_t mTimeout;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
}  // namespace image
Packit f0b94e
}  // namespace mozilla
Packit f0b94e
Packit f0b94e
#endif  // mozilla_image_FrameTimeout_h