--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -2215,19 +2215,28 @@ nsCanvasRenderingContext2D::CairoSurface
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (widthOut)
*widthOut = imgWidth;
if (heightOut)
*heightOut = imgHeight;
- nsRefPtr<gfxASurface> gfxsurf;
- rv = img->GetSurface(getter_AddRefs(gfxsurf));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsRefPtr<gfxPattern> gfxpattern;
+ img->GetPattern(getter_AddRefs(gfxpattern));
+ nsRefPtr<gfxASurface> gfxsurf = gfxpattern->GetSurface();
+
+ if (!gfxsurf) {
+ gfxsurf = new gfxImageSurface (gfxIntSize(imgWidth, imgHeight), gfxASurface::ImageFormatARGB32);
+ nsRefPtr<gfxContext> ctx = new gfxContext(gfxsurf);
+
+ ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+ ctx->SetPattern(gfxpattern);
+ ctx->Paint();
+ }
*aCairoSurface = gfxsurf->CairoSurface();
cairo_surface_reference (*aCairoSurface);
*imgData = nsnull;
return NS_OK;
}
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -169,12 +169,11 @@ INCLUDES += \
-I$(srcdir)/../../../xml/content/src \
-I$(srcdir)/../../../../dom \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../../layout/svg/base/src \
-I$(srcdir)/../../../../layout/style \
-I$(srcdir)/../../../events/src \
-I$(srcdir)/../../../html/content/src \
-I$(topsrcdir)/content/xbl/src \
- -I$(topsrcdir)/gfx/src/thebes \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -58,17 +58,17 @@
#include "nsIDocument.h"
#include "nsIFrame.h"
#include "gfxContext.h"
#include "nsSVGLengthList.h"
#include "nsIDOMSVGURIReference.h"
#include "nsImageLoadingContent.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
-#include "nsThebesImage.h"
+#include "nsIImage.h"
#include "nsSVGAnimatedPreserveAspectRatio.h"
#include "nsSVGPreserveAspectRatio.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsSVGMatrix.h"
#include "nsSVGFilterElement.h"
#if defined(XP_WIN)
// Prevent Windows redefining LoadImage
#undef LoadImage
@@ -5577,46 +5577,41 @@ nsSVGFEImageElement::Filter(nsSVGFilterI
nsCOMPtr<imgIContainer> imageContainer;
if (currentRequest)
currentRequest->GetImage(getter_AddRefs(imageContainer));
nsCOMPtr<gfxIImageFrame> currentFrame;
if (imageContainer)
imageContainer->GetCurrentFrame(getter_AddRefs(currentFrame));
- gfxASurface *thebesSurface = nsnull;
+ nsRefPtr<gfxPattern> thebesPattern = nsnull;
if (currentFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(currentFrame));
- nsThebesImage *thebesImage = nsnull;
- if (img)
- thebesImage = static_cast<nsThebesImage*>(img.get());
-
- if (thebesImage)
- thebesSurface = thebesImage->ThebesSurface();
+ img->GetPattern(getter_AddRefs(thebesPattern));
}
- if (thebesSurface) {
+ if (thebesPattern) {
PRInt32 x, y, nativeWidth, nativeHeight;
currentFrame->GetX(&x);
currentFrame->GetY(&y);
currentFrame->GetWidth(&nativeWidth);
currentFrame->GetHeight(&nativeHeight);
nsCOMPtr<nsIDOMSVGMatrix> trans;
trans = nsSVGUtils::GetViewBoxTransform(filterSubregion.width, filterSubregion.height,
x, y,
nativeWidth, nativeHeight,
mPreserveAspectRatio);
nsCOMPtr<nsIDOMSVGMatrix> xy, fini;
NS_NewSVGMatrix(getter_AddRefs(xy), 1, 0, 0, 1, filterSubregion.x, filterSubregion.y);
xy->Multiply(trans, getter_AddRefs(fini));
gfxContext ctx(targetSurface);
- nsSVGUtils::CompositeSurfaceMatrix(&ctx, thebesSurface, fini, 1.0);
+ nsSVGUtils::CompositePatternMatrix(&ctx, thebesPattern, fini, nativeWidth, nativeHeight, 1.0);
}
return NS_OK;
}
nsRect
nsSVGFEImageElement::ComputeTargetBBox(const nsTArray<nsRect>& aSourceBBoxes,
const nsSVGFilterInstance& aInstance)
--- a/gfx/public/nsIImage.h
+++ b/gfx/public/nsIImage.h
@@ -39,16 +39,17 @@
#define nsIImage_h___
#include "nsISupports.h"
#include "nsIRenderingContext.h"
#include "nsRect.h"
#include "gfxRect.h"
class gfxASurface;
+class gfxPattern;
class nsIDeviceContext;
struct nsColorMap
{
//I lifted this from the image lib. The difference is that
//this uses nscolor instead of NI_RGB. Multiple color pollution
//is a bad thing. MMP
@@ -208,17 +209,21 @@ public:
* @return a bitmap info structure for the Device Dependent Bits
*/
virtual void* GetBitInfo() = 0;
/**
* LockImagePixels
* Lock the image pixels so that we can access them directly,
- * with safely. May be a noop on some platforms.
+ * with safety. May be a noop on some platforms.
+ *
+ * If you want to be able to call GetSurface(), wrap the call in
+ * LockImagePixels()/UnlockImagePixels(). This also allows you to write to
+ * the surface returned by GetSurface().
*
* aMaskPixels = PR_TRUE for the mask, PR_FALSE for the image
*
* Must be balanced by a call to UnlockImagePixels().
*
* @update - sfraser 10/18/99
* @return error result
*/
@@ -234,24 +239,35 @@ public:
*
* @update - sfraser 10/18/99
* @return error result
*/
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels) = 0;
/**
* GetSurface
- * Return the Thebes gfxASurface in aSurface.
+ * Return the Thebes gfxASurface in aSurface, if there is one. Should be
+ * wrapped by LockImagePixels()/UnlockImagePixels().
*
* aSurface will be AddRef'd (as with most getters), so
* getter_AddRefs should be used.
*/
NS_IMETHOD GetSurface(gfxASurface **aSurface) = 0;
/**
+ * GetSurface
+ * Return the Thebes gfxPattern in aPattern. It is always possible to get a
+ * gfxPattern (unlike the gfxASurface from GetSurface()).
+ *
+ * aPattern will be AddRef'd (as with most getters), so
+ * getter_AddRefs should be used.
+ */
+ NS_IMETHOD GetPattern(gfxPattern **aPattern) = 0;
+
+ /**
* SetHasNoAlpha
*
* Hint to the image that all the pixels are fully opaque, even if
* the original format requested a 1-bit or 8-bit alpha mask
*/
virtual void SetHasNoAlpha() = 0;
};
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -254,34 +254,26 @@ nsThebesImage::Optimize(nsIDeviceContext
mSinglePixelColor = gfxRGBA
(firstPixel,
(mFormat == gfxImageSurface::ImageFormatRGB24 ?
gfxRGBA::PACKED_XRGB :
gfxRGBA::PACKED_ARGB_PREMULTIPLIED));
mSinglePixel = PR_TRUE;
- // XXX we can't do this until we either teach anyone
- // who calls GetSurface() about single-color stuff,
- // or until we make GetSurface() create a new temporary
- // surface to return (and that callers understand that
- // modifying that surface won't modify the image).
- // Current users are drag & drop and clipboard.
-#if 0
// blow away the older surfaces, to release data
mImageSurface = nsnull;
mOptSurface = nsnull;
#ifdef XP_WIN
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
-#endif
return NS_OK;
}
}
// if it's not RGB24/ARGB32, don't optimize, but we never hit this at the moment
}
// if we're being forced to use image surfaces due to
@@ -386,17 +378,25 @@ nsThebesImage::LockImagePixels(PRBool aM
return NS_ERROR_OUT_OF_MEMORY;
gfxContext context(mImageSurface);
context.SetOperator(gfxContext::OPERATOR_SOURCE);
if (mSinglePixel)
context.SetColor(mSinglePixelColor);
else
context.SetSource(mOptSurface);
context.Paint();
+
+#ifdef XP_WIN
+ mWinSurface = nsnull;
+#endif
+#ifdef XP_MACOSX
+ mQuartzSurface = nsnull;
+#endif
}
+
return NS_OK;
}
NS_IMETHODIMP
nsThebesImage::UnlockImagePixels(PRBool aMaskPixels)
{
if (aMaskPixels)
return NS_ERROR_NOT_IMPLEMENTED;
--- a/gfx/src/thebes/nsThebesImage.h
+++ b/gfx/src/thebes/nsThebesImage.h
@@ -39,16 +39,17 @@
#ifndef _NSTHEBESIMAGE_H_
#define _NSTHEBESIMAGE_H_
#include "nsIImage.h"
#include "gfxColor.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h"
+#include "gfxPattern.h"
#if defined(XP_WIN)
#include "gfxWindowsSurface.h"
#elif defined(XP_MACOSX)
#include "gfxQuartzImageSurface.h"
#endif
class nsThebesImage : public nsIImage
{
@@ -91,16 +92,32 @@ public:
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
NS_IMETHOD GetSurface(gfxASurface **aSurface) {
*aSurface = ThebesSurface();
NS_ADDREF(*aSurface);
return NS_OK;
}
+ NS_IMETHOD GetPattern(gfxPattern **aPattern) {
+ *aPattern = ThebesPattern();
+ NS_ADDREF(*aPattern);
+ return NS_OK;
+ }
+
+ gfxPattern* ThebesPattern() {
+ gfxPattern *pattern;
+ if (mSinglePixel)
+ pattern = new gfxPattern(mSinglePixelColor);
+ else
+ pattern = new gfxPattern(ThebesSurface());
+
+ return pattern;
+ }
+
gfxASurface* ThebesSurface() {
if (mOptSurface)
return mOptSurface;
#if defined(XP_WIN)
if (mWinSurface)
return mWinSurface;
#elif defined(XP_MACOSX)
if (mQuartzSurface)
--- a/gfx/thebes/public/gfxPattern.h
+++ b/gfx/thebes/public/gfxPattern.h
@@ -73,16 +73,27 @@ public:
EXTEND_REFLECT,
EXTEND_PAD
};
// none, repeat, reflect
void SetExtend(GraphicsExtend extend);
GraphicsExtend Extend() const;
+ enum GraphicsPatternType {
+ PATTERN_SOLID,
+ PATTERN_SURFACE,
+ PATTERN_LINEAR,
+ PATTERN_RADIAL
+ };
+
+ GraphicsPatternType GetType() const;
+
+ int CairoStatus();
+
void SetFilter(int filter);
int Filter() const;
/* returns TRUE if it succeeded */
PRBool GetSolidColor(gfxRGBA& aColor);
already_AddRefed<gfxASurface> GetSurface();
--- a/gfx/thebes/src/gfxPattern.cpp
+++ b/gfx/thebes/src/gfxPattern.cpp
@@ -163,11 +163,22 @@ gfxPattern::GetSolidColor(gfxRGBA& aColo
already_AddRefed<gfxASurface>
gfxPattern::GetSurface()
{
cairo_surface_t *surf = nsnull;
if (cairo_pattern_get_surface (mPattern, &surf) != CAIRO_STATUS_SUCCESS)
return nsnull;
-
return gfxASurface::Wrap(surf);
}
+
+gfxPattern::GraphicsPatternType
+gfxPattern::GetType() const
+{
+ return (GraphicsPatternType) cairo_pattern_get_type(mPattern);
+}
+
+int
+gfxPattern::CairoStatus()
+{
+ return cairo_pattern_status(mPattern);
+}
--- a/layout/svg/base/src/Makefile.in
+++ b/layout/svg/base/src/Makefile.in
@@ -112,17 +112,16 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir)/../../../base \
-I$(srcdir)/../../../generic \
-I$(srcdir)/../../../style \
-I$(srcdir)/../../../xul/base/src \
-I$(srcdir)/../../../../content/svg/content/src \
-I$(srcdir)/../../../../content/base/src \
- -I$(topsrcdir)/gfx/src/thebes \
$(NULL)
libs::
$(INSTALL) $(srcdir)/svg.css $(DIST)/bin/res
install::
$(SYSINSTALL) $(IFLAGS1) $(srcdir)/svg.css $(DESTDIR)$(mozappdir)/res
--- a/layout/svg/base/src/nsSVGImageFrame.cpp
+++ b/layout/svg/base/src/nsSVGImageFrame.cpp
@@ -42,17 +42,17 @@
#include "nsStubImageDecoderObserver.h"
#include "nsImageLoadingContent.h"
#include "nsIDOMSVGImageElement.h"
#include "nsSVGElement.h"
#include "nsSVGUtils.h"
#include "nsSVGMatrix.h"
#include "gfxContext.h"
#include "nsIInterfaceRequestorUtils.h"
-#include "nsThebesImage.h"
+#include "nsIImage.h"
class nsSVGImageFrame;
class nsSVGImageListener : public nsStubImageDecoderObserver
{
public:
nsSVGImageListener(nsSVGImageFrame *aFrame);
@@ -252,29 +252,24 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderSta
if (currentRequest)
currentRequest->GetImage(getter_AddRefs(mImageContainer));
}
nsCOMPtr<gfxIImageFrame> currentFrame;
if (mImageContainer)
mImageContainer->GetCurrentFrame(getter_AddRefs(currentFrame));
- gfxASurface *thebesSurface = nsnull;
+ nsRefPtr<gfxPattern> thebesPattern = nsnull;
if (currentFrame) {
nsCOMPtr<nsIImage> img(do_GetInterface(currentFrame));
- nsThebesImage *thebesImage = nsnull;
- if (img)
- thebesImage = static_cast<nsThebesImage*>(img.get());
-
- if (thebesImage)
- thebesSurface = thebesImage->ThebesSurface();
+ img->GetPattern(getter_AddRefs(thebesPattern));
}
- if (thebesSurface) {
+ if (thebesPattern) {
gfxContext *gfx = aContext->GetGfxContext();
if (GetStyleDisplay()->IsScrollableOverflow()) {
gfx->Save();
nsCOMPtr<nsIDOMSVGMatrix> ctm;
GetCanvasTM(getter_AddRefs(ctm));
@@ -288,17 +283,17 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderSta
// fill-opacity doesn't affect <image>, so if we're allowed to
// optimize group opacity, the opacity used for compositing the
// image into the current canvas is just the group opacity.
float opacity = 1.0f;
if (nsSVGUtils::CanOptimizeOpacity(this)) {
opacity = GetStyleDisplay()->mOpacity;
}
- nsSVGUtils::CompositeSurfaceMatrix(gfx, thebesSurface, fini, opacity);
+ nsSVGUtils::CompositePatternMatrix(gfx, thebesPattern, fini, width, height, opacity);
if (GetStyleDisplay()->IsScrollableOverflow())
gfx->Restore();
}
return rv;
}
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -1595,16 +1595,37 @@ nsSVGUtils::CompositeSurfaceMatrix(gfxCo
aContext->SetSource(aSurface);
aContext->Paint(aOpacity);
aContext->Restore();
}
void
+nsSVGUtils::CompositePatternMatrix(gfxContext *aContext,
+ gfxPattern *aPattern,
+ nsIDOMSVGMatrix *aCTM, float aWidth, float aHeight, float aOpacity)
+{
+ gfxMatrix matrix = ConvertSVGMatrixToThebes(aCTM);
+ if (matrix.IsSingular())
+ return;
+
+ aContext->Save();
+
+ SetClipRect(aContext, aCTM, 0, 0, aWidth, aHeight);
+
+ aContext->Multiply(matrix);
+
+ aContext->SetPattern(aPattern);
+ aContext->Paint(aOpacity);
+
+ aContext->Restore();
+}
+
+void
nsSVGUtils::SetClipRect(gfxContext *aContext,
nsIDOMSVGMatrix *aCTM, float aX, float aY,
float aWidth, float aHeight)
{
gfxMatrix matrix = ConvertSVGMatrixToThebes(aCTM);
if (matrix.IsSingular())
return;
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -64,16 +64,17 @@ class nsIDOMSVGAnimatedPreserveAspectRat
class nsISVGValueObserver;
class nsIAtom;
class nsSVGLength2;
class nsSVGElement;
class nsSVGSVGElement;
class nsAttrValue;
class gfxContext;
class gfxASurface;
+class gfxPattern;
class nsIRenderingContext;
class gfxImageSurface;
struct gfxRect;
struct gfxMatrix;
struct gfxSize;
struct gfxIntSize;
struct nsStyleFont;
class nsSVGEnum;
@@ -405,16 +406,20 @@ public:
float aRX, float aRY, float aRWidth, float aRHeight,
float aX, float aY);
static void CompositeSurfaceMatrix(gfxContext *aContext,
gfxASurface *aSurface,
nsIDOMSVGMatrix *aCTM, float aOpacity);
+ static void CompositePatternMatrix(gfxContext *aContext,
+ gfxPattern *aPattern,
+ nsIDOMSVGMatrix *aCTM, float aWidth, float aHeight, float aOpacity);
+
static void SetClipRect(gfxContext *aContext,
nsIDOMSVGMatrix *aCTM, float aX, float aY,
float aWidth, float aHeight);
/* Using group opacity instead of fill or stroke opacity on a
* geometry object seems to be a common authoring mistake. If we're
* not applying filters and not both stroking and filling, we can
* generate the same result without going through the overhead of a
--- a/modules/libpr0n/src/imgContainer.cpp
+++ b/modules/libpr0n/src/imgContainer.cpp
@@ -1034,40 +1034,46 @@ nsresult imgContainer::DoComposite(gfxII
// Fill aFrame with black. Does also clears the mask.
void imgContainer::ClearFrame(gfxIImageFrame *aFrame)
{
if (!aFrame)
return;
nsCOMPtr<nsIImage> img(do_GetInterface(aFrame));
nsRefPtr<gfxASurface> surf;
+
+ img->LockImagePixels(0);
img->GetSurface(getter_AddRefs(surf));
// Erase the surface to transparent
gfxContext ctx(surf);
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
ctx.Paint();
+ img->UnlockImagePixels(0);
}
//******************************************************************************
void imgContainer::ClearFrame(gfxIImageFrame *aFrame, nsIntRect &aRect)
{
if (!aFrame || aRect.width <= 0 || aRect.height <= 0) {
return;
}
nsCOMPtr<nsIImage> img(do_GetInterface(aFrame));
nsRefPtr<gfxASurface> surf;
+
+ img->LockImagePixels(0);
img->GetSurface(getter_AddRefs(surf));
// Erase the destination rectangle to transparent
gfxContext ctx(surf);
ctx.SetOperator(gfxContext::OPERATOR_CLEAR);
ctx.Rectangle(gfxRect(aRect.x, aRect.y, aRect.width, aRect.height));
ctx.Fill();
+ img->UnlockImagePixels(0);
}
//******************************************************************************
// Whether we succeed or fail will not cause a crash, and there's not much
// we can do about a failure, so there we don't return a nsresult
PRBool imgContainer::CopyFrameImage(gfxIImageFrame *aSrcFrame,
gfxIImageFrame *aDstFrame)
@@ -1179,37 +1185,39 @@ nsresult imgContainer::DrawFrameTo(gfxII
dstPixels += dstRect.width;
}
}
aDst->UnlockImageData();
return NS_OK;
}
nsCOMPtr<nsIImage> srcImg(do_GetInterface(aSrc));
- nsRefPtr<gfxASurface> srcSurf;
- srcImg->GetSurface(getter_AddRefs(srcSurf));
+ nsRefPtr<gfxPattern> srcPatt;
+ srcImg->GetPattern(getter_AddRefs(srcPatt));
nsCOMPtr<nsIImage> dstImg(do_GetInterface(aDst));
nsRefPtr<gfxASurface> dstSurf;
+ // Note: dstImage has LockImageData() called on it above, so it's safe to get
+ // the surface.
dstImg->GetSurface(getter_AddRefs(dstSurf));
gfxContext dst(dstSurf);
dst.Translate(gfxPoint(aSrcRect.x, aSrcRect.y));
dst.Rectangle(gfxRect(0, 0, aSrcRect.width, aSrcRect.height), PR_TRUE);
// first clear the surface if the blend flag says so
PRInt32 blendMethod;
aSrc->GetBlendMethod(&blendMethod);
if (blendMethod == imgIContainer::kBlendSource) {
gfxContext::GraphicsOperator defaultOperator = dst.CurrentOperator();
dst.SetOperator(gfxContext::OPERATOR_CLEAR);
dst.Fill();
dst.SetOperator(defaultOperator);
}
- dst.SetSource(srcSurf);
+ dst.SetPattern(srcPatt);
dst.Paint();
return NS_OK;
}
/********* Methods to implement lazy allocation of nsIProperties object *************/
NS_IMETHODIMP imgContainer::Get(const char *prop, const nsIID & iid, void * *result)
--- a/modules/libpr0n/src/imgTools.cpp
+++ b/modules/libpr0n/src/imgTools.cpp
@@ -314,36 +314,35 @@ NS_IMETHODIMP imgTools::EncodeScaledImag
frame->GetImageBytesPerRow(&strideSize);
bitmapDataLength = aScaledHeight * strideSize;
} else {
// Prepare to draw a scaled version of the image to a temporary surface...
// Get the source image surface
- nsRefPtr<gfxASurface> gfxsurf;
- rv = img->GetSurface(getter_AddRefs(gfxsurf));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsRefPtr<gfxPattern> gfxpat;
+ img->GetPattern(getter_AddRefs(gfxpat));
// Create a temporary image surface
dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight),
gfxASurface::ImageFormatARGB32);
if (!dest)
return NS_ERROR_OUT_OF_MEMORY;
gfxContext ctx(dest);
// Set scaling
gfxFloat sw = (double) aScaledWidth / w;
gfxFloat sh = (double) aScaledHeight / h;
ctx.Scale(sw, sh);
// Paint a scaled image
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
- ctx.SetSource(gfxsurf);
+ ctx.SetPattern(gfxpat);
ctx.Paint();
bitmapData = dest->Data();
strideSize = dest->Stride();
bitmapDataLength = aScaledHeight * strideSize;
}
// Encode the bitmap
--- a/widget/src/gtk2/nsImageToPixbuf.cpp
+++ b/widget/src/gtk2/nsImageToPixbuf.cpp
@@ -66,62 +66,37 @@ nsImageToPixbuf::ConvertImageToPixbuf(ns
}
GdkPixbuf*
nsImageToPixbuf::ImageToPixbuf(nsIImage* aImage)
{
PRInt32 width = aImage->GetWidth(),
height = aImage->GetHeight();
- nsRefPtr<gfxASurface> surface;
- aImage->GetSurface(getter_AddRefs(surface));
+ nsRefPtr<gfxPattern> pattern;
+ aImage->GetPattern(getter_AddRefs(pattern));
- return SurfaceToPixbuf(surface, width, height);
+ return PatternToPixbuf(pattern, width, height);
}
GdkPixbuf*
-nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, PRInt32 aWidth, PRInt32 aHeight)
+nsImageToPixbuf::ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface, PRInt32 aWidth, PRInt32 aHeight)
{
- if (aSurface->CairoStatus()) {
- NS_ERROR("invalid surface");
- return nsnull;
- }
-
- nsRefPtr<gfxImageSurface> imgSurface;
- if (aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
- imgSurface = static_cast<gfxImageSurface*>
- (static_cast<gfxASurface*>(aSurface));
- } else {
- imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
- gfxImageSurface::ImageFormatARGB32);
-
- if (!imgSurface)
- return nsnull;
-
- nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
- if (!context)
- return nsnull;
-
- context->SetOperator(gfxContext::OPERATOR_SOURCE);
- context->SetSource(aSurface);
- context->Paint();
- }
-
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, PR_TRUE, 8,
aWidth, aHeight);
if (!pixbuf)
return nsnull;
PRUint32 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
guchar* pixels = gdk_pixbuf_get_pixels (pixbuf);
- long cairoStride = imgSurface->Stride();
- unsigned char* cairoData = imgSurface->Data();
+ long cairoStride = aImgSurface->Stride();
+ unsigned char* cairoData = aImgSurface->Data();
- gfxASurface::gfxImageFormat format = imgSurface->Format();
+ gfxASurface::gfxImageFormat format = aImgSurface->Format();
for (PRInt32 row = 0; row < aHeight; ++row) {
for (PRInt32 col = 0; col < aWidth; ++col) {
guchar* pixel = pixels + row * rowstride + 4 * col;
PRUint32* cairoPixel = reinterpret_cast<PRUint32*>
((cairoData + row * cairoStride + 4 * col));
@@ -147,8 +122,75 @@ nsImageToPixbuf::SurfaceToPixbuf(gfxASur
*pixel++ = b;
*pixel++ = 0xFF; // A
}
}
}
return pixbuf;
}
+
+GdkPixbuf*
+nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, PRInt32 aWidth, PRInt32 aHeight)
+{
+ if (aSurface->CairoStatus()) {
+ NS_ERROR("invalid surface");
+ return nsnull;
+ }
+
+ nsRefPtr<gfxImageSurface> imgSurface;
+ if (aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+ imgSurface = static_cast<gfxImageSurface*>
+ (static_cast<gfxASurface*>(aSurface));
+ } else {
+ imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
+ gfxImageSurface::ImageFormatARGB32);
+
+ if (!imgSurface)
+ return nsnull;
+
+ nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
+ if (!context)
+ return nsnull;
+
+ context->SetOperator(gfxContext::OPERATOR_SOURCE);
+ context->SetSource(aSurface);
+ context->Paint();
+ }
+
+ return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
+}
+
+GdkPixbuf*
+nsImageToPixbuf::PatternToPixbuf(gfxPattern* aPattern, PRInt32 aWidth, PRInt32 aHeight)
+{
+ if (aPattern->CairoStatus()) {
+ NS_ERROR("invalid pattern");
+ return nsnull;
+ }
+
+ nsRefPtr<gfxImageSurface> imgSurface;
+ if (aPattern->GetType() == gfxPattern::PATTERN_SURFACE) {
+ nsRefPtr<gfxASurface> surface = aPattern->GetSurface();
+ if (surface->GetType() == gfxASurface::SurfaceTypeImage) {
+ imgSurface = static_cast<gfxImageSurface*>
+ (static_cast<gfxASurface*>(surface.get()));
+ }
+ }
+
+ if (!imgSurface) {
+ imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight),
+ gfxImageSurface::ImageFormatARGB32);
+
+ if (!imgSurface)
+ return nsnull;
+
+ nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
+ if (!context)
+ return nsnull;
+
+ context->SetOperator(gfxContext::OPERATOR_SOURCE);
+ context->SetPattern(aPattern);
+ context->Paint();
+ }
+
+ return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
+}
--- a/widget/src/gtk2/nsImageToPixbuf.h
+++ b/widget/src/gtk2/nsImageToPixbuf.h
@@ -36,28 +36,34 @@
* ***** END LICENSE BLOCK ***** */
#ifndef NSIMAGETOPIXBUF_H_
#define NSIMAGETOPIXBUF_H_
#include "nsIImageToPixbuf.h"
class gfxASurface;
+class gfxPattern;
+class gfxImageSurface;
class nsImageToPixbuf : public nsIImageToPixbuf {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(nsIImage* aImage);
// Friendlier version of ConvertImageToPixbuf for callers inside of
// widget
static GdkPixbuf* ImageToPixbuf(nsIImage* aImage);
static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
PRInt32 aWidth, PRInt32 aHeight);
+ static GdkPixbuf* PatternToPixbuf(gfxPattern* aPattern,
+ PRInt32 aWidth, PRInt32 aHeight);
private:
+ static GdkPixbuf* ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface,
+ PRInt32 aWidth, PRInt32 aHeight);
~nsImageToPixbuf() {}
};
// fc2389b8-c650-4093-9e42-b05e5f0685b7
#define NS_IMAGE_TO_PIXBUF_CID \
{ 0xfc2389b8, 0xc650, 0x4093, \
{ 0x9e, 0x42, 0xb0, 0x5e, 0x5f, 0x06, 0x85, 0xb7 } }