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..4aa5f752495f2ca98df6a250b4612dd241a494ad 100644 |
--- a/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp |
+++ b/third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp |
@@ -48,12 +48,28 @@ 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::kLowestCommonMultiple) { |
+ return lowestCommonMultiple(start_length, end_length); |
+ } |
+ DCHECK_EQ(length_matching_strategy, |
+ ListInterpolationFunctions::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 +93,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 +112,41 @@ 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 == 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, 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 +181,58 @@ 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::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 +242,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 +257,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 +267,54 @@ 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 == 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, 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); |
+ } |
} |
} |