mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Add support for animation of nsRect values. (Bug 520488) r=bzbarsky
This commit is contained in:
parent
544fa1d874
commit
4cb8a38d3f
@ -1190,8 +1190,8 @@ CSS_PROP_DISPLAY(
|
||||
mClip,
|
||||
eCSSType_Rect,
|
||||
nsnull,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_None)
|
||||
offsetof(nsStyleDisplay, mClip),
|
||||
eStyleAnimType_Custom)
|
||||
CSS_PROP_COLOR(
|
||||
color,
|
||||
color,
|
||||
@ -1523,8 +1523,8 @@ CSS_PROP_LIST(
|
||||
mImageRegion,
|
||||
eCSSType_Rect,
|
||||
nsnull,
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_None)
|
||||
offsetof(nsStyleList, mImageRegion),
|
||||
eStyleAnimType_Custom)
|
||||
CSS_PROP_UIRESET(
|
||||
ime-mode,
|
||||
ime_mode,
|
||||
|
@ -244,6 +244,42 @@ nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty,
|
||||
aDistance = sqrt(squareDistance);
|
||||
break;
|
||||
}
|
||||
case eUnit_CSSRect: {
|
||||
const nsCSSRect *rect1 = aStartValue.GetCSSRectValue();
|
||||
const nsCSSRect *rect2 = aEndValue.GetCSSRectValue();
|
||||
if (rect1->mTop.GetUnit() != rect2->mTop.GetUnit() ||
|
||||
rect1->mRight.GetUnit() != rect2->mRight.GetUnit() ||
|
||||
rect1->mBottom.GetUnit() != rect2->mBottom.GetUnit() ||
|
||||
rect1->mLeft.GetUnit() != rect2->mLeft.GetUnit()) {
|
||||
// At least until we have calc()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
double squareDistance = 0.0;
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(nsCSSRect::sides); ++i) {
|
||||
nsCSSValue nsCSSRect::*member = nsCSSRect::sides[i];
|
||||
NS_ABORT_IF_FALSE((rect1->*member).GetUnit() ==
|
||||
(rect2->*member).GetUnit(),
|
||||
"should have returned above");
|
||||
double diff;
|
||||
switch ((rect1->*member).GetUnit()) {
|
||||
case eCSSUnit_Pixel:
|
||||
diff = (rect1->*member).GetFloatValue() -
|
||||
(rect2->*member).GetFloatValue();
|
||||
break;
|
||||
case eCSSUnit_Auto:
|
||||
diff = 0;
|
||||
break;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected unit");
|
||||
return PR_FALSE;
|
||||
}
|
||||
squareDistance += diff * diff;
|
||||
}
|
||||
|
||||
aDistance = sqrt(squareDistance);
|
||||
break;
|
||||
}
|
||||
case eUnit_Dasharray: {
|
||||
// NOTE: This produces results on substantially different scales
|
||||
// for length values and percentage values, which might even be
|
||||
@ -366,6 +402,13 @@ nsStyleAnimation::ComputeDistance(nsCSSProperty aProperty,
|
||||
return success;
|
||||
}
|
||||
|
||||
inline void
|
||||
nscoordToCSSValue(nscoord aCoord, nsCSSValue& aCSSValue)
|
||||
{
|
||||
aCSSValue.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aCoord),
|
||||
eCSSUnit_Pixel);
|
||||
}
|
||||
|
||||
#define MAX_PACKED_COLOR_COMPONENT 255
|
||||
|
||||
inline PRUint8 ClampColor(double aColor)
|
||||
@ -586,6 +629,50 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
||||
eUnit_CSSValuePair);
|
||||
break;
|
||||
}
|
||||
case eUnit_CSSRect: {
|
||||
const nsCSSRect *rect1 = aValue1.GetCSSRectValue();
|
||||
const nsCSSRect *rect2 = aValue2.GetCSSRectValue();
|
||||
if (rect1->mTop.GetUnit() != rect2->mTop.GetUnit() ||
|
||||
rect1->mRight.GetUnit() != rect2->mRight.GetUnit() ||
|
||||
rect1->mBottom.GetUnit() != rect2->mBottom.GetUnit() ||
|
||||
rect1->mLeft.GetUnit() != rect2->mLeft.GetUnit()) {
|
||||
// At least until we have calc()
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsAutoPtr<nsCSSRect> result(new nsCSSRect);
|
||||
if (!result) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(nsCSSRect::sides); ++i) {
|
||||
nsCSSValue nsCSSRect::*member = nsCSSRect::sides[i];
|
||||
NS_ABORT_IF_FALSE((rect1->*member).GetUnit() ==
|
||||
(rect2->*member).GetUnit(),
|
||||
"should have returned above");
|
||||
switch ((rect1->*member).GetUnit()) {
|
||||
case eCSSUnit_Pixel:
|
||||
(result->*member).SetFloatValue(
|
||||
aCoeff1 * (rect1->*member).GetFloatValue() +
|
||||
aCoeff2 * (rect2->*member).GetFloatValue(),
|
||||
eCSSUnit_Pixel);
|
||||
break;
|
||||
case eCSSUnit_Auto:
|
||||
if (float(aCoeff1 + aCoeff2) != 1.0f) {
|
||||
// Interpolating between two auto values makes sense;
|
||||
// adding in other ratios does not.
|
||||
return PR_FALSE;
|
||||
}
|
||||
(result->*member).SetAutoValue();
|
||||
break;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(PR_FALSE, "unexpected unit");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
aResultValue.SetAndAdoptCSSRectValue(result.forget(), eUnit_CSSRect);
|
||||
break;
|
||||
}
|
||||
case eUnit_Dasharray: {
|
||||
const nsCSSValueList *list1 = aValue1.GetCSSValueListValue();
|
||||
const nsCSSValueList *list2 = aValue2.GetCSSValueListValue();
|
||||
@ -896,10 +983,8 @@ nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty,
|
||||
case eUnit_Coord: {
|
||||
NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] == eCSSType_Value,
|
||||
"type mismatch");
|
||||
float pxVal = aPresContext->AppUnitsToFloatCSSPixels(
|
||||
aComputedValue.GetCoordValue());
|
||||
static_cast<nsCSSValue*>(aSpecifiedValue)->
|
||||
SetFloatValue(pxVal, eCSSUnit_Pixel);
|
||||
nscoordToCSSValue(aComputedValue.GetCoordValue(),
|
||||
*static_cast<nsCSSValue*>(aSpecifiedValue));
|
||||
break;
|
||||
}
|
||||
case eUnit_Percent:
|
||||
@ -936,6 +1021,12 @@ nsStyleAnimation::UncomputeValue(nsCSSProperty aProperty,
|
||||
*static_cast<nsCSSValuePair*>(aSpecifiedValue) =
|
||||
*aComputedValue.GetCSSValuePairValue();
|
||||
break;
|
||||
case eUnit_CSSRect:
|
||||
NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
|
||||
eCSSType_Rect, "type mismatch");
|
||||
*static_cast<nsCSSRect*>(aSpecifiedValue) =
|
||||
*aComputedValue.GetCSSRectValue();
|
||||
break;
|
||||
case eUnit_Dasharray:
|
||||
case eUnit_Shadow:
|
||||
NS_ABORT_IF_FALSE(nsCSSProps::kTypeTable[aProperty] ==
|
||||
@ -1063,9 +1154,7 @@ StyleCoordToCSSValue(const nsStyleCoord& aCoord, nsCSSValue& aCSSValue)
|
||||
{
|
||||
switch (aCoord.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
aCSSValue.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(
|
||||
aCoord.GetCoordValue()),
|
||||
eCSSUnit_Pixel);
|
||||
nscoordToCSSValue(aCoord.GetCoordValue(), aCSSValue);
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
aCSSValue.SetPercentValue(aCoord.GetPercentValue());
|
||||
@ -1164,14 +1253,8 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
|
||||
if (!pair) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
pair->mXValue.SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(
|
||||
styleTableBorder->mBorderSpacingX),
|
||||
eCSSUnit_Pixel);
|
||||
pair->mYValue.SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(
|
||||
styleTableBorder->mBorderSpacingY),
|
||||
eCSSUnit_Pixel);
|
||||
nscoordToCSSValue(styleTableBorder->mBorderSpacingX, pair->mXValue);
|
||||
nscoordToCSSValue(styleTableBorder->mBorderSpacingY, pair->mYValue);
|
||||
aComputedValue.SetAndAdoptCSSValuePairValue(pair,
|
||||
eUnit_CSSValuePair);
|
||||
break;
|
||||
@ -1270,6 +1353,64 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
case eCSSProperty_image_region: {
|
||||
const nsStyleList *list =
|
||||
static_cast<const nsStyleList*>(styleStruct);
|
||||
const nsRect &srect = list->mImageRegion;
|
||||
if (srect.IsEmpty()) {
|
||||
aComputedValue.SetAutoValue();
|
||||
break;
|
||||
}
|
||||
|
||||
nsCSSRect *vrect = new nsCSSRect;
|
||||
if (!vrect) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
nscoordToCSSValue(srect.x, vrect->mLeft);
|
||||
nscoordToCSSValue(srect.y, vrect->mTop);
|
||||
nscoordToCSSValue(srect.XMost(), vrect->mRight);
|
||||
nscoordToCSSValue(srect.YMost(), vrect->mBottom);
|
||||
aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect);
|
||||
break;
|
||||
}
|
||||
|
||||
case eCSSProperty_clip: {
|
||||
const nsStyleDisplay *display =
|
||||
static_cast<const nsStyleDisplay*>(styleStruct);
|
||||
if (!(display->mClipFlags & NS_STYLE_CLIP_RECT)) {
|
||||
aComputedValue.SetAutoValue();
|
||||
break;
|
||||
}
|
||||
|
||||
nsCSSRect *vrect = new nsCSSRect;
|
||||
if (!vrect) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
const nsRect &srect = display->mClip;
|
||||
if (display->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
|
||||
vrect->mTop.SetAutoValue();
|
||||
} else {
|
||||
nscoordToCSSValue(srect.y, vrect->mTop);
|
||||
}
|
||||
if (display->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
|
||||
vrect->mRight.SetAutoValue();
|
||||
} else {
|
||||
nscoordToCSSValue(srect.XMost(), vrect->mRight);
|
||||
}
|
||||
if (display->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
|
||||
vrect->mBottom.SetAutoValue();
|
||||
} else {
|
||||
nscoordToCSSValue(srect.YMost(), vrect->mBottom);
|
||||
}
|
||||
if (display->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
|
||||
vrect->mLeft.SetAutoValue();
|
||||
} else {
|
||||
nscoordToCSSValue(srect.x, vrect->mLeft);
|
||||
}
|
||||
aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(PR_FALSE, "missing property implementation");
|
||||
return PR_FALSE;
|
||||
@ -1376,20 +1517,12 @@ nsStyleAnimation::ExtractComputedValue(nsCSSProperty aProperty,
|
||||
const nsCSSShadowItem *shadow = shadowArray->ShadowAt(i);
|
||||
// X, Y, Radius, Spread, Color, Inset
|
||||
nsRefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(6);
|
||||
arr->Item(0).SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(shadow->mXOffset),
|
||||
eCSSUnit_Pixel);
|
||||
arr->Item(1).SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(shadow->mYOffset),
|
||||
eCSSUnit_Pixel);
|
||||
arr->Item(2).SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(shadow->mRadius),
|
||||
eCSSUnit_Pixel);
|
||||
nscoordToCSSValue(shadow->mXOffset, arr->Item(0));
|
||||
nscoordToCSSValue(shadow->mYOffset, arr->Item(1));
|
||||
nscoordToCSSValue(shadow->mRadius, arr->Item(2));
|
||||
// NOTE: This code sometimes stores mSpread: 0 even when
|
||||
// the parser would be required to leave it null.
|
||||
arr->Item(3).SetFloatValue(
|
||||
nsPresContext::AppUnitsToFloatCSSPixels(shadow->mSpread),
|
||||
eCSSUnit_Pixel);
|
||||
nscoordToCSSValue(shadow->mSpread, arr->Item(3));
|
||||
if (shadow->mHasColor) {
|
||||
arr->Item(4).SetColorValue(shadow->mColor);
|
||||
}
|
||||
@ -1482,6 +1615,13 @@ nsStyleAnimation::Value::operator=(const Value& aOther)
|
||||
mUnit = eUnit_Null;
|
||||
}
|
||||
break;
|
||||
case eUnit_CSSRect:
|
||||
NS_ABORT_IF_FALSE(aOther.mValue.mCSSRect, "rects may not be null");
|
||||
mValue.mCSSRect = new nsCSSRect(*aOther.mValue.mCSSRect);
|
||||
if (!mValue.mCSSRect) {
|
||||
mUnit = eUnit_Null;
|
||||
}
|
||||
break;
|
||||
case eUnit_Dasharray:
|
||||
case eUnit_Shadow:
|
||||
NS_ABORT_IF_FALSE(mUnit != eUnit_Dasharray || aOther.mValue.mCSSValueList,
|
||||
@ -1591,6 +1731,16 @@ nsStyleAnimation::Value::SetAndAdoptCSSValuePairValue(
|
||||
mValue.mCSSValuePair = aValuePair; // take ownership
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleAnimation::Value::SetAndAdoptCSSRectValue(nsCSSRect *aRect, Unit aUnit)
|
||||
{
|
||||
FreeValue();
|
||||
NS_ABORT_IF_FALSE(IsCSSRectUnit(aUnit), "bad unit");
|
||||
NS_ABORT_IF_FALSE(aRect != nsnull, "value pairs may not be null");
|
||||
mUnit = aUnit;
|
||||
mValue.mCSSRect = aRect; // take ownership
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleAnimation::Value::SetAndAdoptCSSValueListValue(
|
||||
nsCSSValueList *aValueList, Unit aUnit)
|
||||
@ -1610,6 +1760,8 @@ nsStyleAnimation::Value::FreeValue()
|
||||
delete mValue.mCSSValueList;
|
||||
} else if (IsCSSValuePairUnit(mUnit)) {
|
||||
delete mValue.mCSSValuePair;
|
||||
} else if (IsCSSRectUnit(mUnit)) {
|
||||
delete mValue.mCSSRect;
|
||||
} else if (IsStringUnit(mUnit)) {
|
||||
NS_ABORT_IF_FALSE(mValue.mString, "expecting non-null string");
|
||||
mValue.mString->Release();
|
||||
@ -1641,6 +1793,8 @@ nsStyleAnimation::Value::operator==(const Value& aOther) const
|
||||
return mValue.mColor == aOther.mValue.mColor;
|
||||
case eUnit_CSSValuePair:
|
||||
return *mValue.mCSSValuePair == *aOther.mValue.mCSSValuePair;
|
||||
case eUnit_CSSRect:
|
||||
return *mValue.mCSSRect == *aOther.mValue.mCSSRect;
|
||||
case eUnit_Dasharray:
|
||||
case eUnit_Shadow:
|
||||
return nsCSSValueList::Equal(mValue.mCSSValueList,
|
||||
|
@ -56,6 +56,7 @@ class nsPresContext;
|
||||
class nsStyleContext;
|
||||
struct nsCSSValueList;
|
||||
struct nsCSSValuePair;
|
||||
struct nsCSSRect;
|
||||
|
||||
/**
|
||||
* Utility class to handle animated style values
|
||||
@ -234,6 +235,7 @@ public:
|
||||
eUnit_Float,
|
||||
eUnit_Color,
|
||||
eUnit_CSSValuePair, // nsCSSValuePair* (never null)
|
||||
eUnit_CSSRect, // nsCSSRect* (never null)
|
||||
eUnit_Dasharray, // nsCSSValueList* (never null)
|
||||
eUnit_Shadow, // nsCSSValueList* (may be null)
|
||||
eUnit_UnparsedString // nsStringBuffer* (never null)
|
||||
@ -248,6 +250,7 @@ public:
|
||||
float mFloat;
|
||||
nscolor mColor;
|
||||
nsCSSValuePair* mCSSValuePair;
|
||||
nsCSSRect* mCSSRect;
|
||||
nsCSSValueList* mCSSValueList;
|
||||
nsStringBuffer* mString;
|
||||
} mValue;
|
||||
@ -287,6 +290,10 @@ public:
|
||||
NS_ASSERTION(IsCSSValuePairUnit(mUnit), "unit mismatch");
|
||||
return mValue.mCSSValuePair;
|
||||
}
|
||||
nsCSSRect* GetCSSRectValue() const {
|
||||
NS_ASSERTION(IsCSSRectUnit(mUnit), "unit mismatch");
|
||||
return mValue.mCSSRect;
|
||||
}
|
||||
nsCSSValueList* GetCSSValueListValue() const {
|
||||
NS_ASSERTION(IsCSSValueListUnit(mUnit), "unit mismatch");
|
||||
return mValue.mCSSValueList;
|
||||
@ -336,6 +343,7 @@ public:
|
||||
// "SetAndAdopt*".
|
||||
void SetAndAdoptCSSValueListValue(nsCSSValueList *aValue, Unit aUnit);
|
||||
void SetAndAdoptCSSValuePairValue(nsCSSValuePair *aValue, Unit aUnit);
|
||||
void SetAndAdoptCSSRectValue(nsCSSRect *aValue, Unit aUnit);
|
||||
|
||||
Value& operator=(const Value& aOther);
|
||||
|
||||
@ -356,6 +364,9 @@ public:
|
||||
static PRBool IsCSSValuePairUnit(Unit aUnit) {
|
||||
return aUnit == eUnit_CSSValuePair;
|
||||
}
|
||||
static PRBool IsCSSRectUnit(Unit aUnit) {
|
||||
return aUnit == eUnit_CSSRect;
|
||||
}
|
||||
static PRBool IsCSSValueListUnit(Unit aUnit) {
|
||||
return aUnit == eUnit_Dasharray || aUnit == eUnit_Shadow;
|
||||
}
|
||||
|
@ -1302,14 +1302,7 @@ struct nsStyleDisplay {
|
||||
// We guarantee that if mBinding is non-null, so are mBinding->mURI and
|
||||
// mBinding->mOriginPrincipal.
|
||||
nsRefPtr<nsCSSValue::URL> mBinding; // [reset]
|
||||
#if 0
|
||||
// XXX This is how it is defined in the CSS2 spec, but the errata
|
||||
// changed it to be consistent with the positioning draft and how
|
||||
// Nav and IE implement it
|
||||
nsMargin mClip; // [reset] offsets from respective edge
|
||||
#else
|
||||
nsRect mClip; // [reset] offsets from upper-left border edge
|
||||
#endif
|
||||
float mOpacity; // [reset]
|
||||
PRUint8 mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
|
||||
PRUint8 mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed
|
||||
|
@ -59,6 +59,7 @@ var supported_properties = {
|
||||
"-moz-column-rule-color": [ test_color_transition ],
|
||||
"-moz-column-rule-width": [ test_length_transition ],
|
||||
"-moz-column-width": [ test_length_transition ],
|
||||
"-moz-image-region": [ test_rect_transition ],
|
||||
"-moz-outline-radius-bottomleft": [ test_radius_transition ],
|
||||
"-moz-outline-radius-bottomright": [ test_radius_transition ],
|
||||
"-moz-outline-radius-topleft": [ test_radius_transition ],
|
||||
@ -76,6 +77,7 @@ var supported_properties = {
|
||||
"border-top-color": [ test_color_transition ],
|
||||
"border-top-width": [ test_length_transition ],
|
||||
"bottom": [ test_length_transition, test_percent_transition ],
|
||||
"clip": [ test_rect_transition ],
|
||||
"color": [ test_color_transition ],
|
||||
"fill": [ test_color_transition ],
|
||||
"fill-opacity" : [ test_float_zeroToOne_transition ],
|
||||
@ -526,6 +528,26 @@ function test_length_percent_pair_transition(prop) {
|
||||
"length-valued property " + prop + ": interpolation of lengths");
|
||||
}
|
||||
|
||||
function test_rect_transition(prop) {
|
||||
div.style.setProperty("-moz-transition-property", "none", "");
|
||||
div.style.setProperty(prop, "rect(4px, 16px, 12px, 8px)", "");
|
||||
is(cs.getPropertyValue(prop), "rect(4px, 16px, 12px, 8px)",
|
||||
"rect-valued property " + prop + ": computed value before transition");
|
||||
div.style.setProperty("-moz-transition-property", prop, "");
|
||||
div.style.setProperty(prop, "rect(0px, 6px, 4px, 2px)", "");
|
||||
is(cs.getPropertyValue(prop), "rect(2px, 11px, 8px, 5px)",
|
||||
"rect-valued property " + prop + ": interpolation of rects");
|
||||
if (prop == "clip") {
|
||||
div.style.setProperty(prop, "rect(0px, 6px, 4px, auto)", "");
|
||||
is(cs.getPropertyValue(prop), "rect(0px, 6px, 4px, auto)",
|
||||
"rect-valued property " + prop + ": can't interpolate auto components");
|
||||
div.style.setProperty(prop, "rect(0px, 6px, 4px, 2px)", "");
|
||||
}
|
||||
div.style.setProperty(prop, "auto", "");
|
||||
is(cs.getPropertyValue(prop), "auto",
|
||||
"rect-valued property " + prop + ": can't interpolate auto components");
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user