mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Bug 1496619 - Part 1: Drop frames() timing function r=birtles
frames() timing function was removed from the spec, so we drop it. Besides, some devtool tests are removed because they use frame(). I will add them back by using new step function later. Differential Revision: https://phabricator.services.mozilla.com/D9309 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
185c47a7b2
commit
adff31eff9
@ -25,27 +25,6 @@ const TEST_DATA = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
targetClass: "frames-keyframe",
|
||||
properties: [
|
||||
{
|
||||
name: "opacity",
|
||||
computedValuePathClass: "distance-path",
|
||||
expectedPathSegments: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 199, y: 0 },
|
||||
{ x: 200, y: 25 },
|
||||
{ x: 399, y: 25 },
|
||||
{ x: 400, y: 50 },
|
||||
{ x: 599, y: 50 },
|
||||
{ x: 600, y: 75 },
|
||||
{ x: 799, y: 75 },
|
||||
{ x: 800, y: 100 },
|
||||
{ x: 1000, y: 100 },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
targetClass: "narrow-offsets",
|
||||
properties: [
|
||||
|
@ -44,7 +44,7 @@
|
||||
{ opacity: 1 },
|
||||
{ opacity: 0 },
|
||||
],
|
||||
"frames(5)"
|
||||
"steps(5)"
|
||||
);
|
||||
|
||||
createAnimation(
|
||||
|
@ -149,19 +149,6 @@
|
||||
"steps(2)"
|
||||
);
|
||||
|
||||
createAnimation(
|
||||
"frames-keyframe",
|
||||
[
|
||||
{
|
||||
easing: "frames(5)",
|
||||
opacity: 0,
|
||||
},
|
||||
{
|
||||
opacity: 1,
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
createAnimation(
|
||||
"narrow-offsets",
|
||||
[
|
||||
|
@ -49,9 +49,7 @@ const closeAnimationInspector = async function() {
|
||||
|
||||
/**
|
||||
* Some animation features are not enabled by default in release/beta channels
|
||||
* yet including:
|
||||
* * parts of the Web Animations API (Bug 1264101), and
|
||||
* * the frames() timing function (Bug 1379582).
|
||||
* yet including parts of the Web Animations API.
|
||||
*/
|
||||
const enableAnimationFeatures = function() {
|
||||
return new Promise(resolve => {
|
||||
@ -60,7 +58,6 @@ const enableAnimationFeatures = function() {
|
||||
["dom.animations-api.getAnimations.enabled", true],
|
||||
["dom.animations-api.implicit-keyframes.enabled", true],
|
||||
["dom.animations-api.timelines.enabled", true],
|
||||
["layout.css.frames-timing.enabled", true],
|
||||
]}, resolve);
|
||||
});
|
||||
};
|
||||
|
@ -41,7 +41,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"forwards",
|
||||
"frames",
|
||||
"infinite",
|
||||
"inherit",
|
||||
"initial",
|
||||
@ -167,7 +166,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -1230,7 +1228,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -1293,7 +1290,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -1496,7 +1492,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"forwards",
|
||||
"frames",
|
||||
"infinite",
|
||||
"inherit",
|
||||
"initial",
|
||||
@ -1622,7 +1617,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -2678,7 +2672,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -2741,7 +2734,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -3203,7 +3195,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"forwards",
|
||||
"frames",
|
||||
"infinite",
|
||||
"inherit",
|
||||
"initial",
|
||||
@ -3329,7 +3320,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -8991,7 +8981,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
@ -9054,7 +9043,6 @@ exports.CSS_PROPERTIES = {
|
||||
"ease-in",
|
||||
"ease-in-out",
|
||||
"ease-out",
|
||||
"frames",
|
||||
"inherit",
|
||||
"initial",
|
||||
"linear",
|
||||
|
@ -18,7 +18,7 @@ ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
|
||||
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
|
||||
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
|
||||
} else {
|
||||
mStepsOrFrames = aFunction.mStepsOrFrames;
|
||||
mSteps = aFunction.mSteps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,22 +61,6 @@ StepTiming(uint32_t aSteps,
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline double
|
||||
FramesTiming(uint32_t aFrames, double aPortion)
|
||||
{
|
||||
MOZ_ASSERT(aFrames > 1, "the number of frames must be greater than 1");
|
||||
int32_t currentFrame = floor(aPortion * aFrames);
|
||||
double result = double(currentFrame) / double(aFrames - 1);
|
||||
|
||||
// Don't overshoot the natural range of the animation (by producing an output
|
||||
// progress greater than 1.0) when we are at the exact end of its interval
|
||||
// (i.e. the input progress is 1.0).
|
||||
if (result > 1.0 && aPortion <= 1.0) {
|
||||
return 1.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double
|
||||
ComputedTimingFunction::GetValue(
|
||||
double aPortion,
|
||||
@ -128,9 +112,7 @@ ComputedTimingFunction::GetValue(
|
||||
return mTimingFunction.GetSplineValue(aPortion);
|
||||
}
|
||||
|
||||
return mType == nsTimingFunction::Type::Frames
|
||||
? FramesTiming(mStepsOrFrames, aPortion)
|
||||
: StepTiming(mStepsOrFrames, aPortion, aBeforeFlag, mType);
|
||||
return StepTiming(mSteps, aPortion, aBeforeFlag, mType);
|
||||
}
|
||||
|
||||
int32_t
|
||||
@ -146,10 +128,9 @@ ComputedTimingFunction::Compare(const ComputedTimingFunction& aRhs) const
|
||||
return order;
|
||||
}
|
||||
} else if (mType == nsTimingFunction::Type::StepStart ||
|
||||
mType == nsTimingFunction::Type::StepEnd ||
|
||||
mType == nsTimingFunction::Type::Frames) {
|
||||
if (mStepsOrFrames != aRhs.mStepsOrFrames) {
|
||||
return int32_t(mStepsOrFrames) - int32_t(aRhs.mStepsOrFrames);
|
||||
mType == nsTimingFunction::Type::StepEnd) {
|
||||
if (mSteps != aRhs.mSteps) {
|
||||
return int32_t(mSteps) - int32_t(aRhs.mSteps);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,10 +150,7 @@ ComputedTimingFunction::AppendToString(nsAString& aResult) const
|
||||
break;
|
||||
case nsTimingFunction::Type::StepStart:
|
||||
case nsTimingFunction::Type::StepEnd:
|
||||
nsStyleUtil::AppendStepsTimingFunction(mType, mStepsOrFrames, aResult);
|
||||
break;
|
||||
case nsTimingFunction::Type::Frames:
|
||||
nsStyleUtil::AppendFramesTimingFunction(mStepsOrFrames, aResult);
|
||||
nsStyleUtil::AppendStepsTimingFunction(mType, mSteps, aResult);
|
||||
break;
|
||||
default:
|
||||
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(mType, aResult);
|
||||
|
@ -35,16 +35,10 @@ public:
|
||||
MOZ_ASSERT(aSteps > 0, "The number of steps should be 1 or more");
|
||||
return ComputedTimingFunction(aType, aSteps);
|
||||
}
|
||||
static ComputedTimingFunction
|
||||
Frames(uint32_t aFrames)
|
||||
{
|
||||
MOZ_ASSERT(aFrames > 1, "The number of frames should be 2 or more");
|
||||
return ComputedTimingFunction(nsTimingFunction::Type::Frames, aFrames);
|
||||
}
|
||||
|
||||
ComputedTimingFunction() = default;
|
||||
explicit ComputedTimingFunction(const nsTimingFunction& aFunction)
|
||||
: mStepsOrFrames(0)
|
||||
: mSteps(0)
|
||||
{
|
||||
Init(aFunction);
|
||||
}
|
||||
@ -68,19 +62,14 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(mType == nsTimingFunction::Type::StepStart ||
|
||||
mType == nsTimingFunction::Type::StepEnd);
|
||||
return mStepsOrFrames;
|
||||
}
|
||||
uint32_t GetFrames() const
|
||||
{
|
||||
MOZ_ASSERT(mType == nsTimingFunction::Type::Frames);
|
||||
return mStepsOrFrames;
|
||||
return mSteps;
|
||||
}
|
||||
bool operator==(const ComputedTimingFunction& aOther) const
|
||||
{
|
||||
return mType == aOther.mType &&
|
||||
(HasSpline() ?
|
||||
mTimingFunction == aOther.mTimingFunction :
|
||||
mStepsOrFrames == aOther.mStepsOrFrames);
|
||||
mSteps == aOther.mSteps);
|
||||
}
|
||||
bool operator!=(const ComputedTimingFunction& aOther) const
|
||||
{
|
||||
@ -94,7 +83,7 @@ public:
|
||||
mTimingFunction.Y1() == aOther.mFunc.mY1 &&
|
||||
mTimingFunction.X2() == aOther.mFunc.mX2 &&
|
||||
mTimingFunction.Y2() == aOther.mFunc.mY2
|
||||
: mStepsOrFrames == aOther.mStepsOrFrames);
|
||||
: mSteps == aOther.mSteps);
|
||||
}
|
||||
bool operator!=(const nsTimingFunction& aOther) const
|
||||
{
|
||||
@ -116,16 +105,16 @@ private:
|
||||
ComputedTimingFunction(double x1, double y1, double x2, double y2)
|
||||
: mType(nsTimingFunction::Type::CubicBezier)
|
||||
, mTimingFunction(x1, y1, x2, y2)
|
||||
, mStepsOrFrames(0)
|
||||
, mSteps(0)
|
||||
{
|
||||
}
|
||||
ComputedTimingFunction(nsTimingFunction::Type aType, uint32_t aStepsOrFrames)
|
||||
ComputedTimingFunction(nsTimingFunction::Type aType, uint32_t aSteps)
|
||||
: mType(aType)
|
||||
, mStepsOrFrames(aStepsOrFrames) { }
|
||||
, mSteps(aSteps) { }
|
||||
|
||||
nsTimingFunction::Type mType = nsTimingFunction::Type::Linear;
|
||||
nsSMILKeySpline mTimingFunction;
|
||||
uint32_t mStepsOrFrames;
|
||||
uint32_t mSteps;
|
||||
};
|
||||
|
||||
inline bool
|
||||
|
@ -31,10 +31,6 @@ AnimationUtils::TimingFunctionToComputedTimingFunction(
|
||||
nsTimingFunction::Type::StepEnd;
|
||||
return Some(ComputedTimingFunction::Steps(type, sf.steps()));
|
||||
}
|
||||
case TimingFunction::TFramesFunction: {
|
||||
FramesFunction ff = aTimingFunction.get_FramesFunction();
|
||||
return Some(ComputedTimingFunction::Frames(ff.frames()));
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Function must be null, bezier, step or frames");
|
||||
|
@ -100,15 +100,10 @@ struct StepFunction {
|
||||
int type;
|
||||
};
|
||||
|
||||
struct FramesFunction {
|
||||
int frames;
|
||||
};
|
||||
|
||||
union TimingFunction {
|
||||
null_t;
|
||||
CubicBezierFunction;
|
||||
StepFunction;
|
||||
FramesFunction;
|
||||
};
|
||||
|
||||
// Send the angle with units rather than sending all angles in radians
|
||||
|
@ -121,7 +121,7 @@ function do_test() {
|
||||
var prop = "-moz-transition";
|
||||
var values = InspectorUtils.getCSSValuesForProperty(prop);
|
||||
var expected = [ "initial", "all", "unset", "cubic-bezier", "ease", "ease-in", "ease-in-out",
|
||||
"ease-out", "frames", "inherit", "linear", "none", "step-end", "step-start",
|
||||
"ease-out", "inherit", "linear", "none", "step-end", "step-start",
|
||||
"steps" ];
|
||||
ok(testValues(values, expected), "property -moz-transition's values.");
|
||||
|
||||
|
@ -420,10 +420,6 @@ ToTimingFunction(const Maybe<ComputedTimingFunction>& aCTF)
|
||||
spline->X1(), spline->Y1(), spline->X2(), spline->Y2()));
|
||||
}
|
||||
|
||||
if (aCTF->GetType() == nsTimingFunction::Type::Frames) {
|
||||
return TimingFunction(FramesFunction(aCTF->GetFrames()));
|
||||
}
|
||||
|
||||
uint32_t type = aCTF->GetType() == nsTimingFunction::Type::StepStart ? 1 : 2;
|
||||
return TimingFunction(StepFunction(aCTF->GetSteps(), type));
|
||||
}
|
||||
|
@ -4594,13 +4594,9 @@ nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList,
|
||||
case nsTimingFunction::Type::StepStart:
|
||||
case nsTimingFunction::Type::StepEnd:
|
||||
nsStyleUtil::AppendStepsTimingFunction(aTimingFunction.mType,
|
||||
aTimingFunction.mStepsOrFrames,
|
||||
aTimingFunction.mSteps,
|
||||
tmp);
|
||||
break;
|
||||
case nsTimingFunction::Type::Frames:
|
||||
nsStyleUtil::AppendFramesTimingFunction(aTimingFunction.mStepsOrFrames,
|
||||
tmp);
|
||||
break;
|
||||
default:
|
||||
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(aTimingFunction.mType,
|
||||
tmp);
|
||||
|
@ -3324,13 +3324,13 @@ nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
|
||||
switch (aTimingFunctionType) {
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
|
||||
mType = Type::StepStart;
|
||||
mStepsOrFrames = 1;
|
||||
mSteps = 1;
|
||||
return;
|
||||
default:
|
||||
MOZ_FALLTHROUGH_ASSERT("aTimingFunctionType must be a keyword value");
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
|
||||
mType = Type::StepEnd;
|
||||
mStepsOrFrames = 1;
|
||||
mSteps = 1;
|
||||
return;
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE:
|
||||
case NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR:
|
||||
|
@ -291,15 +291,6 @@ nsStyleUtil::AppendStepsTimingFunction(nsTimingFunction::Type aType,
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsStyleUtil::AppendFramesTimingFunction(uint32_t aFrames,
|
||||
nsAString& aResult)
|
||||
{
|
||||
aResult.AppendLiteral("frames(");
|
||||
aResult.AppendInt(aFrames);
|
||||
aResult.AppendLiteral(")");
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsStyleUtil::AppendCubicBezierTimingFunction(float aX1, float aY1,
|
||||
float aX2, float aY2,
|
||||
|
@ -79,8 +79,6 @@ public:
|
||||
static void AppendStepsTimingFunction(nsTimingFunction::Type aType,
|
||||
uint32_t aSteps,
|
||||
nsAString& aResult);
|
||||
static void AppendFramesTimingFunction(uint32_t aFrames,
|
||||
nsAString& aResult);
|
||||
static void AppendCubicBezierTimingFunction(float aX1, float aY1,
|
||||
float aX2, float aY2,
|
||||
nsAString& aResult);
|
||||
|
@ -20,16 +20,13 @@ struct nsTimingFunction
|
||||
StepStart, // step-start and steps(..., start)
|
||||
StepEnd, // step-end, steps(..., end) and steps(...)
|
||||
CubicBezier, // cubic-bezier()
|
||||
Frames, // frames()
|
||||
};
|
||||
|
||||
// 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 &&
|
||||
aType != Type::Frames;
|
||||
return aType != Type::StepStart && aType != Type::StepEnd;
|
||||
}
|
||||
|
||||
explicit nsTimingFunction(
|
||||
@ -51,14 +48,12 @@ struct nsTimingFunction
|
||||
|
||||
enum class Keyword { Implicit, Explicit };
|
||||
|
||||
nsTimingFunction(Type aType, uint32_t aStepsOrFrames)
|
||||
nsTimingFunction(Type aType, uint32_t aSteps)
|
||||
: mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(mType == Type::StepStart ||
|
||||
mType == Type::StepEnd ||
|
||||
mType == Type::Frames,
|
||||
MOZ_ASSERT(mType == Type::StepStart || mType == Type::StepEnd,
|
||||
"wrong type");
|
||||
mStepsOrFrames = aStepsOrFrames;
|
||||
mSteps = aSteps;
|
||||
}
|
||||
|
||||
nsTimingFunction(const nsTimingFunction& aOther)
|
||||
@ -75,7 +70,7 @@ struct nsTimingFunction
|
||||
float mY2;
|
||||
} mFunc;
|
||||
struct {
|
||||
uint32_t mStepsOrFrames;
|
||||
uint32_t mSteps;
|
||||
};
|
||||
};
|
||||
|
||||
@ -94,7 +89,7 @@ struct nsTimingFunction
|
||||
mFunc.mX2 = aOther.mFunc.mX2;
|
||||
mFunc.mY2 = aOther.mFunc.mY2;
|
||||
} else {
|
||||
mStepsOrFrames = aOther.mStepsOrFrames;
|
||||
mSteps = aOther.mSteps;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -109,7 +104,7 @@ struct nsTimingFunction
|
||||
return mFunc.mX1 == aOther.mFunc.mX1 && mFunc.mY1 == aOther.mFunc.mY1 &&
|
||||
mFunc.mX2 == aOther.mFunc.mX2 && mFunc.mY2 == aOther.mFunc.mY2;
|
||||
}
|
||||
return mStepsOrFrames == aOther.mStepsOrFrames;
|
||||
return mSteps == aOther.mSteps;
|
||||
}
|
||||
|
||||
bool operator!=(const nsTimingFunction& aOther) const
|
||||
|
@ -6439,14 +6439,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.font-variations.enabled")) {
|
||||
.push("'vert' calc(2.5)");
|
||||
}
|
||||
|
||||
if (IsCSSPropertyPrefEnabled("layout.css.frames-timing.enabled")) {
|
||||
gCSSProperties["animation-timing-function"].other_values.push(
|
||||
"frames(2)", "frames(1000)", "frames( 2 )");
|
||||
gCSSProperties["animation-timing-function"].invalid_values.push(
|
||||
"frames(1)", "frames(-2)", "frames", "frames()", "frames(,)",
|
||||
"frames(a)", "frames(2.0)", "frames(2.5)", "frames(2 3)");
|
||||
}
|
||||
|
||||
if (IsCSSPropertyPrefEnabled("svg.transform-box.enabled")) {
|
||||
gCSSProperties["transform-box"] = {
|
||||
domProp: "transformBox",
|
||||
|
@ -678,19 +678,6 @@ VARCACHE_PREF(
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// Is support for the frames() timing function enabled?
|
||||
#ifdef RELEASE_OR_BETA
|
||||
# define PREF_VALUE false
|
||||
#else
|
||||
# define PREF_VALUE true
|
||||
#endif
|
||||
VARCACHE_PREF(
|
||||
"layout.css.frames-timing.enabled",
|
||||
layout_css_frames_timing_enabled,
|
||||
bool, PREF_VALUE
|
||||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
// Should the :visited selector ever match (otherwise :link matches instead)?
|
||||
VARCACHE_PREF(
|
||||
"layout.css.visited_links_enabled",
|
||||
|
@ -369,22 +369,6 @@ impl PropertyAnimation {
|
||||
GenericTimingFunction::Steps(steps, StepPosition::End) => {
|
||||
(time * (steps as f64)).floor() / (steps as f64)
|
||||
},
|
||||
GenericTimingFunction::Frames(frames) => {
|
||||
// https://drafts.csswg.org/css-timing/#frames-timing-functions
|
||||
let mut out = (time * (frames as f64)).floor() / ((frames - 1) as f64);
|
||||
if out > 1.0 {
|
||||
// FIXME: Basically, during the animation sampling process, the input progress
|
||||
// should be in the range of [0, 1]. However, |time| is not accurate enough
|
||||
// here, which means |time| could be larger than 1.0 in the last animation
|
||||
// frame. (It should be equal to 1.0 exactly.) This makes the output of frames
|
||||
// timing function jumps to the next frame/level.
|
||||
// However, this solution is still not correct because |time| is possible
|
||||
// outside the range of [0, 1] after introducing Web Animations. We should fix
|
||||
// this problem when implementing web animations.
|
||||
out = 1.0;
|
||||
}
|
||||
out
|
||||
},
|
||||
GenericTimingFunction::Keyword(keyword) => {
|
||||
let (x1, x2, y1, y2) = keyword.to_bezier();
|
||||
Bezier::new(x1, x2, y1, y2).solve(time, epsilon)
|
||||
|
@ -22,17 +22,7 @@ impl nsTimingFunction {
|
||||
self.__bindgen_anon_1
|
||||
.__bindgen_anon_1
|
||||
.as_mut()
|
||||
.mStepsOrFrames = steps;
|
||||
}
|
||||
}
|
||||
|
||||
fn set_as_frames(&mut self, frames: u32) {
|
||||
self.mType = nsTimingFunction_Type::Frames;
|
||||
unsafe {
|
||||
self.__bindgen_anon_1
|
||||
.__bindgen_anon_1
|
||||
.as_mut()
|
||||
.mStepsOrFrames = frames;
|
||||
.mSteps = steps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,10 +64,6 @@ impl From<TimingFunction> for nsTimingFunction {
|
||||
debug_assert!(steps.value() >= 0);
|
||||
tf.set_as_step(nsTimingFunction_Type::StepEnd, steps.value() as u32);
|
||||
},
|
||||
GenericTimingFunction::Frames(frames) => {
|
||||
debug_assert!(frames.value() >= 2);
|
||||
tf.set_as_frames(frames.value() as u32);
|
||||
},
|
||||
GenericTimingFunction::CubicBezier { x1, y1, x2, y2 } => {
|
||||
tf.set_as_bezier(
|
||||
nsTimingFunction_Type::CubicBezier,
|
||||
@ -105,7 +91,7 @@ impl From<nsTimingFunction> for ComputedTimingFunction {
|
||||
.__bindgen_anon_1
|
||||
.__bindgen_anon_1
|
||||
.as_ref()
|
||||
.mStepsOrFrames
|
||||
.mSteps
|
||||
},
|
||||
StepPosition::Start,
|
||||
),
|
||||
@ -115,17 +101,10 @@ impl From<nsTimingFunction> for ComputedTimingFunction {
|
||||
.__bindgen_anon_1
|
||||
.__bindgen_anon_1
|
||||
.as_ref()
|
||||
.mStepsOrFrames
|
||||
.mSteps
|
||||
},
|
||||
StepPosition::End,
|
||||
),
|
||||
nsTimingFunction_Type::Frames => GenericTimingFunction::Frames(unsafe {
|
||||
function
|
||||
.__bindgen_anon_1
|
||||
.__bindgen_anon_1
|
||||
.as_ref()
|
||||
.mStepsOrFrames
|
||||
}),
|
||||
nsTimingFunction_Type::Ease => GenericTimingFunction::Keyword(TimingKeyword::Ease),
|
||||
nsTimingFunction_Type::Linear => GenericTimingFunction::Keyword(TimingKeyword::Linear),
|
||||
nsTimingFunction_Type::EaseIn => GenericTimingFunction::Keyword(TimingKeyword::EaseIn),
|
||||
|
@ -92,7 +92,7 @@ pub struct TransformOrigin<H, V, Depth> {
|
||||
|
||||
/// A generic timing function.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-timing-1/#single-timing-function-production>
|
||||
/// https://drafts.csswg.org/css-easing-1/#timing-functions
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)]
|
||||
#[value_info(ty = "TIMING_FUNCTION")]
|
||||
pub enum TimingFunction<Integer, Number> {
|
||||
@ -111,9 +111,6 @@ pub enum TimingFunction<Integer, Number> {
|
||||
#[css(comma, function)]
|
||||
#[value_info(other_values = "step-start,step-end")]
|
||||
Steps(Integer, #[css(skip_if = "is_end")] StepPosition),
|
||||
/// `frames(<integer>)`
|
||||
#[css(comma, function)]
|
||||
Frames(Integer),
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
|
@ -350,19 +350,6 @@ impl<S> OriginComponent<S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
#[inline]
|
||||
fn allow_frames_timing() -> bool {
|
||||
use gecko_bindings::structs::mozilla;
|
||||
unsafe { mozilla::StaticPrefs_sVarCache_layout_css_frames_timing_enabled }
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[inline]
|
||||
fn allow_frames_timing() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Parse for TimingFunction {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
@ -406,14 +393,6 @@ impl Parse for TimingFunction {
|
||||
}).unwrap_or(StepPosition::End);
|
||||
Ok(generic::TimingFunction::Steps(steps, position))
|
||||
},
|
||||
"frames" => {
|
||||
if allow_frames_timing() {
|
||||
let frames = Integer::parse_with_minimum(context, i, 2)?;
|
||||
Ok(generic::TimingFunction::Frames(frames))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
},
|
||||
_ => Err(()),
|
||||
}).map_err(|()| {
|
||||
location.new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone()))
|
||||
@ -440,9 +419,6 @@ impl ToComputedValue for TimingFunction {
|
||||
generic::TimingFunction::Steps(steps, position) => {
|
||||
generic::TimingFunction::Steps(steps.to_computed_value(context) as u32, position)
|
||||
},
|
||||
generic::TimingFunction::Frames(frames) => {
|
||||
generic::TimingFunction::Frames(frames.to_computed_value(context) as u32)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,9 +441,6 @@ impl ToComputedValue for TimingFunction {
|
||||
Integer::from_computed_value(&(steps as i32)),
|
||||
position,
|
||||
),
|
||||
generic::TimingFunction::Frames(frames) => {
|
||||
generic::TimingFunction::Frames(Integer::from_computed_value(&(frames as i32)))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
prefs: [dom.animations-api.core.enabled:true, layout.css.frames-timing.enabled:true]
|
||||
prefs: [dom.animations-api.core.enabled:true]
|
||||
|
@ -1 +1 @@
|
||||
prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.frames-timing.enabled:true]
|
||||
prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.core.enabled:true, dom.animations-api.getAnimations.enabled:true, dom.animations-api.implicit-keyframes.enabled:true, dom.animations-api.timelines.enabled:true]
|
||||
|
@ -1,152 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<meta name="assert"
|
||||
content="This test checks the output of frame timing functions with different frame numbers" />
|
||||
<title>Frames timing function output tests</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/css-timing/#frames-timing-functions">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { left: 0px; }
|
||||
to { left: 100px; }
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'anim 10s frames(2) forwards';
|
||||
assert_equals(getComputedStyle(div).left, '0px');
|
||||
}, 'For an input progress of 0.0, the output of a frames timing function is ' +
|
||||
'the first frame');
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'anim 10s frames(2) forwards';
|
||||
|
||||
div.style.animationDelay = '-4999ms';
|
||||
assert_equals(getComputedStyle(div).left, '0px');
|
||||
div.style.animationDelay = '-5000ms';
|
||||
assert_equals(getComputedStyle(div).left, '100px');
|
||||
}, 'At a frame boundary, the output of a frames timing function is the next ' +
|
||||
'frame');
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'anim 10s frames(2) forwards';
|
||||
|
||||
div.style.animationDelay = '-10s';
|
||||
assert_equals(getComputedStyle(div).left, '100px');
|
||||
}, 'For an input progress of 1.0, the output of a frames timing function is ' +
|
||||
'the final frame');
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'anim 11s frames(11) forwards';
|
||||
|
||||
// We have 11 frames in 11s, so the first step happens at 1.0.
|
||||
div.style.animationDelay = '-999ms';
|
||||
assert_equals(getComputedStyle(div).left, '0px');
|
||||
div.style.animationDelay = '-1000ms';
|
||||
assert_equals(getComputedStyle(div).left, '10px');
|
||||
}, 'The number of frames is correctly reflected in the frames timing ' +
|
||||
'function output');
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.transition = 'left 11s frames(11)';
|
||||
|
||||
// We have 11 frames in 11s, so the first step happens at 1.0.
|
||||
div.style.left = '0px';
|
||||
div.style.transitionDelay = '-999ms';
|
||||
getComputedStyle(div).left;
|
||||
div.style.left = '100px';
|
||||
assert_equals(getComputedStyle(div).left, '0px');
|
||||
|
||||
div.style.left = '0px';
|
||||
div.style.transitionDelay = '-1000ms';
|
||||
getComputedStyle(div).left;
|
||||
div.style.left = '100px';
|
||||
assert_equals(getComputedStyle(div).left, '10px');
|
||||
}, 'The number of frames is correctly reflected in the frames timing ' +
|
||||
'function output on CSS Transitions');
|
||||
|
||||
test(function(t) {
|
||||
var target = createDiv(t);
|
||||
target.style.position = 'absolute';
|
||||
var anim = target.animate([ { left: '0px', easing: 'frames(2)' },
|
||||
{ left: '100px' } ],
|
||||
{ duration: 1000,
|
||||
fill: 'forwards',
|
||||
easing: 'cubic-bezier(0, 1.5, 1, 1.5)' });
|
||||
|
||||
// The bezier function produces values between 0.5 and 1 in
|
||||
// (~0.0442, 0.23368), and values between 1 and 2 in (0.23368794, 1).
|
||||
anim.currentTime = 0;
|
||||
assert_equals(getComputedStyle(target).left, '0px');
|
||||
anim.currentTime = 45;
|
||||
assert_equals(getComputedStyle(target).left, '100px');
|
||||
anim.currentTime = 230;
|
||||
assert_equals(getComputedStyle(target).left, '100px');
|
||||
anim.currentTime = 250;
|
||||
assert_equals(getComputedStyle(target).left, '200px');
|
||||
anim.currentTime = 1000;
|
||||
assert_equals(getComputedStyle(target).left, '100px');
|
||||
}, 'frames easing with input progress greater than 1');
|
||||
|
||||
test(function(t) {
|
||||
var target = createDiv(t);
|
||||
target.style.position = 'absolute';
|
||||
var anim = target.animate([ { left: '0px', easing: 'frames(2)' },
|
||||
{ left: '100px' } ],
|
||||
{ duration: 1000,
|
||||
fill: 'forwards',
|
||||
easing: 'cubic-bezier(0, 3, 1, 3)' });
|
||||
|
||||
// The bezier funciton produces values:
|
||||
// Input -> Output
|
||||
// 0.0 0.0
|
||||
// 0.114 ~ 0.245 1.5~2.0, so frames(2) is 3.0
|
||||
// 0.245 ~ 0.6 2.0~2.4, so frames(2) is 4.0
|
||||
// 0.6 ~ 0.882 2.4~2.0, so frames(2) is 4.0
|
||||
// 0.882 ~ 0.976 2.0~1.5, so frames(2) is 3.0
|
||||
// 1.0 1.0
|
||||
anim.currentTime = 0;
|
||||
assert_equals(getComputedStyle(target).left, '0px');
|
||||
anim.currentTime = 114;
|
||||
assert_equals(getComputedStyle(target).left, '300px');
|
||||
anim.currentTime = 500;
|
||||
assert_equals(getComputedStyle(target).left, '400px');
|
||||
anim.currentTime = 900;
|
||||
assert_equals(getComputedStyle(target).left, '300px');
|
||||
}, 'frames easing with input progress greater than 1.5');
|
||||
|
||||
test(function(t) {
|
||||
var target = createDiv(t);
|
||||
target.style.position = 'absolute';
|
||||
var anim = target.animate([ { left: '0px', easing: 'frames(2)' },
|
||||
{ left: '100px' } ],
|
||||
{ duration: 1000,
|
||||
fill: 'forwards',
|
||||
easing: 'cubic-bezier(0, -0.5, 1, -0.5)' });
|
||||
|
||||
// The bezier function produces negative values (but always greater than -0.5)
|
||||
// in (0, 0.766312060).
|
||||
anim.currentTime = 0;
|
||||
assert_equals(getComputedStyle(target).left, '0px');
|
||||
anim.currentTime = 750;
|
||||
assert_equals(getComputedStyle(target).left, '-100px');
|
||||
anim.currentTime = 800;
|
||||
assert_equals(getComputedStyle(target).left, '0px');
|
||||
anim.currentTime = 1000;
|
||||
assert_equals(getComputedStyle(target).left, '100px');
|
||||
}, 'frames easing with input progress less than 0');
|
||||
|
||||
</script>
|
||||
</body>
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<meta name="assert"
|
||||
content="This test checks the syntax output of frame timing functions" />
|
||||
<title>Frames timing function syntax tests</title>
|
||||
<link rel="help"
|
||||
href="https://drafts.csswg.org/css-timing/#frames-timing-functions">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'abc 1s ease-in';
|
||||
div.style.animationTimingFunction = 'frames(1)';
|
||||
assert_equals(getComputedStyle(div).animationTimingFunction, 'ease-in');
|
||||
}, 'The number of frames must be a positive integer greater than 1, or we ' +
|
||||
'fallback to the previously-set easing');
|
||||
|
||||
test(function(t) {
|
||||
const div = createDiv(t);
|
||||
div.style.animation = 'abc 1s frames( 2 )';
|
||||
assert_equals(getComputedStyle(div).animationTimingFunction, 'frames(2)');
|
||||
}, 'The serialization of frames is \'frames(n)\', n is the number of frames');
|
||||
|
||||
</script>
|
||||
</body>
|
@ -24,7 +24,7 @@ runListValuedPropertyTests('animation-timing-function', [
|
||||
]);
|
||||
|
||||
runUnsupportedPropertyTests('animation-timing-function', [
|
||||
'cubic-bezier(0.1, 0.7, 1.0, 0.1)', 'steps(4, end)', 'frames(10)'
|
||||
'cubic-bezier(0.1, 0.7, 1.0, 0.1)', 'steps(4, end)'
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
@ -24,7 +24,7 @@ runListValuedPropertyTests('transition-timing-function', [
|
||||
]);
|
||||
|
||||
runUnsupportedPropertyTests('transition-timing-function', [
|
||||
'cubic-bezier(0.1, 0.7, 1.0, 0.1)', 'steps(4, end)', 'frames(10)'
|
||||
'cubic-bezier(0.1, 0.7, 1.0, 0.1)', 'steps(4, end)'
|
||||
]);
|
||||
|
||||
</script>
|
||||
|
@ -40,11 +40,6 @@ const gEasingTests = [
|
||||
easingFunction: stepEnd(2),
|
||||
serialization: 'steps(2)'
|
||||
},
|
||||
{
|
||||
desc: 'frames function',
|
||||
easing: 'frames(5)',
|
||||
easingFunction: framesTiming(5)
|
||||
},
|
||||
{
|
||||
desc: 'linear function',
|
||||
easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0)
|
||||
@ -111,14 +106,6 @@ const gInvalidEasings = [
|
||||
'function (a){return a}',
|
||||
'function (x){return x}',
|
||||
'function(x, y){return 0.3}',
|
||||
'frames(1)',
|
||||
'frames',
|
||||
'frames()',
|
||||
'frames(,)',
|
||||
'frames(a)',
|
||||
'frames(2.0)',
|
||||
'frames(2.5)',
|
||||
'frames(2 3)',
|
||||
];
|
||||
|
||||
// Easings that should serialize to the same string
|
||||
@ -131,5 +118,4 @@ const gRoundtripEasings = [
|
||||
'cubic-bezier(0.1, 5, 0.23, 0)',
|
||||
'steps(3, start)',
|
||||
'steps(3)',
|
||||
'frames(3)',
|
||||
];
|
||||
|
@ -150,13 +150,6 @@ function stepStart(nsteps) {
|
||||
};
|
||||
}
|
||||
|
||||
function framesTiming(nframes) {
|
||||
return x => {
|
||||
const result = Math.floor(x * nframes) / (nframes - 1);
|
||||
return (result > 1.0 && x <= 1.0) ? 1.0 : result;
|
||||
};
|
||||
}
|
||||
|
||||
function waitForAnimationFrames(frameCount) {
|
||||
return new Promise(resolve => {
|
||||
function handleFrame() {
|
||||
|
@ -32,10 +32,9 @@ for (const params of gEasingTests) {
|
||||
}, `Transformed progress for ${params.desc}`);
|
||||
}
|
||||
|
||||
// Additional tests for various boundary conditions of step timing functions and
|
||||
// frames timing functions.
|
||||
// Additional tests for various boundary conditions of step timing functions.
|
||||
|
||||
const gStepAndFramesTimingFunctionTests = [
|
||||
const gStepTimingFunctionTests = [
|
||||
{
|
||||
description: 'Test bounds point of step-start easing',
|
||||
effect: {
|
||||
@ -254,44 +253,9 @@ const gStepAndFramesTimingFunctionTests = [
|
||||
{ currentTime: 2500, progress: 0.5 },
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Test bounds point of frames easing',
|
||||
effect: {
|
||||
delay: 1000,
|
||||
duration: 1000,
|
||||
fill: 'both',
|
||||
easing: 'frames(2)'
|
||||
},
|
||||
conditions: [
|
||||
{ currentTime: 0, progress: 0 },
|
||||
{ currentTime: 1000, progress: 0 },
|
||||
{ currentTime: 1499, progress: 0 },
|
||||
{ currentTime: 1500, progress: 1 },
|
||||
{ currentTime: 2000, progress: 1 }
|
||||
]
|
||||
},
|
||||
{
|
||||
description: 'Test bounds point of frames easing ' +
|
||||
'with iterationStart and delay',
|
||||
effect: {
|
||||
delay: 1000,
|
||||
duration: 1000,
|
||||
fill: 'both',
|
||||
iterationStart: 0.5,
|
||||
easing: 'frames(2)'
|
||||
},
|
||||
conditions: [
|
||||
{ currentTime: 0, progress: 1 },
|
||||
{ currentTime: 1000, progress: 1 },
|
||||
{ currentTime: 1499, progress: 1 },
|
||||
{ currentTime: 1500, progress: 0 },
|
||||
{ currentTime: 1999, progress: 0 },
|
||||
{ currentTime: 2000, progress: 1 }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
for (const options of gStepAndFramesTimingFunctionTests) {
|
||||
for (const options of gStepTimingFunctionTests) {
|
||||
test(t => {
|
||||
const target = createDiv(t);
|
||||
const animation = target.animate(null, options.effect);
|
||||
|
Loading…
Reference in New Issue
Block a user