Commit 9d432ecd authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

Mostly fix additive composition for filter

Previously additive composition was implemented as something close to
accumulate, using a pairwise addition. This CL changes it to the by-spec
behavior of concatenating the lists.

Unfortunately due to underlying issues in the way Chromium handles
0%/100% Animations (we fast-path through the interpolation code), things
get weird at those points and we end up dropping the addition - against
spec. This could be a serious problem, for example for fill-forward
animations, so will warrant further CLs to fix.

See https://drafts.fxtf.org/filter-effects-1/#addition

Bug: 1005828
Change-Id: I941c986627c57738c65fb67674bfbce6dc437155
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1822021
Commit-Queue: Alan Cutter <alancutter@chromium.org>
Auto-Submit: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701016}
parent 1d64fd34
...@@ -125,7 +125,10 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertNeutral( ...@@ -125,7 +125,10 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertNeutral(
ToInterpolableList(underlying.interpolable_value.get()); ToInterpolableList(underlying.interpolable_value.get());
conversion_checkers.push_back( conversion_checkers.push_back(
std::make_unique<UnderlyingFilterListChecker>(interpolable_list)); std::make_unique<UnderlyingFilterListChecker>(interpolable_list));
return InterpolationValue(underlying.interpolable_value->CloneAndZero()); // The neutral value for composition for a filter list is the empty list, as
// the additive operator is concatenation, so concat(underlying, []) ==
// underlying.
return InterpolationValue(std::make_unique<InterpolableList>(0));
} }
InterpolationValue CSSFilterListInterpolationType::MaybeConvertInitial( InterpolationValue CSSFilterListInterpolationType::MaybeConvertInitial(
...@@ -232,45 +235,9 @@ void CSSFilterListInterpolationType::Composite( ...@@ -232,45 +235,9 @@ void CSSFilterListInterpolationType::Composite(
double underlying_fraction, double underlying_fraction,
const InterpolationValue& value, const InterpolationValue& value,
double interpolation_fraction) const { double interpolation_fraction) const {
// TODO(crbug.com/1005828): The below behavior is not correct for addition of // We do our actual compositing behavior in |MakeAdditive|; see the
// filter values. Additive composition is defined as list concatenation in the // documentation on that method.
// spec: https://drafts.fxtf.org/filter-effects-1/#addition underlying_value_owner.Set(*this, value);
InterpolableList& underlying_list =
ToInterpolableList(*underlying_value_owner.Value().interpolable_value);
const InterpolableList& interpolable_list =
ToInterpolableList(*value.interpolable_value);
wtf_size_t underlying_length = underlying_list.length();
wtf_size_t length = interpolable_list.length();
for (wtf_size_t i = 0; i < underlying_length && i < length; i++) {
if (To<InterpolableFilter>(interpolable_list.Get(i))->GetType() !=
To<InterpolableFilter>(underlying_list.Get(i))->GetType()) {
underlying_value_owner.Set(*this, value);
return;
}
}
for (wtf_size_t i = 0; i < length && i < underlying_length; i++) {
underlying_list.GetMutable(i)->ScaleAndAdd(underlying_fraction,
*interpolable_list.Get(i));
}
if (length <= underlying_length)
return;
auto extended_interpolable_list = std::make_unique<InterpolableList>(length);
for (wtf_size_t i = 0; i < length; i++) {
if (i < underlying_length) {
extended_interpolable_list->Set(i,
std::move(underlying_list.GetMutable(i)));
} else {
extended_interpolable_list->Set(i, interpolable_list.Get(i)->Clone());
}
}
underlying_value_owner.MutableValue().interpolable_value =
std::move(extended_interpolable_list);
underlying_value_owner.MutableValue().non_interpolable_value =
value.non_interpolable_value;
} }
void CSSFilterListInterpolationType::ApplyStandardPropertyValue( void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
...@@ -291,4 +258,40 @@ void CSSFilterListInterpolationType::ApplyStandardPropertyValue( ...@@ -291,4 +258,40 @@ void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
SetFilterList(CssProperty(), *state.Style(), std::move(filter_operations)); SetFilterList(CssProperty(), *state.Style(), std::move(filter_operations));
} }
InterpolationValue CSSFilterListInterpolationType::MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const {
DCHECK(!value.non_interpolable_value);
DCHECK(!underlying.non_interpolable_value);
// By default, the interpolation stack attempts to optimize composition by
// doing it after interpolation. This does not work in the case of filter
// lists, as they have a composition behavior of concatenation. To work around
// that, we hackily perform our composition in MakeAdditive (which runs before
// interpolation), and then make Composite a simple replacement of the
// underlying value (which we have already incorporated here).
// The underlying value can be nullptr, most commonly if it contains a url().
if (!underlying.interpolable_value)
return nullptr;
const InterpolableList& interpolable_list =
ToInterpolableList(*value.interpolable_value);
const InterpolableList& underlying_list =
ToInterpolableList(*underlying.interpolable_value);
auto composited_list = std::make_unique<InterpolableList>(
underlying_list.length() + interpolable_list.length());
for (wtf_size_t i = 0; i < composited_list->length(); i++) {
if (i < underlying_list.length()) {
composited_list->Set(i, underlying_list.Get(i)->Clone());
} else {
composited_list->Set(
i, interpolable_list.Get(i - underlying_list.length())->Clone());
}
}
return InterpolationValue(std::move(composited_list));
}
} // namespace blink } // namespace blink
...@@ -26,6 +26,9 @@ class CSSFilterListInterpolationType : public CSSInterpolationType { ...@@ -26,6 +26,9 @@ class CSSFilterListInterpolationType : public CSSInterpolationType {
void ApplyStandardPropertyValue(const InterpolableValue&, void ApplyStandardPropertyValue(const InterpolableValue&,
const NonInterpolableValue*, const NonInterpolableValue*,
StyleResolverState&) const final; StyleResolverState&) const final;
InterpolationValue MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const final;
private: private:
InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying, InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying,
......
...@@ -141,7 +141,7 @@ InterpolationValue CSSInterpolationType::MaybeConvertSingle( ...@@ -141,7 +141,7 @@ InterpolationValue CSSInterpolationType::MaybeConvertSingle(
keyframe, environment, underlying, conversion_checkers); keyframe, environment, underlying, conversion_checkers);
if (result && keyframe.Composite() != if (result && keyframe.Composite() !=
EffectModel::CompositeOperation::kCompositeReplace) { EffectModel::CompositeOperation::kCompositeReplace) {
return MakeAdditive(std::move(result)); return MakeAdditive(std::move(result), underlying);
} }
return result; return result;
} }
......
...@@ -63,7 +63,9 @@ class CORE_EXPORT CSSInterpolationType : public InterpolationType { ...@@ -63,7 +63,9 @@ class CORE_EXPORT CSSInterpolationType : public InterpolationType {
const InterpolationValue& underlying, const InterpolationValue& underlying,
ConversionCheckers&) const final; ConversionCheckers&) const final;
virtual InterpolationValue MakeAdditive(InterpolationValue value) const { virtual InterpolationValue MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const {
return value; return value;
} }
......
...@@ -213,7 +213,8 @@ InterpolationValue CSSRotateInterpolationType::MaybeConvertValue( ...@@ -213,7 +213,8 @@ InterpolationValue CSSRotateInterpolationType::MaybeConvertValue(
} }
InterpolationValue CSSRotateInterpolationType::MakeAdditive( InterpolationValue CSSRotateInterpolationType::MakeAdditive(
InterpolationValue value) const { InterpolationValue value,
const InterpolationValue& underlying) const {
value.non_interpolable_value = CSSRotateNonInterpolableValue::CreateAdditive( value.non_interpolable_value = CSSRotateNonInterpolableValue::CreateAdditive(
ToCSSRotateNonInterpolableValue(*value.non_interpolable_value)); ToCSSRotateNonInterpolableValue(*value.non_interpolable_value));
return value; return value;
......
...@@ -39,7 +39,9 @@ class CSSRotateInterpolationType : public CSSInterpolationType { ...@@ -39,7 +39,9 @@ class CSSRotateInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&, InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*, const StyleResolverState*,
ConversionCheckers&) const final; ConversionCheckers&) const final;
InterpolationValue MakeAdditive(InterpolationValue) const final; InterpolationValue MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const final;
}; };
} // namespace blink } // namespace blink
......
...@@ -194,7 +194,8 @@ InterpolationValue CSSScaleInterpolationType::MaybeConvertValue( ...@@ -194,7 +194,8 @@ InterpolationValue CSSScaleInterpolationType::MaybeConvertValue(
} }
InterpolationValue CSSScaleInterpolationType::MakeAdditive( InterpolationValue CSSScaleInterpolationType::MakeAdditive(
InterpolationValue value) const { InterpolationValue value,
const InterpolationValue& underlying) const {
value.non_interpolable_value = CSSScaleNonInterpolableValue::CreateAdditive( value.non_interpolable_value = CSSScaleNonInterpolableValue::CreateAdditive(
ToCSSScaleNonInterpolableValue(*value.non_interpolable_value)); ToCSSScaleNonInterpolableValue(*value.non_interpolable_value));
return value; return value;
......
...@@ -36,7 +36,9 @@ class CSSScaleInterpolationType : public CSSInterpolationType { ...@@ -36,7 +36,9 @@ class CSSScaleInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&, InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*, const StyleResolverState*,
ConversionCheckers&) const final; ConversionCheckers&) const final;
InterpolationValue MakeAdditive(InterpolationValue) const final; InterpolationValue MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const final;
PairwiseInterpolationValue MaybeMergeSingles( PairwiseInterpolationValue MaybeMergeSingles(
InterpolationValue&&, InterpolationValue&&,
......
...@@ -251,7 +251,8 @@ InterpolationValue CSSTransformInterpolationType::MaybeConvertValue( ...@@ -251,7 +251,8 @@ InterpolationValue CSSTransformInterpolationType::MaybeConvertValue(
} }
InterpolationValue CSSTransformInterpolationType::MakeAdditive( InterpolationValue CSSTransformInterpolationType::MakeAdditive(
InterpolationValue value) const { InterpolationValue value,
const InterpolationValue& underlying) const {
value.non_interpolable_value = value.non_interpolable_value =
CSSTransformNonInterpolableValue::CreateAdditive( CSSTransformNonInterpolableValue::CreateAdditive(
ToCSSTransformNonInterpolableValue(*value.non_interpolable_value)); ToCSSTransformNonInterpolableValue(*value.non_interpolable_value));
......
...@@ -39,7 +39,9 @@ class CSSTransformInterpolationType : public CSSInterpolationType { ...@@ -39,7 +39,9 @@ class CSSTransformInterpolationType : public CSSInterpolationType {
InterpolationValue MaybeConvertValue(const CSSValue&, InterpolationValue MaybeConvertValue(const CSSValue&,
const StyleResolverState*, const StyleResolverState*,
ConversionCheckers&) const final; ConversionCheckers&) const final;
InterpolationValue MakeAdditive(InterpolationValue) const final; InterpolationValue MakeAdditive(
InterpolationValue value,
const InterpolationValue& underlying) const final;
}; };
} // namespace blink } // namespace blink
......
...@@ -210,8 +210,9 @@ FilterOperation* InterpolableFilter::CreateFilterOperation( ...@@ -210,8 +210,9 @@ FilterOperation* InterpolableFilter::CreateFilterOperation(
void InterpolableFilter::AssertCanInterpolateWith( void InterpolableFilter::AssertCanInterpolateWith(
const InterpolableValue& other) const { const InterpolableValue& other) const {
DCHECK(other.IsFilter()); const InterpolableFilter& other_filter = To<InterpolableFilter>(other);
DCHECK_EQ(type_, To<InterpolableFilter>(other).type_); value_->AssertCanInterpolateWith(*other_filter.value_);
DCHECK_EQ(type_, other_filter.type_);
} }
void InterpolableFilter::Interpolate(const InterpolableValue& to, void InterpolableFilter::Interpolate(const InterpolableValue& to,
......
...@@ -51,7 +51,7 @@ class CORE_EXPORT InterpolableFilter final : public InterpolableValue { ...@@ -51,7 +51,7 @@ class CORE_EXPORT InterpolableFilter final : public InterpolableValue {
} }
void Scale(double scale) final { NOTREACHED(); } void Scale(double scale) final { NOTREACHED(); }
void ScaleAndAdd(double scale, const InterpolableValue& other) final { void ScaleAndAdd(double scale, const InterpolableValue& other) final {
value_->ScaleAndAdd(scale, *To<InterpolableFilter>(other).value_); NOTREACHED();
} }
void AssertCanInterpolateWith(const InterpolableValue& other) const final; void AssertCanInterpolateWith(const InterpolableValue& other) const final;
......
...@@ -9,155 +9,129 @@ assertComposition({ ...@@ -9,155 +9,129 @@ assertComposition({
addFrom: 'blur(40px)', addFrom: 'blur(40px)',
addTo: 'blur(90px)', addTo: 'blur(90px)',
}, [ }, [
{at: -0.5, is: 'blur(25px)'}, {at: -0.5, is: 'blur(10px) blur(15px)'},
{at: 0, is: 'blur(50px)'}, {at: 0, is: 'blur(10px) blur(40px)'},
{at: 0.25, is: 'blur(62.5px)'}, {at: 0.25, is: 'blur(10px) blur(52.5px)'},
{at: 0.5, is: 'blur(75px)'}, {at: 0.5, is: 'blur(10px) blur(65px)'},
{at: 0.75, is: 'blur(87.5px)'}, {at: 0.75, is: 'blur(10px) blur(77.5px)'},
{at: 1, is: 'blur(100px)'}, {at: 1, is: 'blur(10px) blur(90px)'},
{at: 1.5, is: 'blur(125px)'}, {at: 1.5, is: 'blur(10px) blur(115px)'},
]); ]);
// Here we have add-from and replace-to, so the list will be have mismatched
// lengths and the replace-to list will have to be extended to interpolate as
// per https://drafts.fxtf.org/filter-effects-1/#interpolation-of-filters
//
// That is, this becomes an interpolation of the form:
// sepia(0.5) sepia(0.5) --> sepia(1) sepia(0)
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'sepia(0.5)', underlying: 'sepia(0.5)',
addFrom: 'sepia(0.5)', addFrom: 'sepia(0.5)',
replaceTo: 'sepia(0)', replaceTo: 'sepia(1)',
}, [ }, [
{at: -0.5, is: 'sepia(1)'}, {at: -0.5, is: 'sepia(0.25) sepia(0.75)'},
{at: 0, is: 'sepia(1)'}, {at: 0, is: 'sepia(0.5) sepia(0.5)'},
{at: 0.25, is: 'sepia(0.75)'}, {at: 0.25, is: 'sepia(0.625) sepia(0.375)'},
{at: 0.5, is: 'sepia(0.5)'}, {at: 0.5, is: 'sepia(0.75) sepia(0.25)'},
{at: 0.75, is: 'sepia(0.25)'}, {at: 0.75, is: 'sepia(0.875) sepia(0.125)'},
{at: 1, is: 'sepia(0)'}, {at: 1, is: 'sepia(1) sepia(0)'},
{at: 1.5, is: 'sepia(0)'}, {at: 1.5, is: 'sepia(1) sepia(0)'},
]); ]);
// In this case we have replace-from and add-to, so similar extending behavior
// takes place. Note that brightness has an initial value of 1.
//
// That is, this becomes an interpolation of the form:
// brightness(0.5) brightness(1) --> brightness(0) brightness(1.5)
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'brightness(0.25)', underlying: 'brightness(0)',
replaceFrom: 'brightness(0.5)', replaceFrom: 'brightness(0.5)',
addTo: 'brightness(1.25)', addTo: 'brightness(1.5)',
}, [ }, [
{at: -0.5, is: 'brightness(0)'}, {at: -0.5, is: 'brightness(0.75) brightness(0.75)'},
{at: 0, is: 'brightness(0.5)'}, {at: 0, is: 'brightness(0.5) brightness(1)'},
{at: 0.25, is: 'brightness(0.75)'}, {at: 0.25, is: 'brightness(0.375) brightness(1.125)'},
{at: 0.5, is: 'brightness(1)'}, {at: 0.5, is: 'brightness(0.25) brightness(1.25)'},
{at: 0.75, is: 'brightness(1.25)'}, {at: 0.75, is: 'brightness(0.125) brightness(1.375)'},
{at: 1, is: 'brightness(1.5)'}, {at: 1, is: 'brightness(0) brightness(1.5)'},
{at: 1.5, is: 'brightness(2)'}, {at: 1.5, is: 'brightness(0) brightness(1.75)'},
]);
assertComposition({
property: 'backdrop-filter',
underlying: 'invert(0.5) saturate(1)',
addFrom: 'invert(1) saturate(2)',
addTo: 'invert(25%) saturate(3)',
}, [
{at: -0.5, is: 'invert(1) saturate(2.5)'},
{at: 0, is: 'invert(1) saturate(3)'},
{at: 0.25, is: 'invert(1) saturate(3.25)'},
{at: 0.5, is: 'invert(1) saturate(3.5)'},
{at: 0.75, is: 'invert(0.9375) saturate(3.75)'},
{at: 1, is: 'invert(0.75) saturate(4)'},
{at: 1.5, is: 'invert(0.375) saturate(4.5)'},
]); ]);
// Test mixing properties.
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'invert(0.5)', underlying: 'invert(0.5)',
addFrom: 'invert(1) saturate(200%)', addFrom: 'saturate(2)',
addTo: 'invert(25%) saturate(3) contrast(50%)', addTo: 'saturate(3)',
}, [ }, [
{at: -0.5, is: 'invert(1) saturate(1.5) contrast(1.25)'}, {at: -0.5, is: 'invert(0.5) saturate(1.5)'},
{at: 0, is: 'invert(1) saturate(2)'}, {at: 0, is: 'invert(0.5) saturate(2)'},
{at: 0.25, is: 'invert(1) saturate(2.25) contrast(0.875)'}, {at: 0.25, is: 'invert(0.5) saturate(2.25)'},
{at: 0.5, is: 'invert(1) saturate(2.5) contrast(0.75)'}, {at: 0.5, is: 'invert(0.5) saturate(2.5)'},
{at: 0.75, is: 'invert(0.9375) saturate(2.75) contrast(0.625)'}, {at: 0.75, is: 'invert(0.5) saturate(2.75)'},
{at: 1, is: 'invert(0.75) saturate(3) contrast(0.5)'}, {at: 1, is: 'invert(0.5) saturate(3)'},
{at: 1.5, is: 'invert(0.375) saturate(3.5) contrast(0.25)'}, {at: 1.5, is: 'invert(0.5) saturate(3.5)'},
]); ]);
// Test the 'none' behavior; composition happens before interpolation, so this
// is actually an interpolation of:
// invert(0.5) saturate(1) --> invert(1) saturate(3)
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'invert(0.5)', underlying: 'invert(0.5)',
addFrom: 'none', addFrom: 'none',
addTo: 'invert(25%) saturate(3) contrast(50%)', replaceTo: 'invert(1) saturate(3)',
}, [
{at: -0.5, is: 'invert(0.375) saturate(0) contrast(1.25)'},
{at: 0, is: 'invert(0.5)'},
{at: 0.25, is: 'invert(0.5625) saturate(1.5) contrast(0.875)'},
{at: 0.5, is: 'invert(0.625) saturate(2) contrast(0.75)'},
{at: 0.75, is: 'invert(0.6875) saturate(2.5) contrast(0.625)'},
{at: 1, is: 'invert(0.75) saturate(3) contrast(0.5)'},
{at: 1.5, is: 'invert(0.875) saturate(4) contrast(0.25)'},
]);
assertComposition({
property: 'backdrop-filter',
underlying: 'invert(0.5)',
addFrom: 'invert(1) saturate(200%)',
addTo: 'none',
}, [ }, [
{at: -0.5, is: 'invert(1) saturate(2.5)'}, {at: -0.5, is: 'invert(0.25) saturate(0)'},
{at: 0, is: 'invert(1) saturate(2)'}, {at: 0, is: 'invert(0.5) saturate(1)'},
{at: 0.25, is: 'invert(1) saturate(1.75)'}, {at: 0.25, is: 'invert(0.625) saturate(1.5)'},
{at: 0.5, is: 'invert(1) saturate(1.5)'}, {at: 0.5, is: 'invert(0.75) saturate(2)'},
{at: 0.75, is: 'invert(0.75) saturate(1.25)'}, {at: 0.75, is: 'invert(0.875) saturate(2.5)'},
{at: 1, is: 'invert(0.5)'}, {at: 1, is: 'invert(1) saturate(3)'},
{at: 1.5, is: 'invert(0) saturate(0.5)'}, {at: 1.5, is: 'invert(1.25) saturate(4)'},
]);
assertComposition({
property: 'backdrop-filter',
underlying: 'none',
addFrom: 'invert(1) saturate(200%)',
addTo: 'invert(25%) saturate(3) contrast(50%)',
}, [
{at: -0.5, is: 'invert(1) saturate(1.5) contrast(1.25)'},
{at: 0, is: 'invert(1) saturate(2)'},
{at: 0.25, is: 'invert(0.8125) saturate(2.25) contrast(0.875)'},
{at: 0.5, is: 'invert(0.625) saturate(2.5) contrast(0.75)'},
{at: 0.75, is: 'invert(0.4375) saturate(2.75) contrast(0.625)'},
{at: 1, is: 'invert(0.25) saturate(3) contrast(0.5)'},
{at: 1.5, is: 'invert(0) saturate(3.5) contrast(0.25)'},
]); ]);
// Test having multiple underlying values
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'grayscale(25%) blur(10px)', underlying: 'grayscale(25%) blur(10px)',
addFrom: 'grayscale(50%) blur(10px)', addFrom: 'brightness(0)',
addTo: 'blur(10px)', addTo: 'brightness(1)',
}, [ }, [
{at: -0.5, is: 'grayscale(0.75) blur(20px)'}, {at: -0.5, is: 'grayscale(25%) blur(10px) brightness(0)'},
{at: 0, is: 'grayscale(0.75) blur(20px)'}, {at: 0, is: 'grayscale(25%) blur(10px) brightness(0)'},
{at: 0.25, is: 'grayscale(0.75) blur(20px)'}, {at: 0.25, is: 'grayscale(25%) blur(10px) brightness(0.25)'},
{at: 0.5, is: 'blur(10px)'}, {at: 0.5, is: 'grayscale(25%) blur(10px) brightness(0.5)'},
{at: 0.75, is: 'blur(10px)'}, {at: 0.75, is: 'grayscale(25%) blur(10px) brightness(0.75)'},
{at: 1, is: 'blur(10px)'}, {at: 1, is: 'grayscale(25%) blur(10px) brightness(1)'},
{at: 1.5, is: 'blur(10px)'}, {at: 1.5, is: 'grayscale(25%) blur(10px) brightness(1.5)'},
]); ]);
// Make sure that a matching underlying value is still prefixed.
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'blur(10px)', underlying: 'blur(10px)',
addFrom: 'grayscale(50%) blur(10px)', addFrom: 'grayscale(50%) blur(10px)',
addTo: 'grayscale(25%) blur(10px)', addTo: 'grayscale(25%) blur(10px)',
}, [ }, [
{at: -0.5, is: 'grayscale(0.625) blur(10px)'}, {at: -0.5, is: 'blur(10px) grayscale(0.625) blur(10px)'},
{at: 0, is: 'grayscale(0.5) blur(10px)'}, {at: 0, is: 'blur(10px) grayscale(0.5) blur(10px)'},
{at: 0.25, is: 'grayscale(0.4375) blur(10px)'}, {at: 0.25, is: 'blur(10px) grayscale(0.4375) blur(10px)'},
{at: 0.5, is: 'grayscale(0.375) blur(10px)'}, {at: 0.5, is: 'blur(10px) grayscale(0.375) blur(10px)'},
{at: 0.75, is: 'grayscale(0.3125) blur(10px)'}, {at: 0.75, is: 'blur(10px) grayscale(0.3125) blur(10px)'},
{at: 1, is: 'grayscale(0.25) blur(10px)'}, {at: 1, is: 'blur(10px) grayscale(0.25) blur(10px)'},
{at: 1.5, is: 'grayscale(0.125) blur(10px)'}, {at: 1.5, is: 'blur(10px) grayscale(0.125) blur(10px)'},
]); ]);
// Check the case where composition causes a url() to be included; the animation
// should change to discrete.
assertComposition({ assertComposition({
property: 'backdrop-filter', property: 'backdrop-filter',
underlying: 'url(#a) grayscale(50%) blur(20px)', underlying: 'url(#a)',
addFrom: 'url(#a) grayscale(50%) blur(30px)', addFrom: 'grayscale(50%) blur(30px)',
addTo: 'url(#a) grayscale(25%) blur(40px)', addTo: 'grayscale(25%) blur(40px)',
}, [ }, [
{at: -0.5, is: 'url("#a") grayscale(0.5) blur(30px)'}, {at: -0.5, is: 'url("#a") grayscale(0.5) blur(30px)'},
{at: 0, is: 'url("#a") grayscale(0.5) blur(30px)'}, {at: 0, is: 'url("#a") grayscale(0.5) blur(30px)'},
...@@ -167,5 +141,22 @@ assertComposition({ ...@@ -167,5 +141,22 @@ assertComposition({
{at: 1, is: 'url("#a") grayscale(0.25) blur(40px)'}, {at: 1, is: 'url("#a") grayscale(0.25) blur(40px)'},
{at: 1.5, is: 'url("#a") grayscale(0.25) blur(40px)'}, {at: 1.5, is: 'url("#a") grayscale(0.25) blur(40px)'},
]); ]);
// And check the inverse; nothing fancy here but it should be a discrete
// animation with blur prepended.
assertComposition({
property: 'backdrop-filter',
underlying: 'blur(10px)',
addFrom: 'url(#a) brightness(1)',
addTo: 'url(#b) brightness(0)',
}, [
{at: -0.5, is: 'blur(10px) url(#a) brightness(1)'},
{at: 0, is: 'blur(10px) url(#a) brightness(1)'},
{at: 0.25, is: 'blur(10px) url(#a) brightness(1)'},
{at: 0.5, is: 'blur(10px) url(#b) brightness(0)'},
{at: 0.75, is: 'blur(10px) url(#b) brightness(0)'},
{at: 1, is: 'blur(10px) url(#b) brightness(0)'},
{at: 1.5, is: 'blur(10px) url(#b) brightness(0)'},
]);
</script> </script>
</body> </body>
This is a testharness.js-based test. This is a testharness.js-based test.
Found 563 tests; 531 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN. Found 563 tests; 530 PASS, 33 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Setup PASS Setup
PASS align-content (type: discrete) has testAccumulation function PASS align-content (type: discrete) has testAccumulation function
PASS align-content: "flex-end" onto "flex-start" PASS align-content: "flex-end" onto "flex-start"
...@@ -201,8 +201,8 @@ PASS fill-rule (type: discrete) has testAccumulation function ...@@ -201,8 +201,8 @@ PASS fill-rule (type: discrete) has testAccumulation function
PASS fill-rule: "nonzero" onto "evenodd" PASS fill-rule: "nonzero" onto "evenodd"
PASS fill-rule: "evenodd" onto "nonzero" PASS fill-rule: "evenodd" onto "nonzero"
PASS filter (type: filterList) has testAccumulation function PASS filter (type: filterList) has testAccumulation function
FAIL filter: same ordered filter functions assert_equals: The value should be blur(30px) brightness(0) at 0ms expected "blur(30px) brightness(0)" but got "blur(30px) brightness(0.4)" FAIL filter: same ordered filter functions assert_equals: The value should be blur(30px) brightness(0) at 0ms expected "blur(30px) brightness(0)" but got "blur(10px) brightness(0.3) blur(20px) brightness(0.1)"
PASS filter: mismatched ordered filter functions FAIL filter: mismatched ordered filter functions assert_equals: The value should be brightness(1.2) blur(20px) at 0ms expected "brightness(1.2) blur(20px)" but got "blur(10px) brightness(1.3) brightness(1.2) blur(20px)"
PASS flex-basis (type: lengthPercentageOrCalc) has testAccumulation function PASS flex-basis (type: lengthPercentageOrCalc) has testAccumulation function
PASS flex-basis: length PASS flex-basis: length
PASS flex-basis: length of rem PASS flex-basis: length of rem
......
This is a testharness.js-based test. This is a testharness.js-based test.
Found 559 tests; 538 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN. Found 559 tests; 540 PASS, 19 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Setup PASS Setup
PASS align-content (type: discrete) has testAddition function PASS align-content (type: discrete) has testAddition function
PASS align-content: "flex-end" onto "flex-start" PASS align-content: "flex-end" onto "flex-start"
...@@ -201,8 +201,8 @@ PASS fill-rule (type: discrete) has testAddition function ...@@ -201,8 +201,8 @@ PASS fill-rule (type: discrete) has testAddition function
PASS fill-rule: "nonzero" onto "evenodd" PASS fill-rule: "nonzero" onto "evenodd"
PASS fill-rule: "evenodd" onto "nonzero" PASS fill-rule: "evenodd" onto "nonzero"
PASS filter (type: filterList) has testAddition function PASS filter (type: filterList) has testAddition function
FAIL filter: blur on blur assert_equals: The value should be blur(10px) blur(20px) at 0ms expected "blur(10px) blur(20px)" but got "blur(30px)" PASS filter: blur on blur
FAIL filter: different filter functions assert_equals: The value should be blur(10px) brightness(0.8) at 0ms expected "blur(10px) brightness(0.8)" but got "brightness(0.8)" PASS filter: different filter functions
PASS flex-basis (type: lengthPercentageOrCalc) has testAddition function PASS flex-basis (type: lengthPercentageOrCalc) has testAddition function
PASS flex-basis: length PASS flex-basis: length
PASS flex-basis: length of rem PASS flex-basis: length of rem
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment