1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/FrameAnimator.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,174 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_imagelib_FrameAnimator_h_ 1.11 +#define mozilla_imagelib_FrameAnimator_h_ 1.12 + 1.13 +#include "mozilla/TimeStamp.h" 1.14 +#include "nsRect.h" 1.15 + 1.16 +namespace mozilla { 1.17 +namespace image { 1.18 + 1.19 +class FrameBlender; 1.20 + 1.21 +class FrameAnimator 1.22 +{ 1.23 +public: 1.24 + FrameAnimator(FrameBlender& aBlender, uint16_t aAnimationMode); 1.25 + 1.26 + /** 1.27 + * Return value from RequestRefresh. Tells callers what happened in that call 1.28 + * to RequestRefresh. 1.29 + */ 1.30 + struct RefreshResult 1.31 + { 1.32 + // The dirty rectangle to be re-drawn after this RequestRefresh(). 1.33 + nsIntRect dirtyRect; 1.34 + 1.35 + // Whether any frame changed, and hence the dirty rect was set. 1.36 + bool frameAdvanced : 1; 1.37 + 1.38 + // Whether the animation has finished playing. 1.39 + bool animationFinished : 1; 1.40 + 1.41 + // Whether an error has occurred when trying to advance a frame. Note that 1.42 + // errors do not, on their own, end the animation. 1.43 + bool error : 1; 1.44 + 1.45 + RefreshResult() 1.46 + : frameAdvanced(false) 1.47 + , animationFinished(false) 1.48 + , error(false) 1.49 + {} 1.50 + 1.51 + void Accumulate(const RefreshResult& other) 1.52 + { 1.53 + frameAdvanced = frameAdvanced || other.frameAdvanced; 1.54 + animationFinished = animationFinished || other.animationFinished; 1.55 + error = error || other.error; 1.56 + dirtyRect = dirtyRect.Union(other.dirtyRect); 1.57 + } 1.58 + }; 1.59 + 1.60 + /** 1.61 + * Re-evaluate what frame we're supposed to be on, and do whatever blending 1.62 + * is necessary to get us to that frame. 1.63 + * 1.64 + * Returns the result of that blending, including whether the current frame 1.65 + * changed and what the resulting dirty rectangle is. 1.66 + */ 1.67 + RefreshResult RequestRefresh(const mozilla::TimeStamp& aTime); 1.68 + 1.69 + /** 1.70 + * Call when this image is finished decoding so we know that there aren't any 1.71 + * more frames coming. 1.72 + */ 1.73 + void SetDoneDecoding(bool aDone); 1.74 + 1.75 + /** 1.76 + * Call when you need to re-start animating. Ensures we start from the first 1.77 + * frame. 1.78 + */ 1.79 + void ResetAnimation(); 1.80 + 1.81 + /** 1.82 + * The animation mode of the image. 1.83 + * 1.84 + * Constants defined in imgIContainer.idl. 1.85 + */ 1.86 + void SetAnimationMode(uint16_t aAnimationMode); 1.87 + 1.88 + /** 1.89 + * Set the area to refresh when we loop around to the first frame. 1.90 + */ 1.91 + void SetFirstFrameRefreshArea(const nsIntRect& aRect); 1.92 + 1.93 + /** 1.94 + * Union the area to refresh when we loop around to the first frame with this 1.95 + * rect. 1.96 + */ 1.97 + void UnionFirstFrameRefreshArea(const nsIntRect& aRect); 1.98 + 1.99 + /** 1.100 + * If the animation frame time has not yet been set, set it to 1.101 + * TimeStamp::Now(). 1.102 + */ 1.103 + void InitAnimationFrameTimeIfNecessary(); 1.104 + 1.105 + /** 1.106 + * Set the animation frame time to @aTime. 1.107 + */ 1.108 + void SetAnimationFrameTime(const TimeStamp& aTime); 1.109 + 1.110 + /** 1.111 + * The current frame we're on, from 0 to (numFrames - 1). 1.112 + */ 1.113 + uint32_t GetCurrentAnimationFrameIndex() const; 1.114 + 1.115 + /** 1.116 + * Get the area we refresh when we loop around to the first frame. 1.117 + */ 1.118 + nsIntRect GetFirstFrameRefreshArea() const; 1.119 + 1.120 +private: // methods 1.121 + /** 1.122 + * Gets the length of a single loop of this image, in milliseconds. 1.123 + * 1.124 + * If this image is not finished decoding, is not animated, or it is animated 1.125 + * but does not loop, returns -1. Can return 0 in the case of an animated image 1.126 + * that has a 0ms delay between its frames and does not loop. 1.127 + */ 1.128 + int32_t GetSingleLoopTime() const; 1.129 + 1.130 + /** 1.131 + * Advances the animation. Typically, this will advance a single frame, but it 1.132 + * may advance multiple frames. This may happen if we have infrequently 1.133 + * "ticking" refresh drivers (e.g. in background tabs), or extremely short- 1.134 + * lived animation frames. 1.135 + * 1.136 + * @param aTime the time that the animation should advance to. This will 1.137 + * typically be <= TimeStamp::Now(). 1.138 + * 1.139 + * @returns a RefreshResult that shows whether the frame was successfully 1.140 + * advanced, and its resulting dirty rect. 1.141 + */ 1.142 + RefreshResult AdvanceFrame(mozilla::TimeStamp aTime); 1.143 + 1.144 + /** 1.145 + * Get the time the frame we're currently displaying is supposed to end. 1.146 + * 1.147 + * In the error case, returns an "infinity" timestamp. 1.148 + */ 1.149 + mozilla::TimeStamp GetCurrentImgFrameEndTime() const; 1.150 + 1.151 +private: // data 1.152 + //! Area of the first frame that needs to be redrawn on subsequent loops. 1.153 + nsIntRect mFirstFrameRefreshArea; 1.154 + 1.155 + //! the time that the animation advanced to the current frame 1.156 + TimeStamp mCurrentAnimationFrameTime; 1.157 + 1.158 + //! The current frame index we're on. 0 to (numFrames - 1). 1.159 + uint32_t mCurrentAnimationFrameIndex; 1.160 + 1.161 + //! number of loops remaining before animation stops (-1 no stop) 1.162 + int32_t mLoopCounter; 1.163 + 1.164 + //! All the frames of the image, shared with our owner 1.165 + FrameBlender& mFrameBlender; 1.166 + 1.167 + //! The animation mode of this image. Constants defined in imgIContainer. 1.168 + uint16_t mAnimationMode; 1.169 + 1.170 + //! Whether this image is done being decoded. 1.171 + bool mDoneDecoding; 1.172 +}; 1.173 + 1.174 +} // namespace image 1.175 +} // namespace mozilla 1.176 + 1.177 +#endif /* mozilla_imagelib_FrameAnimator_h_ */