Bug 282026 - use appropriate transform when drawing objectBoundingBox

dimensioned gradients.  r=scooter
This commit is contained in:
tor%cs.brown.edu 2005-02-18 23:17:48 +00:00
parent b4fca87aba
commit aa09f6e30d
14 changed files with 116 additions and 131 deletions

View File

@ -58,6 +58,10 @@
#include "nsStyleContext.h"
#include "nsNetUtil.h"
#include "nsINameSpaceManager.h"
#include "nsISVGChildFrame.h"
#include "nsIDOMSVGRect.h"
#include "nsSVGMatrix.h"
#include "nsISVGGeometrySource.h"
nsresult NS_NewSVGGenericContainerFrame(nsIPresShell *aPresShell, nsIContent *aContent, nsIFrame **aNewFrame);
static nsresult GetSVGGradient(nsISVGGradient **result, nsCAutoString& aSpec,
@ -302,25 +306,60 @@ nsSVGGradientFrame::GetGradientUnits(PRUint16 *aUnits)
}
NS_IMETHODIMP
nsSVGGradientFrame::GetGradientTransform(nsIDOMSVGMatrix **aGradientTransform)
nsSVGGradientFrame::GetGradientTransform(nsIDOMSVGMatrix **aGradientTransform,
nsISVGGeometrySource *aSource)
{
*aGradientTransform = nsnull;
nsCOMPtr<nsIDOMSVGAnimatedTransformList> aTrans;
nsCOMPtr<nsIDOMSVGGradientElement> aGrad = do_QueryInterface(mContent);
NS_ASSERTION(aGrad, "Wrong content element (not gradient)");
if (aGrad == nsnull) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMSVGMatrix> bboxTransform;
PRUint16 bbox;
GetGradientUnits(&bbox);
if (bbox == nsIDOMSVGGradientElement::SVG_GRUNITS_OBJECTBOUNDINGBOX) {
nsISVGChildFrame *frame = nsnull;
if (aSource)
CallQueryInterface(aSource, &frame);
nsCOMPtr<nsIDOMSVGRect> rect;
if (frame) {
frame->SetMatrixPropagation(PR_FALSE);
frame->NotifyCanvasTMChanged();
frame->GetBBox(getter_AddRefs(rect));
frame->SetMatrixPropagation(PR_TRUE);
frame->NotifyCanvasTMChanged();
}
if (rect) {
float x, y, width, height;
rect->GetX(&x);
rect->GetY(&y);
rect->GetWidth(&width);
rect->GetHeight(&height);
NS_NewSVGMatrix(getter_AddRefs(bboxTransform),
width, 0, 0, height, x, y);
}
}
if (!bboxTransform)
NS_NewSVGMatrix(getter_AddRefs(bboxTransform));
nsCOMPtr<nsIDOMSVGMatrix> gradientTransform;
// See if we need to get the value from another gradient
if (!checkURITarget(nsSVGAtoms::gradientTransform)) {
// No, return the values
aGrad->GetGradientTransform(getter_AddRefs(aTrans));
nsCOMPtr<nsIDOMSVGTransformList> lTrans;
aTrans->GetAnimVal(getter_AddRefs(lTrans));
lTrans->GetConsolidationMatrix(aGradientTransform);
lTrans->GetConsolidationMatrix(getter_AddRefs(gradientTransform));
} else {
// Yes, get it from the target
mNextGrad->GetGradientTransform(aGradientTransform);
mNextGrad->GetGradientTransform(getter_AddRefs(gradientTransform), nsnull);
}
bboxTransform->Multiply(gradientTransform, aGradientTransform);
return NS_OK;
}

View File

@ -49,6 +49,7 @@ interface nsIDOMSVGMatrix;
interface nsISVGLinearGradient;
interface nsISVGRadialGradient;
interface nsIFrame;
interface nsISVGGeometrySource;
/**
* \addtogroup rendering_backend_interfaces Rendering Backend Interfaces
@ -61,7 +62,7 @@ interface nsIFrame;
*
* @nosubgrouping
*/
[uuid(e56bc6e1-26ea-4e30-afec-531a53179022)]
[uuid(ba84ad21-3ffb-465d-9321-b080105f8608)]
interface nsISVGGradient : nsISupports
{
const unsigned long SVG_UNKNOWN_GRADIENT = 0;
@ -70,7 +71,6 @@ interface nsISVGGradient : nsISupports
readonly attribute PRUint32 gradientType;
readonly attribute PRUint16 gradientUnits;
readonly attribute nsIDOMSVGMatrix gradientTransform;
readonly attribute PRUint16 spreadMethod;
void GetStopCount(out PRUint32 aStopCount);
@ -78,7 +78,9 @@ interface nsISVGGradient : nsISupports
void GetStopColorType(in PRInt32 aIndex, out PRUint16 aStopColorType);
void GetStopColor(in PRInt32 aIndex, out nscolor aStopColor);
void GetStopOpacity(in PRInt32 aIndex, out float aStopOpacity);
void GetNextGradient (out nsISVGGradient aNextGrad, in PRUint32 aType);
void GetNextGradient(out nsISVGGradient aNextGrad, in PRUint32 aType);
void GetGradientTransform(out nsIDOMSVGMatrix retval,
in nsISVGGeometrySource aSource);
/** @} */
};

View File

@ -245,12 +245,7 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGGradient> aGrad;
mSource->GetFillGradient(getter_AddRefs(aGrad));
cairo_text_extents_t extents;
cairo_text_extents(ctx,
(unsigned char*)NS_ConvertUCS2toUTF8(text).get(),
&extents);
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, &extents);
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);
cairo_set_pattern(ctx, gradient);
cairo_show_text(ctx, (unsigned char*)NS_ConvertUCS2toUTF8(text).get());
cairo_pattern_destroy(gradient);
@ -327,7 +322,7 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGGradient> aGrad;
mSource->GetStrokeGradient(getter_AddRefs(aGrad));
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad);
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);
cairo_set_pattern(ctx, gradient);
cairo_stroke(ctx);
cairo_pattern_destroy(gradient);

View File

@ -120,50 +120,24 @@ CairoRadialGradient(cairo_t *ctx, nsISVGGradient *aGrad)
aRgrad->GetFx(&fFx);
aRgrad->GetFy(&fFy);
return cairo_pattern_create_radial(fCx, fCy, 0, fFx, fFy, fR);
return cairo_pattern_create_radial(fFx, fFy, 0, fCx, fCy, fR);
}
cairo_pattern_t *
CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, cairo_text_extents_t *extent)
CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad,
nsISVGGeometrySource *aSource)
{
NS_ASSERTION(aGrad, "Called CairoGradient without a gradient!");
if (!aGrad)
return NULL;
// Get the gradientUnits
PRUint16 bbox;
aGrad->GetGradientUnits(&bbox);
cairo_matrix_t *patternMatrix = cairo_matrix_create();
if (bbox == nsIDOMSVGGradientElement::SVG_GRUNITS_OBJECTBOUNDINGBOX) {
// BoundingBox
// We need to calculate this from the Region (Uta?) in
// the object we're filling
double x1, x2, y1, y2;
if (!extent) {
cairo_fill_extents(ctx, &x1, &y1, &x2, &y2);
} else {
x1 = extent->x_bearing;
y1 = extent->y_bearing;
x2 = extent->x_bearing + extent->width;
y2 = extent->y_bearing + extent->height;
}
cairo_matrix_set_affine(patternMatrix, x2 - x1, 0, 0, y2 - y1, x1, y1);
} else {
cairo_matrix_set_identity(patternMatrix);
}
// Get the transform list (if there is one)
nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix));
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix), aSource);
NS_ASSERTION(svgMatrix, "CairoGradient: GetGradientTransform returns null");
cairo_matrix_t *aTransMatrix = SVGToMatrix(svgMatrix);
cairo_matrix_multiply(patternMatrix, aTransMatrix, patternMatrix);
cairo_matrix_destroy(aTransMatrix);
cairo_matrix_t *patternMatrix = SVGToMatrix(svgMatrix);
cairo_pattern_t *gradient;
@ -192,4 +166,3 @@ CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, cairo_text_extents_t *extent)
return gradient;
}

View File

@ -48,6 +48,6 @@
cairo_pattern_t *
CairoGradient(cairo_t *ctx,
nsISVGGradient *aGrad,
cairo_text_extents_t *extent=NULL);
nsISVGGeometrySource *aSource);
#endif

View File

@ -321,7 +321,7 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGGradient> aGrad;
mSource->GetFillGradient(getter_AddRefs(aGrad));
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad);
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);
cairo_set_pattern(ctx, gradient);
cairo_fill(ctx);
cairo_pattern_destroy(gradient);
@ -348,7 +348,7 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGGradient> aGrad;
mSource->GetStrokeGradient(getter_AddRefs(aGrad));
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad);
cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource);
cairo_set_pattern(ctx, gradient);
cairo_stroke(ctx);
cairo_pattern_destroy(gradient);

View File

@ -215,6 +215,7 @@ class nsSVGGDIPlusGlyphGeometry : public nsISVGRendererGlyphGeometry
protected:
friend nsresult NS_NewSVGGDIPlusGlyphGeometry(nsISVGRendererGlyphGeometry **result,
nsISVGGlyphGeometrySource *src);
friend void gradCBPath(Graphics *gfx, Brush *brush, void *cbStruct);
nsSVGGDIPlusGlyphGeometry();
~nsSVGGDIPlusGlyphGeometry();
@ -226,7 +227,7 @@ public:
// nsISVGRendererGlyphGeometry interface:
NS_DECL_NSISVGRENDERERGLYPHGEOMETRY
protected:
void DrawFill(Graphics* g, Brush& b, nsISVGGradient *aGrad,
const WCHAR* start, INT length, float x, float y);
@ -303,8 +304,8 @@ NS_INTERFACE_MAP_END
static void gradCBPath(Graphics *gfx, Brush *brush, void *cbStruct)
{
GraphicsPath *path = (GraphicsPath *)cbStruct;
gfx->FillPath(brush, path);
nsSVGGDIPlusGlyphGeometry *geom = (nsSVGGDIPlusGlyphGeometry *)cbStruct;
gfx->FillPath(brush, geom->mStroke);
}
/** Implements void render(in nsISVGRendererCanvas canvas); */
@ -456,8 +457,8 @@ nsSVGGDIPlusGlyphGeometry::Render(nsISVGRendererCanvas *canvas)
mSource->GetCanvasTM(getter_AddRefs(ctm));
GDIPlusGradient(aRegion, aGrad, ctm,
gdiplusCanvas->GetGraphics(),
gradCBPath, mStroke);
gdiplusCanvas->GetGraphics(), mSource,
gradCBPath, this);
}
}
else {
@ -612,7 +613,7 @@ nsSVGGDIPlusGlyphGeometry::DrawFill(Graphics* g, Brush& b, nsISVGGradient *aGrad
cb.x = x; cb.y = y;
cb.stringformat = &stringFormat;
GDIPlusGradient(aRegion, aGrad, ctm, g, gradCBString, &cb);
GDIPlusGradient(aRegion, aGrad, ctm, g, mSource, gradCBString, &cb);
}
else
g->DrawString(start, length, metrics->GetFont(), PointF(x,y),

View File

@ -131,12 +131,15 @@ GDIPlusGetStops(nsISVGGradient *aGrad, Color **aColors, REAL **aPositions,
(*aPositions)[i] = 1.0f - (*aPositions)[*aStops - 1 - i];
(*aPositions)[*aStops - 1 - i] = 1.0f - tmpOffset;
}
// need to flip position of center color
if (*aStops & 1)
(*aPositions)[*aStops / 2] = 1.0f - (*aPositions)[*aStops / 2];
}
}
static void
GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix,
Graphics *aGFX, Matrix *aCTM,
void(*aCallback)(Graphics *, Brush*, void *), void *aData)
{
float fX1, fY1, fX2, fY2;
@ -172,6 +175,7 @@ GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
delete [] stopsPos;
gradient.MultiplyTransform(aMatrix, MatrixOrderAppend);
gradient.MultiplyTransform(aCTM, MatrixOrderAppend);
if (aSpread == nsIDOMSVGGradientElement::SVG_SPREADMETHOD_PAD) {
float dx = fX2 - fX1;
@ -181,19 +185,16 @@ GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
#define INF 100
PointF rect[4];
rect[0].X = fX1 + dy; rect[0].Y = fY1 - dx;
rect[1].X = fX2 + dy; rect[1].Y = fY2 - dx;
rect[2].X = fX2 - dy; rect[2].Y = fY2 + dx;
rect[3].X = fX1 - dy; rect[3].Y = fY1 + dx;
GraphicsPath left;
left.StartFigure();
rect[0].X = fX1 + INF * dy; rect[0].Y = fY1 - INF * dx;
rect[0].X = fX1 + INF * dy; rect[0].Y = fY1 - INF * dx;
rect[1].X = fX1 + INF * dx + INF * dy; rect[1].Y = fY1 + INF * dy - INF * dx;
rect[2].X = fX1 + INF * dx - INF * dy; rect[2].Y = fY1 + INF * dy + INF * dx;
rect[3].X = fX1 - INF * dy; rect[3].Y = fY1 + INF * dx;
rect[3].X = fX1 - INF * dy; rect[3].Y = fY1 + INF * dx;
left.AddPolygon(rect, 4);
left.Transform(aMatrix);
left.Transform(aCTM);
GraphicsPath center;
center.StartFigure();
@ -203,15 +204,17 @@ GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
rect[3].X = fX1 - INF * dy; rect[3].Y = fY1 + INF * dx;
center.AddPolygon(rect, 4);
center.Transform(aMatrix);
center.Transform(aCTM);
GraphicsPath right;
right.StartFigure();
rect[0].X = fX2 - INF * dx + INF * dy; rect[0].Y = fY2 - INF * dy - INF * dx;
rect[1].X = fX2 + INF * dy; rect[1].Y = fY2 - INF * dx;
rect[2].X = fX2 - INF * dy; rect[2].Y = fY2 + INF * dx;
rect[1].X = fX2 + INF * dy; rect[1].Y = fY2 - INF * dx;
rect[2].X = fX2 - INF * dy; rect[2].Y = fY2 + INF * dx;
rect[3].X = fX2 - INF * dx - INF * dy; rect[3].Y = fY2 - INF * dy + INF * dx;
right.AddPolygon(rect, 4);
right.Transform(aMatrix);
right.Transform(aCTM);
Region leftRegion(&left), centerRegion(&center), rightRegion(&right), oldClip;
aGFX->GetClip(&oldClip);
@ -233,7 +236,8 @@ GDIPlusLinearGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
}
static void
GDIPlusRadialGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
GDIPlusRadialGradient(nsISVGGradient *aGrad, Matrix *aMatrix,
Graphics *aGFX, Matrix *aCTM,
void(*aCallback)(Graphics *, Brush*, void *), void *aData)
{
float fCx, fCy, fR, fFx, fFy;
@ -274,9 +278,11 @@ GDIPlusRadialGradient(nsISVGGradient *aGrad, Matrix *aMatrix, Graphics *aGFX,
delete [] stopsPos;
gradient.MultiplyTransform(aMatrix, MatrixOrderAppend);
gradient.MultiplyTransform(aCTM, MatrixOrderAppend);
if (aSpread == nsIDOMSVGGradientElement::SVG_SPREADMETHOD_PAD) {
circle.Transform(aMatrix);
circle.Transform(aCTM);
Region exclude(&circle), oldClip;
aGFX->GetClip(&oldClip);
@ -293,6 +299,7 @@ void
GDIPlusGradient(nsISVGGDIPlusRegion *aRegion, nsISVGGradient *aGrad,
nsIDOMSVGMatrix *aCTM,
Graphics *aGFX,
nsISVGGeometrySource *aSource,
void(*aCallback)(Graphics *, Brush*, void *), void *aData)
{
NS_ASSERTION(aGrad, "Called GDIPlusGradient without a gradient!");
@ -303,38 +310,22 @@ GDIPlusGradient(nsISVGGDIPlusRegion *aRegion, nsISVGGradient *aGrad,
PRUint16 bbox;
aGrad->GetGradientUnits(&bbox);
Matrix *patternMatrix;
if (bbox == nsIDOMSVGGradientElement::SVG_GRUNITS_OBJECTBOUNDINGBOX) {
// BoundingBox
// We need to calculate this from the Region (Uta?) in
// the object we're filling
const RectF *rect = aRegion->GetRect();
#ifdef DEBUG_tor
printf("In GDIPlusGradient: bbox (%f, %f %f x %f)\n",
rect->X, rect->Y, rect->Width, rect->Height);
#endif
patternMatrix = new Matrix(rect->Width, 0, 0, rect->Height, rect->X, rect->Y);
} else {
patternMatrix = SVGToMatrix(aCTM);
}
// Get the transform list (if there is one)
nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix));
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix), aSource);
NS_ASSERTION(svgMatrix, "GDIPlusGradient: GetGradientTransform returns null");
Matrix *aTransMatrix = SVGToMatrix(svgMatrix);
patternMatrix->Multiply(aTransMatrix);
delete aTransMatrix;
Matrix *patternMatrix = SVGToMatrix(svgMatrix);
Matrix *ctm = SVGToMatrix(aCTM);
// Linear or Radial?
PRUint32 type;
aGrad->GetGradientType(&type);
if (type == nsISVGGradient::SVG_LINEAR_GRADIENT)
GDIPlusLinearGradient(aGrad, patternMatrix, aGFX, aCallback, aData);
GDIPlusLinearGradient(aGrad, patternMatrix, aGFX, ctm, aCallback, aData);
else if (type == nsISVGGradient::SVG_RADIAL_GRADIENT)
GDIPlusRadialGradient(aGrad, patternMatrix, aGFX, aCallback, aData);
GDIPlusRadialGradient(aGrad, patternMatrix, aGFX, ctm, aCallback, aData);
delete patternMatrix;
delete ctm;
}

View File

@ -39,9 +39,10 @@
#include "nsISVGGradient.h"
#include "nsISVGGDIPlusRegion.h"
#include "nsISVGGeometrySource.h"
void GDIPlusGradient(nsISVGGDIPlusRegion *aRegion, nsISVGGradient *aGrad,
nsIDOMSVGMatrix *aCTM, Graphics *aGFX,
nsIDOMSVGMatrix *aCTM, Graphics *aGFX, nsISVGGeometrySource *aSource,
void(*aCallback)(Graphics *, Brush*, void *), void *aData);
#endif

View File

@ -60,6 +60,7 @@ using namespace Gdiplus;
#include "nsSVGTypeCIDs.h"
#include "nsIComponentManager.h"
/**
* \addtogroup gdiplus_renderer GDI+ Rendering Engine
* @{
@ -73,6 +74,8 @@ class nsSVGGDIPlusPathGeometry : public nsISVGRendererPathGeometry
protected:
friend nsresult NS_NewSVGGDIPlusPathGeometry(nsISVGRendererPathGeometry **result,
nsISVGPathGeometrySource *src);
friend void gradCBFill(Graphics *gfx, Brush *brush, void *cbStruct);
friend void gradCBStroke(Graphics *gfx, Brush *brush, void *cbStruct);
nsSVGGDIPlusPathGeometry();
~nsSVGGDIPlusPathGeometry();
@ -84,7 +87,7 @@ public:
// nsISVGRendererPathGeometry interface:
NS_DECL_NSISVGRENDERERPATHGEOMETRY
protected:
void ClearPath() { if (mPath) { delete mPath; mPath=nsnull; } }
void ClearFill() { if (mFill) { delete mFill; mFill=nsnull; } }
@ -369,10 +372,16 @@ nsSVGGDIPlusPathGeometry::RenderPath(GraphicsPath *path, nscolor color, float op
//----------------------------------------------------------------------
// nsISVGRendererPathGeometry methods:
static void gradCBPath(Graphics *gfx, Brush *brush, void *cbStruct)
static void gradCBFill(Graphics *gfx, Brush *brush, void *cbStruct)
{
GraphicsPath *path = (GraphicsPath *)cbStruct;
gfx->FillPath(brush, path);
nsSVGGDIPlusPathGeometry *geom = (nsSVGGDIPlusPathGeometry *)cbStruct;
gfx->FillPath(brush, geom->GetFill());
}
static void gradCBStroke(Graphics *gfx, Brush *brush, void *cbStruct)
{
nsSVGGDIPlusPathGeometry *geom = (nsSVGGDIPlusPathGeometry *)cbStruct;
gfx->FillPath(brush, geom->GetStroke());
}
/** Implements void render(in nsISVGRendererCanvas canvas); */
@ -437,7 +446,7 @@ nsSVGGDIPlusPathGeometry::Render(nsISVGRendererCanvas *canvas)
mSource->GetCanvasTM(getter_AddRefs(ctm));
GDIPlusGradient(aRegion, aGrad, ctm, gdiplusCanvas->GetGraphics(),
gradCBPath, GetFill());
mSource, gradCBFill, this);
}
}
@ -459,7 +468,7 @@ nsSVGGDIPlusPathGeometry::Render(nsISVGRendererCanvas *canvas)
mSource->GetCanvasTM(getter_AddRefs(ctm));
GDIPlusGradient(aRegion, aGrad, ctm, gdiplusCanvas->GetGraphics(),
gradCBPath, GetStroke());
mSource, gradCBStroke, this);
}
}

View File

@ -300,7 +300,7 @@ nsSVGLibartGlyphGeometryFT::PaintFill(nsISVGLibartCanvas* canvas,
else if (type == nsISVGGeometrySource::PAINT_TYPE_SERVER) {
nsCOMPtr<nsIDOMSVGMatrix> ctm;
mSource->GetCanvasTM(getter_AddRefs(ctm));
LibartGradient(render, ctm, aGrad, aLibartRegion);
LibartGradient(render, ctm, aGrad, aLibartRegion, mSource);
}
art_render_mask_solid(render, (int)(0x10000*opacity));

View File

@ -250,7 +250,8 @@ LibartRadialGradient(ArtRender *render, nsISVGGradient *aGrad, double *affine)
void
LibartGradient(ArtRender *render, nsIDOMSVGMatrix *aMatrix,
nsISVGGradient *aGrad, nsISVGLibartRegion *aRegion)
nsISVGGradient *aGrad, nsISVGLibartRegion *aRegion,
nsISVGGeometrySource *aSource)
{
double affine[6];
NS_ASSERTION(aGrad, "Called LibartGradient without a gradient!");
@ -258,50 +259,21 @@ LibartGradient(ArtRender *render, nsIDOMSVGMatrix *aMatrix,
return;
}
// Get the gradientUnits
PRUint16 bbox;
aGrad->GetGradientUnits(&bbox);
if (bbox == nsIDOMSVGGradientElement::SVG_GRUNITS_OBJECTBOUNDINGBOX)
{
// BoundingBox
// We need to calculate this from the Region (Uta?) in
// the object we're filling
ArtIRect aBoundsRect;
GetBounds(aRegion, &aBoundsRect);
#ifdef DEBUG_scooter
printf("In LibartGradient: bbox (%f, %f, %f, %f)\n", (float)aBoundsRect.x0,
(float)aBoundsRect.x1, (float)aBoundsRect.y0, (float)aBoundsRect.y1);
#endif
affine[0] = aBoundsRect.x1 - aBoundsRect.x0;
affine[1] = 0.;
affine[2] = 0.;
affine[3] = aBoundsRect.y1 - aBoundsRect.y0;
affine[4] = aBoundsRect.x0;
affine[5] = aBoundsRect.y0;
} else {
// userSpaceOnUse
// Get the current transformation matrix
SVGToMatrix(aMatrix, affine);
}
// Get the transform list (if there is one)
nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix));
aGrad->GetGradientTransform(getter_AddRefs(svgMatrix), aSource);
NS_ASSERTION(svgMatrix, "LibartLinearGradient: GetGradientTransform returns null");
double aTransMatrix[6];
SVGToMatrix(svgMatrix, aTransMatrix);
art_affine_multiply(affine, aTransMatrix, affine);
// Linear or Radial?
PRUint32 type;
aGrad->GetGradientType(&type);
if (type == nsISVGGradient::SVG_LINEAR_GRADIENT)
LibartLinearGradient(render, aGrad, affine);
LibartLinearGradient(render, aGrad, aTransMatrix);
else if (type == nsISVGGradient::SVG_RADIAL_GRADIENT)
LibartRadialGradient(render, aGrad, affine);
LibartRadialGradient(render, aGrad, aTransMatrix);
return;
}

View File

@ -44,10 +44,12 @@
#include "nsISVGGradient.h"
#include "nsISVGLibartRegion.h"
#include "nsISVGLibartCanvas.h"
#include "nsISVGGeometrySource.h"
// Define external
void LibartGradient(ArtRender *render, nsIDOMSVGMatrix *aMatrix,
nsISVGGradient *aGrad, nsISVGLibartRegion *aRegion);
nsISVGGradient *aGrad, nsISVGLibartRegion *aRegion,
nsISVGGeometrySource *aSource);
#endif // __NS_SVGLIBARTGRADIENT_H__

View File

@ -295,7 +295,7 @@ nsSVGLibartPathGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGLibartRegion> aLibartRegion = do_QueryInterface(region);
nsCOMPtr<nsIDOMSVGMatrix> ctm;
mSource->GetCanvasTM(getter_AddRefs(ctm));
LibartGradient(render, ctm, aGrad, aLibartRegion);
LibartGradient(render, ctm, aGrad, aLibartRegion, mSource);
// And draw it
libartCanvas->InvokeRender(render);
@ -338,7 +338,7 @@ nsSVGLibartPathGeometry::Render(nsISVGRendererCanvas *canvas)
nsCOMPtr<nsISVGLibartRegion> aLibartRegion = do_QueryInterface(region);
nsCOMPtr<nsIDOMSVGMatrix> ctm;
mSource->GetCanvasTM(getter_AddRefs(ctm));
LibartGradient(render, ctm, aGrad, aLibartRegion);
LibartGradient(render, ctm, aGrad, aLibartRegion, mSource);
// And draw it
libartCanvas->InvokeRender(render);