OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/animation/ListInterpolationFunctions.h" | 5 #include "core/animation/ListInterpolationFunctions.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "core/animation/UnderlyingValueOwner.h" | 8 #include "core/animation/UnderlyingValueOwner.h" |
9 #include "core/css/CSSValueList.h" | 9 #include "core/css/CSSValueList.h" |
10 #include "platform/wtf/MathExtras.h" | 10 #include "platform/wtf/MathExtras.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 ToNonInterpolableList(*b.non_interpolable_value); | 41 ToNonInterpolableList(*b.non_interpolable_value); |
42 | 42 |
43 for (size_t i = 0; i < length; i++) { | 43 for (size_t i = 0; i < length; i++) { |
44 if (!equal_non_interpolable_values(non_interpolable_list_a.Get(i), | 44 if (!equal_non_interpolable_values(non_interpolable_list_a.Get(i), |
45 non_interpolable_list_b.Get(i))) | 45 non_interpolable_list_b.Get(i))) |
46 return false; | 46 return false; |
47 } | 47 } |
48 return true; | 48 return true; |
49 } | 49 } |
50 | 50 |
| 51 static size_t MatchLengths(size_t start_length, |
| 52 size_t end_length, |
| 53 ListInterpolationFunctions::LengthMatchingStrategy |
| 54 length_matching_strategy) { |
| 55 if (length_matching_strategy == |
| 56 ListInterpolationFunctions::kLowestCommonMultiple) { |
| 57 return lowestCommonMultiple(start_length, end_length); |
| 58 } |
| 59 DCHECK_EQ(length_matching_strategy, |
| 60 ListInterpolationFunctions::kPadToLargest); |
| 61 return std::max(start_length, end_length); |
| 62 } |
| 63 |
51 PairwiseInterpolationValue ListInterpolationFunctions::MaybeMergeSingles( | 64 PairwiseInterpolationValue ListInterpolationFunctions::MaybeMergeSingles( |
52 InterpolationValue&& start, | 65 InterpolationValue&& start, |
53 InterpolationValue&& end, | 66 InterpolationValue&& end, |
| 67 LengthMatchingStrategy length_matching_strategy, |
54 MergeSingleItemConversionsCallback merge_single_item_conversions) { | 68 MergeSingleItemConversionsCallback merge_single_item_conversions) { |
55 size_t start_length = ToInterpolableList(*start.interpolable_value).length(); | 69 const size_t start_length = |
56 size_t end_length = ToInterpolableList(*end.interpolable_value).length(); | 70 ToInterpolableList(*start.interpolable_value).length(); |
| 71 const size_t end_length = |
| 72 ToInterpolableList(*end.interpolable_value).length(); |
57 | 73 |
58 if (start_length == 0 && end_length == 0) { | 74 if (start_length == 0 && end_length == 0) { |
59 return PairwiseInterpolationValue(std::move(start.interpolable_value), | 75 return PairwiseInterpolationValue(std::move(start.interpolable_value), |
60 std::move(end.interpolable_value), | 76 std::move(end.interpolable_value), |
61 nullptr); | 77 nullptr); |
62 } | 78 } |
63 | 79 |
64 if (start_length == 0) { | 80 if (start_length == 0) { |
65 std::unique_ptr<InterpolableValue> start_interpolable_value = | 81 std::unique_ptr<InterpolableValue> start_interpolable_value = |
66 end.interpolable_value->CloneAndZero(); | 82 end.interpolable_value->CloneAndZero(); |
67 return PairwiseInterpolationValue(std::move(start_interpolable_value), | 83 return PairwiseInterpolationValue(std::move(start_interpolable_value), |
68 std::move(end.interpolable_value), | 84 std::move(end.interpolable_value), |
69 std::move(end.non_interpolable_value)); | 85 std::move(end.non_interpolable_value)); |
70 } | 86 } |
71 | 87 |
72 if (end_length == 0) { | 88 if (end_length == 0) { |
73 std::unique_ptr<InterpolableValue> end_interpolable_value = | 89 std::unique_ptr<InterpolableValue> end_interpolable_value = |
74 start.interpolable_value->CloneAndZero(); | 90 start.interpolable_value->CloneAndZero(); |
75 return PairwiseInterpolationValue(std::move(start.interpolable_value), | 91 return PairwiseInterpolationValue(std::move(start.interpolable_value), |
76 std::move(end_interpolable_value), | 92 std::move(end_interpolable_value), |
77 std::move(start.non_interpolable_value)); | 93 std::move(start.non_interpolable_value)); |
78 } | 94 } |
79 | 95 |
80 size_t final_length = lowestCommonMultiple(start_length, end_length); | 96 const size_t final_length = |
| 97 MatchLengths(start_length, end_length, length_matching_strategy); |
81 std::unique_ptr<InterpolableList> result_start_interpolable_list = | 98 std::unique_ptr<InterpolableList> result_start_interpolable_list = |
82 InterpolableList::Create(final_length); | 99 InterpolableList::Create(final_length); |
83 std::unique_ptr<InterpolableList> result_end_interpolable_list = | 100 std::unique_ptr<InterpolableList> result_end_interpolable_list = |
84 InterpolableList::Create(final_length); | 101 InterpolableList::Create(final_length); |
85 Vector<RefPtr<NonInterpolableValue>> result_non_interpolable_values( | 102 Vector<RefPtr<NonInterpolableValue>> result_non_interpolable_values( |
86 final_length); | 103 final_length); |
87 | 104 |
88 InterpolableList& start_interpolable_list = | 105 InterpolableList& start_interpolable_list = |
89 ToInterpolableList(*start.interpolable_value); | 106 ToInterpolableList(*start.interpolable_value); |
90 InterpolableList& end_interpolable_list = | 107 InterpolableList& end_interpolable_list = |
91 ToInterpolableList(*end.interpolable_value); | 108 ToInterpolableList(*end.interpolable_value); |
92 NonInterpolableList& start_non_interpolable_list = | 109 NonInterpolableList& start_non_interpolable_list = |
93 ToNonInterpolableList(*start.non_interpolable_value); | 110 ToNonInterpolableList(*start.non_interpolable_value); |
94 NonInterpolableList& end_non_interpolable_list = | 111 NonInterpolableList& end_non_interpolable_list = |
95 ToNonInterpolableList(*end.non_interpolable_value); | 112 ToNonInterpolableList(*end.non_interpolable_value); |
96 | 113 |
97 for (size_t i = 0; i < final_length; i++) { | 114 for (size_t i = 0; i < final_length; i++) { |
98 InterpolationValue start( | 115 PairwiseInterpolationValue result = nullptr; |
99 start_interpolable_list.Get(i % start_length)->Clone(), | 116 if (length_matching_strategy == kLowestCommonMultiple || |
100 start_non_interpolable_list.Get(i % start_length)); | 117 (i < start_length && i < end_length)) { |
101 InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(), | 118 InterpolationValue start( |
102 end_non_interpolable_list.Get(i % end_length)); | 119 start_interpolable_list.Get(i % start_length)->Clone(), |
103 PairwiseInterpolationValue result = | 120 start_non_interpolable_list.Get(i % start_length)); |
104 merge_single_item_conversions(std::move(start), std::move(end)); | 121 InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(), |
105 if (!result) | 122 end_non_interpolable_list.Get(i % end_length)); |
106 return nullptr; | 123 PairwiseInterpolationValue result = |
107 result_start_interpolable_list->Set( | 124 merge_single_item_conversions(std::move(start), std::move(end)); |
108 i, std::move(result.start_interpolable_value)); | 125 if (!result) |
109 result_end_interpolable_list->Set(i, | 126 return nullptr; |
110 std::move(result.end_interpolable_value)); | 127 result_start_interpolable_list->Set( |
111 result_non_interpolable_values[i] = | 128 i, std::move(result.start_interpolable_value)); |
112 std::move(result.non_interpolable_value); | 129 result_end_interpolable_list->Set( |
| 130 i, std::move(result.end_interpolable_value)); |
| 131 result_non_interpolable_values[i] = |
| 132 std::move(result.non_interpolable_value); |
| 133 } else { |
| 134 DCHECK_EQ(length_matching_strategy, kPadToLargest); |
| 135 if (i < start_length) { |
| 136 result_start_interpolable_list->Set( |
| 137 i, start_interpolable_list.Get(i)->Clone()); |
| 138 result_end_interpolable_list->Set( |
| 139 i, start_interpolable_list.Get(i)->CloneAndZero()); |
| 140 result_non_interpolable_values[i] = start_non_interpolable_list.Get(i); |
| 141 } else { |
| 142 DCHECK_LT(i, end_length); |
| 143 result_start_interpolable_list->Set( |
| 144 i, end_interpolable_list.Get(i)->CloneAndZero()); |
| 145 result_end_interpolable_list->Set( |
| 146 i, end_interpolable_list.Get(i)->Clone()); |
| 147 result_non_interpolable_values[i] = end_non_interpolable_list.Get(i); |
| 148 } |
| 149 } |
113 } | 150 } |
114 | 151 |
115 return PairwiseInterpolationValue( | 152 return PairwiseInterpolationValue( |
116 std::move(result_start_interpolable_list), | 153 std::move(result_start_interpolable_list), |
117 std::move(result_end_interpolable_list), | 154 std::move(result_end_interpolable_list), |
118 NonInterpolableList::Create(std::move(result_non_interpolable_values))); | 155 NonInterpolableList::Create(std::move(result_non_interpolable_values))); |
119 } | 156 } |
120 | 157 |
121 static void RepeatToLength(InterpolationValue& value, size_t length) { | 158 static void RepeatToLength(InterpolationValue& value, size_t length) { |
122 InterpolableList& interpolable_list = | 159 InterpolableList& interpolable_list = |
(...skipping 14 matching lines...) Expand all Loading... |
137 ? std::move(interpolable_list.GetMutable(i)) | 174 ? std::move(interpolable_list.GetMutable(i)) |
138 : interpolable_list.Get(i % current_length)->Clone()); | 175 : interpolable_list.Get(i % current_length)->Clone()); |
139 new_non_interpolable_values[i] = | 176 new_non_interpolable_values[i] = |
140 non_interpolable_list.Get(i % current_length); | 177 non_interpolable_list.Get(i % current_length); |
141 } | 178 } |
142 value.interpolable_value = std::move(new_interpolable_list); | 179 value.interpolable_value = std::move(new_interpolable_list); |
143 value.non_interpolable_value = | 180 value.non_interpolable_value = |
144 NonInterpolableList::Create(std::move(new_non_interpolable_values)); | 181 NonInterpolableList::Create(std::move(new_non_interpolable_values)); |
145 } | 182 } |
146 | 183 |
| 184 // This helper function makes value the same length as length_value by |
| 185 // CloneAndZero-ing the additional items from length_value into value. |
| 186 static void PadToSameLength(InterpolationValue& value, |
| 187 const InterpolationValue& length_value) { |
| 188 InterpolableList& interpolable_list = |
| 189 ToInterpolableList(*value.interpolable_value); |
| 190 NonInterpolableList& non_interpolable_list = |
| 191 ToNonInterpolableList(*value.non_interpolable_value); |
| 192 const size_t current_length = interpolable_list.length(); |
| 193 InterpolableList& target_interpolable_list = |
| 194 ToInterpolableList(*length_value.interpolable_value); |
| 195 NonInterpolableList& target_non_interpolable_list = |
| 196 ToNonInterpolableList(*length_value.non_interpolable_value); |
| 197 const size_t target_length = target_interpolable_list.length(); |
| 198 DCHECK_LT(current_length, target_length); |
| 199 std::unique_ptr<InterpolableList> new_interpolable_list = |
| 200 InterpolableList::Create(target_length); |
| 201 Vector<RefPtr<NonInterpolableValue>> new_non_interpolable_values( |
| 202 target_length); |
| 203 size_t index = 0; |
| 204 for (; index < current_length; index++) { |
| 205 new_interpolable_list->Set(index, |
| 206 std::move(interpolable_list.GetMutable(index))); |
| 207 new_non_interpolable_values[index] = non_interpolable_list.Get(index); |
| 208 } |
| 209 for (; index < target_length; index++) { |
| 210 new_interpolable_list->Set( |
| 211 index, target_interpolable_list.Get(index)->CloneAndZero()); |
| 212 new_non_interpolable_values[index] = |
| 213 target_non_interpolable_list.Get(index); |
| 214 } |
| 215 value.interpolable_value = std::move(new_interpolable_list); |
| 216 value.non_interpolable_value = |
| 217 NonInterpolableList::Create(std::move(new_non_interpolable_values)); |
| 218 } |
| 219 |
147 static bool NonInterpolableListsAreCompatible( | 220 static bool NonInterpolableListsAreCompatible( |
148 const NonInterpolableList& a, | 221 const NonInterpolableList& a, |
149 const NonInterpolableList& b, | 222 const NonInterpolableList& b, |
150 size_t length, | 223 size_t length, |
| 224 ListInterpolationFunctions::LengthMatchingStrategy length_matching_strategy, |
151 ListInterpolationFunctions::NonInterpolableValuesAreCompatibleCallback | 225 ListInterpolationFunctions::NonInterpolableValuesAreCompatibleCallback |
152 non_interpolable_values_are_compatible) { | 226 non_interpolable_values_are_compatible) { |
153 for (size_t i = 0; i < length; i++) { | 227 for (size_t i = 0; i < length; i++) { |
154 if (!non_interpolable_values_are_compatible(a.Get(i % a.length()), | 228 if (length_matching_strategy == |
155 b.Get(i % b.length()))) | 229 ListInterpolationFunctions::kLowestCommonMultiple || |
156 return false; | 230 (i < a.length() && i < b.length())) { |
| 231 if (!non_interpolable_values_are_compatible(a.Get(i % a.length()), |
| 232 b.Get(i % b.length()))) { |
| 233 return false; |
| 234 } |
| 235 } |
157 } | 236 } |
158 return true; | 237 return true; |
159 } | 238 } |
160 | 239 |
161 void ListInterpolationFunctions::Composite( | 240 void ListInterpolationFunctions::Composite( |
162 UnderlyingValueOwner& underlying_value_owner, | 241 UnderlyingValueOwner& underlying_value_owner, |
163 double underlying_fraction, | 242 double underlying_fraction, |
164 const InterpolationType& type, | 243 const InterpolationType& type, |
165 const InterpolationValue& value, | 244 const InterpolationValue& value, |
| 245 LengthMatchingStrategy length_matching_strategy, |
166 NonInterpolableValuesAreCompatibleCallback | 246 NonInterpolableValuesAreCompatibleCallback |
167 non_interpolable_values_are_compatible, | 247 non_interpolable_values_are_compatible, |
168 CompositeItemCallback composite_item) { | 248 CompositeItemCallback composite_item) { |
169 size_t underlying_length = | 249 const size_t underlying_length = |
170 ToInterpolableList(*underlying_value_owner.Value().interpolable_value) | 250 ToInterpolableList(*underlying_value_owner.Value().interpolable_value) |
171 .length(); | 251 .length(); |
172 if (underlying_length == 0) { | 252 if (underlying_length == 0) { |
173 DCHECK(!underlying_value_owner.Value().non_interpolable_value); | 253 DCHECK(!underlying_value_owner.Value().non_interpolable_value); |
174 underlying_value_owner.Set(type, value); | 254 underlying_value_owner.Set(type, value); |
175 return; | 255 return; |
176 } | 256 } |
177 | 257 |
178 const InterpolableList& interpolable_list = | 258 const InterpolableList& interpolable_list = |
179 ToInterpolableList(*value.interpolable_value); | 259 ToInterpolableList(*value.interpolable_value); |
180 size_t value_length = interpolable_list.length(); | 260 const size_t value_length = interpolable_list.length(); |
181 if (value_length == 0) { | 261 if (value_length == 0) { |
182 DCHECK(!value.non_interpolable_value); | 262 DCHECK(!value.non_interpolable_value); |
183 underlying_value_owner.MutableValue().interpolable_value->Scale( | 263 underlying_value_owner.MutableValue().interpolable_value->Scale( |
184 underlying_fraction); | 264 underlying_fraction); |
185 return; | 265 return; |
186 } | 266 } |
187 | 267 |
188 const NonInterpolableList& non_interpolable_list = | 268 const NonInterpolableList& non_interpolable_list = |
189 ToNonInterpolableList(*value.non_interpolable_value); | 269 ToNonInterpolableList(*value.non_interpolable_value); |
190 size_t new_length = lowestCommonMultiple(underlying_length, value_length); | 270 const size_t final_length = |
| 271 MatchLengths(underlying_length, value_length, length_matching_strategy); |
191 if (!NonInterpolableListsAreCompatible( | 272 if (!NonInterpolableListsAreCompatible( |
192 ToNonInterpolableList( | 273 ToNonInterpolableList( |
193 *underlying_value_owner.Value().non_interpolable_value), | 274 *underlying_value_owner.Value().non_interpolable_value), |
194 non_interpolable_list, new_length, | 275 non_interpolable_list, final_length, length_matching_strategy, |
195 non_interpolable_values_are_compatible)) { | 276 non_interpolable_values_are_compatible)) { |
196 underlying_value_owner.Set(type, value); | 277 underlying_value_owner.Set(type, value); |
197 return; | 278 return; |
198 } | 279 } |
199 | 280 |
200 InterpolationValue& underlying_value = underlying_value_owner.MutableValue(); | 281 InterpolationValue& underlying_value = underlying_value_owner.MutableValue(); |
201 if (underlying_length < new_length) | 282 if (length_matching_strategy == kLowestCommonMultiple) { |
202 RepeatToLength(underlying_value, new_length); | 283 if (underlying_length < final_length) { |
| 284 RepeatToLength(underlying_value, final_length); |
| 285 } |
| 286 InterpolableList& underlying_interpolable_list = |
| 287 ToInterpolableList(*underlying_value.interpolable_value); |
| 288 NonInterpolableList& underlying_non_interpolable_list = |
| 289 ToNonInterpolableList(*underlying_value.non_interpolable_value); |
203 | 290 |
204 InterpolableList& underlying_interpolable_list = | 291 for (size_t i = 0; i < final_length; i++) { |
205 ToInterpolableList(*underlying_value.interpolable_value); | 292 composite_item(underlying_interpolable_list.GetMutable(i), |
206 NonInterpolableList& underlying_non_interpolable_list = | 293 underlying_non_interpolable_list.GetMutable(i), |
207 ToNonInterpolableList(*underlying_value.non_interpolable_value); | 294 underlying_fraction, |
208 for (size_t i = 0; i < new_length; i++) { | 295 *interpolable_list.Get(i % value_length), |
209 composite_item(underlying_interpolable_list.GetMutable(i), | 296 non_interpolable_list.Get(i % value_length)); |
210 underlying_non_interpolable_list.GetMutable(i), | 297 } |
211 underlying_fraction, | 298 } else { |
212 *interpolable_list.Get(i % value_length), | 299 DCHECK_EQ(length_matching_strategy, kPadToLargest); |
213 non_interpolable_list.Get(i % value_length)); | 300 if (underlying_length < final_length) { |
| 301 DCHECK_EQ(value_length, final_length); |
| 302 PadToSameLength(underlying_value, value); |
| 303 } |
| 304 InterpolableList& underlying_interpolable_list = |
| 305 ToInterpolableList(*underlying_value.interpolable_value); |
| 306 NonInterpolableList& underlying_non_interpolable_list = |
| 307 ToNonInterpolableList(*underlying_value.non_interpolable_value); |
| 308 |
| 309 for (size_t i = 0; i < value_length; i++) { |
| 310 composite_item(underlying_interpolable_list.GetMutable(i), |
| 311 underlying_non_interpolable_list.GetMutable(i), |
| 312 underlying_fraction, *interpolable_list.Get(i), |
| 313 non_interpolable_list.Get(i)); |
| 314 } |
| 315 for (size_t i = value_length; i < final_length; i++) { |
| 316 underlying_interpolable_list.GetMutable(i)->Scale(underlying_fraction); |
| 317 } |
214 } | 318 } |
215 } | 319 } |
216 | 320 |
217 } // namespace blink | 321 } // namespace blink |
OLD | NEW |