mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-13 18:27:35 +00:00
Bug 282026 - use appropriate transform when drawing objectBoundingBox
dimensioned gradients. r=scooter
This commit is contained in:
parent
b4fca87aba
commit
aa09f6e30d
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
/** @} */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,6 @@
|
||||
cairo_pattern_t *
|
||||
CairoGradient(cairo_t *ctx,
|
||||
nsISVGGradient *aGrad,
|
||||
cairo_text_extents_t *extent=NULL);
|
||||
nsISVGGeometrySource *aSource);
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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(¢er), 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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user