Bug 1191609 - Always stroke CSS border sides separately from corner fills. r=mstange
authorLee Salzman <lsalzman@mozilla.com>
Thu, 06 Aug 2015 00:33:44 -0400
changeset 288421 7ae3e401ce999641792b0f577846c5df2c76550a
parent 288420 106c0863db60127996c8cea813c1ee93026ec27a
child 288422 51ebb22f97a07958624c0ed6c52d9181f08e199f
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange
bugs1191609
milestone42.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 1191609 - Always stroke CSS border sides separately from corner fills. r=mstange
layout/base/nsCSSRenderingBorders.cpp
--- a/layout/base/nsCSSRenderingBorders.cpp
+++ b/layout/base/nsCSSRenderingBorders.cpp
@@ -1171,21 +1171,18 @@ ComputeCornerSkirtSize(Float aAlpha1, Fl
     aSizeResult = slopeScale - sqrtf(discrim);
     aSlopeResult = slope;
   }
 }
 
 // Draws a border radius with possibly different sides.
 // A skirt is drawn underneath the corner intersection to hide possible
 // seams when anti-aliased drawing is used.
-// As an optimization, this tries to combine the drawing of the side itself
-// with the drawing of the border radius where possible.
 static void
 DrawBorderRadius(DrawTarget* aDrawTarget,
-                 const Point& aSideStart, Float aSideWidth,
                  mozilla::css::Corner c,
                  const Point& aOuterCorner, const Point& aInnerCorner,
                  const twoFloats& aCornerMultPrev, const twoFloats& aCornerMultNext,
                  const Size& aCornerDims,
                  const Size& aOuterRadius, const Size& aInnerRadius,
                  const Color& aFirstColor, const Color& aSecondColor,
                  Float aSkirtSize, Float aSkirtSlope)
 {
@@ -1216,24 +1213,17 @@ DrawBorderRadius(DrawTarget* aDrawTarget
   // Inner radius center
   Point innerCenter = aInnerCorner + (aCornerMultPrev + aCornerMultNext) * aInnerRadius;
 
   RefPtr<PathBuilder> builder;
   RefPtr<Path> path;
 
   if (aFirstColor.a > 0) {
     builder = aDrawTarget->CreatePathBuilder();
-    // Combine stroke with corner if color matches.
-    if (aSideWidth > 0) {
-      builder->MoveTo(aSideStart + aCornerMultNext * aSideWidth);
-      builder->LineTo(aSideStart);
-      builder->LineTo(outerCornerStart);
-    } else {
-      builder->MoveTo(outerCornerStart);
-    }
+    builder->MoveTo(outerCornerStart);
   }
 
   if (aFirstColor != aSecondColor) {
     // Start and end angles of corner quadrant
     Float startAngle = (c * M_PI) / 2.0f - M_PI,
           endAngle = startAngle + M_PI / 2.0f,
           outerSplitAngle, innerSplitAngle;
     Point outerSplit, innerSplit;
@@ -1303,21 +1293,18 @@ DrawBorderRadius(DrawTarget* aDrawTarget
     path = builder->Finish();
     aDrawTarget->Fill(path, ColorPattern(aFirstColor));
   }
 }
 
 // Draw a corner with possibly different sides.
 // A skirt is drawn underneath the corner intersection to hide possible
 // seams when anti-aliased drawing is used.
-// As an optimization, this tries to combine the drawing of the side itself
-// with the drawing of the corner where possible.
 static void
 DrawCorner(DrawTarget* aDrawTarget,
-           const Point& aSideStart, Float aSideWidth,
            mozilla::css::Corner c,
            const Point& aOuterCorner, const Point& aInnerCorner,
            const twoFloats& aCornerMultPrev, const twoFloats& aCornerMultNext,
            const Size& aCornerDims,
            const Color& aFirstColor, const Color& aSecondColor,
            Float aSkirtSize, Float aSkirtSlope)
 {
   // Corner box start point
@@ -1325,23 +1312,17 @@ DrawCorner(DrawTarget* aDrawTarget,
   // Corner box end point
   Point cornerEnd = aOuterCorner + aCornerMultNext * aCornerDims;
 
   RefPtr<PathBuilder> builder;
   RefPtr<Path> path;
 
   if (aFirstColor.a > 0) {
     builder = aDrawTarget->CreatePathBuilder();
-    // Combine stroke with corner if color matches.
-    if (aSideWidth > 0) {
-      builder->MoveTo(aSideStart + aCornerMultNext * aSideWidth);
-      builder->LineTo(aSideStart);
-    } else {
-      builder->MoveTo(cornerStart);
-    }
+    builder->MoveTo(cornerStart);
   }
 
   if (aFirstColor != aSecondColor) {
     // Draw first half with first color
     if (aFirstColor.a > 0) {
       builder->LineTo(aOuterCorner);
       // Draw skirt as part of first half
       if (aSkirtSize > 0) {
@@ -1393,18 +1374,18 @@ nsCSSBorderRenderer::DrawNoCompositeColo
 
   Rect strokeRect = mOuterRect;
   strokeRect.Deflate(Margin(mBorderWidths[0] / 2.0, mBorderWidths[1] / 2.0,
                             mBorderWidths[2] / 2.0, mBorderWidths[3] / 2.0));
 
   NS_FOR_CSS_SIDES(i) {
     // We now draw the current side and the CW corner following it.
     // The CCW corner of this side was already drawn in the previous iteration.
-    // The side will either be drawn as an explicit stroke or combined
-    // with the drawing of the CW corner.
+    // The side will be drawn as an explicit stroke, and the CW corner will be
+    // filled separately.
     // If the next side does not have a matching color, then we split the
     // corner into two halves, one of each side's color and draw both.
     // Thus, the CCW corner of the next side will end up drawn here.
 
     // the corner index -- either 1 2 3 0 (cw) or 0 3 2 1 (ccw)
     mozilla::css::Corner c = mozilla::css::Corner((i+1) % 4);
     mozilla::css::Corner prevCorner = mozilla::css::Corner(i);
 
@@ -1438,55 +1419,51 @@ nsCSSBorderRenderer::DrawNoCompositeColo
     Point outerCorner = mOuterRect.AtCorner(c);
     Point innerCorner = mInnerRect.AtCorner(c);
 
     // start and end points of border side stroke between corners
     Point sideStart =
       mOuterRect.AtCorner(prevCorner) +
         cornerMults[i2] * mBorderCornerDimensions[prevCorner];
     Point sideEnd = outerCorner + cornerMults[i] * mBorderCornerDimensions[c];
-    // if the side is inverted, don't draw it
-    if (-(sideEnd - sideStart).DotProduct(cornerMults[i]) <= 0) {
-      sideWidth = 0.0f;
+    // check if the side is visible and not inverted
+    if (sideWidth > 0 && firstColor.a > 0 &&
+        -(sideEnd - sideStart).DotProduct(cornerMults[i]) > 0) {
+      mDrawTarget->StrokeLine(sideStart + centerAdjusts[i] * sideWidth,
+                              sideEnd + centerAdjusts[i] * sideWidth,
+                              ColorPattern(firstColor),
+                              StrokeOptions(sideWidth));
     }
 
     Float skirtSize = 0.0f, skirtSlope = 0.0f;
     // the sides don't match, so compute a skirt
     if (firstColor != secondColor &&
         mPresContextType != nsPresContext::eContext_Print) {
       Point cornerDir = outerCorner - innerCorner;
       ComputeCornerSkirtSize(firstColor.a, secondColor.a,
                              cornerDir.DotProduct(cornerMults[i]),
                              cornerDir.DotProduct(cornerMults[i3]),
                              skirtSize, skirtSlope);
     }
 
     if (!mBorderRadii[c].IsEmpty()) {
       // the corner has a border radius
       DrawBorderRadius(mDrawTarget,
-                       sideStart, sideWidth,
                        c, outerCorner, innerCorner,
                        cornerMults[i], cornerMults[i3],
                        mBorderCornerDimensions[c],
                        mBorderRadii[c], innerRadii[c],
                        firstColor, secondColor, skirtSize, skirtSlope);
     } else if (!mBorderCornerDimensions[c].IsEmpty()) {
       // a corner with no border radius
       DrawCorner(mDrawTarget,
-                 sideStart, sideWidth,
                  c, outerCorner, innerCorner,
                  cornerMults[i], cornerMults[i3],
                  mBorderCornerDimensions[c],
                  firstColor, secondColor, skirtSize, skirtSlope);
-    } else if (sideWidth > 0 && firstColor.a > 0) {
-      // if there is no corner, then stroke the border side separately
-      mDrawTarget->StrokeLine(sideStart + centerAdjusts[i] * sideWidth,
-                              sideEnd + centerAdjusts[i] * sideWidth,
-                              ColorPattern(firstColor),
-                              StrokeOptions(sideWidth));
     }
   }
 }
 
 void
 nsCSSBorderRenderer::DrawRectangularCompositeColors()
 {
   nsBorderColors *currentColors[4];