Bug 1361639 - Part 1. Depend on input flag, return bbox of an <use> element in different coordinate system. draft
authorcku <cku@mozilla.com>
Tue, 29 Aug 2017 20:41:45 +0800
changeset 656359 5f21c9a29e5fac698f19608412fe3f650d411643
parent 656284 d9b405d82cffb07343a5f2fd941e029298c7f6c4
child 656360 f7360810085667c6759e6a80ae5a7f54fba544c7
push id77183
push userbmo:cku@mozilla.com
push dateThu, 31 Aug 2017 03:28:47 +0000
bugs1361639, 537623
milestone57.0a1
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
dom/svg/SVGTransformableElement.cpp
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- 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.