mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1198708 - Part 1: Store exact timing-function type on nsTimingFunction and ComputedTimingFunction. r=birtles
Since Keyframe.easing should reflect the {transition,animation}-timing- function value relevant to each keyframe, we'll need to store on nsTimingFunction the specific timing function value that was used, and copy it down into ComputedTimingFunction for KeyframeEffectReadOnly.getFrames() to access. This includes storing whether the optional start/end keyword in a steps() function was specified.
This commit is contained in:
parent
eac578d6c8
commit
8fcad4b3cb
@ -17,11 +17,12 @@ void
|
||||
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
|
||||
{
|
||||
mType = aFunction.mType;
|
||||
if (mType == nsTimingFunction::Function) {
|
||||
if (nsTimingFunction::IsSplineType(mType)) {
|
||||
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
|
||||
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
|
||||
} else {
|
||||
mSteps = aFunction.mSteps;
|
||||
mStepSyntax = aFunction.mStepSyntax;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,23 +37,20 @@ StepEnd(uint32_t aSteps, double aPortion)
|
||||
double
|
||||
ComputedTimingFunction::GetValue(double aPortion) const
|
||||
{
|
||||
switch (mType) {
|
||||
case nsTimingFunction::Function:
|
||||
return mTimingFunction.GetSplineValue(aPortion);
|
||||
case nsTimingFunction::StepStart:
|
||||
// There are diagrams in the spec that seem to suggest this check
|
||||
// and the bounds point should not be symmetric with StepEnd, but
|
||||
// should actually step up at rather than immediately after the
|
||||
// fraction points. However, we rely on rounding negative values
|
||||
// up to zero, so we can't do that. And it's not clear the spec
|
||||
// really meant it.
|
||||
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
|
||||
default:
|
||||
MOZ_ASSERT(false, "bad type");
|
||||
// fall through
|
||||
case nsTimingFunction::StepEnd:
|
||||
return StepEnd(mSteps, aPortion);
|
||||
if (HasSpline()) {
|
||||
return mTimingFunction.GetSplineValue(aPortion);
|
||||
}
|
||||
if (mType == nsTimingFunction::Type::StepStart) {
|
||||
// There are diagrams in the spec that seem to suggest this check
|
||||
// and the bounds point should not be symmetric with StepEnd, but
|
||||
// should actually step up at rather than immediately after the
|
||||
// fraction points. However, we rely on rounding negative values
|
||||
// up to zero, so we can't do that. And it's not clear the spec
|
||||
// really meant it.
|
||||
return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
|
||||
}
|
||||
MOZ_ASSERT(mType == nsTimingFunction::Type::StepEnd, "bad type");
|
||||
return StepEnd(mSteps, aPortion);
|
||||
}
|
||||
|
||||
// In the Web Animations model, the iteration progress can be outside the range
|
||||
|
@ -109,19 +109,23 @@ class ComputedTimingFunction
|
||||
{
|
||||
public:
|
||||
typedef nsTimingFunction::Type Type;
|
||||
typedef nsTimingFunction::StepSyntax StepSyntax;
|
||||
void Init(const nsTimingFunction &aFunction);
|
||||
double GetValue(double aPortion) const;
|
||||
const nsSMILKeySpline* GetFunction() const {
|
||||
NS_ASSERTION(mType == nsTimingFunction::Function, "Type mismatch");
|
||||
NS_ASSERTION(HasSpline(), "Type mismatch");
|
||||
return &mTimingFunction;
|
||||
}
|
||||
Type GetType() const { return mType; }
|
||||
bool HasSpline() const { return nsTimingFunction::IsSplineType(mType); }
|
||||
uint32_t GetSteps() const { return mSteps; }
|
||||
StepSyntax GetStepSyntax() const { return mStepSyntax; }
|
||||
bool operator==(const ComputedTimingFunction& aOther) const {
|
||||
return mType == aOther.mType &&
|
||||
(mType == nsTimingFunction::Function ?
|
||||
(HasSpline() ?
|
||||
mTimingFunction == aOther.mTimingFunction :
|
||||
mSteps == aOther.mSteps);
|
||||
(mSteps == aOther.mSteps &&
|
||||
mStepSyntax == aOther.mStepSyntax));
|
||||
}
|
||||
bool operator!=(const ComputedTimingFunction& aOther) const {
|
||||
return !(*this == aOther);
|
||||
@ -131,6 +135,7 @@ private:
|
||||
Type mType;
|
||||
nsSMILKeySpline mTimingFunction;
|
||||
uint32_t mSteps;
|
||||
StepSyntax mStepSyntax;
|
||||
};
|
||||
|
||||
struct AnimationPropertySegment
|
||||
|
@ -463,9 +463,11 @@ Layer::SetAnimations(const AnimationArray& aAnimations)
|
||||
NS_ASSERTION(tf.type() == TimingFunction::TStepFunction,
|
||||
"Function must be bezier or step");
|
||||
StepFunction sf = tf.get_StepFunction();
|
||||
nsTimingFunction::Type type = sf.type() == 1 ? nsTimingFunction::StepStart
|
||||
: nsTimingFunction::StepEnd;
|
||||
ctf->Init(nsTimingFunction(type, sf.steps()));
|
||||
nsTimingFunction::Type type = sf.type() == 1 ?
|
||||
nsTimingFunction::Type::StepStart :
|
||||
nsTimingFunction::Type::StepEnd;
|
||||
ctf->Init(nsTimingFunction(type, sf.steps(),
|
||||
nsTimingFunction::Keyword::Explicit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -340,13 +340,13 @@ static void AddTransformFunctions(nsCSSValueList* aList,
|
||||
static TimingFunction
|
||||
ToTimingFunction(const ComputedTimingFunction& aCTF)
|
||||
{
|
||||
if (aCTF.GetType() == nsTimingFunction::Function) {
|
||||
if (aCTF.HasSpline()) {
|
||||
const nsSMILKeySpline* spline = aCTF.GetFunction();
|
||||
return TimingFunction(CubicBezierFunction(spline->X1(), spline->Y1(),
|
||||
spline->X2(), spline->Y2()));
|
||||
}
|
||||
|
||||
uint32_t type = aCTF.GetType() == nsTimingFunction::StepStart ? 1 : 2;
|
||||
uint32_t type = aCTF.GetType() == nsTimingFunction::Type::StepStart ? 1 : 2;
|
||||
return TimingFunction(StepFunction(aCTF.GetSteps(), type));
|
||||
}
|
||||
|
||||
|
@ -14687,12 +14687,11 @@ CSSParserImpl::ParseTransitionStepTimingFunctionValues(nsCSSValue& aValue)
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t type = NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END;
|
||||
int32_t type = -1; // indicates an implicit end value
|
||||
if (ExpectSymbol(',', true)) {
|
||||
if (!GetToken(true)) {
|
||||
return false;
|
||||
}
|
||||
type = -1;
|
||||
if (mToken.mType == eCSSToken_Ident) {
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("start")) {
|
||||
type = NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START;
|
||||
|
@ -1062,7 +1062,8 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult,
|
||||
(array->Item(i).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
|
||||
array->Item(i).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
|
||||
array->Item(i).GetIntValue() == -1),
|
||||
"unexpected value");
|
||||
if (array->Item(i).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) {
|
||||
|
@ -5801,7 +5801,7 @@ nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList,
|
||||
|
||||
nsAutoString tmp;
|
||||
|
||||
if (aTimingFunction.mType == nsTimingFunction::Function) {
|
||||
if (aTimingFunction.HasSpline()) {
|
||||
// set the value from the cubic-bezier control points
|
||||
// (We could try to regenerate the keywords if we want.)
|
||||
tmp.AppendLiteral("cubic-bezier(");
|
||||
@ -5816,7 +5816,7 @@ nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList,
|
||||
} else {
|
||||
tmp.AppendLiteral("steps(");
|
||||
tmp.AppendInt(aTimingFunction.mSteps);
|
||||
if (aTimingFunction.mType == nsTimingFunction::StepStart) {
|
||||
if (aTimingFunction.mType == nsTimingFunction::Type::StepStart) {
|
||||
tmp.AppendLiteral(", start)");
|
||||
} else {
|
||||
tmp.AppendLiteral(", end)");
|
||||
|
@ -4848,13 +4848,18 @@ ComputeTimingFunction(const nsCSSValue& aValue, nsTimingFunction& aResult)
|
||||
(array->Item(1).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
|
||||
array->Item(1).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
|
||||
array->Item(1).GetIntValue() == -1),
|
||||
"unexpected second value");
|
||||
nsTimingFunction::Type type =
|
||||
(array->Item(1).GetIntValue() ==
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END)
|
||||
? nsTimingFunction::StepEnd : nsTimingFunction::StepStart;
|
||||
aResult = nsTimingFunction(type, array->Item(0).GetIntValue());
|
||||
NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) ?
|
||||
nsTimingFunction::Type::StepStart :
|
||||
nsTimingFunction::Type::StepEnd;
|
||||
aResult = nsTimingFunction(type, array->Item(0).GetIntValue(),
|
||||
array->Item(1).GetIntValue() == -1 ?
|
||||
nsTimingFunction::Keyword::Implicit :
|
||||
nsTimingFunction::Keyword::Explicit);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -2462,15 +2462,24 @@ void nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
|
||||
{
|
||||
switch (aTimingFunctionType) {
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
|
||||
mType = StepStart;
|
||||
mSteps = 1;
|
||||
return;
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
|
||||
mType = StepEnd;
|
||||
mType = Type::StepStart;
|
||||
mStepSyntax = StepSyntax::Keyword;
|
||||
mSteps = 1;
|
||||
return;
|
||||
default:
|
||||
mType = Function;
|
||||
MOZ_ASSERT_UNREACHABLE("aTimingFunctionType must be a keyword value");
|
||||
// fall through
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
|
||||
mType = Type::StepEnd;
|
||||
mStepSyntax = StepSyntax::Keyword;
|
||||
mSteps = 1;
|
||||
return;
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE:
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR:
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN:
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT:
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT:
|
||||
mType = static_cast<Type>(aTimingFunctionType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1874,7 +1874,31 @@ struct nsStyleVisibility {
|
||||
};
|
||||
|
||||
struct nsTimingFunction {
|
||||
enum Type { Function, StepStart, StepEnd };
|
||||
|
||||
enum class Type {
|
||||
Ease, // ease
|
||||
Linear, // linear
|
||||
EaseIn, // ease-in
|
||||
EaseOut, // ease-out
|
||||
EaseInOut, // ease-in-out
|
||||
StepStart, // step-start and steps(..., start)
|
||||
StepEnd, // step-end, steps(..., end) and steps(...)
|
||||
CubicBezier, // cubic-bezier()
|
||||
};
|
||||
|
||||
enum class StepSyntax {
|
||||
Keyword, // step-start and step-end
|
||||
FunctionalWithoutKeyword, // steps(...)
|
||||
FunctionalWithStartKeyword, // steps(..., start)
|
||||
FunctionalWithEndKeyword, // steps(..., end)
|
||||
};
|
||||
|
||||
// Whether the timing function type is represented by a spline,
|
||||
// and thus will have mFunc filled in.
|
||||
static bool IsSplineType(Type aType)
|
||||
{
|
||||
return aType != Type::StepStart && aType != Type::StepEnd;
|
||||
}
|
||||
|
||||
explicit nsTimingFunction(int32_t aTimingFunctionType
|
||||
= NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)
|
||||
@ -1883,7 +1907,7 @@ struct nsTimingFunction {
|
||||
}
|
||||
|
||||
nsTimingFunction(float x1, float y1, float x2, float y2)
|
||||
: mType(Function)
|
||||
: mType(Type::CubicBezier)
|
||||
{
|
||||
mFunc.mX1 = x1;
|
||||
mFunc.mY1 = y1;
|
||||
@ -1891,11 +1915,23 @@ struct nsTimingFunction {
|
||||
mFunc.mY2 = y2;
|
||||
}
|
||||
|
||||
nsTimingFunction(Type aType, uint32_t aSteps)
|
||||
enum class Keyword { Implicit, Explicit };
|
||||
|
||||
nsTimingFunction(Type aType, uint32_t aSteps, Keyword aKeyword)
|
||||
: mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(mType == StepStart || mType == StepEnd, "wrong type");
|
||||
MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepEnd,
|
||||
"wrong type");
|
||||
mSteps = aSteps;
|
||||
if (mType == Type::StepStart) {
|
||||
MOZ_ASSERT(aKeyword == Keyword::Explicit,
|
||||
"only StepEnd can have an implicit keyword");
|
||||
mStepSyntax = StepSyntax::FunctionalWithStartKeyword;
|
||||
} else {
|
||||
mStepSyntax = aKeyword == Keyword::Explicit ?
|
||||
StepSyntax::FunctionalWithEndKeyword :
|
||||
StepSyntax::FunctionalWithoutKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
nsTimingFunction(const nsTimingFunction& aOther)
|
||||
@ -1911,7 +1947,10 @@ struct nsTimingFunction {
|
||||
float mX2;
|
||||
float mY2;
|
||||
} mFunc;
|
||||
uint32_t mSteps;
|
||||
struct {
|
||||
StepSyntax mStepSyntax;
|
||||
uint32_t mSteps;
|
||||
};
|
||||
};
|
||||
|
||||
nsTimingFunction&
|
||||
@ -1922,13 +1961,14 @@ struct nsTimingFunction {
|
||||
|
||||
mType = aOther.mType;
|
||||
|
||||
if (mType == Function) {
|
||||
if (HasSpline()) {
|
||||
mFunc.mX1 = aOther.mFunc.mX1;
|
||||
mFunc.mY1 = aOther.mFunc.mY1;
|
||||
mFunc.mX2 = aOther.mFunc.mX2;
|
||||
mFunc.mY2 = aOther.mFunc.mY2;
|
||||
} else {
|
||||
mSteps = aOther.mSteps;
|
||||
mStepSyntax = aOther.mStepSyntax;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -1939,11 +1979,12 @@ struct nsTimingFunction {
|
||||
if (mType != aOther.mType) {
|
||||
return false;
|
||||
}
|
||||
if (mType == Function) {
|
||||
if (HasSpline()) {
|
||||
return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
|
||||
mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
|
||||
}
|
||||
return mSteps == aOther.mSteps;
|
||||
return mSteps == aOther.mSteps &&
|
||||
mStepSyntax == aOther.mStepSyntax;
|
||||
}
|
||||
|
||||
bool operator!=(const nsTimingFunction& aOther) const
|
||||
@ -1951,6 +1992,8 @@ struct nsTimingFunction {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
bool HasSpline() const { return IsSplineType(mType); }
|
||||
|
||||
private:
|
||||
void AssignFromKeyword(int32_t aTimingFunctionType);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user