зеркало из https://github.com/mozilla/gecko-dev.git
Bug 384208 - svg:pattern not correct for general transforms. r=longsonr, sr+a=roc
This commit is contained in:
Родитель
af8e780399
Коммит
7b54df5ad9
|
@ -175,18 +175,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
|
|||
nsSVGUtils::ConvertToSurfaceSize(gfxSize(filterResX, filterResY),
|
||||
&resultOverflows);
|
||||
} else {
|
||||
float a, b, c, d;
|
||||
ctm->GetA(&a);
|
||||
ctm->GetB(&b);
|
||||
ctm->GetC(&c);
|
||||
ctm->GetD(&d);
|
||||
|
||||
// maximum expansion derivation from
|
||||
// http://lists.cairographics.org/archives/cairo/2004-October/001980.html
|
||||
float f = (a * a + b * b + c * c + d * d) / 2;
|
||||
float g = (a * a - b * b + c * c - d * d) / 2;
|
||||
float h = a * b + c * d;
|
||||
float scale = sqrt(f + sqrt(g * g + h * h));
|
||||
float scale = nsSVGUtils::MaxExpansion(ctm);
|
||||
#ifdef DEBUG_tor
|
||||
fprintf(stderr, "scale: %f\n", scale);
|
||||
#endif
|
||||
|
|
|
@ -258,14 +258,15 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
|
|||
|
||||
// Construct the CTM that we will provide to our children when we
|
||||
// render them into the tile.
|
||||
if (NS_FAILED(ConstructCTM(getter_AddRefs(mCTM), callerBBox)))
|
||||
if (NS_FAILED(ConstructCTM(getter_AddRefs(mCTM), callerBBox, callerCTM)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Get the bounding box of the pattern. This will be used to determine
|
||||
// the size of the surface, and will also be used to define the bounding
|
||||
// box for the pattern tile.
|
||||
nsCOMPtr<nsIDOMSVGRect> bbox;
|
||||
if (NS_FAILED(GetPatternRect(getter_AddRefs(bbox), callerBBox,
|
||||
if (NS_FAILED(GetPatternRect(getter_AddRefs(bbox),
|
||||
callerBBox, callerCTM,
|
||||
callerContent)))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -274,9 +275,10 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
|
|||
*patternMatrix = GetPatternMatrix(bbox, callerBBox, callerCTM);
|
||||
|
||||
#ifdef DEBUG_scooter
|
||||
printRect("Bounding Rect: ",bbox);
|
||||
printCTM("Pattern TM ",*patternMatrix);
|
||||
printCTM("Child TM ",mCTM);
|
||||
printRect("Geometry Rect: ", callerBBox);
|
||||
printRect("Pattern Rect: ", bbox);
|
||||
printCTM("Pattern TM ", *patternMatrix);
|
||||
printCTM("Child TM ", mCTM);
|
||||
#endif
|
||||
|
||||
// Now that we have all of the necessary geometries, we can
|
||||
|
@ -620,7 +622,8 @@ nsSVGPatternFrame::checkURITarget(void) {
|
|||
|
||||
nsresult
|
||||
nsSVGPatternFrame::GetPatternRect(nsIDOMSVGRect **patternRect,
|
||||
nsIDOMSVGRect *bbox,
|
||||
nsIDOMSVGRect *bbox,
|
||||
nsIDOMSVGMatrix *callerCTM,
|
||||
nsSVGElement *content)
|
||||
{
|
||||
// Get our type
|
||||
|
@ -642,10 +645,11 @@ nsSVGPatternFrame::GetPatternRect(nsIDOMSVGRect **patternRect,
|
|||
width = nsSVGUtils::ObjectSpace(bbox, tmpWidth);
|
||||
height = nsSVGUtils::ObjectSpace(bbox, tmpHeight);
|
||||
} else {
|
||||
x = nsSVGUtils::UserSpace(content, tmpX);
|
||||
y = nsSVGUtils::UserSpace(content, tmpY);
|
||||
width = nsSVGUtils::UserSpace(content, tmpWidth);
|
||||
height = nsSVGUtils::UserSpace(content, tmpHeight);
|
||||
float scale = nsSVGUtils::MaxExpansion(callerCTM);
|
||||
x = nsSVGUtils::UserSpace(content, tmpX) * scale;
|
||||
y = nsSVGUtils::UserSpace(content, tmpY) * scale;
|
||||
width = nsSVGUtils::UserSpace(content, tmpWidth) * scale;
|
||||
height = nsSVGUtils::UserSpace(content, tmpHeight) * scale;
|
||||
}
|
||||
|
||||
return NS_NewSVGRect(patternRect, x, y, width, height);
|
||||
|
@ -659,7 +663,8 @@ GetLengthValue(nsSVGLength2 *aLength)
|
|||
|
||||
nsresult
|
||||
nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
|
||||
nsIDOMSVGRect *callerBBox)
|
||||
nsIDOMSVGRect *callerBBox,
|
||||
nsIDOMSVGMatrix *callerCTM)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSVGMatrix> tCTM, tempTM;
|
||||
|
||||
|
@ -675,7 +680,8 @@ nsSVGPatternFrame::ConstructCTM(nsIDOMSVGMatrix **aCTM,
|
|||
NS_NewSVGMatrix(getter_AddRefs(tCTM), width, 0.0f, 0.0f,
|
||||
height, 0.0f, 0.0f);
|
||||
} else {
|
||||
NS_NewSVGMatrix(getter_AddRefs(tCTM));
|
||||
float scale = nsSVGUtils::MaxExpansion(callerCTM);
|
||||
NS_NewSVGMatrix(getter_AddRefs(tCTM), scale, 0, 0, scale, 0, 0);
|
||||
}
|
||||
|
||||
// Do we have a viewbox?
|
||||
|
@ -734,10 +740,11 @@ nsSVGPatternFrame::GetPatternMatrix(nsIDOMSVGRect *bbox,
|
|||
miny += y;
|
||||
}
|
||||
|
||||
float scale = 1.0f / nsSVGUtils::MaxExpansion(callerCTM);
|
||||
patternTransform.Scale(scale, scale);
|
||||
patternTransform.Translate(gfxPoint(minx, miny));
|
||||
|
||||
// Multiply in the caller's CTM to handle device coordinates
|
||||
return patternTransform * nsSVGUtils::ConvertSVGMatrixToThebes(callerCTM);
|
||||
return patternTransform;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -772,7 +779,13 @@ nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
|
|||
CallQueryInterface(aSource->GetParent(), &callerSVGFrame);
|
||||
else
|
||||
CallQueryInterface(aSource, &callerSVGFrame);
|
||||
|
||||
callerSVGFrame->SetMatrixPropagation(PR_FALSE);
|
||||
callerSVGFrame->NotifyCanvasTMChanged(PR_TRUE);
|
||||
callerSVGFrame->GetBBox(aBBox);
|
||||
callerSVGFrame->SetMatrixPropagation(PR_TRUE);
|
||||
callerSVGFrame->NotifyCanvasTMChanged(PR_TRUE);
|
||||
|
||||
// Sanity check
|
||||
PRUint16 type = GetPatternUnits();
|
||||
if (type == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
|
||||
|
@ -795,15 +808,15 @@ nsSVGPatternFrame::GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
|
|||
(*aBBox)->GetY(&y);
|
||||
(*aBBox)->GetWidth(&width);
|
||||
(*aBBox)->GetHeight(&height);
|
||||
float xpos, ypos, xscale, yscale;
|
||||
(*aCTM)->GetA(&xscale);
|
||||
(*aCTM)->GetD(&yscale);
|
||||
(*aCTM)->GetE(&xpos);
|
||||
(*aCTM)->GetF(&ypos);
|
||||
x = (x - xpos) / xscale;
|
||||
y = (y - ypos) / yscale;
|
||||
width = width / xscale;
|
||||
height = height / yscale;
|
||||
float scale = nsSVGUtils::MaxExpansion(*aCTM);
|
||||
#ifdef DEBUG_scooter
|
||||
fprintf(stderr, "pattern scale %f\n", scale);
|
||||
fprintf(stderr, "x,y,width,height: %f %f %f %f\n", x, y, width, height);
|
||||
#endif
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
(*aBBox)->SetX(x);
|
||||
(*aBBox)->SetY(y);
|
||||
(*aBBox)->SetWidth(width);
|
||||
|
@ -834,18 +847,16 @@ nsSVGPatternFrame::SetupPaintServer(gfxContext *aContext,
|
|||
aContext->IdentityMatrix();
|
||||
nsresult rv = PaintPattern(getter_AddRefs(surface), &pMatrix,
|
||||
aSource, aGraphicOpacity);
|
||||
|
||||
aContext->SetMatrix(matrix);
|
||||
if (NS_FAILED(rv)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Translate the pattern frame
|
||||
matrix.Invert();
|
||||
pMatrix *= matrix;
|
||||
|
||||
if (pMatrix.IsSingular()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
pMatrix.Invert();
|
||||
|
||||
nsRefPtr<gfxPattern> pattern = new gfxPattern(surface);
|
||||
|
|
|
@ -137,12 +137,16 @@ protected:
|
|||
**aPreserveAspectRatio);
|
||||
NS_IMETHOD GetPatternFirstChild(nsIFrame **kid);
|
||||
NS_IMETHOD GetViewBox(nsIDOMSVGRect * *aMatrix);
|
||||
nsresult GetPatternRect(nsIDOMSVGRect **patternRect, nsIDOMSVGRect *bbox,
|
||||
nsresult GetPatternRect(nsIDOMSVGRect **patternRect,
|
||||
nsIDOMSVGRect *bbox,
|
||||
nsIDOMSVGMatrix *callerCTM,
|
||||
nsSVGElement *content);
|
||||
gfxMatrix GetPatternMatrix(nsIDOMSVGRect *bbox,
|
||||
nsIDOMSVGRect *callerBBox,
|
||||
nsIDOMSVGMatrix *callerCTM);
|
||||
nsresult ConstructCTM(nsIDOMSVGMatrix **ctm, nsIDOMSVGRect *callerBBox);
|
||||
nsresult ConstructCTM(nsIDOMSVGMatrix **ctm,
|
||||
nsIDOMSVGRect *callerBBox,
|
||||
nsIDOMSVGMatrix *callerCTM);
|
||||
nsresult GetCallerGeometry(nsIDOMSVGMatrix **aCTM,
|
||||
nsIDOMSVGRect **aBBox,
|
||||
nsSVGElement **aContent,
|
||||
|
|
|
@ -1456,6 +1456,23 @@ nsSVGUtils::CanOptimizeOpacity(nsIFrame *aFrame)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
float
|
||||
nsSVGUtils::MaxExpansion(nsIDOMSVGMatrix *aMatrix)
|
||||
{
|
||||
float a, b, c, d;
|
||||
aMatrix->GetA(&a);
|
||||
aMatrix->GetB(&b);
|
||||
aMatrix->GetC(&c);
|
||||
aMatrix->GetD(&d);
|
||||
|
||||
// maximum expansion derivation from
|
||||
// http://lists.cairographics.org/archives/cairo/2004-October/001980.html
|
||||
float f = (a * a + b * b + c * c + d * d) / 2;
|
||||
float g = (a * a + b * b - c * c - d * d) / 2;
|
||||
float h = a * c + b * d;
|
||||
return sqrt(f + sqrt(g * g + h * h));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsSVGUtils::WritePPM(const char *fname, gfxImageSurface *aSurface)
|
||||
|
|
|
@ -384,6 +384,10 @@ public:
|
|||
static PRBool
|
||||
CanOptimizeOpacity(nsIFrame *aFrame);
|
||||
|
||||
/* Calculate the maximum expansion of a matrix */
|
||||
static float
|
||||
MaxExpansion(nsIDOMSVGMatrix *aMatrix);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
WritePPM(const char *fname, gfxImageSurface *aSurface);
|
||||
|
|
Загрузка…
Ссылка в новой задаче