Bug 1335876 - Part 3. (Main) Setup basis of the matrix according to transform-box. draft
authorcku <cku@mozilla.com>
Tue, 07 Feb 2017 02:34:01 +0800
changeset 479444 ad73100be814036bada79a13fb9700dac2d7c8fd
parent 479443 256f1d361f6098f91b6bc560ba9dbc6053af377c
child 479445 6b4d5d762880b5f917533311e082a0236f0819d9
push id44261
push userbmo:cku@mozilla.com
push dateMon, 06 Feb 2017 18:35:30 +0000
bugs1335876
milestone54.0a1
Bug 1335876 - Part 3. (Main) Setup basis of the matrix according to transform-box. MozReview-Commit-ID: GDVraFTlPbQ
layout/painting/nsDisplayList.cpp
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6387,36 +6387,61 @@ nsDisplayTransform::GetResultingTransfor
     // This is a simplification of the following |else| block, the
     // simplification being possible because we don't need to apply
     // mToTransformOrigin between two transforms.
     result.ChangeBasis(aProperties.mToTransformOrigin);
   } else {
     Point3D refBoxOffset(NSAppUnitsToFloatPixels(refBox.X(), aAppUnitsPerPixel),
                          NSAppUnitsToFloatPixels(refBox.Y(), aAppUnitsPerPixel),
                          0);
+
     // We have both a transform and children-only transform. The
     // 'transform-origin' must apply between the two, so we need to apply it
     // now before we apply transformFromSVGParent. Since mToTransformOrigin is
     // relative to the frame's TopLeft(), we need to convert it to SVG user
     // space by subtracting refBoxOffset. (Then after applying
     // transformFromSVGParent we have to reapply refBoxOffset below.)
     result.ChangeBasis(aProperties.mToTransformOrigin - refBoxOffset);
 
     // Now apply the children-only transforms, converting the translation
     // components to device pixels:
     float pixelsPerCSSPx =
       frame->PresContext()->AppUnitsPerCSSPixel() / aAppUnitsPerPixel;
     transformFromSVGParent._31 *= pixelsPerCSSPx;
     transformFromSVGParent._32 *= pixelsPerCSSPx;
-    result = result * Matrix4x4::From2D(transformFromSVGParent);
-
-    // Similar to the code in the |if| block above, but since we've accounted
-    // for mToTransformOrigin so we don't include that. We also need to reapply
-    // refBoxOffset.
+
+    // There are two kinds of transforms that we will apply to 'frame':
+    // frame's owned transform(stores in result, denotes as TO) and a
+    // transform from 'frame''s parent(stores in transformFromSVGParent,
+    // denotes as TP).
+    //
+    // The origin of TP has nothing to do with transform-box, and should
+    // always be at the origin of user space.
+    // Depends on the value of transform-box, the origin of TO can be either
+    // located at the top-left corner of 'frame''s fill-box if transform-box is
+    // fill-box, or at the origin of user space if transform-box is
+    // view-box(or border-box, which will be fallback to view-box in SVG
+    // layout).
+    // So the final transform will look like
+    // 1. For fill-box:
+    //   TO.ChangeBasis(toFillBoxOffset) * TP.ChangeBasis(toUserSpaceOffset)
+    // 2. For view-box(or border-box):
+    //   TO.ChangeBasis(toUserSpaceOffset) * TP.ChangeBasis(toUserSpaceOffset)
     result.ChangeBasis(refBoxOffset);
+
+    Point3D frameOffset(
+      NSAppUnitsToFloatPixels(-frame->GetPosition().x, aAppUnitsPerPixel),
+      NSAppUnitsToFloatPixels(-frame->GetPosition().y, aAppUnitsPerPixel),
+      0);
+    Matrix4x4 transformFromParent =
+      Matrix4x4::From2D(transformFromSVGParent).ChangeBasis(frameOffset);
+
+    // Compose frame's owned transform with the transforom from parent
+    // (usually produced by viewbox scaling) as the resulting transform.
+    result *= transformFromParent;
   }
 
   if (hasPerspective) {
     result = result * perspectiveMatrix;
   }
 
   if ((aFlags & INCLUDE_PRESERVE3D_ANCESTORS) &&
       frame && frame->Combines3DTransformWithAncestors()) {