Bug 382721 - Part 8: Render too large dotted/dashed corner with solid style. r=jrmuizel
☠☠ backed out by fa5f93123f1b ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Fri, 10 Jun 2016 13:10:03 +0900
changeset 343582 ba37839e4fdebd7575845f4ed0b06a9c191c30b2
parent 343581 ddf602c6e885b6a14b4946eeee44a7f77c5db913
child 343583 c3f66208fe851ffd0b03dbc1b2cbe6883d2e6d21
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs382721
milestone50.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 382721 - Part 8: Render too large dotted/dashed corner with solid style. r=jrmuizel
layout/base/BorderConsts.h
layout/base/nsCSSRenderingBorders.cpp
layout/base/nsCSSRenderingBorders.h
layout/generic/crashtests/crashtests.list
layout/generic/crashtests/large-border-radius-dashed.html
layout/generic/crashtests/large-border-radius-dashed2.html
layout/generic/crashtests/large-border-radius-dotted.html
layout/generic/crashtests/large-border-radius-dotted2.html
--- a/layout/base/BorderConsts.h
+++ b/layout/base/BorderConsts.h
@@ -18,10 +18,11 @@
 #define SIDE_BITS_ALL (SIDE_BIT_TOP|SIDE_BIT_RIGHT|SIDE_BIT_BOTTOM|SIDE_BIT_LEFT)
 
 #define C_TL NS_CORNER_TOP_LEFT
 #define C_TR NS_CORNER_TOP_RIGHT
 #define C_BR NS_CORNER_BOTTOM_RIGHT
 #define C_BL NS_CORNER_BOTTOM_LEFT
 
 #define BORDER_SEGMENT_COUNT_MAX 100
+#define BORDER_DOTTED_CORNER_MAX_RADIUS 100000
 
 #endif /* mozilla_BorderConsts_h_ */
--- a/layout/base/nsCSSRenderingBorders.cpp
+++ b/layout/base/nsCSSRenderingBorders.cpp
@@ -2188,16 +2188,23 @@ nsCSSBorderRenderer::DrawDashedOrDottedC
 
   // Corner between dotted and others with radius=0 is drawn by side.
   if (IsZeroSize(mBorderRadii[aCorner]) &&
       (styleV == NS_STYLE_BORDER_STYLE_DOTTED ||
        styleH == NS_STYLE_BORDER_STYLE_DOTTED)) {
     return;
   }
 
+  Float maxRadius = std::max(mBorderRadii[aCorner].width,
+                             mBorderRadii[aCorner].height);
+  if (maxRadius > BORDER_DOTTED_CORNER_MAX_RADIUS) {
+    DrawFallbackSolidCorner(aSide, aCorner);
+    return;
+  }
+
   if (borderWidthH != borderWidthV || borderWidthH > 2.0f) {
     uint8_t style = mBorderStyles[aSide];
     if (style == NS_STYLE_BORDER_STYLE_DOTTED) {
       DrawDottedCornerSlow(aSide, aCorner);
     } else {
       DrawDashedCornerSlow(aSide, aCorner);
     }
     return;
@@ -2423,16 +2430,48 @@ nsCSSBorderRenderer::DrawDashedCornerSlo
     builder->LineTo(Point(outerBezier.mPoints[3].x, innerBezier.mPoints[3].y));
     builder->LineTo(outerBezier.mPoints[3]);
   }
 
   RefPtr<Path> path = builder->Finish();
   mDrawTarget->Fill(path, ColorPattern(ToDeviceColor(borderColor)));
 }
 
+void
+nsCSSBorderRenderer::DrawFallbackSolidCorner(mozilla::css::Side aSide,
+                                             mozilla::css::Corner aCorner)
+{
+  // Render too large dashed or dotted corner with solid style, to avoid hangup
+  // inside DashedCornerFinder and DottedCornerFinder.
+
+  NS_ASSERTION(mBorderStyles[aSide] == NS_STYLE_BORDER_STYLE_DASHED ||
+               mBorderStyles[aSide] == NS_STYLE_BORDER_STYLE_DOTTED,
+               "Style should be dashed or dotted.");
+
+  nscolor borderColor = mBorderColors[aSide];
+  Bezier outerBezier;
+  Bezier innerBezier;
+  GetOuterAndInnerBezier(&outerBezier, &innerBezier, aCorner);
+
+  RefPtr<PathBuilder> builder = mDrawTarget->CreatePathBuilder();
+
+  builder->MoveTo(outerBezier.mPoints[0]);
+  builder->BezierTo(outerBezier.mPoints[1],
+                    outerBezier.mPoints[2],
+                    outerBezier.mPoints[3]);
+  builder->LineTo(innerBezier.mPoints[3]);
+  builder->BezierTo(innerBezier.mPoints[2],
+                    innerBezier.mPoints[1],
+                    innerBezier.mPoints[0]);
+  builder->LineTo(outerBezier.mPoints[0]);
+
+  RefPtr<Path> path = builder->Finish();
+  mDrawTarget->Fill(path, ColorPattern(ToDeviceColor(borderColor)));
+}
+
 bool
 nsCSSBorderRenderer::AllBordersSameWidth()
 {
   if (mBorderWidths[0] == mBorderWidths[1] &&
       mBorderWidths[0] == mBorderWidths[2] &&
       mBorderWidths[0] == mBorderWidths[3])
   {
     return true;
--- a/layout/base/nsCSSRenderingBorders.h
+++ b/layout/base/nsCSSRenderingBorders.h
@@ -224,16 +224,20 @@ private:
   // Draw the given dotted corner, each segment separately
   void DrawDottedCornerSlow(mozilla::css::Side aSide,
                             mozilla::css::Corner aCorner);
 
   // Draw the given dashed corner, each dot separately
   void DrawDashedCornerSlow(mozilla::css::Side aSide,
                             mozilla::css::Corner aCorner);
 
+  // Draw the given dashed/dotted corner with solid style
+  void DrawFallbackSolidCorner(mozilla::css::Side aSide,
+                               mozilla::css::Corner aCorner);
+
   // Analyze if all border sides have the same width.
   bool AllBordersSameWidth();
 
   // Analyze if all borders are 'solid' this also considers hidden or 'none'
   // borders because they can be considered 'solid' borders of 0 width and
   // with no color effect.
   bool AllBordersSolid(bool *aHasCompositeColors);
 
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -622,8 +622,12 @@ load text-overflow-bug671796.xhtml
 load text-overflow-bug713610.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 asserts-if(Android,2-4) asserts-if(!Android,4) load 1225005.html # bug 682647 and bug 448083
 load 1233191.html
 asserts(2) load 1272983-1.html # bug 586628
 asserts(2) load 1272983-2.html # bug 586628
 load 1278007.html
+load large-border-radius-dashed.html
+load large-border-radius-dashed2.html
+load large-border-radius-dotted.html
+load large-border-radius-dotted2.html
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/large-border-radius-dashed.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><html style="height: 10000000px; width: 10000000px; box-sizing: border-box; border-radius: 10000000px; border-style: dashed; border-width: 10px 20px;"></html>
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/large-border-radius-dashed2.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><html style="height: 6523790304542em; width: 6207636626031em; box-sizing: border-box; border-radius: 6523790304542em; border-style: dashed; border-width: 10px 20px;"></html>
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/large-border-radius-dotted.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><html style="height: 10000000px; width: 10000000px; box-sizing: border-box; border-radius: 10000000px; border-style: dotted; border-width: 10px 20px;"></html>
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/large-border-radius-dotted2.html
@@ -0,0 +1,1 @@
+<!DOCTYPE html><html style="height: 6523790304542em; width: 6207636626031em; box-sizing: border-box; border-radius: 6523790304542em; border-style: dotted; border-width: 10px 20px;"></html>