LCOV - code coverage report
Current view: directory - image/src - VectorImage.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 257 0 0.0 %
Date: 2012-06-02 Functions: 45 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * the Mozilla Foundation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Daniel Holbert <dholbert@mozilla.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "VectorImage.h"
      40                 : 
      41                 : #include "imgIDecoderObserver.h"
      42                 : #include "SVGDocumentWrapper.h"
      43                 : #include "gfxContext.h"
      44                 : #include "gfxPlatform.h"
      45                 : #include "nsPresContext.h"
      46                 : #include "nsRect.h"
      47                 : #include "nsIObserverService.h"
      48                 : #include "nsIPresShell.h"
      49                 : #include "nsIStreamListener.h"
      50                 : #include "nsComponentManagerUtils.h"
      51                 : #include "nsServiceManagerUtils.h"
      52                 : #include "nsSVGUtils.h"  // for nsSVGUtils::ConvertToSurfaceSize
      53                 : #include "nsSVGEffects.h" // for nsSVGRenderingObserver
      54                 : #include "gfxDrawable.h"
      55                 : #include "gfxUtils.h"
      56                 : #include "nsSVGSVGElement.h"
      57                 : 
      58                 : namespace mozilla {
      59                 : 
      60                 : using namespace dom;
      61                 : 
      62                 : namespace image {
      63                 : 
      64                 : // Helper-class: SVGRootRenderingObserver
      65                 : class SVGRootRenderingObserver : public nsSVGRenderingObserver {
      66                 : public:
      67               0 :   SVGRootRenderingObserver(SVGDocumentWrapper* aDocWrapper,
      68                 :                            VectorImage*        aVectorImage)
      69                 :     : nsSVGRenderingObserver(),
      70                 :       mDocWrapper(aDocWrapper),
      71               0 :       mVectorImage(aVectorImage)
      72                 :   {
      73               0 :     StartListening();
      74               0 :     Element* elem = GetTarget();
      75               0 :     if (elem) {
      76               0 :       nsSVGEffects::AddRenderingObserver(elem, this);
      77               0 :       mInObserverList = true;
      78                 :     }
      79                 : #ifdef DEBUG
      80                 :     else {
      81               0 :       NS_ABORT_IF_FALSE(!mInObserverList,
      82                 :                         "Have no target, so we can't be in "
      83                 :                         "target's observer list...");
      84                 :     }
      85                 : #endif
      86               0 :   }
      87                 : 
      88               0 :   virtual ~SVGRootRenderingObserver()
      89               0 :   {
      90               0 :     StopListening();
      91               0 :   }
      92                 : 
      93                 : protected:
      94               0 :   virtual Element* GetTarget()
      95                 :   {
      96               0 :     return mDocWrapper->GetRootSVGElem();
      97                 :   }
      98                 : 
      99               0 :   virtual void DoUpdate()
     100                 :   {
     101               0 :     Element* elem = GetTarget();
     102               0 :     if (!elem)
     103               0 :       return;
     104                 : 
     105               0 :     if (!mDocWrapper->ShouldIgnoreInvalidation()) {
     106               0 :       nsIFrame* frame = elem->GetPrimaryFrame();
     107               0 :       if (!frame || frame->PresContext()->PresShell()->IsDestroying()) {
     108                 :         // We're being destroyed. Bail out.
     109               0 :         return;
     110                 :       }
     111                 : 
     112               0 :       mVectorImage->InvalidateObserver();
     113                 :     }
     114                 : 
     115                 :     // Our caller might've removed us from rendering-observer list.
     116                 :     // Add ourselves back!
     117               0 :     if (!mInObserverList) {
     118               0 :       nsSVGEffects::AddRenderingObserver(elem, this);
     119               0 :       mInObserverList = true;
     120                 :     }
     121                 :   }
     122                 : 
     123                 :   // Private data
     124                 :   nsRefPtr<SVGDocumentWrapper> mDocWrapper;
     125                 :   VectorImage* mVectorImage;   // Raw pointer because it owns me.
     126                 : };
     127                 : 
     128                 : // Helper-class: SVGDrawingCallback
     129               0 : class SVGDrawingCallback : public gfxDrawingCallback {
     130                 : public:
     131               0 :   SVGDrawingCallback(SVGDocumentWrapper* aSVGDocumentWrapper,
     132                 :                      const nsIntRect& aViewport,
     133                 :                      PRUint32 aImageFlags) :
     134                 :     mSVGDocumentWrapper(aSVGDocumentWrapper),
     135                 :     mViewport(aViewport),
     136               0 :     mImageFlags(aImageFlags)
     137               0 :   {}
     138                 :   virtual bool operator()(gfxContext* aContext,
     139                 :                             const gfxRect& aFillRect,
     140                 :                             const gfxPattern::GraphicsFilter& aFilter,
     141                 :                             const gfxMatrix& aTransform);
     142                 : private:
     143                 :   nsRefPtr<SVGDocumentWrapper> mSVGDocumentWrapper;
     144                 :   const nsIntRect mViewport;
     145                 :   PRUint32        mImageFlags;
     146                 : };
     147                 : 
     148                 : // Based loosely on nsSVGIntegrationUtils' PaintFrameCallback::operator()
     149                 : bool
     150               0 : SVGDrawingCallback::operator()(gfxContext* aContext,
     151                 :                                const gfxRect& aFillRect,
     152                 :                                const gfxPattern::GraphicsFilter& aFilter,
     153                 :                                const gfxMatrix& aTransform)
     154                 : {
     155               0 :   NS_ABORT_IF_FALSE(mSVGDocumentWrapper, "need an SVGDocumentWrapper");
     156                 : 
     157                 :   // Get (& sanity-check) the helper-doc's presShell
     158               0 :   nsCOMPtr<nsIPresShell> presShell;
     159               0 :   if (NS_FAILED(mSVGDocumentWrapper->GetPresShell(getter_AddRefs(presShell)))) {
     160               0 :     NS_WARNING("Unable to draw -- presShell lookup failed");
     161               0 :     return false;
     162                 :   }
     163               0 :   NS_ABORT_IF_FALSE(presShell, "GetPresShell succeeded but returned null");
     164                 : 
     165               0 :   gfxContextAutoSaveRestore contextRestorer(aContext);
     166                 : 
     167                 :   // Clip to aFillRect so that we don't paint outside.
     168               0 :   aContext->NewPath();
     169               0 :   aContext->Rectangle(aFillRect);
     170               0 :   aContext->Clip();
     171                 : 
     172               0 :   gfxContextMatrixAutoSaveRestore contextMatrixRestorer(aContext);
     173               0 :   aContext->Multiply(gfxMatrix(aTransform).Invert());
     174                 : 
     175               0 :   nsPresContext* presContext = presShell->GetPresContext();
     176               0 :   NS_ABORT_IF_FALSE(presContext, "pres shell w/out pres context");
     177                 : 
     178                 :   nsRect svgRect(presContext->DevPixelsToAppUnits(mViewport.x),
     179                 :                  presContext->DevPixelsToAppUnits(mViewport.y),
     180                 :                  presContext->DevPixelsToAppUnits(mViewport.width),
     181               0 :                  presContext->DevPixelsToAppUnits(mViewport.height));
     182                 : 
     183               0 :   PRUint32 renderDocFlags = nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
     184               0 :   if (!(mImageFlags & imgIContainer::FLAG_SYNC_DECODE)) {
     185               0 :     renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
     186                 :   }
     187                 : 
     188               0 :   presShell->RenderDocument(svgRect, renderDocFlags,
     189                 :                             NS_RGBA(0, 0, 0, 0), // transparent
     190               0 :                             aContext);
     191                 : 
     192               0 :   return true;
     193                 : }
     194                 : 
     195                 : // Implement VectorImage's nsISupports-inherited methods
     196               0 : NS_IMPL_ISUPPORTS3(VectorImage,
     197                 :                    imgIContainer,
     198                 :                    nsIStreamListener,
     199                 :                    nsIRequestObserver)
     200                 : 
     201                 : //------------------------------------------------------------------------------
     202                 : // Constructor / Destructor
     203                 : 
     204               0 : VectorImage::VectorImage(imgStatusTracker* aStatusTracker) :
     205                 :   Image(aStatusTracker), // invoke superclass's constructor
     206                 :   mRestrictedRegion(0, 0, 0, 0),
     207                 :   mLastRenderedSize(0, 0),
     208                 :   mIsInitialized(false),
     209                 :   mIsFullyLoaded(false),
     210                 :   mIsDrawing(false),
     211                 :   mHaveAnimations(false),
     212               0 :   mHaveRestrictedRegion(false)
     213                 : {
     214               0 : }
     215                 : 
     216               0 : VectorImage::~VectorImage()
     217                 : {
     218               0 : }
     219                 : 
     220                 : //------------------------------------------------------------------------------
     221                 : // Methods inherited from Image.h
     222                 : 
     223                 : nsresult
     224               0 : VectorImage::Init(imgIDecoderObserver* aObserver,
     225                 :                   const char* aMimeType,
     226                 :                   const char* aURIString,
     227                 :                   PRUint32 aFlags)
     228                 : {
     229                 :   // We don't support re-initialization
     230               0 :   if (mIsInitialized)
     231               0 :     return NS_ERROR_ILLEGAL_VALUE;
     232                 : 
     233               0 :   NS_ABORT_IF_FALSE(!mIsFullyLoaded && !mHaveAnimations &&
     234                 :                     !mHaveRestrictedRegion && !mError,
     235                 :                     "Flags unexpectedly set before initialization");
     236                 : 
     237               0 :   mObserver = do_GetWeakReference(aObserver);
     238               0 :   NS_ABORT_IF_FALSE(!strcmp(aMimeType, SVG_MIMETYPE), "Unexpected mimetype");
     239                 : 
     240               0 :   mIsInitialized = true;
     241                 : 
     242               0 :   return NS_OK;
     243                 : }
     244                 : 
     245                 : void
     246               0 : VectorImage::GetCurrentFrameRect(nsIntRect& aRect)
     247                 : {
     248               0 :   aRect = nsIntRect::GetMaxSizedIntRect();
     249               0 : }
     250                 : 
     251                 : size_t
     252               0 : VectorImage::HeapSizeOfSourceWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const
     253                 : {
     254                 :   // We're not storing the source data -- we just feed that directly to
     255                 :   // our helper SVG document as we receive it, for it to parse.
     256                 :   // So 0 is an appropriate return value here.
     257               0 :   return 0;
     258                 : }
     259                 : 
     260                 : size_t
     261               0 : VectorImage::HeapSizeOfDecodedWithComputedFallback(nsMallocSizeOfFun aMallocSizeOf) const
     262                 : {
     263                 :   // XXXdholbert TODO: return num bytes used by helper SVG doc. (bug 590790)
     264               0 :   return 0;
     265                 : }
     266                 : 
     267                 : size_t
     268               0 : VectorImage::NonHeapSizeOfDecoded() const
     269                 : {
     270               0 :   return 0;
     271                 : }
     272                 : 
     273                 : size_t
     274               0 : VectorImage::OutOfProcessSizeOfDecoded() const
     275                 : {
     276               0 :   return 0;
     277                 : }
     278                 : 
     279                 : nsresult
     280               0 : VectorImage::StartAnimation()
     281                 : {
     282               0 :   if (mError)
     283               0 :     return NS_ERROR_FAILURE;
     284                 : 
     285               0 :   NS_ABORT_IF_FALSE(ShouldAnimate(), "Should not animate!");
     286                 : 
     287               0 :   mSVGDocumentWrapper->StartAnimation();
     288               0 :   return NS_OK;
     289                 : }
     290                 : 
     291                 : nsresult
     292               0 : VectorImage::StopAnimation()
     293                 : {
     294               0 :   if (mError)
     295               0 :     return NS_ERROR_FAILURE;
     296                 : 
     297               0 :   NS_ABORT_IF_FALSE(mIsFullyLoaded && mHaveAnimations,
     298                 :                     "Should not have been animating!");
     299                 : 
     300               0 :   mSVGDocumentWrapper->StopAnimation();
     301               0 :   return NS_OK;
     302                 : }
     303                 : 
     304                 : bool
     305               0 : VectorImage::ShouldAnimate()
     306                 : {
     307               0 :   return Image::ShouldAnimate() && mIsFullyLoaded && mHaveAnimations;
     308                 : }
     309                 : 
     310                 : //------------------------------------------------------------------------------
     311                 : // imgIContainer methods
     312                 : 
     313                 : //******************************************************************************
     314                 : /* readonly attribute PRInt32 width; */
     315                 : NS_IMETHODIMP
     316               0 : VectorImage::GetWidth(PRInt32* aWidth)
     317                 : {
     318               0 :   if (mError || !mIsFullyLoaded) {
     319               0 :     *aWidth = 0;
     320               0 :     return NS_ERROR_FAILURE;
     321                 :   }
     322                 : 
     323               0 :   if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth,
     324               0 :                                              *aWidth)) {
     325               0 :     *aWidth = 0;
     326               0 :     return NS_ERROR_FAILURE;
     327                 :   }
     328                 : 
     329               0 :   return NS_OK;
     330                 : }
     331                 : 
     332                 : //******************************************************************************
     333                 : /* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
     334                 : NS_IMETHODIMP_(void)
     335               0 : VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
     336                 : {
     337                 :   // TODO: Implement for b666446.
     338               0 : }
     339                 : 
     340                 : //******************************************************************************
     341                 : /* readonly attribute PRInt32 height; */
     342                 : NS_IMETHODIMP
     343               0 : VectorImage::GetHeight(PRInt32* aHeight)
     344                 : {
     345               0 :   if (mError || !mIsFullyLoaded) {
     346               0 :     *aHeight = 0;
     347               0 :     return NS_ERROR_FAILURE;
     348                 :   }
     349                 : 
     350               0 :   if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight,
     351               0 :                                              *aHeight)) {
     352               0 :     *aHeight = 0;
     353               0 :     return NS_ERROR_FAILURE;
     354                 :   }
     355                 : 
     356               0 :   return NS_OK;
     357                 : }
     358                 : 
     359                 : //******************************************************************************
     360                 : /* readonly attribute unsigned short type; */
     361                 : NS_IMETHODIMP
     362               0 : VectorImage::GetType(PRUint16* aType)
     363                 : {
     364               0 :   NS_ENSURE_ARG_POINTER(aType);
     365                 : 
     366               0 :   *aType = GetType();
     367               0 :   return NS_OK;
     368                 : }
     369                 : 
     370                 : //******************************************************************************
     371                 : /* [noscript, notxpcom] PRUint16 GetType(); */
     372                 : NS_IMETHODIMP_(PRUint16)
     373               0 : VectorImage::GetType()
     374                 : {
     375               0 :   return imgIContainer::TYPE_VECTOR;
     376                 : }
     377                 : 
     378                 : //******************************************************************************
     379                 : /* readonly attribute boolean animated; */
     380                 : NS_IMETHODIMP
     381               0 : VectorImage::GetAnimated(bool* aAnimated)
     382                 : {
     383               0 :   if (mError || !mIsFullyLoaded)
     384               0 :     return NS_ERROR_FAILURE;
     385                 : 
     386               0 :   *aAnimated = mSVGDocumentWrapper->IsAnimated();
     387               0 :   return NS_OK;
     388                 : }
     389                 : 
     390                 : //******************************************************************************
     391                 : /* readonly attribute boolean currentFrameIsOpaque; */
     392                 : NS_IMETHODIMP
     393               0 : VectorImage::GetCurrentFrameIsOpaque(bool* aIsOpaque)
     394                 : {
     395               0 :   NS_ENSURE_ARG_POINTER(aIsOpaque);
     396               0 :   *aIsOpaque = false;   // In general, SVG content is not opaque.
     397               0 :   return NS_OK;
     398                 : }
     399                 : 
     400                 : //******************************************************************************
     401                 : /* [noscript] gfxASurface getFrame(in PRUint32 aWhichFrame,
     402                 :  *                                 in PRUint32 aFlags; */
     403                 : NS_IMETHODIMP
     404               0 : VectorImage::GetFrame(PRUint32 aWhichFrame,
     405                 :                       PRUint32 aFlags,
     406                 :                       gfxASurface** _retval)
     407                 : {
     408               0 :   NS_ENSURE_ARG_POINTER(_retval);
     409               0 :   nsRefPtr<gfxImageSurface> surface;
     410               0 :   nsresult rv = CopyFrame(aWhichFrame, aFlags, getter_AddRefs(surface));
     411               0 :   if (NS_SUCCEEDED(rv)) {
     412               0 :     *_retval = surface.forget().get();
     413                 :   }
     414               0 :   return rv;
     415                 : }
     416                 : 
     417                 : //******************************************************************************
     418                 : /* [noscript] gfxImageSurface copyFrame(in PRUint32 aWhichFrame,
     419                 :  *                                      in PRUint32 aFlags); */
     420                 : NS_IMETHODIMP
     421               0 : VectorImage::CopyFrame(PRUint32 aWhichFrame,
     422                 :                        PRUint32 aFlags,
     423                 :                        gfxImageSurface** _retval)
     424                 : {
     425               0 :   NS_ENSURE_ARG_POINTER(_retval);
     426                 :   // XXXdholbert NOTE: Currently assuming FRAME_CURRENT for simplicity.
     427                 :   // Could handle FRAME_FIRST by saving helper-doc current time, seeking
     428                 :   // to time 0, rendering, and then seeking to saved time.
     429               0 :   if (aWhichFrame > FRAME_MAX_VALUE)
     430               0 :     return NS_ERROR_INVALID_ARG;
     431                 : 
     432               0 :   if (mError)
     433               0 :     return NS_ERROR_FAILURE;
     434                 : 
     435                 :   // Look up height & width
     436                 :   // ----------------------
     437               0 :   nsIntSize imageIntSize;
     438               0 :   if (!mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eWidth,
     439               0 :                                              imageIntSize.width) ||
     440                 :       !mSVGDocumentWrapper->GetWidthOrHeight(SVGDocumentWrapper::eHeight,
     441               0 :                                              imageIntSize.height)) {
     442                 :     // We'll get here if our SVG doc has a percent-valued width or height.
     443               0 :     return NS_ERROR_FAILURE;
     444                 :   }
     445                 : 
     446                 :   // Create a surface that we'll ultimately return
     447                 :   // ---------------------------------------------
     448                 :   // Make our surface the size of what will ultimately be drawn to it.
     449                 :   // (either the full image size, or the restricted region)
     450               0 :   gfxIntSize surfaceSize;
     451               0 :   if (mHaveRestrictedRegion) {
     452               0 :     surfaceSize.width = mRestrictedRegion.width;
     453               0 :     surfaceSize.height = mRestrictedRegion.height;
     454                 :   } else {
     455               0 :     surfaceSize.width = imageIntSize.width;
     456               0 :     surfaceSize.height = imageIntSize.height;
     457                 :   }
     458                 : 
     459                 :   nsRefPtr<gfxImageSurface> surface =
     460               0 :     new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32);
     461               0 :   nsRefPtr<gfxContext> context = new gfxContext(surface);
     462                 : 
     463                 :   // Draw to our surface!
     464                 :   // --------------------
     465                 :   nsresult rv = Draw(context, gfxPattern::FILTER_NEAREST, gfxMatrix(),
     466                 :                      gfxRect(gfxPoint(0,0), gfxIntSize(imageIntSize.width,
     467                 :                                                        imageIntSize.height)),
     468                 :                      nsIntRect(nsIntPoint(0,0), imageIntSize),
     469               0 :                      imageIntSize, aFlags);
     470               0 :   if (NS_SUCCEEDED(rv)) {
     471               0 :     *_retval = surface.forget().get();
     472                 :   }
     473                 : 
     474               0 :   return rv;
     475                 : }
     476                 : 
     477                 : //******************************************************************************
     478                 : /* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
     479                 :  *                                       [const] in nsIntRect aRegion,
     480                 :  *                                       in PRUint32 aFlags); */
     481                 : NS_IMETHODIMP
     482               0 : VectorImage::ExtractFrame(PRUint32 aWhichFrame,
     483                 :                           const nsIntRect& aRegion,
     484                 :                           PRUint32 aFlags,
     485                 :                           imgIContainer** _retval)
     486                 : {
     487               0 :   NS_ENSURE_ARG_POINTER(_retval);
     488               0 :   if (mError || !mIsFullyLoaded)
     489               0 :     return NS_ERROR_FAILURE;
     490                 : 
     491                 :   // XXXdholbert NOTE: This method assumes FRAME_CURRENT (not FRAME_FIRST)
     492                 :   // right now, because mozilla doesn't actually contain any clients of this
     493                 :   // method that use FRAME_FIRST.  If it's needed, we *could* handle
     494                 :   // FRAME_FIRST by saving the helper-doc's current SMIL time, seeking it to
     495                 :   // time 0, rendering to a RasterImage, and then restoring our saved time.
     496               0 :   if (aWhichFrame != FRAME_CURRENT) {
     497                 :     NS_WARNING("VectorImage::ExtractFrame with something other than "
     498               0 :                "FRAME_CURRENT isn't supported yet. Assuming FRAME_CURRENT.");
     499                 :   }
     500                 : 
     501                 :   // XXXdholbert This method also doesn't actually freeze animation in the
     502                 :   // returned imgIContainer, because it shares our helper-document. To
     503                 :   // get a true snapshot, we need to clone the document - see bug 590792.
     504                 : 
     505                 :   // Make a new container with same SVG document.
     506               0 :   nsRefPtr<VectorImage> extractedImg = new VectorImage();
     507               0 :   extractedImg->mSVGDocumentWrapper = mSVGDocumentWrapper;
     508               0 :   extractedImg->mAnimationMode = kDontAnimMode;
     509                 : 
     510               0 :   extractedImg->mRestrictedRegion.x = aRegion.x;
     511               0 :   extractedImg->mRestrictedRegion.y = aRegion.y;
     512                 : 
     513                 :   // (disallow negative width/height on our restricted region)
     514               0 :   extractedImg->mRestrictedRegion.width  = NS_MAX(aRegion.width,  0);
     515               0 :   extractedImg->mRestrictedRegion.height = NS_MAX(aRegion.height, 0);
     516                 : 
     517               0 :   extractedImg->mIsInitialized = true;
     518               0 :   extractedImg->mIsFullyLoaded = true;
     519               0 :   extractedImg->mHaveRestrictedRegion = true;
     520                 : 
     521               0 :   *_retval = extractedImg.forget().get();
     522               0 :   return NS_OK;
     523                 : }
     524                 : 
     525                 : 
     526                 : //******************************************************************************
     527                 : /* [noscript] void draw(in gfxContext aContext,
     528                 :  *                      in gfxGraphicsFilter aFilter,
     529                 :  *                      [const] in gfxMatrix aUserSpaceToImageSpace,
     530                 :  *                      [const] in gfxRect aFill,
     531                 :  *                      [const] in nsIntRect aSubimage,
     532                 :  *                      [const] in nsIntSize aViewportSize,
     533                 :  *                      in PRUint32 aFlags); */
     534                 : NS_IMETHODIMP
     535               0 : VectorImage::Draw(gfxContext* aContext,
     536                 :                   gfxPattern::GraphicsFilter aFilter,
     537                 :                   const gfxMatrix& aUserSpaceToImageSpace,
     538                 :                   const gfxRect& aFill,
     539                 :                   const nsIntRect& aSubimage,
     540                 :                   const nsIntSize& aViewportSize,
     541                 :                   PRUint32 aFlags)
     542                 : {
     543               0 :   NS_ENSURE_ARG_POINTER(aContext);
     544               0 :   if (mError || !mIsFullyLoaded)
     545               0 :     return NS_ERROR_FAILURE;
     546                 : 
     547               0 :   if (mIsDrawing) {
     548               0 :     NS_WARNING("Refusing to make re-entrant call to VectorImage::Draw");
     549               0 :     return NS_ERROR_FAILURE;
     550                 :   }
     551               0 :   mIsDrawing = true;
     552                 : 
     553               0 :   if (aViewportSize != mLastRenderedSize) {
     554               0 :     mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize);
     555               0 :     mLastRenderedSize = aViewportSize;
     556                 :   }
     557               0 :   mSVGDocumentWrapper->FlushImageTransformInvalidation();
     558                 : 
     559                 :   nsIntSize imageSize = mHaveRestrictedRegion ?
     560               0 :     mRestrictedRegion.Size() : aViewportSize;
     561                 : 
     562                 :   // XXXdholbert Do we need to convert image size from
     563                 :   // CSS pixels to dev pixels here? (is gfxCallbackDrawable's 2nd arg in dev
     564                 :   // pixels?)
     565               0 :   gfxIntSize imageSizeGfx(imageSize.width, imageSize.height);
     566                 : 
     567                 :   // Based on imgFrame::Draw
     568               0 :   gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill);
     569               0 :   gfxRect imageRect(0, 0, imageSize.width, imageSize.height);
     570               0 :   gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
     571                 : 
     572                 : 
     573                 :   nsRefPtr<gfxDrawingCallback> cb =
     574                 :     new SVGDrawingCallback(mSVGDocumentWrapper,
     575                 :                            mHaveRestrictedRegion ?
     576                 :                            mRestrictedRegion :
     577                 :                            nsIntRect(nsIntPoint(0, 0), aViewportSize),
     578               0 :                            aFlags);
     579                 : 
     580               0 :   nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, imageSizeGfx);
     581                 : 
     582                 :   gfxUtils::DrawPixelSnapped(aContext, drawable,
     583                 :                              aUserSpaceToImageSpace,
     584                 :                              subimage, sourceRect, imageRect, aFill,
     585               0 :                              gfxASurface::ImageFormatARGB32, aFilter);
     586                 : 
     587               0 :   mIsDrawing = false;
     588               0 :   return NS_OK;
     589                 : }
     590                 : 
     591                 : //******************************************************************************
     592                 : /* [notxpcom] nsIFrame GetRootLayoutFrame() */
     593                 : nsIFrame*
     594               0 : VectorImage::GetRootLayoutFrame()
     595                 : {
     596               0 :   if (mError)
     597               0 :     return nsnull;
     598                 : 
     599               0 :   return mSVGDocumentWrapper->GetRootLayoutFrame();
     600                 : }
     601                 : 
     602                 : //******************************************************************************
     603                 : /* void requestDecode() */
     604                 : NS_IMETHODIMP
     605               0 : VectorImage::RequestDecode()
     606                 : {
     607                 :   // Nothing to do for SVG images
     608               0 :   return NS_OK;
     609                 : }
     610                 : 
     611                 : //******************************************************************************
     612                 : /* void lockImage() */
     613                 : NS_IMETHODIMP
     614               0 : VectorImage::LockImage()
     615                 : {
     616                 :   // This method is for image-discarding, which only applies to RasterImages.
     617               0 :   return NS_OK;
     618                 : }
     619                 : 
     620                 : //******************************************************************************
     621                 : /* void unlockImage() */
     622                 : NS_IMETHODIMP
     623               0 : VectorImage::UnlockImage()
     624                 : {
     625                 :   // This method is for image-discarding, which only applies to RasterImages.
     626               0 :   return NS_OK;
     627                 : }
     628                 : 
     629                 : //******************************************************************************
     630                 : /* void requestDiscard() */
     631                 : NS_IMETHODIMP
     632               0 : VectorImage::RequestDiscard()
     633                 : {
     634                 :   // This method is for image-discarding, which only applies to RasterImages.
     635               0 :   return NS_OK;
     636                 : }
     637                 : 
     638                 : //******************************************************************************
     639                 : /* void resetAnimation (); */
     640                 : NS_IMETHODIMP
     641               0 : VectorImage::ResetAnimation()
     642                 : {
     643               0 :   if (mError)
     644               0 :     return NS_ERROR_FAILURE;
     645                 : 
     646               0 :   if (!mIsFullyLoaded || !mHaveAnimations) {
     647               0 :     return NS_OK; // There are no animations to be reset.
     648                 :   }
     649                 : 
     650               0 :   mSVGDocumentWrapper->ResetAnimation();
     651                 : 
     652               0 :   return NS_OK;
     653                 : }
     654                 : 
     655                 : //------------------------------------------------------------------------------
     656                 : // nsIRequestObserver methods
     657                 : 
     658                 : //******************************************************************************
     659                 : /* void onStartRequest(in nsIRequest request, in nsISupports ctxt); */
     660                 : NS_IMETHODIMP
     661               0 : VectorImage::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt)
     662                 : {
     663               0 :   NS_ABORT_IF_FALSE(!mSVGDocumentWrapper,
     664                 :                     "Repeated call to OnStartRequest -- can this happen?");
     665                 : 
     666               0 :   mSVGDocumentWrapper = new SVGDocumentWrapper();
     667               0 :   nsresult rv = mSVGDocumentWrapper->OnStartRequest(aRequest, aCtxt);
     668               0 :   if (NS_FAILED(rv)) {
     669               0 :     mSVGDocumentWrapper = nsnull;
     670               0 :     mError = true;
     671                 :   }
     672                 : 
     673               0 :   return rv;
     674                 : }
     675                 : 
     676                 : //******************************************************************************
     677                 : /* void onStopRequest(in nsIRequest request, in nsISupports ctxt,
     678                 :                       in nsresult status); */
     679                 : NS_IMETHODIMP
     680               0 : VectorImage::OnStopRequest(nsIRequest* aRequest, nsISupports* aCtxt,
     681                 :                            nsresult aStatus)
     682                 : {
     683               0 :   if (mError)
     684               0 :     return NS_ERROR_FAILURE;
     685                 : 
     686               0 :   NS_ABORT_IF_FALSE(!mIsFullyLoaded && !mHaveAnimations,
     687                 :                     "these flags shouldn't get set until OnStopRequest. "
     688                 :                     "Duplicate calls to OnStopRequest?");
     689                 : 
     690               0 :   nsresult rv = mSVGDocumentWrapper->OnStopRequest(aRequest, aCtxt, aStatus);
     691               0 :   if (!mSVGDocumentWrapper->ParsedSuccessfully()) {
     692                 :     // XXXdholbert Need to do something more here -- right now, this just
     693                 :     // makes us draw the "object" icon, rather than the (jagged) "broken image"
     694                 :     // icon.  See bug 594505.
     695               0 :     mError = true;
     696               0 :     return rv;
     697                 :   }
     698                 : 
     699               0 :   mIsFullyLoaded = true;
     700               0 :   mHaveAnimations = mSVGDocumentWrapper->IsAnimated();
     701                 : 
     702                 :   // Start listening to our image for rendering updates
     703               0 :   mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this);
     704                 : 
     705                 :   // Tell *our* observers that we're done loading
     706               0 :   nsCOMPtr<imgIDecoderObserver> observer = do_QueryReferent(mObserver);
     707               0 :   if (observer) {
     708                 :     // NOTE: This signals that width/height are available.
     709               0 :     observer->OnStartContainer(nsnull, this);
     710                 : 
     711               0 :     observer->FrameChanged(nsnull, this, &nsIntRect::GetMaxSizedIntRect());
     712               0 :     observer->OnStopFrame(nsnull, 0);
     713               0 :     observer->OnStopDecode(nsnull, NS_OK, nsnull);
     714                 :   }
     715               0 :   EvaluateAnimation();
     716                 : 
     717               0 :   return rv;
     718                 : }
     719                 : 
     720                 : //------------------------------------------------------------------------------
     721                 : // nsIStreamListener method
     722                 : 
     723                 : //******************************************************************************
     724                 : /* void onDataAvailable(in nsIRequest request, in nsISupports ctxt,
     725                 :                         in nsIInputStream inStr, in unsigned long sourceOffset,
     726                 :                         in unsigned long count); */
     727                 : NS_IMETHODIMP
     728               0 : VectorImage::OnDataAvailable(nsIRequest* aRequest, nsISupports* aCtxt,
     729                 :                              nsIInputStream* aInStr, PRUint32 aSourceOffset,
     730                 :                              PRUint32 aCount)
     731                 : {
     732               0 :   if (mError)
     733               0 :     return NS_ERROR_FAILURE;
     734                 : 
     735               0 :   return mSVGDocumentWrapper->OnDataAvailable(aRequest, aCtxt, aInStr,
     736               0 :                                               aSourceOffset, aCount);
     737                 : }
     738                 : 
     739                 : // --------------------------
     740                 : // Invalidation helper method
     741                 : 
     742                 : void
     743               0 : VectorImage::InvalidateObserver()
     744                 : {
     745               0 :   if (!mObserver)
     746               0 :     return;
     747                 : 
     748               0 :   nsCOMPtr<imgIContainerObserver> containerObs(do_QueryReferent(mObserver));
     749               0 :   if (containerObs) {
     750               0 :     containerObs->FrameChanged(nsnull, this, &nsIntRect::GetMaxSizedIntRect());
     751                 :   }
     752                 : 
     753               0 :   nsCOMPtr<imgIDecoderObserver> decoderObs(do_QueryReferent(mObserver));
     754               0 :   if (decoderObs) {
     755               0 :     decoderObs->OnStopFrame(nsnull, imgIContainer::FRAME_CURRENT);
     756                 :   }
     757                 : }
     758                 : 
     759                 : } // namespace image
     760                 : } // namespace mozilla

Generated by: LCOV version 1.7