|
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_imagelib_FrameBlender_h_ |
|
8 #define mozilla_imagelib_FrameBlender_h_ |
|
9 |
|
10 #include "mozilla/MemoryReporting.h" |
|
11 #include "gfxTypes.h" |
|
12 #include "FrameSequence.h" |
|
13 #include "nsCOMPtr.h" |
|
14 |
|
15 class imgFrame; |
|
16 |
|
17 namespace mozilla { |
|
18 namespace image { |
|
19 |
|
20 /** |
|
21 * FrameBlender stores and gives access to imgFrames. It also knows how to |
|
22 * blend frames from previous to next, looping if necessary. |
|
23 * |
|
24 * All logic about when and whether to blend are external to FrameBlender. |
|
25 */ |
|
26 class FrameBlender |
|
27 { |
|
28 public: |
|
29 |
|
30 /** |
|
31 * Create a new FrameBlender with a given frame sequence. |
|
32 * |
|
33 * If aSequenceToUse is not specified, it will be allocated automatically. |
|
34 */ |
|
35 FrameBlender(FrameSequence* aSequenceToUse = nullptr); |
|
36 ~FrameBlender(); |
|
37 |
|
38 bool DoBlend(nsIntRect* aDirtyRect, uint32_t aPrevFrameIndex, |
|
39 uint32_t aNextFrameIndex); |
|
40 |
|
41 already_AddRefed<FrameSequence> GetFrameSequence(); |
|
42 |
|
43 /** |
|
44 * Get the @aIndex-th frame, including (if applicable) any results of |
|
45 * blending. |
|
46 */ |
|
47 imgFrame* GetFrame(uint32_t aIndex) const; |
|
48 |
|
49 /** |
|
50 * Get the @aIndex-th frame in the frame index, ignoring results of blending. |
|
51 */ |
|
52 imgFrame* RawGetFrame(uint32_t aIndex) const; |
|
53 |
|
54 void InsertFrame(uint32_t framenum, imgFrame* aFrame); |
|
55 void RemoveFrame(uint32_t framenum); |
|
56 imgFrame* SwapFrame(uint32_t framenum, imgFrame* aFrame); |
|
57 void ClearFrames(); |
|
58 |
|
59 /* The total number of frames in this image. */ |
|
60 uint32_t GetNumFrames() const; |
|
61 |
|
62 /* |
|
63 * Returns the frame's adjusted timeout. If the animation loops and the timeout |
|
64 * falls in between a certain range then the timeout is adjusted so that |
|
65 * it's never 0. If the animation does not loop then no adjustments are made. |
|
66 */ |
|
67 int32_t GetTimeoutForFrame(uint32_t framenum) const; |
|
68 |
|
69 /* |
|
70 * Set number of times to loop the image. |
|
71 * @note -1 means loop forever. |
|
72 */ |
|
73 void SetLoopCount(int32_t aLoopCount); |
|
74 int32_t GetLoopCount() const; |
|
75 |
|
76 void Discard(); |
|
77 |
|
78 void SetSize(nsIntSize aSize) { mSize = aSize; } |
|
79 |
|
80 size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation, |
|
81 mozilla::MallocSizeOf aMallocSizeOf) const; |
|
82 |
|
83 void ResetAnimation(); |
|
84 |
|
85 // "Blend" method indicates how the current image is combined with the |
|
86 // previous image. |
|
87 enum FrameBlendMethod { |
|
88 // All color components of the frame, including alpha, overwrite the current |
|
89 // contents of the frame's output buffer region |
|
90 kBlendSource = 0, |
|
91 |
|
92 // The frame should be composited onto the output buffer based on its alpha, |
|
93 // using a simple OVER operation |
|
94 kBlendOver |
|
95 }; |
|
96 |
|
97 enum FrameDisposalMethod { |
|
98 kDisposeClearAll = -1, // Clear the whole image, revealing |
|
99 // what was there before the gif displayed |
|
100 kDisposeNotSpecified, // Leave frame, let new frame draw on top |
|
101 kDisposeKeep, // Leave frame, let new frame draw on top |
|
102 kDisposeClear, // Clear the frame's area, revealing bg |
|
103 kDisposeRestorePrevious // Restore the previous (composited) frame |
|
104 }; |
|
105 |
|
106 // A hint as to whether an individual frame is entirely opaque, or requires |
|
107 // alpha blending. |
|
108 enum FrameAlpha { |
|
109 kFrameHasAlpha, |
|
110 kFrameOpaque |
|
111 }; |
|
112 |
|
113 private: |
|
114 |
|
115 struct Anim |
|
116 { |
|
117 //! Track the last composited frame for Optimizations (See DoComposite code) |
|
118 int32_t lastCompositedFrameIndex; |
|
119 |
|
120 /** For managing blending of frames |
|
121 * |
|
122 * Some animations will use the compositingFrame to composite images |
|
123 * and just hand this back to the caller when it is time to draw the frame. |
|
124 * NOTE: When clearing compositingFrame, remember to set |
|
125 * lastCompositedFrameIndex to -1. Code assume that if |
|
126 * lastCompositedFrameIndex >= 0 then compositingFrame exists. |
|
127 */ |
|
128 FrameDataPair compositingFrame; |
|
129 |
|
130 /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS |
|
131 * |
|
132 * The Previous Frame (all frames composited up to the current) needs to be |
|
133 * stored in cases where the image specifies it wants the last frame back |
|
134 * when it's done with the current frame. |
|
135 */ |
|
136 FrameDataPair compositingPrevFrame; |
|
137 |
|
138 Anim() : |
|
139 lastCompositedFrameIndex(-1) |
|
140 {} |
|
141 }; |
|
142 |
|
143 void EnsureAnimExists(); |
|
144 |
|
145 /** Clears an area of <aFrame> with transparent black. |
|
146 * |
|
147 * @param aFrameData Target Frame data |
|
148 * @param aFrameRect The rectangle of the data pointed ot by aFrameData |
|
149 * |
|
150 * @note Does also clears the transparancy mask |
|
151 */ |
|
152 static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect); |
|
153 |
|
154 //! @overload |
|
155 static void ClearFrame(uint8_t* aFrameData, const nsIntRect& aFrameRect, const nsIntRect &aRectToClear); |
|
156 |
|
157 //! Copy one frames's image and mask into another |
|
158 static bool CopyFrameImage(const uint8_t *aDataSrc, const nsIntRect& aRectSrc, |
|
159 uint8_t *aDataDest, const nsIntRect& aRectDest); |
|
160 |
|
161 /** |
|
162 * Draws one frames's image to into another, at the position specified by |
|
163 * aSrcRect. |
|
164 * |
|
165 * @aSrcData the raw data of the current frame being drawn |
|
166 * @aSrcRect the size of the source frame, and the position of that frame in |
|
167 * the composition frame |
|
168 * @aSrcPaletteLength the length (in bytes) of the palette at the beginning |
|
169 * of the source data (0 if image is not paletted) |
|
170 * @aSrcHasAlpha whether the source data represents an image with alpha |
|
171 * @aDstPixels the raw data of the composition frame where the current frame |
|
172 * is drawn into (32-bit ARGB) |
|
173 * @aDstRect the size of the composition frame |
|
174 * @aBlendMethod the blend method for how to blend src on the composition frame. |
|
175 */ |
|
176 static nsresult DrawFrameTo(const uint8_t *aSrcData, const nsIntRect& aSrcRect, |
|
177 uint32_t aSrcPaletteLength, bool aSrcHasAlpha, |
|
178 uint8_t *aDstPixels, const nsIntRect& aDstRect, |
|
179 FrameBlendMethod aBlendMethod); |
|
180 |
|
181 private: // data |
|
182 //! All the frames of the image |
|
183 nsRefPtr<FrameSequence> mFrames; |
|
184 nsIntSize mSize; |
|
185 Anim* mAnim; |
|
186 int32_t mLoopCount; |
|
187 }; |
|
188 |
|
189 } // namespace image |
|
190 } // namespace mozilla |
|
191 |
|
192 #endif /* mozilla_imagelib_FrameBlender_h_ */ |