Bug 1320036 - Part 1. Correct objectBoundingBox region of a filter applied to an outer SVG element. draft
authorcku <cku@mozilla.com>
Wed, 15 Mar 2017 18:36:53 +0800
changeset 499028 95cf80425bbaad823a9c48cdb59b76e11cbe0674
parent 498697 8dd496fd015a2b6e99573070279d9d1593836ea9
child 499029 06b2ebbe1a820cfd1fc9228b6cde97250e410e75
push id49319
push userbmo:cku@mozilla.com
push dateWed, 15 Mar 2017 10:59:57 +0000
bugs1320036
milestone55.0a1
Bug 1320036 - Part 1. Correct objectBoundingBox region of a filter applied to an outer SVG element. MozReview-Commit-ID: 8frACVe2gFE
layout/svg/nsFilterInstance.cpp
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -177,17 +177,19 @@ nsFilterInstance::nsFilterInstance(nsIFr
   , mPaintCallback(aPaintCallback)
   , mPaintTransform(aPaintTransform)
   , mInitialized(false)
 {
   if (aOverrideBBox) {
     mTargetBBox = *aOverrideBBox;
   } else {
     MOZ_ASSERT(mTargetFrame, "Need to supply a frame when there's no aOverrideBBox");
-    mTargetBBox = nsSVGUtils::GetBBox(mTargetFrame);
+    mTargetBBox = nsSVGUtils::GetBBox(mTargetFrame,
+                                      nsSVGUtils::eUseFrameBoundsForOuterSVG |
+                                      nsSVGUtils::eBBoxIncludeFillGeometry);
   }
 
   // Compute user space to filter space transforms.
   if (!ComputeUserSpaceToFilterSpaceScale()) {
     return;
   }
 
   if (!ComputeTargetBBoxInFilterSpace()) {
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -187,18 +187,18 @@ nsSVGIntegrationUtils::GetSVGCoordContex
   nsPresContext* presContext = firstFrame->PresContext();
   return gfx::Size(presContext->AppUnitsToFloatCSSPixels(r.width),
                    presContext->AppUnitsToFloatCSSPixels(r.height));
 }
 
 gfxRect
 nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
 {
-  NS_ASSERTION(!aNonSVGFrame->IsFrameOfType(nsIFrame::eSVG),
-               "SVG frames should not get here");
+  NS_ASSERTION(!(aNonSVGFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
+               "Frames with SVG layout should not get here");
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
   // 'r' is in "user space":
   nsRect r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
                                               GetOffsetToBoundingBox(firstFrame));
   return nsLayoutUtils::RectToGfxRect(r,
            aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
 }
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1092,17 +1092,20 @@ nsSVGUtils::SetClipRect(gfxContext *aCon
 gfxRect
 nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
 {
   if (aFrame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
     aFrame = aFrame->GetParent();
   }
   gfxRect bbox;
   nsISVGChildFrame *svg = do_QueryFrame(aFrame);
-  if (svg || aFrame->IsSVGText()) {
+  const bool hasSVGLayout = aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT;
+  if (hasSVGLayout || aFrame->IsSVGText() ||
+      // if we evaluate the following, |svg| can only be an outer-<svg> or null
+      (svg && !(aFlags & eUseFrameBoundsForOuterSVG))) {
     // It is possible to apply a gradient, pattern, clipping path, mask or
     // filter to text. When one of these facilities is applied to text
     // the bounding box is the entire text element in all
     // cases.
     if (aFrame->IsSVGText()) {
       nsIFrame* ancestor = GetFirstNonAAncestorFrame(aFrame);
       if (ancestor && ancestor->IsSVGText()) {
         while (ancestor->GetType() != nsGkAtoms::svgTextFrame) {
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -398,17 +398,21 @@ public:
                        nsIFrame *aFrame);
 
   enum BBoxFlags {
     eBBoxIncludeFill           = 1 << 0,
     eBBoxIncludeFillGeometry   = 1 << 1,
     eBBoxIncludeStroke         = 1 << 2,
     eBBoxIncludeStrokeGeometry = 1 << 3,
     eBBoxIncludeMarkers        = 1 << 4,
-    eBBoxIncludeClipped        = 1 << 5
+    eBBoxIncludeClipped        = 1 << 5,
+    // Normally a getBBox call on outer-<svg> should only return the
+    // bounds of the elements children.  This flag will cause the
+    // element's bounds to be returned instead.
+    eUseFrameBoundsForOuterSVG = 1 << 6
   };
   /**
    * Get the SVG bbox (the SVG spec's simplified idea of bounds) of aFrame in
    * aFrame's userspace.
    */
   static gfxRect GetBBox(nsIFrame *aFrame,
                          // If the default arg changes, update the handling for
                          // ObjectBoundingBoxProperty() in the implementation.