Backed out changeset 1f22cefbef23 (bug 1092125) for M3 bustage on CLOSED TREE
authorNigel Babu <nigelbabu@gmail.com>
Wed, 02 Sep 2015 11:34:47 +0530
changeset 260451 192893adb2c38cf940aba5d1f06c4f89aa75b45a
parent 260450 63bf0b9aed0fced2510cb89a481cb51763f85087
child 260452 196b7de875ef521f938904e0dceb62a6ba2fd897
push id64502
push usernigelbabu@gmail.com
push dateWed, 02 Sep 2015 06:05:45 +0000
treeherdermozilla-inbound@192893adb2c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1092125
milestone43.0a1
backs out1f22cefbef234d7a7d30b004af735fe7a4c3dfe1
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
Backed out changeset 1f22cefbef23 (bug 1092125) for M3 bustage on CLOSED TREE
dom/svg/SVGCircleElement.cpp
dom/svg/SVGCircleElement.h
dom/svg/SVGContentUtils.cpp
dom/svg/SVGContentUtils.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
dom/svg/test/bounds-helper.svg
dom/svg/test/test_bounds.html
layout/svg/nsSVGPathGeometryFrame.cpp
--- a/dom/svg/SVGCircleElement.cpp
+++ b/dom/svg/SVGCircleElement.cpp
@@ -78,48 +78,36 @@ SVGCircleElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGCircleElement::GetGeometryBounds(Rect* aBounds,
-                                    const StrokeOptions& aStrokeOptions,
-                                    const Matrix& aToBoundsSpace,
-                                    const Matrix* aToNonScalingStrokeSpace)
+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(aToBoundsSpace * Point(x, y), Size());
+    *aBounds = Rect(aTransform * Point(x, y), Size());
     return true;
   }
 
-  if (aToBoundsSpace.IsRectilinear()) {
+  if (aTransform.IsRectilinear()) {
     // Optimize the case where we can treat the circle as a rectangle and
     // still get tight bounds.
     if (aStrokeOptions.mLineWidth > 0.f) {
-      if (aToNonScalingStrokeSpace) {
-        if (aToNonScalingStrokeSpace->IsRectilinear()) {
-          Rect userBounds(x - r, y - r, 2 * r, 2 * r);
-          SVGContentUtils::RectilinearGetStrokeBounds(
-            userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
-            aStrokeOptions.mLineWidth, aBounds);
-          return true;
-        }
-        return false;
-      }
       r += aStrokeOptions.mLineWidth / 2.f;
     }
     Rect rect(x - r, y - r, 2 * r, 2 * r);
-    *aBounds = aToBoundsSpace.TransformBounds(rect);
+    *aBounds = aTransform.TransformBounds(rect);
     return true;
   }
 
   return false;
 }
 
 already_AddRefed<Path>
 SVGCircleElement::BuildPath(PathBuilder* aBuilder)
--- a/dom/svg/SVGCircleElement.h
+++ b/dom/svg/SVGCircleElement.h
@@ -27,18 +27,17 @@ protected:
                                             already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> R();
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -459,55 +459,16 @@ GetCTMInternal(nsSVGElement *aElement, b
 }
 
 gfx::Matrix
 SVGContentUtils::GetCTM(nsSVGElement *aElement, bool aScreenCTM)
 {
   return GetCTMInternal(aElement, aScreenCTM, false);
 }
 
-void
-SVGContentUtils::RectilinearGetStrokeBounds(const Rect& aRect,
-                                            const Matrix& aToBoundsSpace,
-                                            const Matrix& aToNonScalingStrokeSpace,
-                                            float aStrokeWidth,
-                                            Rect* aBounds)
-{
-  MOZ_ASSERT(aToBoundsSpace.IsRectilinear(),
-             "aToBoundsSpace must be rectilinear");
-  MOZ_ASSERT(aToNonScalingStrokeSpace.IsRectilinear(),
-             "aToNonScalingStrokeSpace must be rectilinear");
-
-  Matrix nonScalingToSource = aToNonScalingStrokeSpace.Inverse();
-  Matrix nonScalingToBounds = nonScalingToSource * aToBoundsSpace;
-
-  *aBounds = aToBoundsSpace.TransformBounds(aRect);
-
-  // Compute the amounts dx and dy that nonScalingToBounds scales a half-width
-  // stroke in the x and y directions, and then inflate aBounds by those amounts
-  // so that when aBounds is transformed back to non-scaling-stroke space
-  // it will map onto the correct stroked bounds.
-
-  Float dx = 0.0f;
-  Float dy = 0.0f;
-  // nonScalingToBounds is rectilinear, so either _12 and _21 are zero or _11
-  // and _22 are zero, and in each case the non-zero entries (from among _11,
-  // _12, _21, _22) simply scale the stroke width in the x and y directions.
-  if (FuzzyEqual(nonScalingToBounds._12, 0) &&
-      FuzzyEqual(nonScalingToBounds._21, 0)) {
-    dx = (aStrokeWidth / 2.0f) * std::abs(nonScalingToBounds._11);
-    dy = (aStrokeWidth / 2.0f) * std::abs(nonScalingToBounds._22);
-  } else {
-    dx = (aStrokeWidth / 2.0f) * std::abs(nonScalingToBounds._21);
-    dy = (aStrokeWidth / 2.0f) * std::abs(nonScalingToBounds._12);
-  }
-
-  aBounds->Inflate(dx, dy);
-}
-
 double
 SVGContentUtils::ComputeNormalizedHypotenuse(double aWidth, double aHeight)
 {
   return sqrt((aWidth*aWidth + aHeight*aHeight)/2);
 }
 
 float
 SVGContentUtils::AngleBisect(float a1, float a2)
--- a/dom/svg/SVGContentUtils.h
+++ b/dom/svg/SVGContentUtils.h
@@ -58,18 +58,16 @@ IsSVGWhitespace(char16_t aChar)
 /**
  * Functions generally used by SVG Content classes. Functions here
  * should not generally depend on layout methods/classes e.g. nsSVGUtils
  */
 class SVGContentUtils
 {
 public:
   typedef mozilla::gfx::Float Float;
-  typedef mozilla::gfx::Matrix Matrix;
-  typedef mozilla::gfx::Rect Rect;
   typedef mozilla::gfx::StrokeOptions StrokeOptions;
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
   typedef mozilla::SVGPreserveAspectRatio SVGPreserveAspectRatio;
 
   /*
    * Get the outer SVG element of an nsIContent
    */
   static mozilla::dom::SVGSVGElement *GetOuterSVGElement(nsSVGElement *aSVGElement);
@@ -177,33 +175,17 @@ public:
   /*
    * Report a localized error message to the error console.
    */
   static nsresult ReportToConsole(nsIDocument* doc,
                                   const char* aWarning,
                                   const char16_t **aParams,
                                   uint32_t aParamsLength);
 
-  static Matrix GetCTM(nsSVGElement *aElement, bool aScreenCTM);
-
-  /**
-   * Gets the tight bounds-space stroke bounds of the non-scaling-stroked rect
-   * aRect.
-   * @param aToBoundsSpace transforms from source space to the space aBounds
-   *        should be computed in.  Must be rectilinear.
-   * @param aToNonScalingStrokeSpace transforms from source
-   *        space to the space in which non-scaling stroke should be applied.
-   *        Must be rectilinear.
-   */
-  static void
-  RectilinearGetStrokeBounds(const Rect& aRect,
-                             const Matrix& aToBoundsSpace,
-                             const Matrix& aToNonScalingStrokeSpace,
-                             float aStrokeWidth,
-                             Rect* aBounds);
+  static mozilla::gfx::Matrix GetCTM(nsSVGElement *aElement, bool aScreenCTM);
 
   /**
    * Check if this is one of the SVG elements that SVG 1.1 Full says
    * establishes a viewport: svg, symbol, image or foreignObject.
    */
   static bool EstablishesViewport(nsIContent *aContent);
 
   static nsSVGElement*
@@ -218,23 +200,23 @@ public:
   static double ComputeNormalizedHypotenuse(double aWidth, double aHeight);
 
   /* Returns the angle halfway between the two specified angles */
   static float
   AngleBisect(float a1, float a2);
 
   /* Generate a viewbox to viewport tranformation matrix */
 
-  static Matrix
+  static mozilla::gfx::Matrix
   GetViewBoxTransform(float aViewportWidth, float aViewportHeight,
                       float aViewboxX, float aViewboxY,
                       float aViewboxWidth, float aViewboxHeight,
                       const SVGAnimatedPreserveAspectRatio &aPreserveAspectRatio);
 
-  static Matrix
+  static mozilla::gfx::Matrix
   GetViewBoxTransform(float aViewportWidth, float aViewportHeight,
                       float aViewboxX, float aViewboxY,
                       float aViewboxWidth, float aViewboxHeight,
                       const SVGPreserveAspectRatio &aPreserveAspectRatio);
 
   static mozilla::RangedPtr<const char16_t>
   GetStartRangedPtr(const nsAString& aString);
 
--- a/dom/svg/SVGEllipseElement.cpp
+++ b/dom/svg/SVGEllipseElement.cpp
@@ -89,49 +89,37 @@ SVGEllipseElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGEllipseElement::GetGeometryBounds(Rect* aBounds,
-                                     const StrokeOptions& aStrokeOptions,
-                                     const Matrix& aToBoundsSpace,
-                                     const Matrix* aToNonScalingStrokeSpace)
+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(aToBoundsSpace * Point(x, y), Size());
+    *aBounds = Rect(aTransform * Point(x, y), Size());
     return true;
   }
 
-  if (aToBoundsSpace.IsRectilinear()) {
+  if (aTransform.IsRectilinear()) {
     // Optimize the case where we can treat the ellipse as a rectangle and
     // still get tight bounds.
     if (aStrokeOptions.mLineWidth > 0.f) {
-      if (aToNonScalingStrokeSpace) {
-        if (aToNonScalingStrokeSpace->IsRectilinear()) {
-          Rect userBounds(x - rx, y - ry, 2 * rx, 2 * ry);
-          SVGContentUtils::RectilinearGetStrokeBounds(
-            userBounds, aToBoundsSpace, *aToNonScalingStrokeSpace,
-            aStrokeOptions.mLineWidth, aBounds);
-          return true;
-        }
-        return false;
-      }
       rx += aStrokeOptions.mLineWidth / 2.f;
       ry += aStrokeOptions.mLineWidth / 2.f;
     }
     Rect rect(x - rx, y - ry, 2 * rx, 2 * ry);
-    *aBounds = aToBoundsSpace.TransformBounds(rect);
+    *aBounds = aTransform.TransformBounds(rect);
     return true;
   }
 
   return false;
 }
 
 already_AddRefed<Path>
 SVGEllipseElement::BuildPath(PathBuilder* aBuilder)
--- a/dom/svg/SVGEllipseElement.h
+++ b/dom/svg/SVGEllipseElement.h
@@ -27,18 +27,17 @@ protected:
                                              already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> Cx();
   already_AddRefed<SVGAnimatedLength> Cy();
   already_AddRefed<SVGAnimatedLength> Rx();
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -221,31 +221,29 @@ SVGImageElement::IsAttributeMapped(const
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 /* For the purposes of the update/invalidation logic pretend to
    be a rectangle. */
 bool
-SVGImageElement::GetGeometryBounds(Rect* aBounds,
-                                   const StrokeOptions& aStrokeOptions,
-                                   const Matrix& aToBoundsSpace,
-                                   const Matrix* aToNonScalingStrokeSpace)
+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
   }
 
-  *aBounds = aToBoundsSpace.TransformBounds(rect);
+  *aBounds = aTransform.TransformBounds(rect);
   return true;
 }
 
 already_AddRefed<Path>
 SVGImageElement::BuildPath(PathBuilder* aBuilder)
 {
   // We get called in order to get bounds for this element, and for
   // hit-testing against it. For that we just pretend to be a rectangle.
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -50,18 +50,17 @@ public:
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual EventStates IntrinsicState() const override;
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
 
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
--- a/dom/svg/SVGLineElement.cpp
+++ b/dom/svg/SVGLineElement.cpp
@@ -143,43 +143,37 @@ SVGLineElement::BuildPath(PathBuilder* a
   MaybeAdjustForZeroLength(x1, y1, x2, y2);
   aBuilder->MoveTo(Point(x1, y1));
   aBuilder->LineTo(Point(x2, y2));
 
   return aBuilder->Finish();
 }
 
 bool
-SVGLineElement::GetGeometryBounds(Rect* aBounds,
-                                  const StrokeOptions& aStrokeOptions,
-                                  const Matrix& aToBoundsSpace,
-                                  const Matrix* aToNonScalingStrokeSpace)
+SVGLineElement::GetGeometryBounds(
+  Rect* aBounds, const StrokeOptions& aStrokeOptions, const Matrix& aTransform)
 {
-  if (aToNonScalingStrokeSpace) {
-    return false;
-  }
-
   float x1, y1, x2, y2;
   GetAnimatedLengthValues(&x1, &y1, &x2, &y2, nullptr);
 
   if (aStrokeOptions.mLineWidth <= 0) {
-    *aBounds = Rect(aToBoundsSpace * Point(x1, y1), Size());
-    aBounds->ExpandToEnclose(aToBoundsSpace * Point(x2, y2));
+    *aBounds = Rect(aTransform * Point(x1, y1), Size());
+    aBounds->ExpandToEnclose(aTransform * Point(x2, y2));
     return true;
   }
 
   if (aStrokeOptions.mLineCap == CapStyle::ROUND) {
-    if (!aToBoundsSpace.IsRectilinear()) {
+    if (!aTransform.IsRectilinear()) {
       // TODO: handle this case.
       return false;
     }
     Rect bounds(Point(x1, y1), Size());
     bounds.ExpandToEnclose(Point(x2, y2));
     bounds.Inflate(aStrokeOptions.mLineWidth / 2.f);
-    *aBounds = aToBoundsSpace.TransformBounds(bounds);
+    *aBounds = aTransform.TransformBounds(bounds);
     return true;
   }
 
   Float length = Float(NS_hypot(x2 - x1, y2 - y1));
   Float xDelta;
   Float yDelta;
 
   if (aStrokeOptions.mLineCap == CapStyle::BUTT) {
@@ -202,17 +196,17 @@ SVGLineElement::GetGeometryBounds(Rect* 
 
   Point points[4];
 
   points[0] = Point(x1 - xDelta, y1 - yDelta);
   points[1] = Point(x1 + xDelta, y1 + yDelta);
   points[2] = Point(x2 + xDelta, y2 + yDelta);
   points[3] = Point(x2 - xDelta, y2 - yDelta);
 
-  *aBounds = Rect(aToBoundsSpace * points[0], Size());
+  *aBounds = Rect(aTransform * points[0], Size());
   for (uint32_t i = 1; i < 4; ++i) {
-    aBounds->ExpandToEnclose(aToBoundsSpace * points[i]);
+    aBounds->ExpandToEnclose(aTransform * points[i]);
   }
   return true;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/svg/SVGLineElement.h
+++ b/dom/svg/SVGLineElement.h
@@ -35,18 +35,17 @@ public:
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool IsMarkable() override { return true; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) override;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder) override;
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const 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
@@ -107,67 +107,47 @@ SVGRectElement::GetLengthInfo()
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 //----------------------------------------------------------------------
 // nsSVGPathGeometryElement methods
 
 bool
-SVGRectElement::GetGeometryBounds(Rect* aBounds,
-                                  const StrokeOptions& aStrokeOptions,
-                                  const Matrix& aToBoundsSpace,
-                                  const Matrix* aToNonScalingStrokeSpace)
+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
     rect.SetEmpty(); // Make sure width/height are zero and not negative
     // We still want the x/y position from 'rect'
-    *aBounds = aToBoundsSpace.TransformBounds(rect);
+    *aBounds = aTransform.TransformBounds(rect);
     return true;
   }
 
-  if (!aToBoundsSpace.IsRectilinear()) {
+  if (!aTransform.IsRectilinear()) {
     // We can't ignore the radii in this case if we want tight bounds
     rx = std::max(rx, 0.0f);
     ry = std::max(ry, 0.0f);
 
     if (rx != 0 || ry != 0) {
       return false;
     }
   }
 
   if (aStrokeOptions.mLineWidth > 0.f) {
-    if (aToNonScalingStrokeSpace) {
-      if (aToNonScalingStrokeSpace->IsRectilinear()) {
-        rect = aToNonScalingStrokeSpace->TransformBounds(rect);
-        // Note that, in principle, an author could cause the corners of the
-        // rect to be beveled by specifying stroke-linejoin or setting
-        // stroke-miterlimit to be less than sqrt(2). In that very unlikely
-        // event the bounds that we calculate here may be too big if
-        // aToBoundsSpace is non-rectilinear. This is likely to be so rare it's
-        // not worth handling though.
-        rect.Inflate(aStrokeOptions.mLineWidth / 2.f);
-        Matrix nonScalingToBounds =
-          aToNonScalingStrokeSpace->Inverse() * aToBoundsSpace;
-        *aBounds = nonScalingToBounds.TransformBounds(rect);
-        return true;
-      }
-      return false;
-    }
-    // The "beveled" comment above applies here too
     rect.Inflate(aStrokeOptions.mLineWidth / 2.f);
   }
 
-  *aBounds = aToBoundsSpace.TransformBounds(rect);
+  *aBounds = aTransform.TransformBounds(rect);
   return true;
 }
 
 void
 SVGRectElement::GetAsSimplePath(SimplePath* aSimplePath)
 {
   float x, y, width, height, rx, ry;
   GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nullptr);
--- a/dom/svg/SVGRectElement.h
+++ b/dom/svg/SVGRectElement.h
@@ -27,18 +27,17 @@ protected:
                                           already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo));
 
 public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
   virtual void GetAsSimplePath(SimplePath* aSimplePath) override;
   virtual already_AddRefed<Path> BuildPath(PathBuilder* aBuilder = nullptr) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
--- a/dom/svg/nsSVGPathGeometryElement.h
+++ b/dom/svg/nsSVGPathGeometryElement.h
@@ -71,28 +71,19 @@ public:
   virtual bool IsMarkable();
   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.
-   *
-   * If |aToNonScalingStrokeSpace| is non-null then |aBounds|, which is computed
-   * in bounds space, has the property that it's the smallest (axis-aligned)
-   * rectangular bound containing the image of this shape as stroked in
-   * non-scaling-stroke space.  (When all transforms involved are rectilinear
-   * the bounds of the image of |aBounds| in non-scaling-stroke space will be
-   * tight, but if there are non-rectilinear transforms involved then that may
-   * be impossible and this method will return false).
    */
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) {
+                                 const Matrix& aTransform) {
     return false;
   }
 
   /**
    * For use with GetAsSimplePath.
    */
   class SimplePath
   {
--- a/dom/svg/nsSVGPolyElement.cpp
+++ b/dom/svg/nsSVGPolyElement.cpp
@@ -117,43 +117,41 @@ nsSVGPolyElement::GetMarkPoints(nsTArray
     py = y;
   }
 
   aMarks->LastElement().angle = prevAngle;
   aMarks->LastElement().type = nsSVGMark::eEnd;
 }
 
 bool
-nsSVGPolyElement::GetGeometryBounds(Rect* aBounds,
-                                    const StrokeOptions& aStrokeOptions,
-                                    const Matrix& aToBoundsSpace,
-                                    const Matrix* aToNonScalingStrokeSpace)
+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 (aStrokeOptions.mLineWidth > 0 || aToNonScalingStrokeSpace) {
-    // We don't handle non-scaling-stroke or stroke-miterlimit etc. yet
+  if (aStrokeOptions.mLineWidth > 0) {
+    // We don't handle stroke-miterlimit etc. yet
     return false;
   }
 
-  if (aToBoundsSpace.IsRectilinear()) {
+  if (aTransform.IsRectilinear()) {
     // We can avoid transforming each point and just transform the result.
     // Important for large point lists.
     Rect bounds(points[0], Size());
     for (uint32_t i = 1; i < points.Length(); ++i) {
       bounds.ExpandToEnclose(points[i]);
     }
-    *aBounds = aToBoundsSpace.TransformBounds(bounds);
+    *aBounds = aTransform.TransformBounds(bounds);
   } else {
-    *aBounds = Rect(aToBoundsSpace * points[0], Size());
+    *aBounds = Rect(aTransform * points[0], Size());
     for (uint32_t i = 1; i < points.Length(); ++i) {
-      aBounds->ExpandToEnclose(aToBoundsSpace * points[i]);
+      aBounds->ExpandToEnclose(aTransform * points[i]);
     }
   }
   return true;
 }
 
--- a/dom/svg/nsSVGPolyElement.h
+++ b/dom/svg/nsSVGPolyElement.h
@@ -42,18 +42,17 @@ public:
   // nsSVGElement methods:
   virtual bool HasValidDimensions() const override;
 
   // nsSVGPathGeometryElement methods:
   virtual bool AttributeDefinesGeometry(const nsIAtom *aName) override;
   virtual bool IsMarkable() override { return true; }
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks) override;
   virtual bool GetGeometryBounds(Rect* aBounds, const StrokeOptions& aStrokeOptions,
-                                 const Matrix& aToBoundsSpace,
-                                 const Matrix* aToNonScalingStrokeSpace = nullptr) override;
+                                 const Matrix& aTransform) override;
 
   // WebIDL
   already_AddRefed<mozilla::DOMSVGPointList> Points();
   already_AddRefed<mozilla::DOMSVGPointList> AnimatedPoints();
 
 protected:
   SVGAnimatedPointList mPoints;
 };
--- a/dom/svg/test/bounds-helper.svg
+++ b/dom/svg/test/bounds-helper.svg
@@ -34,18 +34,10 @@ text { font: 20px monospace; }
     <rect id="rect4" x="150" y="50" width="50" height="50" fill="yellow"/>
     <rect id="rect4a" x="150" y="50" width="50" height="50" fill="none" stroke-width="4" stroke="blue"/>
   </g>
   <text id="text4" x="185" y="25"/>
   <g id="g2">
     <rect x="100" y="100" width="50" height="50" fill="pink"/>
     <text x="200" y="200"/>
   </g>
-  <circle id="nonScalingStrokedCircle1" cx="0" cy="0" r="10"
-          transform="translate(45 130) scale(3 -2)"
-          fill="none" stroke="gray" stroke-width="10"
-          vector-effect="non-scaling-stroke"/>
-  <ellipse id="nonScalingStrokedEllipse1" cx="20" cy="-10" rx="5" ry="5"
-           transform="matrix(0 3 -2 0 0 0)"
-           fill="none" stroke="steelblue" stroke-width="10"
-           vector-effect="non-scaling-stroke" />
 </g>
 </svg>
--- a/dom/svg/test/test_bounds.html
+++ b/dom/svg/test/test_bounds.html
@@ -154,20 +154,23 @@ function runTest()
   isWithAbsTolerance(rect2aBounds.width, rect.width, 0.1, "rect2a.getBoundingClientRect().width");
   isWithAbsTolerance(rect2aBounds.height, rect.height, 0.1, "rect2a.getBoundingClientRect().height");
 
   is(rect3aBounds.left, 46, "rect3a.getBoundingClientRect().left");
   is(rect3aBounds.top, 156, "rect3a.getBoundingClientRect().top");
   is(rect3aBounds.width, 108, "rect3a.getBoundingClientRect().width");
   is(rect3aBounds.height, 108, "rect3a.getBoundingClientRect().height");
 
-  isWithAbsTolerance(rect3bBounds.left, 198, 0.1, "rect3b.getBoundingClientRect().left");
-  isWithAbsTolerance(rect3bBounds.top, 198, 0.1, "rect3b.getBoundingClientRect().top");
-  isWithAbsTolerance(rect3bBounds.width, 54, 0.1, "rect3b.getBoundingClientRect().width");
-  isWithAbsTolerance(rect3bBounds.height, 54, 0.1, "rect3b.getBoundingClientRect().height");
+  // Our PathExtentsToMaxStrokeExtents implementation considers the stroke
+  // width to be sqrt(2)*stroke-width in case the rect is rotated 45 degrees,
+  // so unfortunately we get slightly large results currently. Bug 1092125.
+  isWithAbsTolerance(rect3bBounds.left, 198, 1, "rect3b.getBoundingClientRect().left");
+  isWithAbsTolerance(rect3bBounds.top, 198, 1, "rect3b.getBoundingClientRect().top");
+  isWithAbsTolerance(rect3bBounds.width, 54, 2, "rect3b.getBoundingClientRect().width");
+  isWithAbsTolerance(rect3bBounds.height, 54, 2, "rect3b.getBoundingClientRect().height");
 
   rect = new Rect(350 - 108 * sin45, 150 - 108 * sin45, 108 * sin45 * 2, 108 * sin45 * 2);
   isWithAbsTolerance(rect4aBounds.left, rect.left, 0.1, "rect4a.getBoundingClientRect().left");
   isWithAbsTolerance(rect4aBounds.top, rect.top, 0.1, "rect4a.getBoundingClientRect().top");
   isWithAbsTolerance(rect4aBounds.width, rect.width, 0.1, "rect4a.getBoundingClientRect().width");
   isWithAbsTolerance(rect4aBounds.height, rect.height, 0.1, "rect4a.getBoundingClientRect().height");
 
   var text1a = doc.getElementById("text1a");
@@ -195,38 +198,16 @@ function runTest()
   is(text4Bounds.height, 0, "text4.getBoundingClientRect().height");
 
   var gBounds = doc.getElementById("g2").getBoundingClientRect();
   is(gBounds.left, 100, "g2.getBoundingClientRect().left");
   is(gBounds.top, 100, "g2.getBoundingClientRect().top");
   is(gBounds.width, 50, "g2.getBoundingClientRect().width");
   is(gBounds.height, 50, "g2.getBoundingClientRect().height");
 
-  var nonScalingStrokedCircle1Bounds =
-    doc.getElementById("nonScalingStrokedCircle1").getBoundingClientRect();
-  isWithAbsTolerance(nonScalingStrokedCircle1Bounds.left, 10, 0.15,
-                     "nonScalingStrokedCircle1.getBoundingClientRect().left");
-  isWithAbsTolerance(nonScalingStrokedCircle1Bounds.top, 105, 0.15,
-                     "nonScalingStrokedCircle1.getBoundingClientRect().top");
-  isWithAbsTolerance(nonScalingStrokedCircle1Bounds.width, 70, 0.15,
-                     "nonScalingStrokedCircle1.getBoundingClientRect().width");
-  isWithAbsTolerance(nonScalingStrokedCircle1Bounds.height, 50, 0.15,
-                     "nonScalingStrokedCircle1.getBoundingClientRect().height");
-
-  var nonScalingStrokedEllipse1Bounds =
-    doc.getElementById("nonScalingStrokedEllipse1").getBoundingClientRect();
-  isWithAbsTolerance(nonScalingStrokedEllipse1Bounds.left, 5, 0.15,
-                     "nonScalingStrokedEllipse1.getBoundingClientRect().left");
-  isWithAbsTolerance(nonScalingStrokedEllipse1Bounds.top, 40, 0.15,
-                     "nonScalingStrokedEllipse1.getBoundingClientRect().top");
-  isWithAbsTolerance(nonScalingStrokedEllipse1Bounds.width, 30, 0.15,
-                     "nonScalingStrokedEllipse1.getBoundingClientRect().width");
-  isWithAbsTolerance(nonScalingStrokedEllipse1Bounds.height, 40, 0.15,
-                     "nonScalingStrokedEllipse1.getBoundingClientRect().height");
-
   SimpleTest.finish();
 }
 
 window.addEventListener("load", runTest, false);
 </script>
 </pre>
 </body>
 </html>
--- a/layout/svg/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/nsSVGPathGeometryFrame.cpp
@@ -465,46 +465,35 @@ nsSVGPathGeometryFrame::GetBBoxContribut
   bool getFill = (aFlags & nsSVGUtils::eBBoxIncludeFillGeometry) ||
                  ((aFlags & nsSVGUtils::eBBoxIncludeFill) &&
                   StyleSVG()->mFill.mType != eStyleSVGPaintType_None);
 
   bool getStroke = (aFlags & nsSVGUtils::eBBoxIncludeStrokeGeometry) ||
                    ((aFlags & nsSVGUtils::eBBoxIncludeStroke) &&
                     nsSVGUtils::HasStroke(this));
 
-  SVGContentUtils::AutoStrokeOptions strokeOptions;
-  if (getStroke) {
-    SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
-                                      StyleContext(), nullptr,
-                                      SVGContentUtils::eIgnoreStrokeDashing);
-  } else {
-    // Override the default line width of 1.f so that when we call
-    // GetGeometryBounds below the result doesn't include stroke bounds.
+  bool gotSimpleBounds = false;
+  if (!StyleSVGReset()->HasNonScalingStroke()) {
+    SVGContentUtils::AutoStrokeOptions strokeOptions;
     strokeOptions.mLineWidth = 0.f;
-  }
-
-  Rect simpleBounds;
-  bool gotSimpleBounds = false;
-  gfxMatrix userToOuterSVG;
-  if (getStroke &&
-      nsSVGUtils::GetNonScalingStrokeTransform(this, &userToOuterSVG)) {
-    Matrix moz2dUserToOuterSVG = ToMatrix(userToOuterSVG);
-    gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
-                                                 strokeOptions,
-                                                 aToBBoxUserspace,
-                                                 &moz2dUserToOuterSVG);
-  } else {
+    if (getStroke) {
+      SVGContentUtils::GetStrokeOptions(&strokeOptions, element,
+        StyleContext(), nullptr,
+        SVGContentUtils::eIgnoreStrokeDashing);
+    }
+    Rect simpleBounds;
     gotSimpleBounds = element->GetGeometryBounds(&simpleBounds,
                                                  strokeOptions,
                                                  aToBBoxUserspace);
+    if (gotSimpleBounds) {
+      bbox = simpleBounds;
+    }
   }
 
-  if (gotSimpleBounds) {
-    bbox = simpleBounds;
-  } else {
+  if (!gotSimpleBounds) {
     // Get the bounds using a Moz2D Path object (more expensive):
     RefPtr<DrawTarget> tmpDT;
 #ifdef XP_WIN
     // Unfortunately D2D backed DrawTarget produces bounds with rounding errors
     // when whole number results are expected, even in the case of trivial
     // calculations. To avoid that and meet the expectations of web content we
     // have to use a CAIRO DrawTarget. The most efficient way to do that is to
     // wrap the cached cairo_surface_t from ScreenReferenceSurface():