Bug 1273706 - Part 7: Add support to StyleAnimationValues for storing lists of values. r?heycam
The lists are homogeneous lists of style animation values. We also implement
computing distances & interpolating between them.
The lists are simple lists, not repeatable lists. [1]
This is for support of custom properties with syntax like <number>+, which
indicates a list of <number>s with length at least one. Currently the syntax
only supports homogeneous non-empty list.
[1]: https://github.com/w3c/css-houdini-drafts/issues/273
MozReview-Commit-ID: 6DHgXxwpgVl
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -945,16 +945,35 @@ StyleAnimationValue::ComputeDistance(nsC
} while (list1 && list2);
if (list1 || list2) {
// We can't interpolate lists of different lengths.
return false;
}
aDistance = sqrt(squareDistance);
return true;
}
+ case eUnit_List: {
+ const nsTArray<StyleAnimationValue>* start = aStartValue.mValue.mList;
+ const nsTArray<StyleAnimationValue>* end = aEndValue.mValue.mList;
+ if (start->Length() != end->Length()) {
+ // These are simple lists, not repeatable lists.
+ return false;
+ }
+ double dist2 = 0;
+ for (size_t i = 0; i < start->Length(); i++) {
+ double d = 0;
+ if (!ComputeDistance(aProperty, (*start)[i], (*end)[i], d)) {
+ return false;
+ }
+ // We square the component distances just like we do above.
+ dist2 += d * d;
+ }
+ aDistance = sqrt(dist2);
+ return true;
+ }
}
MOZ_ASSERT(false, "Can't compute distance using the given common unit");
return false;
}
#define MAX_PACKED_COLOR_COMPONENT 255
@@ -2741,16 +2760,36 @@ StyleAnimationValue::AddWeighted(nsCSSPr
UniquePtr<nsCSSValuePairList> result =
AddCSSValuePairList(aProperty, aCoeff1, list1, aCoeff2, list2);
if (!result) {
return false;
}
aResultValue.SetAndAdoptCSSValuePairListValue(result.release());
return true;
}
+ case eUnit_List: {
+ const nsTArray<StyleAnimationValue>* start = aValue1.mValue.mList;
+ const nsTArray<StyleAnimationValue>* end = aValue2.mValue.mList;
+ if (start->Length() != end->Length()) {
+ // These are simple lists, not repeatable lists.
+ return false;
+ }
+ UniquePtr<nsTArray<StyleAnimationValue>> result
+ (new nsTArray<StyleAnimationValue>(start->Length()));
+ for (size_t i = 0; i < start->Length(); i++) {
+ StyleAnimationValue val;
+ if (!AddWeighted(aProperty, aCoeff1, (*start)[i], aCoeff2, (*end)[i],
+ val)) {
+ return false;
+ }
+ result->AppendElement(Move(val));
+ }
+ aResultValue.SetAndAdoptListValue(Move(result));
+ return true;
+ }
}
MOZ_ASSERT(false, "Can't interpolate using the given common unit");
return false;
}
already_AddRefed<css::StyleRule>
BuildStyleRule(nsCSSPropertyID aProperty,
@@ -3119,16 +3158,32 @@ StyleAnimationValue::UncomputeValue(nsCS
case eUnit_Transform:
aSpecifiedValue.
SetSharedListValue(aComputedValue.GetCSSValueSharedListValue());
break;
case eUnit_CSSValuePairList:
aSpecifiedValue.
SetDependentPairListValue(aComputedValue.GetCSSValuePairListValue());
break;
+ case eUnit_List: {
+ nsCSSValueList* toList = aSpecifiedValue.SetListValue();
+ const nsTArray<StyleAnimationValue>* fromList =
+ aComputedValue.mValue.mList;
+ for (size_t i = 0; i < fromList->Length(); i++) {
+ const StyleAnimationValue& term = (*fromList)[i];
+ nsCSSValue value;
+ StyleAnimationValue::UncomputeValue(eCSSProperty_UNKNOWN, term, value);
+ toList->mValue = value;
+ if (i != fromList->Length() - 1) {
+ toList->mNext = new nsCSSValueList;
+ toList = toList->mNext;
+ }
+ }
+ break;
+ }
default:
return false;
}
return true;
}
bool
StyleAnimationValue::UncomputeValue(nsCSSPropertyID aProperty,
@@ -4362,16 +4417,20 @@ StyleAnimationValue::operator=(const Sty
"value pair lists may not be null");
mValue.mCSSValuePairList = aOther.mValue.mCSSValuePairList->Clone();
break;
case eUnit_UnparsedString:
MOZ_ASSERT(aOther.mValue.mString, "expecting non-null string");
mValue.mString = aOther.mValue.mString;
mValue.mString->AddRef();
break;
+ case eUnit_List:
+ MOZ_ASSERT(aOther.mValue.mList, "lists may not be null");
+ mValue.mList = new nsTArray<StyleAnimationValue>(*aOther.mValue.mList);
+ break;
}
return *this;
}
void
StyleAnimationValue::SetNormalValue()
{
@@ -4503,16 +4562,28 @@ StyleAnimationValue::SetCSSValueArrayVal
MOZ_ASSERT(aValue != nullptr,
"not currently expecting any arrays to be null");
mUnit = aUnit;
mValue.mCSSValueArray = aValue;
mValue.mCSSValueArray->AddRef();
}
void
+StyleAnimationValue::SetAndAdoptListValue(UniquePtr<nsTArray<StyleAnimationValue>> aList)
+{
+ MOZ_ASSERT(aList, "lists may not be null");
+ FreeValue();
+ MOZ_ASSERT(aList->Length() >= 1,
+ "These should only be created for custom properties, whose syntax "
+ "only allows at least one element in lists.");
+ mUnit = eUnit_List;
+ mValue.mList = aList.release();
+}
+
+void
StyleAnimationValue::SetAndAdoptCSSValueListValue(nsCSSValueList *aValueList,
Unit aUnit)
{
FreeValue();
MOZ_ASSERT(IsCSSValueListUnit(aUnit), "bad unit");
MOZ_ASSERT(aUnit == eUnit_Shadow || aUnit == eUnit_Filter ||
aValueList != nullptr,
"value lists other than shadows and filters may not be null");
@@ -4556,16 +4627,18 @@ StyleAnimationValue::FreeValue()
delete mValue.mCSSRect;
} else if (IsCSSValuePairListUnit(mUnit)) {
delete mValue.mCSSValuePairList;
} else if (IsCSSValueArrayUnit(mUnit)) {
mValue.mCSSValueArray->Release();
} else if (IsStringUnit(mUnit)) {
MOZ_ASSERT(mValue.mString, "expecting non-null string");
mValue.mString->Release();
+ } else if (mUnit == eUnit_List) {
+ delete mValue.mList;
}
}
bool
StyleAnimationValue::operator==(const StyleAnimationValue& aOther) const
{
if (mUnit != aOther.mUnit) {
return false;
@@ -4612,13 +4685,15 @@ StyleAnimationValue::operator==(const St
case eUnit_Transform:
return *mValue.mCSSValueSharedList == *aOther.mValue.mCSSValueSharedList;
case eUnit_CSSValuePairList:
return nsCSSValuePairList::Equal(mValue.mCSSValuePairList,
aOther.mValue.mCSSValuePairList);
case eUnit_UnparsedString:
return (NS_strcmp(GetStringBufferValue(),
aOther.GetStringBufferValue()) == 0);
+ case eUnit_List:
+ return *mValue.mList == *aOther.mValue.mList;
}
NS_NOTREACHED("incomplete case");
return false;
}
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -11,16 +11,17 @@
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/UniquePtr.h"
#include "nsStringFwd.h"
#include "nsStringBuffer.h"
#include "nsCoord.h"
#include "nsColor.h"
#include "nsCSSProps.h"
#include "nsCSSValue.h"
+#include "nsTArray.h"
class nsIFrame;
class nsStyleContext;
class gfx3DMatrix;
namespace mozilla {
namespace css {
@@ -282,17 +283,21 @@ public:
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_BackgroundPositionCoord, // nsCSSValueList* (never null)
eUnit_CSSValuePairList, // nsCSSValuePairList* (never null)
- eUnit_UnparsedString // nsStringBuffer* (never null)
+ eUnit_UnparsedString, // nsStringBuffer* (never null)
+ eUnit_List, // nsTArray<StyleAnimationValue>* (never null)
+ // Currently only used for custom props! Length >= 1.
+ // All StyleAnimationValues in the list must have the same
+ // simple type (not a list or other compound value).
};
private:
Unit mUnit;
union {
int32_t mInt;
nscoord mCoord;
float mFloat;
@@ -301,16 +306,17 @@ private:
nsCSSValuePair* mCSSValuePair;
nsCSSValueTriplet* mCSSValueTriplet;
nsCSSRect* mCSSRect;
nsCSSValue::Array* mCSSValueArray;
nsCSSValueList* mCSSValueList;
nsCSSValueSharedList* mCSSValueSharedList;
nsCSSValuePairList* mCSSValuePairList;
nsStringBuffer* mString;
+ nsTArray<StyleAnimationValue>* mList;
} mValue;
public:
Unit GetUnit() const {
NS_ASSERTION(mUnit != eUnit_Null, "uninitialized");
return mUnit;
}
@@ -371,16 +377,20 @@ public:
nsCSSValuePairList* GetCSSValuePairListValue() const {
NS_ASSERTION(IsCSSValuePairListUnit(mUnit), "unit mismatch");
return mValue.mCSSValuePairList;
}
const char16_t* GetStringBufferValue() const {
NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch");
return GetBufferValue(mValue.mString);
}
+ nsTArray<StyleAnimationValue>* GetListValue() const {
+ NS_ASSERTION(mUnit == eUnit_List, "unit mismatch");
+ return mValue.mList;
+ }
void GetStringValue(nsAString& aBuffer) const {
NS_ASSERTION(IsStringUnit(mUnit), "unit mismatch");
aBuffer.Truncate();
uint32_t len = NS_strlen(GetBufferValue(mValue.mString));
mValue.mString->ToString(len, aBuffer);
}
@@ -449,16 +459,17 @@ public:
// These setters take ownership of |aValue|, and are therefore named
// "SetAndAdopt*".
void SetAndAdoptCSSValueValue(nsCSSValue *aValue, Unit aUnit);
void SetAndAdoptCSSValuePairValue(nsCSSValuePair *aValue, Unit aUnit);
void SetAndAdoptCSSValueTripletValue(nsCSSValueTriplet *aValue, Unit aUnit);
void SetAndAdoptCSSRectValue(nsCSSRect *aValue, Unit aUnit);
void SetAndAdoptCSSValueListValue(nsCSSValueList *aValue, Unit aUnit);
void SetAndAdoptCSSValuePairListValue(nsCSSValuePairList *aValue);
+ void SetAndAdoptListValue(UniquePtr<nsTArray<StyleAnimationValue>> aList);
void SetTransformValue(nsCSSValueSharedList* aList);
StyleAnimationValue& operator=(const StyleAnimationValue& aOther);
bool operator==(const StyleAnimationValue& aOther) const;
bool operator!=(const StyleAnimationValue& aOther) const
{ return !(*this == aOther); }