From e2a8d249eb79899ebe69f8ddb126aa98d20e5db3 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Tue, 25 Feb 2014 00:51:45 +0000 Subject: [PATCH] Bug 975900 - Convert imgUtils to Moz2D (from gfxASurface to SourceSurface). r=mattwoodrow --HG-- extra : rebase_source : aaa405346704d67005a4453de34cf67d68e2a7c6 --- gfx/thebes/gfxImageSurface.cpp | 12 ++ gfx/thebes/gfxImageSurface.h | 7 + image/src/imgTools.cpp | 225 ++++++++++++++++----------------- image/src/imgTools.h | 21 +-- 4 files changed, 134 insertions(+), 131 deletions(-) diff --git a/gfx/thebes/gfxImageSurface.cpp b/gfx/thebes/gfxImageSurface.cpp index 7e688abbf8f693..600962d9f2bee0 100644 --- a/gfx/thebes/gfxImageSurface.cpp +++ b/gfx/thebes/gfxImageSurface.cpp @@ -317,6 +317,18 @@ gfxImageSurface::CopyTo(SourceSurface *aSurface) { return true; } +TemporaryRef +gfxImageSurface::CopyToB8G8R8A8DataSourceSurface() +{ + RefPtr dataSurface = + Factory::CreateDataSourceSurface(IntSize(GetSize().width, GetSize().height), + SurfaceFormat::B8G8R8A8); + if (dataSurface) { + CopyTo(dataSurface); + } + return dataSurface.forget(); +} + already_AddRefed gfxImageSurface::GetSubimage(const gfxRect& aRect) { diff --git a/gfx/thebes/gfxImageSurface.h b/gfx/thebes/gfxImageSurface.h index 10c1718cd6d557..983cf6754327c3 100644 --- a/gfx/thebes/gfxImageSurface.h +++ b/gfx/thebes/gfxImageSurface.h @@ -7,6 +7,7 @@ #define GFX_IMAGESURFACE_H #include "mozilla/MemoryReporting.h" +#include "mozilla/RefPtr.h" #include "gfxASurface.h" #include "nsAutoPtr.h" #include "nsSize.h" @@ -17,6 +18,7 @@ class gfxSubimageSurface; namespace mozilla { namespace gfx { +class DataSourceSurface; class SourceSurface; } } @@ -108,6 +110,11 @@ class gfxImageSurface : public gfxASurface { */ bool CopyTo (mozilla::gfx::SourceSurface *aSurface); + /** + * Copy to a Moz2D DataSourceSurface. + */ + mozilla::TemporaryRef CopyToB8G8R8A8DataSourceSurface(); + /* return new Subimage with pointing to original image starting from aRect.pos * and size of aRect.size. New subimage keeping current image reference */ diff --git a/image/src/imgTools.cpp b/image/src/imgTools.cpp index b96b6bfa8d3512..a309c089b390d6 100644 --- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -6,6 +6,8 @@ #include "imgTools.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" #include "nsCOMPtr.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" @@ -14,10 +16,7 @@ #include "imgICache.h" #include "imgIContainer.h" #include "imgIEncoder.h" -#include "gfxContext.h" -#include "nsComponentManagerUtils.h" #include "nsStreamUtils.h" -#include "nsNetUtil.h" #include "nsContentUtils.h" #include "ImageFactory.h" #include "Image.h" @@ -98,20 +97,77 @@ NS_IMETHODIMP imgTools::DecodeImage(nsIInputStream* aInStr, return NS_OK; } +static TemporaryRef +GetFirstImageFrame(imgIContainer *aContainer) +{ + nsRefPtr frame = + aContainer->GetFrame(imgIContainer::FRAME_FIRST, + imgIContainer::FLAG_SYNC_DECODE); + NS_ENSURE_TRUE(frame, nullptr); + + nsRefPtr imageSurface = frame->CopyToARGB32ImageSurface(); + NS_ENSURE_TRUE(imageSurface, nullptr); + + return imageSurface->CopyToB8G8R8A8DataSourceSurface(); +} + +/** + * This takes a DataSourceSurface rather than a SourceSurface because some + * of the callers have a DataSourceSurface and we don't want to call + * GetDataSurface on such surfaces since that may incure a conversion to + * SurfaceType::DATA which we don't need. + */ +static nsresult EncodeImageData(DataSourceSurface* aDataSurface, + const nsACString& aMimeType, + const nsAString& aOutputOptions, + nsIInputStream **aStream) +{ + MOZ_ASSERT(aDataSurface->GetFormat() == SurfaceFormat::B8G8R8A8, + "We're assuming B8G8R8A8"); + + // Get an image encoder for the media type + nsAutoCString encoderCID( + NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType); + + nsCOMPtr encoder = do_CreateInstance(encoderCID.get()); + if (!encoder) + return NS_IMAGELIB_ERROR_NO_ENCODER; + + DataSourceSurface::MappedSurface map; + aDataSurface->Map(DataSourceSurface::MapType::READ, &map); + if (!map.mData) + return NS_ERROR_FAILURE; + + IntSize size = aDataSurface->GetSize(); + uint32_t dataLength = map.mStride * size.height; + + // Encode the bitmap + nsresult rv = encoder->InitFromData(map.mData, + dataLength, + size.width, + size.height, + map.mStride, + imgIEncoder::INPUT_FORMAT_HOSTARGB, + aOutputOptions); + + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(encoder, aStream); +} NS_IMETHODIMP imgTools::EncodeImage(imgIContainer *aContainer, const nsACString& aMimeType, const nsAString& aOutputOptions, nsIInputStream **aStream) { - nsresult rv; - // Use frame 0 from the image container. - nsRefPtr frame; - rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame)); - NS_ENSURE_SUCCESS(rv, rv); + RefPtr frame = GetFirstImageFrame(aContainer); + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); + + RefPtr dataSurface = frame->GetDataSurface(); + NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); - return EncodeImageData(frame, aMimeType, aOutputOptions, aStream); + return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream); } NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, @@ -130,11 +186,11 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, } // Use frame 0 from the image container. - nsRefPtr frame; - nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame)); - NS_ENSURE_SUCCESS(rv, rv); + RefPtr frame = GetFirstImageFrame(aContainer); + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - int32_t frameWidth = frame->Width(), frameHeight = frame->Height(); + int32_t frameWidth = frame->GetSize().width; + int32_t frameHeight = frame->GetSize().height; // If the given width or height is zero we'll replace it with the image's // original dimensions. @@ -144,38 +200,27 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, aScaledHeight = frameHeight; } - // Create a temporary image surface - nsRefPtr dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight), - gfxImageFormat::ARGB32); - if (gfxPlatform::GetPlatform()->SupportsAzureContent()) { - RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(dest, IntSize(aScaledWidth, aScaledHeight)); - RefPtr source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, frame); - - dt->DrawSurface(source, - Rect(0, 0, aScaledWidth, aScaledHeight), - Rect(0, 0, frameWidth, frameHeight), - DrawSurfaceOptions(), - DrawOptions(1.0f, CompositionOp::OP_SOURCE)); - } else { - gfxContext ctx(dest); - - // Set scaling - gfxFloat sw = (double) aScaledWidth / frameWidth; - gfxFloat sh = (double) aScaledHeight / frameHeight; - ctx.Scale(sw, sh); - - // Paint a scaled image - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - - nsRefPtr pat = new gfxPattern(frame); - pat->SetExtend(gfxPattern::EXTEND_PAD); - ctx.SetPattern(pat); - ctx.Paint(); - } - + RefPtr dataSurface = + Factory::CreateDataSourceSurface(IntSize(aScaledWidth, aScaledHeight), + SurfaceFormat::B8G8R8A8); + DataSourceSurface::MappedSurface map; + dataSurface->Map(DataSourceSurface::MapType::WRITE, &map); + if (!map.mData) + return NS_ERROR_FAILURE; - return EncodeImageData(dest, aMimeType, aOutputOptions, aStream); + RefPtr dt = + Factory::CreateDrawTargetForData(BackendType::CAIRO, + map.mData, + dataSurface->GetSize(), + map.mStride, + SurfaceFormat::B8G8R8A8); + dt->DrawSurface(frame, + Rect(0, 0, aScaledWidth, aScaledHeight), + Rect(0, 0, frameWidth, frameHeight), + DrawSurfaceOptions(), + DrawOptions(1.0f, CompositionOp::OP_SOURCE)); + + return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream); } NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer, @@ -200,11 +245,11 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer, } // Use frame 0 from the image container. - nsRefPtr frame; - nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame)); - NS_ENSURE_SUCCESS(rv, rv); + RefPtr frame = GetFirstImageFrame(aContainer); + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - int32_t frameWidth = frame->Width(), frameHeight = frame->Height(); + int32_t frameWidth = frame->GetSize().width; + int32_t frameHeight = frame->GetSize().height; // If the given width or height is zero we'll replace it with the image's // original dimensions. @@ -218,75 +263,25 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer, NS_ENSURE_ARG(frameWidth >= aOffsetX + aWidth && frameHeight >= aOffsetY + aHeight); - // Create a temporary image surface - nsRefPtr dest = new gfxImageSurface(gfxIntSize(aWidth, aHeight), - gfxImageFormat::ARGB32); - gfxContext ctx(dest); - - // Set translate - ctx.Translate(gfxPoint(-aOffsetX, -aOffsetY)); - - // Paint a scaled image - ctx.SetOperator(gfxContext::OPERATOR_SOURCE); - ctx.SetSource(frame); - ctx.Paint(); - - return EncodeImageData(dest, aMimeType, aOutputOptions, aStream); -} - -NS_IMETHODIMP imgTools::EncodeImageData(gfxImageSurface *aSurface, - const nsACString& aMimeType, - const nsAString& aOutputOptions, - nsIInputStream **aStream) -{ - uint8_t *bitmapData; - uint32_t bitmapDataLength, strideSize; - - // Get an image encoder for the media type - nsAutoCString encoderCID( - NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType); - - nsCOMPtr encoder = do_CreateInstance(encoderCID.get()); - if (!encoder) - return NS_IMAGELIB_ERROR_NO_ENCODER; - - bitmapData = aSurface->Data(); - if (!bitmapData) + RefPtr dataSurface = + Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight), + SurfaceFormat::B8G8R8A8); + DataSourceSurface::MappedSurface map; + dataSurface->Map(DataSourceSurface::MapType::WRITE, &map); + if (!map.mData) return NS_ERROR_FAILURE; - strideSize = aSurface->Stride(); - - int32_t width = aSurface->Width(), height = aSurface->Height(); - bitmapDataLength = height * strideSize; - - // Encode the bitmap - nsresult rv = encoder->InitFromData(bitmapData, - bitmapDataLength, - width, - height, - strideSize, - imgIEncoder::INPUT_FORMAT_HOSTARGB, - aOutputOptions); - - NS_ENSURE_SUCCESS(rv, rv); - - return CallQueryInterface(encoder, aStream); -} - -NS_IMETHODIMP imgTools::GetFirstImageFrame(imgIContainer *aContainer, - gfxImageSurface **aSurface) -{ - nsRefPtr surface = - aContainer->GetFrame(imgIContainer::FRAME_FIRST, - imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE); - - nsRefPtr frame(surface->CopyToARGB32ImageSurface()); - NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); - NS_ENSURE_TRUE(frame->Width() && frame->Height(), NS_ERROR_FAILURE); - - frame.forget(aSurface); - return NS_OK; + RefPtr dt = + Factory::CreateDrawTargetForData(BackendType::CAIRO, + map.mData, + dataSurface->GetSize(), + map.mStride, + SurfaceFormat::B8G8R8A8); + dt->CopySurface(frame, + IntRect(aOffsetX, aOffsetY, aWidth, aHeight), + IntPoint(0, 0)); + + return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream); } NS_IMETHODIMP imgTools::CreateScriptedObserver(imgIScriptedNotificationObserver* aInner, diff --git a/image/src/imgTools.h b/image/src/imgTools.h index 196927a145cb79..a6014aedf90faf 100644 --- a/image/src/imgTools.h +++ b/image/src/imgTools.h @@ -6,14 +6,12 @@ #include "imgITools.h" -class gfxImageSurface; - #define NS_IMGTOOLS_CID \ -{ /* 4c2383a4-931c-484d-8c4a-973590f66e3f */ \ - 0x4c2383a4, \ - 0x931c, \ - 0x484d, \ - {0x8c, 0x4a, 0x97, 0x35, 0x90, 0xf6, 0x6e, 0x3f} \ +{ /* 3d8fa16d-c9e1-4b50-bdef-2c7ae249967a */ \ + 0x3d8fa16d, \ + 0xc9e1, \ + 0x4b50, \ + {0xbd, 0xef, 0x2c, 0x7a, 0xe2, 0x49, 0x96, 0x7a} \ } class imgTools : public imgITools @@ -24,13 +22,4 @@ class imgTools : public imgITools imgTools(); virtual ~imgTools(); - -private: - NS_IMETHODIMP EncodeImageData(gfxImageSurface *aSurface, - const nsACString& aMimeType, - const nsAString& aOutputOptions, - nsIInputStream **aStream); - - NS_IMETHODIMP GetFirstImageFrame(imgIContainer *aContainer, - gfxImageSurface **aSurface); };