Bug 1265342 Part 3: Stub in shape-margin for shape-outside: image, by implementing only for shape-margin: 0. r=dholbert
authorBrad Werth <bwerth@mozilla.com>
Mon, 12 Mar 2018 17:04:34 -0700
changeset 469089 3b2ffd07d8e669327b56864f71e77d7b1eaa4be9
parent 469088 ab95312a3db6120612753eb41dc2fe1783a5f8ea
child 469090 e5c0631408b2159c4e7ccba4998b2dc35e00eacf
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1265342
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1265342 Part 3: Stub in shape-margin for shape-outside: image, by implementing only for shape-margin: 0. r=dholbert MozReview-Commit-ID: 2gVRyQtd7Io
layout/generic/nsFloatManager.cpp
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -579,17 +579,19 @@ public:
     const UniquePtr<StyleBasicShape>& aBasicShape,
     const LogicalRect& aShapeBoxRect,
     WritingMode aWM,
     const nsSize& aContainerSize);
 
   static UniquePtr<ShapeInfo> CreateImageShape(
     const UniquePtr<nsStyleImage>& aShapeImage,
     float aShapeImageThreshold,
+    nscoord aShapeMargin,
     nsIFrame* const aFrame,
+    const LogicalRect& aMarginRect,
     WritingMode aWM,
     const nsSize& aContainerSize);
 
 protected:
   // Compute the minimum line-axis difference between the bounding shape
   // box and its rounded corner within the given band (block-axis region).
   // This is used as a helper function to compute the LineRight() and
   // LineLeft(). See the picture in the implementation for an example.
@@ -979,17 +981,19 @@ nsFloatManager::PolygonShapeInfo::XInter
 class nsFloatManager::ImageShapeInfo final : public nsFloatManager::ShapeInfo
 {
 public:
   ImageShapeInfo(uint8_t* aAlphaPixels,
                  int32_t aStride,
                  const LayoutDeviceIntSize& aImageSize,
                  int32_t aAppUnitsPerDevPixel,
                  float aShapeImageThreshold,
+                 nscoord aShapeMargin,
                  const nsRect& aContentRect,
+                 const nsRect& aMarginRect,
                  WritingMode aWM,
                  const nsSize& aContainerSize);
 
   nscoord LineLeft(const nscoord aBStart,
                    const nscoord aBEnd) const override;
   nscoord LineRight(const nscoord aBStart,
                     const nscoord aBEnd) const override;
   nscoord BStart() const override { return mBStart; }
@@ -1029,75 +1033,83 @@ private:
 };
 
 nsFloatManager::ImageShapeInfo::ImageShapeInfo(
   uint8_t* aAlphaPixels,
   int32_t aStride,
   const LayoutDeviceIntSize& aImageSize,
   int32_t aAppUnitsPerDevPixel,
   float aShapeImageThreshold,
+  nscoord aShapeMargin,
   const nsRect& aContentRect,
+  const nsRect& aMarginRect,
   WritingMode aWM,
   const nsSize& aContainerSize)
 {
   MOZ_ASSERT(aShapeImageThreshold >=0.0 && aShapeImageThreshold <=1.0,
              "The computed value of shape-image-threshold is wrong!");
 
   const uint8_t threshold = NSToIntFloor(aShapeImageThreshold * 255);
   const int32_t w = aImageSize.width;
   const int32_t h = aImageSize.height;
 
-  // Scan the pixels in a double loop. For horizontal writing modes, we do
-  // this row by row, from top to bottom. For vertical writing modes, we do
-  // column by column, from left to right. We define the two loops
-  // generically, then figure out the rows and cols within the i loop.
-  const int32_t bSize = aWM.IsVertical() ? w : h;
-  const int32_t iSize = aWM.IsVertical() ? h : w;
-  for (int32_t b = 0; b < bSize; ++b) {
-    // iMin and iMax store the start and end of the float area for the row
-    // or column represented by this iteration of the b loop.
-    int32_t iMin = -1;
-    int32_t iMax = -1;
+  if (aShapeMargin <= 0) {
+    // Without a positive aShapeMargin, all we have to do is a
+    // direct threshold comparison of the alpha pixels.
+    // https://drafts.csswg.org/css-shapes-1/#valdef-shape-image-threshold-number
+
+    // Scan the pixels in a double loop. For horizontal writing modes, we do
+    // this row by row, from top to bottom. For vertical writing modes, we do
+    // column by column, from left to right. We define the two loops
+    // generically, then figure out the rows and cols within the inner loop.
+    const int32_t bSize = aWM.IsVertical() ? w : h;
+    const int32_t iSize = aWM.IsVertical() ? h : w;
+    for (int32_t b = 0; b < bSize; ++b) {
+      // iMin and max store the start and end of the float area for the row
+      // or column represented by this iteration of the outer loop.
+      int32_t iMin = -1;
+      int32_t iMax = -1;
+
+      for (int32_t i = 0; i < iSize; ++i) {
+        const int32_t col = aWM.IsVertical() ? b : i;
+        const int32_t row = aWM.IsVertical() ? i : b;
 
-    for (int32_t i = 0; i < iSize; ++i) {
-      const int32_t col = aWM.IsVertical() ? b : i;
-      const int32_t row = aWM.IsVertical() ? i : b;
+        // Determine if the alpha pixel at this row and column has a value
+        // greater than the threshold. If it does, update our iMin and iMax values
+        // to track the edges of the float area for this row or column.
+        // https://drafts.csswg.org/css-shapes-1/#valdef-shape-image-threshold-number
+        const uint8_t alpha = aAlphaPixels[col + row * aStride];
+        if (alpha > threshold) {
+          if (iMin == -1) {
+            iMin = i;
+          }
+          MOZ_ASSERT(iMax < i);
+          iMax = i;
+        }
+      }
 
-      // Determine if the alpha pixel at this row and column has a value
-      // greater than the threshold. If it does, update our iMin and iMax values
-      // to track the edges of the float area for this row or column.
-      // https://drafts.csswg.org/css-shapes-1/#valdef-shape-image-threshold-number
-      const uint8_t alpha = aAlphaPixels[col + row * aStride];
-      if (alpha > threshold) {
-        if (iMin == -1) {
-          iMin = i;
-        }
-        MOZ_ASSERT(iMax < i);
-        iMax = i;
+      // At the end of a row or column; did we find something?
+      if (iMin != -1) {
+        // We need to supply an offset of the content rect top left, since
+        // our col and row have been calculated from the content rect,
+        // instead of the margin rect (against which floats are applied).
+        CreateInterval(iMin, iMax, b, aAppUnitsPerDevPixel,
+                       aContentRect.TopLeft(), aWM, aContainerSize);
       }
     }
 
-    // At the end of a row or column; did we find something?
-    if (iMin != -1) {
-      // We need to supply an offset of the content rect top left, since
-      // our col and row have been calculated from the content rect,
-      // instead of the margin rect (against which floats are applied).
-      CreateInterval(iMin, iMax, b, aAppUnitsPerDevPixel,
-                     aContentRect.TopLeft(), aWM, aContainerSize);
+    if (aWM.IsVerticalRL()) {
+      // vertical-rl or sideways-rl.
+      // Because we scan the columns from left to right, we need to reverse
+      // the array so that it's sorted (in ascending order) on the block
+      // direction.
+      mIntervals.Reverse();
     }
   }
 
-  if (aWM.IsVerticalRL()) {
-    // vertical-rl or sideways-rl.
-    // Because we scan the columns from left to right, we need to reverse
-    // the array so that it's sorted (in ascending order) on the block
-    // direction.
-    mIntervals.Reverse();
-  }
-
   if (!mIntervals.IsEmpty()) {
     mBStart = mIntervals[0].Y();
     mBEnd = mIntervals.LastElement().YMost();
   }
 }
 
 void
 nsFloatManager::ImageShapeInfo::CreateInterval(
@@ -1247,19 +1259,24 @@ nsFloatManager::FloatInfo::FloatInfo(nsI
       return;
 
     case StyleShapeSourceType::URL:
       MOZ_ASSERT_UNREACHABLE("shape-outside doesn't have URL source type!");
       return;
 
     case StyleShapeSourceType::Image: {
       float shapeImageThreshold = mFrame->StyleDisplay()->mShapeImageThreshold;
+      nscoord shapeMargin = nsLayoutUtils::ResolveToLength<true>(
+        mFrame->StyleDisplay()->mShapeMargin,
+        LogicalSize(aWM, aContainerSize).ISize(aWM));
       mShapeInfo = ShapeInfo::CreateImageShape(shapeOutside.GetShapeImage(),
                                                shapeImageThreshold,
+                                               shapeMargin,
                                                mFrame,
+                                               aMarginRect,
                                                aWM,
                                                aContainerSize);
       if (!mShapeInfo) {
         // Image is not ready, or fails to load, etc.
         return;
       }
 
       break;
@@ -1559,17 +1576,19 @@ nsFloatManager::ShapeInfo::CreatePolygon
 
   return MakeUnique<PolygonShapeInfo>(Move(vertices));
 }
 
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreateImageShape(
   const UniquePtr<nsStyleImage>& aShapeImage,
   float aShapeImageThreshold,
+  nscoord aShapeMargin,
   nsIFrame* const aFrame,
+  const LogicalRect& aMarginRect,
   WritingMode aWM,
   const nsSize& aContainerSize)
 {
   MOZ_ASSERT(aShapeImage ==
              aFrame->StyleDisplay()->mShapeOutside.GetShapeImage(),
              "aFrame should be the frame that we got aShapeImage from");
 
   nsImageRenderer imageRenderer(aFrame, aShapeImage.get(),
@@ -1618,27 +1637,31 @@ nsFloatManager::ShapeInfo::CreateImageSh
 
   if (!map.IsMapped()) {
     return nullptr;
   }
 
   MOZ_ASSERT(sourceSurface->GetSize() == contentSizeInDevPixels.ToUnknownSize(),
              "Who changes the size?");
 
+  nsRect marginRect = aMarginRect.GetPhysicalRect(aWM, aContainerSize);
+
   uint8_t* alphaPixels = map.GetData();
   int32_t stride = map.GetStride();
 
   // NOTE: ImageShapeInfo constructor does not keep a persistent copy of
   // alphaPixels; it's only used during the constructor to compute pixel ranges.
   return MakeUnique<ImageShapeInfo>(alphaPixels,
                                     stride,
                                     contentSizeInDevPixels,
                                     appUnitsPerDevPixel,
                                     aShapeImageThreshold,
+                                    aShapeMargin,
                                     contentRect,
+                                    marginRect,
                                     aWM,
                                     aContainerSize);
 }
 
 /* static */ nscoord
 nsFloatManager::ShapeInfo::ComputeEllipseLineInterceptDiff(
   const nscoord aShapeBoxBStart, const nscoord aShapeBoxBEnd,
   const nscoord aBStartCornerRadiusL, const nscoord aBStartCornerRadiusB,