Bug 951904 - SVGTextFrame should always be reflowed even if it is inside a nonactive child of switch element r=longsonr

SVGTextFrame is special, it should always be reflowed to get the correct metrics.

Differential Revision: https://phabricator.services.mozilla.com/D22841

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-03-21 21:17:18 +00:00
Родитель d931e71177
Коммит 76cd3244f4
3 изменённых файлов: 82 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,34 @@
<body onload="go()">
<svg>
<switch>
<text id="a">Bonjour</text>
<text id="b">Hello</text>
<a><text id="c">Hello</text></a>
<g>
<mask>
<text>Lundi</text>
</mask>
</g>
<switch>
<text id="d">Au revoir</text>
<g>
<mask>
<text>Mercredi</text>
</mask>
</g>
<text id="e">Goodbye</text>
<a><text id="f">Goodbye</text></a>
</switch>
</switch>
</svg>
</body>
<script>
function go() {
a.getComputedTextLength();
b.getComputedTextLength();
c.getComputedTextLength();
d.getComputedTextLength();
e.getComputedTextLength();
f.getComputedTextLength();
}
</script>

Просмотреть файл

@ -182,6 +182,7 @@ load 898951-1.svg
load 913990.html
load 919371-1.xhtml
load 950324-1.svg
load 951904-1.html
load 952270-1.svg
load 963086-1.svg
load 974746-1.svg

Просмотреть файл

@ -10,6 +10,8 @@
#include "nsSVGGFrame.h"
#include "mozilla/dom/SVGSwitchElement.h"
#include "nsSVGUtils.h"
#include "SVGTextFrame.h"
#include "nsSVGContainerFrame.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -51,6 +53,8 @@ class nsSVGSwitchFrame final : public nsSVGGFrame {
private:
nsIFrame* GetActiveChildFrame();
void ReflowAllSVGTextFramesInsideNonActiveChildren(nsIFrame* aActiveChild);
static void AlwaysReflowSVGTextFrameDoForOneKid(nsIFrame* aKid);
};
//----------------------------------------------------------------------
@ -135,6 +139,47 @@ nsIFrame* nsSVGSwitchFrame::GetFrameForPoint(const gfxPoint& aPoint) {
return nullptr;
}
void nsSVGSwitchFrame::AlwaysReflowSVGTextFrameDoForOneKid(nsIFrame* aKid) {
if (!NS_SUBTREE_DIRTY(aKid)) {
return;
}
LayoutFrameType type = aKid->Type();
if (type == LayoutFrameType::SVGText) {
MOZ_ASSERT(!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY),
"A non-display SVGTextFrame directly contained in a display "
"container?");
static_cast<SVGTextFrame*>(aKid)->ReflowSVG();
} else if (aKid->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer) ||
type == LayoutFrameType::SVGForeignObject ||
!aKid->IsFrameOfType(nsIFrame::eSVG)) {
if (!aKid->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY)) {
for (nsIFrame* kid : aKid->PrincipalChildList()) {
AlwaysReflowSVGTextFrameDoForOneKid(kid);
}
} else {
// This child is in a nondisplay context, something like:
// <switch>
// ...
// <g><mask><text></text></mask></g>
// </switch>
// We should not call ReflowSVG on it.
nsSVGContainerFrame::ReflowSVGNonDisplayText(aKid);
}
}
}
void nsSVGSwitchFrame::ReflowAllSVGTextFramesInsideNonActiveChildren(
nsIFrame* aActiveChild) {
for (nsIFrame* kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) {
if (aActiveChild == kid) {
continue;
}
AlwaysReflowSVGTextFrameDoForOneKid(kid);
}
}
void nsSVGSwitchFrame::ReflowSVG() {
NS_ASSERTION(nsSVGUtils::OuterSVGIsCallingReflowSVG(this),
"This call is probably a wasteful mistake");
@ -165,6 +210,8 @@ void nsSVGSwitchFrame::ReflowSVG() {
nsOverflowAreas overflowRects;
nsIFrame* child = GetActiveChildFrame();
ReflowAllSVGTextFramesInsideNonActiveChildren(child);
nsSVGDisplayableFrame* svgChild = do_QueryFrame(child);
if (svgChild) {
MOZ_ASSERT(!(child->GetStateBits() & NS_FRAME_IS_NONDISPLAY),