Fix rounding for border-image-width after scaling adjustment

The scaling of the various edges/widths would always round down, which
meant that edges that were supposed to be abutting were not.

Round the scaled width instead, but take care to avoid introducing a new
overlap (which we scaled down to avoid). Use LayoutUnits for this since
we probably want to just compute the widths to LayoutUnit directly in
the future for slightly improved fidelity (TODO added).

Also, fix typo in |include_rigt_edge|.

Bug: 918994
Change-Id: I359fd54d30ddcfa235217e14f340cd6139e9d040
Reviewed-on: https://chromium-review.googlesource.com/c/1452183
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Reviewed-by: Stephen Chenney <schenney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629133}
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc b/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
index a16fead..2e44c5f 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
@@ -26,12 +26,31 @@
                        ValueForLength(slice, LayoutUnit(maximum)).Round());
 }
 
+// Scale the width of the |start| and |end| edges using |scale_factor|.
+// Always round the width of |start|. Based on available space (|box_extent|),
+// the width of |end| is either rounded or floored. This should keep abutting
+// edges flush, while not producing potentially "uneven" widths for a
+// non-overlapping case.
+static void ScaleEdgeWidths(NinePieceImageGrid::Edge& start,
+                            NinePieceImageGrid::Edge& end,
+                            int box_extent,
+                            float scale_factor) {
+  LayoutUnit start_width(start.width);
+  start_width *= scale_factor;
+  LayoutUnit end_width(end.width);
+  end_width *= scale_factor;
+  start.width = start_width.Round();
+  int remaining = box_extent - start.width;
+  int rounded_end = end_width.Round();
+  end.width = rounded_end > remaining ? end_width.Floor() : rounded_end;
+}
+
 NinePieceImageGrid::NinePieceImageGrid(const NinePieceImage& nine_piece_image,
                                        IntSize image_size,
                                        IntRect border_image_area,
                                        const IntRectOutsets& border_widths,
                                        bool include_left_edge,
-                                       bool include_rigt_edge)
+                                       bool include_right_edge)
     : border_image_area_(border_image_area),
       image_size_(image_size),
       horizontal_tile_rule_(nine_piece_image.HorizontalRule()),
@@ -46,10 +65,12 @@
   left_.slice = ComputeEdgeSlice(nine_piece_image.ImageSlices().Left(),
                                  image_size.Width());
 
+  // TODO(fs): Compute edge widths to LayoutUnit, and then only round to
+  // integer at the end - after (potential) compensation for overlapping edges.
   top_.width = ComputeEdgeWidth(nine_piece_image.BorderSlices().Top(),
                                 border_widths.Top(), top_.slice,
                                 border_image_area.Height());
-  right_.width = include_rigt_edge
+  right_.width = include_right_edge
                      ? ComputeEdgeWidth(nine_piece_image.BorderSlices().Right(),
                                         border_widths.Right(), right_.slice,
                                         border_image_area.Width())
@@ -73,10 +94,10 @@
       std::min((float)border_image_area.Width() / border_side_width,
                (float)border_image_area.Height() / border_side_height);
   if (border_side_scale_factor < 1) {
-    top_.width *= border_side_scale_factor;
-    right_.width *= border_side_scale_factor;
-    bottom_.width *= border_side_scale_factor;
-    left_.width *= border_side_scale_factor;
+    ScaleEdgeWidths(top_, bottom_, border_image_area.Height(),
+                    border_side_scale_factor);
+    ScaleEdgeWidths(left_, right_, border_image_area.Width(),
+                    border_side_scale_factor);
   }
 }
 
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
index ddee76a..4089594 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
@@ -136,6 +136,45 @@
     else
       EXPECT_TRUE(draw_info.destination.Size().IsEmpty());
   }
+
+  // Like above, but also make sure to get a scale-down factor that requires
+  // rounding to pick the larger value on one of the edges. (A 1:3, 2:3 split.)
+  BorderImageLength top_left(10);
+  BorderImageLength bottom_right(20);
+  nine_piece.SetBorderSlices(
+      BorderImageLengthBox(top_left, bottom_right, bottom_right, top_left));
+  grid = NinePieceImageGrid(nine_piece, image_size, border_image_area,
+                            border_widths);
+  NinePieceImageGrid::NinePieceDrawInfo draw_info =
+      grid.GetNinePieceDrawInfo(kTopLeftPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(33, 33));
+  draw_info = grid.GetNinePieceDrawInfo(kTopRightPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(67, 33));
+  draw_info = grid.GetNinePieceDrawInfo(kBottomLeftPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(33, 67));
+  draw_info = grid.GetNinePieceDrawInfo(kBottomRightPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(67, 67));
+
+  // Set border slices that overlap in one dimension but not in the other, and
+  // where the resulting width in the non-overlapping dimension will round to a
+  // larger width.
+  BorderImageLength top_bottom(10);
+  BorderImageLength left_right(Length(11, kFixed));
+  nine_piece.SetBorderSlices(
+      BorderImageLengthBox(top_bottom, left_right, top_bottom, left_right));
+  grid = NinePieceImageGrid(nine_piece, image_size, border_image_area,
+                            border_widths);
+  NinePieceImageGrid::NinePieceDrawInfo tl_info =
+      grid.GetNinePieceDrawInfo(kTopLeftPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), FloatSize(6, 50));
+  // The top-right, bottom-left and bottom-right pieces are the same size as
+  // the top-left piece.
+  draw_info = grid.GetNinePieceDrawInfo(kTopRightPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
+  draw_info = grid.GetNinePieceDrawInfo(kBottomLeftPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
+  draw_info = grid.GetNinePieceDrawInfo(kBottomRightPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
 }
 
 TEST_F(NinePieceImageGridTest, NinePieceImagePainting) {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 29c9553..df02898 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3111,7 +3111,6 @@
 crbug.com/626703 external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ]
 crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-values/vh-support-atviewport.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-backgrounds/border-image-calc.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/boundary-shaping/boundary-shaping-005.html [ Failure ]
 crbug.com/626703 external/wpt/css/CSS2/text/white-space-nowrap-attribute-001.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/boundary-shaping/boundary-shaping-010.html [ Failure ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
index 450c5e1ce..611bded 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index eda6e52..c8358206 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
index 1600eaf..7eb5023 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
index f99555d..a56535e 100644
--- a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index 711ae3b..d901e3ff 100644
--- a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
index f2fc9d7..1410f56 100644
--- a/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
index 30e1c799..b0b8011 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
index 44adbc1..239e188 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index af5c0d5..70caec5 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ