From ee7a3a3249eeae78047636662f45d38af9d52b1d Mon Sep 17 00:00:00 2001 From: Ali Juma Date: Tue, 17 Apr 2012 18:04:15 -0400 Subject: [PATCH] Bug 733941 - Let callers of imgIContainer::draw choose to clamp instead of tile. r=roc a=blocking-fennec --- gfx/thebes/gfxUtils.cpp | 6 ++++-- gfx/thebes/gfxUtils.h | 4 +++- image/public/imgIContainer.idl | 10 ++++++++-- image/src/RasterImage.cpp | 2 +- image/src/imgFrame.cpp | 8 +++++--- image/src/imgFrame.h | 4 +++- layout/base/nsLayoutUtils.cpp | 3 +++ 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index df36d041eaa..75b8b4c820d 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -421,9 +421,11 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext, const gfxRect& aImageRect, const gfxRect& aFill, const gfxImageSurface::gfxImageFormat aFormat, - const gfxPattern::GraphicsFilter& aFilter) + const gfxPattern::GraphicsFilter& aFilter, + PRUint32 aImageFlags) { - bool doTile = !aImageRect.Contains(aSourceRect); + bool doTile = !aImageRect.Contains(aSourceRect) && + !(aImageFlags & imgIContainer::FLAG_CLAMP); nsRefPtr currentTarget = aContext->CurrentSurface(); gfxMatrix deviceSpaceToImageSpace = diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h index 01279e69930..56ccfe6d4c2 100644 --- a/gfx/thebes/gfxUtils.h +++ b/gfx/thebes/gfxUtils.h @@ -43,6 +43,7 @@ #include "gfxImageSurface.h" #include "ImageLayers.h" #include "mozilla/gfx/2D.h" +#include "imgIContainer.h" class gfxDrawable; class nsIntRegion; @@ -89,7 +90,8 @@ public: const gfxRect& aImageRect, const gfxRect& aFill, const gfxImageSurface::gfxImageFormat aFormat, - const gfxPattern::GraphicsFilter& aFilter); + const gfxPattern::GraphicsFilter& aFilter, + PRUint32 aImageFlags = imgIContainer::FLAG_NONE); /** * Clip aContext to the region aRegion. diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 14d22f2c554..06b89e58c70 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -93,7 +93,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, uuid(8bf87433-be67-413b-9497-00071c5002bd)] +[scriptable, uuid(ead94080-cfd6-4a3e-8353-bd45333061d2)] interface imgIContainer : nsISupports { /** @@ -156,12 +156,16 @@ interface imgIContainer : nsISupports * FLAG_DECODE_NO_COLORSPACE_CONVERSION: Do not do any colorspace conversion; * ignore any embedded profiles, and don't convert to any particular destination * space. + * + * FLAG_CLAMP: Extend the image to the fill area by clamping image sample + * coordinates instead of by tiling. This only affects 'draw'. */ const long FLAG_NONE = 0x0; const long FLAG_SYNC_DECODE = 0x1; const long FLAG_DECODE_NO_PREMULTIPLY_ALPHA = 0x2; const long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x4; + const long FLAG_CLAMP = 0x8; /** * Constants for specifying various "special" frames. @@ -222,7 +226,9 @@ interface imgIContainer : nsISupports * @param aFilter The filter to be used if we're scaling the image. * @param aUserSpaceToImageSpace The transformation from user space (e.g., * appunits) to image space. - * @param aFill The area in the context to draw pixels to. Image will be + * @param aFill The area in the context to draw pixels to. When aFlags includes + * FLAG_CLAMP, the image will be extended to this area by clampling + * image sample coordinates. Otherwise, the image will be * automatically tiled as necessary. * @param aSubimage The area of the image, in pixels, that we are allowed to * sample from. diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 78266ebaa62..aba67dc2dff 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2634,7 +2634,7 @@ RasterImage::Draw(gfxContext *aContext, mSize.width - framerect.XMost(), mSize.height - framerect.YMost()); - frame->Draw(aContext, aFilter, aUserSpaceToImageSpace, aFill, padding, aSubimage); + frame->Draw(aContext, aFilter, aUserSpaceToImageSpace, aFill, padding, aSubimage, aFlags); if (mDecoded && !mDrawStartTime.IsNull()) { TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime; diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index 4a1ea12d97f..65118033691 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -466,7 +466,8 @@ imgFrame::SurfaceForDrawing(bool aDoPadding, void imgFrame::Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill, - const nsIntMargin &aPadding, const nsIntRect &aSubimage) + const nsIntMargin &aPadding, const nsIntRect &aSubimage, + PRUint32 aImageFlags) { SAMPLE_LABEL("image", "imgFrame::Draw"); NS_ASSERTION(!aFill.IsEmpty(), "zero dest size --- fix caller"); @@ -491,7 +492,8 @@ void imgFrame::Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(), "We must be allowed to sample *some* source pixels!"); - bool doTile = !imageRect.Contains(sourceRect); + bool doTile = !imageRect.Contains(sourceRect) && + !(aImageFlags & imgIContainer::FLAG_CLAMP); SurfaceWithFormat surfaceResult = SurfaceForDrawing(doPadding, doPartialDecode, doTile, aPadding, userSpaceToImageSpace, fill, subimage, sourceRect, @@ -501,7 +503,7 @@ void imgFrame::Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable, userSpaceToImageSpace, subimage, sourceRect, imageRect, fill, - surfaceResult.mFormat, aFilter); + surfaceResult.mFormat, aFilter, aImageFlags); } } diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index 33370ac470f..14c9e41797a 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -54,6 +54,7 @@ #include "gfxQuartzImageSurface.h" #endif #include "nsAutoPtr.h" +#include "imgIContainer.h" class imgFrame { @@ -66,7 +67,8 @@ public: void Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill, - const nsIntMargin &aPadding, const nsIntRect &aSubimage); + const nsIntMargin &aPadding, const nsIntRect &aSubimage, + PRUint32 aImageFlags = imgIContainer::FLAG_NONE); nsresult Extract(const nsIntRect& aRegion, imgFrame** aResult); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1bdc4204336..766d91ca012 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3554,6 +3554,9 @@ DrawImageInternal(nsRenderingContext* aRenderingContext, const nsIntSize& aImageSize, PRUint32 aImageFlags) { + if (aDest.Contains(aFill)) { + aImageFlags |= imgIContainer::FLAG_CLAMP; + } PRInt32 appUnitsPerDevPixel = aRenderingContext->AppUnitsPerDevPixel(); gfxContext* ctx = aRenderingContext->ThebesContext();