Bug 1128281 - Pass strokeOptions to getGeometryBounds. r=jwatt
authorRobert Longson <longsonr@gmail.com>
Tue, 03 Feb 2015 18:36:32 +0000
changeset 227275 0f178e40b0748893a7267af2032c18268a65df2c
parent 227274 1a49a285e08e1fde4a2d5f433ad5de5a862e2ede
child 227276 f33e104ef0b4881a03e1a8d84ce53c730c9aaa8c
push id28225
push userryanvm@gmail.com
push dateTue, 03 Feb 2015 21:15:47 +0000
treeherdermozilla-central@0c2f7434c325 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs1128281
milestone38.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 1128281 - Pass strokeOptions to getGeometryBounds. r=jwatt
dom/svg/SVGCircleElement.cpp
dom/svg/SVGCircleElement.h
dom/svg/SVGEllipseElement.cpp
dom/svg/SVGEllipseElement.h
dom/svg/SVGImageElement.cpp
dom/svg/SVGImageElement.h
dom/svg/SVGLineElement.cpp
dom/svg/SVGLineElement.h
dom/svg/SVGRectElement.cpp
dom/svg/SVGRectElement.h
dom/svg/nsSVGPathGeometryElement.h
dom/svg/nsSVGPolyElement.cpp
dom/svg/nsSVGPolyElement.h
layout/svg/nsSVGPathGeometryFrame.cpp
--- a/dom/svg/SVGCircleElement.cpp
+++ b/dom/svg/SVGCircleElement.cpp
@@ -77,33 +77,33 @@ SVGCircleElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGCircleElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                    CapStyle aCapStyle, const Matrix& aTransform)
+SVGCircleElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   float x, y, r;
   GetAnimatedLengthValues(&x, &y, &r, nullptr);
 
   if (r <= 0.f) {
     // Rendering of the element is disabled
     *aBounds = Rect(aTransform * Point(x, y), Size());
     return true;
   }
 
   if (aTransform.IsRectilinear()) {
     // Optimize the case where we can treat the circle as a rectangle and
     // still get tight bounds.
-    if (aStrokeWidth > 0.f) {
-      r += aStrokeWidth / 2.f;
+    if (aStrokeOptions.mLineWidth > 0.f) {
+      r += aStrokeOptions.mLineWidth / 2.f;
     }
     Rect rect(x - r, y - r, 2 * r, 2 * r);
     *aBounds = aTransform.TransformBounds(rect);
     return true;
   }
 
   return false;
 }
--- a/dom/svg/SVGCircleElement.h
+++ b/dom/svg/SVGCircleElement.h
@@ -25,18 +25,18 @@ protected:
   friend nsresult (::NS_NewSVGCircleElement(nsIContent **aResult,
                                             already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
   virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> R();
--- a/dom/svg/SVGEllipseElement.cpp
+++ b/dom/svg/SVGEllipseElement.cpp
@@ -88,34 +88,34 @@ SVGEllipseElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGEllipseElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                     CapStyle aCapStyle, const Matrix& aTransform)
+SVGEllipseElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   float x, y, rx, ry;
   GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
 
   if (rx <= 0.f || ry <= 0.f) {
     // Rendering of the element is disabled
     *aBounds = Rect(aTransform * Point(x, y), Size());
     return true;
   }
 
   if (aTransform.IsRectilinear()) {
     // Optimize the case where we can treat the ellipse as a rectangle and
     // still get tight bounds.
-    if (aStrokeWidth > 0.f) {
-      rx += aStrokeWidth / 2.f;
-      ry += aStrokeWidth / 2.f;
+    if (aStrokeOptions.mLineWidth > 0.f) {
+      rx += aStrokeOptions.mLineWidth / 2.f;
+      ry += aStrokeOptions.mLineWidth / 2.f;
     }
     Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
     *aBounds = aTransform.TransformBounds(rect);
     return true;
   }
 
   return false;
 }
--- a/dom/svg/SVGEllipseElement.h
+++ b/dom/svg/SVGEllipseElement.h
@@ -25,18 +25,18 @@ protected:
   friend nsresult (::NS_NewSVGEllipseElement(nsIContent **aResult,
                                              already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
   virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> Rx();
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -220,18 +220,18 @@ SVGImageElement::IsAttributeMapped(const
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 /* For the purposes of the update/invalidation logic pretend to
    be a rectangle. */
 bool
-SVGImageElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                   CapStyle aCapStyle, const Matrix& aTransform)
+SVGImageElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   Rect rect;
   GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width,
                           &rect.height, nullptr);
 
   if (rect.IsEmpty()) {
     // Rendering of the element disabled
     rect.SetEmpty(); // Make sure width/height are zero and not negative
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -48,18 +48,18 @@ public:
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) MOZ_OVERRIDE;
 
   virtual EventStates IntrinsicState() const MOZ_OVERRIDE;
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle cap, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
   virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
--- a/dom/svg/SVGLineElement.cpp
+++ b/dom/svg/SVGLineElement.cpp
@@ -122,58 +122,58 @@ SVGLineElement::BuildPath(PathBuilder* a
 
   aBuilder->MoveTo(Point(x1, y1));
   aBuilder->LineTo(Point(x2, y2));
 
   return aBuilder->Finish();
 }
 
 bool
-SVGLineElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                  CapStyle aCapStyle, const Matrix& aTransform)
+SVGLineElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   float x1, y1, x2, y2;
   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
 
-  if (aStrokeWidth <= 0) {
+  if (aStrokeOptions.mLineWidth <= 0) {
     *aBounds = Rect(aTransform * Point(x1, y1), Size());
     aBounds->ExpandToEnclose(aTransform * Point(x2, y2));
     return true;
   }
 
-  if (aCapStyle == CapStyle::ROUND) {
+  if (aStrokeOptions.mLineCap == CapStyle::ROUND) {
     if (!aTransform.IsRectilinear()) {
       // TODO: handle this case.
       return false;
     }
     Rect bounds(Point(x1, y1), Size());
     bounds.ExpandToEnclose(Point(x2, y2));
-    bounds.Inflate(aStrokeWidth / 2.f);
+    bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
     *aBounds = aTransform.TransformBounds(bounds);
     return true;
   }
 
   Float length = Float(NS_hypot(x2 - x1, y2 - y1));
   Float xDelta;
   Float yDelta;
 
-  if (aCapStyle == CapStyle::BUTT) {
+  if (aStrokeOptions.mLineCap == CapStyle::BUTT) {
     if (length == 0.f) {
       xDelta = yDelta = 0.f;
     } else {
-      Float ratio = aStrokeWidth / 2.f / length;
+      Float ratio = aStrokeOptions.mLineWidth / 2.f / length;
       xDelta = ratio * (y2 - y1);
       yDelta = ratio * (x2 - x1);
     }
   } else {
-    MOZ_ASSERT(aCapStyle == CapStyle::SQUARE);
+    MOZ_ASSERT(aStrokeOptions.mLineCap == CapStyle::SQUARE);
     if (length == 0.f) {
-      xDelta = yDelta = aStrokeWidth / 2.f;
+      xDelta = yDelta = aStrokeOptions.mLineWidth / 2.f;
     } else {
-      Float ratio = aStrokeWidth / 2.f / length;
+      Float ratio = aStrokeOptions.mLineWidth / 2.f / length;
       xDelta = yDelta = ratio * (fabs(y2 - y1) + fabs(x2 - x1));
     }
   }
 
   Point points[4];
 
   points[0] = Point(x1 - xDelta, y1 - yDelta);
   points[1] = Point(x1 + xDelta, y1 + yDelta);
--- a/dom/svg/SVGLineElement.h
+++ b/dom/svg/SVGLineElement.h
@@ -29,18 +29,18 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
   virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) MOZ_OVERRIDE;
   virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder) MOZ_OVERRIDE;
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle cap, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X1();
   already_AddRefed<SVGAnimatedLength> Y1();
   already_AddRefed<SVGAnimatedLength> X2();
   already_AddRefed<SVGAnimatedLength> Y2();
--- a/dom/svg/SVGRectElement.cpp
+++ b/dom/svg/SVGRectElement.cpp
@@ -106,18 +106,18 @@ SVGRectElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGRectElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                  CapStyle aCapStyle, const Matrix& aTransform)
+SVGRectElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   Rect rect;
   Float rx, ry;
   GetAnimatedLengthValues(&rect.x, &rect.y, &rect.width,
                           &rect.height, &rx, &ry, nullptr);
 
   if (rect.IsEmpty()) {
     // Rendering of the element disabled
@@ -132,18 +132,18 @@ SVGRectElement::GetGeometryBounds(Rect* 
     rx = std::max(rx, 0.0f);
     ry = std::max(ry, 0.0f);
 
     if (rx != 0 || ry != 0) {
       return false;
     }
   }
 
-  if (aStrokeWidth > 0.f) {
-    rect.Inflate(aStrokeWidth / 2.f);
+  if (aStrokeOptions.mLineWidth > 0.f) {
+    rect.Inflate(aStrokeOptions.mLineWidth / 2.f);
   }
 
   *aBounds = aTransform.TransformBounds(rect);
   return true;
 }
 
 void
 SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath)
--- a/dom/svg/SVGRectElement.h
+++ b/dom/svg/SVGRectElement.h
@@ -25,18 +25,18 @@ protected:
   friend nsresult (::NS_NewSVGRectElement(nsIContent **aResult,
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) MOZ_OVERRIDE;
   virtual TemporaryRef<Path> BuildPath(PathBuilder* aBuilder = nullptr) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
--- a/dom/svg/nsSVGPathGeometryElement.h
+++ b/dom/svg/nsSVGPathGeometryElement.h
@@ -35,16 +35,17 @@ protected:
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::FillRule FillRule;
   typedef mozilla::gfx::Float Float;
   typedef mozilla::gfx::Matrix Matrix;
   typedef mozilla::gfx::Path Path;
   typedef mozilla::gfx::Point Point;
   typedef mozilla::gfx::PathBuilder PathBuilder;
   typedef mozilla::gfx::Rect Rect;
+  typedef mozilla::gfx::StrokeOptions StrokeOptions;
 
 public:
   explicit nsSVGPathGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
 
   /**
@@ -72,18 +73,18 @@ public:
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
 
   /**
    * A method that can be faster than using a Moz2D Path and calling GetBounds/
    * GetStrokedBounds on it.  It also helps us avoid rounding error for simple
    * shapes and simple transforms where the Moz2D Path backends can fail to
    * produce the clean integer bounds that content authors expect in some cases.
    */
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle aCapStyle, const Matrix& aTransform) {
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) {
     return false;
   }
 
   /**
    * For use with GetAsSimplePath.
    */
   class SimplePath
   {
--- a/dom/svg/nsSVGPolyElement.cpp
+++ b/dom/svg/nsSVGPolyElement.cpp
@@ -116,28 +116,28 @@ nsSVGPolyElement::GetMarkPoints(nsTArray
     py = y;
   }
 
   aMarks->LastElement().angle = prevAngle;
   aMarks->LastElement().type = nsSVGMark::eEnd;
 }
 
 bool
-nsSVGPolyElement::GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                    CapStyle aCapStyle, const Matrix& aTransform)
+nsSVGPolyElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
   const SVGPointList &points = mPoints.GetAnimValue();
 
   if (!points.Length()) {
     // Rendering of the element is disabled
     aBounds->SetEmpty();
     return true;
   }
 
-  if (aStrokeWidth > 0) {
+  if (aStrokeOptions.mLineWidth > 0) {
     // We don't handle stroke-miterlimit etc. yet
     return false;
   }
 
   if (aTransform.IsRectilinear()) {
     // We can avoid transforming each point and just transform the result.
     // Important for large point lists.
     Rect bounds(points[0], Size());
--- a/dom/svg/nsSVGPolyElement.h
+++ b/dom/svg/nsSVGPolyElement.h
@@ -40,18 +40,18 @@ public:
 
   // nsSVGElement methods:
   virtual bool HasValidDimensions() const MOZ_OVERRIDE;
 
   // nsSVGPathGeometryElement methods:
   virtual bool AttributeDefinesGeometry(const nsIAtom *aName) MOZ_OVERRIDE;
   virtual bool IsMarkable() MOZ_OVERRIDE { return true; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) MOZ_OVERRIDE;
-  virtual bool GetGeometryBounds(Rect* aBounds, Float aStrokeWidth,
-                                 CapStyle aCapStyle, const Matrix& aTransform) MOZ_OVERRIDE;
+  virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
+                                 const Matrix& aTransform) MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<mozilla::DOMSVGPointList> Points();
   already_AddRefed<mozilla::DOMSVGPointList> AnimatedPoints();
 
 protected:
   SVGAnimatedPointList mPoints;
 };
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -475,18 +475,17 @@ nsSVGPathGeometryFrame::GetBBoxContribut
     strokeOptions.mLineWidth = 0.f;
     if (getStroke) {
       SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
         StyleContext(), nullptr,
         SVGContentUtils::eIgnoreStrokeDashing);
     }
     Rect simpleBounds;
     gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
-                                                 strokeOptions.mLineWidth,
-                                                 strokeOptions.mLineCap,
+                                                 strokeOptions,
                                                  aToBBoxUserspace);
     if (gotSimpleBounds) {
       bbox = simpleBounds;
     }
   }
 
   if (!gotSimpleBounds) {
     // Get the bounds using a Moz2D Path object (more expensive):