mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1074594 - Stop inverting the transform in nsSVGUtils::GetStrokeTransform, give it a more performant signature, and a better name. r=longsonr
This commit is contained in:
parent
575724162a
commit
aee9c12e6a
@ -263,13 +263,12 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame* aSource,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// revert the vector effect transform so that the gradient appears unchanged
|
||||
// revert any vector effect transform so that the gradient appears unchanged
|
||||
if (aFillOrStroke == &nsStyleSVG::mStroke) {
|
||||
gfxMatrix nonScalingStrokeTM = nsSVGUtils::GetStrokeTransform(aSource);
|
||||
if (!nonScalingStrokeTM.Invert()) {
|
||||
return nullptr;
|
||||
gfxMatrix userToOuterSVG;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
|
||||
patternMatrix *= userToOuterSVG;
|
||||
}
|
||||
patternMatrix *= nonScalingStrokeTM;
|
||||
}
|
||||
|
||||
if (!patternMatrix.Invert()) {
|
||||
|
@ -302,18 +302,15 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const gfxPoint& aPoint)
|
||||
Point point = ToPoint(aPoint);
|
||||
SVGContentUtils::AutoStrokeOptions stroke;
|
||||
SVGContentUtils::GetStrokeOptions(&stroke, content, StyleContext(), nullptr);
|
||||
Matrix nonScalingStrokeMatrix = ToMatrix(nsSVGUtils::GetStrokeTransform(this));
|
||||
if (!nonScalingStrokeMatrix.IsIdentity()) {
|
||||
gfxMatrix userToOuterSVG;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
||||
// We need to transform the path back into the appropriate ancestor
|
||||
// coordinate system in order for non-scaled stroke to be correct.
|
||||
// Naturally we also need to transform the point into the same
|
||||
// coordinate system in order to hit-test against the path.
|
||||
if (!nonScalingStrokeMatrix.Invert()) {
|
||||
return nullptr;
|
||||
}
|
||||
point = nonScalingStrokeMatrix * point;
|
||||
point = ToMatrix(userToOuterSVG) * point;
|
||||
RefPtr<PathBuilder> builder =
|
||||
path->TransformedCopyToBuilder(nonScalingStrokeMatrix, fillRule);
|
||||
path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
|
||||
path = builder->Finish();
|
||||
}
|
||||
isHit = path->StrokeContainsPoint(stroke, point, Matrix());
|
||||
@ -677,15 +674,15 @@ nsSVGPathGeometryFrame::Render(gfxContext* aContext,
|
||||
if ((aRenderComponents & eRenderStroke) &&
|
||||
nsSVGUtils::HasStroke(this, contextPaint)) {
|
||||
// Account for vector-effect:non-scaling-stroke:
|
||||
gfxMatrix strokeTransform = nsSVGUtils::GetStrokeTransform(this);
|
||||
if (!strokeTransform.IsIdentity()) {
|
||||
gfxMatrix userToOuterSVG;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
|
||||
// We need to transform the path back into the appropriate ancestor
|
||||
// coordinate system, and paint it it that coordinate system, in order
|
||||
// for non-scaled stroke to paint correctly.
|
||||
aContext->Multiply(strokeTransform);
|
||||
Matrix moz2DstrokeTransform = ToMatrix(strokeTransform); // inverse of Thebes
|
||||
moz2DstrokeTransform.Invert();
|
||||
builder = path->TransformedCopyToBuilder(moz2DstrokeTransform, fillRule);
|
||||
gfxMatrix outerSVGToUser = userToOuterSVG;
|
||||
outerSVGToUser.Invert();
|
||||
aContext->Multiply(outerSVGToUser);
|
||||
builder = path->TransformedCopyToBuilder(ToMatrix(userToOuterSVG), fillRule);
|
||||
path = builder->Finish();
|
||||
}
|
||||
GeneralPattern strokePattern;
|
||||
|
@ -325,12 +325,14 @@ nsSVGPatternFrame::PaintPattern(const DrawTarget* aDrawTarget,
|
||||
|
||||
// revert the vector effect transform so that the pattern appears unchanged
|
||||
if (aFillOrStroke == &nsStyleSVG::mStroke) {
|
||||
Matrix strokeTransform = ToMatrix(nsSVGUtils::GetStrokeTransform(aSource));
|
||||
if (!strokeTransform.Invert()) {
|
||||
NS_WARNING("Should we get here if the stroke transform is singular?");
|
||||
return nullptr;
|
||||
gfxMatrix userToOuterSVG;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
|
||||
patternTransform *= ToMatrix(userToOuterSVG);
|
||||
if (patternTransform.IsSingular()) {
|
||||
NS_WARNING("Singular matrix painting non-scaling-stroke");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
patternTransform *= strokeTransform;
|
||||
}
|
||||
|
||||
// Get the transformation matrix that we will hand to the renderer's pattern
|
||||
|
@ -1119,31 +1119,26 @@ nsSVGUtils::GetFirstNonAAncestorFrame(nsIFrame* aStartFrame)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfxMatrix
|
||||
nsSVGUtils::GetStrokeTransform(nsIFrame *aFrame)
|
||||
bool
|
||||
nsSVGUtils::GetNonScalingStrokeTransform(nsIFrame *aFrame,
|
||||
gfxMatrix* aUserToOuterSVG)
|
||||
{
|
||||
if (aFrame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
|
||||
aFrame = aFrame->GetParent();
|
||||
}
|
||||
|
||||
if (aFrame->StyleSVGReset()->mVectorEffect ==
|
||||
NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE) {
|
||||
|
||||
nsIContent *content = aFrame->GetContent();
|
||||
NS_ABORT_IF_FALSE(content->IsSVG(), "bad cast");
|
||||
|
||||
// a non-scaling stroke is in the screen co-ordinate
|
||||
// space rather so we need to invert the transform
|
||||
// to the screen co-ordinate space to get there.
|
||||
// See http://www.w3.org/TR/SVGTiny12/painting.html#NonScalingStroke
|
||||
gfx::Matrix transform = SVGContentUtils::GetCTM(
|
||||
static_cast<nsSVGElement*>(content), true);
|
||||
if (!transform.IsSingular()) {
|
||||
transform.Invert();
|
||||
return ThebesMatrix(transform);
|
||||
}
|
||||
if (aFrame->StyleSVGReset()->mVectorEffect !=
|
||||
NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE) {
|
||||
return false;
|
||||
}
|
||||
return gfxMatrix();
|
||||
|
||||
nsIContent *content = aFrame->GetContent();
|
||||
NS_ABORT_IF_FALSE(content->IsSVG(), "bad cast");
|
||||
|
||||
*aUserToOuterSVG = ThebesMatrix(SVGContentUtils::GetCTM(
|
||||
static_cast<nsSVGElement*>(content), true));
|
||||
|
||||
return !aUserToOuterSVG->IsIdentity();
|
||||
}
|
||||
|
||||
// The logic here comes from _cairo_stroke_style_max_distance_from_path
|
||||
@ -1156,7 +1151,13 @@ PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
|
||||
double style_expansion =
|
||||
aStyleExpansionFactor * nsSVGUtils::GetStrokeWidth(aFrame);
|
||||
|
||||
gfxMatrix matrix = aMatrix * nsSVGUtils::GetStrokeTransform(aFrame);
|
||||
gfxMatrix matrix = aMatrix;
|
||||
|
||||
gfxMatrix outerSVGToUser;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(aFrame, &outerSVGToUser)) {
|
||||
outerSVGToUser.Invert();
|
||||
matrix *= outerSVGToUser;
|
||||
}
|
||||
|
||||
double dx = style_expansion * (fabs(matrix._11) + fabs(matrix._21));
|
||||
double dy = style_expansion * (fabs(matrix._22) + fabs(matrix._12));
|
||||
@ -1496,9 +1497,10 @@ nsSVGUtils::SetupCairoStrokeGeometry(nsIFrame* aFrame,
|
||||
aContext->SetLineWidth(width);
|
||||
|
||||
// Apply any stroke-specific transform
|
||||
gfxMatrix strokeTransform = GetStrokeTransform(aFrame);
|
||||
if (!strokeTransform.IsIdentity()) {
|
||||
aContext->Multiply(strokeTransform);
|
||||
gfxMatrix outerSVGToUser;
|
||||
if (GetNonScalingStrokeTransform(aFrame, &outerSVGToUser) &&
|
||||
outerSVGToUser.Invert()) {
|
||||
aContext->Multiply(outerSVGToUser);
|
||||
}
|
||||
|
||||
const nsStyleSVG* style = aFrame->StyleSVG();
|
||||
|
@ -467,11 +467,18 @@ public:
|
||||
static bool OuterSVGIsCallingReflowSVG(nsIFrame *aFrame);
|
||||
static bool AnyOuterSVGIsCallingReflowSVG(nsIFrame *aFrame);
|
||||
|
||||
/*
|
||||
* Get any additional transforms that apply only to stroking
|
||||
* e.g. non-scaling-stroke
|
||||
/**
|
||||
* See https://svgwg.org/svg2-draft/painting.html#NonScalingStroke
|
||||
*
|
||||
* If the computed value of the 'vector-effect' property on aFrame is
|
||||
* 'non-scaling-stroke', then this function will set aUserToOuterSVG to the
|
||||
* transform from aFrame's SVG user space to the initial coordinate system
|
||||
* established by the viewport of aFrame's outer-<svg>'s (the coordinate
|
||||
* system in which the stroke is fixed). If aUserToOuterSVG is set to a
|
||||
* non-identity matrix this function returns true, else it returns false.
|
||||
*/
|
||||
static gfxMatrix GetStrokeTransform(nsIFrame *aFrame);
|
||||
static bool GetNonScalingStrokeTransform(nsIFrame *aFrame,
|
||||
gfxMatrix* aUserToOuterSVG);
|
||||
|
||||
/**
|
||||
* Compute the maximum possible device space stroke extents of a path given
|
||||
|
Loading…
Reference in New Issue
Block a user