| Index: third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp
|
| diff --git a/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp b/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp
|
| index 82b26f7cec11992684c1e2908b0a758aa0b42ac0..6f39102e39f4de4f5ac855dcb6028d25c720bfb3 100644
|
| --- a/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp
|
| +++ b/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp
|
| @@ -48,12 +48,29 @@ bool ListInterpolationFunctions::EqualValues(
|
| return true;
|
| }
|
|
|
| +static size_t MatchLengths(size_t start_length,
|
| + size_t end_length,
|
| + ListInterpolationFunctions::LengthMatchingStrategy
|
| + length_matching_strategy) {
|
| + if (length_matching_strategy ==
|
| + ListInterpolationFunctions::LengthMatchingStrategy::
|
| + kLowestCommonMultiple) {
|
| + return lowestCommonMultiple(start_length, end_length);
|
| + }
|
| + DCHECK_EQ(length_matching_strategy,
|
| + ListInterpolationFunctions::LengthMatchingStrategy::kPadToLargest);
|
| + return std::max(start_length, end_length);
|
| +}
|
| +
|
| PairwiseInterpolationValue ListInterpolationFunctions::MaybeMergeSingles(
|
| InterpolationValue&& start,
|
| InterpolationValue&& end,
|
| + LengthMatchingStrategy length_matching_strategy,
|
| MergeSingleItemConversionsCallback merge_single_item_conversions) {
|
| - size_t start_length = ToInterpolableList(*start.interpolable_value).length();
|
| - size_t end_length = ToInterpolableList(*end.interpolable_value).length();
|
| + const size_t start_length =
|
| + ToInterpolableList(*start.interpolable_value).length();
|
| + const size_t end_length =
|
| + ToInterpolableList(*end.interpolable_value).length();
|
|
|
| if (start_length == 0 && end_length == 0) {
|
| return PairwiseInterpolationValue(std::move(start.interpolable_value),
|
| @@ -77,7 +94,8 @@ PairwiseInterpolationValue ListInterpolationFunctions::MaybeMergeSingles(
|
| std::move(start.non_interpolable_value));
|
| }
|
|
|
| - size_t final_length = lowestCommonMultiple(start_length, end_length);
|
| + const size_t final_length =
|
| + MatchLengths(start_length, end_length, length_matching_strategy);
|
| std::unique_ptr<InterpolableList> result_start_interpolable_list =
|
| InterpolableList::Create(final_length);
|
| std::unique_ptr<InterpolableList> result_end_interpolable_list =
|
| @@ -95,21 +113,43 @@ PairwiseInterpolationValue ListInterpolationFunctions::MaybeMergeSingles(
|
| ToNonInterpolableList(*end.non_interpolable_value);
|
|
|
| for (size_t i = 0; i < final_length; i++) {
|
| - InterpolationValue start(
|
| - start_interpolable_list.Get(i % start_length)->Clone(),
|
| - start_non_interpolable_list.Get(i % start_length));
|
| - InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(),
|
| - end_non_interpolable_list.Get(i % end_length));
|
| - PairwiseInterpolationValue result =
|
| - merge_single_item_conversions(std::move(start), std::move(end));
|
| - if (!result)
|
| - return nullptr;
|
| - result_start_interpolable_list->Set(
|
| - i, std::move(result.start_interpolable_value));
|
| - result_end_interpolable_list->Set(i,
|
| - std::move(result.end_interpolable_value));
|
| - result_non_interpolable_values[i] =
|
| - std::move(result.non_interpolable_value);
|
| + PairwiseInterpolationValue result = nullptr;
|
| + if (length_matching_strategy ==
|
| + LengthMatchingStrategy::kLowestCommonMultiple ||
|
| + (i < start_length && i < end_length)) {
|
| + InterpolationValue start(
|
| + start_interpolable_list.Get(i % start_length)->Clone(),
|
| + start_non_interpolable_list.Get(i % start_length));
|
| + InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(),
|
| + end_non_interpolable_list.Get(i % end_length));
|
| + PairwiseInterpolationValue result =
|
| + merge_single_item_conversions(std::move(start), std::move(end));
|
| + if (!result)
|
| + return nullptr;
|
| + result_start_interpolable_list->Set(
|
| + i, std::move(result.start_interpolable_value));
|
| + result_end_interpolable_list->Set(
|
| + i, std::move(result.end_interpolable_value));
|
| + result_non_interpolable_values[i] =
|
| + std::move(result.non_interpolable_value);
|
| + } else {
|
| + DCHECK_EQ(length_matching_strategy,
|
| + LengthMatchingStrategy::kPadToLargest);
|
| + if (i < start_length) {
|
| + result_start_interpolable_list->Set(
|
| + i, start_interpolable_list.Get(i)->Clone());
|
| + result_end_interpolable_list->Set(
|
| + i, start_interpolable_list.Get(i)->CloneAndZero());
|
| + result_non_interpolable_values[i] = start_non_interpolable_list.Get(i);
|
| + } else {
|
| + DCHECK_LT(i, end_length);
|
| + result_start_interpolable_list->Set(
|
| + i, end_interpolable_list.Get(i)->CloneAndZero());
|
| + result_end_interpolable_list->Set(
|
| + i, end_interpolable_list.Get(i)->Clone());
|
| + result_non_interpolable_values[i] = end_non_interpolable_list.Get(i);
|
| + }
|
| + }
|
| }
|
|
|
| return PairwiseInterpolationValue(
|
| @@ -144,16 +184,59 @@ static void RepeatToLength(InterpolationValue& value, size_t length) {
|
| NonInterpolableList::Create(std::move(new_non_interpolable_values));
|
| }
|
|
|
| +// This helper function makes value the same length as length_value by
|
| +// CloneAndZero-ing the additional items from length_value into value.
|
| +static void PadToSameLength(InterpolationValue& value,
|
| + const InterpolationValue& length_value) {
|
| + InterpolableList& interpolable_list =
|
| + ToInterpolableList(*value.interpolable_value);
|
| + NonInterpolableList& non_interpolable_list =
|
| + ToNonInterpolableList(*value.non_interpolable_value);
|
| + const size_t current_length = interpolable_list.length();
|
| + InterpolableList& target_interpolable_list =
|
| + ToInterpolableList(*length_value.interpolable_value);
|
| + NonInterpolableList& target_non_interpolable_list =
|
| + ToNonInterpolableList(*length_value.non_interpolable_value);
|
| + const size_t target_length = target_interpolable_list.length();
|
| + DCHECK_LT(current_length, target_length);
|
| + std::unique_ptr<InterpolableList> new_interpolable_list =
|
| + InterpolableList::Create(target_length);
|
| + Vector<RefPtr<NonInterpolableValue>> new_non_interpolable_values(
|
| + target_length);
|
| + size_t index = 0;
|
| + for (; index < current_length; index++) {
|
| + new_interpolable_list->Set(index,
|
| + std::move(interpolable_list.GetMutable(index)));
|
| + new_non_interpolable_values[index] = non_interpolable_list.Get(index);
|
| + }
|
| + for (; index < target_length; index++) {
|
| + new_interpolable_list->Set(
|
| + index, target_interpolable_list.Get(index)->CloneAndZero());
|
| + new_non_interpolable_values[index] =
|
| + target_non_interpolable_list.Get(index);
|
| + }
|
| + value.interpolable_value = std::move(new_interpolable_list);
|
| + value.non_interpolable_value =
|
| + NonInterpolableList::Create(std::move(new_non_interpolable_values));
|
| +}
|
| +
|
| static bool NonInterpolableListsAreCompatible(
|
| const NonInterpolableList& a,
|
| const NonInterpolableList& b,
|
| size_t length,
|
| + ListInterpolationFunctions::LengthMatchingStrategy length_matching_strategy,
|
| ListInterpolationFunctions::NonInterpolableValuesAreCompatibleCallback
|
| non_interpolable_values_are_compatible) {
|
| for (size_t i = 0; i < length; i++) {
|
| - if (!non_interpolable_values_are_compatible(a.Get(i % a.length()),
|
| - b.Get(i % b.length())))
|
| - return false;
|
| + if (length_matching_strategy ==
|
| + ListInterpolationFunctions::LengthMatchingStrategy::
|
| + kLowestCommonMultiple ||
|
| + (i < a.length() && i < b.length())) {
|
| + if (!non_interpolable_values_are_compatible(a.Get(i % a.length()),
|
| + b.Get(i % b.length()))) {
|
| + return false;
|
| + }
|
| + }
|
| }
|
| return true;
|
| }
|
| @@ -163,10 +246,11 @@ void ListInterpolationFunctions::Composite(
|
| double underlying_fraction,
|
| const InterpolationType& type,
|
| const InterpolationValue& value,
|
| + LengthMatchingStrategy length_matching_strategy,
|
| NonInterpolableValuesAreCompatibleCallback
|
| non_interpolable_values_are_compatible,
|
| CompositeItemCallback composite_item) {
|
| - size_t underlying_length =
|
| + const size_t underlying_length =
|
| ToInterpolableList(*underlying_value_owner.Value().interpolable_value)
|
| .length();
|
| if (underlying_length == 0) {
|
| @@ -177,7 +261,7 @@ void ListInterpolationFunctions::Composite(
|
|
|
| const InterpolableList& interpolable_list =
|
| ToInterpolableList(*value.interpolable_value);
|
| - size_t value_length = interpolable_list.length();
|
| + const size_t value_length = interpolable_list.length();
|
| if (value_length == 0) {
|
| DCHECK(!value.non_interpolable_value);
|
| underlying_value_owner.MutableValue().interpolable_value->Scale(
|
| @@ -187,30 +271,55 @@ void ListInterpolationFunctions::Composite(
|
|
|
| const NonInterpolableList& non_interpolable_list =
|
| ToNonInterpolableList(*value.non_interpolable_value);
|
| - size_t new_length = lowestCommonMultiple(underlying_length, value_length);
|
| + const size_t final_length =
|
| + MatchLengths(underlying_length, value_length, length_matching_strategy);
|
| if (!NonInterpolableListsAreCompatible(
|
| ToNonInterpolableList(
|
| *underlying_value_owner.Value().non_interpolable_value),
|
| - non_interpolable_list, new_length,
|
| + non_interpolable_list, final_length, length_matching_strategy,
|
| non_interpolable_values_are_compatible)) {
|
| underlying_value_owner.Set(type, value);
|
| return;
|
| }
|
|
|
| InterpolationValue& underlying_value = underlying_value_owner.MutableValue();
|
| - if (underlying_length < new_length)
|
| - RepeatToLength(underlying_value, new_length);
|
| -
|
| - InterpolableList& underlying_interpolable_list =
|
| - ToInterpolableList(*underlying_value.interpolable_value);
|
| - NonInterpolableList& underlying_non_interpolable_list =
|
| - ToNonInterpolableList(*underlying_value.non_interpolable_value);
|
| - for (size_t i = 0; i < new_length; i++) {
|
| - composite_item(underlying_interpolable_list.GetMutable(i),
|
| - underlying_non_interpolable_list.GetMutable(i),
|
| - underlying_fraction,
|
| - *interpolable_list.Get(i % value_length),
|
| - non_interpolable_list.Get(i % value_length));
|
| + if (length_matching_strategy ==
|
| + LengthMatchingStrategy::kLowestCommonMultiple) {
|
| + if (underlying_length < final_length) {
|
| + RepeatToLength(underlying_value, final_length);
|
| + }
|
| + InterpolableList& underlying_interpolable_list =
|
| + ToInterpolableList(*underlying_value.interpolable_value);
|
| + NonInterpolableList& underlying_non_interpolable_list =
|
| + ToNonInterpolableList(*underlying_value.non_interpolable_value);
|
| +
|
| + for (size_t i = 0; i < final_length; i++) {
|
| + composite_item(underlying_interpolable_list.GetMutable(i),
|
| + underlying_non_interpolable_list.GetMutable(i),
|
| + underlying_fraction,
|
| + *interpolable_list.Get(i % value_length),
|
| + non_interpolable_list.Get(i % value_length));
|
| + }
|
| + } else {
|
| + DCHECK_EQ(length_matching_strategy, LengthMatchingStrategy::kPadToLargest);
|
| + if (underlying_length < final_length) {
|
| + DCHECK_EQ(value_length, final_length);
|
| + PadToSameLength(underlying_value, value);
|
| + }
|
| + InterpolableList& underlying_interpolable_list =
|
| + ToInterpolableList(*underlying_value.interpolable_value);
|
| + NonInterpolableList& underlying_non_interpolable_list =
|
| + ToNonInterpolableList(*underlying_value.non_interpolable_value);
|
| +
|
| + for (size_t i = 0; i < value_length; i++) {
|
| + composite_item(underlying_interpolable_list.GetMutable(i),
|
| + underlying_non_interpolable_list.GetMutable(i),
|
| + underlying_fraction, *interpolable_list.Get(i),
|
| + non_interpolable_list.Get(i));
|
| + }
|
| + for (size_t i = value_length; i < final_length; i++) {
|
| + underlying_interpolable_list.GetMutable(i)->Scale(underlying_fraction);
|
| + }
|
| }
|
| }
|
|
|
|
|