|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef MOZILLA_IMAGELIB_DECODER_H_ |
|
7 #define MOZILLA_IMAGELIB_DECODER_H_ |
|
8 |
|
9 #include "RasterImage.h" |
|
10 #include "imgDecoderObserver.h" |
|
11 #include "mozilla/RefPtr.h" |
|
12 #include "DecodeStrategy.h" |
|
13 #include "ImageMetadata.h" |
|
14 #include "Orientation.h" |
|
15 #include "mozilla/Telemetry.h" |
|
16 |
|
17 namespace mozilla { |
|
18 namespace image { |
|
19 |
|
20 class Decoder |
|
21 { |
|
22 public: |
|
23 |
|
24 Decoder(RasterImage& aImage); |
|
25 virtual ~Decoder(); |
|
26 |
|
27 /** |
|
28 * Initialize an image decoder. Decoders may not be re-initialized. |
|
29 * |
|
30 * Notifications Sent: TODO |
|
31 */ |
|
32 void Init(); |
|
33 |
|
34 /** |
|
35 * Initializes a decoder whose image and observer is already being used by a |
|
36 * parent decoder. Decoders may not be re-initialized. |
|
37 * |
|
38 * Notifications Sent: TODO |
|
39 */ |
|
40 void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength, |
|
41 uint32_t* colormap, uint32_t colormapSize, |
|
42 imgFrame* currentFrame); |
|
43 |
|
44 /** |
|
45 * Writes data to the decoder. |
|
46 * |
|
47 * @param aBuffer buffer containing the data to be written |
|
48 * @param aCount the number of bytes to write |
|
49 * |
|
50 * Any errors are reported by setting the appropriate state on the decoder. |
|
51 * |
|
52 * Notifications Sent: TODO |
|
53 */ |
|
54 void Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); |
|
55 |
|
56 /** |
|
57 * Informs the decoder that all the data has been written. |
|
58 * |
|
59 * Notifications Sent: TODO |
|
60 */ |
|
61 void Finish(RasterImage::eShutdownIntent aShutdownIntent); |
|
62 |
|
63 /** |
|
64 * Informs the shared decoder that all the data has been written. |
|
65 * Should only be used if InitSharedDecoder was useed |
|
66 * |
|
67 * Notifications Sent: TODO |
|
68 */ |
|
69 void FinishSharedDecoder(); |
|
70 |
|
71 /** |
|
72 * Tells the decoder to flush any pending invalidations. This informs the image |
|
73 * frame of its decoded region, and sends the appropriate OnDataAvailable call |
|
74 * to consumers. |
|
75 * |
|
76 * This can be called any time when we're midway through decoding a frame, |
|
77 * and must be called after finishing a frame (before starting a new one). |
|
78 */ |
|
79 void FlushInvalidations(); |
|
80 |
|
81 // We're not COM-y, so we don't get refcounts by default |
|
82 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder) |
|
83 |
|
84 /* |
|
85 * State. |
|
86 */ |
|
87 |
|
88 // If we're doing a "size decode", we more or less pass through the image |
|
89 // data, stopping only to scoop out the image dimensions. A size decode |
|
90 // must be enabled by SetSizeDecode() _before_calling Init(). |
|
91 bool IsSizeDecode() { return mSizeDecode; } |
|
92 void SetSizeDecode(bool aSizeDecode) |
|
93 { |
|
94 NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!"); |
|
95 mSizeDecode = aSizeDecode; |
|
96 } |
|
97 |
|
98 void SetObserver(imgDecoderObserver* aObserver) |
|
99 { |
|
100 MOZ_ASSERT(aObserver); |
|
101 mObserver = aObserver; |
|
102 } |
|
103 |
|
104 // The number of frames we have, including anything in-progress. Thus, this |
|
105 // is only 0 if we haven't begun any frames. |
|
106 uint32_t GetFrameCount() { return mFrameCount; } |
|
107 |
|
108 // The number of complete frames we have (ie, not including anything in-progress). |
|
109 uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; } |
|
110 |
|
111 // Error tracking |
|
112 bool HasError() { return HasDataError() || HasDecoderError(); } |
|
113 bool HasDataError() { return mDataError; } |
|
114 bool HasDecoderError() { return NS_FAILED(mFailCode); } |
|
115 nsresult GetDecoderError() { return mFailCode; } |
|
116 void PostResizeError() { PostDataError(); } |
|
117 bool GetDecodeDone() const { |
|
118 return mDecodeDone; |
|
119 } |
|
120 |
|
121 // flags. Keep these in sync with imgIContainer.idl. |
|
122 // SetDecodeFlags must be called before Init(), otherwise |
|
123 // default flags are assumed. |
|
124 enum { |
|
125 DECODER_NO_PREMULTIPLY_ALPHA = 0x2, // imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA |
|
126 DECODER_NO_COLORSPACE_CONVERSION = 0x4 // imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION |
|
127 }; |
|
128 |
|
129 enum DecodeStyle { |
|
130 PROGRESSIVE, // produce intermediate frames representing the partial state of the image |
|
131 SEQUENTIAL // decode to final image immediately |
|
132 }; |
|
133 |
|
134 void SetDecodeFlags(uint32_t aFlags) { mDecodeFlags = aFlags; } |
|
135 uint32_t GetDecodeFlags() { return mDecodeFlags; } |
|
136 |
|
137 bool HasSize() const { return mImageMetadata.HasSize(); } |
|
138 void SetSizeOnImage(); |
|
139 |
|
140 // Use HistogramCount as an invalid Histogram ID |
|
141 virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; } |
|
142 |
|
143 ImageMetadata& GetImageMetadata() { return mImageMetadata; } |
|
144 |
|
145 // Tell the decoder infrastructure to allocate a frame. By default, frame 0 |
|
146 // is created as an ARGB frame with no offset and with size width * height. |
|
147 // If decoders need something different, they must ask for it. |
|
148 // This is called by decoders when they need a new frame. These decoders |
|
149 // must then save the data they have been sent but not yet processed and |
|
150 // return from WriteInternal. When the new frame is created, WriteInternal |
|
151 // will be called again with nullptr and 0 as arguments. |
|
152 void NeedNewFrame(uint32_t frameNum, uint32_t x_offset, uint32_t y_offset, |
|
153 uint32_t width, uint32_t height, |
|
154 gfxImageFormat format, |
|
155 uint8_t palette_depth = 0); |
|
156 |
|
157 virtual bool NeedsNewFrame() const { return mNeedsNewFrame; } |
|
158 |
|
159 // Try to allocate a frame as described in mNewFrameData and return the |
|
160 // status code from that attempt. Clears mNewFrameData. |
|
161 virtual nsresult AllocateFrame(); |
|
162 |
|
163 // Called when a chunk of decoding has been done and the frame needs to be |
|
164 // marked as dirty. Must be called only on the main thread. |
|
165 void MarkFrameDirty(); |
|
166 |
|
167 imgFrame* GetCurrentFrame() const { return mCurrentFrame; } |
|
168 |
|
169 protected: |
|
170 |
|
171 /* |
|
172 * Internal hooks. Decoder implementations may override these and |
|
173 * only these methods. |
|
174 */ |
|
175 virtual void InitInternal(); |
|
176 virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); |
|
177 virtual void FinishInternal(); |
|
178 |
|
179 /* |
|
180 * Progress notifications. |
|
181 */ |
|
182 |
|
183 // Called by decoders when they determine the size of the image. Informs |
|
184 // the image of its size and sends notifications. |
|
185 void PostSize(int32_t aWidth, |
|
186 int32_t aHeight, |
|
187 Orientation aOrientation = Orientation()); |
|
188 |
|
189 // Called by decoders when they begin a frame. Informs the image, sends |
|
190 // notifications, and does internal book-keeping. |
|
191 void PostFrameStart(); |
|
192 |
|
193 // Called by decoders when they end a frame. Informs the image, sends |
|
194 // notifications, and does internal book-keeping. |
|
195 // Specify whether this frame is opaque as an optimization. |
|
196 // For animated images, specify the disposal, blend method and timeout for |
|
197 // this frame. |
|
198 void PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha = FrameBlender::kFrameHasAlpha, |
|
199 FrameBlender::FrameDisposalMethod aDisposalMethod = FrameBlender::kDisposeKeep, |
|
200 int32_t aTimeout = 0, |
|
201 FrameBlender::FrameBlendMethod aBlendMethod = FrameBlender::kBlendOver); |
|
202 |
|
203 // Called by the decoders when they have a region to invalidate. We may not |
|
204 // actually pass these invalidations on right away. |
|
205 void PostInvalidation(nsIntRect& aRect); |
|
206 |
|
207 // Called by the decoders when they have successfully decoded the image. This |
|
208 // may occur as the result of the decoder getting to the appropriate point in |
|
209 // the stream, or by us calling FinishInternal(). |
|
210 // |
|
211 // May not be called mid-frame. |
|
212 // |
|
213 // For animated images, specify the loop count. -1 means loop forever, 0 |
|
214 // means a single iteration, stopping on the last frame. |
|
215 void PostDecodeDone(int32_t aLoopCount = 0); |
|
216 |
|
217 // Data errors are the fault of the source data, decoder errors are our fault |
|
218 void PostDataError(); |
|
219 void PostDecoderError(nsresult aFailCode); |
|
220 |
|
221 /* |
|
222 * Member variables. |
|
223 * |
|
224 */ |
|
225 RasterImage &mImage; |
|
226 imgFrame* mCurrentFrame; |
|
227 RefPtr<imgDecoderObserver> mObserver; |
|
228 ImageMetadata mImageMetadata; |
|
229 |
|
230 uint8_t* mImageData; // Pointer to image data in either Cairo or 8bit format |
|
231 uint32_t mImageDataLength; |
|
232 uint32_t* mColormap; // Current colormap to be used in Cairo format |
|
233 uint32_t mColormapSize; |
|
234 |
|
235 uint32_t mDecodeFlags; |
|
236 bool mDecodeDone; |
|
237 bool mDataError; |
|
238 |
|
239 private: |
|
240 uint32_t mFrameCount; // Number of frames, including anything in-progress |
|
241 |
|
242 nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame. |
|
243 |
|
244 nsresult mFailCode; |
|
245 |
|
246 struct NewFrameData |
|
247 { |
|
248 NewFrameData() |
|
249 {} |
|
250 |
|
251 NewFrameData(uint32_t num, uint32_t offsetx, uint32_t offsety, |
|
252 uint32_t width, uint32_t height, |
|
253 gfxImageFormat format, uint8_t paletteDepth) |
|
254 : mFrameNum(num) |
|
255 , mOffsetX(offsetx) |
|
256 , mOffsetY(offsety) |
|
257 , mWidth(width) |
|
258 , mHeight(height) |
|
259 , mFormat(format) |
|
260 , mPaletteDepth(paletteDepth) |
|
261 {} |
|
262 uint32_t mFrameNum; |
|
263 uint32_t mOffsetX; |
|
264 uint32_t mOffsetY; |
|
265 uint32_t mWidth; |
|
266 uint32_t mHeight; |
|
267 gfxImageFormat mFormat; |
|
268 uint8_t mPaletteDepth; |
|
269 }; |
|
270 NewFrameData mNewFrameData; |
|
271 bool mNeedsNewFrame; |
|
272 bool mInitialized; |
|
273 bool mSizeDecode; |
|
274 bool mInFrame; |
|
275 bool mIsAnimated; |
|
276 }; |
|
277 |
|
278 } // namespace image |
|
279 } // namespace mozilla |
|
280 |
|
281 #endif // MOZILLA_IMAGELIB_DECODER_H_ |