From e40db04549919c1cafec761da8ab1196a779f173 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Mon, 28 Jul 2014 14:27:40 -0700 Subject: [PATCH] Bug 1034345 (Part 4) - Implement OptimalImageSizeForDest for other image types. r=tn --HG-- extra : rebase_source : 3237d5ec3e196ec674d9ab0e67b65b867f458251 --- image/src/ClippedImage.cpp | 41 +++++++++++++++++++++++++++++++++++++ image/src/ClippedImage.h | 4 ++++ image/src/DynamicImage.cpp | 7 +++++++ image/src/ImageWrapper.cpp | 7 +++++++ image/src/OrientedImage.cpp | 17 +++++++++++++++ image/src/OrientedImage.h | 4 ++++ 6 files changed, 80 insertions(+) diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp index 940e28cd8c1a..c840473fb9a0 100644 --- a/image/src/ClippedImage.cpp +++ b/image/src/ClippedImage.cpp @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + #include "gfxDrawable.h" #include "gfxPlatform.h" #include "gfxUtils.h" @@ -19,6 +21,7 @@ namespace mozilla { using namespace gfx; using layers::LayerManager; using layers::ImageContainer; +using std::modf; namespace image { @@ -424,6 +427,44 @@ ClippedImage::GetOrientation() return InnerImage()->GetOrientation(); } +nsIntSize +ClippedImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, + GraphicsFilter aFilter, uint32_t aFlags) +{ + if (!ShouldClip()) { + return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); + } + + int32_t imgWidth, imgHeight; + if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && + NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { + // To avoid ugly sampling artifacts, ClippedImage needs the image size to + // be chosen such that the clipping region lies on pixel boundaries. + + // First, we select a scale that's good for ClippedImage. An integer multiple + // of the size of the clipping region is always fine. + nsIntSize scale(ceil(aDest.width / mClip.width), + ceil(aDest.height / mClip.height)); + + // Determine the size we'd prefer to render the inner image at, and ask the + // inner image what size we should actually use. + gfxSize desiredSize(imgWidth * scale.width, imgHeight * scale.height); + nsIntSize innerDesiredSize = + InnerImage()->OptimalImageSizeForDest(desiredSize, aWhichFrame, + aFilter, aFlags); + + // To get our final result, we take the inner image's desired size and + // determine how large the clipped region would be at that scale. (Again, we + // ensure an integer multiple of the size of the clipping region.) + nsIntSize finalScale(ceil(double(innerDesiredSize.width) / imgWidth), + ceil(double(innerDesiredSize.height) / imgHeight)); + return mClip.Size() * finalScale; + } else { + MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); + return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); + } +} + NS_IMETHODIMP_(nsIntRect) ClippedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) { diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h index 1e92dab60e36..4b03b233bf2b 100644 --- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -53,6 +53,10 @@ public: NS_IMETHOD RequestDiscard() MOZ_OVERRIDE; NS_IMETHOD_(Orientation) GetOrientation() MOZ_OVERRIDE; NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE; + nsIntSize OptimalImageSizeForDest(const gfxSize& aDest, + uint32_t aWhichFrame, + GraphicsFilter aFilter, + uint32_t aFlags) MOZ_OVERRIDE; protected: ClippedImage(Image* aImage, nsIntRect aClip); diff --git a/image/src/DynamicImage.cpp b/image/src/DynamicImage.cpp index 23744f1b9427..86e1eda84192 100644 --- a/image/src/DynamicImage.cpp +++ b/image/src/DynamicImage.cpp @@ -338,6 +338,13 @@ NS_IMETHODIMP_(void) DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime) { } +nsIntSize +DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, GraphicsFilter aFilter, uint32_t aFlags) +{ + gfxIntSize size(mDrawable->Size()); + return nsIntSize(size.width, size.height); +} + NS_IMETHODIMP_(nsIntRect) DynamicImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) { diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index 07463089bf46..aff2d933e87a 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -318,6 +318,13 @@ ImageWrapper::SetAnimationStartTime(const TimeStamp& aTime) mInnerImage->SetAnimationStartTime(aTime); } +nsIntSize +ImageWrapper::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, + GraphicsFilter aFilter, uint32_t aFlags) +{ + return mInnerImage->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); +} + NS_IMETHODIMP_(nsIntRect) ImageWrapper::GetImageSpaceInvalidationRect(const nsIntRect& aRect) { diff --git a/image/src/OrientedImage.cpp b/image/src/OrientedImage.cpp index 9f697909e52e..86ecfaa7a4fa 100644 --- a/image/src/OrientedImage.cpp +++ b/image/src/OrientedImage.cpp @@ -251,6 +251,23 @@ OrientedImage::Draw(gfxContext* aContext, aWhichFrame, aFlags); } +nsIntSize +OrientedImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame, + GraphicsFilter aFilter, uint32_t aFlags) +{ + if (!mOrientation.SwapsWidthAndHeight()) { + return InnerImage()->OptimalImageSizeForDest(aDest, aWhichFrame, aFilter, aFlags); + } + + // Swap the size for the calculation, then swap it back for the caller. + gfxSize destSize(aDest.height, aDest.width); + nsIntSize innerImageSize(InnerImage()->OptimalImageSizeForDest(destSize, + aWhichFrame, + aFilter, + aFlags)); + return nsIntSize(innerImageSize.height, innerImageSize.width); +} + NS_IMETHODIMP_(nsIntRect) OrientedImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) { diff --git a/image/src/OrientedImage.h b/image/src/OrientedImage.h index 731e1abf4849..880bf446ae03 100644 --- a/image/src/OrientedImage.h +++ b/image/src/OrientedImage.h @@ -48,6 +48,10 @@ public: uint32_t aWhichFrame, uint32_t aFlags) MOZ_OVERRIDE; NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect) MOZ_OVERRIDE; + nsIntSize OptimalImageSizeForDest(const gfxSize& aDest, + uint32_t aWhichFrame, + GraphicsFilter aFilter, + uint32_t aFlags) MOZ_OVERRIDE; protected: OrientedImage(Image* aImage, Orientation aOrientation)