Bug Part 1 - Add BBoxFlags::eIncludeOnlyCurrentFrameForNonSVGElement to determine whether include all continuations while computing bbox of a html frame. draft
authorLouis Chang <lochang@mozilla.com>
Fri, 11 Aug 2017 18:19:47 +0800
changeset 644774 cb9e7abeaee84aaafa64f4da6169befa5ab93d49
parent 643939 165a764bb2ed32ff8ee2f663141e28da775e8fdc
child 644775 2d909ec24205e52e97a1d93829cbb89fea8a1a53
child 644782 0d1dc4530d3c4213d3e070fcb26460617d8878bd
push id73549
push userlochang@mozilla.com
push dateFri, 11 Aug 2017 10:34:27 +0000
milestone57.0a1
Bug Part 1 - Add BBoxFlags::eIncludeOnlyCurrentFrameForNonSVGElement to determine whether include all continuations while computing bbox of a html frame. MozReview-Commit-ID: Fx11LjhBcrM
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGIntegrationUtils.h
layout/svg/nsSVGUtils.cpp
layout/svg/nsSVGUtils.h
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -208,38 +208,36 @@ nsSVGIntegrationUtils::GetSVGCoordContex
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
   nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(firstFrame, firstFrame);
   nsPresContext* presContext = firstFrame->PresContext();
   return gfx::Size(presContext->AppUnitsToFloatCSSPixels(r.width),
                    presContext->AppUnitsToFloatCSSPixels(r.height));
 }
 
 gfxRect
-nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
+nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame,
+                                                bool aUnionContinuations)
 {
   // Except for nsSVGOuterSVGFrame, we shouldn't be getting here with SVG
   // frames at all. This function is for elements that are laid out using the
   // CSS box model rules.
   NS_ASSERTION(!(aNonSVGFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
                "Frames with SVG layout should not get here");
   MOZ_ASSERT(!aNonSVGFrame->IsFrameOfType(nsIFrame::eSVG) ||
              aNonSVGFrame->IsSVGOuterSVGFrame());
 
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
   // 'r' is in "user space":
-  nsRect r;
-  if (aNonSVGFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone) {
-    r = GetPreEffectsVisualOverflow(firstFrame, aNonSVGFrame,
-                                    GetOffsetToBoundingBox(firstFrame));
-  } else {
-    r = GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
-                                         GetOffsetToBoundingBox(firstFrame),
-                                         false);
-  }
+  nsRect r = (aUnionContinuations)
+    ? GetPreEffectsVisualOverflowUnion(firstFrame, nullptr, nsRect(),
+                                       GetOffsetToBoundingBox(firstFrame),
+                                       false)
+    : GetPreEffectsVisualOverflow(firstFrame, aNonSVGFrame,
+                                  GetOffsetToBoundingBox(firstFrame));
 
   return nsLayoutUtils::RectToGfxRect(r,
            aNonSVGFrame->PresContext()->AppUnitsPerCSSPixel());
 }
 
 // XXX Since we're called during reflow, this method is broken for frames with
 // continuations. When we're called for a frame with continuations, we're
 // called for each continuation in turn as it's reflowed. However, it isn't
--- a/layout/svg/nsSVGIntegrationUtils.h
+++ b/layout/svg/nsSVGIntegrationUtils.h
@@ -73,22 +73,23 @@ public:
   static mozilla::gfx::Size
   GetSVGCoordContextForNonSVGFrame(nsIFrame* aNonSVGFrame);
 
   /**
    * SVG effects such as SVG filters, masking and clipPath may require an SVG
    * "bbox" for the element they're being applied to in order to make decisions
    * about positioning, and to resolve various lengths against. This method
    * provides the "bbox" for non-SVG frames. The bbox returned is in CSS px
-   * units, and is the union of all aNonSVGFrame's continuations' overflow
-   * areas, relative to the top-left of the union of all aNonSVGFrame's
+   * units, and aUnionContinuations decide whether bbox contains the area of
+   * current frame only or the union of all aNonSVGFrame's continuations'
+   * overflow areas, relative to the top-left of the union of all aNonSVGFrame's
    * continuations' border box rects.
    */
   static gfxRect
-  GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame);
+  GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame, bool aUnionContinuations);
 
   /**
    * Used to adjust a frame's pre-effects visual overflow rect to take account
    * of SVG effects.
    *
    * XXX This method will not do the right thing for frames with continuations.
    * It really needs all the continuations to have been reflowed before being
    * called, but we currently call it on each continuation as its overflow
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -1094,17 +1094,19 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
   }
 
   const bool isOuterSVG = svg && !hasSVGLayout;
   MOZ_ASSERT(!isOuterSVG || aFrame->IsSVGOuterSVGFrame());
   if (!svg ||
       (isOuterSVG && (aFlags & eUseFrameBoundsForOuterSVG))) {
     // An HTML element or an SVG outer frame.
     MOZ_ASSERT(!hasSVGLayout);
-    return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(aFrame);
+    bool onlyCurrentFrame = aFlags & eIncludeOnlyCurrentFrameForNonSVGElement;
+    return nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(
+      aFrame, !onlyCurrentFrame);
   }
 
   MOZ_ASSERT(svg);
 
   nsIContent* content = aFrame->GetContent();
   if (content->IsSVGElement() &&
       !static_cast<const nsSVGElement*>(content)->HasValidDimensions()) {
     return gfxRect();
@@ -1295,17 +1297,21 @@ nsSVGUtils::CanOptimizeOpacity(nsIFrame 
 
 gfxMatrix
 nsSVGUtils::AdjustMatrixForUnits(const gfxMatrix &aMatrix,
                                  nsSVGEnum *aUnits,
                                  nsIFrame *aFrame)
 {
   if (aFrame &&
       aUnits->GetAnimValue() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
-    gfxRect bbox = GetBBox(aFrame);
+    uint32_t flags =
+      (aFrame->StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone)
+        ? eBBoxIncludeFillGeometry | eIncludeOnlyCurrentFrameForNonSVGElement
+        : eBBoxIncludeFillGeometry;
+    gfxRect bbox = GetBBox(aFrame, flags);
     gfxMatrix tm = aMatrix;
     tm.PreTranslate(gfxPoint(bbox.X(), bbox.Y()));
     tm.PreScale(bbox.Width(), bbox.Height());
     return tm;
   }
   return aMatrix;
 }
 
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -387,21 +387,25 @@ public:
   enum BBoxFlags {
     eBBoxIncludeFill           = 1 << 0,
     eBBoxIncludeFillGeometry   = 1 << 1,
     eBBoxIncludeStroke         = 1 << 2,
     eBBoxIncludeStrokeGeometry = 1 << 3,
     eBBoxIncludeMarkers        = 1 << 4,
     eBBoxIncludeClipped        = 1 << 5,
     // Normally a getBBox call on outer-<svg> should only return the
-    // bounds of the elements children.  This flag will cause the
+    // bounds of the elements children. This flag will cause the
     // 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 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.