зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1764126 - Part 5: Enable `linear(...)` timing function on C++ side, r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D148791
This commit is contained in:
Родитель
d3f7b3772d
Коммит
562eecc50f
|
@ -45,8 +45,9 @@ ComputedTimingFunction::Function ComputedTimingFunction::ConstructFunction(
|
|||
return AsVariant(
|
||||
StepFunc{static_cast<uint32_t>(timing.steps._0), timing.steps._1});
|
||||
case StyleComputedTimingFunction::Tag::LinearFunction: {
|
||||
// TODO(dshin): To be implemented (bug 1764126)
|
||||
return ConstructFunction(nsTimingFunction{StyleTimingKeyword::Linear});
|
||||
StylePiecewiseLinearFunction result;
|
||||
Servo_CreatePiecewiseLinearFunction(&timing.linear_function._0, &result);
|
||||
return AsVariant(result);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown timing function.");
|
||||
|
@ -175,6 +176,10 @@ double ComputedTimingFunction::GetValue(
|
|||
},
|
||||
[aPortion, aBeforeFlag](const StepFunc& aFunction) {
|
||||
return StepTiming(aFunction, aPortion, aBeforeFlag);
|
||||
},
|
||||
[aPortion](const StylePiecewiseLinearFunction& aFunction) {
|
||||
return static_cast<double>(Servo_PiecewiseLinearFunctionAt(
|
||||
&aFunction, static_cast<float>(aPortion)));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -194,6 +199,19 @@ void ComputedTimingFunction::AppendToString(nsACString& aResult) const {
|
|||
[](const StepFunc& aFunction) {
|
||||
return StyleComputedTimingFunction::Steps(
|
||||
static_cast<int>(aFunction.mSteps), aFunction.mPos);
|
||||
},
|
||||
[](const StylePiecewiseLinearFunction& aFunction) {
|
||||
// TODO(dshin, bug 1773493): Having to go back and forth isn't ideal.
|
||||
Vector<StyleComputedLinearStop> stops;
|
||||
bool reserved = stops.initCapacity(aFunction.entries.Length());
|
||||
MOZ_RELEASE_ASSERT(reserved, "Failed to reserve memory");
|
||||
for (const auto& e : aFunction.entries.AsSpan()) {
|
||||
stops.infallibleAppend(StyleComputedLinearStop{
|
||||
e.y, StyleOptional<StylePercentage>::Some(StylePercentage{e.x}),
|
||||
StyleOptional<StylePercentage>::None()});
|
||||
}
|
||||
return StyleComputedTimingFunction::LinearFunction(
|
||||
StyleOwnedSlice<StyleComputedLinearStop>{std::move(stops)});
|
||||
})};
|
||||
Servo_SerializeEasing(&timing, &aResult);
|
||||
}
|
||||
|
@ -213,6 +231,18 @@ Maybe<ComputedTimingFunction> ComputedTimingFunction::FromLayersTimingFunction(
|
|||
StyleStepPosition pos = static_cast<StyleStepPosition>(sf.type());
|
||||
return Some(ComputedTimingFunction::Steps(sf.steps(), pos));
|
||||
}
|
||||
case layers::TimingFunction::TLinearFunction: {
|
||||
auto lf = aTimingFunction.get_LinearFunction();
|
||||
Vector<StylePiecewiseLinearFunctionEntry> stops;
|
||||
bool reserved = stops.initCapacity(lf.stops().Length());
|
||||
MOZ_RELEASE_ASSERT(reserved, "Failed to reserve memory");
|
||||
for (const auto& e : lf.stops()) {
|
||||
stops.infallibleAppend(
|
||||
StylePiecewiseLinearFunctionEntry{e.input(), e.output()});
|
||||
}
|
||||
StylePiecewiseLinearFunction result;
|
||||
return Some(ComputedTimingFunction{result});
|
||||
}
|
||||
case layers::TimingFunction::T__None:
|
||||
break;
|
||||
}
|
||||
|
@ -244,6 +274,13 @@ layers::TimingFunction ComputedTimingFunction::ToLayersTimingFunction(
|
|||
return layers::TimingFunction{
|
||||
layers::StepFunction{static_cast<int>(aFunction.mSteps),
|
||||
static_cast<uint8_t>(aFunction.mPos)}};
|
||||
},
|
||||
[](const StylePiecewiseLinearFunction& aFunction) {
|
||||
nsTArray<layers::LinearStop> stops{aFunction.entries.Length()};
|
||||
for (const auto& e : aFunction.entries.AsSpan()) {
|
||||
stops.AppendElement(layers::LinearStop{e.x, e.y});
|
||||
}
|
||||
return layers::TimingFunction{layers::LinearFunction{stops}};
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,17 @@ class ComputedTimingFunction {
|
|||
StyleComputedTimingFunction::Tag::Steps &&
|
||||
aFunction.mSteps == uint32_t(aOther.mTiming.steps._0) &&
|
||||
aFunction.mPos == aOther.mTiming.steps._1;
|
||||
},
|
||||
[&aOther](const StylePiecewiseLinearFunction& aFunction) {
|
||||
if (aOther.mTiming.tag !=
|
||||
StyleComputedTimingFunction::Tag::LinearFunction) {
|
||||
return false;
|
||||
}
|
||||
StylePiecewiseLinearFunction other;
|
||||
// TODO(dshin, bug 1773493): Having to go back and forth isn't ideal.
|
||||
Servo_CreatePiecewiseLinearFunction(
|
||||
&aOther.mTiming.linear_function._0, &other);
|
||||
return aFunction.entries == other.entries;
|
||||
});
|
||||
}
|
||||
bool operator!=(const nsTimingFunction& aOther) const {
|
||||
|
@ -105,13 +116,17 @@ class ComputedTimingFunction {
|
|||
mozilla::StyleTimingKeyword mKeyword;
|
||||
SMILKeySpline mFunction;
|
||||
};
|
||||
using Function = mozilla::Variant<KeywordFunction, SMILKeySpline, StepFunc>;
|
||||
|
||||
using Function = mozilla::Variant<KeywordFunction, SMILKeySpline, StepFunc,
|
||||
StylePiecewiseLinearFunction>;
|
||||
|
||||
static Function ConstructFunction(const nsTimingFunction& aFunction);
|
||||
ComputedTimingFunction(double x1, double y1, double x2, double y2)
|
||||
: mFunction{AsVariant(SMILKeySpline{x1, y1, x2, y2})} {}
|
||||
ComputedTimingFunction(uint32_t aSteps, StyleStepPosition aPos)
|
||||
: mFunction{AsVariant(StepFunc{aSteps, aPos})} {}
|
||||
explicit ComputedTimingFunction(StylePiecewiseLinearFunction aFunction)
|
||||
: mFunction{AsVariant(std::move(aFunction))} {}
|
||||
|
||||
Function mFunction;
|
||||
};
|
||||
|
|
|
@ -101,10 +101,20 @@ struct StepFunction {
|
|||
uint8_t type; // Converted from StyleStepPosition.
|
||||
};
|
||||
|
||||
struct LinearStop {
|
||||
float input;
|
||||
float output;
|
||||
};
|
||||
|
||||
struct LinearFunction {
|
||||
LinearStop[] stops;
|
||||
};
|
||||
|
||||
union TimingFunction {
|
||||
null_t;
|
||||
CubicBezierFunction;
|
||||
StepFunction;
|
||||
LinearFunction;
|
||||
};
|
||||
|
||||
struct LayerColor { DeviceColor value; };
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [layout.css.linear-easing-function.enabled:true]
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<meta name="assert" content="This test checks the output of linear timing functions" />
|
||||
<title>Tests for the output of linear timing functions</title>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/6533">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/util.js"></script>
|
||||
<script src="testcommon.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function assert_style_left_at(animation, time, expected_y) {
|
||||
animation.currentTime = time;
|
||||
assert_approx_equals(pxToNum(getComputedStyle(animation.effect.target).left),
|
||||
expected_y * 100,
|
||||
0.01,
|
||||
'The left of the animation should be approximately ' +
|
||||
expected_y * 100 + ' at ' + time + 'ms');
|
||||
}
|
||||
|
||||
function assert_animations_equal_at(actual_animation, expected_animation, time) {
|
||||
actual_animation.currentTime = time;
|
||||
var actual_left = pxToNum(getComputedStyle(actual_animation.effect.target).left);
|
||||
expected_animation.currentTime = time;
|
||||
var expected_left = pxToNum(getComputedStyle(expected_animation.effect.target).left);
|
||||
assert_approx_equals(actual_left,
|
||||
expected_left,
|
||||
0.01,
|
||||
'The left of the animation should be approximately ' +
|
||||
expected_left + ' at ' + time + 'ms');
|
||||
}
|
||||
|
||||
function create_animated_div(t, easing_function) {
|
||||
var target = createDiv(t);
|
||||
target.style.position = 'absolute';
|
||||
return target.animate(
|
||||
[ { left: '0px' },
|
||||
{ left: '100px' } ],
|
||||
{ duration: 1000,
|
||||
fill: 'forwards',
|
||||
easing: easing_function });
|
||||
}
|
||||
|
||||
test(function(t) {
|
||||
var anim = create_animated_div(t, 'linear(0, 1.5, 1)');
|
||||
|
||||
assert_style_left_at(anim, 0, 0.0);
|
||||
assert_style_left_at(anim, 250, 0.75);
|
||||
assert_style_left_at(anim, 500, 1.5);
|
||||
assert_style_left_at(anim, 750, 1.25);
|
||||
assert_style_left_at(anim, 1000, 1.00);
|
||||
}, 'linear function easing with output greater than 1');
|
||||
|
||||
test(function(t) {
|
||||
var anim = create_animated_div(t, 'linear(1, -0.5, 0)');
|
||||
|
||||
assert_style_left_at(anim, 0, 1.0);
|
||||
assert_style_left_at(anim, 250, 0.25);
|
||||
assert_style_left_at(anim, 500, -0.5);
|
||||
assert_style_left_at(anim, 750, -0.25);
|
||||
assert_style_left_at(anim, 1000, 0.00);
|
||||
}, 'linear function easing with output less than 1');
|
||||
|
||||
test(function(t) {
|
||||
var anim = create_animated_div(t, 'linear()');
|
||||
var equiv = create_animated_div(t, 'linear');
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 0);
|
||||
assert_animations_equal_at(anim, equiv, 250);
|
||||
assert_animations_equal_at(anim, equiv, 750);
|
||||
assert_animations_equal_at(anim, equiv, 1000);
|
||||
}, 'linear function easing, linear equivalent');
|
||||
|
||||
test(function(t) {
|
||||
var anim = create_animated_div(t, 'linear(0.5)');
|
||||
|
||||
assert_style_left_at(anim, 0, 0.5);
|
||||
assert_style_left_at(anim, 250, 0.5);
|
||||
assert_style_left_at(anim, 500, 0.5);
|
||||
assert_style_left_at(anim, 750, 0.5);
|
||||
assert_style_left_at(anim, 1000, 0.5);
|
||||
}, 'linear function easing, constant');
|
||||
|
||||
test(function(t) {
|
||||
var anim = create_animated_div(t, 'linear(0.2 0% 20%, 0.4 20% 40%, 0.6 40% 60%, 0.8 60% 80%, 1.0 80% 100%)');
|
||||
var equiv = create_animated_div(t, 'steps(5, jump-start)');
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 0);
|
||||
// Spec doesn't specify which way these steps should be continuous,
|
||||
// so just check on each side.
|
||||
assert_animations_equal_at(anim, equiv, 199);
|
||||
assert_animations_equal_at(anim, equiv, 201);
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 399);
|
||||
assert_animations_equal_at(anim, equiv, 401);
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 599);
|
||||
assert_animations_equal_at(anim, equiv, 601);
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 799);
|
||||
assert_animations_equal_at(anim, equiv, 801);
|
||||
|
||||
assert_animations_equal_at(anim, equiv, 1000);
|
||||
}, 'linear function easing, steps equivalent');
|
||||
</script>
|
||||
</body>
|
Загрузка…
Ссылка в новой задаче