Bug 1121835: Infinite in canvas
authorMilan Sreckovic <milan@mozilla.com>
Mon, 19 Jan 2015 14:18:16 -0500
changeset 326728 852f84996843ac60478b5ac8bf760ff90ab0f9c2
parent 326727 7b186fd1105cab6d49e551329fbbea6dc765ee87
child 326729 7b3268cab61b9c901b3e5079e0e5323f3439d460
push id10169
push userdminor@mozilla.com
push dateThu, 28 Jan 2016 13:10:48 +0000
bugs1121835
milestone38.0a1
Bug 1121835: Infinite in canvas
gfx/2d/BasePoint.h
gfx/2d/PathCG.cpp
--- a/gfx/2d/BasePoint.h
+++ b/gfx/2d/BasePoint.h
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_GFX_BASEPOINT_H_
 #define MOZILLA_GFX_BASEPOINT_H_
 
 #include <cmath>
 #include "mozilla/Attributes.h"
 #include "mozilla/ToString.h"
+#include "mozilla/FloatingPoint.h"
+#include "mozilla/TypeTraits.h"
 
 namespace mozilla {
 namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
@@ -75,16 +77,24 @@ struct BasePoint {
   // They are always rounding as floor(n + 0.5).
   // See https://bugzilla.mozilla.org/show_bug.cgi?id=410748#c14
   Sub& Round() {
     x = Coord(floor(T(x) + T(0.5)));
     y = Coord(floor(T(y) + T(0.5)));
     return *static_cast<Sub*>(this);
   }
 
+  // "Finite" means not inf and not NaN
+  bool IsFinite() const
+  {
+    typedef typename mozilla::Conditional<mozilla::IsSame<T, float>::value, float, double>::Type FloatType;
+    return (mozilla::IsFinite(FloatType(x)) && mozilla::IsFinite(FloatType(y)));
+    return true;
+  }
+
   friend std::ostream& operator<<(std::ostream& stream, const BasePoint<T, Sub, Coord>& aPoint) {
     return stream << '(' << aPoint.x << ',' << aPoint.y << ')';
   }
 
 };
 
 }
 }
--- a/gfx/2d/PathCG.cpp
+++ b/gfx/2d/PathCG.cpp
@@ -15,65 +15,84 @@ namespace gfx {
 PathBuilderCG::~PathBuilderCG()
 {
   CGPathRelease(mCGPath);
 }
 
 void
 PathBuilderCG::MoveTo(const Point &aPoint)
 {
+  if (!aPoint.IsFinite()) {
+    return;
+  }
   CGPathMoveToPoint(mCGPath, nullptr, aPoint.x, aPoint.y);
 }
 
 void
 PathBuilderCG::LineTo(const Point &aPoint)
 {
+  if (!aPoint.IsFinite()) {
+    return;
+  }
+
   if (CGPathIsEmpty(mCGPath))
     MoveTo(aPoint);
   else
     CGPathAddLineToPoint(mCGPath, nullptr, aPoint.x, aPoint.y);
 }
 
 void
 PathBuilderCG::BezierTo(const Point &aCP1,
                          const Point &aCP2,
                          const Point &aCP3)
 {
+  if (!aCP1.IsFinite() || !aCP2.IsFinite() || !aCP3.IsFinite()) {
+    return;
+  }
 
   if (CGPathIsEmpty(mCGPath))
     MoveTo(aCP1);
   CGPathAddCurveToPoint(mCGPath, nullptr,
                           aCP1.x, aCP1.y,
                           aCP2.x, aCP2.y,
                           aCP3.x, aCP3.y);
 
 }
 
 void
 PathBuilderCG::QuadraticBezierTo(const Point &aCP1,
-                                  const Point &aCP2)
+                                 const Point &aCP2)
 {
+  if (!aCP1.IsFinite() || !aCP2.IsFinite()) {
+    return;
+  }
+
   if (CGPathIsEmpty(mCGPath))
     MoveTo(aCP1);
   CGPathAddQuadCurveToPoint(mCGPath, nullptr,
-                              aCP1.x, aCP1.y,
-                              aCP2.x, aCP2.y);
+                            aCP1.x, aCP1.y,
+                            aCP2.x, aCP2.y);
 }
 
 void
 PathBuilderCG::Close()
 {
   if (!CGPathIsEmpty(mCGPath))
     CGPathCloseSubpath(mCGPath);
 }
 
 void
 PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
                  Float aEndAngle, bool aAntiClockwise)
 {
+  if (!aOrigin.IsFinite() || !IsFinite(aRadius) ||
+      !IsFinite(aStartAngle) || !IsFinite(aEndAngle)) {
+    return;
+  }
+
   // Disabled for now due to a CG bug when using CGPathAddArc with stroke
   // dashing and rotation transforms that are multiples of 90 degrees. See:
   // https://bugzilla.mozilla.org/show_bug.cgi?id=949661#c8
 #if 0
   // Core Graphic's initial coordinate system is y-axis up, whereas Moz2D's is
   // y-axis down. Core Graphics therefore considers "clockwise" to mean "sweep
   // in the direction of decreasing angle" whereas Moz2D considers it to mean
   // "sweep in the direction of increasing angle". In other words if this