Bug 382721 - Part 8: Render too large dotted/dashed corner with solid style. r=jrmuizel
authorTooru Fujisawa <arai_a@mac.com>
Fri, 10 Jun 2016 13:10:03 +0900
changeset 343655 04c0b0cde81d17048bd42c4d618985b1cd826641
parent 343654 8d81a2b35bc0f525319b097a79fa97ff89d4f514
child 343656 0ac2613adaeefd45f9cde2d4d16746484a1be5e5
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
@@ -2300,16 +2300,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;
@@ -2535,16 +2542,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>