mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 898909 - Reflow non-display SVG text under non-display outer <svg> frames. r=jwatt
This commit is contained in:
parent
eb70871278
commit
707aa0fde3
11
layout/svg/crashtests/898909-1.svg
Normal file
11
layout/svg/crashtests/898909-1.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" requiredFeatures="foo">
|
||||
|
||||
<text id="t" />
|
||||
|
||||
<script>
|
||||
window.addEventListener("load", function() {
|
||||
document.getElementById("t").getComputedTextLength();
|
||||
}, false);
|
||||
</script>
|
||||
|
||||
</svg>
|
After Width: | Height: | Size: 239 B |
@ -174,4 +174,5 @@ load 890783-1.svg
|
||||
load 893510-1.svg
|
||||
load 895311-1.svg
|
||||
load 897342-1.svg
|
||||
load 898909-1.svg
|
||||
load 898951-1.svg
|
||||
|
@ -82,6 +82,53 @@ nsSVGContainerFrame::UpdateOverflow()
|
||||
return nsSVGContainerFrameBase::UpdateOverflow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses a frame tree, marking any nsSVGTextFrame2 frames as dirty
|
||||
* and calling InvalidateRenderingObservers() on it.
|
||||
*
|
||||
* The reason that this helper exists is because nsSVGTextFrame2 is special.
|
||||
* None of the other SVG frames ever need to be reflowed when they have the
|
||||
* NS_FRAME_IS_NONDISPLAY bit set on them because their PaintSVG methods
|
||||
* (and those of any containers that they can validly be contained within) do
|
||||
* not make use of mRect or overflow rects. "em" lengths, etc., are resolved
|
||||
* as those elements are painted.
|
||||
*
|
||||
* nsSVGTextFrame2 is different because its anonymous block and inline frames
|
||||
* need to be reflowed in order to get the correct metrics when things like
|
||||
* inherited font-size of an ancestor changes, or a delayed webfont loads and
|
||||
* applies.
|
||||
*
|
||||
* We assume that any change that requires the anonymous kid of an
|
||||
* nsSVGTextFrame2 to reflow will result in an NS_FRAME_IS_DIRTY reflow. When
|
||||
* that reflow reaches an NS_FRAME_IS_NONDISPLAY frame it would normally
|
||||
* stop, but this helper looks for any nsSVGTextFrame2 descendants of such
|
||||
* frames and marks them NS_FRAME_IS_DIRTY so that the next time that they are
|
||||
* painted their anonymous kid will first get the necessary reflow.
|
||||
*/
|
||||
/* static */ void
|
||||
nsSVGContainerFrame::ReflowSVGNonDisplayText(nsIFrame* aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY,
|
||||
"expected aContainer to be NS_FRAME_IS_DIRTY");
|
||||
NS_ASSERTION((aContainer->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
|
||||
!aContainer->IsFrameOfType(nsIFrame::eSVG),
|
||||
"it is wasteful to call ReflowSVGNonDisplayText on a container "
|
||||
"frame that is not NS_FRAME_IS_NONDISPLAY");
|
||||
for (nsIFrame* kid = aContainer->GetFirstPrincipalChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsIAtom* type = kid->GetType();
|
||||
if (type == nsGkAtoms::svgTextFrame2) {
|
||||
static_cast<nsSVGTextFrame2*>(kid)->ReflowSVGNonDisplayText();
|
||||
} else {
|
||||
if (kid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
|
||||
type == nsGkAtoms::svgForeignObjectFrame ||
|
||||
!kid->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
ReflowSVGNonDisplayText(kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGDisplayContainerFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
@ -242,53 +289,6 @@ nsSVGDisplayContainerFrame::GetCoveredRegion()
|
||||
return nsSVGUtils::GetCoveredRegion(mFrames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses a frame tree, marking any nsSVGTextFrame2 frames as dirty
|
||||
* and calling InvalidateRenderingObservers() on it.
|
||||
*
|
||||
* The reason that this helper exists is because nsSVGTextFrame2 is special.
|
||||
* None of the other SVG frames ever need to be reflowed when they have the
|
||||
* NS_FRAME_IS_NONDISPLAY bit set on them because their PaintSVG methods
|
||||
* (and those of any containers that they can validly be contained within) do
|
||||
* not make use of mRect or overflow rects. "em" lengths, etc., are resolved
|
||||
* as those elements are painted.
|
||||
*
|
||||
* nsSVGTextFrame2 is different because its anonymous block and inline frames
|
||||
* need to be reflowed in order to get the correct metrics when things like
|
||||
* inherited font-size of an ancestor changes, or a delayed webfont loads and
|
||||
* applies.
|
||||
*
|
||||
* We assume that any change that requires the anonymous kid of an
|
||||
* nsSVGTextFrame2 to reflow will result in an NS_FRAME_IS_DIRTY reflow. When
|
||||
* that reflow reaches an NS_FRAME_IS_NONDISPLAY frame it would normally
|
||||
* stop, but this helper looks for any nsSVGTextFrame2 descendants of such
|
||||
* frames and marks them NS_FRAME_IS_DIRTY so that the next time that they are
|
||||
* painted their anonymous kid will first get the necessary reflow.
|
||||
*/
|
||||
static void
|
||||
ReflowSVGNonDisplayText(nsIFrame* aContainer)
|
||||
{
|
||||
NS_ASSERTION(aContainer->GetStateBits() & NS_FRAME_IS_DIRTY,
|
||||
"expected aContainer to be NS_FRAME_IS_DIRTY");
|
||||
NS_ASSERTION((aContainer->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
|
||||
!aContainer->IsFrameOfType(nsIFrame::eSVG),
|
||||
"it is wasteful to call ReflowSVGNonDisplayText on a container "
|
||||
"frame that is not NS_FRAME_IS_NONDISPLAY");
|
||||
for (nsIFrame* kid = aContainer->GetFirstPrincipalChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
nsIAtom* type = kid->GetType();
|
||||
if (type == nsGkAtoms::svgTextFrame2) {
|
||||
static_cast<nsSVGTextFrame2*>(kid)->ReflowSVGNonDisplayText();
|
||||
} else {
|
||||
if (kid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
|
||||
type == nsGkAtoms::svgForeignObjectFrame ||
|
||||
!kid->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
ReflowSVGNonDisplayText(kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGDisplayContainerFrame::ReflowSVG()
|
||||
{
|
||||
|
@ -91,6 +91,13 @@ public:
|
||||
const nsDisplayListSet& aLists) MOZ_OVERRIDE {}
|
||||
|
||||
virtual bool UpdateOverflow() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Traverses a frame tree, marking any nsSVGTextFrame2 frames as dirty
|
||||
* and calling InvalidateRenderingObservers() on it.
|
||||
*/
|
||||
static void ReflowSVGNonDisplayText(nsIFrame* aContainer);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -463,21 +463,21 @@ nsSVGOuterSVGFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
mViewportInitialized = true;
|
||||
|
||||
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
|
||||
// Now that we've marked the necessary children as dirty, call
|
||||
// ReflowSVG() on them:
|
||||
|
||||
mCallingReflowSVG = true;
|
||||
|
||||
// Now that we've marked the necessary children as dirty, call
|
||||
// ReflowSVG() or ReflowSVGNonDisplayText() on them, depending
|
||||
// on whether we are non-display.
|
||||
mCallingReflowSVG = true;
|
||||
if (GetStateBits() & NS_FRAME_IS_NONDISPLAY) {
|
||||
ReflowSVGNonDisplayText(this);
|
||||
} else {
|
||||
// Update the mRects and visual overflow rects of all our descendants,
|
||||
// including our anonymous wrapper kid:
|
||||
anonKid->AddStateBits(mState & NS_FRAME_IS_DIRTY);
|
||||
anonKid->ReflowSVG();
|
||||
NS_ABORT_IF_FALSE(!anonKid->GetNextSibling(),
|
||||
"We should have one anonymous child frame wrapping our real children");
|
||||
|
||||
mCallingReflowSVG = false;
|
||||
}
|
||||
mCallingReflowSVG = false;
|
||||
|
||||
// Set our anonymous kid's offset from our border box:
|
||||
anonKid->SetPosition(GetContentRectRelativeToSelf().TopLeft());
|
||||
|
Loading…
Reference in New Issue
Block a user