Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 #ifndef MOZILLA_IMAGELIB_DECODER_H_
7 #define MOZILLA_IMAGELIB_DECODER_H_
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"
17 namespace mozilla {
18 namespace image {
20 class Decoder
21 {
22 public:
24 Decoder(RasterImage& aImage);
25 virtual ~Decoder();
27 /**
28 * Initialize an image decoder. Decoders may not be re-initialized.
29 *
30 * Notifications Sent: TODO
31 */
32 void Init();
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);
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);
56 /**
57 * Informs the decoder that all the data has been written.
58 *
59 * Notifications Sent: TODO
60 */
61 void Finish(RasterImage::eShutdownIntent aShutdownIntent);
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();
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();
81 // We're not COM-y, so we don't get refcounts by default
82 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder)
84 /*
85 * State.
86 */
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 }
98 void SetObserver(imgDecoderObserver* aObserver)
99 {
100 MOZ_ASSERT(aObserver);
101 mObserver = aObserver;
102 }
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; }
108 // The number of complete frames we have (ie, not including anything in-progress).
109 uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; }
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 }
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 };
129 enum DecodeStyle {
130 PROGRESSIVE, // produce intermediate frames representing the partial state of the image
131 SEQUENTIAL // decode to final image immediately
132 };
134 void SetDecodeFlags(uint32_t aFlags) { mDecodeFlags = aFlags; }
135 uint32_t GetDecodeFlags() { return mDecodeFlags; }
137 bool HasSize() const { return mImageMetadata.HasSize(); }
138 void SetSizeOnImage();
140 // Use HistogramCount as an invalid Histogram ID
141 virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; }
143 ImageMetadata& GetImageMetadata() { return mImageMetadata; }
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);
157 virtual bool NeedsNewFrame() const { return mNeedsNewFrame; }
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();
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();
167 imgFrame* GetCurrentFrame() const { return mCurrentFrame; }
169 protected:
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();
179 /*
180 * Progress notifications.
181 */
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());
189 // Called by decoders when they begin a frame. Informs the image, sends
190 // notifications, and does internal book-keeping.
191 void PostFrameStart();
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);
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);
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);
217 // Data errors are the fault of the source data, decoder errors are our fault
218 void PostDataError();
219 void PostDecoderError(nsresult aFailCode);
221 /*
222 * Member variables.
223 *
224 */
225 RasterImage &mImage;
226 imgFrame* mCurrentFrame;
227 RefPtr<imgDecoderObserver> mObserver;
228 ImageMetadata mImageMetadata;
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;
235 uint32_t mDecodeFlags;
236 bool mDecodeDone;
237 bool mDataError;
239 private:
240 uint32_t mFrameCount; // Number of frames, including anything in-progress
242 nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
244 nsresult mFailCode;
246 struct NewFrameData
247 {
248 NewFrameData()
249 {}
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 };
278 } // namespace image
279 } // namespace mozilla
281 #endif // MOZILLA_IMAGELIB_DECODER_H_