mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1092125 - part 2 - add non-scaling-stroke support to SVGLineElement::GetGeometryBounds. r=jwatt
This commit is contained in:
parent
67a6154671
commit
7579b60c17
@ -153,10 +153,6 @@ SVGLineElement::GetGeometryBounds(Rect* aBounds,
|
||||
const Matrix& aToBoundsSpace,
|
||||
const Matrix* aToNonScalingStrokeSpace)
|
||||
{
|
||||
if (aToNonScalingStrokeSpace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float x1, y1, x2, y2;
|
||||
GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
|
||||
|
||||
@ -166,21 +162,53 @@ SVGLineElement::GetGeometryBounds(Rect* aBounds,
|
||||
return true;
|
||||
}
|
||||
|
||||
// transform from non-scaling-stroke space to the space in which we compute
|
||||
// bounds
|
||||
Matrix nonScalingToBounds;
|
||||
if (aToNonScalingStrokeSpace) {
|
||||
Matrix nonScalingToUser = aToNonScalingStrokeSpace->Inverse();
|
||||
nonScalingToBounds = nonScalingToUser * aToBoundsSpace;
|
||||
}
|
||||
|
||||
if (aStrokeOptions.mLineCap == CapStyle::ROUND) {
|
||||
if (!aToBoundsSpace.IsRectilinear()) {
|
||||
if (!aToBoundsSpace.IsRectilinear() ||
|
||||
(aToNonScalingStrokeSpace &&
|
||||
!aToNonScalingStrokeSpace->IsRectilinear())) {
|
||||
// TODO: handle this case.
|
||||
return false;
|
||||
}
|
||||
Rect bounds(Point(x1, y1), Size());
|
||||
bounds.ExpandToEnclose(Point(x2, y2));
|
||||
bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
|
||||
*aBounds = aToBoundsSpace.TransformBounds(bounds);
|
||||
if (aToNonScalingStrokeSpace) {
|
||||
bounds = aToNonScalingStrokeSpace->TransformBounds(bounds);
|
||||
bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
|
||||
*aBounds = nonScalingToBounds.TransformBounds(bounds);
|
||||
} else {
|
||||
bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
|
||||
*aBounds = aToBoundsSpace.TransformBounds(bounds);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle butt and square linecap, normal and non-scaling stroke cases
|
||||
// together: start with endpoints (x1, y1), (x2, y2) in the stroke space,
|
||||
// compute the four corners of the stroked line, transform the corners to
|
||||
// bounds space, and compute bounds there.
|
||||
|
||||
if (aToNonScalingStrokeSpace) {
|
||||
Point nonScalingSpaceP1, nonScalingSpaceP2;
|
||||
nonScalingSpaceP1 = *aToNonScalingStrokeSpace * Point(x1, y1);
|
||||
nonScalingSpaceP2 = *aToNonScalingStrokeSpace * Point(x2, y2);
|
||||
x1 = nonScalingSpaceP1.x;
|
||||
y1 = nonScalingSpaceP1.y;
|
||||
x2 = nonScalingSpaceP2.x;
|
||||
y2 = nonScalingSpaceP2.y;
|
||||
}
|
||||
|
||||
Float length = Float(NS_hypot(x2 - x1, y2 - y1));
|
||||
Float xDelta;
|
||||
Float yDelta;
|
||||
Point points[4];
|
||||
|
||||
if (aStrokeOptions.mLineCap == CapStyle::BUTT) {
|
||||
if (length == 0.f) {
|
||||
@ -190,27 +218,37 @@ SVGLineElement::GetGeometryBounds(Rect* aBounds,
|
||||
xDelta = ratio * (y2 - y1);
|
||||
yDelta = ratio * (x2 - x1);
|
||||
}
|
||||
points[0] = Point(x1 - xDelta, y1 + yDelta);
|
||||
points[1] = Point(x1 + xDelta, y1 - yDelta);
|
||||
points[2] = Point(x2 + xDelta, y2 - yDelta);
|
||||
points[3] = Point(x2 - xDelta, y2 + yDelta);
|
||||
} else {
|
||||
MOZ_ASSERT(aStrokeOptions.mLineCap == CapStyle::SQUARE);
|
||||
if (length == 0.f) {
|
||||
xDelta = yDelta = aStrokeOptions.mLineWidth / 2.f;
|
||||
points[0] = Point(x1 - xDelta, y1 + yDelta);
|
||||
points[1] = Point(x1 - xDelta, y1 - yDelta);
|
||||
points[2] = Point(x1 + xDelta, y1 - yDelta);
|
||||
points[3] = Point(x1 + xDelta, y1 + yDelta);
|
||||
} else {
|
||||
Float ratio = aStrokeOptions.mLineWidth / 2.f / length;
|
||||
xDelta = yDelta = ratio * (fabs(y2 - y1) + fabs(x2 - x1));
|
||||
yDelta = ratio * (x2 - x1);
|
||||
xDelta = ratio * (y2 - y1);
|
||||
points[0] = Point(x1 - yDelta - xDelta, y1 - xDelta + yDelta);
|
||||
points[1] = Point(x1 - yDelta + xDelta, y1 - xDelta - yDelta);
|
||||
points[2] = Point(x2 + yDelta + xDelta, y2 + xDelta - yDelta);
|
||||
points[3] = Point(x2 + yDelta - xDelta, y2 + xDelta + yDelta);
|
||||
}
|
||||
}
|
||||
|
||||
Point points[4];
|
||||
const Matrix& toBoundsSpace = aToNonScalingStrokeSpace ?
|
||||
nonScalingToBounds : aToBoundsSpace;
|
||||
|
||||
points[0] = Point(x1 - xDelta, y1 - yDelta);
|
||||
points[1] = Point(x1 + xDelta, y1 + yDelta);
|
||||
points[2] = Point(x2 + xDelta, y2 + yDelta);
|
||||
points[3] = Point(x2 - xDelta, y2 - yDelta);
|
||||
|
||||
*aBounds = Rect(aToBoundsSpace * points[0], Size());
|
||||
*aBounds = Rect(toBoundsSpace * points[0], Size());
|
||||
for (uint32_t i = 1; i < 4; ++i) {
|
||||
aBounds->ExpandToEnclose(aToBoundsSpace * points[i]);
|
||||
aBounds->ExpandToEnclose(toBoundsSpace * points[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -47,5 +47,17 @@ text { font: 20px monospace; }
|
||||
transform="matrix(0 3 -2 0 0 0)"
|
||||
fill="none" stroke="steelblue" stroke-width="10"
|
||||
vector-effect="non-scaling-stroke" />
|
||||
<line id="nonScalingStrokedLine1" x1="120" y1="5" x2="120" y2="10"
|
||||
transform="scale(2 3)"
|
||||
stroke-width="10" stroke-linecap="round" stroke="orange"
|
||||
vector-effect="non-scaling-stroke" />
|
||||
<line id="nonScalingStrokedLine2" x1="130" y1="5" x2="140" y2="5"
|
||||
transform="rotate(45 260 15) scale(2 3)"
|
||||
stroke-width="10" stroke-linecap="square" stroke="crimson"
|
||||
vector-effect="non-scaling-stroke" />
|
||||
<line id="nonScalingStrokedLine3" x1="140" y1="5" x2="150" y2="5"
|
||||
transform="rotate(45 280 15) scale(2 3)"
|
||||
stroke-width="10" stroke-linecap="butt" stroke="indigo"
|
||||
vector-effect="non-scaling-stroke" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 3.1 KiB |
@ -222,6 +222,45 @@ function runTest()
|
||||
isWithAbsTolerance(nonScalingStrokedEllipse1Bounds.height, 40, 0.15,
|
||||
"nonScalingStrokedEllipse1.getBoundingClientRect().height");
|
||||
|
||||
var nonScalingStrokedLine1Bounds =
|
||||
doc.getElementById("nonScalingStrokedLine1").getBoundingClientRect();
|
||||
isWithAbsTolerance(nonScalingStrokedLine1Bounds.left, 235, 0.1,
|
||||
"nonScalingStrokedLine1.getBoundingClientRect().left");
|
||||
isWithAbsTolerance(nonScalingStrokedLine1Bounds.top, 10, 0.1,
|
||||
"nonScalingStrokedLine1.getBoundingClientRect().top");
|
||||
isWithAbsTolerance(nonScalingStrokedLine1Bounds.width, 10, 0.1,
|
||||
"nonScalingStrokedLine1.getBoundingClientRect().width");
|
||||
isWithAbsTolerance(nonScalingStrokedLine1Bounds.height, 25, 0.1,
|
||||
"nonScalingStrokedLine1.getBoundingClientRect().height");
|
||||
|
||||
var nonScalingStrokedLine2Bounds =
|
||||
doc.getElementById("nonScalingStrokedLine2").getBoundingClientRect();
|
||||
var capDelta = 5/Math.SQRT2 + 5/Math.SQRT2;
|
||||
rect = new Rect(260 - capDelta, 15 - capDelta, 20/Math.SQRT2 + 2 * capDelta,
|
||||
20/Math.SQRT2 + 2 * capDelta);
|
||||
isWithAbsTolerance(nonScalingStrokedLine2Bounds.left, rect.left, 0.1,
|
||||
"nonScalingStrokedLine2.getBoundingClientRect().left");
|
||||
isWithAbsTolerance(nonScalingStrokedLine2Bounds.top, rect.top, 0.1,
|
||||
"nonScalingStrokedLine2.getBoundingClientRect().top");
|
||||
isWithAbsTolerance(nonScalingStrokedLine2Bounds.width, rect.width, 0.15,
|
||||
"nonScalingStrokedLine2.getBoundingClientRect().width");
|
||||
isWithAbsTolerance(nonScalingStrokedLine2Bounds.height, rect.height, 0.15,
|
||||
"nonScalingStrokedLine2.getBoundingClientRect().height");
|
||||
|
||||
var nonScalingStrokedLine3Bounds =
|
||||
doc.getElementById("nonScalingStrokedLine3").getBoundingClientRect();
|
||||
var capDelta = 5/Math.SQRT2;
|
||||
rect = new Rect(280 - capDelta, 15 - capDelta, 20/Math.SQRT2 + 2 * capDelta,
|
||||
20/Math.SQRT2 + 2 * capDelta);
|
||||
isWithAbsTolerance(nonScalingStrokedLine3Bounds.left, rect.left, 0.1,
|
||||
"nonScalingStrokedLine3.getBoundingClientRect().left");
|
||||
isWithAbsTolerance(nonScalingStrokedLine3Bounds.top, rect.top, 0.1,
|
||||
"nonScalingStrokedLine3.getBoundingClientRect().top");
|
||||
isWithAbsTolerance(nonScalingStrokedLine3Bounds.width, rect.width, 0.1,
|
||||
"nonScalingStrokedLine3.getBoundingClientRect().width");
|
||||
isWithAbsTolerance(nonScalingStrokedLine3Bounds.height, rect.height, 0.1,
|
||||
"nonScalingStrokedLine3.getBoundingClientRect().height");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -1171,7 +1171,7 @@ PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
|
||||
gfxMatrix outerSVGToUser;
|
||||
if (nsSVGUtils::GetNonScalingStrokeTransform(aFrame, &outerSVGToUser)) {
|
||||
outerSVGToUser.Invert();
|
||||
matrix *= outerSVGToUser;
|
||||
matrix.PreMultiply(outerSVGToUser);
|
||||
}
|
||||
|
||||
double dx = style_expansion * (fabs(matrix._11) + fabs(matrix._21));
|
||||
|
Loading…
Reference in New Issue
Block a user