From 4cc0ce1c76f82bf8d1f62876f736e93dcf7becc6 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Thu, 26 Jun 2014 16:02:04 -0700 Subject: [PATCH] Bug 997604 - Add invalidation rect support to ImageWrappers, and use it in nsImageFrame. r=tn,sr=bz --HG-- extra : rebase_source : a0b0f79c2bfab604f13e1098d09b2ec61e578a37 --- image/public/imgIContainer.idl | 13 ++++++++++++- image/src/ClippedImage.cpp | 13 +++++++++++++ image/src/ClippedImage.h | 1 + image/src/ImageWrapper.cpp | 6 ++++++ image/src/OrientedImage.cpp | 27 +++++++++++++++++++++++++++ image/src/OrientedImage.h | 1 + image/src/RasterImage.cpp | 6 ++++++ image/src/VectorImage.cpp | 6 ++++++ layout/generic/nsImageFrame.cpp | 9 +++++---- 9 files changed, 77 insertions(+), 5 deletions(-) diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 5d541c66760..829c6572c74 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -44,6 +44,7 @@ struct Orientation; [ref] native gfxRect(gfxRect); native gfxGraphicsFilter(GraphicsFilter); [ref] native nsIntRect(nsIntRect); +native nsIntRectByVal(nsIntRect); [ref] native nsIntSize(nsIntSize); native nsSize(nsSize); [ptr] native nsIFrame(nsIFrame); @@ -62,7 +63,7 @@ native TempRefSourceSurface(mozilla::TemporaryRef); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(503a830c-734d-4362-91f6-73f83ac59646)] +[scriptable, builtinclass, uuid(48590bac-a5b3-45b1-bd4e-57ab938eab9e)] interface imgIContainer : nsISupports { /** @@ -348,4 +349,14 @@ interface imgIContainer : nsISupports * resetAnimation(), or requestRefresh() is called for the first time. */ [notxpcom] void setAnimationStartTime([const] in TimeStamp aTime); + + /* + * Given an invalidation rect in the coordinate system used by the decoder, + * returns an invalidation rect in image space. + * + * This is the identity transformation in most cases, but the result can + * differ if the image is wrapped by an ImageWrapper that changes its size + * or orientation. + */ + [notxpcom] nsIntRectByVal getImageSpaceInvalidationRect([const] in nsIntRect aRect); }; diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp index 8f07924d583..339a0356766 100644 --- a/image/src/ClippedImage.cpp +++ b/image/src/ClippedImage.cpp @@ -424,5 +424,18 @@ ClippedImage::GetOrientation() return InnerImage()->GetOrientation(); } +NS_IMETHODIMP_(nsIntRect) +ClippedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) +{ + if (!ShouldClip()) { + return InnerImage()->GetImageSpaceInvalidationRect(aRect); + } + + nsIntRect rect(InnerImage()->GetImageSpaceInvalidationRect(aRect)); + rect = rect.Intersect(mClip); + rect.MoveBy(-mClip.x, -mClip.y); + return rect; +} + } // namespace image } // namespace mozilla diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h index bf915ba84af..76fbf6f89fd 100644 --- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -52,6 +52,7 @@ public: uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD RequestDiscard() MOZ_OVERRIDE; NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE; + NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE; protected: ClippedImage(Image* aImage, nsIntRect aClip); diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index 8e585bbb565..17b4729ec5a 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -317,5 +317,11 @@ ImageWrapper::SetAnimationStartTime(const mozilla::TimeStamp& aTime) mInnerImage->SetAnimationStartTime(aTime); } +NS_IMETHODIMP_(nsIntRect) +ImageWrapper::GetImageSpaceInvalidationRect(const nsIntRect& aRect) +{ + return mInnerImage->GetImageSpaceInvalidationRect(aRect); +} + } // namespace image } // namespace mozilla diff --git a/image/src/OrientedImage.cpp b/image/src/OrientedImage.cpp index 08f95bddcb4..2b9cb696cce 100644 --- a/image/src/OrientedImage.cpp +++ b/image/src/OrientedImage.cpp @@ -250,5 +250,32 @@ OrientedImage::Draw(gfxContext* aContext, aWhichFrame, aFlags); } +NS_IMETHODIMP_(nsIntRect) +OrientedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) +{ + nsIntRect rect(InnerImage()->GetImageSpaceInvalidationRect(aRect)); + + if (mOrientation.IsIdentity()) { + return rect; + } + + int32_t width, height; + nsresult rv = InnerImage()->GetWidth(&width); + rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&height); + if (NS_FAILED(rv)) { + // Fall back to identity if the width and height aren't available. + return rect; + } + + // Transform the invalidation rect into the correct orientation. + gfxMatrix matrix(OrientationMatrix(nsIntSize(width, height)).Invert()); + gfxRect invalidRect(matrix.TransformBounds(gfxRect(rect.x, rect.y, + rect.width, rect.height))); + invalidRect.RoundOut(); + + return nsIntRect(invalidRect.x, invalidRect.y, + invalidRect.width, invalidRect.height); +} + } // namespace image } // namespace mozilla diff --git a/image/src/OrientedImage.h b/image/src/OrientedImage.h index 23545973ff9..dd564d3489f 100644 --- a/image/src/OrientedImage.h +++ b/image/src/OrientedImage.h @@ -47,6 +47,7 @@ public: const SVGImageContext* aSVGContext, uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; + NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE; protected: OrientedImage(Image* aImage, Orientation aOrientation) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 8cf4e2fc75a..025d597c2b2 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -1601,6 +1601,12 @@ RasterImage::SetLoopCount(int32_t aLoopCount) } } +NS_IMETHODIMP_(nsIntRect) +RasterImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) +{ + return aRect; +} + nsresult RasterImage::AddSourceData(const char *aBuffer, uint32_t aCount) { diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 07d5bac89a5..36bbba90719 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -570,6 +570,12 @@ VectorImage::SendInvalidationNotifications() } } +NS_IMETHODIMP_(nsIntRect) +VectorImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) +{ + return aRect; +} + //****************************************************************************** /* readonly attribute int32_t height; */ NS_IMETHODIMP diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 1593e358412..8204cfa5987 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -216,8 +216,6 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot) nsSplittableFrame::DestroyFrom(aDestructRoot); } - - void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, @@ -604,16 +602,19 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest, return NS_OK; } + nsIntRect rect = mImage ? mImage->GetImageSpaceInvalidationRect(*aRect) + : *aRect; + #ifdef DEBUG_decode printf("Source rect (%d,%d,%d,%d)\n", aRect->x, aRect->y, aRect->width, aRect->height); #endif - if (aRect->IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) { + if (rect.IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) { InvalidateFrame(nsDisplayItem::TYPE_IMAGE); InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK); } else { - nsRect invalid = SourceRectToDest(*aRect); + nsRect invalid = SourceRectToDest(rect); InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE); InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK); }