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