Bug 1347411 part 2. Fix stylo to properly update styles for the various frames that use FCDATA_WITH_WRAPPING_BLOCK to wrap an anonymous block around their kids. r?heycam
This handles ::-moz-button-content, ::-moz-html-canvas-content, ::-moz-svg-text,
::-moz-svg-foreign-content.
MozReview-Commit-ID: 3xk7214X2uR
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3995,16 +3995,18 @@ nsCSSFrameConstructor::ConstructFrameFro
} else {
innerFrame = NS_NewBlockFormattingContext(mPresShell, outerSC);
InitAndRestoreFrame(aState, content, container, innerFrame);
outerFrame = innerFrame;
}
SetInitialSingleChild(container, outerFrame);
+ container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
+
// Now figure out whether newFrame or outerFrame should be the
// absolute container.
auto outerDisplay = outerSC->StyleDisplay();
if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
maybeAbsoluteContainingBlockDisplay = outerDisplay;
maybeAbsoluteContainingBlock = outerFrame;
maybeAbsoluteContainingBlockStyleFrame = outerFrame;
innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -395,16 +395,29 @@ nsHTMLButtonControlFrame::GetAdditionalS
void
nsHTMLButtonControlFrame::SetAdditionalStyleContext(int32_t aIndex,
nsStyleContext* aStyleContext)
{
mRenderer.SetStyleContext(aIndex, aStyleContext);
}
+void
+nsHTMLButtonControlFrame::DoUpdateStyleOfOwnedAnonBoxes(
+ ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame)
+{
+ MOZ_ASSERT(mFrames.FirstChild(), "Must have our button-content anon box");
+ MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
+ "Must only have our button-content anon box");
+ UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
+ aStyleSet, aChangeList, aHintForThisFrame);
+}
+
#ifdef DEBUG
void
nsHTMLButtonControlFrame::AppendFrames(ChildListID aListID,
nsFrameList& aFrameList)
{
MOZ_CRASH("unsupported operation");
}
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -92,16 +92,22 @@ public:
}
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
+ /**
+ * Update the style of our ::-moz-button-content anonymous box.
+ */
+ void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame) override;
protected:
virtual bool IsInput() { return false; }
// Indicates whether we should clip our children's painting to our
// border-box (either because of "overflow" or because of legacy reasons
// about how <input>-flavored buttons work).
bool ShouldClipPaintingToBorderBox();
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -414,16 +414,28 @@ nsHTMLCanvasFrame::GetContinuationOffset
offset += rect.height;
}
offset -= mBorderPadding.GetPhysicalMargin(GetWritingMode()).top;
offset = std::max(0, offset);
}
return offset;
}
+void
+nsHTMLCanvasFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame)
+{
+ MOZ_ASSERT(mFrames.FirstChild(), "Must have our canvas content anon box");
+ MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
+ "Must only have our canvas content anon box");
+ UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
+ aStyleSet, aChangeList, aHintForThisFrame);
+}
+
#ifdef ACCESSIBILITY
a11y::AccType
nsHTMLCanvasFrame::AccessibleType()
{
return a11y::eHTMLCanvasType;
}
#endif
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -94,16 +94,22 @@ public:
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
// Inserted child content gets its frames parented by our child block
virtual nsContainerFrame* GetContentInsertionFrame() override {
return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
}
+ /**
+ * Update the style of our ::-moz-html-canvas-content anonymous box.
+ */
+ void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame) override;
protected:
virtual ~nsHTMLCanvasFrame();
nscoord GetContinuationOffset(nscoord* aWidth = 0) const;
mozilla::LogicalMargin mBorderPadding;
};
--- a/layout/reftests/canvas/reftest-stylo.list
+++ b/layout/reftests/canvas/reftest-stylo.list
@@ -107,8 +107,11 @@ fails asserts-if(stylo,1) == 1107096-inv
== 1201272-1.html 1201272-1.html
== 1224976-1.html 1224976-1.html
== 1238795-1.html 1238795-1.html
== 1303534-1.html 1303534-1.html
fails asserts-if(stylo,1) == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1.html # bug 1324700
fails asserts-if(stylo,1) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2.html # bug 1324700
fails asserts-if(stylo,1) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1.html # bug 1324700
+
+skip-if(stylo) == text-indent-1a.html text-indent-1a.html # Bug 1347410
+fails == text-indent-1b.html text-indent-1b.html # Bug 1347410
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -103,8 +103,11 @@ fuzzy-if(d2d,12,21) fuzzy-if(skiaContent
== 1201272-1.html 1201272-1-ref.html
== 1224976-1.html 1224976-1-ref.html
== 1238795-1.html 1238795-1-ref.html
== 1303534-1.html 1303534-1-ref.html
== 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1-ref.html
fuzzy-if(winWidget,1,14) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2-ref.html
fuzzy-if(winWidget,94,1575) fuzzy-if(cocoaWidget,1,24) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1-ref.html
+
+== text-indent-1a.html text-indent-1-ref.html
+== text-indent-1b.html text-indent-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<iframe sandbox
+ style="width: 400px"
+ srcdoc="<div style='text-indent: 50vw'>Text</div>"></iframe>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1a.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<iframe sandbox
+ style="width: 400px"
+ srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1b.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <iframe sandbox
+ style="width: 200px"
+ srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>
+ <script>
+ onload = function() {
+ var i = document.querySelector("iframe");
+ window.w = i.offsetWidth;
+ i.style.width = "400px";
+ document.documentElement.className = "";
+ }
+ </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/dynamic-text-indent-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+ <button style="text-indent: 50px">Some text</button>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/dynamic-text-indent.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <button>Some text</button>
+ <script>
+ onload = function() {
+ var obj = document.querySelector("button");
+ window.w = obj.getBoundingClientRect().width;
+ obj.style.textIndent = "50px";
+ document.documentElement.className = "";
+ }
+ </script>
+</html>
--- a/layout/reftests/forms/button/reftest-stylo.list
+++ b/layout/reftests/forms/button/reftest-stylo.list
@@ -35,8 +35,10 @@ fails == disabled-6.html disabled-6.html
== width-auto-size-em-ltr.html width-auto-size-em-ltr.html
== width-auto-size-ltr.html width-auto-size-ltr.html
fails == width-exact-fit-ltr.html width-exact-fit-ltr.html # Bug 1341086
== width-auto-size-em-rtl.html width-auto-size-em-rtl.html
== width-auto-size-rtl.html width-auto-size-rtl.html
fails == width-exact-fit-rtl.html width-exact-fit-rtl.html # Bug 1341086
fails == display-grid-flex-columnset.html display-grid-flex-columnset.html
== 1317351.html 1317351.html
+
+fails == dynamic-text-indent.html dynamic-text-indent.html # Bug 1341086
--- a/layout/reftests/forms/button/reftest.list
+++ b/layout/reftests/forms/button/reftest.list
@@ -34,8 +34,10 @@ fails-if(Android) == disabled-1.html dis
== width-auto-size-em-ltr.html width-auto-size-em-ltr-ref.html
== width-auto-size-ltr.html width-auto-size-ltr-ref.html
== width-exact-fit-ltr.html width-auto-size-ltr-ref.html
== width-auto-size-em-rtl.html width-auto-size-em-rtl-ref.html
== width-auto-size-rtl.html width-auto-size-rtl-ref.html
== width-exact-fit-rtl.html width-auto-size-rtl-ref.html
== display-grid-flex-columnset.html display-grid-flex-columnset-ref.html
== 1317351.html 1317351-ref.html
+
+== dynamic-text-indent.html dynamic-text-indent-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/foreignObject-dynamic-line-height-01-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+ <svg>
+ <foreignObject width="100" height="100" style="line-height: 3">
+ This is long text that wraps.
+ </foreignObject>
+ </svg>
+</htmml>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/foreignObject-dynamic-line-height-01.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <svg>
+ <foreignObject width="100" height="100">
+ This is long text that wraps.
+ </foreignObject>
+ </svg>
+ <script>
+ onload = function() {
+ var obj = document.querySelector("foreignObject");
+ window.w = obj.getBoundingClientRect().width;
+ obj.style.lineHeight = 3;
+ document.documentElement.className = "";
+ }
+ </script>
+</htmml>
--- a/layout/reftests/svg/reftest-stylo.list
+++ b/layout/reftests/svg/reftest-stylo.list
@@ -180,16 +180,17 @@ fuzzy-if(skiaContent,1,800000) == filter
== foreignObject-start-hidden-01.svg foreignObject-start-hidden-01.svg
== foreignObject-start-hidden-02.svg foreignObject-start-hidden-02.svg
== foreignObject-style-change-01.svg foreignObject-style-change-01.svg
== foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01.html
== foreignObject-fixedpos-01.html foreignObject-fixedpos-01.html
== foreignObject-fixedpos-02.html foreignObject-fixedpos-02.html
== foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-fixedpos-01.html
== foreignObject-vertical-01.svg foreignObject-vertical-01.svg
+== foreignObject-dynamic-line-height-01.html foreignObject-dynamic-line-height-01.html
== g-transform-01.svg g-transform-01.svg
== getElementById-a-element-01.svg getElementById-a-element-01.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01a.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg gradient-live-01b.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01c.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01d.svg
== gradient-transform-01.svg gradient-transform-01.svg
== import-svg-01.html import-svg-01.html
@@ -340,16 +341,18 @@ fuzzy-if(OSX==1007,6,2) fuzzy-if(OSX==10
== text-layout-05.svg text-layout-05.svg
fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layout-06.svg
== text-layout-07.svg text-layout-07.svg
== text-layout-08.svg text-layout-08.svg
== text-scale-01.svg text-scale-01.svg
fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02.svg
HTTP(..) == text-scale-03.svg text-scale-03.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01.svg
+== text-stroke-scaling-02a.html text-stroke-scaling-02a.html
+== text-stroke-scaling-02b.html text-stroke-scaling-02b.html
== stroke-dasharray-01.svg stroke-dasharray-01.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg stroke-dasharray-02.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg stroke-dasharray-03.svg
== stroke-dasharray-and-pathLength-01.svg stroke-dasharray-and-pathLength-01.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01.svg
== stroke-dashoffset-01.svg stroke-dashoffset-01.svg
== stroke-dashoffset-and-pathLength-01.svg stroke-dashoffset-and-pathLength-01.svg
== stroke-linecap-round-w-zero-length-segs-01.svg stroke-linecap-round-w-zero-length-segs-01.svg
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -179,16 +179,17 @@ fuzzy-if(skiaContent,1,800000) == filter
== foreignObject-start-hidden-01.svg pass.svg # followup from Bug 596765
== foreignObject-start-hidden-02.svg pass.svg
== foreignObject-style-change-01.svg pass.svg
== foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01-ref.html
fuzzy-if(Android,18,600) == foreignObject-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
== foreignObject-fixedpos-02.html foreignObject-fixedpos-ref.html
== foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
== foreignObject-vertical-01.svg foreignObject-vertical-01-ref.svg
+== foreignObject-dynamic-line-height-01.html foreignObject-dynamic-line-height-01-ref.html
== g-transform-01.svg pass.svg
== getElementById-a-element-01.svg pass.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01-ref.svg
== gradient-transform-01.svg pass.svg
fuzzy-if(skiaContent,1,550) == import-svg-01.html pass.svg
@@ -339,16 +340,19 @@ random-if(gtkWidget) != text-language-01
== text-layout-05.svg text-layout-05-ref.svg
fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layout-06-ref.svg
== text-layout-07.svg text-layout-07-ref.svg
== text-layout-08.svg text-layout-08-ref.svg
== text-scale-01.svg text-scale-01-ref.svg
fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02-ref.svg
HTTP(..) == text-scale-03.svg text-scale-03-ref.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
+fuzzy(16,3) == text-stroke-scaling-02a.html text-stroke-scaling-02-ref.html # antialiasing
+fuzzy(16,3) == text-stroke-scaling-02b.html text-stroke-scaling-02-ref.html # antialiasing
+== text-stroke-scaling-02a.html text-stroke-scaling-02b.html
== stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg pass.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg pass.svg
== stroke-dasharray-and-pathLength-01.svg pass.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg
== stroke-dashoffset-01.svg pass.svg
== stroke-dashoffset-and-pathLength-01.svg pass.svg
== stroke-linecap-round-w-zero-length-segs-01.svg pass.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <svg width="500" height="400">
+ <text x="0" y="20" style="stroke: orange; stroke-width: 0.5px"
+ transform="scale(4)">
+ This is some text
+ </text>
+ </svg>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02a.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <svg width="500" height="400">
+ <text x="0" y="20" style="stroke: orange; stroke-width: 2px"
+ transform="scale(4)">
+ This is some text
+ </text>
+ </svg>
+ <script>
+ onload = function() {
+ var obj = document.querySelector("text");
+ window.w = obj.getBoundingClientRect().width;
+ obj.style.vectorEffect = "non-scaling-stroke";
+ document.documentElement.className = "";
+ }
+ </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02b.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <svg width="500" height="400">
+ <text x="0" y="20" style="stroke: orange; vector-effect: non-scaling-stroke;
+ stroke-width: 2px"
+ transform="scale(4)">
+ This is some text
+ </text>
+ </svg>
+</html>
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -5647,8 +5647,18 @@ SVGTextFrame::TransformFrameRectFromText
// Subtract the mRect offset from the result, as our user space for
// this frame is relative to the top-left of mRect.
float factor = presContext->AppUnitsPerCSSPixel();
gfxPoint framePosition(NSAppUnitsToFloatPixels(mRect.x, factor),
NSAppUnitsToFloatPixels(mRect.y, factor));
return result - framePosition;
}
+
+void
+SVGTextFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame)
+{
+ MOZ_ASSERT(PrincipalChildList().FirstChild(), "Must have our anon box");
+ UpdateStyleOfChildAnonBox(PrincipalChildList().FirstChild(),
+ aStyleSet, aChangeList, aHintForThisFrame);
+}
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -366,16 +366,23 @@ public:
* Takes an app unit rectangle in the coordinate space of a given descendant
* frame of this frame, and returns a rectangle in the <text> element's user
* space that covers all parts of rendered runs that intersect with the
* rectangle.
*/
gfxRect TransformFrameRectFromTextChild(const nsRect& aRect,
nsIFrame* aChildFrame);
+ /**
+ * Update the style of our ::-moz-svg-text anonymous box.
+ */
+ void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame) override;
+
private:
/**
* Mutation observer used to watch for text positioning attribute changes
* on descendent text content elements (like <tspan>s).
*/
class MutationObserver final : public nsStubMutationObserver {
public:
explicit MutationObserver(SVGTextFrame* aFrame)
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -584,9 +584,18 @@ nsSVGForeignObjectFrame::GetInvalidRegio
r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
nsRect rect = nsSVGUtils::ToCanvasBounds(r, GetCanvasTM(), PresContext());
rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
return rect;
}
return nsRect();
}
-
+void
+nsSVGForeignObjectFrame::DoUpdateStyleOfOwnedAnonBoxes(
+ ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame)
+{
+ MOZ_ASSERT(PrincipalChildList().FirstChild(), "Must have our anon box");
+ UpdateStyleOfChildAnonBox(PrincipalChildList().FirstChild(),
+ aStyleSet, aChangeList, aHintForThisFrame);
+}
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -84,16 +84,23 @@ public:
virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
uint32_t aFlags) override;
virtual bool IsDisplayContainer() override { return true; }
gfxMatrix GetCanvasTM();
nsRect GetInvalidRegion();
+ /**
+ * Update the style of our ::-moz-svg-foreign-content anonymous box.
+ */
+ void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+ nsStyleChangeList& aChangeList,
+ nsChangeHint aHintForThisFrame) override;
+
protected:
// implementation helpers:
void DoReflow();
void RequestReflow(nsIPresShell::IntrinsicDirty aType);
// If width or height is less than or equal to zero we must disable rendering
bool IsDisabled() const { return mRect.width <= 0 || mRect.height <= 0; }