--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -444,16 +444,42 @@ CalcPositionSquareDistance(const nsCSSVa
float difflen = calcVal[i+2].mLength - calcVal[i].mLength;
float diffpct = calcVal[i+2].mPercent - calcVal[i].mPercent;
squareDistance += difflen * difflen + diffpct * diffpct;
}
return squareDistance;
}
+static PixelCalcValue
+CalcBackgroundCoord(const nsCSSValue& aCoord)
+{
+ NS_ASSERTION(aCoord.GetUnit() == eCSSUnit_Array,
+ "Expected array");
+
+ nsCSSValue::Array* array = aCoord.GetArrayValue();
+ MOZ_ASSERT(array->Count() == 2 &&
+ array->Item(0).GetUnit() == eCSSUnit_Null &&
+ array->Item(1).GetUnit() != eCSSUnit_Null,
+ "Invalid position value");
+ return ExtractCalcValue(array->Item(1));
+}
+
+double
+CalcPositionCoordSquareDistance(const nsCSSValue& aPos1,
+ const nsCSSValue& aPos2)
+{
+ PixelCalcValue calcVal1 = CalcBackgroundCoord(aPos1);
+ PixelCalcValue calcVal2 = CalcBackgroundCoord(aPos2);
+
+ float difflen = calcVal2.mLength - calcVal1.mLength;
+ float diffpct = calcVal2.mPercent - calcVal1.mPercent;
+ return difflen * difflen + diffpct * diffpct;
+}
+
// CLASS METHODS
// -------------
bool
StyleAnimationValue::ComputeDistance(nsCSSProperty aProperty,
const StyleAnimationValue& aStartValue,
const StyleAnimationValue& aEndValue,
double& aDistance)
@@ -839,26 +865,26 @@ StyleAnimationValue::ComputeDistance(nsC
case eUnit_Shape: {
return false;
}
case eUnit_Filter:
// FIXME: Support paced animations for filter function interpolation.
case eUnit_Transform: {
return false;
}
- case eUnit_BackgroundPosition: {
+ case eUnit_BackgroundPositionCoord: {
const nsCSSValueList *position1 = aStartValue.GetCSSValueListValue();
const nsCSSValueList *position2 = aEndValue.GetCSSValueListValue();
double squareDistance = 0.0;
MOZ_ASSERT(!position1 == !position2, "lists should be same length");
while (position1 && position2) {
- squareDistance += CalcPositionSquareDistance(position1->mValue,
- position2->mValue);
+ squareDistance += CalcPositionCoordSquareDistance(position1->mValue,
+ position2->mValue);
position1 = position1->mNext;
position2 = position2->mNext;
}
// fail if lists differ in length.
if (position1 || position2) {
return false;
}
@@ -2186,16 +2212,36 @@ AddTransformLists(double aCoeff1, const
} while (aList1);
MOZ_ASSERT(!aList2, "list length mismatch");
MOZ_ASSERT(!*resultTail,
"resultTail isn't pointing to the tail");
return result.forget();
}
+static void
+AddPositionCoords(double aCoeff1, const nsCSSValue& aPos1,
+ double aCoeff2, const nsCSSValue& aPos2,
+ nsCSSValue& aResultPos)
+{
+ const nsCSSValue::Array* posArray1 = aPos1.GetArrayValue();
+ const nsCSSValue::Array* posArray2 = aPos2.GetArrayValue();
+ nsCSSValue::Array* resultPosArray = nsCSSValue::Array::Create(2);
+ aResultPos.SetArrayValue(resultPosArray, eCSSUnit_Array);
+
+ /* Only compute element 1. The <position-coord> is
+ * 'uncomputed' to only that element.
+ */
+ const nsCSSValue& v1 = posArray1->Item(1);
+ const nsCSSValue& v2 = posArray2->Item(1);
+ nsCSSValue& vr = resultPosArray->Item(1);
+ AddCSSValueCanonicalCalc(aCoeff1, v1,
+ aCoeff2, v2, vr);
+}
+
bool
StyleAnimationValue::AddWeighted(nsCSSProperty aProperty,
double aCoeff1,
const StyleAnimationValue& aValue1,
double aCoeff2,
const StyleAnimationValue& aValue2,
StyleAnimationValue& aResultValue)
{
@@ -2660,40 +2706,40 @@ StyleAnimationValue::AddWeighted(nsCSSPr
result = AddDifferentTransformLists(aCoeff1, list1, aCoeff2, list2);
}
}
}
aResultValue.SetTransformValue(new nsCSSValueSharedList(result.forget()));
return true;
}
- case eUnit_BackgroundPosition: {
+ case eUnit_BackgroundPositionCoord: {
const nsCSSValueList *position1 = aValue1.GetCSSValueListValue();
const nsCSSValueList *position2 = aValue2.GetCSSValueListValue();
nsAutoPtr<nsCSSValueList> result;
nsCSSValueList **resultTail = getter_Transfers(result);
while (position1 && position2) {
nsCSSValueList *item = new nsCSSValueList;
*resultTail = item;
resultTail = &item->mNext;
- AddPositions(aCoeff1, position1->mValue,
- aCoeff2, position2->mValue, item->mValue);
+ AddPositionCoords(aCoeff1, position1->mValue,
+ aCoeff2, position2->mValue, item->mValue);
position1 = position1->mNext;
position2 = position2->mNext;
}
// Check for different lengths
if (position1 || position2) {
return false;
}
aResultValue.SetAndAdoptCSSValueListValue(result.forget(),
- eUnit_BackgroundPosition);
+ eUnit_BackgroundPositionCoord);
return true;
}
case eUnit_CSSValuePairList: {
const nsCSSValuePairList *list1 = aValue1.GetCSSValuePairListValue();
const nsCSSValuePairList *list2 = aValue2.GetCSSValuePairListValue();
UniquePtr<nsCSSValuePairList> result =
AddCSSValuePairList(aProperty, aCoeff1, list1, aCoeff2, list2);
if (!result) {
@@ -3052,17 +3098,17 @@ StyleAnimationValue::UncomputeValue(nsCS
} break;
case eUnit_CSSRect: {
nsCSSRect& rect = aSpecifiedValue.SetRectValue();
rect = *aComputedValue.GetCSSRectValue();
} break;
case eUnit_Dasharray:
case eUnit_Shadow:
case eUnit_Filter:
- case eUnit_BackgroundPosition:
+ case eUnit_BackgroundPositionCoord:
{
nsCSSValueList* computedList = aComputedValue.GetCSSValueListValue();
if (computedList) {
aSpecifiedValue.SetDependentListValue(computedList);
} else {
aSpecifiedValue.SetNoneValue();
}
}
@@ -3091,17 +3137,17 @@ StyleAnimationValue::UncomputeValue(nsCS
StyleAnimationValue&& aComputedValue,
nsCSSValue& aSpecifiedValue)
{
Unit unit = aComputedValue.GetUnit();
switch (unit) {
case eUnit_Dasharray:
case eUnit_Shadow:
case eUnit_Filter:
- case eUnit_BackgroundPosition:
+ case eUnit_BackgroundPositionCoord:
{
UniquePtr<nsCSSValueList> computedList =
aComputedValue.TakeCSSValueListValue();
if (computedList) {
aSpecifiedValue.AdoptListValue(Move(computedList));
} else {
aSpecifiedValue.SetNoneValue();
}
@@ -3271,16 +3317,33 @@ SetPositionValue(const nsStyleImageLayer
// we'll just have a normalized "x,y" position, with no edge names needed.
nsCSSValue& xValue = posArray->Item(1);
nsCSSValue& yValue = posArray->Item(3);
SetCalcValue(&aPos.mXPosition, xValue);
SetCalcValue(&aPos.mYPosition, yValue);
}
+static void
+SetPositionCoordValue(const nsStyleImageLayers::Position::PositionCoord& aPosCoord,
+ nsCSSValue& aCSSValue)
+{
+ RefPtr<nsCSSValue::Array> posArray = nsCSSValue::Array::Create(2);
+ aCSSValue.SetArrayValue(posArray.get(), eCSSUnit_Array);
+
+ // NOTE: Array entry #0 here is intentionally left untouched, with
+ // eCSSUnit_Null. The purpose of this entry in our specified-style
+ // <position-coord> representation is to store edge names. But for values
+ // extracted from computed style (which is what we're dealing with here),
+ // we'll just have a normalized "x"/"y" position, with no edge names needed.
+ nsCSSValue& value = posArray->Item(1);
+
+ SetCalcValue(&aPosCoord, value);
+}
+
/*
* Assign |aOutput = aInput|, except with any non-pixel lengths
* replaced with the equivalent in pixels, and any non-canonical calc()
* expressions replaced with canonical ones.
*/
static void
SubstitutePixelValues(nsStyleContext* aStyleContext,
const nsCSSValue& aInput, nsCSSValue& aOutput)
@@ -3314,32 +3377,53 @@ SubstitutePixelValues(nsStyleContext* aS
aOutput.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(len),
eCSSUnit_Pixel);
} else {
aOutput = aInput;
}
}
static void
-ExtractImageLayerPositionList(const nsStyleImageLayers& aLayer,
- StyleAnimationValue& aComputedValue)
+ExtractImageLayerPositionXList(const nsStyleImageLayers& aLayer,
+ StyleAnimationValue& aComputedValue)
{
- MOZ_ASSERT(aLayer.mPositionCount > 0, "unexpected count");
+ MOZ_ASSERT(aLayer.mPositionXCount > 0, "unexpected count");
nsAutoPtr<nsCSSValueList> result;
nsCSSValueList **resultTail = getter_Transfers(result);
- for (uint32_t i = 0, i_end = aLayer.mPositionCount; i != i_end; ++i) {
+ for (uint32_t i = 0, i_end = aLayer.mPositionXCount; i != i_end; ++i) {
nsCSSValueList *item = new nsCSSValueList;
*resultTail = item;
resultTail = &item->mNext;
- SetPositionValue(aLayer.mLayers[i].mPosition, item->mValue);
+ SetPositionCoordValue(aLayer.mLayers[i].mPosition.mXPosition,
+ item->mValue);
}
aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
- StyleAnimationValue::eUnit_BackgroundPosition);
+ StyleAnimationValue::eUnit_BackgroundPositionCoord);
+}
+
+static void
+ExtractImageLayerPositionYList(const nsStyleImageLayers& aLayer,
+ StyleAnimationValue& aComputedValue)
+{
+ MOZ_ASSERT(aLayer.mPositionYCount > 0, "unexpected count");
+
+ nsAutoPtr<nsCSSValueList> result;
+ nsCSSValueList **resultTail = getter_Transfers(result);
+ for (uint32_t i = 0, i_end = aLayer.mPositionYCount; i != i_end; ++i) {
+ nsCSSValueList *item = new nsCSSValueList;
+ *resultTail = item;
+ resultTail = &item->mNext;
+ SetPositionCoordValue(aLayer.mLayers[i].mPosition.mYPosition,
+ item->mValue);
+ }
+
+ aComputedValue.SetAndAdoptCSSValueListValue(result.forget(),
+ StyleAnimationValue::eUnit_BackgroundPositionCoord);
}
static void
ExtractImageLayerSizePairList(const nsStyleImageLayers& aLayer,
StyleAnimationValue& aComputedValue)
{
MOZ_ASSERT(aLayer.mSizeCount > 0, "unexpected count");
@@ -3816,27 +3900,44 @@ StyleAnimationValue::ExtractComputedValu
nsAutoPtr<nsCSSValue> val(new nsCSSValue);
SetPositionValue(stylePos->mObjectPosition, *val);
aComputedValue.SetAndAdoptCSSValueValue(val.forget(),
eUnit_ObjectPosition);
break;
}
- case eCSSProperty_background_position: {
+ case eCSSProperty_background_position_x: {
const nsStyleImageLayers& layers =
static_cast<const nsStyleBackground*>(styleStruct)->mImage;
- ExtractImageLayerPositionList(layers, aComputedValue);
+ ExtractImageLayerPositionXList(layers, aComputedValue);
break;
}
+ case eCSSProperty_background_position_y: {
+ const nsStyleImageLayers& layers =
+ static_cast<const nsStyleBackground*>(styleStruct)->mImage;
+ ExtractImageLayerPositionYList(layers, aComputedValue);
+ break;
+
+
+
+
+ }
#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
- case eCSSProperty_mask_position: {
+ case eCSSProperty_mask_position_x: {
const nsStyleImageLayers& layers =
static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
- ExtractImageLayerPositionList(layers, aComputedValue);
+ ExtractImageLayerPositionXList(layers, aComputedValue);
+ break;
+ }
+ case eCSSProperty_mask_position_y: {
+ const nsStyleImageLayers& layers =
+ static_cast<const nsStyleSVGReset*>(styleStruct)->mMask;
+ ExtractImageLayerPositionYList(layers, aComputedValue);
+
break;
}
#endif
case eCSSProperty_background_size: {
const nsStyleImageLayers& layers =
static_cast<const nsStyleBackground*>(styleStruct)->mImage;
ExtractImageLayerSizePairList(layers, aComputedValue);
break;
@@ -4243,17 +4344,17 @@ StyleAnimationValue::operator=(const Sty
break;
case eUnit_CSSRect:
MOZ_ASSERT(aOther.mValue.mCSSRect, "rects may not be null");
mValue.mCSSRect = new nsCSSRect(*aOther.mValue.mCSSRect);
break;
case eUnit_Dasharray:
case eUnit_Shadow:
case eUnit_Filter:
- case eUnit_BackgroundPosition:
+ case eUnit_BackgroundPositionCoord:
MOZ_ASSERT(mUnit == eUnit_Shadow || mUnit == eUnit_Filter ||
aOther.mValue.mCSSValueList,
"value lists other than shadows and filters may not be null");
if (aOther.mValue.mCSSValueList) {
mValue.mCSSValueList = aOther.mValue.mCSSValueList->Clone();
} else {
mValue.mCSSValueList = nullptr;
}
@@ -4507,17 +4608,17 @@ StyleAnimationValue::operator==(const St
return *mValue.mCSSValuePair == *aOther.mValue.mCSSValuePair;
case eUnit_CSSValueTriplet:
return *mValue.mCSSValueTriplet == *aOther.mValue.mCSSValueTriplet;
case eUnit_CSSRect:
return *mValue.mCSSRect == *aOther.mValue.mCSSRect;
case eUnit_Dasharray:
case eUnit_Shadow:
case eUnit_Filter:
- case eUnit_BackgroundPosition:
+ case eUnit_BackgroundPositionCoord:
return nsCSSValueList::Equal(mValue.mCSSValueList,
aOther.mValue.mCSSValueList);
case eUnit_Shape:
return *mValue.mCSSValueArray == *aOther.mValue.mCSSValueArray;
case eUnit_Transform:
return *mValue.mCSSValueSharedList == *aOther.mValue.mCSSValueSharedList;
case eUnit_CSSValuePairList:
return nsCSSValuePairList::Equal(mValue.mCSSValuePairList,
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -280,17 +280,17 @@ public:
eUnit_CSSValuePair, // nsCSSValuePair* (never null)
eUnit_CSSValueTriplet, // nsCSSValueTriplet* (never null)
eUnit_CSSRect, // nsCSSRect* (never null)
eUnit_Dasharray, // nsCSSValueList* (never null)
eUnit_Shadow, // nsCSSValueList* (may be null)
eUnit_Shape, // nsCSSValue::Array* (never null)
eUnit_Filter, // nsCSSValueList* (may be null)
eUnit_Transform, // nsCSSValueList* (never null)
- eUnit_BackgroundPosition, // nsCSSValueList* (never null)
+ eUnit_BackgroundPositionCoord, // nsCSSValueList* (never null)
eUnit_CSSValuePairList, // nsCSSValuePairList* (never null)
eUnit_UnparsedString // nsStringBuffer* (never null)
};
private:
Unit mUnit;
union {
int32_t mInt;
@@ -481,17 +481,17 @@ private:
return aUnit == eUnit_CSSRect;
}
static bool IsCSSValueArrayUnit(Unit aUnit) {
return aUnit == eUnit_Shape;
}
static bool IsCSSValueListUnit(Unit aUnit) {
return aUnit == eUnit_Dasharray || aUnit == eUnit_Filter ||
aUnit == eUnit_Shadow ||
- aUnit == eUnit_BackgroundPosition;
+ aUnit == eUnit_BackgroundPositionCoord;
}
static bool IsCSSValueSharedListValue(Unit aUnit) {
return aUnit == eUnit_Transform;
}
static bool IsCSSValuePairListUnit(Unit aUnit) {
return aUnit == eUnit_CSSValuePairList;
}
static bool IsStringUnit(Unit aUnit) {
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -277,16 +277,30 @@ var supported_properties = {
};
if (SupportsMaskShorthand()) {
supported_properties["mask-position"] = [ test_background_position_transition,
// FIXME: We don't currently test clamping,
// since mask-position uses calc() as
// an intermediate form.
/* test_length_percent_pair_unclamped */ ];
+ supported_properties["mask-position-x"] = [ test_background_position_coord_transition,
+ test_length_transition,
+ test_percent_transition,
+ // FIXME: We don't currently test clamping,
+ // since background-position-x uses calc() as
+ // an intermediate form.
+ /* test_length_percent_pair_unclamped */ ];
+ supported_properties["mask-position-y"] = [ test_background_position_coord_transition,
+ test_length_transition,
+ test_percent_transition,
+ // FIXME: We don't currently test clamping,
+ // since background-position-y uses calc() as
+ // an intermediate form.
+ /* test_length_percent_pair_unclamped */ ];
supported_properties["mask-size"] = [ test_background_size_transition,
// FIXME: We don't currently test clamping,
// since mask-size uses calc() as an
// intermediate form.
/* test_length_percent_pair_clamped */ ];
}
var div = document.getElementById("display");