Bug 1288938: Allow passing different reasons to dirty a non display SVG text frame.
Otherwise, when a glyph changes, we might end up doing too much work, destroying
the text-run and the observer that dirtied the frame, causing an assertion when
trying to delete it from the observer set.
MozReview-Commit-ID: LMQVr6pYFVM
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -838,17 +838,17 @@ nsFrame::DidSetStyleContext(nsStyleConte
// Note that we must check NS_FRAME_FIRST_REFLOW on our SVGTextFrame's
// anonymous block frame rather than our self, since NS_FRAME_FIRST_REFLOW
// may be set on us if we're a new frame that has been inserted after the
// document's first reflow. (In which case this DidSetStyleContext call may
// be happening under frame construction under a Reflow() call.)
if (anonBlock && !(anonBlock->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
(svgTextFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) &&
!(svgTextFrame->GetStateBits() & NS_STATE_SVG_TEXT_IN_REFLOW)) {
- svgTextFrame->ScheduleReflowSVGNonDisplayText();
+ svgTextFrame->ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
}
}
const nsStyleImageLayers *oldLayers = aOldStyleContext ?
&aOldStyleContext->StyleBackground()->mImage :
nullptr;
const nsStyleImageLayers *newLayers = &StyleBackground()->mImage;
AddAndRemoveImageAssociations(this, oldLayers, newLayers);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -650,17 +650,17 @@ InvalidateFrameDueToGlyphsChanged(nsIFra
// If this is a non-display text frame within SVG <text>, we need
// to reflow the SVGTextFrame. (This is similar to reflowing the
// SVGTextFrame in response to style changes, in
// SVGTextFrame::DidSetStyleContext.)
if (f->IsSVGText() && f->GetStateBits() & NS_FRAME_IS_NONDISPLAY) {
auto svgTextFrame = static_cast<SVGTextFrame*>(
nsLayoutUtils::GetClosestFrameOfType(f,
nsGkAtoms::svgTextFrame));
- svgTextFrame->ScheduleReflowSVGNonDisplayText();
+ svgTextFrame->ScheduleReflowSVGNonDisplayText(nsIPresShell::eResize);
} else {
// Theoretically we could just update overflow areas, perhaps using
// OverflowChangedTracker, but that would do a bunch of work eagerly that
// we should probably do lazily here since there could be a lot
// of text frames affected and we'd like to coalesce the work. So that's
// not easy to do well.
shell->FrameNeedsReflow(f, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
}
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -3317,17 +3317,17 @@ SVGTextFrame::DidSetStyleContext(nsStyle
// on the parent of the <defs>, then in
// nsSVGDisplayContainerFrame::ReflowSVG, we would find the non-display
// <defs> container and then call ReflowSVGNonDisplayText on it. If we do
// not actually reflow the parent of the <defs>, then without this
// DidSetStyleContext we would (a) not cause the <text>'s anonymous block
// child to be reflowed when it is next painted, and (b) not cause the
// <text> to be repainted anyway since the user of the <mask> would not
// know it needs to be repainted.
- ScheduleReflowSVGNonDisplayText();
+ ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
}
}
void
SVGTextFrame::ReflowSVGNonDisplayText()
{
MOZ_ASSERT(nsSVGUtils::AnyOuterSVGIsCallingReflowSVG(this),
"only call ReflowSVGNonDisplayText when an outer SVG frame is "
@@ -3351,17 +3351,17 @@ SVGTextFrame::ReflowSVGNonDisplayText()
// Finally, we need to actually reflow the anonymous block frame and update
// mPositions, in case we are being reflowed immediately after a DOM
// mutation that needs frame reconstruction.
MaybeReflowAnonymousBlockChild();
UpdateGlyphPositioning();
}
void
-SVGTextFrame::ScheduleReflowSVGNonDisplayText()
+SVGTextFrame::ScheduleReflowSVGNonDisplayText(nsIPresShell::IntrinsicDirty aReason)
{
MOZ_ASSERT(!nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
"do not call ScheduleReflowSVGNonDisplayText when the outer SVG "
"frame is under ReflowSVG");
MOZ_ASSERT(!(mState & NS_STATE_SVG_TEXT_IN_REFLOW),
"do not call ScheduleReflowSVGNonDisplayText while reflowing the "
"anonymous block child");
@@ -3390,17 +3390,17 @@ SVGTextFrame::ScheduleReflowSVGNonDispla
f->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
}
f = f->GetParent();
}
MOZ_ASSERT(f, "should have found an ancestor frame to reflow");
PresContext()->PresShell()->FrameNeedsReflow(
- f, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
+ f, aReason, NS_FRAME_IS_DIRTY);
}
NS_IMPL_ISUPPORTS(SVGTextFrame::MutationObserver, nsIMutationObserver)
void
SVGTextFrame::MutationObserver::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aFirstNewContent,
@@ -5292,17 +5292,17 @@ SVGTextFrame::ShouldRenderAsPath(nsTextF
return false;
}
void
SVGTextFrame::ScheduleReflowSVG()
{
if (mState & NS_FRAME_IS_NONDISPLAY) {
- ScheduleReflowSVGNonDisplayText();
+ ScheduleReflowSVGNonDisplayText(nsIPresShell::eStyleChange);
} else {
nsSVGUtils::ScheduleReflowSVG(this);
}
}
void
SVGTextFrame::NotifyGlyphMetricsChange()
{
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -398,17 +398,17 @@ public:
* be called on its closest display container frame, so that
* nsSVGDisplayContainerFrame::ReflowSVG will call ReflowSVGNonDisplayText on
* it.
*
* The only case where we have to do this is in response to a style change on
* a non-display <text>. It is done in response to glyphs changes on
* non-display <text> (i.e., animated SVG-in-OpenType glyphs).
*/
- void ScheduleReflowSVGNonDisplayText();
+ void ScheduleReflowSVGNonDisplayText(nsIPresShell::IntrinsicDirty aReason);
/**
* Updates the mFontSizeScaleFactor value by looking at the range of
* font-sizes used within the <text>.
*
* @return Whether mFontSizeScaleFactor changed.
*/
bool UpdateFontSizeScaleFactor();