LCOV - code coverage report
Current view: directory - image/src - RasterImage.h (source / functions) Found Hit Coverage
Test: app.info Lines: 27 17 63.0 %
Date: 2012-06-02 Functions: 13 8 61.5 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Stuart Parmenter <pavlov@netscape.com>
      25                 :  *   Chris Saari <saari@netscape.com>
      26                 :  *   Federico Mena-Quintero <federico@novell.com>
      27                 :  *   Bobby Holley <bobbyholley@gmail.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      31                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : /** @file
      44                 :  * This file declares the RasterImage class, which
      45                 :  * handles static and animated rasterized images.
      46                 :  *
      47                 :  * @author  Stuart Parmenter <pavlov@netscape.com>
      48                 :  * @author  Chris Saari <saari@netscape.com>
      49                 :  * @author  Arron Mogge <paper@animecity.nu>
      50                 :  * @author  Andrew Smith <asmith15@learn.senecac.on.ca>
      51                 :  */
      52                 : 
      53                 : #ifndef mozilla_imagelib_RasterImage_h_
      54                 : #define mozilla_imagelib_RasterImage_h_
      55                 : 
      56                 : #include "Image.h"
      57                 : #include "nsCOMArray.h"
      58                 : #include "nsCOMPtr.h"
      59                 : #include "imgIContainer.h"
      60                 : #include "nsIProperties.h"
      61                 : #include "nsITimer.h"
      62                 : #include "nsWeakReference.h"
      63                 : #include "nsTArray.h"
      64                 : #include "imgFrame.h"
      65                 : #include "nsThreadUtils.h"
      66                 : #include "DiscardTracker.h"
      67                 : #include "mozilla/TimeStamp.h"
      68                 : #include "mozilla/Telemetry.h"
      69                 : #include "mozilla/LinkedList.h"
      70                 : #ifdef DEBUG
      71                 :   #include "imgIContainerDebug.h"
      72                 : #endif
      73                 : 
      74                 : class imgIDecoder;
      75                 : class imgIContainerObserver;
      76                 : class nsIInputStream;
      77                 : 
      78                 : #define NS_RASTERIMAGE_CID \
      79                 : { /* 376ff2c1-9bf6-418a-b143-3340c00112f7 */         \
      80                 :      0x376ff2c1,                                     \
      81                 :      0x9bf6,                                         \
      82                 :      0x418a,                                         \
      83                 :     {0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
      84                 : }
      85                 : 
      86                 : /**
      87                 :  * Handles static and animated image containers.
      88                 :  *
      89                 :  *
      90                 :  * @par A Quick Walk Through
      91                 :  * The decoder initializes this class and calls AppendFrame() to add a frame.
      92                 :  * Once RasterImage detects more than one frame, it starts the animation
      93                 :  * with StartAnimation(). Note that the invalidation events for RasterImage are
      94                 :  * generated automatically using nsRefreshDriver.
      95                 :  *
      96                 :  * @par
      97                 :  * StartAnimation() initializes the animation helper object and sets the time
      98                 :  * the first frame was displayed to the current clock time.
      99                 :  *
     100                 :  * @par
     101                 :  * When the refresh driver corresponding to the imgIContainer that this image is
     102                 :  * a part of notifies the RasterImage that it's time to invalidate,
     103                 :  * RequestRefresh() is called with a given TimeStamp to advance to. As long as
     104                 :  * the timeout of the given frame (the frame's "delay") plus the time that frame
     105                 :  * was first displayed is less than or equal to the TimeStamp given,
     106                 :  * RequestRefresh() calls AdvanceFrame().
     107                 :  *
     108                 :  * @par
     109                 :  * AdvanceFrame() is responsible for advancing a single frame of the animation.
     110                 :  * It can return true, meaning that the frame advanced, or false, meaning that
     111                 :  * the frame failed to advance (usually because the next frame hasn't been
     112                 :  * decoded yet). It is also responsible for performing the final animation stop
     113                 :  * procedure if the final frame of a non-looping animation is reached.
     114                 :  *
     115                 :  * @par
     116                 :  * Each frame can have a different method of removing itself. These are
     117                 :  * listed as imgIContainer::cDispose... constants.  Notify() calls 
     118                 :  * DoComposite() to handle any special frame destruction.
     119                 :  *
     120                 :  * @par
     121                 :  * The basic path through DoComposite() is:
     122                 :  * 1) Calculate Area that needs updating, which is at least the area of
     123                 :  *    aNextFrame.
     124                 :  * 2) Dispose of previous frame.
     125                 :  * 3) Draw new image onto compositingFrame.
     126                 :  * See comments in DoComposite() for more information and optimizations.
     127                 :  *
     128                 :  * @par
     129                 :  * The rest of the RasterImage specific functions are used by DoComposite to
     130                 :  * destroy the old frame and build the new one.
     131                 :  *
     132                 :  * @note
     133                 :  * <li> "Mask", "Alpha", and "Alpha Level" are interchangeable phrases in
     134                 :  * respects to RasterImage.
     135                 :  *
     136                 :  * @par
     137                 :  * <li> GIFs never have more than a 1 bit alpha.
     138                 :  * <li> APNGs may have a full alpha channel.
     139                 :  *
     140                 :  * @par
     141                 :  * <li> Background color specified in GIF is ignored by web browsers.
     142                 :  *
     143                 :  * @par
     144                 :  * <li> If Frame 3 wants to dispose by restoring previous, what it wants is to
     145                 :  * restore the composition up to and including Frame 2, as well as Frame 2s
     146                 :  * disposal.  So, in the middle of DoComposite when composing Frame 3, right
     147                 :  * after destroying Frame 2's area, we copy compositingFrame to
     148                 :  * prevCompositingFrame.  When DoComposite gets called to do Frame 4, we
     149                 :  * copy prevCompositingFrame back, and then draw Frame 4 on top.
     150                 :  *
     151                 :  * @par
     152                 :  * The mAnim structure has members only needed for animated images, so
     153                 :  * it's not allocated until the second frame is added.
     154                 :  *
     155                 :  * @note
     156                 :  * mAnimationMode, mLoopCount and mObserver are not in the mAnim structure
     157                 :  * because the first two have public setters and the observer we only get
     158                 :  * in Init().
     159                 :  */
     160                 : 
     161                 : namespace mozilla {
     162                 : namespace layers {
     163                 : class LayerManager;
     164                 : class ImageContainer;
     165                 : }
     166                 : namespace image {
     167                 : 
     168                 : class Decoder;
     169                 : 
     170                 : class RasterImage : public Image
     171                 :                   , public nsIProperties
     172                 :                   , public nsSupportsWeakReference
     173                 : #ifdef DEBUG
     174                 :                   , public imgIContainerDebug
     175                 : #endif
     176                 : {
     177                 : public:
     178                 :   NS_DECL_ISUPPORTS
     179                 :   NS_DECL_NSIPROPERTIES
     180                 : #ifdef DEBUG
     181                 :   NS_DECL_IMGICONTAINERDEBUG
     182                 : #endif
     183                 : 
     184                 :   // BEGIN NS_DECL_IMGICONTAINER (minus GetAnimationMode/SetAnimationMode)
     185                 :   // ** Don't edit this chunk except to mirror changes in imgIContainer.idl **
     186                 :   NS_SCRIPTABLE NS_IMETHOD GetWidth(PRInt32 *aWidth);
     187                 :   NS_SCRIPTABLE NS_IMETHOD GetHeight(PRInt32 *aHeight);
     188                 :   NS_SCRIPTABLE NS_IMETHOD GetType(PRUint16 *aType);
     189                 :   NS_IMETHOD_(PRUint16) GetType(void);
     190                 :   NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated);
     191                 :   NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque);
     192                 :   NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM);
     193                 :   NS_IMETHOD GetImageContainer(mozilla::layers::ImageContainer **_retval NS_OUTPARAM);
     194                 :   NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
     195                 :   NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
     196                 :   NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);
     197                 :   NS_IMETHOD_(nsIFrame *) GetRootLayoutFrame(void);
     198                 :   NS_SCRIPTABLE NS_IMETHOD RequestDecode(void);
     199                 :   NS_SCRIPTABLE NS_IMETHOD LockImage(void);
     200                 :   NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
     201                 :   NS_SCRIPTABLE NS_IMETHOD RequestDiscard(void);
     202                 :   NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
     203                 :   NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
     204                 :   // END NS_DECL_IMGICONTAINER
     205                 : 
     206                 :   RasterImage(imgStatusTracker* aStatusTracker = nsnull);
     207                 :   virtual ~RasterImage();
     208                 : 
     209                 :   virtual nsresult StartAnimation();
     210                 :   virtual nsresult StopAnimation();
     211                 : 
     212                 :   // Methods inherited from Image
     213                 :   nsresult Init(imgIDecoderObserver* aObserver,
     214                 :                 const char* aMimeType,
     215                 :                 const char* aURIString,
     216                 :                 PRUint32 aFlags);
     217                 :   void     GetCurrentFrameRect(nsIntRect& aRect);
     218                 : 
     219                 :   // Raster-specific methods
     220                 :   static NS_METHOD WriteToRasterImage(nsIInputStream* aIn, void* aClosure,
     221                 :                                       const char* aFromRawSegment,
     222                 :                                       PRUint32 aToOffset, PRUint32 aCount,
     223                 :                                       PRUint32* aWriteCount);
     224                 : 
     225                 :   /* The index of the current frame that would be drawn if the image was to be
     226                 :    * drawn now. */
     227                 :   PRUint32 GetCurrentFrameIndex();
     228                 : 
     229                 :   /* The total number of frames in this image. */
     230                 :   PRUint32 GetNumFrames();
     231                 : 
     232                 :   virtual size_t HeapSizeOfSourceWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const;
     233                 :   virtual size_t HeapSizeOfDecodedWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const;
     234                 :   virtual size_t NonHeapSizeOfDecoded() const;
     235                 :   virtual size_t OutOfProcessSizeOfDecoded() const;
     236                 : 
     237                 :   /* Triggers discarding. */
     238                 :   void Discard(bool force = false);
     239               0 :   void ForceDiscard() { Discard(/* force = */ true); }
     240                 : 
     241                 :   /* Callbacks for decoders */
     242                 :   nsresult SetFrameDisposalMethod(PRUint32 aFrameNum,
     243                 :                                   PRInt32 aDisposalMethod);
     244                 :   nsresult SetFrameTimeout(PRUint32 aFrameNum, PRInt32 aTimeout);
     245                 :   nsresult SetFrameBlendMethod(PRUint32 aFrameNum, PRInt32 aBlendMethod);
     246                 :   nsresult SetFrameHasNoAlpha(PRUint32 aFrameNum);
     247                 : 
     248                 :   /**
     249                 :    * Sets the size of the container. This should only be called by the
     250                 :    * decoder. This function may be called multiple times, but will throw an
     251                 :    * error if subsequent calls do not match the first.
     252                 :    */
     253                 :   nsresult SetSize(PRInt32 aWidth, PRInt32 aHeight);
     254                 : 
     255                 : 
     256                 :   /**
     257                 :    * Ensures that a given frame number exists with the given parameters, and
     258                 :    * returns pointers to the data storage for that frame.
     259                 :    * It is not possible to create sparse frame arrays; you can only append
     260                 :    * frames to the current frame array.
     261                 :    */
     262                 :   nsresult EnsureFrame(PRUint32 aFramenum, PRInt32 aX, PRInt32 aY,
     263                 :                        PRInt32 aWidth, PRInt32 aHeight,
     264                 :                        gfxASurface::gfxImageFormat aFormat,
     265                 :                        PRUint8 aPaletteDepth,
     266                 :                        PRUint8** imageData,
     267                 :                        PRUint32* imageLength,
     268                 :                        PRUint32** paletteData,
     269                 :                        PRUint32* paletteLength);
     270                 : 
     271                 :   /**
     272                 :    * A shorthand for EnsureFrame, above, with aPaletteDepth = 0 and paletteData
     273                 :    * and paletteLength set to null.
     274                 :    */
     275                 :   nsresult EnsureFrame(PRUint32 aFramenum, PRInt32 aX, PRInt32 aY,
     276                 :                        PRInt32 aWidth, PRInt32 aHeight,
     277                 :                        gfxASurface::gfxImageFormat aFormat,
     278                 :                        PRUint8** imageData,
     279                 :                        PRUint32* imageLength);
     280                 : 
     281                 :   void FrameUpdated(PRUint32 aFrameNum, nsIntRect& aUpdatedRect);
     282                 : 
     283                 :   /* notification that the entire image has been decoded */
     284                 :   nsresult DecodingComplete();
     285                 : 
     286                 :   /**
     287                 :    * Number of times to loop the image.
     288                 :    * @note -1 means forever.
     289                 :    */
     290                 :   void     SetLoopCount(PRInt32 aLoopCount);
     291                 : 
     292                 :   /* Add compressed source data to the imgContainer.
     293                 :    *
     294                 :    * The decoder will use this data, either immediately or at draw time, to
     295                 :    * decode the image.
     296                 :    *
     297                 :    * XXX This method's only caller (WriteToContainer) ignores the return
     298                 :    * value. Should this just return void?
     299                 :    */
     300                 :   nsresult AddSourceData(const char *aBuffer, PRUint32 aCount);
     301                 : 
     302                 :   /* Called after the all the source data has been added with addSourceData. */
     303                 :   nsresult SourceDataComplete();
     304                 : 
     305                 :   /* Called for multipart images when there's a new source image to add. */
     306                 :   nsresult NewSourceData();
     307                 : 
     308                 :   /**
     309                 :    * A hint of the number of bytes of source data that the image contains. If
     310                 :    * called early on, this can help reduce copying and reallocations by
     311                 :    * appropriately preallocating the source data buffer.
     312                 :    *
     313                 :    * We take this approach rather than having the source data management code do
     314                 :    * something more complicated (like chunklisting) because HTTP is by far the
     315                 :    * dominant source of images, and the Content-Length header is quite reliable.
     316                 :    * Thus, pre-allocation simplifies code and reduces the total number of
     317                 :    * allocations.
     318                 :    */
     319                 :   nsresult SetSourceSizeHint(PRUint32 sizeHint);
     320                 : 
     321                 :   // "Blend" method indicates how the current image is combined with the
     322                 :   // previous image.
     323                 :   enum {
     324                 :     // All color components of the frame, including alpha, overwrite the current
     325                 :     // contents of the frame's output buffer region
     326                 :     kBlendSource =  0,
     327                 : 
     328                 :     // The frame should be composited onto the output buffer based on its alpha,
     329                 :     // using a simple OVER operation
     330                 :     kBlendOver
     331                 :   };
     332                 : 
     333                 :   enum {
     334                 :     kDisposeClearAll         = -1, // Clear the whole image, revealing
     335                 :                                    // what was there before the gif displayed
     336                 :     kDisposeNotSpecified,   // Leave frame, let new frame draw on top
     337                 :     kDisposeKeep,           // Leave frame, let new frame draw on top
     338                 :     kDisposeClear,          // Clear the frame's area, revealing bg
     339                 :     kDisposeRestorePrevious // Restore the previous (composited) frame
     340                 :   };
     341                 : 
     342               2 :   const char* GetURIString() { return mURIString.get();}
     343                 : 
     344                 : private:
     345                 :   struct Anim
     346                 :   {
     347                 :     //! Area of the first frame that needs to be redrawn on subsequent loops.
     348                 :     nsIntRect                  firstFrameRefreshArea;
     349                 :     PRUint32                   currentAnimationFrameIndex; // 0 to numFrames-1
     350                 : 
     351                 :     // the time that the animation advanced to the current frame
     352                 :     TimeStamp                  currentAnimationFrameTime;
     353                 : 
     354                 :     //! Track the last composited frame for Optimizations (See DoComposite code)
     355                 :     PRInt32                    lastCompositedFrameIndex;
     356                 :     /** For managing blending of frames
     357                 :      *
     358                 :      * Some animations will use the compositingFrame to composite images
     359                 :      * and just hand this back to the caller when it is time to draw the frame.
     360                 :      * NOTE: When clearing compositingFrame, remember to set
     361                 :      *       lastCompositedFrameIndex to -1.  Code assume that if
     362                 :      *       lastCompositedFrameIndex >= 0 then compositingFrame exists.
     363                 :      */
     364                 :     nsAutoPtr<imgFrame>        compositingFrame;
     365                 :     /** the previous composited frame, for DISPOSE_RESTORE_PREVIOUS
     366                 :      *
     367                 :      * The Previous Frame (all frames composited up to the current) needs to be
     368                 :      * stored in cases where the image specifies it wants the last frame back
     369                 :      * when it's done with the current frame.
     370                 :      */
     371                 :     nsAutoPtr<imgFrame>        compositingPrevFrame;
     372                 : 
     373               1 :     Anim() :
     374                 :       firstFrameRefreshArea(),
     375                 :       currentAnimationFrameIndex(0),
     376               1 :       lastCompositedFrameIndex(-1) {}
     377               1 :     ~Anim() {}
     378                 :   };
     379                 : 
     380                 :   /**
     381                 :    * DecodeWorker keeps a linked list of DecodeRequests to keep track of the
     382                 :    * images it needs to decode.
     383                 :    *
     384                 :    * Each RasterImage has a single DecodeRequest member.
     385                 :    */
     386                 :   struct DecodeRequest : public LinkedListElement<DecodeRequest>
     387                 :   {
     388              24 :     DecodeRequest(RasterImage* aImage)
     389                 :       : mImage(aImage)
     390              24 :       , mIsASAP(false)
     391                 :     {
     392              24 :     }
     393                 : 
     394                 :     RasterImage* const mImage;
     395                 : 
     396                 :     /* Keeps track of how much time we've burned decoding this particular decode
     397                 :      * request. */
     398                 :     TimeDuration mDecodeTime;
     399                 : 
     400                 :     /* True if we need to handle this decode as soon as possible. */
     401                 :     bool mIsASAP;
     402                 :   };
     403                 : 
     404                 :   /*
     405                 :    * DecodeWorker is a singleton class we use when decoding large images.
     406                 :    *
     407                 :    * When we wish to decode an image larger than
     408                 :    * image.mem.max_bytes_for_sync_decode, we call DecodeWorker::RequestDecode()
     409                 :    * for the image.  This adds the image to a queue of pending requests and posts
     410                 :    * the DecodeWorker singleton to the event queue, if it's not already pending
     411                 :    * there.
     412                 :    *
     413                 :    * When the DecodeWorker is run from the event queue, it decodes the image (and
     414                 :    * all others it's managing) in chunks, periodically yielding control back to
     415                 :    * the event loop.
     416                 :    *
     417                 :    * An image being decoded may have one of two priorities: normal or ASAP.  ASAP
     418                 :    * images are always decoded before normal images.  (We currently give ASAP
     419                 :    * priority to images which appear onscreen but are not yet decoded.)
     420                 :    */
     421                 :   class DecodeWorker : public nsRunnable
     422              16 :   {
     423                 :   public:
     424                 :     static DecodeWorker* Singleton();
     425                 : 
     426                 :     /**
     427                 :      * Ask the DecodeWorker to asynchronously decode this image.
     428                 :      */
     429                 :     void RequestDecode(RasterImage* aImg);
     430                 : 
     431                 :     /**
     432                 :      * Give this image ASAP priority; it will be decoded before all non-ASAP
     433                 :      * images.  You can call MarkAsASAP before or after you call RequestDecode
     434                 :      * for the image, but if you MarkAsASAP before you call RequestDecode, you
     435                 :      * still need to call RequestDecode.
     436                 :      *
     437                 :      * StopDecoding() resets the image's ASAP flag.
     438                 :      */
     439                 :     void MarkAsASAP(RasterImage* aImg);
     440                 : 
     441                 :     /**
     442                 :      * Ask the DecodeWorker to stop decoding this image.  Internally, we also
     443                 :      * call this function when we finish decoding an image.
     444                 :      *
     445                 :      * Since the DecodeWorker keeps raw pointers to RasterImages, make sure you
     446                 :      * call this before a RasterImage is destroyed!
     447                 :      */
     448                 :     void StopDecoding(RasterImage* aImg);
     449                 : 
     450                 :     /**
     451                 :      * Synchronously decode the beginning of the image until we run out of
     452                 :      * bytes or we get the image's size.  Note that this done on a best-effort
     453                 :      * basis; if the size is burried too deep in the image, we'll give up.
     454                 :      *
     455                 :      * @return NS_ERROR if an error is encountered, and NS_OK otherwise.  (Note
     456                 :      *         that we return NS_OK even when the size was not found.)
     457                 :      */
     458                 :     nsresult DecodeUntilSizeAvailable(RasterImage* aImg);
     459                 : 
     460                 :     NS_IMETHOD Run();
     461                 : 
     462                 :   private: /* statics */
     463                 :     static nsRefPtr<DecodeWorker> sSingleton;
     464                 : 
     465                 :   private: /* methods */
     466               4 :     DecodeWorker()
     467               4 :       : mPendingInEventLoop(false)
     468               4 :     {}
     469                 : 
     470                 :     /* Post ourselves to the event loop if we're not currently pending. */
     471                 :     void EnsurePendingInEventLoop();
     472                 : 
     473                 :     /* Add the given request to the appropriate list of decode requests, but
     474                 :      * don't ensure that we're pending in the event loop. */
     475                 :     void AddDecodeRequest(DecodeRequest* aRequest);
     476                 : 
     477                 :     enum DecodeType {
     478                 :       DECODE_TYPE_NORMAL,
     479                 :       DECODE_TYPE_UNTIL_SIZE
     480                 :     };
     481                 : 
     482                 :     /* Decode some chunks of the given image.  If aDecodeType is UNTIL_SIZE,
     483                 :      * decode until we have the image's size, then stop. */
     484                 :     nsresult DecodeSomeOfImage(RasterImage* aImg,
     485                 :                                DecodeType aDecodeType = DECODE_TYPE_NORMAL);
     486                 : 
     487                 :   private: /* members */
     488                 : 
     489                 :     LinkedList<DecodeRequest> mASAPDecodeRequests;
     490                 :     LinkedList<DecodeRequest> mNormalDecodeRequests;
     491                 : 
     492                 :     /* True if we've posted ourselves to the event loop and expect Run() to
     493                 :      * be called sometime in the future. */
     494                 :     bool mPendingInEventLoop;
     495                 :   };
     496                 : 
     497                 :   /**
     498                 :    * Advances the animation. Typically, this will advance a single frame, but it
     499                 :    * may advance multiple frames. This may happen if we have infrequently
     500                 :    * "ticking" refresh drivers (e.g. in background tabs), or extremely short-
     501                 :    * lived animation frames.
     502                 :    *
     503                 :    * @param aTime the time that the animation should advance to. This will
     504                 :    *              typically be <= TimeStamp::Now().
     505                 :    *
     506                 :    * @param [out] aDirtyRect a pointer to an nsIntRect which encapsulates the
     507                 :    *        area to be repainted after the frame is advanced.
     508                 :    *
     509                 :    * @returns true, if the frame was successfully advanced, false if it was not
     510                 :    *          able to be advanced (e.g. the frame to which we want to advance is
     511                 :    *          still decoding). Note: If false is returned, then aDirtyRect will
     512                 :    *          remain unmodified.
     513                 :    */
     514                 :   bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
     515                 : 
     516                 :   /**
     517                 :    * Deletes and nulls out the frame in mFrames[framenum].
     518                 :    *
     519                 :    * Does not change the size of mFrames.
     520                 :    *
     521                 :    * @param framenum The index of the frame to be deleted. 
     522                 :    *                 Must lie in [0, mFrames.Length() )
     523                 :    */
     524                 :   void DeleteImgFrame(PRUint32 framenum);
     525                 : 
     526                 :   imgFrame* GetImgFrameNoDecode(PRUint32 framenum);
     527                 :   imgFrame* GetImgFrame(PRUint32 framenum);
     528                 :   imgFrame* GetDrawableImgFrame(PRUint32 framenum);
     529                 :   imgFrame* GetCurrentImgFrame();
     530                 :   imgFrame* GetCurrentDrawableImgFrame();
     531                 :   PRUint32 GetCurrentImgFrameIndex() const;
     532                 :   mozilla::TimeStamp GetCurrentImgFrameEndTime() const;
     533                 :   
     534               1 :   inline void EnsureAnimExists()
     535                 :   {
     536               1 :     if (!mAnim) {
     537                 : 
     538                 :       // Create the animation context
     539               1 :       mAnim = new Anim();
     540                 : 
     541                 :       // We don't support discarding animated images (See bug 414259).
     542                 :       // Lock the image and throw away the key.
     543                 :       // 
     544                 :       // Note that this is inefficient, since we could get rid of the source
     545                 :       // data too. However, doing this is actually hard, because we're probably
     546                 :       // calling ensureAnimExists mid-decode, and thus we're decoding out of
     547                 :       // the source buffer. Since we're going to fix this anyway later, and
     548                 :       // since we didn't kill the source data in the old world either, locking
     549                 :       // is acceptable for the moment.
     550               1 :       LockImage();
     551                 : 
     552                 :       // Notify our observers that we are starting animation.
     553               1 :       mStatusTracker->RecordImageIsAnimated();
     554                 :     }
     555               1 :   }
     556                 : 
     557                 :   /** Function for doing the frame compositing of animations
     558                 :    *
     559                 :    * @param aDirtyRect  Area that the display will need to update
     560                 :    * @param aPrevFrame  Last Frame seen/processed
     561                 :    * @param aNextFrame  Frame we need to incorperate/display
     562                 :    * @param aNextFrameIndex Position of aNextFrame in mFrames list
     563                 :    */
     564                 :   nsresult DoComposite(nsIntRect* aDirtyRect,
     565                 :                        imgFrame* aPrevFrame,
     566                 :                        imgFrame* aNextFrame,
     567                 :                        PRInt32 aNextFrameIndex);
     568                 : 
     569                 :   /** Clears an area of <aFrame> with transparent black.
     570                 :    *
     571                 :    * @param aFrame Target Frame
     572                 :    *
     573                 :    * @note Does also clears the transparancy mask
     574                 :    */
     575                 :   static void ClearFrame(imgFrame* aFrame);
     576                 : 
     577                 :   //! @overload
     578                 :   static void ClearFrame(imgFrame* aFrame, nsIntRect &aRect);
     579                 :   
     580                 :   //! Copy one frames's image and mask into another
     581                 :   static bool CopyFrameImage(imgFrame *aSrcFrame,
     582                 :                                imgFrame *aDstFrame);
     583                 :   
     584                 :   /** Draws one frames's image to into another,
     585                 :    * at the position specified by aRect
     586                 :    *
     587                 :    * @param aSrcFrame  Frame providing the source image
     588                 :    * @param aDstFrame  Frame where the image is drawn into
     589                 :    * @param aRect      The position and size to draw the image
     590                 :    */
     591                 :   static nsresult DrawFrameTo(imgFrame *aSrcFrame,
     592                 :                               imgFrame *aDstFrame,
     593                 :                               nsIntRect& aRect);
     594                 : 
     595                 :   nsresult InternalAddFrameHelper(PRUint32 framenum, imgFrame *frame,
     596                 :                                   PRUint8 **imageData, PRUint32 *imageLength,
     597                 :                                   PRUint32 **paletteData, PRUint32 *paletteLength);
     598                 :   nsresult InternalAddFrame(PRUint32 framenum, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,
     599                 :                             gfxASurface::gfxImageFormat aFormat, PRUint8 aPaletteDepth,
     600                 :                             PRUint8 **imageData, PRUint32 *imageLength,
     601                 :                             PRUint32 **paletteData, PRUint32 *paletteLength);
     602                 : 
     603                 : private: // data
     604                 : 
     605                 :   nsIntSize                  mSize;
     606                 : 
     607                 :   // Whether mFrames below were decoded using any special flags.
     608                 :   // Some flags (e.g. unpremultiplied data) may not be compatible
     609                 :   // with the browser's needs for displaying the image to the user.
     610                 :   // As such, we may need to redecode if we're being asked for
     611                 :   // a frame with different flags.  0 indicates default flags.
     612                 :   //
     613                 :   // Valid flag bits are imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA
     614                 :   // and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION.
     615                 :   PRUint32                   mFrameDecodeFlags;
     616                 : 
     617                 :   //! All the frames of the image
     618                 :   // IMPORTANT: if you use mFrames in a method, call EnsureImageIsDecoded() first 
     619                 :   // to ensure that the frames actually exist (they may have been discarded to save
     620                 :   // memory, or we may be decoding on draw).
     621                 :   nsTArray<imgFrame *>       mFrames;
     622                 :   
     623                 :   nsCOMPtr<nsIProperties>    mProperties;
     624                 : 
     625                 :   // IMPORTANT: if you use mAnim in a method, call EnsureImageIsDecoded() first to ensure
     626                 :   // that the frames actually exist (they may have been discarded to save memory, or
     627                 :   // we maybe decoding on draw).
     628                 :   RasterImage::Anim*        mAnim;
     629                 :   
     630                 :   //! # loops remaining before animation stops (-1 no stop)
     631                 :   PRInt32                    mLoopCount;
     632                 :   
     633                 :   //! imgIDecoderObserver
     634                 :   nsWeakPtr                  mObserver;
     635                 : 
     636                 :   // Discard members
     637                 :   PRUint32                   mLockCount;
     638                 :   DiscardTrackerNode         mDiscardTrackerNode;
     639                 : 
     640                 :   // Source data members
     641                 :   FallibleTArray<char>       mSourceData;
     642                 :   nsCString                  mSourceDataMimeType;
     643                 :   nsCString                  mURIString;
     644                 : 
     645                 :   friend class DiscardTracker;
     646                 : 
     647                 :   // Decoder and friends
     648                 :   nsRefPtr<Decoder>              mDecoder;
     649                 :   DecodeRequest                  mDecodeRequest;
     650                 :   PRUint32                       mBytesDecoded;
     651                 : 
     652                 :   // How many times we've decoded this image.
     653                 :   // This is currently only used for statistics
     654                 :   PRInt32                        mDecodeCount;
     655                 : 
     656                 :   // Cached value for GetImageContainer.
     657                 :   nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
     658                 : 
     659                 : #ifdef DEBUG
     660                 :   PRUint32                       mFramesNotified;
     661                 : #endif
     662                 : 
     663                 :   // Boolean flags (clustered together to conserve space):
     664                 :   bool                       mHasSize:1;       // Has SetSize() been called?
     665                 :   bool                       mDecodeOnDraw:1;  // Decoding on draw?
     666                 :   bool                       mMultipart:1;     // Multipart?
     667                 :   bool                       mDiscardable:1;   // Is container discardable?
     668                 :   bool                       mHasSourceData:1; // Do we have source data?
     669                 : 
     670                 :   // Do we have the frames in decoded form?
     671                 :   bool                       mDecoded:1;
     672                 :   bool                       mHasBeenDecoded:1;
     673                 : 
     674                 :   bool                       mInDecoder:1;
     675                 : 
     676                 :   // Whether the animation can stop, due to running out
     677                 :   // of frames, or no more owning request
     678                 :   bool                       mAnimationFinished:1;
     679                 : 
     680                 :   // Decoding
     681                 :   nsresult WantDecodedFrames();
     682                 :   nsresult SyncDecode();
     683                 :   nsresult InitDecoder(bool aDoSizeDecode);
     684                 :   nsresult WriteToDecoder(const char *aBuffer, PRUint32 aCount);
     685                 :   nsresult DecodeSomeData(PRUint32 aMaxBytes);
     686                 :   bool     IsDecodeFinished();
     687                 :   TimeStamp mDrawStartTime;
     688                 : 
     689                 :   // Decoder shutdown
     690                 :   enum eShutdownIntent {
     691                 :     eShutdownIntent_Done        = 0,
     692                 :     eShutdownIntent_Interrupted = 1,
     693                 :     eShutdownIntent_Error       = 2,
     694                 :     eShutdownIntent_AllCount    = 3
     695                 :   };
     696                 :   nsresult ShutdownDecoder(eShutdownIntent aIntent);
     697                 : 
     698                 :   // Helpers
     699                 :   void DoError();
     700                 :   bool CanDiscard();
     701                 :   bool CanForciblyDiscard();
     702                 :   bool DiscardingActive();
     703                 :   bool StoringSourceData() const;
     704                 : 
     705                 : protected:
     706                 :   bool ShouldAnimate();
     707                 : };
     708                 : 
     709                 : // Asynchronous Decode Requestor
     710                 : //
     711                 : // We use this class when someone calls requestDecode() from within a decode
     712                 : // notification. Since requestDecode() involves modifying the decoder's state
     713                 : // (for example, possibly shutting down a header-only decode and starting a
     714                 : // full decode), we don't want to do this from inside a decoder.
     715                 : class imgDecodeRequestor : public nsRunnable
     716               0 : {
     717                 :   public:
     718               0 :     imgDecodeRequestor(imgIContainer *aContainer) {
     719               0 :       mContainer = do_GetWeakReference(aContainer);
     720               0 :     }
     721               0 :     NS_IMETHOD Run() {
     722               0 :       nsCOMPtr<imgIContainer> con = do_QueryReferent(mContainer);
     723               0 :       if (con)
     724               0 :         con->RequestDecode();
     725               0 :       return NS_OK;
     726                 :     }
     727                 : 
     728                 :   private:
     729                 :     nsWeakPtr mContainer;
     730                 : };
     731                 : 
     732                 : } // namespace image
     733                 : } // namespace mozilla
     734                 : 
     735                 : #endif /* mozilla_imagelib_RasterImage_h_ */

Generated by: LCOV version 1.7