diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 01ce8df91bf..b19d3e94515 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -55,6 +55,13 @@ interface imgIDecoderObserver; #include "nsSize.h" #include "limits.h" +namespace mozilla { +namespace layers { +class LayerManager; +class ImageContainer; +} +} + class nsIFrame; %} @@ -68,6 +75,8 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter); [ref] native nsIntRect(nsIntRect); [ref] native nsIntSize(nsIntSize); [ptr] native nsIFrame(nsIFrame); +[ptr] native ImageContainer(mozilla::layers::ImageContainer); +[ptr] native LayerManager(mozilla::layers::LayerManager); /** * imgIContainer is the interface that represents an image. It allows @@ -170,6 +179,14 @@ interface imgIContainer : nsISupports [noscript] gfxASurface getFrame(in PRUint32 aWhichFrame, in PRUint32 aFlags); + /** + * Attempts to create an ImageContainer (and Image) containing the current + * frame. Only valid for RASTER type images. + * + * @param aManager The layer manager to use to create the ImageContainer. + */ + [noscript] ImageContainer getImageContainer(in LayerManager aManager); + /** * Create and return a new copy of the given frame that you can write to * and otherwise inspect the pixels of. diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index ffb999751f8..4037950a008 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -58,6 +58,7 @@ #include "ImageLogging.h" #include "mozilla/TimeStamp.h" #include "mozilla/Telemetry.h" +#include "ImageLayers.h" #include "nsPNGDecoder.h" #include "nsGIFDecoder2.h" @@ -70,6 +71,7 @@ using namespace mozilla; using namespace mozilla::imagelib; +using namespace mozilla::layers; // a mask for flags that will affect the decoding #define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION) @@ -747,6 +749,42 @@ RasterImage::GetFrame(PRUint32 aWhichFrame, return rv; } + +NS_IMETHODIMP +RasterImage::GetImageContainer(LayerManager* aManager, + ImageContainer **_retval) +{ + if (mImageContainer && + (mImageContainer->Manager() == aManager || + (!mImageContainer->Manager() && + (mImageContainer->GetBackendType() == aManager->GetBackendType())))) { + *_retval = mImageContainer; + return NS_OK; + } + + CairoImage::Data cairoData; + nsRefPtr imageSurface; + GetFrame(FRAME_CURRENT, FLAG_SYNC_DECODE, getter_AddRefs(imageSurface)); + cairoData.mSurface = imageSurface; + GetWidth(&cairoData.mSize.width); + GetHeight(&cairoData.mSize.height); + + mImageContainer = aManager->CreateImageContainer(); + NS_ASSERTION(mImageContainer, "Failed to create ImageContainer!"); + + // Now create a CairoImage to display the surface. + layers::Image::Format cairoFormat = layers::Image::CAIRO_SURFACE; + nsRefPtr image = mImageContainer->CreateImage(&cairoFormat, 1); + NS_ASSERTION(image, "Failed to create Image"); + + NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format"); + static_cast(image.get())->SetData(cairoData); + mImageContainer->SetCurrentImage(image); + + *_retval = mImageContainer; + return NS_OK; +} + namespace { PRUint32 @@ -1011,6 +1049,8 @@ RasterImage::FrameUpdated(PRUint32 aFrameNum, nsIntRect &aUpdatedRect) NS_ABORT_IF_FALSE(frame, "Calling FrameUpdated on frame that doesn't exist!"); frame->ImageUpdated(aUpdatedRect); + // The image has changed, so we need to invalidate our cached ImageContainer. + mImageContainer = NULL; } nsresult diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 66b8e1f066a..e22a5b3caa2 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -145,6 +145,10 @@ class nsIInputStream; */ namespace mozilla { +namespace layers { +class LayerManager; +class ImageContainer; +} namespace imagelib { class imgDecodeWorker; @@ -175,6 +179,7 @@ public: NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated); NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque); NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM); + NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM); NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM); NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM); NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags); @@ -506,6 +511,9 @@ private: // data // This is currently only used for statistics PRInt32 mDecodeCount; + // Cached value for GetImageContainer. + nsRefPtr mImageContainer; + #ifdef DEBUG PRUint32 mFramesNotified; #endif diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index d12b9b89d11..9fe294caa50 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -46,6 +46,10 @@ class imgIDecoderObserver; namespace mozilla { +namespace layers { +class LayerManager; +class ImageContainer; +} namespace imagelib { class SVGDocumentWrapper; @@ -68,6 +72,7 @@ public: NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated); NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque); NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM); + NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM) { *_retval = NULL; return NS_OK; } NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM); NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM); NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index b34d4f0f023..5046a1e6ee0 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -550,7 +550,6 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage) */ nsPresContext *presContext = PresContext(); aImage->SetAnimationMode(presContext->ImageAnimationMode()); - mImageContainer = nsnull; if (IsPendingLoad(aRequest)) { // We don't care @@ -614,7 +613,6 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest, r.x, r.y, r.width, r.height); #endif - mImageContainer = nsnull; Invalidate(r); return NS_OK; @@ -628,7 +626,6 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsPresContext *presContext = PresContext(); nsIPresShell *presShell = presContext->GetPresShell(); NS_ASSERTION(presShell, "No PresShell."); - mImageContainer = nsnull; // Check what request type we're dealing with nsCOMPtr imageLoader = do_QueryInterface(mContent); @@ -695,7 +692,6 @@ nsImageFrame::FrameChanged(imgIContainer *aContainer, // Update border+content to account for image change Invalidate(r); - mImageContainer = nsnull; return NS_OK; } @@ -1213,7 +1209,10 @@ nsDisplayImage::GetImage() nsRefPtr nsDisplayImage::GetContainer(LayerManager* aManager) { - return static_cast(mFrame)->GetContainer(aManager, mImage); + ImageContainer* container; + nsresult rv = mImage->GetImageContainer(aManager, &container); + NS_ENSURE_SUCCESS(rv, NULL); + return container; } void @@ -1242,44 +1241,6 @@ nsDisplayImage::ConfigureLayer(ImageLayer* aLayer) aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight)); } -nsRefPtr -nsImageFrame::GetContainer(LayerManager* aManager, imgIContainer* aImage) -{ - if (mImageContainer && - (mImageContainer->Manager() == aManager || - (!mImageContainer->Manager() && - (mImageContainer->GetBackendType() == aManager->GetBackendType())))) { - return mImageContainer; - } - - if (aImage->GetType() != imgIContainer::TYPE_RASTER) { - return nsnull; - } - - CairoImage::Data cairoData; - nsRefPtr imageSurface; - aImage->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE, - getter_AddRefs(imageSurface)); - cairoData.mSurface = imageSurface; - aImage->GetWidth(&cairoData.mSize.width); - aImage->GetHeight(&cairoData.mSize.height); - - mImageContainer = aManager->CreateImageContainer(); - NS_ASSERTION(mImageContainer, "Failed to create ImageContainer!"); - - // Now create a CairoImage to display the surface. - Image::Format cairoFormat = Image::CAIRO_SURFACE; - nsRefPtr image = mImageContainer->CreateImage(&cairoFormat, 1); - NS_ASSERTION(image, "Failed to create Image"); - - NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format"); - static_cast(image.get())->SetData(cairoData); - mImageContainer->SetCurrentImage(image); - - return mImageContainer; -} - void nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect, imgIContainer* aImage, diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 815207a84e8..b6bc5c63e79 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -187,9 +187,6 @@ public: virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, InlineMinWidthData *aData); - nsRefPtr GetContainer(LayerManager* aManager, - imgIContainer* aImage); - void DisconnectMap(); protected: virtual ~nsImageFrame(); @@ -307,8 +304,6 @@ private: static nsIIOService* sIOService; - nsRefPtr mImageContainer; - /* loading / broken image icon support */ // XXXbz this should be handled by the prescontext, I think; that