1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/image/src/Decoder.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,281 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_IMAGELIB_DECODER_H_ 1.10 +#define MOZILLA_IMAGELIB_DECODER_H_ 1.11 + 1.12 +#include "RasterImage.h" 1.13 +#include "imgDecoderObserver.h" 1.14 +#include "mozilla/RefPtr.h" 1.15 +#include "DecodeStrategy.h" 1.16 +#include "ImageMetadata.h" 1.17 +#include "Orientation.h" 1.18 +#include "mozilla/Telemetry.h" 1.19 + 1.20 +namespace mozilla { 1.21 +namespace image { 1.22 + 1.23 +class Decoder 1.24 +{ 1.25 +public: 1.26 + 1.27 + Decoder(RasterImage& aImage); 1.28 + virtual ~Decoder(); 1.29 + 1.30 + /** 1.31 + * Initialize an image decoder. Decoders may not be re-initialized. 1.32 + * 1.33 + * Notifications Sent: TODO 1.34 + */ 1.35 + void Init(); 1.36 + 1.37 + /** 1.38 + * Initializes a decoder whose image and observer is already being used by a 1.39 + * parent decoder. Decoders may not be re-initialized. 1.40 + * 1.41 + * Notifications Sent: TODO 1.42 + */ 1.43 + void InitSharedDecoder(uint8_t* imageData, uint32_t imageDataLength, 1.44 + uint32_t* colormap, uint32_t colormapSize, 1.45 + imgFrame* currentFrame); 1.46 + 1.47 + /** 1.48 + * Writes data to the decoder. 1.49 + * 1.50 + * @param aBuffer buffer containing the data to be written 1.51 + * @param aCount the number of bytes to write 1.52 + * 1.53 + * Any errors are reported by setting the appropriate state on the decoder. 1.54 + * 1.55 + * Notifications Sent: TODO 1.56 + */ 1.57 + void Write(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); 1.58 + 1.59 + /** 1.60 + * Informs the decoder that all the data has been written. 1.61 + * 1.62 + * Notifications Sent: TODO 1.63 + */ 1.64 + void Finish(RasterImage::eShutdownIntent aShutdownIntent); 1.65 + 1.66 + /** 1.67 + * Informs the shared decoder that all the data has been written. 1.68 + * Should only be used if InitSharedDecoder was useed 1.69 + * 1.70 + * Notifications Sent: TODO 1.71 + */ 1.72 + void FinishSharedDecoder(); 1.73 + 1.74 + /** 1.75 + * Tells the decoder to flush any pending invalidations. This informs the image 1.76 + * frame of its decoded region, and sends the appropriate OnDataAvailable call 1.77 + * to consumers. 1.78 + * 1.79 + * This can be called any time when we're midway through decoding a frame, 1.80 + * and must be called after finishing a frame (before starting a new one). 1.81 + */ 1.82 + void FlushInvalidations(); 1.83 + 1.84 + // We're not COM-y, so we don't get refcounts by default 1.85 + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Decoder) 1.86 + 1.87 + /* 1.88 + * State. 1.89 + */ 1.90 + 1.91 + // If we're doing a "size decode", we more or less pass through the image 1.92 + // data, stopping only to scoop out the image dimensions. A size decode 1.93 + // must be enabled by SetSizeDecode() _before_calling Init(). 1.94 + bool IsSizeDecode() { return mSizeDecode; } 1.95 + void SetSizeDecode(bool aSizeDecode) 1.96 + { 1.97 + NS_ABORT_IF_FALSE(!mInitialized, "Can't set size decode after Init()!"); 1.98 + mSizeDecode = aSizeDecode; 1.99 + } 1.100 + 1.101 + void SetObserver(imgDecoderObserver* aObserver) 1.102 + { 1.103 + MOZ_ASSERT(aObserver); 1.104 + mObserver = aObserver; 1.105 + } 1.106 + 1.107 + // The number of frames we have, including anything in-progress. Thus, this 1.108 + // is only 0 if we haven't begun any frames. 1.109 + uint32_t GetFrameCount() { return mFrameCount; } 1.110 + 1.111 + // The number of complete frames we have (ie, not including anything in-progress). 1.112 + uint32_t GetCompleteFrameCount() { return mInFrame ? mFrameCount - 1 : mFrameCount; } 1.113 + 1.114 + // Error tracking 1.115 + bool HasError() { return HasDataError() || HasDecoderError(); } 1.116 + bool HasDataError() { return mDataError; } 1.117 + bool HasDecoderError() { return NS_FAILED(mFailCode); } 1.118 + nsresult GetDecoderError() { return mFailCode; } 1.119 + void PostResizeError() { PostDataError(); } 1.120 + bool GetDecodeDone() const { 1.121 + return mDecodeDone; 1.122 + } 1.123 + 1.124 + // flags. Keep these in sync with imgIContainer.idl. 1.125 + // SetDecodeFlags must be called before Init(), otherwise 1.126 + // default flags are assumed. 1.127 + enum { 1.128 + DECODER_NO_PREMULTIPLY_ALPHA = 0x2, // imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA 1.129 + DECODER_NO_COLORSPACE_CONVERSION = 0x4 // imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION 1.130 + }; 1.131 + 1.132 + enum DecodeStyle { 1.133 + PROGRESSIVE, // produce intermediate frames representing the partial state of the image 1.134 + SEQUENTIAL // decode to final image immediately 1.135 + }; 1.136 + 1.137 + void SetDecodeFlags(uint32_t aFlags) { mDecodeFlags = aFlags; } 1.138 + uint32_t GetDecodeFlags() { return mDecodeFlags; } 1.139 + 1.140 + bool HasSize() const { return mImageMetadata.HasSize(); } 1.141 + void SetSizeOnImage(); 1.142 + 1.143 + // Use HistogramCount as an invalid Histogram ID 1.144 + virtual Telemetry::ID SpeedHistogram() { return Telemetry::HistogramCount; } 1.145 + 1.146 + ImageMetadata& GetImageMetadata() { return mImageMetadata; } 1.147 + 1.148 + // Tell the decoder infrastructure to allocate a frame. By default, frame 0 1.149 + // is created as an ARGB frame with no offset and with size width * height. 1.150 + // If decoders need something different, they must ask for it. 1.151 + // This is called by decoders when they need a new frame. These decoders 1.152 + // must then save the data they have been sent but not yet processed and 1.153 + // return from WriteInternal. When the new frame is created, WriteInternal 1.154 + // will be called again with nullptr and 0 as arguments. 1.155 + void NeedNewFrame(uint32_t frameNum, uint32_t x_offset, uint32_t y_offset, 1.156 + uint32_t width, uint32_t height, 1.157 + gfxImageFormat format, 1.158 + uint8_t palette_depth = 0); 1.159 + 1.160 + virtual bool NeedsNewFrame() const { return mNeedsNewFrame; } 1.161 + 1.162 + // Try to allocate a frame as described in mNewFrameData and return the 1.163 + // status code from that attempt. Clears mNewFrameData. 1.164 + virtual nsresult AllocateFrame(); 1.165 + 1.166 + // Called when a chunk of decoding has been done and the frame needs to be 1.167 + // marked as dirty. Must be called only on the main thread. 1.168 + void MarkFrameDirty(); 1.169 + 1.170 + imgFrame* GetCurrentFrame() const { return mCurrentFrame; } 1.171 + 1.172 +protected: 1.173 + 1.174 + /* 1.175 + * Internal hooks. Decoder implementations may override these and 1.176 + * only these methods. 1.177 + */ 1.178 + virtual void InitInternal(); 1.179 + virtual void WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy); 1.180 + virtual void FinishInternal(); 1.181 + 1.182 + /* 1.183 + * Progress notifications. 1.184 + */ 1.185 + 1.186 + // Called by decoders when they determine the size of the image. Informs 1.187 + // the image of its size and sends notifications. 1.188 + void PostSize(int32_t aWidth, 1.189 + int32_t aHeight, 1.190 + Orientation aOrientation = Orientation()); 1.191 + 1.192 + // Called by decoders when they begin a frame. Informs the image, sends 1.193 + // notifications, and does internal book-keeping. 1.194 + void PostFrameStart(); 1.195 + 1.196 + // Called by decoders when they end a frame. Informs the image, sends 1.197 + // notifications, and does internal book-keeping. 1.198 + // Specify whether this frame is opaque as an optimization. 1.199 + // For animated images, specify the disposal, blend method and timeout for 1.200 + // this frame. 1.201 + void PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha = FrameBlender::kFrameHasAlpha, 1.202 + FrameBlender::FrameDisposalMethod aDisposalMethod = FrameBlender::kDisposeKeep, 1.203 + int32_t aTimeout = 0, 1.204 + FrameBlender::FrameBlendMethod aBlendMethod = FrameBlender::kBlendOver); 1.205 + 1.206 + // Called by the decoders when they have a region to invalidate. We may not 1.207 + // actually pass these invalidations on right away. 1.208 + void PostInvalidation(nsIntRect& aRect); 1.209 + 1.210 + // Called by the decoders when they have successfully decoded the image. This 1.211 + // may occur as the result of the decoder getting to the appropriate point in 1.212 + // the stream, or by us calling FinishInternal(). 1.213 + // 1.214 + // May not be called mid-frame. 1.215 + // 1.216 + // For animated images, specify the loop count. -1 means loop forever, 0 1.217 + // means a single iteration, stopping on the last frame. 1.218 + void PostDecodeDone(int32_t aLoopCount = 0); 1.219 + 1.220 + // Data errors are the fault of the source data, decoder errors are our fault 1.221 + void PostDataError(); 1.222 + void PostDecoderError(nsresult aFailCode); 1.223 + 1.224 + /* 1.225 + * Member variables. 1.226 + * 1.227 + */ 1.228 + RasterImage &mImage; 1.229 + imgFrame* mCurrentFrame; 1.230 + RefPtr<imgDecoderObserver> mObserver; 1.231 + ImageMetadata mImageMetadata; 1.232 + 1.233 + uint8_t* mImageData; // Pointer to image data in either Cairo or 8bit format 1.234 + uint32_t mImageDataLength; 1.235 + uint32_t* mColormap; // Current colormap to be used in Cairo format 1.236 + uint32_t mColormapSize; 1.237 + 1.238 + uint32_t mDecodeFlags; 1.239 + bool mDecodeDone; 1.240 + bool mDataError; 1.241 + 1.242 +private: 1.243 + uint32_t mFrameCount; // Number of frames, including anything in-progress 1.244 + 1.245 + nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame. 1.246 + 1.247 + nsresult mFailCode; 1.248 + 1.249 + struct NewFrameData 1.250 + { 1.251 + NewFrameData() 1.252 + {} 1.253 + 1.254 + NewFrameData(uint32_t num, uint32_t offsetx, uint32_t offsety, 1.255 + uint32_t width, uint32_t height, 1.256 + gfxImageFormat format, uint8_t paletteDepth) 1.257 + : mFrameNum(num) 1.258 + , mOffsetX(offsetx) 1.259 + , mOffsetY(offsety) 1.260 + , mWidth(width) 1.261 + , mHeight(height) 1.262 + , mFormat(format) 1.263 + , mPaletteDepth(paletteDepth) 1.264 + {} 1.265 + uint32_t mFrameNum; 1.266 + uint32_t mOffsetX; 1.267 + uint32_t mOffsetY; 1.268 + uint32_t mWidth; 1.269 + uint32_t mHeight; 1.270 + gfxImageFormat mFormat; 1.271 + uint8_t mPaletteDepth; 1.272 + }; 1.273 + NewFrameData mNewFrameData; 1.274 + bool mNeedsNewFrame; 1.275 + bool mInitialized; 1.276 + bool mSizeDecode; 1.277 + bool mInFrame; 1.278 + bool mIsAnimated; 1.279 +}; 1.280 + 1.281 +} // namespace image 1.282 +} // namespace mozilla 1.283 + 1.284 +#endif // MOZILLA_IMAGELIB_DECODER_H_