Bug 937268 - Should implement getBBox() for tspan r=longsonr

We implements getBBox for tspan. The implementation also has consistent
behavior as getBoundingClientRect.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-14 05:57:24 +00:00
parent 0376cbf447
commit a92c08d83f
3 changed files with 56 additions and 6 deletions

View File

@ -15,6 +15,7 @@
#include "mozilla/dom/SVGSVGElement.h"
#include "nsContentUtils.h"
#include "nsIFrame.h"
#include "SVGTextFrame.h"
#include "SVGContentUtils.h"
#include "nsSVGDisplayableFrame.h"
#include "nsSVGUtils.h"
@ -164,9 +165,41 @@ already_AddRefed<SVGIRect> SVGTransformableElement::GetBBox(
return nullptr;
}
nsSVGDisplayableFrame* svgframe = do_QueryFrame(frame);
if (!svgframe) {
rv.Throw(NS_ERROR_NOT_IMPLEMENTED); // XXX: outer svg
return nullptr;
if (!nsSVGUtils::IsInSVGTextSubtree(frame)) {
rv.Throw(NS_ERROR_NOT_IMPLEMENTED); // XXX: outer svg
return nullptr;
}
// For <tspan>, <textPath>, the frame is an nsInlineFrame or
// nsBlockFrame, |svgframe| will be a nullptr.
// We implement their getBBox directly here instead of in
// nsSVGUtils::GetBBox, because nsSVGUtils::GetBBox is more
// or less used for other purpose elsewhere. e.g. gradient
// code assumes GetBBox of <tspan> returns the bbox of the
// outer <text>.
// TODO: cleanup this sort of usecase of nsSVGUtils::GetBBox,
// then move this code nsSVGUtils::GetBBox.
SVGTextFrame* text =
static_cast<SVGTextFrame*>(nsLayoutUtils::GetClosestFrameOfType(
frame->GetParent(), LayoutFrameType::SVGText));
if (text->HasAnyStateBits(NS_FRAME_IS_NONDISPLAY)) {
rv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
gfxRect rec = text->TransformFrameRectFromTextChild(
frame->GetRectRelativeToSelf(), frame);
// Should also add the |x|, |y| of the SVGTextFrame itself, since
// the result obtained by TransformFrameRectFromTextChild doesn't
// include them.
rec.x += float(text->GetPosition().x) / AppUnitsPerCSSPixel();
rec.y += float(text->GetPosition().y) / AppUnitsPerCSSPixel();
return NS_NewSVGRect(this, ToRect(rec));
}
if (!NS_SVGNewGetBBoxEnabled()) {

View File

@ -4,12 +4,13 @@
<foreignObject id="fO" x="10" y="10" width="100" height="100"/>
<image id="i" x="10" y="10" width="100" height="100"/>
</g>
<text id="b" x="20" y="20">b</text>
<text id="b" x="100" y="100">abcdef</text>
<text id="a" x="20" y="30">a</text>
<text id="y" x="20" y="40">y</text>
<text id="tspan">
<tspan x="20" y="20">b</tspan>
<text id="tspantext1">
<tspan id="tspan1" x="100" y="100">abcdef</tspan>
</text>
<text id="tspantext2" x="100" y="100">ABCEDF<tspan id="tspan2">ABCEDF</tspan></text>
<text id="text" x="20" y="60">text</text>
<!-- &#8206; is the same as the HTML &lrm; -->
<text id="lrmText" x="20" y="60">&#8206;text</text>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -46,17 +46,33 @@ function run() {
isFuzzy(bbox1.width, bbox2.width, 0.0002, id1 + ".getBBox().width");
is(bbox1.height, bbox2.height, id1 + ".getBBox().height");
}
function compareBBoxFuzzy(id1, id2, err) {
var bbox1 = getBBox(id1);
var bbox2 = getBBox(id2);
isfuzzy(bbox1.x, bbox2.x, err, id1 + ".getBBox().x");
isfuzzy(bbox1.y, bbox2.y, err, id1 + ".getBBox().y");
isfuzzy(bbox1.width, bbox2.width, err, id1 + ".getBBox().width");
isfuzzy(bbox1.height, bbox2.height, err, id1 + ".getBBox().height");
}
function compareBBoxHeight(id1, id2) {
var bbox1 = getBBox(id1);
var bbox2 = getBBox(id2);
is(bbox1.height, bbox2.height, id1 + ".getBBox().height");
}
function compareBBoxWidthWithScaleFuzzy(id1, id2, scaleOfId2, err) {
var bbox1 = getBBox(id1);
var bbox2 = getBBox(id2);
isfuzzy(bbox1.width, bbox2.width * scaleOfId2, err, id1 + ".getBBox().width");
}
checkBBox("fO", 10, 10, 100, 100, 0.0);
checkBBox("i", 10, 10, 100, 100, 0.0);
compareBBoxHeight("a", "b");
compareBBoxHeight("a", "y");
compareBBox("b", "tspan");
compareBBox("b", "tspantext1");
compareBBoxFuzzy("tspantext1", "tspan1", 5);
compareBBoxHeight("tspantext2", "tspan2");
compareBBoxWidthWithScaleFuzzy("tspantext2", "tspan2", 2, 5);
compareBBoxHeight("text", "lrmText");
checkBBox("v", 95, 45, 10, 155, 0.001);
checkBBox("h", 195, 45, 105, 55, 0.001);