Skip to content

Commit

Permalink
Bug 975900 - Convert imgUtils to Moz2D (from gfxASurface to SourceSur…
Browse files Browse the repository at this point in the history
…face). r=mattwoodrow

--HG--
extra : rebase_source : aaa405346704d67005a4453de34cf67d68e2a7c6
  • Loading branch information
jwatt committed Feb 25, 2014
1 parent 80905c8 commit e2a8d24
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 131 deletions.
12 changes: 12 additions & 0 deletions gfx/thebes/gfxImageSurface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,18 @@ gfxImageSurface::CopyTo(SourceSurface *aSurface) {
return true;
}

TemporaryRef<DataSourceSurface>
gfxImageSurface::CopyToB8G8R8A8DataSourceSurface()
{
RefPtr<DataSourceSurface> dataSurface =
Factory::CreateDataSourceSurface(IntSize(GetSize().width, GetSize().height),
SurfaceFormat::B8G8R8A8);
if (dataSurface) {
CopyTo(dataSurface);
}
return dataSurface.forget();
}

already_AddRefed<gfxSubimageSurface>
gfxImageSurface::GetSubimage(const gfxRect& aRect)
{
Expand Down
7 changes: 7 additions & 0 deletions gfx/thebes/gfxImageSurface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -17,6 +18,7 @@ class gfxSubimageSurface;

namespace mozilla {
namespace gfx {
class DataSourceSurface;
class SourceSurface;
}
}
Expand Down Expand Up @@ -108,6 +110,11 @@ class gfxImageSurface : public gfxASurface {
*/
bool CopyTo (mozilla::gfx::SourceSurface *aSurface);

/**
* Copy to a Moz2D DataSourceSurface.
*/
mozilla::TemporaryRef<mozilla::gfx::DataSourceSurface> CopyToB8G8R8A8DataSourceSurface();

/* return new Subimage with pointing to original image starting from aRect.pos
* and size of aRect.size. New subimage keeping current image reference
*/
Expand Down
225 changes: 110 additions & 115 deletions image/src/imgTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -98,20 +97,77 @@ NS_IMETHODIMP imgTools::DecodeImage(nsIInputStream* aInStr,
return NS_OK;
}

static TemporaryRef<SourceSurface>
GetFirstImageFrame(imgIContainer *aContainer)
{
nsRefPtr<gfxASurface> frame =
aContainer->GetFrame(imgIContainer::FRAME_FIRST,
imgIContainer::FLAG_SYNC_DECODE);
NS_ENSURE_TRUE(frame, nullptr);

nsRefPtr<gfxImageSurface> 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<imgIEncoder> 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<gfxImageSurface> frame;
rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<SourceSurface> frame = GetFirstImageFrame(aContainer);
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);

RefPtr<DataSourceSurface> 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,
Expand All @@ -130,11 +186,11 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
}

// Use frame 0 from the image container.
nsRefPtr<gfxImageSurface> frame;
nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<SourceSurface> 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.
Expand All @@ -144,38 +200,27 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
aScaledHeight = frameHeight;
}

// Create a temporary image surface
nsRefPtr<gfxImageSurface> dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight),
gfxImageFormat::ARGB32);
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(dest, IntSize(aScaledWidth, aScaledHeight));
RefPtr<SourceSurface> 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<gfxPattern> pat = new gfxPattern(frame);
pat->SetExtend(gfxPattern::EXTEND_PAD);
ctx.SetPattern(pat);
ctx.Paint();
}

RefPtr<DataSourceSurface> 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<DrawTarget> 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,
Expand All @@ -200,11 +245,11 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer,
}

// Use frame 0 from the image container.
nsRefPtr<gfxImageSurface> frame;
nsresult rv = GetFirstImageFrame(aContainer, getter_AddRefs(frame));
NS_ENSURE_SUCCESS(rv, rv);
RefPtr<SourceSurface> 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.
Expand All @@ -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<gfxImageSurface> 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<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
if (!encoder)
return NS_IMAGELIB_ERROR_NO_ENCODER;

bitmapData = aSurface->Data();
if (!bitmapData)
RefPtr<DataSourceSurface> 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<gfxASurface> surface =
aContainer->GetFrame(imgIContainer::FRAME_FIRST,
imgIContainer::FLAG_SYNC_DECODE);
NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE);

nsRefPtr<gfxImageSurface> 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<DrawTarget> 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,
Expand Down
21 changes: 5 additions & 16 deletions image/src/imgTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
};

0 comments on commit e2a8d24

Please sign in to comment.