1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
8 * This file declares the RasterImage class, which
9 * handles static and animated rasterized images.
11 * @author Stuart Parmenter <pavlov@netscape.com>
12 * @author Chris Saari <saari@netscape.com>
13 * @author Arron Mogge <paper@animecity.nu>
14 * @author Andrew Smith <asmith15@learn.senecac.on.ca>
17 #ifndef mozilla_imagelib_RasterImage_h_
18 #define mozilla_imagelib_RasterImage_h_
21 #include "FrameBlender.h"
23 #include "imgIContainer.h"
24 #include "nsIProperties.h"
27 #include "nsThreadUtils.h"
28 #include "DecodeStrategy.h"
29 #include "DiscardTracker.h"
30 #include "Orientation.h"
31 #include "nsIObserver.h"
32 #include "mozilla/MemoryReporting.h"
33 #include "mozilla/Mutex.h"
34 #include "mozilla/ReentrantMonitor.h"
35 #include "mozilla/TimeStamp.h"
36 #include "mozilla/StaticPtr.h"
37 #include "mozilla/WeakPtr.h"
39 #include "imgIContainerDebug.h"
46 #define NS_RASTERIMAGE_CID \
47 { /* 376ff2c1-9bf6-418a-b143-3340c00112f7 */ \
51 {0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
55 * Handles static and animated image containers.
58 * @par A Quick Walk Through
59 * The decoder initializes this class and calls AppendFrame() to add a frame.
60 * Once RasterImage detects more than one frame, it starts the animation
61 * with StartAnimation(). Note that the invalidation events for RasterImage are
62 * generated automatically using nsRefreshDriver.
65 * StartAnimation() initializes the animation helper object and sets the time
66 * the first frame was displayed to the current clock time.
69 * When the refresh driver corresponding to the imgIContainer that this image is
70 * a part of notifies the RasterImage that it's time to invalidate,
71 * RequestRefresh() is called with a given TimeStamp to advance to. As long as
72 * the timeout of the given frame (the frame's "delay") plus the time that frame
73 * was first displayed is less than or equal to the TimeStamp given,
74 * RequestRefresh() calls AdvanceFrame().
77 * AdvanceFrame() is responsible for advancing a single frame of the animation.
78 * It can return true, meaning that the frame advanced, or false, meaning that
79 * the frame failed to advance (usually because the next frame hasn't been
80 * decoded yet). It is also responsible for performing the final animation stop
81 * procedure if the final frame of a non-looping animation is reached.
84 * Each frame can have a different method of removing itself. These are
85 * listed as imgIContainer::cDispose... constants. Notify() calls
86 * DoComposite() to handle any special frame destruction.
89 * The basic path through DoComposite() is:
90 * 1) Calculate Area that needs updating, which is at least the area of
92 * 2) Dispose of previous frame.
93 * 3) Draw new image onto compositingFrame.
94 * See comments in DoComposite() for more information and optimizations.
97 * The rest of the RasterImage specific functions are used by DoComposite to
98 * destroy the old frame and build the new one.
101 * <li> "Mask", "Alpha", and "Alpha Level" are interchangeable phrases in
102 * respects to RasterImage.
105 * <li> GIFs never have more than a 1 bit alpha.
106 * <li> APNGs may have a full alpha channel.
109 * <li> Background color specified in GIF is ignored by web browsers.
112 * <li> If Frame 3 wants to dispose by restoring previous, what it wants is to
113 * restore the composition up to and including Frame 2, as well as Frame 2s
114 * disposal. So, in the middle of DoComposite when composing Frame 3, right
115 * after destroying Frame 2's area, we copy compositingFrame to
116 * prevCompositingFrame. When DoComposite gets called to do Frame 4, we
117 * copy prevCompositingFrame back, and then draw Frame 4 on top.
120 * The mAnim structure has members only needed for animated images, so
121 * it's not allocated until the second frame is added.
128 class ImageContainer
;
138 class RasterImage MOZ_FINAL
: public ImageResource
139 , public nsIProperties
140 , public SupportsWeakPtr
<RasterImage
>
142 , public imgIContainerDebug
145 // (no public constructor - use ImageFactory)
146 virtual ~RasterImage();
149 MOZ_DECLARE_REFCOUNTED_TYPENAME(RasterImage
)
150 NS_DECL_THREADSAFE_ISUPPORTS
151 NS_DECL_NSIPROPERTIES
152 NS_DECL_IMGICONTAINER
154 NS_DECL_IMGICONTAINERDEBUG
157 virtual nsresult
StartAnimation();
158 virtual nsresult
StopAnimation();
160 // Methods inherited from Image
161 nsresult
Init(const char* aMimeType
,
163 virtual nsIntRect
FrameRect(uint32_t aWhichFrame
) MOZ_OVERRIDE
;
165 // Raster-specific methods
166 static NS_METHOD
WriteToRasterImage(nsIInputStream
* aIn
, void* aClosure
,
167 const char* aFromRawSegment
,
168 uint32_t aToOffset
, uint32_t aCount
,
169 uint32_t* aWriteCount
);
171 /* The index of the current frame that would be drawn if the image was to be
173 uint32_t GetCurrentFrameIndex();
175 /* The total number of frames in this image. */
176 uint32_t GetNumFrames() const;
178 virtual size_t HeapSizeOfSourceWithComputedFallback(MallocSizeOf aMallocSizeOf
) const;
179 virtual size_t HeapSizeOfDecodedWithComputedFallback(MallocSizeOf aMallocSizeOf
) const;
180 virtual size_t NonHeapSizeOfDecoded() const;
181 virtual size_t OutOfProcessSizeOfDecoded() const;
183 virtual size_t HeapSizeOfVectorImageDocument(nsACString
* aDocURL
= nullptr) const MOZ_OVERRIDE
{
187 /* Triggers discarding. */
188 void Discard(bool force
= false);
189 void ForceDiscard() { Discard(/* force = */ true); }
191 /* Callbacks for decoders */
192 nsresult
SetFrameAsNonPremult(uint32_t aFrameNum
, bool aIsNonPremult
);
194 /** Sets the size and inherent orientation of the container. This should only
195 * be called by the decoder. This function may be called multiple times, but
196 * will throw an error if subsequent calls do not match the first.
198 nsresult
SetSize(int32_t aWidth
, int32_t aHeight
, Orientation aOrientation
);
201 * Ensures that a given frame number exists with the given parameters, and
202 * returns pointers to the data storage for that frame.
203 * It is not possible to create sparse frame arrays; you can only append
204 * frames to the current frame array.
206 nsresult
EnsureFrame(uint32_t aFramenum
, int32_t aX
, int32_t aY
,
207 int32_t aWidth
, int32_t aHeight
,
208 gfx::SurfaceFormat aFormat
,
209 uint8_t aPaletteDepth
,
211 uint32_t* imageLength
,
212 uint32_t** paletteData
,
213 uint32_t* paletteLength
,
217 * A shorthand for EnsureFrame, above, with aPaletteDepth = 0 and paletteData
218 * and paletteLength set to null.
220 nsresult
EnsureFrame(uint32_t aFramenum
, int32_t aX
, int32_t aY
,
221 int32_t aWidth
, int32_t aHeight
,
222 gfx::SurfaceFormat aFormat
,
224 uint32_t* imageLength
,
227 /* notification that the entire image has been decoded */
228 nsresult
DecodingComplete();
231 * Number of times to loop the image.
232 * @note -1 means forever.
234 void SetLoopCount(int32_t aLoopCount
);
236 /* Add compressed source data to the imgContainer.
238 * The decoder will use this data, either immediately or at draw time, to
241 * XXX This method's only caller (WriteToContainer) ignores the return
242 * value. Should this just return void?
244 nsresult
AddSourceData(const char *aBuffer
, uint32_t aCount
);
246 virtual nsresult
OnImageDataAvailable(nsIRequest
* aRequest
,
247 nsISupports
* aContext
,
248 nsIInputStream
* aInStr
,
249 uint64_t aSourceOffset
,
250 uint32_t aCount
) MOZ_OVERRIDE
;
251 virtual nsresult
OnImageDataComplete(nsIRequest
* aRequest
,
252 nsISupports
* aContext
,
254 bool aLastPart
) MOZ_OVERRIDE
;
255 virtual nsresult
OnNewSourceData() MOZ_OVERRIDE
;
257 static already_AddRefed
<nsIEventTarget
> GetEventTarget() {
258 return DecodePool::Singleton()->GetEventTarget();
262 * A hint of the number of bytes of source data that the image contains. If
263 * called early on, this can help reduce copying and reallocations by
264 * appropriately preallocating the source data buffer.
266 * We take this approach rather than having the source data management code do
267 * something more complicated (like chunklisting) because HTTP is by far the
268 * dominant source of images, and the Content-Length header is quite reliable.
269 * Thus, pre-allocation simplifies code and reduces the total number of
272 nsresult
SetSourceSizeHint(uint32_t sizeHint
);
274 /* Provide a hint for the requested resolution of the resulting image. */
275 void SetRequestedResolution(const nsIntSize requestedResolution
) {
276 mRequestedResolution
= requestedResolution
;
279 nsIntSize
GetRequestedResolution() {
280 return mRequestedResolution
;
282 /* Provide a hint for the requested dimension of the resulting image. */
283 void SetRequestedSampleSize(int requestedSampleSize
) {
284 mRequestedSampleSize
= requestedSampleSize
;
287 int GetRequestedSampleSize() {
288 return mRequestedSampleSize
;
293 nsCString
GetURIString() {
296 GetURI()->GetSpec(spec
);
301 // Called from module startup. Sets up RasterImage to be used.
302 static void Initialize();
311 // Call this with a new ScaleRequest to mark this RasterImage's scale result
312 // as waiting for the results of this request. You call to ScalingDone before
313 // request is destroyed!
314 void ScalingStart(ScaleRequest
* request
);
316 // Call this with a finished ScaleRequest to set this RasterImage's scale
317 // result. Give it a ScaleStatus of SCALE_DONE if everything succeeded, and
318 // SCALE_INVALID otherwise.
319 void ScalingDone(ScaleRequest
* request
, ScaleStatus status
);
322 enum eShutdownIntent
{
323 eShutdownIntent_Done
= 0,
324 eShutdownIntent_NotNeeded
= 1,
325 eShutdownIntent_Error
= 2,
326 eShutdownIntent_AllCount
= 3
332 // Initiates an HQ scale for the given frame, if possible.
333 void RequestScale(imgFrame
* aFrame
, nsIntSize aScale
);
335 already_AddRefed
<imgStatusTracker
> CurrentStatusTracker()
337 mDecodingMonitor
.AssertCurrentThreadIn();
338 nsRefPtr
<imgStatusTracker
> statusTracker
;
339 statusTracker
= mDecodeRequest
? mDecodeRequest
->mStatusTracker
341 MOZ_ASSERT(statusTracker
);
342 return statusTracker
.forget();
345 nsresult
OnImageDataCompleteCore(nsIRequest
* aRequest
, nsISupports
*, nsresult aStatus
);
348 * Each RasterImage has a pointer to one or zero heap-allocated
353 DecodeRequest(RasterImage
* aImage
)
356 , mRequestStatus(REQUEST_INACTIVE
)
358 , mAllocatedNewFrame(false)
360 MOZ_ASSERT(aImage
, "aImage cannot be null");
361 MOZ_ASSERT(aImage
->mStatusTracker
,
362 "aImage should have an imgStatusTracker");
363 mStatusTracker
= aImage
->mStatusTracker
->CloneForRecording();
366 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecodeRequest
)
368 // The status tracker that is associated with a given decode request, to
369 // ensure their lifetimes are linked.
370 nsRefPtr
<imgStatusTracker
> mStatusTracker
;
374 size_t mBytesToDecode
;
376 enum DecodeRequestStatus
385 /* Keeps track of how much time we've burned decoding this particular decode
387 TimeDuration mDecodeTime
;
389 /* The number of chunks it took to decode this image. */
392 /* True if a new frame has been allocated, but DecodeSomeData hasn't yet
393 * been called to flush data to it */
394 bool mAllocatedNewFrame
;
401 * DecodePool is a singleton class we use when decoding large images.
403 * When we wish to decode an image larger than
404 * image.mem.max_bytes_for_sync_decode, we call DecodePool::RequestDecode()
405 * for the image. This adds the image to a queue of pending requests and posts
406 * the DecodePool singleton to the event queue, if it's not already pending
409 * When the DecodePool is run from the event queue, it decodes the image (and
410 * all others it's managing) in chunks, periodically yielding control back to
413 class DecodePool
: public nsIObserver
416 NS_DECL_THREADSAFE_ISUPPORTS
419 static DecodePool
* Singleton();
422 * Ask the DecodePool to asynchronously decode this image.
424 void RequestDecode(RasterImage
* aImg
);
427 * Decode aImg for a short amount of time, and post the remainder to the
430 void DecodeABitOf(RasterImage
* aImg
, DecodeStrategy aStrategy
);
433 * Ask the DecodePool to stop decoding this image. Internally, we also
434 * call this function when we finish decoding an image.
436 * Since the DecodePool keeps raw pointers to RasterImages, make sure you
437 * call this before a RasterImage is destroyed!
439 static void StopDecoding(RasterImage
* aImg
);
442 * Synchronously decode the beginning of the image until we run out of
443 * bytes or we get the image's size. Note that this done on a best-effort
444 * basis; if the size is burried too deep in the image, we'll give up.
446 * @return NS_ERROR if an error is encountered, and NS_OK otherwise. (Note
447 * that we return NS_OK even when the size was not found.)
449 nsresult
DecodeUntilSizeAvailable(RasterImage
* aImg
);
452 * Returns an event target interface to the thread pool; primarily for
453 * OnDataAvailable delivery off main thread.
455 * @return An nsIEventTarget interface to mThreadPool.
457 already_AddRefed
<nsIEventTarget
> GetEventTarget();
459 private: /* statics */
460 static StaticRefPtr
<DecodePool
> sSingleton
;
462 private: /* methods */
464 virtual ~DecodePool();
467 DECODE_TYPE_UNTIL_TIME
,
468 DECODE_TYPE_UNTIL_SIZE
,
469 DECODE_TYPE_UNTIL_DONE_BYTES
472 /* Decode some chunks of the given image. If aDecodeType is UNTIL_SIZE,
473 * decode until we have the image's size, then stop. If bytesToDecode is
474 * non-0, at most bytesToDecode bytes will be decoded. if aDecodeType is
475 * UNTIL_DONE_BYTES, decode until all bytesToDecode bytes are decoded.
477 nsresult
DecodeSomeOfImage(RasterImage
* aImg
,
478 DecodeStrategy aStrategy
,
479 DecodeType aDecodeType
= DECODE_TYPE_UNTIL_TIME
,
480 uint32_t bytesToDecode
= 0);
482 /* A decode job dispatched to a thread pool by DecodePool.
484 class DecodeJob
: public nsRunnable
487 DecodeJob(DecodeRequest
* aRequest
, RasterImage
* aImg
)
495 virtual ~DecodeJob();
498 nsRefPtr
<DecodeRequest
> mRequest
;
499 nsRefPtr
<RasterImage
> mImage
;
502 private: /* members */
504 // mThreadPoolMutex protects mThreadPool. For all RasterImages R,
505 // R::mDecodingMonitor must be acquired before mThreadPoolMutex
506 // if both are acquired; the other order may cause deadlock.
507 Mutex mThreadPoolMutex
;
508 nsCOMPtr
<nsIThreadPool
> mThreadPool
;
511 class DecodeDoneWorker
: public nsRunnable
515 * Called by the DecodePool with an image when it's done some significant
516 * portion of decoding that needs to be notified about.
518 * Ensures the decode state accumulated by the decoding process gets
519 * applied to the image.
521 static void NotifyFinishedSomeDecoding(RasterImage
* image
, DecodeRequest
* request
);
525 private: /* methods */
526 DecodeDoneWorker(RasterImage
* image
, DecodeRequest
* request
);
528 private: /* members */
530 nsRefPtr
<RasterImage
> mImage
;
531 nsRefPtr
<DecodeRequest
> mRequest
;
534 class FrameNeededWorker
: public nsRunnable
538 * Called by the DecodeJob with an image when it's been told by the
539 * decoder that it needs a new frame to be allocated on the main thread.
541 * Dispatches an event to do so, which will further dispatch a
542 * DecodeRequest event to continue decoding.
544 static void GetNewFrame(RasterImage
* image
);
548 private: /* methods */
549 FrameNeededWorker(RasterImage
* image
);
551 private: /* members */
553 nsRefPtr
<RasterImage
> mImage
;
556 nsresult
FinishedSomeDecoding(eShutdownIntent intent
= eShutdownIntent_Done
,
557 DecodeRequest
* request
= nullptr);
559 bool DrawWithPreDownscaleIfNeeded(imgFrame
*aFrame
,
560 gfxContext
*aContext
,
561 const nsIntSize
& aSize
,
562 const ImageRegion
& aRegion
,
563 GraphicsFilter aFilter
,
566 TemporaryRef
<gfx::SourceSurface
> CopyFrame(uint32_t aWhichFrame
,
570 * Deletes and nulls out the frame in mFrames[framenum].
572 * Does not change the size of mFrames.
574 * @param framenum The index of the frame to be deleted.
575 * Must lie in [0, mFrames.Length() )
577 void DeleteImgFrame(uint32_t framenum
);
579 already_AddRefed
<imgFrame
> GetImgFrameNoDecode(uint32_t framenum
);
580 already_AddRefed
<imgFrame
> GetImgFrame(uint32_t framenum
);
581 already_AddRefed
<imgFrame
> GetDrawableImgFrame(uint32_t framenum
);
582 already_AddRefed
<imgFrame
> GetCurrentImgFrame();
583 uint32_t GetCurrentImgFrameIndex() const;
585 size_t SizeOfDecodedWithComputedFallbackIfHeap(gfxMemoryLocation aLocation
,
586 MallocSizeOf aMallocSizeOf
) const;
588 void EnsureAnimExists();
590 nsresult
InternalAddFrameHelper(uint32_t framenum
, imgFrame
*frame
,
591 uint8_t **imageData
, uint32_t *imageLength
,
592 uint32_t **paletteData
, uint32_t *paletteLength
,
593 imgFrame
** aRetFrame
);
594 nsresult
InternalAddFrame(uint32_t framenum
, int32_t aX
, int32_t aY
, int32_t aWidth
, int32_t aHeight
,
595 gfx::SurfaceFormat aFormat
, uint8_t aPaletteDepth
,
596 uint8_t **imageData
, uint32_t *imageLength
,
597 uint32_t **paletteData
, uint32_t *paletteLength
,
598 imgFrame
** aRetFrame
);
600 nsresult
DoImageDataComplete();
602 bool ApplyDecodeFlags(uint32_t aNewFlags
, uint32_t aWhichFrame
);
604 already_AddRefed
<layers::Image
> GetCurrentImage();
605 void UpdateImageContainer();
607 void SetInUpdateImageContainer(bool aInUpdate
) { mInUpdateImageContainer
= aInUpdate
; }
608 bool IsInUpdateImageContainer() { return mInUpdateImageContainer
; }
609 enum RequestDecodeType
{
612 SYNCHRONOUS_NOTIFY_AND_SOME_DECODE
614 NS_IMETHOD
RequestDecodeCore(RequestDecodeType aDecodeType
);
616 // We would like to just check if we have a zero lock count, but we can't do
617 // that for animated images because in EnsureAnimExists we lock the image and
618 // never unlock so that animated images always have their lock count >= 1. In
619 // that case we use our animation consumers count as a proxy for lock count.
620 bool IsUnlocked() { return (mLockCount
== 0 || (mAnim
&& mAnimationConsumers
== 0)); }
624 Orientation mOrientation
;
626 // Whether our frames were decoded using any special flags.
627 // Some flags (e.g. unpremultiplied data) may not be compatible
628 // with the browser's needs for displaying the image to the user.
629 // As such, we may need to redecode if we're being asked for
630 // a frame with different flags. 0 indicates default flags.
632 // Valid flag bits are imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA
633 // and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION.
634 uint32_t mFrameDecodeFlags
;
636 //! All the frames of the image
637 FrameBlender mFrameBlender
;
639 // The last frame we decoded for multipart images.
640 nsRefPtr
<imgFrame
> mMultipartDecodedFrame
;
642 nsCOMPtr
<nsIProperties
> mProperties
;
644 // IMPORTANT: if you use mAnim in a method, call EnsureImageIsDecoded() first to ensure
645 // that the frames actually exist (they may have been discarded to save memory, or
646 // we maybe decoding on draw).
647 FrameAnimator
* mAnim
;
651 DiscardTracker::Node mDiscardTrackerNode
;
653 // Source data members
654 nsCString mSourceDataMimeType
;
656 friend class DiscardTracker
;
658 // How many times we've decoded this image.
659 // This is currently only used for statistics
660 int32_t mDecodeCount
;
662 // If the image contains multiple resolutions, a hint as to which one should be used
663 nsIntSize mRequestedResolution
;
665 // A hint for image decoder that directly scale the image to smaller buffer
666 int mRequestedSampleSize
;
668 // Cached value for GetImageContainer.
669 nsRefPtr
<layers::ImageContainer
> mImageContainer
;
671 // If not cached in mImageContainer, this might have our image container
672 WeakPtr
<layers::ImageContainer
> mImageContainerCache
;
675 uint32_t mFramesNotified
;
678 // Below are the pieces of data that can be accessed on more than one thread
679 // at once, and hence need to be locked by mDecodingMonitor.
681 // BEGIN LOCKED MEMBER VARIABLES
682 ReentrantMonitor mDecodingMonitor
;
684 FallibleTArray
<char> mSourceData
;
686 // Decoder and friends
687 nsRefPtr
<Decoder
> mDecoder
;
688 nsRefPtr
<DecodeRequest
> mDecodeRequest
;
689 size_t mBytesDecoded
;
692 // END LOCKED MEMBER VARIABLES
694 // Notification state. Used to avoid recursive notifications.
695 ImageStatusDiff mStatusDiff
;
698 // Boolean flags (clustered together to conserve space):
699 bool mHasSize
:1; // Has SetSize() been called?
700 bool mDecodeOnDraw
:1; // Decoding on draw?
701 bool mMultipart
:1; // Multipart?
702 bool mDiscardable
:1; // Is container discardable?
703 bool mHasSourceData
:1; // Do we have source data?
705 // Do we have the frames in decoded form?
707 bool mHasBeenDecoded
:1;
710 // Whether the animation can stop, due to running out
711 // of frames, or no more owning request
712 bool mAnimationFinished
:1;
714 // Whether we're calling Decoder::Finish() from ShutdownDecoder.
717 bool mInUpdateImageContainer
:1;
719 // Whether, once we are done doing a size decode, we should immediately kick
720 // off a full decode.
721 bool mWantFullDecode
:1;
723 // Set when a decode worker detects an error off-main-thread. Once the error
724 // is handled on the main thread, mError is set, but mPendingError is used to
725 // stop decode work immediately.
726 bool mPendingError
:1;
729 nsresult
RequestDecodeIfNeeded(nsresult aStatus
,
730 eShutdownIntent aIntent
,
733 nsresult
WantDecodedFrames();
734 nsresult
SyncDecode();
735 nsresult
InitDecoder(bool aDoSizeDecode
);
736 nsresult
WriteToDecoder(const char *aBuffer
, uint32_t aCount
, DecodeStrategy aStrategy
);
737 nsresult
DecodeSomeData(size_t aMaxBytes
, DecodeStrategy aStrategy
);
738 bool IsDecodeFinished();
739 TimeStamp mDrawStartTime
;
741 inline bool CanQualityScale(const gfx::Size
& scale
);
742 inline bool CanScale(GraphicsFilter aFilter
, gfx::Size aScale
, uint32_t aFlags
);
747 : status(SCALE_INVALID
)
750 nsIntSize scaledSize
;
751 nsRefPtr
<imgFrame
> frame
;
755 ScaleResult mScaleResult
;
757 // We hold on to a bare pointer to a ScaleRequest while it's outstanding so
758 // we can mark it as stopped if necessary. The ScaleWorker/DrawWorker duo
759 // will inform us when to let go of this pointer.
760 ScaleRequest
* mScaleRequest
;
762 // Initializes imgStatusTracker and resets it on RasterImage destruction.
763 nsAutoPtr
<imgStatusTrackerInit
> mStatusTrackerInit
;
765 nsresult
ShutdownDecoder(eShutdownIntent aIntent
);
770 class HandleErrorWorker
: public nsRunnable
774 * Called from decoder threads when DoError() is called, since errors can't
775 * be handled safely off-main-thread. Dispatches an event which reinvokes
776 * DoError on the main thread if there isn't one already pending.
778 static void DispatchIfNeeded(RasterImage
* aImage
);
783 HandleErrorWorker(RasterImage
* aImage
);
785 nsRefPtr
<RasterImage
> mImage
;
790 bool CanForciblyDiscard();
791 bool CanForciblyDiscardAndRedecode();
792 bool DiscardingActive();
793 bool StoringSourceData() const;
796 RasterImage(imgStatusTracker
* aStatusTracker
= nullptr,
797 ImageURL
* aURI
= nullptr);
799 bool ShouldAnimate();
801 friend class ImageFactory
;
804 inline NS_IMETHODIMP
RasterImage::GetAnimationMode(uint16_t *aAnimationMode
) {
805 return GetAnimationModeInternal(aAnimationMode
);
808 // Asynchronous Decode Requestor
810 // We use this class when someone calls requestDecode() from within a decode
811 // notification. Since requestDecode() involves modifying the decoder's state
812 // (for example, possibly shutting down a header-only decode and starting a
813 // full decode), we don't want to do this from inside a decoder.
814 class imgDecodeRequestor
: public nsRunnable
817 imgDecodeRequestor(RasterImage
&aContainer
) {
818 mContainer
= &aContainer
;
822 mContainer
->StartDecoding();
827 WeakPtr
<RasterImage
> mContainer
;
831 } // namespace mozilla
833 #endif /* mozilla_imagelib_RasterImage_h_ */