Bug 1461046 Part 1: Change EllipseShapeInfo to tolerate empty circles/ellipses and treat them as singular points/lines (possibly expanded by shape-margin). draft
authorBrad Werth <bwerth@mozilla.com>
Fri, 18 May 2018 17:13:22 -0700
changeset 801223 bb29ceb94494eb9b10785244bfdaa1be2463df76
parent 800874 f01bb6245db1ea2a87e5360104a4110571265137
child 801224 3dab62f84c97bb5d735eb5b51c8c8e3c3fa1a037
push id111608
push userbwerth@mozilla.com
push dateTue, 29 May 2018 22:29:47 +0000
bugs1461046
milestone62.0a1
Bug 1461046 Part 1: Change EllipseShapeInfo to tolerate empty circles/ellipses and treat them as singular points/lines (possibly expanded by shape-margin). MozReview-Commit-ID: 69VQiRjhtqA
layout/generic/nsFloatManager.cpp
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -725,17 +725,20 @@ public:
                     const nscoord aBEnd) const override;
   nscoord BStart() const override {
     return mCenter.y - mRadii.height - mShapeMargin;
   }
   nscoord BEnd() const override {
     return mCenter.y + mRadii.height + mShapeMargin;
   }
   bool IsEmpty() const override {
-    return mRadii.IsEmpty();
+    // An EllipseShapeInfo is never empty, because an ellipse or circle with
+    // a zero radius acts like a point, and an ellipse with one zero radius
+    // acts like a line.
+    return false;
   }
 
   void Translate(nscoord aLineLeft, nscoord aBlockStart) override
   {
     mCenter.MoveBy(aLineLeft, aBlockStart);
 
     for (nsRect& interval : mIntervals) {
       interval.MoveBy(aLineLeft, aBlockStart);
@@ -861,38 +864,46 @@ nsFloatManager::EllipseShapeInfo::Ellips
     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 bEnd of the ellipse, the intercept is nscoord_MIN.
-    const int32_t iIntercept = (bIsInExpandedRegion ||
-                                bIsMoreThanEllipseBEnd) ? nscoord_MIN :
+    // We have one other special case to consider: when the ellipse has no
+    // height. In that case we treat the bInAppUnits == 0 case as
+    // intercepting at the width of the ellipse. All other cases solve
+    // the intersection mathematically.
+    const int32_t iIntercept =
+      (bIsInExpandedRegion || bIsMoreThanEllipseBEnd) ? nscoord_MIN :
       iExpand + NSAppUnitsToIntPixels(
-        XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height),
+        (!!mRadii.height || bInAppUnits) ?
+        XInterceptAtY(bInAppUnits, mRadii.width, mRadii.height) :
+        mRadii.width,
         aAppUnitsPerDevPixel);
 
     // Set iMax in preparation for this block row.
     int32_t iMax = iIntercept;
 
     for (uint32_t i = 0; i < iSize; ++i) {
       const uint32_t index = i + b * iSize;
       MOZ_ASSERT(index < (iSize * bSize),
                  "Our distance field index should be in-bounds.");
 
       // Handle our three cases, in order.
       if (i < iExpand ||
           bIsInExpandedRegion) {
         // Case 1: Expanded reqion pixel.
         df[index] = MAX_MARGIN_5X;
       } else if ((int32_t)i <= iIntercept) {
-        // Case 2: Pixel within the ellipse.
-        df[index] = 0;
+        // Case 2: Pixel within the ellipse, or just outside the edge of it.
+        // Having a positive height indicates that there's an area we can
+        // be inside of.
+        df[index] = (!!mRadii.height) ? 0 : 5;
       } else {
         // Case 3: Other pixel.
 
         // Backward-looking neighborhood distance from target pixel X
         // with chamfer 5-7-11 looks like:
         //
         // +--+--+--+
         // |  |11|  |