Bug 1361639 - Part 1. Depend on input flag, return bbox of an <use> element in different coordinate system.
When nsSVGUtils::getBBox is called on <use> element:
1. Call from SVGGraphicsElement::getBBox(WebAPI):
According to the spec, getBBox should return the bbox as the union box of
children in user space.
2. Call from mask/ clip-path or filter painting:
Since we want to paint those elements in the coordinate space formed by
<use>(
bug 537623), getBBox should return the bbox as the union box of
children in coordinate system of <use>.
Depend on the use case, we return the bbox of an <use> element on different
coordinate system. In this patch, I bring in a new
flag(eInUserSpaceOfUseElement) so that nsSVGUtils::getBBox can return bbox on
different coordinate system accordingly.
MozReview-Commit-ID: FfZalTI8J0y
--- a/dom/svg/SVGTransformableElement.cpp
+++ b/dom/svg/SVGTransformableElement.cpp
@@ -183,19 +183,21 @@ SVGTransformableElement::GetBBox(const S
}
nsSVGDisplayableFrame* svgframe = do_QueryFrame(frame);
if (!svgframe) {
rv.Throw(NS_ERROR_NOT_IMPLEMENTED); // XXX: outer svg
return nullptr;
}
if (!NS_SVGNewGetBBoxEnabled()) {
- return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame)));
+ return NS_NewSVGRect(this, ToRect(nsSVGUtils::GetBBox(frame,
+ nsSVGUtils::eBBoxIncludeFillGeometry |
+ nsSVGUtils::eUseUserSpaceOfUseElement)));
} else {
- uint32_t flags = 0;
+ uint32_t flags = nsSVGUtils::eUseUserSpaceOfUseElement;
if (aOptions.mFill) {
flags |= nsSVGUtils::eBBoxIncludeFill;
}
if (aOptions.mStroke) {
flags |= nsSVGUtils::eBBoxIncludeStroke;
}
if (aOptions.mMarkers) {
flags |= nsSVGUtils::eBBoxIncludeMarkers;
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1122,17 +1122,19 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
}
}
gfxMatrix matrix;
if (aToBoundsSpace) {
matrix = *aToBoundsSpace;
}
- if (aFrame->IsSVGForeignObjectFrame()) {
+ if (aFrame->IsSVGForeignObjectFrame() ||
+ (aFrame->IsSVGUseFrame() &&
+ (aFlags & nsSVGUtils::eUseUserSpaceOfUseElement))) {
// The spec says getBBox "Returns the tight bounding box in *current user
// space*". So we should really be doing this for all elements, but that
// needs investigation to check that we won't break too much content.
// NOTE: When changing this to apply to other frame types, make sure to
// also update nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset.
MOZ_ASSERT(content->IsSVGElement(), "bad cast");
nsSVGElement *element = static_cast<nsSVGElement*>(content);
matrix = element->PrependLocalTransformsTo(matrix, eChildToUserSpace);
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -399,16 +399,21 @@ public:
// element's bounds to be returned instead.
eUseFrameBoundsForOuterSVG = 1 << 6,
// https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
eForGetClientRects = 1 << 7,
// If the given frame is an HTML element, only include the region of the
// given frame, instead of all continuations of it, while computing bbox if
// this flag is set.
eIncludeOnlyCurrentFrameForNonSVGElement = 1 << 8,
+ // This flag is only has an effect when the target is a <use> element.
+ // getBBox returns the bounds of the elements children in user space if
+ // this flag is set; Otherwise, getBBox returns the union bounds in
+ // the coordinate system formed by the <use> element.
+ eUseUserSpaceOfUseElement = 1 << 9,
};
/**
* This function in primarily for implementing the SVG DOM function getBBox()
* and the SVG attribute value 'objectBoundingBox'. However, it has been
* extended with various extra parameters in order to become more of a
* general purpose getter of all sorts of bounds that we might need to obtain
* for SVG elements, or even for other elements that have SVG effects applied
* to them.