Bug 1459697 Part 1: In EllipseShapeInfo distance field calculation, remove a warning that might trigger due to rounding error, and shorten the iteration of each block pixel row, when possible. draft
authorBrad Werth <bwerth@mozilla.com>
Tue, 08 May 2018 11:11:47 -0700
changeset 793682 fa0da0cd245a6df6b5f72e1922a4aec32cf3d923
parent 793594 b52b2eb81d1e52d259d55d948281c7f6ddf1270c
child 793683 f46f4b9eaf2cd395a17a1136561acd9640aad933
push id109467
push userbwerth@mozilla.com
push dateThu, 10 May 2018 16:19:57 +0000
bugs1459697
milestone62.0a1
Bug 1459697 Part 1: In EllipseShapeInfo distance field calculation, remove a warning that might trigger due to rounding error, and shorten the iteration of each block pixel row, when possible. MozReview-Commit-ID: 6itpj3HBSRy
layout/generic/nsFloatManager.cpp
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -817,19 +817,21 @@ nsFloatManager::EllipseShapeInfo::Ellips
   // use a chamfer 5-7-11 5x5 matrix to compute minimum distance to an edge
   // pixel. This integer math computation is reasonably close to the true
   // Euclidean distance. The distances will be approximately 5x the true
   // distance, quantized in integer units. The 5x is factored away in the
   // comparison which builds the intervals.
   dfType usedMargin5X = CalcUsedShapeMargin5X(aShapeMargin,
                                               aAppUnitsPerDevPixel);
 
+  // Calculate the bounds of one quadrant of the ellipse, in integer device
+  // pixels. These bounds are equal to the rectangle defined by the radii,
+  // plus the shape-margin value in both dimensions.
   const LayoutDeviceIntSize bounds =
-    LayoutDevicePixel::FromAppUnitsRounded(mRadii,
-                                           aAppUnitsPerDevPixel) +
+    LayoutDevicePixel::FromAppUnitsRounded(mRadii, aAppUnitsPerDevPixel) +
     LayoutDeviceIntSize(usedMargin5X / 5, usedMargin5X / 5);
 
   // Since our distance field is computed with a 5x5 neighborhood, but only
   // looks in the negative block and negative inline directions, it is
   // effectively a 3x3 neighborhood. We need to expand our distance field
   // outwards by a further 2 pixels in both axes (on the minimum block edge
   // and the minimum inline edge). We call this edge area the expanded region.
 
@@ -858,17 +860,17 @@ nsFloatManager::EllipseShapeInfo::Ellips
   for (uint32_t b = 0; b < bSize; ++b) {
     bool bIsInExpandedRegion(b < bExpand);
     nscoord bInAppUnits = (b - bExpand) * aAppUnitsPerDevPixel;
     bool bIsMoreThanEllipseBEnd(bInAppUnits > mRadii.height);
 
     // Find the i intercept of the ellipse edge for this block row, and
     // adjust it to compensate for the expansion of the inline dimension.
     // If we're in the expanded region, or if we're using a b that's more
-    // than the bStart of the ellipse, the intercept is nscoord_MIN.
+    // than the bEnd of the ellipse, the intercept is nscoord_MIN.
     const int32_t iIntercept = (bIsInExpandedRegion ||
                                 bIsMoreThanEllipseBEnd) ? nscoord_MIN :
       iExpand + NSAppUnitsToIntPixels(
         XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height),
         aAppUnitsPerDevPixel);
 
     // Set iMax in preparation for this block row.
     int32_t iMax = iIntercept;
@@ -913,25 +915,33 @@ nsFloatManager::EllipseShapeInfo::Ellips
                     std::min<dfType>(df[index - iSize - 2] + 11,
                                      df[index - (iSize * 2) - 1] + 11))));
 
         // Check the df value and see if it's less than or equal to the
         // usedMargin5X value.
         if (df[index] <= usedMargin5X) {
           MOZ_ASSERT(iMax < (int32_t)i);
           iMax = i;
+        } else {
+          // Since we're computing the bottom-right quadrant, there's no way
+          // for a later i value in this row to be within the usedMargin5X
+          // value. Likewise, every row beyond us will encounter this
+          // condition with an i value less than or equal to our i value now.
+          // Since our chamfer only looks upward and leftward, we can stop
+          // calculating for the rest of the row, because the distance field
+          // values there will never be looked at in a later row's chamfer
+          // calculation.
+          break;
         }
       }
     }
 
-    NS_WARNING_ASSERTION(bIsInExpandedRegion || iMax > nscoord_MIN,
-                         "Once past the expanded region, we should always "
-                         "find a pixel within the shape-margin distance for "
-                         "each block row.");
-
+    // It's very likely, though not guaranteed that we will find an pixel
+    // within the shape-margin distance for each block row. This may not
+    // always be true due to rounding errors.
     if (iMax > nscoord_MIN) {
       // Origin for this interval is at the center of the ellipse, adjusted
       // in the positive block direction by bInAppUnits.
       nsPoint origin(aCenter.x, aCenter.y + bInAppUnits);
       // Size is an inline iMax plus 1 (to account for the whole pixel) dev
       // pixels, by 1 block dev pixel. We convert this to app units.
       nsSize size((iMax - iExpand + 1) * aAppUnitsPerDevPixel,
                   aAppUnitsPerDevPixel);