mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 505115 - Part 9 - Implement the perspective() transform function and the perspective CSS property. r=dbaron
This commit is contained in:
parent
d9e573335e
commit
b4bfd8dd6a
@ -51,7 +51,7 @@
|
||||
* 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
|
||||
{
|
||||
attribute DOMString background;
|
||||
@ -681,6 +681,9 @@ interface nsIDOMCSS2Properties : nsISupports
|
||||
attribute DOMString MozTransformOrigin;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString MozPerspective;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
attribute DOMString MozWindowShadow;
|
||||
// raises(DOMException) on setting
|
||||
|
||||
|
@ -2376,24 +2376,39 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
|
||||
|
||||
/* Get the matrix, then change its basis to factor in the origin. */
|
||||
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
|
||||
(newOrigin + toMozOrigin,
|
||||
nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
|
||||
aFrame->GetStyleContext(),
|
||||
aFrame->PresContext(),
|
||||
dummy, bounds, aFactor));
|
||||
}
|
||||
|
||||
const gfx3DMatrix&
|
||||
nsDisplayTransform::GetTransform(float aFactor)
|
||||
{
|
||||
if (mTransform.IsIdentity() || mCachedFactor != aFactor) {
|
||||
mTransform =
|
||||
GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
|
||||
aFactor,
|
||||
nsnull);
|
||||
mCachedFactor = aFactor;
|
||||
}
|
||||
(newOrigin + toMozOrigin, result);
|
||||
}
|
||||
|
||||
const gfx3DMatrix&
|
||||
nsDisplayTransform::GetTransform(float aFactor)
|
||||
{
|
||||
if (mTransform.IsIdentity() || mCachedFactor != aFactor) {
|
||||
mTransform =
|
||||
GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
|
||||
aFactor,
|
||||
nsnull);
|
||||
mCachedFactor = aFactor;
|
||||
}
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
|
@ -367,6 +367,7 @@ CSS_KEY(padding-box, padding_box)
|
||||
CSS_KEY(painted, painted)
|
||||
CSS_KEY(paused, paused)
|
||||
CSS_KEY(pc, pc)
|
||||
CSS_KEY(perspective, perspective)
|
||||
CSS_KEY(physical, physical)
|
||||
CSS_KEY(pointer, pointer)
|
||||
CSS_KEY(portrait, portrait)
|
||||
|
@ -121,6 +121,7 @@ namespace css = mozilla::css;
|
||||
#define VARIANT_ZERO_ANGLE 0x02000000 // unitless zero for angles
|
||||
#define VARIANT_CALC 0x04000000 // eCSSUnit_Calc
|
||||
#define VARIANT_ELEMENT 0x08000000 // eCSSUnit_Element
|
||||
#define VARIANT_POSITIVE_LENGTH 0x10000000 // Only lengths greater than 0.0
|
||||
|
||||
// Common combinations of variants
|
||||
#define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH)
|
||||
@ -4545,6 +4546,12 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
||||
((aVariantMask & (VARIANT_LENGTH | VARIANT_ZERO_ANGLE)) != 0 &&
|
||||
eCSSToken_Number == tk->mType &&
|
||||
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)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -7278,6 +7285,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
||||
eAngle,
|
||||
eTwoAngles,
|
||||
eNumber,
|
||||
ePositiveLength,
|
||||
eTwoNumbers,
|
||||
eThreeNumbers,
|
||||
eThreeNumbersOneAngle,
|
||||
@ -7293,6 +7301,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
||||
{VARIANT_ANGLE_OR_ZERO},
|
||||
{VARIANT_ANGLE_OR_ZERO, VARIANT_ANGLE_OR_ZERO},
|
||||
{VARIANT_NUMBER},
|
||||
{VARIANT_LENGTH|VARIANT_POSITIVE_LENGTH},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER},
|
||||
{VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_NUMBER, VARIANT_ANGLE_OR_ZERO},
|
||||
@ -7305,7 +7314,7 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
||||
|
||||
#ifdef DEBUG
|
||||
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
|
||||
|
||||
PRInt32 variantIndex = eNumVariantMasks;
|
||||
@ -7409,6 +7418,13 @@ static PRBool GetFunctionParseInformation(nsCSSKeyword aToken,
|
||||
aMaxElems = 16U;
|
||||
aIs3D = PR_TRUE;
|
||||
break;
|
||||
case eCSSKeyword_perspective:
|
||||
/* Exactly one scale number. */
|
||||
variantIndex = ePositiveLength;
|
||||
aMinElems = 1U;
|
||||
aMaxElems = 1U;
|
||||
aIs3D = PR_TRUE;
|
||||
break;
|
||||
default:
|
||||
/* Oh dear, we didn't match. Report an error. */
|
||||
return PR_FALSE;
|
||||
|
@ -2258,6 +2258,15 @@ CSS_PROP_DISPLAY(
|
||||
kBackgroundPositionKTable,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
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(
|
||||
top,
|
||||
top,
|
||||
|
@ -941,6 +941,19 @@ nsComputedDOMStyle::DoGetMozTransformOrigin()
|
||||
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.
|
||||
* Otherwise, compute the aggregate transform matrix and hands it back in a
|
||||
* "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_topLeft, OutlineRadiusTopLeft),
|
||||
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(_moz_tab_size, MozTabSize),
|
||||
COMPUTED_STYLE_MAP_ENTRY(text_blink, MozTextBlink),
|
||||
|
@ -347,6 +347,7 @@ private:
|
||||
nsIDOMCSSValue* DoGetPageBreakBefore();
|
||||
nsIDOMCSSValue* DoGetMozTransform();
|
||||
nsIDOMCSSValue* DoGetMozTransformOrigin();
|
||||
nsIDOMCSSValue* DoGetMozPerspective();
|
||||
nsIDOMCSSValue* DoGetOrient();
|
||||
|
||||
/* User interface properties */
|
||||
|
@ -4484,6 +4484,11 @@ nsRuleNode::ComputeDisplayData(void* aStartStruct,
|
||||
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
|
||||
SetDiscrete(*aRuleData->ValueForOrient(),
|
||||
display->mOrient, canStoreInRuleTree,
|
||||
|
@ -2033,6 +2033,7 @@ nsStyleDisplay::nsStyleDisplay()
|
||||
mSpecifiedTransform = nsnull;
|
||||
mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
|
||||
mTransformOrigin[1].SetPercentValue(0.5f);
|
||||
mChildPerspective.SetCoordValue(0);
|
||||
mOrient = NS_STYLE_ORIENT_HORIZONTAL;
|
||||
|
||||
mTransitions.AppendElement();
|
||||
@ -2098,6 +2099,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
|
||||
/* Copy over transform origin. */
|
||||
mTransformOrigin[0] = aSource.mTransformOrigin[0];
|
||||
mTransformOrigin[1] = aSource.mTransformOrigin[1];
|
||||
mChildPerspective = aSource.mChildPerspective;
|
||||
}
|
||||
|
||||
nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|
||||
@ -2159,6 +2161,10 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|
||||
nsChangeHint_RepaintFrame));
|
||||
break;
|
||||
}
|
||||
|
||||
if (mChildPerspective != aOther.mChildPerspective)
|
||||
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame,
|
||||
nsChangeHint_RepaintFrame));
|
||||
}
|
||||
|
||||
// Note: Our current behavior for handling changes to the
|
||||
|
@ -1515,6 +1515,7 @@ struct nsStyleDisplay {
|
||||
// null, as appropriate.) (owned by the style rule)
|
||||
const nsCSSValueList *mSpecifiedTransform; // [reset]
|
||||
nsStyleCoord mTransformOrigin[2]; // [reset] percent, coord, calc
|
||||
nsStyleCoord mChildPerspective; // [reset] coord
|
||||
|
||||
nsAutoTArray<nsTransition, 1> mTransitions; // [reset]
|
||||
// The number of elements in mTransitions that are not from repeating
|
||||
|
@ -607,6 +607,34 @@ nsStyleTransformMatrix::ProcessRotate3D(const nsCSSValue::Array* aData)
|
||||
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
|
||||
* nsCSSValue::Array from a transform list.
|
||||
@ -687,6 +715,9 @@ nsStyleTransformMatrix::MatrixForTransformFunction(const nsCSSValue::Array * aDa
|
||||
case eCSSKeyword_interpolatematrix:
|
||||
return ProcessInterpolateMatrix(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
|
||||
case eCSSKeyword_perspective:
|
||||
return ProcessPerspective(aData, aContext, aPresContext,
|
||||
aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
|
||||
default:
|
||||
NS_NOTREACHED("Unknown transform function!");
|
||||
}
|
||||
|
@ -150,6 +150,11 @@ class nsStyleTransformMatrix
|
||||
static gfx3DMatrix ProcessRotateY(const nsCSSValue::Array *aData);
|
||||
static gfx3DMatrix ProcessRotateZ(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
|
||||
|
@ -967,6 +967,14 @@ var gCSSProperties = {
|
||||
"border", "center red", "right diagonal",
|
||||
"#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": {
|
||||
domProp: "MozUserFocus",
|
||||
inherited: true,
|
||||
|
@ -191,6 +191,7 @@ var supported_properties = {
|
||||
"padding-top": [ test_length_transition, test_percent_transition,
|
||||
test_length_percent_calc_transition,
|
||||
test_length_clamped, test_percent_clamped ],
|
||||
"-moz-perspective": [ test_length_transition ],
|
||||
"right": [ test_length_transition, test_percent_transition,
|
||||
test_length_percent_calc_transition,
|
||||
test_length_unclamped, test_percent_unclamped ],
|
||||
|
Loading…
Reference in New Issue
Block a user