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

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