Commit 1165da6c authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

Refactor filter interpolation functions into an InterpolableFilter

This CL is part of the shift away from NonInterpolableValues to instead
having more InterpolableValue subclasses. It introduces a new subclass,
InterpolableFilter, which can represent a blink::FilterOperation. This
should enable us to more easily implement the correct additive behavior
for filter, see [0].

There should be no behavioral change from this CL, it is (intended to
be) a pure refactoring.

Bug: 1005828

[0]: https://docs.google.com/document/d/1aAvTNwxSSl0OWP3hQAV-Q7ru5-o5MzV4UEz7Uw9VHZk/edit#heading=h.9b2xtih585di

Change-Id: Ib60b5857167db8950f3eb457cfaeec98ee781ff1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1817284
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700843}
parent c281c2a5
......@@ -152,12 +152,12 @@ blink_core_sources("animation") {
"effect_stack.h",
"element_animations.cc",
"element_animations.h",
"filter_interpolation_functions.cc",
"filter_interpolation_functions.h",
"image_list_property_functions.h",
"image_slice_property_functions.h",
"inert_effect.cc",
"inert_effect.h",
"interpolable_filter.cc",
"interpolable_filter.h",
"interpolable_length.cc",
"interpolable_length.h",
"interpolable_shadow.cc",
......
......@@ -8,7 +8,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/animation/filter_interpolation_functions.h"
#include "third_party/blink/renderer/core/animation/interpolable_filter.h"
#include "third_party/blink/renderer/core/animation/list_interpolation_functions.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_names.h"
......@@ -52,28 +52,32 @@ void SetFilterList(const CSSProperty& property,
class UnderlyingFilterListChecker
: public CSSInterpolationType::CSSConversionChecker {
public:
UnderlyingFilterListChecker(
scoped_refptr<const NonInterpolableList> non_interpolable_list)
: non_interpolable_list_(std::move(non_interpolable_list)) {}
UnderlyingFilterListChecker(const InterpolableList* interpolable_list) {
wtf_size_t length = interpolable_list->length();
types_.ReserveInitialCapacity(length);
for (wtf_size_t i = 0; i < length; i++) {
types_.push_back(
To<InterpolableFilter>(interpolable_list->Get(i))->GetType());
}
}
bool IsValid(const StyleResolverState&,
const InterpolationValue& underlying) const final {
const NonInterpolableList& underlying_non_interpolable_list =
ToNonInterpolableList(*underlying.non_interpolable_value);
if (non_interpolable_list_->length() !=
underlying_non_interpolable_list.length())
const InterpolableList& underlying_list =
ToInterpolableList(*underlying.interpolable_value);
if (underlying_list.length() != types_.size())
return false;
for (wtf_size_t i = 0; i < non_interpolable_list_->length(); i++) {
if (!filter_interpolation_functions::FiltersAreCompatible(
*non_interpolable_list_->Get(i),
*underlying_non_interpolable_list.Get(i)))
for (wtf_size_t i = 0; i < types_.size(); i++) {
FilterOperation::OperationType other_type =
To<InterpolableFilter>(underlying_list.Get(i))->GetType();
if (types_[i] != other_type)
return false;
}
return true;
}
private:
scoped_refptr<const NonInterpolableList> non_interpolable_list_;
Vector<FilterOperation::OperationType> types_;
};
class InheritedFilterListChecker
......@@ -101,21 +105,15 @@ InterpolationValue ConvertFilterList(const FilterOperations& filter_operations,
double zoom) {
wtf_size_t length = filter_operations.size();
auto interpolable_list = std::make_unique<InterpolableList>(length);
Vector<scoped_refptr<const NonInterpolableValue>> non_interpolable_values(
length);
for (wtf_size_t i = 0; i < length; i++) {
InterpolationValue filter_result =
filter_interpolation_functions::MaybeConvertFilter(
*filter_operations.Operations()[i], zoom);
if (!filter_result)
std::unique_ptr<InterpolableFilter> result =
InterpolableFilter::MaybeCreate(*filter_operations.Operations()[i],
zoom);
if (!result)
return nullptr;
interpolable_list->Set(i, std::move(filter_result.interpolable_value));
non_interpolable_values[i] =
std::move(filter_result.non_interpolable_value);
interpolable_list->Set(i, std::move(result));
}
return InterpolationValue(
std::move(interpolable_list),
NonInterpolableList::Create(std::move(non_interpolable_values)));
return InterpolationValue(std::move(interpolable_list));
}
} // namespace
......@@ -123,13 +121,11 @@ InterpolationValue ConvertFilterList(const FilterOperations& filter_operations,
InterpolationValue CSSFilterListInterpolationType::MaybeConvertNeutral(
const InterpolationValue& underlying,
ConversionCheckers& conversion_checkers) const {
// const_cast for taking refs.
NonInterpolableList& non_interpolable_list = const_cast<NonInterpolableList&>(
ToNonInterpolableList(*underlying.non_interpolable_value));
const InterpolableList* interpolable_list =
ToInterpolableList(underlying.interpolable_value.get());
conversion_checkers.push_back(
std::make_unique<UnderlyingFilterListChecker>(&non_interpolable_list));
return InterpolationValue(underlying.interpolable_value->CloneAndZero(),
&non_interpolable_list);
std::make_unique<UnderlyingFilterListChecker>(interpolable_list));
return InterpolationValue(underlying.interpolable_value->CloneAndZero());
}
InterpolationValue CSSFilterListInterpolationType::MaybeConvertInitial(
......@@ -156,8 +152,7 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertValue(
ConversionCheckers&) const {
auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
if (identifier_value && identifier_value->GetValueID() == CSSValueID::kNone)
return InterpolationValue(std::make_unique<InterpolableList>(0),
NonInterpolableList::Create());
return InterpolationValue(std::make_unique<InterpolableList>(0));
if (!value.IsBaseValueList())
return nullptr;
......@@ -165,19 +160,14 @@ InterpolationValue CSSFilterListInterpolationType::MaybeConvertValue(
const auto& list = To<CSSValueList>(value);
wtf_size_t length = list.length();
auto interpolable_list = std::make_unique<InterpolableList>(length);
Vector<scoped_refptr<const NonInterpolableValue>> non_interpolable_values(
length);
for (wtf_size_t i = 0; i < length; i++) {
InterpolationValue item_result =
filter_interpolation_functions::MaybeConvertCSSFilter(list.Item(i));
if (!item_result)
std::unique_ptr<InterpolableFilter> result =
InterpolableFilter::MaybeConvertCSSValue(list.Item(i));
if (!result)
return nullptr;
interpolable_list->Set(i, std::move(item_result.interpolable_value));
non_interpolable_values[i] = std::move(item_result.non_interpolable_value);
interpolable_list->Set(i, std::move(result));
}
return InterpolationValue(
std::move(interpolable_list),
NonInterpolableList::Create(std::move(non_interpolable_values)));
return InterpolationValue(std::move(interpolable_list));
}
InterpolationValue
......@@ -190,38 +180,35 @@ CSSFilterListInterpolationType::MaybeConvertStandardPropertyUnderlyingValue(
PairwiseInterpolationValue CSSFilterListInterpolationType::MaybeMergeSingles(
InterpolationValue&& start,
InterpolationValue&& end) const {
const NonInterpolableList& start_non_interpolable_list =
ToNonInterpolableList(*start.non_interpolable_value);
const NonInterpolableList& end_non_interpolable_list =
ToNonInterpolableList(*end.non_interpolable_value);
wtf_size_t start_length = start_non_interpolable_list.length();
wtf_size_t end_length = end_non_interpolable_list.length();
InterpolableList& start_interpolable_list =
ToInterpolableList(*start.interpolable_value);
InterpolableList& end_interpolable_list =
ToInterpolableList(*end.interpolable_value);
wtf_size_t start_length = start_interpolable_list.length();
wtf_size_t end_length = end_interpolable_list.length();
for (wtf_size_t i = 0; i < start_length && i < end_length; i++) {
if (!filter_interpolation_functions::FiltersAreCompatible(
*start_non_interpolable_list.Get(i),
*end_non_interpolable_list.Get(i)))
if (To<InterpolableFilter>(start_interpolable_list.Get(i))->GetType() !=
To<InterpolableFilter>(end_interpolable_list.Get(i))->GetType())
return nullptr;
}
if (start_length == end_length) {
return PairwiseInterpolationValue(std::move(start.interpolable_value),
std::move(end.interpolable_value),
std::move(start.non_interpolable_value));
std::move(end.interpolable_value));
}
// Extend the shorter InterpolableList with neutral values that are compatible
// with corresponding filters in the longer list.
InterpolationValue& shorter = start_length < end_length ? start : end;
InterpolationValue& longer = start_length < end_length ? end : start;
wtf_size_t shorter_length =
ToNonInterpolableList(*shorter.non_interpolable_value).length();
wtf_size_t longer_length =
ToNonInterpolableList(*longer.non_interpolable_value).length();
InterpolableList& shorter_interpolable_list =
ToInterpolableList(*shorter.interpolable_value);
const NonInterpolableList& longer_non_interpolable_list =
ToNonInterpolableList(*longer.non_interpolable_value);
wtf_size_t shorter_length = std::min(start_length, end_length);
wtf_size_t longer_length = std::max(start_length, end_length);
InterpolableList& shorter_interpolable_list = start_length < end_length
? start_interpolable_list
: end_interpolable_list;
const InterpolableList& longer_interpolable_list =
start_length < end_length ? end_interpolable_list
: start_interpolable_list;
auto extended_interpolable_list =
std::make_unique<InterpolableList>(longer_length);
for (wtf_size_t i = 0; i < longer_length; i++) {
......@@ -230,14 +217,14 @@ PairwiseInterpolationValue CSSFilterListInterpolationType::MaybeMergeSingles(
i, std::move(shorter_interpolable_list.GetMutable(i)));
else
extended_interpolable_list->Set(
i, filter_interpolation_functions::CreateNoneValue(
*longer_non_interpolable_list.Get(i)));
i, InterpolableFilter::CreateInitialValue(
To<InterpolableFilter>(longer_interpolable_list.Get(i))
->GetType()));
}
shorter.interpolable_value = std::move(extended_interpolable_list);
return PairwiseInterpolationValue(std::move(start.interpolable_value),
std::move(end.interpolable_value),
std::move(longer.non_interpolable_value));
std::move(end.interpolable_value));
}
void CSSFilterListInterpolationType::Composite(
......@@ -245,44 +232,40 @@ void CSSFilterListInterpolationType::Composite(
double underlying_fraction,
const InterpolationValue& value,
double interpolation_fraction) const {
const NonInterpolableList& underlying_non_interpolable_list =
ToNonInterpolableList(
*underlying_value_owner.Value().non_interpolable_value);
const NonInterpolableList& non_interpolable_list =
ToNonInterpolableList(*value.non_interpolable_value);
wtf_size_t underlying_length = underlying_non_interpolable_list.length();
wtf_size_t length = non_interpolable_list.length();
// TODO(crbug.com/1005828): The below behavior is not correct for addition of
// filter values. Additive composition is defined as list concatenation in the
// spec: https://drafts.fxtf.org/filter-effects-1/#addition
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 (!filter_interpolation_functions::FiltersAreCompatible(
*underlying_non_interpolable_list.Get(i),
*non_interpolable_list.Get(i))) {
if (To<InterpolableFilter>(interpolable_list.Get(i))->GetType() !=
To<InterpolableFilter>(underlying_list.Get(i))->GetType()) {
underlying_value_owner.Set(*this, value);
return;
}
}
InterpolableList& underlying_interpolable_list = ToInterpolableList(
*underlying_value_owner.MutableValue().interpolable_value);
const InterpolableList& interpolable_list =
ToInterpolableList(*value.interpolable_value);
DCHECK_EQ(underlying_length, underlying_interpolable_list.length());
DCHECK_EQ(length, interpolable_list.length());
for (wtf_size_t i = 0; i < length && i < underlying_length; i++)
underlying_interpolable_list.GetMutable(i)->ScaleAndAdd(
underlying_fraction, *interpolable_list.Get(i));
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_interpolable_list.GetMutable(i)));
else
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);
......@@ -296,17 +279,14 @@ void CSSFilterListInterpolationType::ApplyStandardPropertyValue(
StyleResolverState& state) const {
const InterpolableList& interpolable_list =
ToInterpolableList(interpolable_value);
const NonInterpolableList& non_interpolable_list =
ToNonInterpolableList(*non_interpolable_value);
wtf_size_t length = interpolable_list.length();
DCHECK_EQ(length, non_interpolable_list.length());
FilterOperations filter_operations;
filter_operations.Operations().ReserveCapacity(length);
for (wtf_size_t i = 0; i < length; i++) {
filter_operations.Operations().push_back(
filter_interpolation_functions::CreateFilter(
*interpolable_list.Get(i), *non_interpolable_list.Get(i), state));
To<InterpolableFilter>(interpolable_list.Get(i))
->CreateFilterOperation(state));
}
SetFilterList(CssProperty(), *state.Style(), std::move(filter_operations));
}
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
#include <memory>
#include "third_party/blink/renderer/core/animation/interpolation_value.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class FilterOperation;
class CSSValue;
class StyleResolverState;
namespace filter_interpolation_functions {
InterpolationValue MaybeConvertCSSFilter(const CSSValue&);
InterpolationValue MaybeConvertFilter(const FilterOperation&, double zoom);
std::unique_ptr<InterpolableValue> CreateNoneValue(const NonInterpolableValue&);
bool FiltersAreCompatible(const NonInterpolableValue&,
const NonInterpolableValue&);
FilterOperation* CreateFilter(const InterpolableValue&,
const NonInterpolableValue&,
const StyleResolverState&);
} // namespace filter_interpolation_functions
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_FILTER_INTERPOLATION_FUNCTIONS_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/animation/filter_interpolation_functions.h"
#include <memory>
#include "third_party/blink/renderer/core/animation/interpolable_filter.h"
#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/animation/interpolable_shadow.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_shadow_value.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
#include "third_party/blink/renderer/core/style/filter_operations.h"
#include "third_party/blink/renderer/core/style/shadow_data.h"
namespace blink {
class FilterNonInterpolableValue : public NonInterpolableValue {
public:
static scoped_refptr<FilterNonInterpolableValue> Create(
FilterOperation::OperationType type,
scoped_refptr<const NonInterpolableValue> type_non_interpolable_value) {
return base::AdoptRef(new FilterNonInterpolableValue(
type, std::move(type_non_interpolable_value)));
}
FilterOperation::OperationType GetOperationType() const { return type_; }
const NonInterpolableValue* TypeNonInterpolableValue() const {
return type_non_interpolable_value_.get();
}
DECLARE_NON_INTERPOLABLE_VALUE_TYPE();
private:
FilterNonInterpolableValue(
FilterOperation::OperationType type,
scoped_refptr<const NonInterpolableValue> type_non_interpolable_value)
: type_(type),
type_non_interpolable_value_(std::move(type_non_interpolable_value)) {}
const FilterOperation::OperationType type_;
scoped_refptr<const NonInterpolableValue> type_non_interpolable_value_;
};
DEFINE_NON_INTERPOLABLE_VALUE_TYPE(FilterNonInterpolableValue);
DEFINE_NON_INTERPOLABLE_VALUE_TYPE_CASTS(FilterNonInterpolableValue);
namespace {
double ClampParameter(double value, FilterOperation::OperationType type) {
switch (type) {
case FilterOperation::BRIGHTNESS:
......@@ -69,184 +35,168 @@ double ClampParameter(double value, FilterOperation::OperationType type) {
return 0;
}
}
} // namespace
InterpolationValue filter_interpolation_functions::MaybeConvertCSSFilter(
const CSSValue& value) {
if (value.IsURIValue())
return nullptr;
const auto& filter = To<CSSFunctionValue>(value);
DCHECK_LE(filter.length(), 1u);
FilterOperation::OperationType type =
FilterOperationResolver::FilterOperationForType(filter.FunctionType());
InterpolationValue result = nullptr;
// static
std::unique_ptr<InterpolableFilter> InterpolableFilter::MaybeCreate(
const FilterOperation& filter,
double zoom) {
std::unique_ptr<InterpolableValue> value = nullptr;
FilterOperation::OperationType type = filter.GetType();
switch (type) {
case FilterOperation::GRAYSCALE:
case FilterOperation::HUE_ROTATE:
case FilterOperation::SATURATE:
case FilterOperation::SEPIA:
value = std::make_unique<InterpolableNumber>(
To<BasicColorMatrixFilterOperation>(filter).Amount());
break;
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::GRAYSCALE:
case FilterOperation::INVERT:
case FilterOperation::OPACITY:
case FilterOperation::SATURATE:
case FilterOperation::SEPIA:
case FilterOperation::HUE_ROTATE:
result.interpolable_value = std::make_unique<InterpolableNumber>(
FilterOperationResolver::ResolveNumericArgumentForFunction(filter));
value = std::make_unique<InterpolableNumber>(
To<BasicComponentTransferFilterOperation>(filter).Amount());
break;
case FilterOperation::BLUR: {
if (filter.length() == 0) {
result.interpolable_value = InterpolableLength::CreateNeutral();
} else {
result = InterpolationValue(
InterpolableLength::MaybeConvertCSSValue(filter.Item(0)));
}
case FilterOperation::BLUR:
value = InterpolableLength::MaybeConvertLength(
To<BlurFilterOperation>(filter).StdDeviation(), zoom);
break;
}
case FilterOperation::DROP_SHADOW:
result.interpolable_value =
InterpolableShadow::MaybeConvertCSSValue(filter.Item(0));
value = InterpolableShadow::Create(
To<DropShadowFilterOperation>(filter).Shadow(), zoom);
break;
case FilterOperation::REFERENCE:
return nullptr;
default:
NOTREACHED();
return nullptr;
}
if (!result)
if (!value)
return nullptr;
result.non_interpolable_value = FilterNonInterpolableValue::Create(
type, std::move(result.non_interpolable_value));
return result;
return std::make_unique<InterpolableFilter>(std::move(value), type);
}
InterpolationValue filter_interpolation_functions::MaybeConvertFilter(
const FilterOperation& filter,
double zoom) {
InterpolationValue result = nullptr;
// static
std::unique_ptr<InterpolableFilter> InterpolableFilter::MaybeConvertCSSValue(
const CSSValue& css_value) {
if (css_value.IsURIValue())
return nullptr;
switch (filter.GetType()) {
case FilterOperation::GRAYSCALE:
case FilterOperation::HUE_ROTATE:
case FilterOperation::SATURATE:
case FilterOperation::SEPIA:
result.interpolable_value = std::make_unique<InterpolableNumber>(
To<BasicColorMatrixFilterOperation>(filter).Amount());
break;
const auto& filter = To<CSSFunctionValue>(css_value);
DCHECK_LE(filter.length(), 1u);
std::unique_ptr<InterpolableValue> value = nullptr;
FilterOperation::OperationType type =
FilterOperationResolver::FilterOperationForType(filter.FunctionType());
switch (type) {
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::GRAYSCALE:
case FilterOperation::INVERT:
case FilterOperation::OPACITY:
result.interpolable_value = std::make_unique<InterpolableNumber>(
To<BasicComponentTransferFilterOperation>(filter).Amount());
case FilterOperation::SATURATE:
case FilterOperation::SEPIA:
case FilterOperation::HUE_ROTATE:
value = std::make_unique<InterpolableNumber>(
FilterOperationResolver::ResolveNumericArgumentForFunction(filter));
break;
case FilterOperation::BLUR:
result = InterpolationValue(InterpolableLength::MaybeConvertLength(
To<BlurFilterOperation>(filter).StdDeviation(), zoom));
value = filter.length() > 0
? InterpolableLength::MaybeConvertCSSValue(filter.Item(0))
: InterpolableLength::CreateNeutral();
break;
case FilterOperation::DROP_SHADOW:
result.interpolable_value = InterpolableShadow::Create(
To<DropShadowFilterOperation>(filter).Shadow(), zoom);
value = InterpolableShadow::MaybeConvertCSSValue(filter.Item(0));
break;
case FilterOperation::REFERENCE:
return nullptr;
default:
NOTREACHED();
return nullptr;
}
if (!result)
if (!value)
return nullptr;
result.non_interpolable_value = FilterNonInterpolableValue::Create(
filter.GetType(), std::move(result.non_interpolable_value));
return result;
return std::make_unique<InterpolableFilter>(std::move(value), type);
}
std::unique_ptr<InterpolableValue>
filter_interpolation_functions::CreateNoneValue(
const NonInterpolableValue& untyped_value) {
switch (ToFilterNonInterpolableValue(untyped_value).GetOperationType()) {
// static
std::unique_ptr<InterpolableFilter> InterpolableFilter::CreateInitialValue(
FilterOperation::OperationType type) {
// See https://drafts.fxtf.org/filter-effects-1/#filter-functions for the
// mapping of OperationType to initial value.
std::unique_ptr<InterpolableValue> value = nullptr;
switch (type) {
case FilterOperation::GRAYSCALE:
case FilterOperation::INVERT:
case FilterOperation::SEPIA:
case FilterOperation::HUE_ROTATE:
return std::make_unique<InterpolableNumber>(0);
value = std::make_unique<InterpolableNumber>(0);
break;
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::OPACITY:
case FilterOperation::SATURATE:
return std::make_unique<InterpolableNumber>(1);
value = std::make_unique<InterpolableNumber>(1);
break;
case FilterOperation::BLUR:
return InterpolableLength::CreateNeutral();
value = InterpolableLength::CreateNeutral();
break;
case FilterOperation::DROP_SHADOW:
return InterpolableShadow::CreateNeutral();
value = InterpolableShadow::CreateNeutral();
break;
default:
NOTREACHED();
return nullptr;
}
}
bool filter_interpolation_functions::FiltersAreCompatible(
const NonInterpolableValue& a,
const NonInterpolableValue& b) {
return ToFilterNonInterpolableValue(a).GetOperationType() ==
ToFilterNonInterpolableValue(b).GetOperationType();
return std::make_unique<InterpolableFilter>(std::move(value), type);
}
FilterOperation* filter_interpolation_functions::CreateFilter(
const InterpolableValue& interpolable_value,
const NonInterpolableValue& untyped_non_interpolable_value,
const StyleResolverState& state) {
const FilterNonInterpolableValue& non_interpolable_value =
ToFilterNonInterpolableValue(untyped_non_interpolable_value);
FilterOperation::OperationType type =
non_interpolable_value.GetOperationType();
switch (type) {
FilterOperation* InterpolableFilter::CreateFilterOperation(
const StyleResolverState& state) const {
switch (type_) {
case FilterOperation::GRAYSCALE:
case FilterOperation::HUE_ROTATE:
case FilterOperation::SATURATE:
case FilterOperation::SEPIA: {
double value = ClampParameter(
ToInterpolableNumber(interpolable_value).Value(), type);
return MakeGarbageCollected<BasicColorMatrixFilterOperation>(value, type);
double value =
ClampParameter(ToInterpolableNumber(*value_).Value(), type_);
return MakeGarbageCollected<BasicColorMatrixFilterOperation>(value,
type_);
}
case FilterOperation::BRIGHTNESS:
case FilterOperation::CONTRAST:
case FilterOperation::INVERT:
case FilterOperation::OPACITY: {
double value = ClampParameter(
ToInterpolableNumber(interpolable_value).Value(), type);
double value =
ClampParameter(ToInterpolableNumber(*value_).Value(), type_);
return MakeGarbageCollected<BasicComponentTransferFilterOperation>(value,
type);
type_);
}
case FilterOperation::BLUR: {
Length std_deviation =
To<InterpolableLength>(interpolable_value)
.CreateLength(state.CssToLengthConversionData(),
kValueRangeNonNegative);
Length std_deviation = To<InterpolableLength>(*value_).CreateLength(
state.CssToLengthConversionData(), kValueRangeNonNegative);
return MakeGarbageCollected<BlurFilterOperation>(std_deviation);
}
case FilterOperation::DROP_SHADOW: {
ShadowData shadow_data =
To<InterpolableShadow>(interpolable_value).CreateShadowData(state);
To<InterpolableShadow>(*value_).CreateShadowData(state);
if (shadow_data.GetColor().IsCurrentColor())
shadow_data.OverrideColor(Color::kBlack);
return DropShadowFilterOperation::Create(shadow_data);
......@@ -258,4 +208,18 @@ FilterOperation* filter_interpolation_functions::CreateFilter(
}
}
void InterpolableFilter::AssertCanInterpolateWith(
const InterpolableValue& other) const {
DCHECK(other.IsFilter());
DCHECK_EQ(type_, To<InterpolableFilter>(other).type_);
}
void InterpolableFilter::Interpolate(const InterpolableValue& to,
const double progress,
InterpolableValue& result) const {
const InterpolableFilter& filter_to = To<InterpolableFilter>(to);
InterpolableFilter& filter_result = To<InterpolableFilter>(result);
value_->Interpolate(*filter_to.value_, progress, *filter_result.value_);
}
} // namespace blink
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
#include <memory>
#include "third_party/blink/renderer/core/animation/interpolable_value.h"
#include "third_party/blink/renderer/core/style/filter_operation.h"
namespace blink {
class CSSValue;
class StyleResolverState;
// Represents a blink::FilterOperation, converted into a form that can be
// interpolated from/to.
class CORE_EXPORT InterpolableFilter final : public InterpolableValue {
public:
InterpolableFilter(std::unique_ptr<InterpolableValue> value,
FilterOperation::OperationType type)
: value_(std::move(value)), type_(type) {
DCHECK(value_);
}
static std::unique_ptr<InterpolableFilter> MaybeCreate(const FilterOperation&,
double zoom);
static std::unique_ptr<InterpolableFilter> MaybeConvertCSSValue(
const CSSValue&);
// Create an InterpolableFilter representing the 'initial value for
// interpolation' for the given OperationType.
static std::unique_ptr<InterpolableFilter> CreateInitialValue(
FilterOperation::OperationType);
FilterOperation::OperationType GetType() const { return type_; }
// Convert this InterpolableFilter back into a FilterOperation class, usually
// to be applied to the style after interpolating |this|.
FilterOperation* CreateFilterOperation(const StyleResolverState&) const;
// InterpolableValue implementation:
void Interpolate(const InterpolableValue& to,
const double progress,
InterpolableValue& result) const final;
bool IsFilter() const final { return true; }
bool Equals(const InterpolableValue& other) const final {
NOTREACHED();
return false;
}
void Scale(double scale) final { NOTREACHED(); }
void ScaleAndAdd(double scale, const InterpolableValue& other) final {
value_->ScaleAndAdd(scale, *To<InterpolableFilter>(other).value_);
}
void AssertCanInterpolateWith(const InterpolableValue& other) const final;
private:
InterpolableFilter* RawClone() const final {
return new InterpolableFilter(value_->Clone(), type_);
}
InterpolableFilter* RawCloneAndZero() const final {
return new InterpolableFilter(value_->CloneAndZero(), type_);
}
// Stores the interpolable data for the filter. The form varies depending on
// the |type_|; see the implementation file for details of the mapping.
std::unique_ptr<InterpolableValue> value_;
FilterOperation::OperationType type_;
};
template <>
struct DowncastTraits<InterpolableFilter> {
static bool AllowFrom(const InterpolableValue& interpolable_value) {
return interpolable_value.IsFilter();
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_FILTER_H_
......@@ -39,6 +39,7 @@ class CORE_EXPORT InterpolableValue {
virtual bool IsList() const { return false; }
virtual bool IsLength() const { return false; }
virtual bool IsShadow() const { return false; }
virtual bool IsFilter() const { return false; }
// TODO(alancutter): Remove Equals().
virtual bool Equals(const InterpolableValue&) const = 0;
......
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