Bug 1024860 - getTotalLength on an empty path should not throw but return 0 instead. r=jwatt,bzbarsky
authorRobert Longson <longsonr@gmail.com>
Thu, 03 Jul 2014 19:50:42 +0100
changeset 192172 82210155467cd41aa704541c663e99db64fe464f
parent 192171 2c0234a7ba1eba725f4aa61a1d65d8190848a18f
child 192173 c571df9a85de14c34bab14c1bcd48303a326cb86
push id45775
push userlongsonr@gmail.com
push dateThu, 03 Jul 2014 18:51:02 +0000
treeherdermozilla-inbound@82210155467c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt, bzbarsky
bugs1024860
milestone33.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 1024860 - getTotalLength on an empty path should not throw but return 0 instead. r=jwatt,bzbarsky
content/svg/content/src/SVGPathElement.cpp
content/svg/content/src/SVGPathElement.h
content/svg/content/test/test_pathLength.html
dom/webidl/SVGPathElement.webidl
--- a/content/svg/content/src/SVGPathElement.cpp
+++ b/content/svg/content/src/SVGPathElement.cpp
@@ -63,26 +63,20 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPathE
 
 already_AddRefed<SVGAnimatedNumber>
 SVGPathElement::PathLength()
 {
   return mPathLength.ToDOMAnimatedNumber(this);
 }
 
 float
-SVGPathElement::GetTotalLength(ErrorResult& rv)
+SVGPathElement::GetTotalLength()
 {
   RefPtr<Path> flat = GetPathForLengthOrPositionMeasuring();
-
-  if (!flat) {
-    rv.Throw(NS_ERROR_FAILURE);
-    return 0.f;
-  }
-
-  return flat->ComputeLength();
+  return flat ? flat->ComputeLength() : 0.f;
 }
 
 already_AddRefed<nsISVGPoint>
 SVGPathElement::GetPointAtLength(float distance, ErrorResult& rv)
 {
   RefPtr<Path> path = GetPathForLengthOrPositionMeasuring();
   if (!path) {
     rv.Throw(NS_ERROR_FAILURE);
@@ -348,32 +342,33 @@ float
 SVGPathElement::GetPathLengthScale(PathLengthScaleForType aFor)
 {
   NS_ABORT_IF_FALSE(aFor == eForTextPath || aFor == eForStroking,
                     "Unknown enum");
   if (mPathLength.IsExplicitlySet()) {
     float authorsPathLengthEstimate = mPathLength.GetAnimValue();
     if (authorsPathLengthEstimate > 0) {
       RefPtr<Path> path = GetPathForLengthOrPositionMeasuring();
-
+      if (!path) {
+        // The path is empty or invalid so its length must be zero and
+        // we know that 0 / authorsPathLengthEstimate = 0.
+        return 0.0;
+      }
       if (aFor == eForTextPath) {
         // For textPath, a transform on the referenced path affects the
         // textPath layout, so when calculating the actual path length
         // we need to take that into account.
         gfxMatrix matrix = PrependLocalTransformsTo(gfxMatrix());
         if (!matrix.IsIdentity()) {
           RefPtr<PathBuilder> builder =
             path->TransformedCopyToBuilder(ToMatrix(matrix));
           path = builder->Finish();
         }
       }
-
-      if (path) {
-        return path->ComputeLength() / authorsPathLengthEstimate;
-      }
+      return path->ComputeLength() / authorsPathLengthEstimate;
     }
   }
   return 1.0;
 }
 
 TemporaryRef<Path>
 SVGPathElement::BuildPath()
 {
--- a/content/svg/content/src/SVGPathElement.h
+++ b/content/svg/content/src/SVGPathElement.h
@@ -83,17 +83,17 @@ public:
    * Gets the ratio of the actual path length to the content author's estimated
    * length (as provided by the <path> element's 'pathLength' attribute). This
    * is used to scale stroke dashing, and to scale offsets along a textPath.
    */
   float GetPathLengthScale(PathLengthScaleForType aFor);
 
   // WebIDL
   already_AddRefed<SVGAnimatedNumber> PathLength();
-  float GetTotalLength(ErrorResult& rv);
+  float GetTotalLength();
   already_AddRefed<nsISVGPoint> GetPointAtLength(float distance, ErrorResult& rv);
   uint32_t GetPathSegAtLength(float distance);
   already_AddRefed<DOMSVGPathSegClosePath> CreateSVGPathSegClosePath();
   already_AddRefed<DOMSVGPathSegMovetoAbs> CreateSVGPathSegMovetoAbs(float x, float y);
   already_AddRefed<DOMSVGPathSegMovetoRel> CreateSVGPathSegMovetoRel(float x, float y);
   already_AddRefed<DOMSVGPathSegLinetoAbs> CreateSVGPathSegLinetoAbs(float x, float y);
   already_AddRefed<DOMSVGPathSegLinetoRel> CreateSVGPathSegLinetoRel(float x, float y);
   already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
--- a/content/svg/content/test/test_pathLength.html
+++ b/content/svg/content/test/test_pathLength.html
@@ -27,14 +27,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   is(path.getTotalLength(), 500, "Unexpected path length");
 
   for (var i = 0; i < 2; i++) {
       path.pathSegList.removeItem(path.pathSegList.numberOfItems - 1);
   }
 
   is(path.getTotalLength(), 150, "Unexpected path length");
 
+  while (path.pathSegList.numberOfItems > 0) {
+      path.pathSegList.removeItem(0);
+  }
+
+  is(path.getTotalLength(), 0, "Unexpected path length");
+
   SimpleTest.finish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/webidl/SVGPathElement.webidl
+++ b/dom/webidl/SVGPathElement.webidl
@@ -8,17 +8,16 @@
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 interface SVGPathElement : SVGGraphicsElement {
 
   readonly attribute SVGAnimatedNumber pathLength;
 
-  [Throws]
   float getTotalLength();
   [NewObject, Throws]
   SVGPoint getPointAtLength(float distance);
   unsigned long getPathSegAtLength(float distance);
   [NewObject]
   SVGPathSegClosePath createSVGPathSegClosePath();
   [NewObject]
   SVGPathSegMovetoAbs createSVGPathSegMovetoAbs(float x, float y);