Bug 1461046 Part 2: Change ShapeUtils::ComputeInsetRect to return the inverse of a rect deflated more than its bounds can tolerate. draft
authorBrad Werth <bwerth@mozilla.com>
Fri, 18 May 2018 17:51:19 -0700
changeset 803570 6d3893660c55b2c93f1f00454a4d49ed69ce4837
parent 803569 b0001b34c9353c5e21e64b7629ba658f0239db08
child 803571 5ceda79450157fe427438336a24c117d56003831
push id112151
push userbwerth@mozilla.com
push dateMon, 04 Jun 2018 15:53:26 +0000
bugs1461046
milestone62.0a1
Bug 1461046 Part 2: Change ShapeUtils::ComputeInsetRect to return the inverse of a rect deflated more than its bounds can tolerate. MozReview-Commit-ID: IScKyqzjMoy
layout/base/ShapeUtils.cpp
layout/base/ShapeUtils.h
--- a/layout/base/ShapeUtils.cpp
+++ b/layout/base/ShapeUtils.cpp
@@ -119,25 +119,39 @@ ShapeUtils::ComputeInsetRect(const Uniqu
                              const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Inset,
              "The basic shape must be inset()!");
 
   const nsTArray<nsStyleCoord>& coords = aBasicShape->Coordinates();
   MOZ_ASSERT(coords.Length() == 4, "wrong number of arguments");
 
-  nsMargin inset(coords[0].ComputeCoordPercentCalc(aRefBox.height),
-                 coords[1].ComputeCoordPercentCalc(aRefBox.width),
-                 coords[2].ComputeCoordPercentCalc(aRefBox.height),
-                 coords[3].ComputeCoordPercentCalc(aRefBox.width));
+  nsMargin inset(coords[0].ComputeCoordPercentCalc(aRefBox.Height()),
+                 coords[1].ComputeCoordPercentCalc(aRefBox.Width()),
+                 coords[2].ComputeCoordPercentCalc(aRefBox.Height()),
+                 coords[3].ComputeCoordPercentCalc(aRefBox.Width()));
+
+  nscoord x = aRefBox.X() + inset.left;
+  nscoord width = aRefBox.Width() - inset.LeftRight();
+  nscoord y = aRefBox.Y() + inset.top;
+  nscoord height = aRefBox.Height() - inset.TopBottom();
 
-  nsRect insetRect(aRefBox);
-  insetRect.Deflate(inset);
+  // Invert left and right, if necessary.
+  if (width < 0) {
+    width *= -1;
+    x -= width;
+  }
 
-  return insetRect;
+  // Invert top and bottom, if necessary.
+  if (height < 0) {
+    height *= -1;
+    y -= height;
+  }
+
+  return nsRect(x, y, width, height);
 }
 
 /* static */ bool
 ShapeUtils::ComputeInsetRadii(const UniquePtr<StyleBasicShape>& aBasicShape,
                               const nsRect& aInsetRect,
                               const nsRect& aRefBox,
                               nscoord aRadii[8])
 {
--- a/layout/base/ShapeUtils.h
+++ b/layout/base/ShapeUtils.h
@@ -52,17 +52,26 @@ struct ShapeUtils final
   // @param aCenter the center of the ellipse.
   // @param aRefBox the reference box of the ellipse.
   // @return The radii of the ellipse in app units. The width and height
   // represent the x-axis and y-axis radii of the ellipse.
   static nsSize ComputeEllipseRadii(
     const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsPoint& aCenter, const nsRect& aRefBox);
 
-  // Compute the rect for an inset.
+  // Compute the rect for an inset. If the inset amount is larger than
+  // aRefBox itself, this will return a rect the same shape as the inverse
+  // rect that would be created by insetting aRefBox by the inset amount.
+  // This process is *not* what is called for by the current spec at
+  // https://drafts.csswg.org/css-shapes-1/#supported-basic-shapes.
+  // The spec currently treats empty shapes, including overly-inset rects, as
+  // defining 'empty float areas' that don't affect layout. However, it is
+  // practically useful to treat empty shapes as having edges for purposes of
+  // affecting layout, and there is growing momentum for the approach we
+  // are taking here.
   // @param aRefBox the reference box of the inset.
   // @return The inset rect in app units.
   static nsRect ComputeInsetRect(
     const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsRect& aRefBox);
 
   // Compute the radii for an inset.
   // @param aRefBox the reference box of the inset.