mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 17:24:29 +00:00
Bug 1683652 - Clear cached path when reframed. r=longsonr
The issue here is caused (a bit surprisingly) by the counter-reset declaration. The underlying issue is that counter-reset causes us to rebuild the frame tree for the whole `<body>`, in order to rebuild the counter tree. That makes the geometry frame not get its updated style (because the frame goes away), and the next frame getting constructed getting a null aOldComputedStyle (as expected, as it's a new frame). We can't rely on the cached path not to change while there's no frame, so clear it out when there's no old style. The test is a simpler version of the test-case, where instead of `counter-reset`, I use `display: none` to trigger the bogus codepath. Differential Revision: https://phabricator.services.mozilla.com/D100237
This commit is contained in:
parent
fdedcdeece
commit
4ec02c259b
@ -151,12 +151,11 @@ already_AddRefed<Path> SVGCircleElement::BuildPath(PathBuilder* aBuilder) {
|
||||
|
||||
bool SVGCircleElement::IsLengthChangedViaCSS(const ComputedStyle& aNewStyle,
|
||||
const ComputedStyle& aOldStyle) {
|
||||
auto *newSVGReset = aNewStyle.StyleSVGReset(),
|
||||
*oldSVGReset = aOldStyle.StyleSVGReset();
|
||||
const auto& newSVGReset = *aNewStyle.StyleSVGReset();
|
||||
const auto& oldSVGReset = *aOldStyle.StyleSVGReset();
|
||||
|
||||
return newSVGReset->mCx != oldSVGReset->mCx ||
|
||||
newSVGReset->mCy != oldSVGReset->mCy ||
|
||||
newSVGReset->mR != oldSVGReset->mR;
|
||||
return newSVGReset.mCx != oldSVGReset.mCx ||
|
||||
newSVGReset.mCy != oldSVGReset.mCy || newSVGReset.mR != oldSVGReset.mR;
|
||||
}
|
||||
|
||||
nsCSSPropertyID SVGCircleElement::GetCSSPropertyIdForAttrEnum(
|
||||
|
@ -136,37 +136,37 @@ nsresult SVGGeometryFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||
/* virtual */
|
||||
void SVGGeometryFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||
nsIFrame::DidSetComputedStyle(aOldComputedStyle);
|
||||
auto* element = static_cast<SVGGeometryElement*>(GetContent());
|
||||
if (!aOldComputedStyle) {
|
||||
element->ClearAnyCachedPath();
|
||||
return;
|
||||
}
|
||||
|
||||
if (aOldComputedStyle) {
|
||||
SVGGeometryElement* element =
|
||||
static_cast<SVGGeometryElement*>(GetContent());
|
||||
|
||||
const auto* oldStyleSVG = aOldComputedStyle->StyleSVG();
|
||||
if (!SVGContentUtils::ShapeTypeHasNoCorners(GetContent())) {
|
||||
if (StyleSVG()->mStrokeLinecap != oldStyleSVG->mStrokeLinecap &&
|
||||
element->IsSVGElement(nsGkAtoms::path)) {
|
||||
// If the stroke-linecap changes to or from "butt" then our element
|
||||
// needs to update its cached Moz2D Path, since SVGPathData::BuildPath
|
||||
// decides whether or not to insert little lines into the path for zero
|
||||
// length subpaths base on that property.
|
||||
const auto* oldStyleSVG = aOldComputedStyle->StyleSVG();
|
||||
if (!SVGContentUtils::ShapeTypeHasNoCorners(GetContent())) {
|
||||
if (StyleSVG()->mStrokeLinecap != oldStyleSVG->mStrokeLinecap &&
|
||||
element->IsSVGElement(nsGkAtoms::path)) {
|
||||
// If the stroke-linecap changes to or from "butt" then our element
|
||||
// needs to update its cached Moz2D Path, since SVGPathData::BuildPath
|
||||
// decides whether or not to insert little lines into the path for zero
|
||||
// length subpaths base on that property.
|
||||
element->ClearAnyCachedPath();
|
||||
} else if (HasAnyStateBits(NS_STATE_SVG_CLIPPATH_CHILD)) {
|
||||
if (StyleSVG()->mClipRule != oldStyleSVG->mClipRule) {
|
||||
// Moz2D Path objects are fill-rule specific.
|
||||
// For clipPath we use clip-rule as the path's fill-rule.
|
||||
element->ClearAnyCachedPath();
|
||||
}
|
||||
} else {
|
||||
if (StyleSVG()->mFillRule != oldStyleSVG->mFillRule) {
|
||||
// Moz2D Path objects are fill-rule specific.
|
||||
element->ClearAnyCachedPath();
|
||||
} else if (HasAnyStateBits(NS_STATE_SVG_CLIPPATH_CHILD)) {
|
||||
if (StyleSVG()->mClipRule != oldStyleSVG->mClipRule) {
|
||||
// Moz2D Path objects are fill-rule specific.
|
||||
// For clipPath we use clip-rule as the path's fill-rule.
|
||||
element->ClearAnyCachedPath();
|
||||
}
|
||||
} else {
|
||||
if (StyleSVG()->mFillRule != oldStyleSVG->mFillRule) {
|
||||
// Moz2D Path objects are fill-rule specific.
|
||||
element->ClearAnyCachedPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (element->IsGeometryChangedViaCSS(*Style(), *aOldComputedStyle)) {
|
||||
element->ClearAnyCachedPath();
|
||||
}
|
||||
if (element->IsGeometryChangedViaCSS(*Style(), *aOldComputedStyle)) {
|
||||
element->ClearAnyCachedPath();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
<svg width="340" height="140"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||
<title>Circle coordinates and radius specified by properties</title>
|
||||
<html:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html"/>
|
||||
<html:link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1683652"/>
|
||||
<html:link rel="match" href="circle-ref.svg"/>
|
||||
<style>
|
||||
circle {
|
||||
cx: 204px;
|
||||
cy: 56px;
|
||||
r: 5px;
|
||||
fill: blue;
|
||||
}
|
||||
</style>
|
||||
<circle />
|
||||
<script><![CDATA[
|
||||
let circle = document.querySelector("circle");
|
||||
circle.parentNode.style.display = "none";
|
||||
circle.getTotalLength();
|
||||
circle.parentNode.style.display = "";
|
||||
circle.style.r = "65px";
|
||||
]]></script>
|
||||
</svg>
|
After Width: | Height: | Size: 752 B |
Loading…
x
Reference in New Issue
Block a user