Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: third_party/WebKit/Source/core/animation/ListInterpolationFunctions.cpp

Issue 2844213002: Fix behaviour of shadow interpolation with mismatched list lengths (Closed)
Patch Set: testspants Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698