Bug 505115 - Part 12b - Layout changes to use -moz-perspective-origin. r=roc
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2343,16 +2343,76 @@ gfxPoint3D GetDeltaToMozTransformOrigin(
/* Adjust based on the origin of the rectangle. */
result.x += NSAppUnitsToFloatPixels(boundingRect.x, aFactor);
result.y += NSAppUnitsToFloatPixels(boundingRect.y, aFactor);
return result;
}
+/* 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.
+ */
+static
+gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
+ float aFactor,
+ const nsRect* aBoundsOverride)
+{
+ NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
+ NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
+ "Can't get a delta for an untransformed frame!");
+
+ /* For both of the coordinates, if the value of -moz-perspective-origin is a
+ * percentage, it's relative to the size of the frame. Otherwise, if it's
+ * a distance, it's already computed for us!
+ */
+
+ //TODO: Should this be using our bounds or the parent's bounds?
+ // How do we handle aBoundsOverride in the latter case?
+ const nsStyleDisplay* display = aFrame->GetParent()->GetStyleDisplay();
+ nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
+ nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
+
+ /* Allows us to access named variables by index. */
+ gfxPoint3D result;
+ result.z = 0.0f;
+ gfxFloat* coords[2] = {&result.x, &result.y};
+ const nscoord* dimensions[2] =
+ {&boundingRect.width, &boundingRect.height};
+
+ for (PRUint8 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->mPerspectiveOrigin[index];
+ if (coord.GetUnit() == eStyleUnit_Calc) {
+ const nsStyleCoord::Calc *calc = coord.GetCalcValue();
+ *coords[index] = NSAppUnitsToFloatPixels(*dimensions[index], aFactor) *
+ calc->mPercent +
+ NSAppUnitsToFloatPixels(calc->mLength, aFactor);
+ } else if (coord.GetUnit() == eStyleUnit_Percent) {
+ *coords[index] = NSAppUnitsToFloatPixels(*dimensions[index], aFactor) *
+ coord.GetPercentValue();
+ } else {
+ NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
+ *coords[index] = NSAppUnitsToFloatPixels(coord.GetCoordValue(), aFactor);
+ }
+ }
+
+ /**
+ * An offset of (0,0) results in the perspective-origin being at the centre of the element,
+ * so include a shift of the centre point to (0,0).
+ */
+ result.x -= NSAppUnitsToFloatPixels(boundingRect.width, aFactor)/2;
+ result.y -= NSAppUnitsToFloatPixels(boundingRect.height, aFactor)/2;
+
+ return result;
+}
+
/* 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
nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
const nsPoint &aOrigin,
float aFactor,
@@ -2361,16 +2421,17 @@ nsDisplayTransform::GetResultingTransfor
NS_PRECONDITION(aFrame, "Cannot get transform matrix for a null frame!");
NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
"Cannot get transform matrix if frame isn't transformed!");
/* Account for the -moz-transform-origin property by translating the
* coordinate space to the new origin.
*/
gfxPoint3D toMozOrigin = GetDeltaToMozTransformOrigin(aFrame, aFactor, aBoundsOverride);
+ gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aFactor, aBoundsOverride);
gfxPoint3D newOrigin = gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aFactor),
NSAppUnitsToFloatPixels(aOrigin.y, aFactor),
0.0f);
/* Get the underlying transform matrix. This requires us to get the
* bounds of the frame.
*/
const nsStyleDisplay* disp = aFrame->GetStyleDisplay();
@@ -2391,17 +2452,17 @@ nsDisplayTransform::GetResultingTransfor
}
if (nsLayoutUtils::Are3DTransformsEnabled() &&
parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
gfx3DMatrix perspective;
perspective._34 =
-1.0 / NSAppUnitsToFloatPixels(parentDisp->mChildPerspective.GetCoordValue(),
aFactor);
- result = result * perspective;
+ result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin, perspective);
}
return nsLayoutUtils::ChangeMatrixBasis
(newOrigin + toMozOrigin, result);
}
const gfx3DMatrix&
nsDisplayTransform::GetTransform(float aFactor)
{
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4454,16 +4454,17 @@ nsComputedDOMStyle::GetQueryableProperty
COMPUTED_STYLE_MAP_ENTRY(hyphens, Hyphens),
COMPUTED_STYLE_MAP_ENTRY(image_region, ImageRegion),
COMPUTED_STYLE_MAP_ENTRY(orient, Orient),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_bottomLeft, OutlineRadiusBottomLeft),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_bottomRight,OutlineRadiusBottomRight),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topLeft, OutlineRadiusTopLeft),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topRight, OutlineRadiusTopRight),
COMPUTED_STYLE_MAP_ENTRY(perspective, MozPerspective),
+ COMPUTED_STYLE_MAP_ENTRY_LAYOUT(perspective_origin, MozPerspectiveOrigin),
COMPUTED_STYLE_MAP_ENTRY(stack_sizing, StackSizing),
COMPUTED_STYLE_MAP_ENTRY(_moz_tab_size, MozTabSize),
COMPUTED_STYLE_MAP_ENTRY(text_blink, MozTextBlink),
COMPUTED_STYLE_MAP_ENTRY(text_decoration_color, MozTextDecorationColor),
COMPUTED_STYLE_MAP_ENTRY(text_decoration_line, MozTextDecorationLine),
COMPUTED_STYLE_MAP_ENTRY(text_decoration_style, MozTextDecorationStyle),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_transform, MozTransform),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_transform_origin, MozTransformOrigin),