--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -90,17 +90,16 @@
#include "nsIDocShellTreeItem.h"
#include "nsIDocShellTreeNode.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "jsnum.h"
#include "nsTArray.h"
-#include "cairo.h"
#include "imgIEncoder.h"
#include "gfxContext.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h"
#include "gfxPlatform.h"
#include "gfxFont.h"
#include "gfxTextRunCache.h"
@@ -162,28 +161,23 @@ static PRBool FloatValidate (double f1,
**/
#define NS_CANVASGRADIENT_PRIVATE_IID \
{ 0x491d39d8, 0x4058, 0x42bd, { 0xac, 0x76, 0x70, 0xd5, 0x62, 0x7f, 0x02, 0x10 } }
class nsCanvasGradient : public nsIDOMCanvasGradient
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASGRADIENT_PRIVATE_IID)
- nsCanvasGradient(cairo_pattern_t *cpat, nsICSSParser *cssparser)
- : mPattern(cpat), mCSSParser(cssparser)
+ nsCanvasGradient(gfxPattern* pat, nsICSSParser* cssparser)
+ : mPattern(pat), mCSSParser(cssparser)
{
}
- ~nsCanvasGradient() {
- if (mPattern)
- cairo_pattern_destroy(mPattern);
- }
-
- void Apply(cairo_t *cairo) {
- cairo_set_source(cairo, mPattern);
+ void Apply(gfxContext* ctx) {
+ ctx->SetPattern(mPattern);
}
/* nsIDOMCanvasGradient */
NS_IMETHOD AddColorStop (float offset,
const nsAString& colorstr)
{
nscolor color;
@@ -192,28 +186,25 @@ public:
if (offset < 0.0 || offset > 1.0)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
nsresult rv = mCSSParser->ParseColorString(nsString(colorstr), nsnull, 0, &color);
if (NS_FAILED(rv))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_pattern_add_color_stop_rgba (mPattern, (double) offset,
- NS_GET_R(color) / 255.0,
- NS_GET_G(color) / 255.0,
- NS_GET_B(color) / 255.0,
- NS_GET_A(color) / 255.0);
+ mPattern->AddColorStop(offset, gfxRGBA(color));
+
return NS_OK;
}
NS_DECL_ISUPPORTS
protected:
- cairo_pattern_t *mPattern;
+ nsRefPtr<gfxPattern> mPattern;
nsCOMPtr<nsICSSParser> mCSSParser;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCanvasGradient, NS_CANVASGRADIENT_PRIVATE_IID)
NS_IMPL_ADDREF(nsCanvasGradient)
NS_IMPL_RELEASE(nsCanvasGradient)
@@ -229,43 +220,37 @@ NS_INTERFACE_MAP_END
**/
#define NS_CANVASPATTERN_PRIVATE_IID \
{ 0xb85c6c8a, 0x0624, 0x4530, { 0xb8, 0xee, 0xff, 0xdf, 0x42, 0xe8, 0x21, 0x6d } }
class nsCanvasPattern : public nsIDOMCanvasPattern
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CANVASPATTERN_PRIVATE_IID)
- nsCanvasPattern(cairo_pattern_t *cpat,
+ nsCanvasPattern(gfxPattern* pat,
nsIPrincipal* principalForSecurityCheck,
PRBool forceWriteOnly)
- : mPattern(cpat),
+ : mPattern(pat),
mPrincipal(principalForSecurityCheck),
mForceWriteOnly(forceWriteOnly)
{
NS_PRECONDITION(mPrincipal, "Must have a principal");
}
- ~nsCanvasPattern() {
- if (mPattern)
- cairo_pattern_destroy(mPattern);
- }
-
- void Apply(cairo_t *cairo) {
- cairo_set_source(cairo, mPattern);
+ void Apply(gfxContext* ctx) {
+ ctx->SetPattern(mPattern);
}
nsIPrincipal* Principal() { return mPrincipal; }
PRBool GetForceWriteOnly() { return mForceWriteOnly; }
NS_DECL_ISUPPORTS
protected:
- cairo_pattern_t *mPattern;
- PRUint8 *mData;
+ nsRefPtr<gfxPattern> mPattern;
nsCOMPtr<nsIPrincipal> mPrincipal;
PRPackedBool mForceWriteOnly;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCanvasPattern, NS_CANVASPATTERN_PRIVATE_IID)
NS_IMPL_ADDREF(nsCanvasPattern)
NS_IMPL_RELEASE(nsCanvasPattern)
@@ -323,17 +308,17 @@ class nsCanvasRenderingContext2D :
public nsIDOMCanvasRenderingContext2D,
public nsICanvasRenderingContextInternal
{
public:
nsCanvasRenderingContext2D();
virtual ~nsCanvasRenderingContext2D();
nsresult Redraw();
- void SetCairoColor(nscolor c);
+ void SetThebesColor(nscolor c);
// nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
NS_IMETHOD Render(gfxContext *ctx);
NS_IMETHOD GetInputStream(const char* aMimeType,
const PRUnichar* aEncoderOptions,
nsIInputStream **aStream);
@@ -342,35 +327,32 @@ public:
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMCanvasRenderingContext2D interface
NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
protected:
- // destroy cairo/image stuff, in preparation for possibly recreating
+ // destroy thebes/image stuff, in preparation for possibly recreating
void Destroy();
// Some helpers. Doesn't modify acolor on failure.
- enum {
+ enum Style {
STYLE_STROKE = 0,
STYLE_FILL,
- STYLE_SHADOW
- //STYLE_MAX
+ STYLE_SHADOW,
+ STYLE_MAX
};
- // VC6 sucks
-#define STYLE_MAX 3
-
- nsresult SetStyleFromVariant(nsIVariant* aStyle, PRInt32 aWhichStyle);
+ nsresult SetStyleFromVariant(nsIVariant* aStyle, Style aWhichStyle);
void StyleColorToString(const nscolor& aColor, nsAString& aStr);
void DirtyAllStyles();
- void ApplyStyle(PRInt32 aWhichStyle);
+ void ApplyStyle(Style aWhichStyle);
// If aPrincipal is not subsumed by this canvas element, then
// we make the canvas write-only so bad guys can't extract the pixel
// data. If forceWriteOnly is set, we force write only to be set
// and ignore aPrincipal. (This is used for when the original data came
// from a <canvas> that had write-only set.)
void DoDrawImageSecurityCheck(nsIPrincipal* aPrincipal,
PRBool forceWriteOnly);
@@ -382,23 +364,26 @@ protected:
// the canvas element informs us when it's going away,
// so these are not nsCOMPtrs
nsICanvasElement* mCanvasElement;
// our CSS parser, for colors and whatnot
nsCOMPtr<nsICSSParser> mCSSParser;
- // yay cairo
- nsRefPtr<gfxContext> mThebesContext;
- nsRefPtr<gfxASurface> mThebesSurface;
+ // yay thebes
+ nsRefPtr<gfxContext> mThebes;
+ nsRefPtr<gfxASurface> mSurface;
PRUint32 mSaveCount;
- cairo_t *mCairo;
- cairo_surface_t *mSurface;
+
+ /**
+ * Draws a rectangle in the given style; used by FillRect and StrokeRect.
+ */
+ nsresult DrawRect(const gfxRect& rect, Style style);
// text
enum TextAlign {
TEXT_ALIGN_START,
TEXT_ALIGN_END,
TEXT_ALIGN_LEFT,
TEXT_ALIGN_RIGHT,
TEXT_ALIGN_CENTER
@@ -428,17 +413,21 @@ protected:
nsresult DrawOrMeasureText(const nsAString& text,
float x,
float y,
float maxWidth,
TextDrawOperation op,
float* aWidth);
// style handling
- PRInt32 mLastStyle;
+ /*
+ * The previous set style. Is equal to STYLE_MAX when there is no valid
+ * previous style.
+ */
+ Style mLastStyle;
PRPackedBool mDirtyStyle[STYLE_MAX];
// state stack handling
class ContextState {
public:
ContextState() : globalAlpha(1.0),
textAlign(TEXT_ALIGN_START),
textBaseline(TEXT_BASELINE_ALPHABETIC) { }
@@ -452,28 +441,28 @@ protected:
{
for (int i = 0; i < STYLE_MAX; i++) {
colorStyles[i] = other.colorStyles[i];
gradientStyles[i] = other.gradientStyles[i];
patternStyles[i] = other.patternStyles[i];
}
}
- inline void SetColorStyle(int whichStyle, nscolor color) {
+ inline void SetColorStyle(Style whichStyle, nscolor color) {
colorStyles[whichStyle] = color;
gradientStyles[whichStyle] = nsnull;
patternStyles[whichStyle] = nsnull;
}
- inline void SetPatternStyle(int whichStyle, nsCanvasPattern* pat) {
+ inline void SetPatternStyle(Style whichStyle, nsCanvasPattern* pat) {
gradientStyles[whichStyle] = nsnull;
patternStyles[whichStyle] = pat;
}
- inline void SetGradientStyle(int whichStyle, nsCanvasGradient* grad) {
+ inline void SetGradientStyle(Style whichStyle, nsCanvasGradient* grad) {
gradientStyles[whichStyle] = grad;
patternStyles[whichStyle] = nsnull;
}
float globalAlpha;
nsString font;
nsRefPtr<gfxFontGroup> fontGroup;
@@ -494,23 +483,23 @@ protected:
// stolen from nsJSUtils
static PRBool ConvertJSValToUint32(PRUint32* aProp, JSContext* aContext,
jsval aValue);
static PRBool ConvertJSValToXPCObject(nsISupports** aSupports, REFNSIID aIID,
JSContext* aContext, jsval aValue);
static PRBool ConvertJSValToDouble(double* aProp, JSContext* aContext,
jsval aValue);
- // cairo helpers
- nsresult CairoSurfaceFromElement(nsIDOMElement *imgElt,
- PRBool forceCopy,
- cairo_surface_t **aCairoSurface,
- PRInt32 *widthOut, PRInt32 *heightOut,
- nsIPrincipal **prinOut,
- PRBool *forceWriteOnlyOut);
+ // thebes helpers
+ nsresult ThebesSurfaceFromElement(nsIDOMElement *imgElt,
+ PRBool forceCopy,
+ gfxASurface **aSurface,
+ PRInt32 *widthOut, PRInt32 *heightOut,
+ nsIPrincipal **prinOut,
+ PRBool *forceWriteOnlyOut);
// other helpers
void GetAppUnitsValues(PRUint32 *perDevPixel, PRUint32 *perCSSPixel) {
// If we don't have a canvas element, we just return something generic.
PRUint32 devPixel = 60;
PRUint32 cssPixel = 60;
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
@@ -547,49 +536,45 @@ NS_INTERFACE_MAP_END
/**
** CanvasRenderingContext2D impl
**/
nsresult
NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
{
- nsIDOMCanvasRenderingContext2D* ctx = new nsCanvasRenderingContext2D();
+ nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx = new nsCanvasRenderingContext2D();
if (!ctx)
return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(*aResult = ctx);
+ *aResult = ctx.forget().get();
return NS_OK;
}
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
- mSaveCount(0), mCairo(nsnull), mSurface(nsnull), mStyleStack(20)
+ mSaveCount(0), mStyleStack(20)
{
}
nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
{
Destroy();
}
void
nsCanvasRenderingContext2D::Destroy()
{
mSurface = nsnull;
- mThebesSurface = nsnull;
-
- mCairo = nsnull;
- mThebesContext = nsnull;
-
+ mThebes = nsnull;
mValid = PR_FALSE;
}
nsresult
-nsCanvasRenderingContext2D::SetStyleFromVariant(nsIVariant* aStyle, PRInt32 aWhichStyle)
+nsCanvasRenderingContext2D::SetStyleFromVariant(nsIVariant* aStyle, Style aWhichStyle)
{
nsresult rv;
nscolor color;
PRUint16 paramType;
rv = aStyle->GetDataType(¶mType);
NS_ENSURE_SUCCESS(rv, rv);
@@ -710,17 +695,17 @@ nsCanvasRenderingContext2D::DoDrawImageS
return;
}
}
mCanvasElement->SetWriteOnly();
}
void
-nsCanvasRenderingContext2D::ApplyStyle(PRInt32 aWhichStyle)
+nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle)
{
if (mLastStyle == aWhichStyle &&
!mDirtyStyle[aWhichStyle])
{
// nothing to do, this is already the set style
return;
}
@@ -729,107 +714,102 @@ nsCanvasRenderingContext2D::ApplyStyle(P
nsCanvasPattern* pattern = CurrentState().patternStyles[aWhichStyle];
if (pattern) {
if (!mCanvasElement)
return;
DoDrawImageSecurityCheck(pattern->Principal(),
pattern->GetForceWriteOnly());
- pattern->Apply(mCairo);
+ pattern->Apply(mThebes);
return;
}
if (CurrentState().gradientStyles[aWhichStyle]) {
- CurrentState().gradientStyles[aWhichStyle]->Apply(mCairo);
+ CurrentState().gradientStyles[aWhichStyle]->Apply(mThebes);
return;
}
- SetCairoColor(CurrentState().colorStyles[aWhichStyle]);
+ SetThebesColor(CurrentState().colorStyles[aWhichStyle]);
}
nsresult
nsCanvasRenderingContext2D::Redraw()
{
if (!mCanvasElement)
- return nsnull;
+ return NS_OK;
return mCanvasElement->InvalidateFrame();
}
void
-nsCanvasRenderingContext2D::SetCairoColor(nscolor c)
+nsCanvasRenderingContext2D::SetThebesColor(nscolor c)
{
- double r = double(NS_GET_R(c) / 255.0);
- double g = double(NS_GET_G(c) / 255.0);
- double b = double(NS_GET_B(c) / 255.0);
- double a = double(NS_GET_A(c) / 255.0) * CurrentState().globalAlpha;
-
- cairo_set_source_rgba (mCairo, r, g, b, a);
+ gfxRGBA color(c);
+ color.a *= CurrentState().globalAlpha;
+
+ mThebes->SetColor(color);
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
{
Destroy();
mWidth = width;
mHeight = height;
// Check that the dimensions are sane
if (gfxASurface::CheckSurfaceSize(gfxIntSize(width, height), 0xffff)) {
gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
if (mOpaque)
format = gfxASurface::ImageFormatRGB24;
- mThebesSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
+ mSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(width, height), format);
- if (mThebesSurface->CairoStatus() == 0) {
- mThebesContext = new gfxContext(mThebesSurface);
+ if (mSurface->CairoStatus() == 0) {
+ mThebes = new gfxContext(mSurface);
}
}
/* Create dummy surfaces here */
- if (mThebesSurface == nsnull || mThebesSurface->CairoStatus() != 0 ||
- mThebesContext == nsnull || mThebesContext->HasError())
+ if (mSurface == nsnull || mSurface->CairoStatus() != 0 ||
+ mThebes == nsnull || mThebes->HasError())
{
- mThebesSurface = new gfxImageSurface(gfxIntSize(1,1), gfxASurface::ImageFormatARGB32);
- mThebesContext = new gfxContext(mThebesSurface);
+ mSurface = new gfxImageSurface(gfxIntSize(1,1), gfxASurface::ImageFormatARGB32);
+ mThebes = new gfxContext(mSurface);
} else {
mValid = PR_TRUE;
}
- mSurface = mThebesSurface->CairoSurface();
- mCairo = mThebesContext->GetCairo();
-
// set up the initial canvas defaults
mStyleStack.Clear();
mSaveCount = 0;
ContextState *state = mStyleStack.AppendElement();
state->globalAlpha = 1.0;
for (int i = 0; i < STYLE_MAX; i++)
state->colorStyles[i] = NS_RGB(0,0,0);
- mLastStyle = -1;
+ mLastStyle = STYLE_MAX;
DirtyAllStyles();
- cairo_set_operator(mCairo, CAIRO_OPERATOR_CLEAR);
- cairo_new_path(mCairo);
- cairo_rectangle(mCairo, 0, 0, mWidth, mHeight);
- cairo_fill(mCairo);
-
- cairo_set_line_width(mCairo, 1.0);
- cairo_set_operator(mCairo, CAIRO_OPERATOR_OVER);
- cairo_set_miter_limit(mCairo, 10.0);
- cairo_set_line_cap(mCairo, CAIRO_LINE_CAP_BUTT);
- cairo_set_line_join(mCairo, CAIRO_LINE_JOIN_MITER);
-
- cairo_new_path(mCairo);
+ mThebes->SetOperator(gfxContext::OPERATOR_CLEAR);
+ mThebes->NewPath();
+ mThebes->Rectangle(gfxRect(0, 0, mWidth, mHeight));
+ mThebes->Fill();
+
+ mThebes->SetLineWidth(1.0);
+ mThebes->SetOperator(gfxContext::OPERATOR_OVER);
+ mThebes->SetMiterLimit(10.0);
+ mThebes->SetLineCap(gfxContext::LINE_CAP_BUTT);
+ mThebes->SetLineJoin(gfxContext::LINE_JOIN_MITER);
+
+ mThebes->NewPath();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetIsOpaque(PRBool isOpaque)
{
if (isOpaque == mOpaque)
@@ -847,25 +827,25 @@ nsCanvasRenderingContext2D::SetIsOpaque(
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Render(gfxContext *ctx)
{
nsresult rv = NS_OK;
- if (!mValid || !mSurface || !mCairo ||
- cairo_surface_status(mSurface) != CAIRO_STATUS_SUCCESS ||
- cairo_status(mCairo) != CAIRO_STATUS_SUCCESS)
+ if (!mValid || !mSurface ||
+ mSurface->CairoStatus() ||
+ mThebes->HasError())
return NS_ERROR_FAILURE;
- if (!mThebesSurface)
+ if (!mSurface)
return NS_ERROR_FAILURE;
- nsRefPtr<gfxPattern> pat = new gfxPattern(mThebesSurface);
+ nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
gfxContext::GraphicsOperator op = ctx->CurrentOperator();
if (mOpaque)
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
// XXX I don't want to use PixelSnapped here, but layout doesn't guarantee
// pixel alignment for this stuff!
ctx->NewPath();
@@ -879,18 +859,18 @@ nsCanvasRenderingContext2D::Render(gfxCo
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetInputStream(const char *aMimeType,
const PRUnichar *aEncoderOptions,
nsIInputStream **aStream)
{
if (!mValid || !mSurface ||
- cairo_status(mCairo) != CAIRO_STATUS_SUCCESS ||
- cairo_surface_status(mSurface) != CAIRO_STATUS_SUCCESS)
+ mSurface->CairoStatus() ||
+ mThebes->HasError())
return NS_ERROR_FAILURE;
nsresult rv;
const char encoderPrefix[] = "@mozilla.org/image/encoder;2?type=";
nsAutoArrayPtr<char> conid(new (std::nothrow) char[strlen(encoderPrefix) + strlen(aMimeType) + 1]);
if (!conid)
return NS_ERROR_OUT_OF_MEMORY;
@@ -901,29 +881,32 @@ nsCanvasRenderingContext2D::GetInputStre
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(conid);
if (!encoder)
return NS_ERROR_FAILURE;
nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[mWidth * mHeight * 4]);
if (!imageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
- cairo_surface_t *imgsurf = cairo_image_surface_create_for_data (imageBuffer.get(),
- CAIRO_FORMAT_ARGB32,
- mWidth, mHeight, mWidth * 4);
- if (!imgsurf || cairo_surface_status(imgsurf))
+ nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
+ gfxIntSize(mWidth, mHeight),
+ mWidth * 4,
+ gfxASurface::ImageFormatARGB32);
+
+ if (!imgsurf || imgsurf->CairoStatus())
return NS_ERROR_FAILURE;
- cairo_t *cr = cairo_create(imgsurf);
- cairo_surface_destroy (imgsurf);
-
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface (cr, mSurface, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
+ nsRefPtr<gfxContext> ctx = new gfxContext(imgsurf);
+
+ if (!ctx || ctx->HasError())
+ return NS_ERROR_FAILURE;
+
+ ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+ ctx->SetSource(mSurface, gfxPoint(0, 0));
+ ctx->Paint();
rv = encoder->InitFromData(imageBuffer.get(),
mWidth * mHeight * 4, mWidth, mHeight, mWidth * 4,
imgIEncoder::INPUT_FORMAT_HOSTARGB,
nsDependentString(aEncoderOptions));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(encoder, aStream);
@@ -962,94 +945,94 @@ nsCanvasRenderingContext2D::GetCanvas(ns
// state
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::Save()
{
ContextState state = CurrentState();
mStyleStack.AppendElement(state);
- cairo_save (mCairo);
+ mThebes->Save();
mSaveCount++;
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Restore()
{
if (mSaveCount == 0)
return NS_OK;
if (mSaveCount < 0)
return NS_ERROR_DOM_INVALID_STATE_ERR;
mStyleStack.RemoveElementAt(mSaveCount);
- cairo_restore (mCairo);
-
- mLastStyle = -1;
+ mThebes->Restore();
+
+ mLastStyle = STYLE_MAX;
DirtyAllStyles();
mSaveCount--;
return NS_OK;
}
//
// transformations
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::Scale(float x, float y)
{
if (!FloatValidate(x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_scale (mCairo, x, y);
+ mThebes->Scale(x, y);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Rotate(float angle)
{
if (!FloatValidate(angle))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_rotate (mCairo, angle);
+ mThebes->Rotate(angle);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Translate(float x, float y)
{
if (!FloatValidate(x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_translate (mCairo, x, y);
+ mThebes->Translate(gfxPoint(x, y));
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Transform(float m11, float m12, float m21, float m22, float dx, float dy)
{
if (!FloatValidate(m11,m12,m21,m22,dx,dy))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_matrix_t mat;
- cairo_matrix_init (&mat, m11, m12, m21, m22, dx, dy);
- cairo_transform (mCairo, &mat);
+ gfxMatrix matrix(m11, m12, m21, m22, dx, dy);
+ mThebes->Multiply(matrix);
+
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetTransform(float m11, float m12, float m21, float m22, float dx, float dy)
{
if (!FloatValidate(m11,m12,m21,m22,dx,dy))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_matrix_t mat;
- cairo_matrix_init (&mat, m11, m12, m21, m22, dx, dy);
- cairo_set_matrix (mCairo, &mat);
+ gfxMatrix matrix(m11, m12, m21, m22, dx, dy);
+ mThebes->SetMatrix(matrix);
+
return NS_OK;
}
//
// colors
//
NS_IMETHODIMP
@@ -1101,17 +1084,17 @@ nsCanvasRenderingContext2D::GetStrokeSty
} else {
nsString styleStr;
StyleColorToString(CurrentState().colorStyles[STYLE_STROKE], styleStr);
rv = var->SetAsDOMString(styleStr);
NS_ENSURE_SUCCESS(rv, rv);
}
- NS_ADDREF(*aStyle = var);
+ *aStyle = var.forget().get();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetFillStyle(nsIVariant* aStyle)
{
return SetStyleFromVariant(aStyle, STYLE_FILL);
}
@@ -1136,108 +1119,104 @@ nsCanvasRenderingContext2D::GetFillStyle
} else {
nsString styleStr;
StyleColorToString(CurrentState().colorStyles[STYLE_FILL], styleStr);
rv = var->SetAsDOMString(styleStr);
NS_ENSURE_SUCCESS(rv, rv);
}
- NS_ADDREF(*aStyle = var);
+ *aStyle = var.forget().get();
return NS_OK;
}
//
// gradients and patterns
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::CreateLinearGradient(float x0, float y0, float x1, float y1,
nsIDOMCanvasGradient **_retval)
{
if (!FloatValidate(x0,y0,x1,y1))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_pattern_t *gradpat = nsnull;
- gradpat = cairo_pattern_create_linear ((double) x0, (double) y0, (double) x1, (double) y1);
- nsCanvasGradient *grad = new nsCanvasGradient(gradpat, mCSSParser);
- if (!grad) {
- cairo_pattern_destroy(gradpat);
+ nsRefPtr<gfxPattern> gradpat = new gfxPattern(x0, y0, x1, y1);
+ if (!gradpat)
return NS_ERROR_OUT_OF_MEMORY;
- }
-
- NS_ADDREF(*_retval = grad);
+
+ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat, mCSSParser);
+ if (!grad)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = grad.forget().get();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::CreateRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1,
nsIDOMCanvasGradient **_retval)
{
if (!FloatValidate(x0,y0,r0,x1,y1,r1))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_pattern_t *gradpat = nsnull;
- gradpat = cairo_pattern_create_radial ((double) x0, (double) y0, (double) r0,
- (double) x1, (double) y1, (double) r1);
- nsCanvasGradient *grad = new nsCanvasGradient(gradpat, mCSSParser);
- if (!grad) {
- cairo_pattern_destroy(gradpat);
+ nsRefPtr<gfxPattern> gradpat = new gfxPattern(x0, y0, r0, x1, y1, r1);
+ if (!gradpat)
return NS_ERROR_OUT_OF_MEMORY;
- }
-
- NS_ADDREF(*_retval = grad);
+
+ nsRefPtr<nsIDOMCanvasGradient> grad = new nsCanvasGradient(gradpat, mCSSParser);
+ if (!grad)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ *_retval = grad.forget().get();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
const nsAString& repeat,
nsIDOMCanvasPattern **_retval)
{
nsresult rv;
- cairo_extend_t extend;
+ gfxPattern::GraphicsExtend extend;
if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
- extend = CAIRO_EXTEND_REPEAT;
+ extend = gfxPattern::EXTEND_REPEAT;
} else if (repeat.EqualsLiteral("repeat-x")) {
// XX
- extend = CAIRO_EXTEND_REPEAT;
+ extend = gfxPattern::EXTEND_REPEAT;
} else if (repeat.EqualsLiteral("repeat-y")) {
// XX
- extend = CAIRO_EXTEND_REPEAT;
+ extend = gfxPattern::EXTEND_REPEAT;
} else if (repeat.EqualsLiteral("no-repeat")) {
- extend = CAIRO_EXTEND_NONE;
+ extend = gfxPattern::EXTEND_NONE;
} else {
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SYNTAX_ERR;
}
- cairo_surface_t *imgSurf = nsnull;
PRInt32 imgWidth, imgHeight;
nsCOMPtr<nsIPrincipal> principal;
PRBool forceWriteOnly = PR_FALSE;
- rv = CairoSurfaceFromElement(image, PR_TRUE,
- &imgSurf, &imgWidth, &imgHeight,
- getter_AddRefs(principal), &forceWriteOnly);
+ nsRefPtr<gfxASurface> imgsurf;
+ rv = ThebesSurfaceFromElement(image, PR_TRUE,
+ getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
+ getter_AddRefs(principal), &forceWriteOnly);
if (NS_FAILED(rv))
return rv;
- cairo_pattern_t *cairopat = cairo_pattern_create_for_surface(imgSurf);
- cairo_surface_destroy(imgSurf);
-
- cairo_pattern_set_extend (cairopat, extend);
-
- nsCanvasPattern *pat = new nsCanvasPattern(cairopat, principal,
- forceWriteOnly);
- if (!pat) {
- cairo_pattern_destroy(cairopat);
+ nsRefPtr<gfxPattern> thebespat = new gfxPattern(imgsurf);
+
+ thebespat->SetExtend(extend);
+
+ nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, principal,
+ forceWriteOnly);
+ if (!pat)
return NS_ERROR_OUT_OF_MEMORY;
- }
-
- NS_ADDREF(*_retval = pat);
+
+ *_retval = pat.forget().get();
return NS_OK;
}
//
// shadows
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetShadowOffsetX(float x)
@@ -1306,163 +1285,156 @@ nsCanvasRenderingContext2D::GetShadowCol
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
{
if (!FloatValidate(x,y,w,h))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_path_t *old_path = cairo_copy_path (mCairo);
- cairo_save (mCairo);
- cairo_set_operator (mCairo, CAIRO_OPERATOR_CLEAR);
- cairo_new_path (mCairo);
- cairo_rectangle (mCairo, x, y, w, h);
- cairo_fill (mCairo);
- cairo_restore (mCairo);
- cairo_new_path (mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path (mCairo, old_path);
- cairo_path_destroy (old_path);
+ nsRefPtr<gfxPath> path = mThebes->CopyPath();
+
+ mThebes->Save();
+ mThebes->SetOperator(gfxContext::OPERATOR_CLEAR);
+ mThebes->NewPath();
+ mThebes->Rectangle(gfxRect(x, y, w, h));
+ mThebes->Fill();
+ mThebes->Restore();
+
+ mThebes->NewPath();
+ mThebes->AppendPath(path);
+
+ return Redraw();
+}
+
+nsresult
+nsCanvasRenderingContext2D::DrawRect(const gfxRect& rect, Style style)
+{
+ if (!FloatValidate(rect.pos.x, rect.pos.y, rect.size.width, rect.size.height))
+ return NS_ERROR_DOM_SYNTAX_ERR;
+
+ nsRefPtr<gfxPath> path = mThebes->CopyPath();
+
+ mThebes->NewPath();
+ mThebes->Rectangle(rect);
+
+ ApplyStyle(style);
+ if (style == STYLE_FILL)
+ mThebes->Fill();
+ else // STYLE_STROKE
+ mThebes->Stroke();
+
+ mThebes->NewPath();
+ mThebes->AppendPath(path);
return Redraw();
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::FillRect(float x, float y, float w, float h)
{
- if (!FloatValidate(x,y,w,h))
- return NS_ERROR_DOM_SYNTAX_ERR;
-
- cairo_path_t *old_path = cairo_copy_path (mCairo);
- cairo_new_path (mCairo);
- cairo_rectangle (mCairo, x, y, w, h);
-
- ApplyStyle(STYLE_FILL);
- cairo_fill (mCairo);
- cairo_new_path (mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path (mCairo, old_path);
- cairo_path_destroy (old_path);
-
- return Redraw();
+ return DrawRect(gfxRect(x, y, w, h), STYLE_FILL);
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::StrokeRect(float x, float y, float w, float h)
{
- if (!FloatValidate(x,y,w,h))
- return NS_ERROR_DOM_SYNTAX_ERR;
-
- cairo_path_t *old_path = cairo_copy_path (mCairo);
- cairo_new_path (mCairo);
- cairo_rectangle (mCairo, x, y, w, h);
-
- ApplyStyle(STYLE_STROKE);
- cairo_stroke (mCairo);
- cairo_new_path (mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path (mCairo, old_path);
- cairo_path_destroy (old_path);
-
- return Redraw();
+ return DrawRect(gfxRect(x, y, w, h), STYLE_STROKE);
}
//
// path bits
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::BeginPath()
{
- cairo_new_path(mCairo);
+ mThebes->NewPath();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::ClosePath()
{
- cairo_close_path(mCairo);
+ mThebes->ClosePath();
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Fill()
{
ApplyStyle(STYLE_FILL);
- cairo_fill_preserve(mCairo);
+ mThebes->Fill();
return Redraw();
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Stroke()
{
ApplyStyle(STYLE_STROKE);
- cairo_stroke_preserve(mCairo);
+ mThebes->Stroke();
return Redraw();
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Clip()
{
- cairo_clip_preserve(mCairo);
+ mThebes->Clip();
return Redraw();
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::MoveTo(float x, float y)
{
if (!FloatValidate(x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_move_to(mCairo, x, y);
+ mThebes->MoveTo(gfxPoint(x, y));
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::LineTo(float x, float y)
{
if (!FloatValidate(x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_line_to(mCairo, x, y);
+ mThebes->LineTo(gfxPoint(x, y));
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::QuadraticCurveTo(float cpx, float cpy, float x, float y)
{
if (!FloatValidate(cpx,cpy,x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- double cx, cy;
-
// we will always have a current point, since beginPath forces
// a moveto(0,0)
- cairo_get_current_point(mCairo, &cx, &cy);
- cairo_curve_to(mCairo,
- (cx + cpx * 2.0) / 3.0,
- (cy + cpy * 2.0) / 3.0,
- (cpx * 2.0 + x) / 3.0,
- (cpy * 2.0 + y) / 3.0,
- x,
- y);
+ gfxPoint c = mThebes->CurrentPoint();
+ gfxPoint p(x,y);
+ gfxPoint cp(cpx, cpy);
+
+ mThebes->CurveTo((c+cp*2)/3.0, (p+cp*2)/3.0, p);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::BezierCurveTo(float cp1x, float cp1y,
float cp2x, float cp2y,
float x, float y)
{
if (!FloatValidate(cp1x,cp1y,cp2x,cp2y,x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_curve_to(mCairo, cp1x, cp1y, cp2x, cp2y, x, y);
+ mThebes->CurveTo(gfxPoint(cp1x, cp1y),
+ gfxPoint(cp2x, cp2y),
+ gfxPoint(x, y));
+
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::ArcTo(float x1, float y1, float x2, float y2, float radius)
{
if (!FloatValidate(x1,y1,x2,y2,radius))
return NS_ERROR_DOM_SYNTAX_ERR;
@@ -1470,52 +1442,51 @@ nsCanvasRenderingContext2D::ArcTo(float
if (radius <= 0)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
/* This is an adaptation of the cairo_arc_to patch from Behdad
* Esfahbod; once that patch is accepted, we should remove this
* and just call cairo_arc_to() directly.
*/
- double x0, y0;
double angle0, angle1, angle2, angled;
double d0, d2;
double sin_, cos_;
- double xc, yc, dc;
+ double dc;
int forward;
- cairo_get_current_point(mCairo, &x0, &y0);
-
- angle0 = atan2 (y0 - y1, x0 - x1); /* angle from (x1,y1) to (x0,y0) */
+ gfxPoint p0 = mThebes->CurrentPoint();
+
+ angle0 = atan2 (p0.y - y1, p0.x - x1); /* angle from (x1,y1) to (p0.x,p0.y) */
angle2 = atan2 (y2 - y1, x2 - x1); /* angle from (x1,y1) to (x2,y2) */
angle1 = (angle0 + angle2) / 2; /* angle from (x1,y1) to (xc,yc) */
- angled = angle2 - angle0; /* the angle (x0,y0)--(x1,y1)--(x2,y2) */
+ angled = angle2 - angle0; /* the angle (p0.x,p0.y)--(x1,y1)--(x2,y2) */
/* Shall we go forward or backward? */
if (angled > M_PI || (angled < 0 && angled > -M_PI)) {
angle1 += M_PI;
angled = 2 * M_PI - angled;
forward = 1;
} else {
double tmp;
tmp = angle0;
angle0 = angle2;
angle2 = tmp;
forward = 0;
}
- angle0 += M_PI_2; /* angle from (xc,yc) to (x0,y0) */
+ angle0 += M_PI_2; /* angle from (xc,yc) to (p0.x,p0.y) */
angle2 -= M_PI_2; /* angle from (xc,yc) to (x2,y2) */
- angled /= 2; /* the angle (x0,y0)--(x1,y1)--(xc,yc) */
-
-
- /* distance from (x1,y1) to (x0,y0) */
- d0 = sqrt ((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
- /* distance from (x2,y2) to (x0,y0) */
+ angled /= 2; /* the angle (p0.x,p0.y)--(x1,y1)--(xc,yc) */
+
+
+ /* distance from (x1,y1) to (p0.x,p0.y) */
+ d0 = sqrt ((p0.x-x1)*(p0.x-x1)+(p0.y-y1)*(p0.y-y1));
+ /* distance from (x2,y2) to (p0.x,p0.y) */
d2 = sqrt ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
dc = -1;
sin_ = sin(angled);
cos_ = cos(angled);
if (fabs(cos_) >= 1e-5) { /* the arc may not fit */
/* min distance of end-points from corner */
double min_d = d0 < d2 ? d0 : d2;
@@ -1529,53 +1500,53 @@ nsCanvasRenderingContext2D::ArcTo(float
}
}
if (dc < 0)
dc = radius / sin_; /* distance of (xc,yc) from (x1,y1) */
/* find (cx,cy), the center of the arc */
- xc = x1 + sin(angle1) * dc;
- yc = y1 + cos(angle1) * dc;
-
-
- /* the arc operation draws the line from current point (x0,y0)
+ gfxPoint c(x1 + sin(angle1) * dc, y1 + cos(angle1) * dc);
+
+ /* the arc operation draws the line from current point (p0.x,p0.y)
* to arc center too. */
if (forward)
- cairo_arc (mCairo, xc, yc, radius, angle0, angle2);
+ mThebes->Arc(c, radius, angle0, angle2);
else
- cairo_arc_negative (mCairo, xc, yc, radius, angle2, angle0);
-
- cairo_line_to (mCairo, x2, y2);
+ mThebes->NegativeArc(c, radius, angle2, angle0);
+
+ mThebes->LineTo(gfxPoint(x2, y2));
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Arc(float x, float y, float r, float startAngle, float endAngle, int ccw)
{
if (!FloatValidate(x,y,r,startAngle,endAngle))
return NS_ERROR_DOM_SYNTAX_ERR;
+ gfxPoint p(x,y);
+
if (ccw)
- cairo_arc_negative (mCairo, x, y, r, startAngle, endAngle);
+ mThebes->NegativeArc(p, r, startAngle, endAngle);
else
- cairo_arc (mCairo, x, y, r, startAngle, endAngle);
+ mThebes->Arc(p, r, startAngle, endAngle);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Rect(float x, float y, float w, float h)
{
if (!FloatValidate(x,y,w,h))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_rectangle (mCairo, x, y, w, h);
+ mThebes->Rectangle(gfxRect(x, y, w, h));
return NS_OK;
}
//
// text
//
/**
@@ -1890,53 +1861,53 @@ nsCanvasRenderingContext2D::MeasureText(
*/
struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
{
virtual void SetText(const PRUnichar* text, PRInt32 length, nsBidiDirection direction)
{
mTextRun = gfxTextRunCache::MakeTextRun(text,
length,
mFontgrp,
- mCtx->mThebesContext,
+ mCtx->mThebes,
mAppUnitsPerDevPixel,
direction==NSBIDI_RTL ? gfxTextRunFactory::TEXT_IS_RTL : 0);
}
virtual nscoord GetWidth()
{
PRBool tightBoundingBox = PR_FALSE;
gfxTextRun::Metrics textRunMetrics = mTextRun->MeasureText(0,
mTextRun->GetLength(),
tightBoundingBox,
- mCtx->mThebesContext,
+ mCtx->mThebes,
nsnull);
return static_cast<nscoord>(textRunMetrics.mAdvanceWidth/gfxFloat(mAppUnitsPerDevPixel));
}
virtual void DrawText(nscoord xOffset, nscoord width)
{
gfxPoint point = mPt;
point.x += xOffset * mAppUnitsPerDevPixel;
// offset is given in terms of left side of string
if (mTextRun->IsRightToLeft())
point.x += width * mAppUnitsPerDevPixel;
// stroke or fill the text depending on operation
if (mOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_STROKE)
- mTextRun->DrawToPath(mCtx->mThebesContext,
+ mTextRun->DrawToPath(mCtx->mThebes,
point,
0,
mTextRun->GetLength(),
nsnull,
nsnull);
else
// mOp == TEXT_DRAW_OPERATION_FILL
- mTextRun->Draw(mCtx->mThebesContext,
+ mTextRun->Draw(mCtx->mThebes,
point,
0,
mTextRun->GetLength(),
nsnull,
nsnull,
nsnull);
}
@@ -2097,56 +2068,54 @@ nsCanvasRenderingContext2D::DrawOrMeasur
processor.mPt.y += anchorY;
processor.mPt.x *= processor.mAppUnitsPerDevPixel;
processor.mPt.y *= processor.mAppUnitsPerDevPixel;
// if text is over aMaxWidth, then scale the text horizontally such that its
// width is precisely aMaxWidth
if (aMaxWidth > 0 && totalWidth > aMaxWidth) {
- mThebesContext->Save();
+ mThebes->Save();
// translate the anchor point to 0, then scale and translate back
gfxPoint trans(aX, 0);
- mThebesContext->Translate(trans);
- mThebesContext->Scale(aMaxWidth/totalWidth, 1);
- mThebesContext->Translate(-trans);
+ mThebes->Translate(trans);
+ mThebes->Scale(aMaxWidth/totalWidth, 1);
+ mThebes->Translate(-trans);
}
- cairo_path_t* old_path;
+ nsRefPtr<gfxPath> path;
// back up path if stroking
if (aOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_STROKE)
- old_path = cairo_copy_path(mCairo);
+ path = mThebes->CopyPath();
else
ApplyStyle(STYLE_FILL);
rv = bidiUtils->ProcessText(textToDraw.get(),
textToDraw.Length(),
isRTL ? NSBIDI_RTL : NSBIDI_LTR,
presShell->GetPresContext(),
processor,
nsBidiPresUtils::MODE_DRAW,
nsnull,
0,
nsnull);
// stroke and restore path
if (aOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_STROKE) {
ApplyStyle(STYLE_STROKE);
- mThebesContext->Stroke();
-
- cairo_new_path(mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path(mCairo, old_path);
- cairo_path_destroy(old_path);
+ mThebes->Stroke();
+
+ mThebes->NewPath();
+ mThebes->AppendPath(path);
}
// have to restore the context if was modified for maxWidth
if (aMaxWidth > 0 && totalWidth > aMaxWidth)
- mThebesContext->Restore();
+ mThebes->Restore();
if (NS_FAILED(rv))
return rv;
return Redraw();
}
NS_IMETHODIMP
@@ -2184,29 +2153,29 @@ nsCanvasRenderingContext2D::MozDrawText(
PRUint32 aupdp;
GetAppUnitsValues(&aupdp, NULL);
gfxTextRunCache::AutoTextRun textRun;
textRun = gfxTextRunCache::MakeTextRun(textdata,
textToDraw.Length(),
GetCurrentFontStyle(),
- mThebesContext,
+ mThebes,
aupdp,
textrunflags);
if(!textRun.get())
return NS_ERROR_FAILURE;
gfxPoint pt(0.0f,0.0f);
// Fill color is text color
ApplyStyle(STYLE_FILL);
- textRun->Draw(mThebesContext,
+ textRun->Draw(mThebes,
pt,
/* offset = */ 0,
textToDraw.Length(),
nsnull,
nsnull,
nsnull);
return NS_OK;
}
@@ -2232,53 +2201,53 @@ nsCanvasRenderingContext2D::MozPathText(
PRUint32 aupdp;
GetAppUnitsValues(&aupdp, NULL);
gfxTextRunCache::AutoTextRun textRun;
textRun = gfxTextRunCache::MakeTextRun(textdata,
textToPath.Length(),
GetCurrentFontStyle(),
- mThebesContext,
+ mThebes,
aupdp,
textrunflags);
if(!textRun.get())
return NS_ERROR_FAILURE;
gfxPoint pt(0.0f,0.0f);
- textRun->DrawToPath(mThebesContext,
+ textRun->DrawToPath(mThebes,
pt,
/* offset = */ 0,
textToPath.Length(),
nsnull,
nsnull);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::MozTextAlongPath(const nsAString& textToDraw, PRBool stroke)
{
// Most of this code is copied from its svg equivalent
- nsRefPtr<gfxFlattenedPath> path(mThebesContext->GetFlattenedPath());
+ nsRefPtr<gfxFlattenedPath> path(mThebes->GetFlattenedPath());
const PRUnichar* textdata;
textToDraw.GetData(&textdata);
PRUint32 textrunflags = 0;
PRUint32 aupdp;
GetAppUnitsValues(&aupdp, NULL);
gfxTextRunCache::AutoTextRun textRun;
textRun = gfxTextRunCache::MakeTextRun(textdata,
textToDraw.Length(),
GetCurrentFontStyle(),
- mThebesContext,
+ mThebes,
aupdp,
textrunflags);
if(!textRun.get())
return NS_ERROR_FAILURE;
struct PathChar
{
@@ -2322,157 +2291,157 @@ nsCanvasRenderingContext2D::MozTextAlong
else
ApplyStyle(STYLE_FILL);
for(PRUint32 i = 0; i < strLength; i++)
{
// Skip non-visible characters
if(!cp[i].draw) continue;
- gfxMatrix matrix = mThebesContext->CurrentMatrix();
+ gfxMatrix matrix = mThebes->CurrentMatrix();
gfxMatrix rot;
rot.Rotate(cp[i].angle);
- mThebesContext->Multiply(rot);
+ mThebes->Multiply(rot);
rot.Invert();
rot.Scale(aupdp,aupdp);
gfxPoint pt = rot.Transform(cp[i].pos);
if(stroke) {
- textRun->DrawToPath(mThebesContext, pt, i, 1, nsnull, nsnull);
+ textRun->DrawToPath(mThebes, pt, i, 1, nsnull, nsnull);
} else {
- textRun->Draw(mThebesContext, pt, i, 1, nsnull, nsnull, nsnull);
+ textRun->Draw(mThebes, pt, i, 1, nsnull, nsnull, nsnull);
}
- mThebesContext->SetMatrix(matrix);
+ mThebes->SetMatrix(matrix);
}
delete [] cp;
return NS_OK;
}
//
// line caps/joins
//
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetLineWidth(float width)
{
if (!FloatValidate(width))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_set_line_width(mCairo, width);
+ mThebes->SetLineWidth(width);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetLineWidth(float *width)
{
- double d = cairo_get_line_width(mCairo);
- *width = (float) d;
+ gfxFloat d = mThebes->CurrentLineWidth();
+ *width = static_cast<float>(d);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetLineCap(const nsAString& capstyle)
{
- cairo_line_cap_t cap;
+ gfxContext::GraphicsLineCap cap;
if (capstyle.EqualsLiteral("butt"))
- cap = CAIRO_LINE_CAP_BUTT;
+ cap = gfxContext::LINE_CAP_BUTT;
else if (capstyle.EqualsLiteral("round"))
- cap = CAIRO_LINE_CAP_ROUND;
+ cap = gfxContext::LINE_CAP_ROUND;
else if (capstyle.EqualsLiteral("square"))
- cap = CAIRO_LINE_CAP_SQUARE;
+ cap = gfxContext::LINE_CAP_SQUARE;
else
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_NOT_IMPLEMENTED;
- cairo_set_line_cap (mCairo, cap);
+ mThebes->SetLineCap(cap);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetLineCap(nsAString& capstyle)
{
- cairo_line_cap_t cap = cairo_get_line_cap(mCairo);
-
- if (cap == CAIRO_LINE_CAP_BUTT)
+ gfxContext::GraphicsLineCap cap = mThebes->CurrentLineCap();
+
+ if (cap == gfxContext::LINE_CAP_BUTT)
capstyle.AssignLiteral("butt");
- else if (cap == CAIRO_LINE_CAP_ROUND)
+ else if (cap == gfxContext::LINE_CAP_ROUND)
capstyle.AssignLiteral("round");
- else if (cap == CAIRO_LINE_CAP_SQUARE)
+ else if (cap == gfxContext::LINE_CAP_SQUARE)
capstyle.AssignLiteral("square");
else
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetLineJoin(const nsAString& joinstyle)
{
- cairo_line_join_t j;
+ gfxContext::GraphicsLineJoin j;
if (joinstyle.EqualsLiteral("round"))
- j = CAIRO_LINE_JOIN_ROUND;
+ j = gfxContext::LINE_JOIN_ROUND;
else if (joinstyle.EqualsLiteral("bevel"))
- j = CAIRO_LINE_JOIN_BEVEL;
+ j = gfxContext::LINE_JOIN_BEVEL;
else if (joinstyle.EqualsLiteral("miter"))
- j = CAIRO_LINE_JOIN_MITER;
+ j = gfxContext::LINE_JOIN_MITER;
else
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_NOT_IMPLEMENTED;
- cairo_set_line_join (mCairo, j);
+ mThebes->SetLineJoin(j);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetLineJoin(nsAString& joinstyle)
{
- cairo_line_join_t j = cairo_get_line_join(mCairo);
-
- if (j == CAIRO_LINE_JOIN_ROUND)
+ gfxContext::GraphicsLineJoin j = mThebes->CurrentLineJoin();
+
+ if (j == gfxContext::LINE_JOIN_ROUND)
joinstyle.AssignLiteral("round");
- else if (j == CAIRO_LINE_JOIN_BEVEL)
+ else if (j == gfxContext::LINE_JOIN_BEVEL)
joinstyle.AssignLiteral("bevel");
- else if (j == CAIRO_LINE_JOIN_MITER)
+ else if (j == gfxContext::LINE_JOIN_MITER)
joinstyle.AssignLiteral("miter");
else
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetMiterLimit(float miter)
{
if (!FloatValidate(miter))
return NS_ERROR_DOM_SYNTAX_ERR;
- cairo_set_miter_limit(mCairo, miter);
+ mThebes->SetMiterLimit(miter);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetMiterLimit(float *miter)
{
- double d = cairo_get_miter_limit(mCairo);
- *miter = (float) d;
+ gfxFloat d = mThebes->CurrentMiterLimit();
+ *miter = static_cast<float>(d);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::IsPointInPath(float x, float y, PRBool *retVal)
{
if (!FloatValidate(x,y))
return NS_ERROR_DOM_SYNTAX_ERR;
- *retVal = !!cairo_in_fill(mCairo, x, y);
+ *retVal = mThebes->PointInFill(gfxPoint(x,y));
return NS_OK;
}
//
// image
//
// drawImage(in HTMLImageElement image, in float dx, in float dy);
@@ -2521,26 +2490,26 @@ nsCanvasRenderingContext2D::DrawImage()
double dx,dy,dw,dh;
nsCOMPtr<nsIDOMElement> imgElt;
if (!ConvertJSValToXPCObject(getter_AddRefs(imgElt),
NS_GET_IID(nsIDOMElement),
ctx, argv[0]))
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
- cairo_surface_t *imgSurf = nsnull;
- cairo_matrix_t surfMat;
- cairo_pattern_t *pat;
- cairo_path_t *old_path;
PRInt32 imgWidth, imgHeight;
nsCOMPtr<nsIPrincipal> principal;
PRBool forceWriteOnly = PR_FALSE;
- rv = CairoSurfaceFromElement(imgElt, PR_FALSE,
- &imgSurf, &imgWidth, &imgHeight,
- getter_AddRefs(principal), &forceWriteOnly);
+ gfxMatrix matrix;
+ nsRefPtr<gfxPattern> pattern;
+ nsRefPtr<gfxPath> path;
+ nsRefPtr<gfxASurface> imgsurf;
+ rv = ThebesSurfaceFromElement(imgElt, PR_FALSE,
+ getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
+ getter_AddRefs(principal), &forceWriteOnly);
if (NS_FAILED(rv))
return rv;
DoDrawImageSecurityCheck(principal, forceWriteOnly);
#define GET_ARG(dest,whicharg) \
do { if (!ConvertJSValToDouble(dest, ctx, whicharg)) { rv = NS_ERROR_INVALID_ARG; goto FINISH; } } while (0)
rv = NS_OK;
@@ -2592,121 +2561,112 @@ nsCanvasRenderingContext2D::DrawImage()
sw < 0.0 || sw > (double) imgWidth ||
sh < 0.0 || sh > (double) imgHeight ||
dw < 0.0 || dh < 0.0)
{
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
rv = NS_ERROR_DOM_INDEX_SIZE_ERR;
goto FINISH;
}
-
- cairo_matrix_init_translate(&surfMat, sx, sy);
- cairo_matrix_scale(&surfMat, sw/dw, sh/dh);
- pat = cairo_pattern_create_for_surface(imgSurf);
- cairo_pattern_set_matrix(pat, &surfMat);
-
- old_path = cairo_copy_path(mCairo);
- cairo_save(mCairo);
- cairo_translate(mCairo, dx, dy);
- cairo_new_path(mCairo);
- cairo_rectangle(mCairo, 0, 0, dw, dh);
- cairo_set_source(mCairo, pat);
- cairo_clip(mCairo);
- cairo_paint_with_alpha(mCairo, CurrentState().globalAlpha);
- cairo_restore(mCairo);
+
+ matrix.Translate(gfxPoint(sx, sy));
+ matrix.Scale(sw/dw, sh/dh);
+
+ pattern = new gfxPattern(imgsurf);
+ pattern->SetMatrix(matrix);
+
+ path = mThebes->CopyPath();
+
+ mThebes->Save();
+ mThebes->Translate(gfxPoint(dx, dy));
+ mThebes->SetPattern(pattern);
+ mThebes->Clip(gfxRect(0, 0, dw, dh));
+ mThebes->Paint(CurrentState().globalAlpha);
+ mThebes->Restore();
#if 1
- // XXX cairo bug workaround; force a clip update on mCairo.
+ // XXX cairo bug workaround; force a clip update on mThebes.
// Otherwise, a pixman clip gets left around somewhere, and pixman
// (Render) does source clipping as well -- so we end up
// compositing with an incorrect clip. This only seems to affect
// fallback cases, which happen when we have CSS scaling going on.
// This will blow away the current path, but we already blew it
// away in this function earlier.
- cairo_new_path(mCairo);
- cairo_rectangle(mCairo, 0, 0, 0, 0);
- cairo_fill(mCairo);
+ mThebes->UpdateSurfaceClip();
#endif
- cairo_pattern_destroy(pat);
-
- cairo_new_path(mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path(mCairo, old_path);
- cairo_path_destroy(old_path);
+ mThebes->NewPath();
+ mThebes->AppendPath(path);
FINISH:
- if (imgSurf)
- cairo_surface_destroy(imgSurf);
-
if (NS_SUCCEEDED(rv))
rv = Redraw();
return rv;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op)
{
- cairo_operator_t cairo_op;
-
-#define CANVAS_OP_TO_CAIRO_OP(cvsop,cairoop) \
+ gfxContext::GraphicsOperator thebes_op;
+
+#define CANVAS_OP_TO_THEBES_OP(cvsop,thebesop) \
if (op.EqualsLiteral(cvsop)) \
- cairo_op = CAIRO_OPERATOR_##cairoop;
+ thebes_op = gfxContext::OPERATOR_##thebesop;
// XXX "darker" isn't really correct
- CANVAS_OP_TO_CAIRO_OP("clear", CLEAR)
- else CANVAS_OP_TO_CAIRO_OP("copy", SOURCE)
- else CANVAS_OP_TO_CAIRO_OP("darker", SATURATE) // XXX
- else CANVAS_OP_TO_CAIRO_OP("destination-atop", DEST_ATOP)
- else CANVAS_OP_TO_CAIRO_OP("destination-in", DEST_IN)
- else CANVAS_OP_TO_CAIRO_OP("destination-out", DEST_OUT)
- else CANVAS_OP_TO_CAIRO_OP("destination-over", DEST_OVER)
- else CANVAS_OP_TO_CAIRO_OP("lighter", ADD)
- else CANVAS_OP_TO_CAIRO_OP("source-atop", ATOP)
- else CANVAS_OP_TO_CAIRO_OP("source-in", IN)
- else CANVAS_OP_TO_CAIRO_OP("source-out", OUT)
- else CANVAS_OP_TO_CAIRO_OP("source-over", OVER)
- else CANVAS_OP_TO_CAIRO_OP("xor", XOR)
+ CANVAS_OP_TO_THEBES_OP("clear", CLEAR)
+ else CANVAS_OP_TO_THEBES_OP("copy", SOURCE)
+ else CANVAS_OP_TO_THEBES_OP("darker", SATURATE) // XXX
+ else CANVAS_OP_TO_THEBES_OP("destination-atop", DEST_ATOP)
+ else CANVAS_OP_TO_THEBES_OP("destination-in", DEST_IN)
+ else CANVAS_OP_TO_THEBES_OP("destination-out", DEST_OUT)
+ else CANVAS_OP_TO_THEBES_OP("destination-over", DEST_OVER)
+ else CANVAS_OP_TO_THEBES_OP("lighter", ADD)
+ else CANVAS_OP_TO_THEBES_OP("source-atop", ATOP)
+ else CANVAS_OP_TO_THEBES_OP("source-in", IN)
+ else CANVAS_OP_TO_THEBES_OP("source-out", OUT)
+ else CANVAS_OP_TO_THEBES_OP("source-over", OVER)
+ else CANVAS_OP_TO_THEBES_OP("xor", XOR)
// not part of spec, kept here for compat
- else CANVAS_OP_TO_CAIRO_OP("over", OVER)
+ else CANVAS_OP_TO_THEBES_OP("over", OVER)
else return NS_ERROR_NOT_IMPLEMENTED;
-#undef CANVAS_OP_TO_CAIRO_OP
-
- cairo_set_operator(mCairo, cairo_op);
+#undef CANVAS_OP_TO_THEBES_OP
+
+ mThebes->SetOperator(thebes_op);
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op)
{
- cairo_operator_t cairo_op = cairo_get_operator(mCairo);
-
-#define CANVAS_OP_TO_CAIRO_OP(cvsop,cairoop) \
- if (cairo_op == CAIRO_OPERATOR_##cairoop) \
+ gfxContext::GraphicsOperator thebes_op = mThebes->CurrentOperator();
+
+#define CANVAS_OP_TO_THEBES_OP(cvsop,thebesop) \
+ if (thebes_op == gfxContext::OPERATOR_##thebesop) \
op.AssignLiteral(cvsop);
// XXX "darker" isn't really correct
- CANVAS_OP_TO_CAIRO_OP("clear", CLEAR)
- else CANVAS_OP_TO_CAIRO_OP("copy", SOURCE)
- else CANVAS_OP_TO_CAIRO_OP("darker", SATURATE) // XXX
- else CANVAS_OP_TO_CAIRO_OP("destination-atop", DEST_ATOP)
- else CANVAS_OP_TO_CAIRO_OP("destination-in", DEST_IN)
- else CANVAS_OP_TO_CAIRO_OP("destination-out", DEST_OUT)
- else CANVAS_OP_TO_CAIRO_OP("destination-over", DEST_OVER)
- else CANVAS_OP_TO_CAIRO_OP("lighter", ADD)
- else CANVAS_OP_TO_CAIRO_OP("source-atop", ATOP)
- else CANVAS_OP_TO_CAIRO_OP("source-in", IN)
- else CANVAS_OP_TO_CAIRO_OP("source-out", OUT)
- else CANVAS_OP_TO_CAIRO_OP("source-over", OVER)
- else CANVAS_OP_TO_CAIRO_OP("xor", XOR)
+ CANVAS_OP_TO_THEBES_OP("clear", CLEAR)
+ else CANVAS_OP_TO_THEBES_OP("copy", SOURCE)
+ else CANVAS_OP_TO_THEBES_OP("darker", SATURATE) // XXX
+ else CANVAS_OP_TO_THEBES_OP("destination-atop", DEST_ATOP)
+ else CANVAS_OP_TO_THEBES_OP("destination-in", DEST_IN)
+ else CANVAS_OP_TO_THEBES_OP("destination-out", DEST_OUT)
+ else CANVAS_OP_TO_THEBES_OP("destination-over", DEST_OVER)
+ else CANVAS_OP_TO_THEBES_OP("lighter", ADD)
+ else CANVAS_OP_TO_THEBES_OP("source-atop", ATOP)
+ else CANVAS_OP_TO_THEBES_OP("source-in", IN)
+ else CANVAS_OP_TO_THEBES_OP("source-out", OUT)
+ else CANVAS_OP_TO_THEBES_OP("source-over", OVER)
+ else CANVAS_OP_TO_THEBES_OP("xor", XOR)
else return NS_ERROR_FAILURE;
-#undef CANVAS_OP_TO_CAIRO_OP
+#undef CANVAS_OP_TO_THEBES_OP
return NS_OK;
}
//
// Utils
//
@@ -2757,32 +2717,32 @@ nsCanvasRenderingContext2D::ConvertJSVal
WrapJS(aContext, JSVAL_TO_OBJECT(aValue), aIID, (void**)aSupports);
return NS_SUCCEEDED(rv);
}
return JS_FALSE;
}
-/* cairo ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
+/* thebes ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
* platforms, they appear as BGRA bytes in the surface data. The color values are also
* stored with premultiplied alpha.
*
* If forceCopy is FALSE, a surface may be returned that's only valid during the current
* operation. If it's TRUE, a copy will always be made that can safely be retained.
*/
nsresult
-nsCanvasRenderingContext2D::CairoSurfaceFromElement(nsIDOMElement *imgElt,
- PRBool forceCopy,
- cairo_surface_t **aCairoSurface,
- PRInt32 *widthOut,
- PRInt32 *heightOut,
- nsIPrincipal **prinOut,
- PRBool *forceWriteOnlyOut)
+nsCanvasRenderingContext2D::ThebesSurfaceFromElement(nsIDOMElement *imgElt,
+ PRBool forceCopy,
+ gfxASurface **aSurface,
+ PRInt32 *widthOut,
+ PRInt32 *heightOut,
+ nsIPrincipal **prinOut,
+ PRBool *forceWriteOnlyOut)
{
nsresult rv;
nsCOMPtr<imgIContainer> imgContainer;
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(imgElt);
if (imageLoader) {
nsCOMPtr<imgIRequest> imgRequest;
@@ -2818,17 +2778,17 @@ nsCanvasRenderingContext2D::CairoSurface
nsRefPtr<gfxASurface> sourceSurface;
if (!forceCopy && canvas->CountContexts() == 1) {
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
rv = srcCanvas->GetThebesSurface(getter_AddRefs(sourceSurface));
// force a copy if we couldn't get the surface, or if it's
// the same as what we have
- if (sourceSurface == mThebesSurface || NS_FAILED(rv))
+ if (sourceSurface == mSurface || NS_FAILED(rv))
sourceSurface = nsnull;
}
if (sourceSurface == nsnull) {
nsRefPtr<gfxASurface> surf =
gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
@@ -2840,18 +2800,17 @@ nsCanvasRenderingContext2D::CairoSurface
ctx->SetOperator(gfxContext::OPERATOR_OVER);
rv = canvas->RenderContexts(ctx);
if (NS_FAILED(rv))
return rv;
sourceSurface = surf;
}
- *aCairoSurface = sourceSurface->CairoSurface();
- cairo_surface_reference(*aCairoSurface);
+ *aSurface = sourceSurface.forget().get();
*widthOut = w;
*heightOut = h;
NS_ADDREF(*prinOut = node->NodePrincipal());
*forceWriteOnlyOut = canvas->IsWriteOnly();
return NS_OK;
} else {
@@ -2888,18 +2847,17 @@ nsCanvasRenderingContext2D::CairoSurface
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);
+ *aSurface = gfxsurf.forget().get();
return NS_OK;
}
/* Check that the rect [x,y,w,h] is a valid subrect of [0,0,realWidth,realHeight]
* without overflowing any integers and the like.
*/
PRBool
@@ -2995,20 +2953,20 @@ nsCanvasRenderingContext2D::DrawWindow(n
nsIPresShell* presShell = presContext->PresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
nsRect r(nsPresContext::CSSPixelsToAppUnits(aX),
nsPresContext::CSSPixelsToAppUnits(aY),
nsPresContext::CSSPixelsToAppUnits(aW),
nsPresContext::CSSPixelsToAppUnits(aH));
presShell->RenderDocument(r, PR_FALSE, PR_TRUE, bgColor,
- mThebesContext);
+ mThebes);
// get rid of the pattern surface ref, just in case
- cairo_set_source_rgba (mCairo, 1, 1, 1, 1);
+ mThebes->SetColor(gfxRGBA(1,1,1,1));
DirtyAllStyles();
Redraw();
return rv;
}
//
@@ -3057,25 +3015,34 @@ nsCanvasRenderingContext2D::GetImageData
nsAutoArrayPtr<PRUint8> surfaceData (new (std::nothrow) PRUint8[w * h * 4]);
int surfaceDataStride = w*4;
int surfaceDataOffset = 0;
if (!surfaceData)
return NS_ERROR_OUT_OF_MEMORY;
- cairo_surface_t *tmpsurf = cairo_image_surface_create_for_data (surfaceData,
- CAIRO_FORMAT_ARGB32,
- w, h, w*4);
- cairo_t *tmpcr = cairo_create (tmpsurf);
- cairo_set_operator (tmpcr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_surface (tmpcr, mSurface, -(int)x, -(int)y);
- cairo_paint (tmpcr);
- cairo_destroy (tmpcr);
- cairo_surface_destroy (tmpsurf);
+ nsRefPtr<gfxImageSurface> tmpsurf = new gfxImageSurface(surfaceData,
+ gfxIntSize(w, h),
+ w * 4,
+ gfxASurface::ImageFormatARGB32);
+ if (!tmpsurf || tmpsurf->CairoStatus())
+ return NS_ERROR_FAILURE;
+
+ nsRefPtr<gfxContext> tmpctx = new gfxContext(tmpsurf);
+
+ if (!tmpctx || tmpctx->HasError())
+ return NS_ERROR_FAILURE;
+
+ tmpctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+ tmpctx->SetSource(mSurface, gfxPoint(-(int)x, -(int)y));
+ tmpctx->Paint();
+
+ tmpctx = nsnull;
+ tmpsurf = nsnull;
PRUint32 len = w * h * 4;
if (len > (((PRUint32)0xfff00000)/sizeof(jsval)))
return NS_ERROR_INVALID_ARG;
nsAutoArrayPtr<jsval> jsvector(new (std::nothrow) jsval[w * h * 4]);
if (!jsvector)
return NS_ERROR_OUT_OF_MEMORY;
@@ -3202,17 +3169,16 @@ nsCanvasRenderingContext2D::PutImageData
!JS_GetArrayLength(ctx, dataArray, &arrayLen) ||
arrayLen < (jsuint)(w * h * 4))
return NS_ERROR_DOM_SYNTAX_ERR;
nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[w * h * 4]);
if (!imageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
- cairo_surface_t *imgsurf;
PRUint8 *imgPtr = imageBuffer.get();
jsval vr, vg, vb, va;
PRUint8 ir, ig, ib, ia;
for (int32 j = 0; j < h; j++) {
for (int32 i = 0; i < w; i++) {
if (!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 0, &vr) ||
!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 1, &vg) ||
!JS_GetElement(ctx, dataArray, (j*w*4) + i*4 + 2, &vb) ||
@@ -3250,45 +3216,47 @@ nsCanvasRenderingContext2D::PutImageData
*imgPtr++ = ia;
*imgPtr++ = ir;
*imgPtr++ = ig;
*imgPtr++ = ib;
#endif
}
}
- imgsurf = cairo_image_surface_create_for_data (imageBuffer.get(),
- CAIRO_FORMAT_ARGB32,
- w, h, w*4);
- cairo_path_t *old_path = cairo_copy_path (mCairo);
- cairo_save (mCairo);
- cairo_identity_matrix (mCairo);
- cairo_translate (mCairo, x, y);
- cairo_new_path (mCairo);
- cairo_rectangle (mCairo, 0, 0, w, h);
- cairo_set_source_surface (mCairo, imgsurf, 0, 0);
- cairo_set_operator (mCairo, CAIRO_OPERATOR_SOURCE);
- cairo_fill (mCairo);
- cairo_restore (mCairo);
- cairo_new_path (mCairo);
- if (old_path->status == CAIRO_STATUS_SUCCESS && old_path->num_data != 0)
- cairo_append_path (mCairo, old_path);
- cairo_path_destroy (old_path);
-
- cairo_surface_destroy (imgsurf);
+ nsRefPtr<gfxImageSurface> imgsurf = new gfxImageSurface(imageBuffer.get(),
+ gfxIntSize(w, h),
+ w * 4,
+ gfxASurface::ImageFormatARGB32);
+ if (!imgsurf || imgsurf->CairoStatus())
+ return NS_ERROR_FAILURE;
+
+ nsRefPtr<gfxPath> path = mThebes->CopyPath();
+
+ mThebes->Save();
+ mThebes->IdentityMatrix();
+ mThebes->Translate(gfxPoint(x, y));
+ mThebes->NewPath();
+ mThebes->Rectangle(gfxRect(0, 0, w, h));
+ mThebes->SetSource(imgsurf, gfxPoint(0, 0));
+ mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
+ mThebes->Fill();
+ mThebes->Restore();
+
+ mThebes->NewPath();
+ mThebes->AppendPath(path);
return Redraw();
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::GetThebesSurface(gfxASurface **surface)
{
- if (!mThebesSurface) {
+ if (!mSurface) {
*surface = nsnull;
return NS_ERROR_NOT_AVAILABLE;
}
- *surface = mThebesSurface.get();
+ *surface = mSurface.get();
NS_ADDREF(*surface);
return NS_OK;
}