Bug 1457602 Part 1: Correct shape-outside: image shape-margin calculation for vertical writing modes. draft
authorBrad Werth <bwerth@mozilla.com>
Mon, 30 Apr 2018 17:01:24 -0700
changeset 793380 a2619c20432c57a515a9e1080e424684b572d498
parent 793056 9294f67b3f3bd4a3dd898961148cecd8bfc1ce9c
child 793381 1d411ba50a2f59948f6ab1c84402a07b533c1610
push id109362
push userbwerth@mozilla.com
push dateWed, 09 May 2018 22:24:06 +0000
bugs1457602
milestone62.0a1
Bug 1457602 Part 1: Correct shape-outside: image shape-margin calculation for vertical writing modes. MozReview-Commit-ID: ChUL66vUkHu
layout/generic/nsFloatManager.cpp
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -2000,45 +2000,83 @@ nsFloatManager::ImageShapeInfo::ImageSha
           DebugOnly<uint32_t> alphaIndex = col - dfOffset.x +
                                            (row - dfOffset.y) * aStride;
           MOZ_ASSERT(alphaIndex < (aStride * h),
             "Our aAlphaPixels index should be in-bounds.");
 
           df[index] = 0;
         } else {
           // Case 3: Other pixel.
-
-          // Backward-looking neighborhood distance from target pixel X
-          // with chamfer 5-7-11 looks like:
-          //
-          // +--+--+--+--+--+
-          // |  |11|  |11|  |
-          // +--+--+--+--+--+
-          // |11| 7| 5| 7|11|
-          // +--+--+--+--+--+
-          // |  | 5| X|  |  |
-          // +--+--+--+--+--+
-          //
-          // X should be set to the minimum of MAX_MARGIN_5X and the
-          // values of all of the numbered neighbors summed with the
-          // value in that chamfer cell.
-          MOZ_ASSERT(index - (wEx * 2) - 1 < (iSize * bSize) &&
-                     index - wEx - 2 < (iSize * bSize),
-                     "Our distance field most extreme indices should be "
-                     "in-bounds.");
-
-          df[index] = std::min<dfType>(MAX_MARGIN_5X,
-                      std::min<dfType>(df[index - (wEx * 2) - 1] + 11,
-                      std::min<dfType>(df[index - (wEx * 2) + 1] + 11,
-                      std::min<dfType>(df[index - wEx - 2] + 11,
-                      std::min<dfType>(df[index - wEx - 1] + 7,
-                      std::min<dfType>(df[index - wEx] + 5,
-                      std::min<dfType>(df[index - wEx + 1] + 7,
-                      std::min<dfType>(df[index - wEx + 2] + 11,
-                                       df[index - 1] + 5))))))));
+          if (aWM.IsVertical()) {
+            // Column-by-column, starting at the left, each column
+            // top-to-bottom.
+            // Backward-looking neighborhood distance from target pixel X
+            // with chamfer 5-7-11 looks like:
+            //
+            // +--+--+--+
+            // |  |11|  |   |    +
+            // +--+--+--+   |   /|
+            // |11| 7| 5|   |  / |
+            // +--+--+--+   | /  V
+            // |  | 5| X|   |/
+            // +--+--+--+   +
+            // |11| 7|  |
+            // +--+--+--+
+            // |  |11|  |
+            // +--+--+--+
+            //
+            // X should be set to the minimum of MAX_MARGIN_5X and the
+            // values of all of the numbered neighbors summed with the
+            // value in that chamfer cell.
+            MOZ_ASSERT(index - wEx - 2 < (iSize * bSize) &&
+                       index + wEx - 2 < (iSize * bSize) &&
+                       index - (wEx * 2) - 1 < (iSize * bSize),
+                       "Our distance field most extreme indices should be "
+                       "in-bounds.");
+
+            df[index] = std::min<dfType>(MAX_MARGIN_5X,
+                        std::min<dfType>(df[index - wEx - 2] + 11,
+                        std::min<dfType>(df[index + wEx - 2] + 11,
+                        std::min<dfType>(df[index - (wEx * 2) - 1] + 11,
+                        std::min<dfType>(df[index - wEx - 1] + 7,
+                        std::min<dfType>(df[index - 1] + 5,
+                        std::min<dfType>(df[index + wEx - 1] + 7,
+                        std::min<dfType>(df[index + (wEx * 2) - 1] + 11,
+                                         df[index - wEx] + 5))))))));
+          } else {
+            // Row-by-row, starting at the top, each row left-to-right.
+            // Backward-looking neighborhood distance from target pixel X
+            // with chamfer 5-7-11 looks like:
+            //
+            // +--+--+--+--+--+
+            // |  |11|  |11|  |   ----+
+            // +--+--+--+--+--+      /
+            // |11| 7| 5| 7|11|     /
+            // +--+--+--+--+--+    /
+            // |  | 5| X|  |  |   +-->
+            // +--+--+--+--+--+
+            //
+            // X should be set to the minimum of MAX_MARGIN_5X and the
+            // values of all of the numbered neighbors summed with the
+            // value in that chamfer cell.
+            MOZ_ASSERT(index - (wEx * 2) - 1 < (iSize * bSize) &&
+                       index - wEx - 2 < (iSize * bSize),
+                       "Our distance field most extreme indices should be "
+                       "in-bounds.");
+
+            df[index] = std::min<dfType>(MAX_MARGIN_5X,
+                        std::min<dfType>(df[index - (wEx * 2) - 1] + 11,
+                        std::min<dfType>(df[index - (wEx * 2) + 1] + 11,
+                        std::min<dfType>(df[index - wEx - 2] + 11,
+                        std::min<dfType>(df[index - wEx - 1] + 7,
+                        std::min<dfType>(df[index - wEx] + 5,
+                        std::min<dfType>(df[index - wEx + 1] + 7,
+                        std::min<dfType>(df[index - wEx + 2] + 11,
+                                         df[index - 1] + 5))))))));
+          }
         }
       }
     }
 
     // Okay, time for the second pass. This pass is in reverse order from
     // the first pass. All of our opaque pixels have been set to 0, and all
     // of our expanded region pixels have been set to MAX_MARGIN_5X. Other
     // pixels have been set to some value between those two (inclusive) but
@@ -2073,44 +2111,83 @@ nsFloatManager::ImageShapeInfo::ImageSha
         const uint32_t row = aWM.IsVertical() ? i : b;
         const uint32_t index = col + row * wEx;
         MOZ_ASSERT(index < (wEx * hEx),
                    "Our distance field index should be in-bounds.");
 
         // Only apply the chamfer calculation if the df value is not
         // already 0, since the chamfer can only reduce the value.
         if (df[index]) {
-          // Forward-looking neighborhood distance from target pixel X
-          // with chamfer 5-7-11 looks like:
-          //
-          // +--+--+--+--+--+
-          // |  |  | X| 5|  |
-          // +--+--+--+--+--+
-          // |11| 7| 5| 7|11|
-          // +--+--+--+--+--+
-          // |  |11|  |11|  |
-          // +--+--+--+--+--+
-          //
-          // X should be set to the minimum of its current value and
-          // the values of all of the numbered neighbors summed with
-          // the value in that chamfer cell.
-          MOZ_ASSERT(index + (wEx * 2) + 1 < (wEx * hEx) &&
-                     index + wEx + 2 < (wEx * hEx),
-                     "Our distance field most extreme indices should be "
-                     "in-bounds.");
-
-          df[index] = std::min<dfType>(df[index],
-                      std::min<dfType>(df[index + (wEx * 2) + 1] + 11,
-                      std::min<dfType>(df[index + (wEx * 2) - 1] + 11,
-                      std::min<dfType>(df[index + wEx + 2] + 11,
-                      std::min<dfType>(df[index + wEx + 1] + 7,
-                      std::min<dfType>(df[index + wEx] + 5,
-                      std::min<dfType>(df[index + wEx - 1] + 7,
-                      std::min<dfType>(df[index + wEx - 2] + 11,
-                                       df[index + 1] + 5))))))));
+          if (aWM.IsVertical()) {
+            // Column-by-column, starting at the right, each column
+            // bottom-to-top.
+            // Forward-looking neighborhood distance from target pixel X
+            // with chamfer 5-7-11 looks like:
+            //
+            // +--+--+--+
+            // |  |11|  |        +
+            // +--+--+--+       /|
+            // |  | 7|11|   A  / |
+            // +--+--+--+   | /  |
+            // | X| 5|  |   |/   |
+            // +--+--+--+   +    |
+            // | 5| 7|11|
+            // +--+--+--+
+            // |  |11|  |
+            // +--+--+--+
+            //
+            // X should be set to the minimum of its current value and
+            // the values of all of the numbered neighbors summed with
+            // the value in that chamfer cell.
+            MOZ_ASSERT(index + wEx + 2 < (wEx * hEx) &&
+                       index + (wEx * 2) + 1 < (wEx * hEx) &&
+                       index - (wEx * 2) + 1 < (wEx * hEx),
+                       "Our distance field most extreme indices should be "
+                       "in-bounds.");
+
+            df[index] = std::min<dfType>(df[index],
+                        std::min<dfType>(df[index + wEx + 2] + 11,
+                        std::min<dfType>(df[index - wEx + 2] + 11,
+                        std::min<dfType>(df[index + (wEx * 2) + 1] + 11,
+                        std::min<dfType>(df[index + wEx + 1] + 7,
+                        std::min<dfType>(df[index + 1] + 5,
+                        std::min<dfType>(df[index - wEx + 1] + 7,
+                        std::min<dfType>(df[index - (wEx * 2) + 1] + 11,
+                                         df[index + wEx] + 5))))))));
+          } else {
+            // Row-by-row, starting at the bottom, each row right-to-left.
+            // Forward-looking neighborhood distance from target pixel X
+            // with chamfer 5-7-11 looks like:
+            //
+            // +--+--+--+--+--+
+            // |  |  | X| 5|  |    <--+
+            // +--+--+--+--+--+      /
+            // |11| 7| 5| 7|11|     /
+            // +--+--+--+--+--+    /
+            // |  |11|  |11|  |   +----
+            // +--+--+--+--+--+
+            //
+            // X should be set to the minimum of its current value and
+            // the values of all of the numbered neighbors summed with
+            // the value in that chamfer cell.
+            MOZ_ASSERT(index + (wEx * 2) + 1 < (wEx * hEx) &&
+                       index + wEx + 2 < (wEx * hEx),
+                       "Our distance field most extreme indices should be "
+                       "in-bounds.");
+
+            df[index] = std::min<dfType>(df[index],
+                        std::min<dfType>(df[index + (wEx * 2) + 1] + 11,
+                        std::min<dfType>(df[index + (wEx * 2) - 1] + 11,
+                        std::min<dfType>(df[index + wEx + 2] + 11,
+                        std::min<dfType>(df[index + wEx + 1] + 7,
+                        std::min<dfType>(df[index + wEx] + 5,
+                        std::min<dfType>(df[index + wEx - 1] + 7,
+                        std::min<dfType>(df[index + wEx - 2] + 11,
+                                         df[index + 1] + 5))))))));
+          }
         }
 
         // Finally, we can check the df value and see if it's less than
         // or equal to the usedMargin5X value.
         if (df[index] <= usedMargin5X) {
           if (iMax == -1) {
             iMax = i;
           }