Bug 505115 - Part 9 - Implement the perspective() transform function and the perspective CSS property. r=dbaron

This commit is contained in:
Matt Woodrow 2011-08-03 15:04:22 +12:00
Родитель 85e14ced8b
Коммит 820000a6bf
14 изменённых файлов: 135 добавлений и 19 удалений

Просмотреть файл

@ -51,7 +51,7 @@
* http://www.w3.org/TR/DOM-Level-2-Style * http://www.w3.org/TR/DOM-Level-2-Style
*/ */
[scriptable, uuid(7cf11a5f-4be5-4e31-b427-58d82746b5f5)] [scriptable, uuid(1ca298f0-4eaf-4483-8aa2-587f392f84bb)]
interface nsIDOMCSS2Properties : nsISupports interface nsIDOMCSS2Properties : nsISupports
{ {
attribute DOMString background; attribute DOMString background;
@ -681,6 +681,9 @@ interface nsIDOMCSS2Properties : nsISupports
attribute DOMString MozTransformOrigin; attribute DOMString MozTransformOrigin;
// raises(DOMException) on setting // raises(DOMException) on setting
attribute DOMString MozPerspective;
// raises(DOMException) on setting
attribute DOMString MozWindowShadow; attribute DOMString MozWindowShadow;
// raises(DOMException) on setting // raises(DOMException) on setting

Просмотреть файл

@ -2376,12 +2376,27 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
/* Get the matrix, then change its basis to factor in the origin. */ /* Get the matrix, then change its basis to factor in the origin. */
PRBool dummy; PRBool dummy;
gfx3DMatrix result =
nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
aFrame->GetStyleContext(),
aFrame->PresContext(),
dummy, bounds, aFactor);
const nsStyleDisplay* parentDisp = nsnull;
if (aFrame->GetParent()) {
parentDisp = aFrame->GetParent()->GetStyleDisplay();
}
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;
}
return nsLayoutUtils::ChangeMatrixBasis return nsLayoutUtils::ChangeMatrixBasis
(newOrigin + toMozOrigin, (newOrigin + toMozOrigin, result);
nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
aFrame->GetStyleContext(),
aFrame->PresContext(),
dummy, bounds, aFactor));
} }
const gfx3DMatrix& const gfx3DMatrix&

Просмотреть файл

@ -367,6 +367,7 @@ CSS_KEY(padding-box, padding_box)
CSS_KEY(painted, painted) CSS_KEY(painted, painted)
CSS_KEY(paused, paused) CSS_KEY(paused, paused)
CSS_KEY(pc, pc) CSS_KEY(pc, pc)
CSS_KEY(perspective, perspective)
CSS_KEY(physical, physical) CSS_KEY(physical, physical)
CSS_KEY(pointer, pointer) CSS_KEY(pointer, pointer)
CSS_KEY(portrait, portrait) CSS_KEY(portrait, portrait)

Просмотреть файл

@ -121,6 +121,7 @@ namespace css = mozilla::css;
#define VARIANT_ZERO_ANGLE 0x02000000 // unitless zero for angles #define VARIANT_ZERO_ANGLE 0x02000000 // unitless zero for angles
#define VARIANT_CALC 0x04000000 // eCSSUnit_Calc #define VARIANT_CALC 0x04000000 // eCSSUnit_Calc
#define VARIANT_ELEMENT 0x08000000 // eCSSUnit_Element #define VARIANT_ELEMENT 0x08000000 // eCSSUnit_Element
#define VARIANT_POSITIVE_LENGTH 0x10000000 // Only lengths greater than 0.0
// Common combinations of variants // Common combinations of variants
#define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH) #define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH)
@ -4545,6 +4546,12 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
((aVariantMask & (VARIANT_LENGTH | VARIANT_ZERO_ANGLE)) != 0 && ((aVariantMask & (VARIANT_LENGTH | VARIANT_ZERO_ANGLE)) != 0 &&
eCSSToken_Number == tk->mType && eCSSToken_Number == tk->mType &&
tk->mNumber == 0.0f)) { tk->mNumber == 0.0f)) {
if ((aVariantMask & VARIANT_POSITIVE_LENGTH) != 0 &&
eCSSToken_Number == tk->mType &&
tk->mNumber <= 0.0) {
UngetToken();
return PR_FALSE;
}
if (TranslateDimension(aValue, aVariantMask, tk->mNumber, tk->mIdent)) { if (TranslateDimension(aValue, aVariantMask, tk->mNumber, tk->mIdent)) {
return PR_TRUE; return PR_TRUE;
} }
@ -7278,6 +7285,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
eAngle, eAngle,
eTwoAngles, eTwoAngles,
eNumber, eNumber,
ePositiveLength,
eTwoNumbers, eTwoNumbers,
eThreeNumbers, eThreeNumbers,
eThreeNumbersOneAngle, eThreeNumbersOneAngle,
@ -7293,6 +7301,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
{VARIANT_ANGLE_OR_ZERO}, {VARIANT_ANGLE_OR_ZERO},
{VARIANT_ANGLE_OR_ZERO, VARIANT_ANGLE_OR_ZERO}, {VARIANT_ANGLE_OR_ZERO, VARIANT_ANGLE_OR_ZERO},
{VARIANT_NUMBER}, {VARIANT_NUMBER},
{VARIANT_LENGTH|VARIANT_POSITIVE_LENGTH},
{VARIANT_NUMBER, VARIANT_NUMBER}, {VARIANT_NUMBER, VARIANT_NUMBER},
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER}, {VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER},
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_ANGLE_OR_ZERO}, {VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_ANGLE_OR_ZERO},
@ -7305,7 +7314,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
#ifdef DEBUG #ifdef DEBUG
static const PRUint8 kVariantMaskLengths[eNumVariantMasks] = static const PRUint8 kVariantMaskLengths[eNumVariantMasks] =
{1, 1, 2, 3, 1, 2, 1, 2, 3, 4, 6, 16}; {1, 1, 2, 3, 1, 2, 1, 1, 2, 3, 4, 6, 16};
#endif #endif
PRInt32 variantIndex = eNumVariantMasks; PRInt32 variantIndex = eNumVariantMasks;
@ -7409,6 +7418,13 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
aMaxElems = 16U; aMaxElems = 16U;
aIs3D = PR_TRUE; aIs3D = PR_TRUE;
break; break;
case eCSSKeyword_perspective:
/* Exactly one scale number. */
variantIndex = ePositiveLength;
aMinElems = 1U;
aMaxElems = 1U;
aIs3D = PR_TRUE;
break;
default: default:
/* Oh dear, we didn't match. Report an error. */ /* Oh dear, we didn't match. Report an error. */
return PR_FALSE; return PR_FALSE;

Просмотреть файл

@ -2258,6 +2258,15 @@ CSS_PROP_DISPLAY(
kBackgroundPositionKTable, kBackgroundPositionKTable,
CSS_PROP_NO_OFFSET, CSS_PROP_NO_OFFSET,
eStyleAnimType_Custom) eStyleAnimType_Custom)
CSS_PROP_DISPLAY(
-moz-perspective,
perspective,
CSS_PROP_DOMPROP_PREFIXED(Perspective),
CSS_PROPERTY_PARSE_VALUE,
VARIANT_NONE | VARIANT_INHERIT | VARIANT_LENGTH,
nsnull,
offsetof(nsStyleDisplay, mChildPerspective),
eStyleAnimType_Coord)
CSS_PROP_POSITION( CSS_PROP_POSITION(
top, top,
top, top,

Просмотреть файл

@ -941,6 +941,19 @@ nsComputedDOMStyle::DoGetMozTransformOrigin()
return valueList; return valueList;
} }
nsIDOMCSSValue*
nsComputedDOMStyle::DoGetMozPerspective()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
if (GetStyleDisplay()->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
GetStyleDisplay()->mChildPerspective.GetCoordValue() == 0.0) {
val->SetIdent(eCSSKeyword_none);
} else {
SetValueToCoord(val, GetStyleDisplay()->mChildPerspective, PR_FALSE);
}
return val;
}
/* If the property is "none", hand back "none" wrapped in a value. /* If the property is "none", hand back "none" wrapped in a value.
* Otherwise, compute the aggregate transform matrix and hands it back in a * Otherwise, compute the aggregate transform matrix and hands it back in a
* "matrix" wrapper. * "matrix" wrapper.
@ -4397,6 +4410,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength)
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_bottomRight,OutlineRadiusBottomRight), 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_topLeft, OutlineRadiusTopLeft),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topRight, OutlineRadiusTopRight), COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topRight, OutlineRadiusTopRight),
COMPUTED_STYLE_MAP_ENTRY(perspective, MozPerspective),
COMPUTED_STYLE_MAP_ENTRY(stack_sizing, StackSizing), COMPUTED_STYLE_MAP_ENTRY(stack_sizing, StackSizing),
COMPUTED_STYLE_MAP_ENTRY(_moz_tab_size, MozTabSize), COMPUTED_STYLE_MAP_ENTRY(_moz_tab_size, MozTabSize),
COMPUTED_STYLE_MAP_ENTRY(text_blink, MozTextBlink), COMPUTED_STYLE_MAP_ENTRY(text_blink, MozTextBlink),

Просмотреть файл

@ -347,6 +347,7 @@ private:
nsIDOMCSSValue* DoGetPageBreakBefore(); nsIDOMCSSValue* DoGetPageBreakBefore();
nsIDOMCSSValue* DoGetMozTransform(); nsIDOMCSSValue* DoGetMozTransform();
nsIDOMCSSValue* DoGetMozTransformOrigin(); nsIDOMCSSValue* DoGetMozTransformOrigin();
nsIDOMCSSValue* DoGetMozPerspective();
nsIDOMCSSValue* DoGetOrient(); nsIDOMCSSValue* DoGetOrient();
/* User interface properties */ /* User interface properties */

Просмотреть файл

@ -4484,6 +4484,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
NS_ASSERTION(result, "Malformed -moz-transform-origin parse!"); NS_ASSERTION(result, "Malformed -moz-transform-origin parse!");
} }
SetCoord(*aRuleData->ValueForPerspective(),
display->mChildPerspective, parentDisplay->mChildPerspective,
SETCOORD_LAH | SETCOORD_INITIAL_ZERO | SETCOORD_NONE,
aContext, mPresContext, canStoreInRuleTree);
// orient: enum, inherit, initial // orient: enum, inherit, initial
SetDiscrete(*aRuleData->ValueForOrient(), SetDiscrete(*aRuleData->ValueForOrient(),
display->mOrient, canStoreInRuleTree, display->mOrient, canStoreInRuleTree,

Просмотреть файл

@ -2033,6 +2033,7 @@ nsStyleDisplay::nsStyleDisplay()
mSpecifiedTransform = nsnull; mSpecifiedTransform = nsnull;
mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
mTransformOrigin[1].SetPercentValue(0.5f); mTransformOrigin[1].SetPercentValue(0.5f);
mChildPerspective.SetCoordValue(0);
mOrient = NS_STYLE_ORIENT_HORIZONTAL; mOrient = NS_STYLE_ORIENT_HORIZONTAL;
mTransitions.AppendElement(); mTransitions.AppendElement();
@ -2098,6 +2099,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
/* Copy over transform origin. */ /* Copy over transform origin. */
mTransformOrigin[0] = aSource.mTransformOrigin[0]; mTransformOrigin[0] = aSource.mTransformOrigin[0];
mTransformOrigin[1] = aSource.mTransformOrigin[1]; mTransformOrigin[1] = aSource.mTransformOrigin[1];
mChildPerspective = aSource.mChildPerspective;
} }
nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
@ -2159,6 +2161,10 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
nsChangeHint_RepaintFrame)); nsChangeHint_RepaintFrame));
break; break;
} }
if (mChildPerspective != aOther.mChildPerspective)
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame,
nsChangeHint_RepaintFrame));
} }
// Note: Our current behavior for handling changes to the // Note: Our current behavior for handling changes to the

Просмотреть файл

@ -1515,6 +1515,7 @@ struct nsStyleDisplay {
// null, as appropriate.) (owned by the style rule) // null, as appropriate.) (owned by the style rule)
const nsCSSValueList *mSpecifiedTransform; // [reset] const nsCSSValueList *mSpecifiedTransform; // [reset]
nsStyleCoord mTransformOrigin[2]; // [reset] percent, coord, calc nsStyleCoord mTransformOrigin[2]; // [reset] percent, coord, calc
nsStyleCoord mChildPerspective; // [reset] coord
nsAutoTArray<nsTransition, 1> mTransitions; // [reset] nsAutoTArray<nsTransition, 1> mTransitions; // [reset]
// The number of elements in mTransitions that are not from repeating // The number of elements in mTransitions that are not from repeating

Просмотреть файл

@ -607,6 +607,34 @@ nsStyleTransformMatrix::ProcessRotate3D(const nsCSSValue::Array* aData)
return temp; return temp;
} }
/* static */ gfx3DMatrix
nsStyleTransformMatrix::ProcessPerspective(const nsCSSValue::Array* aData,
nsStyleContext *aContext,
nsPresContext *aPresContext,
PRBool &aCanStoreInRuleTree,
float aAppUnitsPerMatrixUnit)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
/* We want our matrix to look like this:
* | 1 0 0 0 |
* | 0 1 0 0 |
* | 0 0 1 -1/depth |
* | 0 0 0 1 |
*/
gfx3DMatrix temp;
float depth;
ProcessTranslatePart(depth, aData->Item(1), aContext,
aPresContext, aCanStoreInRuleTree,
0, aAppUnitsPerMatrixUnit);
NS_ASSERTION(depth > 0.0, "Perspective must be positive!");
temp._34 = -1.0/depth;
return temp;
}
/** /**
* Return the transform function, as an nsCSSKeyword, for the given * Return the transform function, as an nsCSSKeyword, for the given
* nsCSSValue::Array from a transform list. * nsCSSValue::Array from a transform list.
@ -687,6 +715,9 @@ nsStyleTransformMatrix::MatrixForTransformFunction(const nsCSSValue::Array * aDa
case eCSSKeyword_interpolatematrix: case eCSSKeyword_interpolatematrix:
return ProcessInterpolateMatrix(aData, aContext, aPresContext, return ProcessInterpolateMatrix(aData, aContext, aPresContext,
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit); aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
case eCSSKeyword_perspective:
return ProcessPerspective(aData, aContext, aPresContext,
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
default: default:
NS_NOTREACHED("Unknown transform function!"); NS_NOTREACHED("Unknown transform function!");
} }

Просмотреть файл

@ -150,6 +150,11 @@ class nsStyleTransformMatrix
static gfx3DMatrix ProcessRotateY(const nsCSSValue::Array *aData); static gfx3DMatrix ProcessRotateY(const nsCSSValue::Array *aData);
static gfx3DMatrix ProcessRotateZ(const nsCSSValue::Array *aData); static gfx3DMatrix ProcessRotateZ(const nsCSSValue::Array *aData);
static gfx3DMatrix ProcessRotate3D(const nsCSSValue::Array *aData); static gfx3DMatrix ProcessRotate3D(const nsCSSValue::Array *aData);
static gfx3DMatrix ProcessPerspective(const nsCSSValue::Array *aData,
nsStyleContext *aContext,
nsPresContext *aPresContext,
PRBool &aCanStoreInRuleTree,
float aAppUnitsPerMatrixUnit);
}; };
#endif #endif

Просмотреть файл

@ -967,6 +967,14 @@ var gCSSProperties = {
"border", "center red", "right diagonal", "border", "center red", "right diagonal",
"#00ffff bottom"] "#00ffff bottom"]
}, },
"-moz-perspective": {
domProp: "MozPerspective",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "none", "0" ],
other_values: [ "1000px", "500.2px", "-100px", "-27.2em" ],
invalid_values: [ "pants", "200" ]
},
"-moz-user-focus": { "-moz-user-focus": {
domProp: "MozUserFocus", domProp: "MozUserFocus",
inherited: true, inherited: true,

Просмотреть файл

@ -191,6 +191,7 @@ var supported_properties = {
"padding-top": [ test_length_transition, test_percent_transition, "padding-top": [ test_length_transition, test_percent_transition,
test_length_percent_calc_transition, test_length_percent_calc_transition,
test_length_clamped, test_percent_clamped ], test_length_clamped, test_percent_clamped ],
"-moz-perspective": [ test_length_transition ],
"right": [ test_length_transition, test_percent_transition, "right": [ test_length_transition, test_percent_transition,
test_length_percent_calc_transition, test_length_percent_calc_transition,
test_length_unclamped, test_percent_unclamped ], test_length_unclamped, test_percent_unclamped ],