Bug 1242147 - Honor stroke-linecap on SVG circle and ellipse when stroke is dashed. r=longsonr
authorTom Klein <twointofive@gmail.com>
Tue, 26 Jan 2016 12:30:36 -0600
changeset 281765 cc44ca7bde11647ea2150da56d00f6dec6848139
parent 281764 3412aee78e98bc65c42a45ee0c898efccb57e188
child 281766 8e3441257c0167899ab5ab033303577e602db807
push id29948
push usercbook@mozilla.com
push dateWed, 27 Jan 2016 11:00:24 +0000
treeherdermozilla-central@211a4c710fb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1242147
milestone47.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 1242147 - Honor stroke-linecap on SVG circle and ellipse when stroke is dashed. r=longsonr
dom/svg/SVGContentUtils.cpp
dom/svg/SVGContentUtils.h
layout/reftests/svg/reftest.list
layout/reftests/svg/stroke-linecap-circle-ellipse-dashed-01.svg
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -183,29 +183,31 @@ SVGContentUtils::GetStrokeOptions(AutoSt
   }
 
   if (!styleContext) {
     return;
   }
 
   const nsStyleSVG* styleSVG = styleContext->StyleSVG();
 
+  bool checkedDashAndStrokeIsDashed = false;
   if (aFlags != eIgnoreStrokeDashing) {
     DashState dashState =
       GetStrokeDashData(aStrokeOptions, aElement, styleSVG, aContextPaint);
 
     if (dashState == eNoStroke) {
       // Hopefully this will shortcircuit any stroke operations:
       aStrokeOptions->mLineWidth = 0;
       return;
     }
     if (dashState == eContinuousStroke && aStrokeOptions->mDashPattern) {
       // Prevent our caller from wasting time looking at a pattern without gaps:
       aStrokeOptions->DiscardDashPattern();
     }
+    checkedDashAndStrokeIsDashed = (dashState == eDashedStroke);
   }
 
   aStrokeOptions->mLineWidth =
     GetStrokeWidth(aElement, styleContext, aContextPaint);
 
   aStrokeOptions->mMiterLimit = Float(styleSVG->mStrokeMiterlimit);
 
   switch (styleSVG->mStrokeLinejoin) {
@@ -215,20 +217,22 @@ SVGContentUtils::GetStrokeOptions(AutoSt
   case NS_STYLE_STROKE_LINEJOIN_ROUND:
     aStrokeOptions->mLineJoin = JoinStyle::ROUND;
     break;
   case NS_STYLE_STROKE_LINEJOIN_BEVEL:
     aStrokeOptions->mLineJoin = JoinStyle::BEVEL;
     break;
   }
 
-  if (ShapeTypeHasNoCorners(aElement)) {
+  if (ShapeTypeHasNoCorners(aElement) && !checkedDashAndStrokeIsDashed) {
+    // Note: if aFlags == eIgnoreStrokeDashing then we may be returning the
+    // wrong linecap value here, since the actual linecap used on render in this
+    // case depends on whether the stroke is dashed or not.
     aStrokeOptions->mLineCap = CapStyle::BUTT;
-  }
-  else {
+  } else {
     switch (styleSVG->mStrokeLinecap) {
       case NS_STYLE_STROKE_LINECAP_BUTT:
         aStrokeOptions->mLineCap = CapStyle::BUTT;
         break;
       case NS_STYLE_STROKE_LINECAP_ROUND:
         aStrokeOptions->mLineCap = CapStyle::ROUND;
         break;
       case NS_STYLE_STROKE_LINECAP_SQUARE:
--- a/dom/svg/SVGContentUtils.h
+++ b/dom/svg/SVGContentUtils.h
@@ -158,16 +158,22 @@ public:
     // Most dasharrays will fit in this and save us allocating
     Float mSmallArray[16];
   };
 
   enum StrokeOptionFlags {
     eAllStrokeOptions,
     eIgnoreStrokeDashing
   };
+  /**
+   * Note: the linecap style returned in aStrokeOptions is not valid when
+   * ShapeTypeHasNoCorners(aElement) == true && aFlags == eIgnoreStrokeDashing,
+   * since when aElement has no corners the rendered linecap style depends on
+   * whether or not the stroke is dashed.
+   */
   static void GetStrokeOptions(AutoStrokeOptions* aStrokeOptions,
                                nsSVGElement* aElement,
                                nsStyleContext* aStyleContext,
                                gfxTextContextPaint *aContextPaint,
                                StrokeOptionFlags aFlags = eAllStrokeOptions);
 
   /**
    * Returns the current computed value of the CSS property 'stroke-width' for
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -288,16 +288,17 @@ fuzzy-if(cocoaWidget,4,15982) fuzzy-if(w
 == rect-03.svg pass.svg
 == rect-04.svg pass.svg
 == rect-with-rx-and-ry-01.svg pass.svg
 == rect-with-rx-or-ry-01.svg rect-with-rx-or-ry-01-ref.svg
 == rootElement-null-01.svg pass.svg
 == script-empty-01.svg pass.svg
 == selector-01.svg pass.svg
 == stroke-linecap-circle-ellipse-01.svg stroke-linecap-circle-ellipse-01-ref.svg
+== stroke-linecap-circle-ellipse-dashed-01.svg pass.svg
 == stroke-width-percentage-01.svg pass.svg
 == stroke-width-percentage-02a.svg stroke-width-percentage-02-ref.svg
 == stroke-width-percentage-02b.svg stroke-width-percentage-02-ref.svg
 == stroke-width-percentage-03.xhtml stroke-width-percentage-03-ref.xhtml
 == style-property-on-script-element-01.svg pass.svg
 == style-without-type-attribute.svg pass.svg
 == svg-in-foreignObject-01.xhtml svg-in-foreignObject-01-ref.xhtml
 == svg-in-foreignObject-02.xhtml svg-in-foreignObject-01-ref.xhtml # reuse -01-ref.xhtml
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/stroke-linecap-circle-ellipse-dashed-01.svg
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title>Test that stroke-linecap != "butt" is not ignored on circles and
+  ellipses with dashed stroke</title>
+  <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1242147 -->
+
+  <rect width="100%" height="100%" fill="lime" />
+
+  <circle cx="100" cy="100" r="25" fill="red" />
+  <circle cx="500" cy="100" r="25" fill="red" />
+  <!-- a half circle -->
+  <circle cx="300" cy="100" r="200" stroke="lime" fill="none"
+          stroke-width="80" stroke-linecap="round"
+          stroke-dasharray="628.318 1000" />
+
+  <path d="M 100,400 l 0,0" stroke="red" stroke-width="50"
+        stroke-linecap="square" />
+  <path d="M 500,400 l 0,0" stroke="red" stroke-width="50"
+        stroke-linecap="square" />
+  <!-- another half circle -->
+  <ellipse cx="300" cy="400" rx="200" ry="200" fill="none"
+           stroke="lime" stroke-width="80" stroke-linecap="square"
+           stroke-dasharray="628.318 1000" />
+
+</svg>