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

Side by Side Diff: ui/gfx/paint_vector_icon.cc

Issue 2860163002: WIP - allow vector icons to specify motion.
Patch Set: checkpoint 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
« no previous file with comments | « ui/gfx/paint_vector_icon.h ('k') | ui/gfx/vector_icon_types.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "ui/gfx/paint_vector_icon.h" 5 #include "ui/gfx/paint_vector_icon.h"
6 6
7 #include <map> 7 #include <map>
8 #include <tuple> 8 #include <tuple>
9 9
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h" 15 #include "base/strings/string_split.h"
16 #include "cc/paint/paint_canvas.h" 16 #include "cc/paint/paint_canvas.h"
17 #include "cc/paint/paint_flags.h" 17 #include "cc/paint/paint_flags.h"
18 #include "third_party/skia/include/core/SkPath.h" 18 #include "third_party/skia/include/core/SkPath.h"
19 #include "ui/gfx/animation/tween.h"
19 #include "ui/gfx/canvas.h" 20 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/image/canvas_image_source.h" 21 #include "ui/gfx/image/canvas_image_source.h"
21 #include "ui/gfx/scoped_canvas.h" 22 #include "ui/gfx/scoped_canvas.h"
22 #include "ui/gfx/vector_icon_types.h" 23 #include "ui/gfx/vector_icon_types.h"
23 24
24 namespace gfx { 25 namespace gfx {
25 26
26 namespace { 27 namespace {
27 28
29 class PathParser {
30 public:
31 PathParser(const PathElement* path_elements)
32 : path_elements_(path_elements) {}
33 ~PathParser() {}
34
35 bool Advance() {
36 if (command_index_ < 0)
37 command_index_ = 0;
38 else if (CurrentCommand() != END)
39 command_index_ += GetArgumentCount() + 1;
40 return CurrentCommand() != END;
41 }
42
43 CommandType CurrentCommand() const {
44 return path_elements_[command_index_].command;
45 }
46
47 SkScalar GetArgument(int index) const {
48 DCHECK_LT(index, GetArgumentCount());
49 return path_elements_[command_index_ + 1 + index].arg;
50 }
51
52 private:
53 int GetArgumentCount() const {
54 switch (CurrentCommand()) {
55 case STROKE:
56 case H_LINE_TO:
57 case R_H_LINE_TO:
58 case V_LINE_TO:
59 case R_V_LINE_TO:
60 case CANVAS_DIMENSIONS:
61 return 1;
62
63 case MOVE_TO:
64 case R_MOVE_TO:
65 case LINE_TO:
66 case R_LINE_TO:
67 case TRANSITION_END:
68 return 2;
69
70 case CIRCLE:
71 return 3;
72
73 case PATH_COLOR_ARGB:
74 case CUBIC_TO_SHORTHAND:
75 case CLIP:
76 return 4;
77
78 case ROUND_RECT:
79 return 5;
80
81 case CUBIC_TO:
82 case R_CUBIC_TO:
83 return 6;
84
85 case ARC_TO:
86 case R_ARC_TO:
87 return 7;
88
89 case NEW_PATH:
90 case PATH_MODE_CLEAR:
91 case CAP_SQUARE:
92 case CLOSE:
93 case DISABLE_AA:
94 case FLIPS_IN_RTL:
95 case TRANSITION_FROM:
96 case TRANSITION_TO:
97 case END:
98 return 0;
99 }
100 }
101
102 const PathElement* path_elements_;
103 int command_index_ = -1;
104 };
105
28 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO. 106 // Translates a string such as "MOVE_TO" into a command such as MOVE_TO.
29 CommandType CommandFromString(const std::string& source) { 107 CommandType CommandFromString(const std::string& source) {
30 #define RETURN_IF_IS(command) \ 108 #define RETURN_IF_IS(command) \
31 if (source == #command) \ 109 if (source == #command) \
32 return command; 110 return command;
33 111
34 RETURN_IF_IS(NEW_PATH); 112 RETURN_IF_IS(NEW_PATH);
35 RETURN_IF_IS(PATH_COLOR_ARGB); 113 RETURN_IF_IS(PATH_COLOR_ARGB);
36 RETURN_IF_IS(PATH_MODE_CLEAR); 114 RETURN_IF_IS(PATH_MODE_CLEAR);
37 RETURN_IF_IS(STROKE); 115 RETURN_IF_IS(STROKE);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 path.push_back(PathElement(SkIntToScalar(hex_value))); 154 path.push_back(PathElement(SkIntToScalar(hex_value)));
77 else 155 else
78 path.push_back(PathElement(CommandFromString(piece))); 156 path.push_back(PathElement(CommandFromString(piece)));
79 } 157 }
80 return path; 158 return path;
81 } 159 }
82 160
83 void PaintPath(Canvas* canvas, 161 void PaintPath(Canvas* canvas,
84 const PathElement* path_elements, 162 const PathElement* path_elements,
85 int dip_size, 163 int dip_size,
86 SkColor color) { 164 SkColor color,
165 const base::TimeDelta* elapsed_time = nullptr) {
87 SkPath path; 166 SkPath path;
88 path.setFillType(SkPath::kEvenOdd_FillType); 167 path.setFillType(SkPath::kEvenOdd_FillType);
89 168
90 int canvas_size = kReferenceSizeDip; 169 int canvas_size = kReferenceSizeDip;
91 std::vector<SkPath> paths; 170 std::vector<SkPath> paths;
92 std::vector<cc::PaintFlags> flags_array; 171 std::vector<cc::PaintFlags> flags_array;
93 SkRect clip_rect = SkRect::MakeEmpty(); 172 SkRect clip_rect = SkRect::MakeEmpty();
94 bool flips_in_rtl = false; 173 bool flips_in_rtl = false;
95 CommandType previous_command_type = NEW_PATH; 174 CommandType previous_command_type = NEW_PATH;
96 175
97 for (size_t i = 0; path_elements[i].type != END; i++) { 176 PathParser parser(path_elements);
98 if (paths.empty() || path_elements[i].type == NEW_PATH) { 177 auto arg = [&parser](int i) { return parser.GetArgument(i); };
178
179 while (parser.Advance()) {
180 const CommandType command_type = parser.CurrentCommand();
181
182 auto start_new_path = [&paths]() {
99 paths.push_back(SkPath()); 183 paths.push_back(SkPath());
100 paths.back().setFillType(SkPath::kEvenOdd_FillType); 184 paths.back().setFillType(SkPath::kEvenOdd_FillType);
101 185 };
186 auto start_new_flags = [&flags_array, &color]() {
102 flags_array.push_back(cc::PaintFlags()); 187 flags_array.push_back(cc::PaintFlags());
103 flags_array.back().setColor(color); 188 flags_array.back().setColor(color);
104 flags_array.back().setAntiAlias(true); 189 flags_array.back().setAntiAlias(true);
105 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); 190 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap);
191 };
192
193 if (paths.empty() || command_type == NEW_PATH) {
194 start_new_path();
195 start_new_flags();
106 } 196 }
107 197
108 SkPath& path = paths.back(); 198 SkPath& path = paths.back();
109 cc::PaintFlags& flags = flags_array.back(); 199 cc::PaintFlags& flags = flags_array.back();
110 CommandType command_type = path_elements[i].type;
111 switch (command_type) { 200 switch (command_type) {
112 // Handled above. 201 // Handled above.
113 case NEW_PATH: 202 case NEW_PATH:
114 continue; 203 break;
115 204
116 case PATH_COLOR_ARGB: { 205 case TRANSITION_FROM: {
117 int a = SkScalarFloorToInt(path_elements[++i].arg); 206 start_new_path();
118 int r = SkScalarFloorToInt(path_elements[++i].arg);
119 int g = SkScalarFloorToInt(path_elements[++i].arg);
120 int b = SkScalarFloorToInt(path_elements[++i].arg);
121 flags.setColor(SkColorSetARGB(a, r, g, b));
122 break; 207 break;
123 } 208 }
124 209
125 case PATH_MODE_CLEAR: { 210 case TRANSITION_TO: {
126 flags.setBlendMode(SkBlendMode::kClear); 211 start_new_path();
127 break; 212 start_new_flags();
128 };
129
130 case STROKE: {
131 flags.setStyle(cc::PaintFlags::kStroke_Style);
132 SkScalar width = path_elements[++i].arg;
133 flags.setStrokeWidth(width);
134 break; 213 break;
135 } 214 }
136 215
137 case CAP_SQUARE: { 216 case TRANSITION_END: {
138 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap); 217 DCHECK_GT(paths.size(), 2U);
218
219 base::TimeDelta delay =
220 base::TimeDelta::FromMillisecondsD(SkScalarToDouble(arg(0)));
221 base::TimeDelta duration =
222 base::TimeDelta::FromMillisecondsD(SkScalarToDouble(arg(1)));
223
224 const base::TimeDelta current_time =
225 elapsed_time ? *elapsed_time : base::TimeDelta();
226
227 double state = 0;
228 if (current_time >= delay + duration) {
229 state = 1;
230 } else if (current_time > delay) {
231 state = (current_time - delay).ToInternalValue() /
232 static_cast<double>(duration.ToInternalValue());
233 }
234
235 auto weight = Tween::CalculateValue(Tween::FAST_OUT_SLOW_IN, state);
236
237 SkPath path1, path2;
238 path1.swap(paths.back());
239 paths.pop_back();
240 path2.swap(paths.back());
241 paths.pop_back();
242
243 SkPath interpolated_path;
244 bool could_interpolate =
245 path1.interpolate(path2, weight, &interpolated_path);
246 DCHECK(could_interpolate);
247 paths.back().addPath(interpolated_path);
248
249 // Manual interpolation of flags properties.
250 DCHECK_GT(flags_array.size(), 1U);
251 cc::PaintFlags& end_flags = flags_array.back();
252 cc::PaintFlags& start_flags = flags_array[flags_array.size() - 2];
253
254 start_flags.setColor(Tween::ColorValueBetween(
255 weight, start_flags.getColor(), end_flags.getColor()));
256 start_flags.setStrokeWidth(Tween::FloatValueBetween(
257 weight, start_flags.getStrokeWidth(), end_flags.getStrokeWidth()));
258
259 flags_array.pop_back();
139 break; 260 break;
140 } 261 }
141 262
142 case MOVE_TO: { 263 case PATH_COLOR_ARGB:
143 SkScalar x = path_elements[++i].arg; 264 flags.setColor(SkColorSetARGB(
144 SkScalar y = path_elements[++i].arg; 265 SkScalarFloorToInt(arg(0)), SkScalarFloorToInt(arg(1)),
145 path.moveTo(x, y); 266 SkScalarFloorToInt(arg(2)), SkScalarFloorToInt(arg(3))));
146 break; 267 break;
147 }
148 268
149 case R_MOVE_TO: { 269 case PATH_MODE_CLEAR:
270 flags.setBlendMode(SkBlendMode::kClear);
271 break;
272
273 case STROKE:
274 flags.setStyle(cc::PaintFlags::kStroke_Style);
275 flags.setStrokeWidth(arg(0));
276 break;
277
278 case CAP_SQUARE:
279 flags.setStrokeCap(cc::PaintFlags::kSquare_Cap);
280 break;
281
282 case MOVE_TO:
283 path.moveTo(arg(0), arg(1));
284 break;
285
286 case R_MOVE_TO:
150 if (previous_command_type == CLOSE) { 287 if (previous_command_type == CLOSE) {
151 // This triggers injectMoveToIfNeeded() so that the next subpath 288 // This triggers injectMoveToIfNeeded() so that the next subpath
152 // will start at the correct place. See [ 289 // will start at the correct place. See [
153 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ]. 290 // https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand ].
154 path.rLineTo(0, 0); 291 path.rLineTo(0, 0);
155 } 292 }
156 293
157 SkScalar x = path_elements[++i].arg; 294 path.rMoveTo(arg(0), arg(1));
158 SkScalar y = path_elements[++i].arg;
159 path.rMoveTo(x, y);
160 break; 295 break;
161 }
162 296
163 case ARC_TO: 297 case ARC_TO:
164 case R_ARC_TO: { 298 case R_ARC_TO: {
165 SkScalar rx = path_elements[++i].arg; 299 SkScalar rx = arg(0);
166 SkScalar ry = path_elements[++i].arg; 300 SkScalar ry = arg(1);
167 SkScalar angle = path_elements[++i].arg; 301 SkScalar angle = arg(2);
168 SkScalar large_arc_flag = path_elements[++i].arg; 302 SkScalar large_arc_flag = arg(3);
169 SkScalar arc_sweep_flag = path_elements[++i].arg; 303 SkScalar arc_sweep_flag = arg(4);
170 SkScalar x = path_elements[++i].arg; 304 SkScalar x = arg(5);
171 SkScalar y = path_elements[++i].arg; 305 SkScalar y = arg(6);
172 306
173 auto path_fn = 307 auto path_fn =
174 command_type == ARC_TO 308 command_type == ARC_TO
175 ? static_cast<void (SkPath::*)( 309 ? static_cast<void (SkPath::*)(
176 SkScalar, SkScalar, SkScalar, SkPath::ArcSize, 310 SkScalar, SkScalar, SkScalar, SkPath::ArcSize,
177 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo) 311 SkPath::Direction, SkScalar, SkScalar)>(&SkPath::arcTo)
178 : &SkPath::rArcTo; 312 : &SkPath::rArcTo;
179 (path.*path_fn)( 313 (path.*path_fn)(
180 rx, ry, angle, 314 rx, ry, angle,
181 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize, 315 large_arc_flag ? SkPath::kLarge_ArcSize : SkPath::kSmall_ArcSize,
182 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x, 316 arc_sweep_flag ? SkPath::kCW_Direction : SkPath::kCCW_Direction, x,
183 y); 317 y);
184 break; 318 break;
185 } 319 }
186 320
187 case LINE_TO: { 321 case LINE_TO:
188 SkScalar x = path_elements[++i].arg; 322 path.lineTo(arg(0), arg(1));
189 SkScalar y = path_elements[++i].arg;
190 path.lineTo(x, y);
191 break; 323 break;
192 }
193 324
194 case R_LINE_TO: { 325 case R_LINE_TO:
195 SkScalar x = path_elements[++i].arg; 326 path.rLineTo(arg(0), arg(1));
196 SkScalar y = path_elements[++i].arg;
197 path.rLineTo(x, y);
198 break; 327 break;
199 }
200 328
201 case H_LINE_TO: { 329 case H_LINE_TO: {
202 SkPoint last_point; 330 SkPoint last_point;
203 path.getLastPt(&last_point); 331 path.getLastPt(&last_point);
204 SkScalar x = path_elements[++i].arg; 332 path.lineTo(arg(0), last_point.fY);
205 path.lineTo(x, last_point.fY);
206 break; 333 break;
207 } 334 }
208 335
209 case R_H_LINE_TO: { 336 case R_H_LINE_TO:
210 SkScalar x = path_elements[++i].arg; 337 path.rLineTo(arg(0), 0);
211 path.rLineTo(x, 0);
212 break; 338 break;
213 }
214 339
215 case V_LINE_TO: { 340 case V_LINE_TO: {
216 SkPoint last_point; 341 SkPoint last_point;
217 path.getLastPt(&last_point); 342 path.getLastPt(&last_point);
218 SkScalar y = path_elements[++i].arg; 343 path.lineTo(last_point.fX, arg(0));
219 path.lineTo(last_point.fX, y);
220 break; 344 break;
221 } 345 }
222 346
223 case R_V_LINE_TO: { 347 case R_V_LINE_TO:
224 SkScalar y = path_elements[++i].arg; 348 path.rLineTo(0, arg(0));
225 path.rLineTo(0, y);
226 break; 349 break;
227 }
228 350
229 case CUBIC_TO: { 351 case CUBIC_TO:
230 SkScalar x1 = path_elements[++i].arg; 352 path.cubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5));
231 SkScalar y1 = path_elements[++i].arg;
232 SkScalar x2 = path_elements[++i].arg;
233 SkScalar y2 = path_elements[++i].arg;
234 SkScalar x3 = path_elements[++i].arg;
235 SkScalar y3 = path_elements[++i].arg;
236 path.cubicTo(x1, y1, x2, y2, x3, y3);
237 break; 353 break;
238 }
239 354
240 case R_CUBIC_TO: { 355 case R_CUBIC_TO:
241 SkScalar x1 = path_elements[++i].arg; 356 path.rCubicTo(arg(0), arg(1), arg(2), arg(3), arg(4), arg(5));
242 SkScalar y1 = path_elements[++i].arg;
243 SkScalar x2 = path_elements[++i].arg;
244 SkScalar y2 = path_elements[++i].arg;
245 SkScalar x3 = path_elements[++i].arg;
246 SkScalar y3 = path_elements[++i].arg;
247 path.rCubicTo(x1, y1, x2, y2, x3, y3);
248 break; 357 break;
249 }
250 358
251 case CUBIC_TO_SHORTHAND: { 359 case CUBIC_TO_SHORTHAND: {
252 // Compute the first control point (|x1| and |y1|) as the reflection 360 // Compute the first control point (|x1| and |y1|) as the reflection
253 // of the second control point on the previous command relative to 361 // of the second control point on the previous command relative to
254 // the current point. If there is no previous command or if the 362 // the current point. If there is no previous command or if the
255 // previous command is not a cubic Bezier curve, the first control 363 // previous command is not a cubic Bezier curve, the first control
256 // point is coincident with the current point. Refer to the SVG 364 // point is coincident with the current point. Refer to the SVG
257 // path specs for further details. 365 // path specs for further details.
258 SkPoint last_point; 366 SkPoint last_point;
259 path.getLastPt(&last_point); 367 path.getLastPt(&last_point);
260 SkScalar delta_x = 0; 368 SkScalar delta_x = 0;
261 SkScalar delta_y = 0; 369 SkScalar delta_y = 0;
262 if (previous_command_type == CUBIC_TO || 370 if (previous_command_type == CUBIC_TO ||
263 previous_command_type == R_CUBIC_TO || 371 previous_command_type == R_CUBIC_TO ||
264 previous_command_type == CUBIC_TO_SHORTHAND) { 372 previous_command_type == CUBIC_TO_SHORTHAND) {
265 SkPoint last_control_point = path.getPoint(path.countPoints() - 2); 373 SkPoint last_control_point = path.getPoint(path.countPoints() - 2);
266 delta_x = last_point.fX - last_control_point.fX; 374 delta_x = last_point.fX - last_control_point.fX;
267 delta_y = last_point.fY - last_control_point.fY; 375 delta_y = last_point.fY - last_control_point.fY;
268 } 376 }
269 377
270 SkScalar x1 = last_point.fX + delta_x; 378 SkScalar x1 = last_point.fX + delta_x;
271 SkScalar y1 = last_point.fY + delta_y; 379 SkScalar y1 = last_point.fY + delta_y;
272 SkScalar x2 = path_elements[++i].arg; 380 path.cubicTo(x1, y1, arg(0), arg(1), arg(2), arg(3));
273 SkScalar y2 = path_elements[++i].arg;
274 SkScalar x3 = path_elements[++i].arg;
275 SkScalar y3 = path_elements[++i].arg;
276 path.cubicTo(x1, y1, x2, y2, x3, y3);
277 break; 381 break;
278 } 382 }
279 383
280 case CIRCLE: { 384 case CIRCLE:
281 SkScalar x = path_elements[++i].arg; 385 path.addCircle(arg(0), arg(1), arg(2));
282 SkScalar y = path_elements[++i].arg;
283 SkScalar r = path_elements[++i].arg;
284 path.addCircle(x, y, r);
285 break; 386 break;
286 }
287 387
288 case ROUND_RECT: { 388 case ROUND_RECT:
289 SkScalar x = path_elements[++i].arg; 389 path.addRoundRect(SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3)),
290 SkScalar y = path_elements[++i].arg; 390 arg(4), arg(4));
291 SkScalar w = path_elements[++i].arg;
292 SkScalar h = path_elements[++i].arg;
293 SkScalar radius = path_elements[++i].arg;
294 path.addRoundRect(SkRect::MakeXYWH(x, y, w, h), radius, radius);
295 break; 391 break;
296 }
297 392
298 case CLOSE: { 393 case CLOSE:
299 path.close(); 394 path.close();
300 break; 395 break;
301 }
302 396
303 case CANVAS_DIMENSIONS: { 397 case CANVAS_DIMENSIONS:
304 SkScalar width = path_elements[++i].arg; 398 canvas_size = SkScalarTruncToInt(arg(0));
305 canvas_size = SkScalarTruncToInt(width);
306 break; 399 break;
307 }
308 400
309 case CLIP: { 401 case CLIP:
310 SkScalar x = path_elements[++i].arg; 402 clip_rect = SkRect::MakeXYWH(arg(0), arg(1), arg(2), arg(3));
311 SkScalar y = path_elements[++i].arg;
312 SkScalar w = path_elements[++i].arg;
313 SkScalar h = path_elements[++i].arg;
314 clip_rect = SkRect::MakeXYWH(x, y, w, h);
315 break; 403 break;
316 }
317 404
318 case DISABLE_AA: { 405 case DISABLE_AA:
319 flags.setAntiAlias(false); 406 flags.setAntiAlias(false);
320 break; 407 break;
321 }
322 408
323 case FLIPS_IN_RTL: { 409 case FLIPS_IN_RTL:
324 flips_in_rtl = true; 410 flips_in_rtl = true;
325 break; 411 break;
326 }
327 412
328 case END: 413 case END:
329 NOTREACHED(); 414 NOTREACHED();
330 break; 415 break;
331 } 416 }
332 417
333 previous_command_type = command_type; 418 previous_command_type = command_type;
334 } 419 }
335 420
336 gfx::ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, 421 ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, flips_in_rtl);
337 flips_in_rtl);
338 422
339 if (dip_size != canvas_size) { 423 if (dip_size != canvas_size) {
340 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); 424 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size);
341 canvas->sk_canvas()->scale(scale, scale); 425 canvas->sk_canvas()->scale(scale, scale);
342 } 426 }
343 427
344 if (!clip_rect.isEmpty()) 428 if (!clip_rect.isEmpty())
345 canvas->sk_canvas()->clipRect(clip_rect); 429 canvas->sk_canvas()->clipRect(clip_rect);
346 430
347 DCHECK_EQ(flags_array.size(), paths.size()); 431 DCHECK_EQ(flags_array.size(), paths.size());
348 for (size_t i = 0; i < paths.size(); ++i) 432 for (size_t i = 0; i < paths.size(); ++i)
349 canvas->DrawPath(paths[i], flags_array[i]); 433 canvas->DrawPath(paths[i], flags_array[i]);
350 } 434 }
351 435
352 class VectorIconSource : public CanvasImageSource { 436 class VectorIconSource : public CanvasImageSource {
353 public: 437 public:
354 VectorIconSource(const VectorIcon& icon, 438 VectorIconSource(const VectorIcon& icon,
355 int dip_size, 439 int dip_size,
356 SkColor color, 440 SkColor color,
357 const VectorIcon& badge_icon) 441 const VectorIcon& badge_icon)
358 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), 442 : CanvasImageSource(Size(dip_size, dip_size), false),
359 color_(color), 443 color_(color),
360 icon_(icon), 444 icon_(icon),
361 badge_(badge_icon) {} 445 badge_(badge_icon) {}
362 446
363 VectorIconSource(const std::string& definition, int dip_size, SkColor color) 447 VectorIconSource(const std::string& definition, int dip_size, SkColor color)
364 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), 448 : CanvasImageSource(Size(dip_size, dip_size), false),
365 color_(color), 449 color_(color),
366 icon_(kNoneIcon), 450 icon_(kNoneIcon),
367 badge_(kNoneIcon), 451 badge_(kNoneIcon),
368 path_(PathFromSource(definition)) {} 452 path_(PathFromSource(definition)) {}
369 453
370 ~VectorIconSource() override {} 454 ~VectorIconSource() override {}
371 455
372 // CanvasImageSource: 456 // CanvasImageSource:
373 bool HasRepresentationAtAllScales() const override { 457 bool HasRepresentationAtAllScales() const override {
374 return !icon_.is_empty(); 458 return !icon_.is_empty();
375 } 459 }
376 460
377 void Draw(gfx::Canvas* canvas) override { 461 void Draw(Canvas* canvas) override {
378 if (path_.empty()) { 462 if (path_.empty()) {
379 PaintVectorIcon(canvas, icon_, size_.width(), color_); 463 PaintVectorIcon(canvas, icon_, size_.width(), color_);
380 if (!badge_.is_empty()) 464 if (!badge_.is_empty())
381 PaintVectorIcon(canvas, badge_, size_.width(), color_); 465 PaintVectorIcon(canvas, badge_, size_.width(), color_);
382 } else { 466 } else {
383 PaintPath(canvas, path_.data(), size_.width(), color_); 467 PaintPath(canvas, path_.data(), size_.width(), color_);
384 } 468 }
385 } 469 }
386 470
387 private: 471 private:
(...skipping 17 matching lines...) Expand all
405 int dip_size, 489 int dip_size,
406 SkColor color, 490 SkColor color,
407 const VectorIcon& badge_icon) { 491 const VectorIcon& badge_icon) {
408 IconDescription description(&icon, dip_size, color, &badge_icon); 492 IconDescription description(&icon, dip_size, color, &badge_icon);
409 auto iter = images_.find(description); 493 auto iter = images_.find(description);
410 if (iter != images_.end()) 494 if (iter != images_.end())
411 return iter->second; 495 return iter->second;
412 496
413 ImageSkia icon_image( 497 ImageSkia icon_image(
414 new VectorIconSource(icon, dip_size, color, badge_icon), 498 new VectorIconSource(icon, dip_size, color, badge_icon),
415 gfx::Size(dip_size, dip_size)); 499 Size(dip_size, dip_size));
416 images_.insert(std::make_pair(description, icon_image)); 500 images_.insert(std::make_pair(description, icon_image));
417 return icon_image; 501 return icon_image;
418 } 502 }
419 503
420 private: 504 private:
421 struct IconDescription { 505 struct IconDescription {
422 IconDescription(const VectorIcon* icon, 506 IconDescription(const VectorIcon* icon,
423 int dip_size, 507 int dip_size,
424 SkColor color, 508 SkColor color,
425 const VectorIcon* badge_icon) 509 const VectorIcon* badge_icon)
426 : icon(icon), 510 : icon(icon),
427 dip_size(dip_size), 511 dip_size(dip_size),
428 color(color), 512 color(color),
429 badge_icon(badge_icon) {} 513 badge_icon(badge_icon) {}
430 514
431 bool operator<(const IconDescription& other) const { 515 bool operator<(const IconDescription& other) const {
432 return std::tie(icon, dip_size, color, badge_icon) < 516 return std::tie(icon, dip_size, color, badge_icon) <
433 std::tie(other.icon, other.dip_size, other.color, 517 std::tie(other.icon, other.dip_size, other.color,
434 other.badge_icon); 518 other.badge_icon);
435 } 519 }
436 520
437 const gfx::VectorIcon* icon; 521 const VectorIcon* icon;
438 int dip_size; 522 int dip_size;
439 SkColor color; 523 SkColor color;
440 const gfx::VectorIcon* badge_icon; 524 const VectorIcon* badge_icon;
441 }; 525 };
442 526
443 std::map<IconDescription, ImageSkia> images_; 527 std::map<IconDescription, ImageSkia> images_;
444 528
445 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); 529 DISALLOW_COPY_AND_ASSIGN(VectorIconCache);
446 }; 530 };
447 531
448 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = 532 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache =
449 LAZY_INSTANCE_INITIALIZER; 533 LAZY_INSTANCE_INITIALIZER;
450 534
451 } // namespace 535 } // namespace
452 536
453 const VectorIcon kNoneIcon = {}; 537 const VectorIcon kNoneIcon = {};
454 538
455 void PaintVectorIcon(Canvas* canvas, const VectorIcon& icon, SkColor color) { 539 void PaintVectorIcon(Canvas* canvas,
456 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color); 540 const VectorIcon& icon,
541 SkColor color,
542 const base::TimeDelta* elapsed_time) {
543 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color,
544 elapsed_time);
457 } 545 }
458 546
459 void PaintVectorIcon(Canvas* canvas, 547 void PaintVectorIcon(Canvas* canvas,
460 const VectorIcon& icon, 548 const VectorIcon& icon,
461 int dip_size, 549 int dip_size,
462 SkColor color) { 550 SkColor color,
551 const base::TimeDelta* elapsed_time) {
463 DCHECK(!icon.is_empty()); 552 DCHECK(!icon.is_empty());
464 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_) 553 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_)
465 ? icon.path_1x_ 554 ? icon.path_1x_
466 : icon.path_; 555 : icon.path_;
467 PaintPath(canvas, path, dip_size, color); 556 PaintPath(canvas, path, dip_size, color, elapsed_time);
468 } 557 }
469 558
470 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { 559 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) {
471 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); 560 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color);
472 } 561 }
473 562
474 ImageSkia CreateVectorIcon(const VectorIcon& icon, 563 ImageSkia CreateVectorIcon(const VectorIcon& icon,
475 int dip_size, 564 int dip_size,
476 SkColor color) { 565 SkColor color) {
477 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); 566 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon);
478 } 567 }
479 568
480 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, 569 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon,
481 int dip_size, 570 int dip_size,
482 SkColor color, 571 SkColor color,
483 const VectorIcon& badge_icon) { 572 const VectorIcon& badge_icon) {
484 return icon.is_empty() ? gfx::ImageSkia() 573 return icon.is_empty() ? ImageSkia()
485 : g_icon_cache.Get().GetOrCreateIcon( 574 : g_icon_cache.Get().GetOrCreateIcon(
486 icon, dip_size, color, badge_icon); 575 icon, dip_size, color, badge_icon);
487 } 576 }
488 577
489 ImageSkia CreateVectorIconFromSource(const std::string& source, 578 ImageSkia CreateVectorIconFromSource(const std::string& source,
490 int dip_size, 579 int dip_size,
491 SkColor color) { 580 SkColor color) {
492 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, 581 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size,
493 color); 582 color);
494 } 583 }
495 584
496 int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon) { 585 int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) {
497 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_; 586 const PathElement* one_x_path = icon.path_1x_ ? icon.path_1x_ : icon.path_;
498 return one_x_path[0].type == CANVAS_DIMENSIONS ? one_x_path[1].arg 587 return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg
499 : kReferenceSizeDip; 588 : kReferenceSizeDip;
589 }
590
591 base::TimeDelta GetDurationOfAnimation(const VectorIcon& icon) {
592 base::TimeDelta last_motion;
593 PathParser parser(icon.path_);
594 while (parser.Advance()) {
595 if (parser.CurrentCommand() != TRANSITION_END)
596 continue;
597
598 auto end_time = base::TimeDelta::FromMillisecondsD(parser.GetArgument(0)) +
599 base::TimeDelta::FromMillisecondsD(parser.GetArgument(1));
600 if (end_time > last_motion)
601 last_motion = end_time;
602 }
603 return last_motion;
500 } 604 }
501 605
502 } // namespace gfx 606 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/paint_vector_icon.h ('k') | ui/gfx/vector_icon_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698