Backout changesets 37f9a5424227, c1578a4fc86d and a417424f9213 (for bugs 933354, 929021 and 923193 respectively) while we figure out performance regressions,a=bajaj
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 11 Nov 2013 15:23:56 +1300
changeset 166639 3e5824f3b572f5140f90deb238c61eef91fb7278
parent 166638 c72fa1fa0575999f1e458d62a3cf70d714134b76
child 166640 90c307e8c79ae5e6dc5684f3a7970257a7b4a519
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbajaj
bugs933354, 929021, 923193
milestone27.0a2
backs out37f9a54242270ba5a29fff2c4d4d36f9aaeda918
c1578a4fc86d3d85fd2166947d55c078cc72391e
a417424f9213c410910cbd85fd41d3ddb3162eed
Backout changesets 37f9a5424227, c1578a4fc86d and a417424f9213 (for bugs 933354, 929021 and 923193 respectively) while we figure out performance regressions,a=bajaj
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/reftests/transform/reftest.list
layout/reftests/transform/transform-origin-svg-1-ref.svg
layout/reftests/transform/transform-origin-svg-1a.svg
layout/reftests/transform/transform-origin-svg-1b.svg
layout/reftests/transform/transform-origin-svg-2-ref.svg
layout/reftests/transform/transform-origin-svg-2a.svg
layout/reftests/transform/transform-origin-svg-2b.svg
layout/svg/nsSVGTextFrame2.cpp
layout/svg/svg.css
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3827,37 +3827,35 @@ bool nsDisplayZoom::ComputeVisibility(ns
 #ifndef UNIFIED_CONTINUATIONS
 
 nsRect
 nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "Can't get the bounds of a nonexistent frame!");
 
   if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
-    gfxRect bbox = nsSVGUtils::GetBBox(const_cast<nsIFrame*>(aFrame));
-    return nsLayoutUtils::RoundGfxRectToAppRect(bbox,
-      aFrame->PresContext()->AppUnitsPerCSSPixel()) - aFrame->GetPosition();
+    // TODO: SVG needs to define what percentage translations resolve against.
+    return nsRect();
   }
 
   return nsRect(nsPoint(0, 0), aFrame->GetSize());
 }
 
 #else
 
 nsRect
 nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "Can't get the bounds of a nonexistent frame!");
 
   nsRect result;
 
   if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
-    gfxRect bbox = nsSVGUtils::GetBBox(const_cast<nsIFrame*>(aFrame));
-    return nsLayoutUtils::RoundGfxRectToAppRect(bbox,
-      aFrame->PresContext()->AppUnitsPerCSSPixel()) - aFrame->GetPosition();
+    // TODO: SVG needs to define what percentage translations resolve against.
+    return result;
   }
 
   /* Iterate through the continuation list, unioning together all the
    * bounding rects.
    */
   for (const nsIFrame *currFrame = aFrame->FirstContinuation();
        currFrame != nullptr;
        currFrame = currFrame->GetNextContinuation())
@@ -3917,66 +3915,61 @@ nsDisplayTransform::GetDeltaToTransformO
   NS_PRECONDITION(aFrame->IsTransformed(),
                   "Shouldn't get a delta for an untransformed frame!");
 
   /* For both of the coordinates, if the value of -moz-transform is a
    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    * a distance, it's already computed for us!
    */
   const nsStyleDisplay* display = aFrame->StyleDisplay();
-  nsRect boundingRect;
-  if (aBoundsOverride) {
-    boundingRect = *aBoundsOverride;
-  } else if (display->mTransformOrigin[0].GetUnit() != eStyleUnit_Coord ||
-             display->mTransformOrigin[1].GetUnit() != eStyleUnit_Coord) {
-    // GetFrameBoundsForTransform is expensive for SVG frames and we don't need
-    // it if the origin is coords (which it is by default for SVG).
-    boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(aFrame);
-  }
+  nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
+                         nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
 
   /* Allows us to access named variables by index. */
-  float coords[2];
-  nscoord boundingOffsets[2] = {boundingRect.x, boundingRect.y};
-  nscoord boundingDimensions[2] = {boundingRect.width, boundingRect.height};
-  nscoord frameOffsets[2] = {aFrame->GetPosition().x, aFrame->GetPosition().y};
+  float coords[3];
+  const nscoord* dimensions[2] =
+    {&boundingRect.width, &boundingRect.height};
 
   for (uint8_t index = 0; index < 2; ++index) {
     /* If the -moz-transform-origin specifies a percentage, take the percentage
      * of the size of the box.
      */
     const nsStyleCoord &coord = display->mTransformOrigin[index];
-    if (coord.GetUnit() == eStyleUnit_Percent) {
+    if (coord.GetUnit() == eStyleUnit_Calc) {
+      const nsStyleCoord::Calc *calc = coord.GetCalcValue();
       coords[index] =
-        NSAppUnitsToFloatPixels(boundingDimensions[index], aAppUnitsPerPixel) *
-          coord.GetPercentValue() +
-        NSAppUnitsToFloatPixels(boundingOffsets[index], aAppUnitsPerPixel);
+        NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
+          calc->mPercent +
+        NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
+    } else if (coord.GetUnit() == eStyleUnit_Percent) {
+      coords[index] =
+        NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
+        coord.GetPercentValue();
     } else {
-      if (coord.GetUnit() == eStyleUnit_Calc) {
-        const nsStyleCoord::Calc *calc = coord.GetCalcValue();
-        coords[index] =
-          NSAppUnitsToFloatPixels(boundingDimensions[index], aAppUnitsPerPixel) *
-            calc->mPercent +
-          NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
-      } else {
-        NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
-        coords[index] =
-          NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
-      }
-      if (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) {
-        // <length> values represent offsets from the origin of the SVG element's
-        // user space, not the top left of its border-box, so we must
-        // convert them to be relative to the border-box.
-        coords[index] -= NSAppUnitsToFloatPixels(frameOffsets[index], aAppUnitsPerPixel);
-      }
+      NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
+      coords[index] =
+        NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
     }
-  }
-
-  return gfxPoint3D(coords[0], coords[1],
-                    NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
-                                            aAppUnitsPerPixel));
+    if ((aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+        coord.GetUnit() != eStyleUnit_Percent) {
+      // <length> values represent offsets from the origin of the SVG element's
+      // user space, not the top left of its bounds, so we must adjust for that:
+      nscoord offset =
+        (index == 0) ? aFrame->GetPosition().x : aFrame->GetPosition().y;
+      coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel);
+    }
+  }
+
+  coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
+                                      aAppUnitsPerPixel);
+  /* Adjust based on the origin of the rectangle. */
+  coords[0] += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
+  coords[1] += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
+
+  return gfxPoint3D(coords[0], coords[1], coords[2]);
 }
 
 /* Returns the delta specified by the -moz-perspective-origin property.
  * This is a positive delta, meaning that it indicates the direction to move
  * to get from (0, 0) of the frame to the perspective origin. This function is
  * called off the main thread.
  */
 /* static */ gfxPoint3D
@@ -4040,28 +4033,26 @@ nsDisplayTransform::GetDeltaToPerspectiv
 }
 
 nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame,
                                                                        float aAppUnitsPerPixel,
                                                                        const nsRect* aBoundsOverride)
   : mFrame(aFrame)
   , mTransformList(aFrame->StyleDisplay()->mSpecifiedTransform)
   , mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
+  , mToPerspectiveOrigin(GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel))
   , mChildPerspective(0)
 {
   const nsStyleDisplay* parentDisp = nullptr;
   nsStyleContext* parentStyleContext = aFrame->StyleContext()->GetParent();
   if (parentStyleContext) {
     parentDisp = parentStyleContext->StyleDisplay();
   }
   if (parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord) {
     mChildPerspective = parentDisp->mChildPerspective.GetCoordValue();
-    if (mChildPerspective > 0.0) {
-      mToPerspectiveOrigin = GetDeltaToPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
-    }
   }
 }
 
 /* Wraps up the -moz-transform matrix in a change-of-basis matrix pair that
  * translates from local coordinate space to transform coordinate space, then
  * hands it back.
  */
 gfx3DMatrix
@@ -4151,17 +4142,17 @@ nsDisplayTransform::GetResultingTransfor
 
   if (aProperties.mChildPerspective > 0.0) {
     gfx3DMatrix perspective;
     perspective._34 =
       -1.0 / NSAppUnitsToFloatPixels(aProperties.mChildPerspective, aAppUnitsPerPixel);
     /* At the point when perspective is applied, we have been translated to the transform origin.
      * The translation to the perspective origin is the difference between these values.
      */
-    result = result * nsLayoutUtils::ChangeMatrixBasis(aProperties.GetToPerspectiveOrigin() - aProperties.mToTransformOrigin, perspective);
+    result = result * nsLayoutUtils::ChangeMatrixBasis(aProperties.mToPerspectiveOrigin - aProperties.mToTransformOrigin, perspective);
   }
 
   gfxPoint3D rounded(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x),
                      hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y),
                      0);
 
   if (frame && frame->Preserves3D()) {
       // Include the transform set on our parent
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -3037,34 +3037,25 @@ public:
                              const nsRect* aBoundsOverride);
     FrameTransformProperties(const nsCSSValueList* aTransformList,
                              const gfxPoint3D& aToTransformOrigin,
                              const gfxPoint3D& aToPerspectiveOrigin,
                              nscoord aChildPerspective)
       : mFrame(nullptr)
       , mTransformList(aTransformList)
       , mToTransformOrigin(aToTransformOrigin)
+      , mToPerspectiveOrigin(aToPerspectiveOrigin)
       , mChildPerspective(aChildPerspective)
-      , mToPerspectiveOrigin(aToPerspectiveOrigin)
     {}
 
     const nsIFrame* mFrame;
     const nsCSSValueList* mTransformList;
     const gfxPoint3D mToTransformOrigin;
+    const gfxPoint3D mToPerspectiveOrigin;
     nscoord mChildPerspective;
-
-    const gfxPoint3D& GetToPerspectiveOrigin() const
-    {
-      NS_ASSERTION(mChildPerspective > 0, "Only valid with mChildPerspective > 0");
-      return mToPerspectiveOrigin;
-    }
-
-  private:
-    // mToPerspectiveOrigin is only valid if mChildPerspective > 0.
-    gfxPoint3D mToPerspectiveOrigin;
   };
 
   /**
    * Given a frame with the -moz-transform property or an SVG transform,
    * returns the transformation matrix for that frame.
    *
    * @param aFrame The frame to get the matrix from.
    * @param aOrigin Relative to which point this transform should be applied.
--- a/layout/reftests/transform/reftest.list
+++ b/layout/reftests/transform/reftest.list
@@ -119,12 +119,8 @@ skip-if(B2G) fails-if(Android) fuzzy-if(
 # Bug 722777
 == table-1a.html table-1-ref.html
 == table-1b.html table-1-ref.html
 == table-1c.html table-1-ref.html
 == table-2a.html table-2-ref.html
 == table-2b.html table-2-ref.html
 # Bug 722463
 == inline-1a.html inline-1-ref.html
-== transform-origin-svg-1a.svg transform-origin-svg-1-ref.svg
-== transform-origin-svg-1b.svg transform-origin-svg-1-ref.svg
-== transform-origin-svg-2a.svg transform-origin-svg-2-ref.svg
-== transform-origin-svg-2b.svg transform-origin-svg-2-ref.svg
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-1-ref.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<rect x='40' y='140' width='100' height='100' fill='lime'/>
-</svg>
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-1a.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<g transform="translate(30,30)">
-  <rect x='10' y='10' width='100' height='100' fill='lime'
-        style="transform:rotate(90deg); transform-origin:left bottom;"/>
-</g>
-</svg>
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-1b.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<g transform="translate(30,30)">
-  <rect x='10' y='10' width='100' height='100' fill='lime'
-        style="transform:rotate(90deg); transform-origin:10px 110px;
-               -webkit-transform:rotate(90deg); -webkit-transform-origin:10px 110px;"/>
-</g>
-</svg>
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-2-ref.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<rect x='40' y='140' width='100' height='100' fill='lime' stroke-width='20' stroke='blue'/>
-</svg>
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-2a.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<g transform="translate(30,30)">
-  <rect x='10' y='10' width='100' height='100' fill='lime' stroke-width='20' stroke='blue'
-        style="transform:rotate(90deg); transform-origin:left bottom;"/>
-</g>
-</svg>
deleted file mode 100644
--- a/layout/reftests/transform/transform-origin-svg-2b.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg xmlns='http://www.w3.org/2000/svg'>
-<g transform="translate(30,30)">
-  <rect x='10' y='10' width='100' height='100' fill='lime' stroke-width='20' stroke='blue'
-        style="transform:rotate(90deg); transform-origin:10px 110px;
-               -webkit-transform:rotate(90deg); -webkit-transform-origin:10px 110px;"/>
-</g>
-</svg>
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -3760,26 +3760,24 @@ nsSVGTextFrame2::ReflowSVG()
 
   if (mState & NS_FRAME_FIRST_REFLOW) {
     // Make sure we have our filter property (if any) before calling
     // FinishAndStoreOverflow (subsequent filter changes are handled off
     // nsChangeHint_UpdateEffects):
     nsSVGEffects::UpdateEffects(this);
   }
 
-  // Now unset the various reflow bits. Do this before calling
-  // FinishAndStoreOverflow since FinishAndStoreOverflow can require glyph
-  // positions (to resolve transform-origin).
-  mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
-              NS_FRAME_HAS_DIRTY_CHILDREN);
-
   nsRect overflow = nsRect(nsPoint(0,0), mRect.Size());
   nsOverflowAreas overflowAreas(overflow, overflow);
   FinishAndStoreOverflow(overflowAreas, mRect.Size());
 
+  // Now unset the various reflow bits:
+  mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
+              NS_FRAME_HAS_DIRTY_CHILDREN);
+
   // XXX nsSVGContainerFrame::ReflowSVG only looks at its nsISVGChildFrame
   // children, and calls ConsiderChildOverflow on them.  Does it matter
   // that ConsiderChildOverflow won't be called on our children?
   nsSVGTextFrame2Base::ReflowSVG();
 }
 
 /**
  * Converts nsSVGUtils::eBBox* flags into TextRenderedRun flags appropriate
--- a/layout/svg/svg.css
+++ b/layout/svg/svg.css
@@ -46,17 +46,17 @@ foreignObject {
 
 *|*::-moz-svg-foreign-content {
   display: block !important;
   /* We need to be an absolute and fixed container */
   transform: translate(0) !important;
   text-indent: 0;
 }
 
-/* Set |transform-origin:0 0;| for all SVG elements except outer-<svg>,
+/* Set |transform-origin:0% 0%;| for all SVG elements except outer-<svg>,
    noting that 'svg' as a child of 'foreignObject' counts as outer-<svg>.
 */
 *:not(svg),
 *:not(foreignObject) > svg {
   transform-origin:0 0;
 }
 
 *|*::-moz-svg-text {