blob: 509839e11f3ad70baf246aad546306f7e764dd1f [file] [log] [blame]
// Copyright 2018 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/css_custom_list_interpolation_type.h"
#include "third_party/blink/renderer/core/animation/interpolable_length.h"
#include "third_party/blink/renderer/core/animation/underlying_length_checker.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
InterpolationValue CSSCustomListInterpolationType::MaybeConvertNeutral(
const InterpolationValue& underlying,
ConversionCheckers& conversion_checkers) const {
size_t underlying_length =
UnderlyingLengthChecker::GetUnderlyingLength(underlying);
conversion_checkers.push_back(
std::make_unique<UnderlyingLengthChecker>(underlying_length));
if (underlying_length == 0)
return nullptr;
InterpolationValue null_underlying(nullptr);
ConversionCheckers null_checkers;
auto convert_inner = [this, &null_underlying, &null_checkers](size_t) {
return this->inner_interpolation_type_->MaybeConvertNeutral(null_underlying,
null_checkers);
};
return ListInterpolationFunctions::CreateList(underlying_length,
convert_inner);
}
InterpolationValue CSSCustomListInterpolationType::MaybeConvertValue(
const CSSValue& value,
const StyleResolverState* state,
ConversionCheckers&) const {
const auto* list = DynamicTo<CSSValueList>(value);
if (!list)
return nullptr;
ConversionCheckers null_checkers;
return ListInterpolationFunctions::CreateList(
list->length(), [this, list, state, &null_checkers](size_t index) {
return this->inner_interpolation_type_->MaybeConvertValue(
list->Item(index), state, null_checkers);
});
}
const CSSValue* CSSCustomListInterpolationType::CreateCSSValue(
const InterpolableValue& interpolable_value,
const NonInterpolableValue* non_interpolable_value,
const StyleResolverState& state) const {
const auto& interpolable_list = To<InterpolableList>(interpolable_value);
const auto* non_interpolable_list =
DynamicTo<NonInterpolableList>(*non_interpolable_value);
CSSValueList* list = nullptr;
switch (syntax_repeat_) {
default:
NOTREACHED();
FALLTHROUGH;
case CSSSyntaxRepeat::kSpaceSeparated:
list = CSSValueList::CreateSpaceSeparated();
break;
case CSSSyntaxRepeat::kCommaSeparated:
list = CSSValueList::CreateCommaSeparated();
break;
}
DCHECK(!non_interpolable_list ||
interpolable_list.length() == non_interpolable_list->length());
for (size_t i = 0; i < interpolable_list.length(); ++i) {
const NonInterpolableValue* non_interpolable_single_value =
non_interpolable_list ? non_interpolable_list->Get(i) : nullptr;
list->Append(*inner_interpolation_type_->CreateCSSValue(
*interpolable_list.Get(i), non_interpolable_single_value, state));
}
return list;
}
void CSSCustomListInterpolationType::Composite(
UnderlyingValueOwner& underlying_value_owner,
double underlying_fraction,
const InterpolationValue& value,
double interpolation_fraction) const {
// This adapts a ListInterpolationFunctions::CompositeItemCallback function
// such that we can use the InterpolationType::Composite function of the
// inner interpolation type to get the answer.
//
// TODO(andruud): Make InterpolationType::Composite take an UnderlyingValue
// rather than an UnderlyingValueOwner.
auto composite_callback =
[](const CSSInterpolationType* interpolation_type,
double interpolation_fraction, UnderlyingValue& underlying_value,
double underlying_fraction,
const InterpolableValue& interpolable_value,
const NonInterpolableValue* non_interpolable_value) {
UnderlyingValueOwner owner;
owner.Set(*interpolation_type,
InterpolationValue(
underlying_value.MutableInterpolableValue().Clone(),
underlying_value.GetNonInterpolableValue()));
InterpolationValue interpolation_value(interpolable_value.Clone(),
non_interpolable_value);
interpolation_type->Composite(owner, underlying_fraction,
interpolation_value,
interpolation_fraction);
underlying_value.SetInterpolableValue(
owner.Value().Clone().interpolable_value);
underlying_value.SetNonInterpolableValue(
owner.GetNonInterpolableValue());
};
ListInterpolationFunctions::Composite(
underlying_value_owner, underlying_fraction, *this, value,
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
WTF::BindRepeating(
ListInterpolationFunctions::InterpolableValuesKnownCompatible),
GetNonInterpolableValuesAreCompatibleCallback(),
WTF::BindRepeating(composite_callback,
WTF::Unretained(inner_interpolation_type_.get()),
interpolation_fraction));
}
PairwiseInterpolationValue CSSCustomListInterpolationType::MaybeMergeSingles(
InterpolationValue&& start,
InterpolationValue&& end) const {
return ListInterpolationFunctions::MaybeMergeSingles(
std::move(start), std::move(end),
ListInterpolationFunctions::LengthMatchingStrategy::kEqual,
WTF::BindRepeating(&CSSInterpolationType::MaybeMergeSingles,
WTF::Unretained(inner_interpolation_type_.get())));
}
ListInterpolationFunctions::NonInterpolableValuesAreCompatibleCallback
CSSCustomListInterpolationType::GetNonInterpolableValuesAreCompatibleCallback()
const {
// TODO(https://crbug.com/981537): Add support for <image> here.
// TODO(https://crbug.com/981538): Add support for <transform-function> here.
// TODO(https://crbug.com/981542): Add support for <transform-list> here.
return WTF::BindRepeating(
ListInterpolationFunctions::VerifyNoNonInterpolableValues);
}
} // namespace blink