Chromium Code Reviews| 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 "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 |
| 28 // Helper that simplifies iterating over a sequence of PathElements. | 29 // Helper that simplifies iterating over a sequence of PathElements. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 54 case CANVAS_DIMENSIONS: | 55 case CANVAS_DIMENSIONS: |
| 55 return 1; | 56 return 1; |
| 56 | 57 |
| 57 case MOVE_TO: | 58 case MOVE_TO: |
| 58 case R_MOVE_TO: | 59 case R_MOVE_TO: |
| 59 case LINE_TO: | 60 case LINE_TO: |
| 60 case R_LINE_TO: | 61 case R_LINE_TO: |
| 61 return 2; | 62 return 2; |
| 62 | 63 |
| 63 case CIRCLE: | 64 case CIRCLE: |
| 65 case TRANSITION_END: | |
| 64 return 3; | 66 return 3; |
| 65 | 67 |
| 66 case PATH_COLOR_ARGB: | 68 case PATH_COLOR_ARGB: |
| 67 case CUBIC_TO_SHORTHAND: | 69 case CUBIC_TO_SHORTHAND: |
| 68 case CLIP: | 70 case CLIP: |
| 69 return 4; | 71 return 4; |
| 70 | 72 |
| 71 case ROUND_RECT: | 73 case ROUND_RECT: |
| 72 return 5; | 74 return 5; |
| 73 | 75 |
| 74 case CUBIC_TO: | 76 case CUBIC_TO: |
| 75 case R_CUBIC_TO: | 77 case R_CUBIC_TO: |
| 76 return 6; | 78 return 6; |
| 77 | 79 |
| 78 case ARC_TO: | 80 case ARC_TO: |
| 79 case R_ARC_TO: | 81 case R_ARC_TO: |
| 80 return 7; | 82 return 7; |
| 81 | 83 |
| 82 case NEW_PATH: | 84 case NEW_PATH: |
| 83 case PATH_MODE_CLEAR: | 85 case PATH_MODE_CLEAR: |
| 84 case CAP_SQUARE: | 86 case CAP_SQUARE: |
| 85 case CLOSE: | 87 case CLOSE: |
| 86 case DISABLE_AA: | 88 case DISABLE_AA: |
| 87 case FLIPS_IN_RTL: | 89 case FLIPS_IN_RTL: |
| 90 case TRANSITION_FROM: | |
| 91 case TRANSITION_TO: | |
| 88 case END: | 92 case END: |
| 89 return 0; | 93 return 0; |
| 90 } | 94 } |
| 91 | 95 |
| 92 NOTREACHED(); | 96 NOTREACHED(); |
| 93 return 0; | 97 return 0; |
| 94 } | 98 } |
| 95 | 99 |
| 96 const PathElement* path_elements_; | 100 const PathElement* path_elements_; |
| 97 int command_index_ = 0; | 101 int command_index_ = 0; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 path.push_back(PathElement(SkIntToScalar(hex_value))); | 154 path.push_back(PathElement(SkIntToScalar(hex_value))); |
| 151 else | 155 else |
| 152 path.push_back(PathElement(CommandFromString(piece))); | 156 path.push_back(PathElement(CommandFromString(piece))); |
| 153 } | 157 } |
| 154 return path; | 158 return path; |
| 155 } | 159 } |
| 156 | 160 |
| 157 void PaintPath(Canvas* canvas, | 161 void PaintPath(Canvas* canvas, |
| 158 const PathElement* path_elements, | 162 const PathElement* path_elements, |
| 159 int dip_size, | 163 int dip_size, |
| 160 SkColor color) { | 164 SkColor color, |
| 165 const base::TimeDelta* elapsed_time = nullptr) { | |
|
sadrul
2017/05/11 04:22:55
Can this just be a const-ref?
const base::TimeD
Evan Stade
2017/05/11 16:16:26
Done.
| |
| 161 SkPath path; | 166 SkPath path; |
| 162 path.setFillType(SkPath::kEvenOdd_FillType); | 167 path.setFillType(SkPath::kEvenOdd_FillType); |
| 163 | 168 |
| 164 int canvas_size = kReferenceSizeDip; | 169 int canvas_size = kReferenceSizeDip; |
| 165 std::vector<SkPath> paths; | 170 std::vector<SkPath> paths; |
| 166 std::vector<cc::PaintFlags> flags_array; | 171 std::vector<cc::PaintFlags> flags_array; |
| 167 SkRect clip_rect = SkRect::MakeEmpty(); | 172 SkRect clip_rect = SkRect::MakeEmpty(); |
| 168 bool flips_in_rtl = false; | 173 bool flips_in_rtl = false; |
| 169 CommandType previous_command_type = NEW_PATH; | 174 CommandType previous_command_type = NEW_PATH; |
| 170 | 175 |
| 171 for (PathParser parser(path_elements); parser.CurrentCommand() != END; | 176 for (PathParser parser(path_elements); parser.CurrentCommand() != END; |
| 172 parser.Advance()) { | 177 parser.Advance()) { |
| 173 auto arg = [&parser](int i) { return parser.GetArgument(i); }; | 178 auto arg = [&parser](int i) { return parser.GetArgument(i); }; |
| 174 const CommandType command_type = parser.CurrentCommand(); | 179 const CommandType command_type = parser.CurrentCommand(); |
| 175 if (paths.empty() || command_type == NEW_PATH) { | 180 auto start_new_path = [&paths]() { |
| 176 paths.push_back(SkPath()); | 181 paths.push_back(SkPath()); |
| 177 paths.back().setFillType(SkPath::kEvenOdd_FillType); | 182 paths.back().setFillType(SkPath::kEvenOdd_FillType); |
| 178 | 183 }; |
| 184 auto start_new_flags = [&flags_array, &color]() { | |
| 179 flags_array.push_back(cc::PaintFlags()); | 185 flags_array.push_back(cc::PaintFlags()); |
| 180 flags_array.back().setColor(color); | 186 flags_array.back().setColor(color); |
| 181 flags_array.back().setAntiAlias(true); | 187 flags_array.back().setAntiAlias(true); |
| 182 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); | 188 flags_array.back().setStrokeCap(cc::PaintFlags::kRound_Cap); |
| 189 }; | |
| 190 | |
| 191 if (paths.empty() || command_type == NEW_PATH) { | |
| 192 start_new_path(); | |
| 193 start_new_flags(); | |
| 183 } | 194 } |
| 184 | 195 |
| 185 SkPath& path = paths.back(); | 196 SkPath& path = paths.back(); |
| 186 cc::PaintFlags& flags = flags_array.back(); | 197 cc::PaintFlags& flags = flags_array.back(); |
| 187 switch (command_type) { | 198 switch (command_type) { |
| 188 // Handled above. | 199 // Handled above. |
| 189 case NEW_PATH: | 200 case NEW_PATH: |
| 190 break; | 201 break; |
| 191 | 202 |
| 192 case PATH_COLOR_ARGB: | 203 case PATH_COLOR_ARGB: |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 break; | 343 break; |
| 333 | 344 |
| 334 case DISABLE_AA: | 345 case DISABLE_AA: |
| 335 flags.setAntiAlias(false); | 346 flags.setAntiAlias(false); |
| 336 break; | 347 break; |
| 337 | 348 |
| 338 case FLIPS_IN_RTL: | 349 case FLIPS_IN_RTL: |
| 339 flips_in_rtl = true; | 350 flips_in_rtl = true; |
| 340 break; | 351 break; |
| 341 | 352 |
| 353 // Transitions work by pushing new paths and a new set of flags onto the | |
| 354 // stack. When TRANSITION_END is seen, the paths and flags are | |
| 355 // interpolated based on |elapsed_time| and the tween type. | |
| 356 case TRANSITION_FROM: { | |
| 357 start_new_path(); | |
| 358 break; | |
| 359 } | |
| 360 | |
| 361 case TRANSITION_TO: { | |
| 362 start_new_path(); | |
| 363 start_new_flags(); | |
| 364 break; | |
| 365 } | |
| 366 | |
| 367 case TRANSITION_END: { | |
| 368 DCHECK_GT(paths.size(), 2U); | |
| 369 | |
| 370 const base::TimeDelta delay = | |
| 371 base::TimeDelta::FromMillisecondsD(SkScalarToDouble(arg(0))); | |
| 372 const base::TimeDelta duration = | |
| 373 base::TimeDelta::FromMillisecondsD(SkScalarToDouble(arg(1))); | |
| 374 const base::TimeDelta current_time = | |
| 375 elapsed_time ? *elapsed_time : base::TimeDelta(); | |
| 376 | |
| 377 double state = 0; | |
| 378 if (current_time >= delay + duration) { | |
| 379 state = 1; | |
| 380 } else if (current_time > delay) { | |
| 381 state = (current_time - delay).ToInternalValue() / | |
| 382 static_cast<double>(duration.ToInternalValue()); | |
| 383 } | |
| 384 | |
| 385 auto weight = | |
| 386 Tween::CalculateValue(static_cast<Tween::Type>(arg(2)), state); | |
| 387 | |
| 388 SkPath path1, path2; | |
| 389 path1.swap(paths.back()); | |
| 390 paths.pop_back(); | |
| 391 path2.swap(paths.back()); | |
| 392 paths.pop_back(); | |
| 393 | |
| 394 SkPath interpolated_path; | |
| 395 bool could_interpolate = | |
| 396 path1.interpolate(path2, weight, &interpolated_path); | |
|
sadrul
2017/05/11 04:22:55
Do you have a sense of how costly this interpolati
Evan Stade
2017/05/11 16:16:26
it should be cheap. For each argument it's just ta
sadrul
2017/05/11 17:36:38
Let's add TRACE_EVENT now, and a TODO referencing
| |
| 397 DCHECK(could_interpolate); | |
| 398 paths.back().addPath(interpolated_path); | |
| 399 | |
| 400 // Perform manual interpolation of flags properties. TODO(estade): fill | |
| 401 // more of these in as necessary. | |
| 402 DCHECK_GT(flags_array.size(), 1U); | |
| 403 cc::PaintFlags& end_flags = flags_array.back(); | |
| 404 cc::PaintFlags& start_flags = flags_array[flags_array.size() - 2]; | |
| 405 | |
| 406 start_flags.setColor(Tween::ColorValueBetween( | |
| 407 weight, start_flags.getColor(), end_flags.getColor())); | |
| 408 | |
| 409 flags_array.pop_back(); | |
| 410 break; | |
| 411 } | |
| 412 | |
| 342 case END: | 413 case END: |
| 343 NOTREACHED(); | 414 NOTREACHED(); |
| 344 break; | 415 break; |
| 345 } | 416 } |
| 346 | 417 |
| 347 previous_command_type = command_type; | 418 previous_command_type = command_type; |
| 348 } | 419 } |
| 349 | 420 |
| 350 gfx::ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, | 421 ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, flips_in_rtl); |
| 351 flips_in_rtl); | |
| 352 | 422 |
| 353 if (dip_size != canvas_size) { | 423 if (dip_size != canvas_size) { |
| 354 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); | 424 SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size); |
| 355 canvas->sk_canvas()->scale(scale, scale); | 425 canvas->sk_canvas()->scale(scale, scale); |
| 356 } | 426 } |
| 357 | 427 |
| 358 if (!clip_rect.isEmpty()) | 428 if (!clip_rect.isEmpty()) |
| 359 canvas->sk_canvas()->clipRect(clip_rect); | 429 canvas->sk_canvas()->clipRect(clip_rect); |
| 360 | 430 |
| 361 DCHECK_EQ(flags_array.size(), paths.size()); | 431 DCHECK_EQ(flags_array.size(), paths.size()); |
| 362 for (size_t i = 0; i < paths.size(); ++i) | 432 for (size_t i = 0; i < paths.size(); ++i) |
| 363 canvas->DrawPath(paths[i], flags_array[i]); | 433 canvas->DrawPath(paths[i], flags_array[i]); |
| 364 } | 434 } |
| 365 | 435 |
| 366 class VectorIconSource : public CanvasImageSource { | 436 class VectorIconSource : public CanvasImageSource { |
| 367 public: | 437 public: |
| 368 VectorIconSource(const VectorIcon& icon, | 438 VectorIconSource(const VectorIcon& icon, |
| 369 int dip_size, | 439 int dip_size, |
| 370 SkColor color, | 440 SkColor color, |
| 371 const VectorIcon& badge_icon) | 441 const VectorIcon& badge_icon) |
| 372 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), | 442 : CanvasImageSource(Size(dip_size, dip_size), false), |
| 373 color_(color), | 443 color_(color), |
| 374 icon_(icon), | 444 icon_(icon), |
| 375 badge_(badge_icon) {} | 445 badge_(badge_icon) {} |
| 376 | 446 |
| 377 VectorIconSource(const std::string& definition, int dip_size, SkColor color) | 447 VectorIconSource(const std::string& definition, int dip_size, SkColor color) |
| 378 : CanvasImageSource(gfx::Size(dip_size, dip_size), false), | 448 : CanvasImageSource(Size(dip_size, dip_size), false), |
| 379 color_(color), | 449 color_(color), |
| 380 icon_(kNoneIcon), | 450 icon_(kNoneIcon), |
| 381 badge_(kNoneIcon), | 451 badge_(kNoneIcon), |
| 382 path_(PathFromSource(definition)) {} | 452 path_(PathFromSource(definition)) {} |
| 383 | 453 |
| 384 ~VectorIconSource() override {} | 454 ~VectorIconSource() override {} |
| 385 | 455 |
| 386 // CanvasImageSource: | 456 // CanvasImageSource: |
| 387 bool HasRepresentationAtAllScales() const override { | 457 bool HasRepresentationAtAllScales() const override { |
| 388 return !icon_.is_empty(); | 458 return !icon_.is_empty(); |
| 389 } | 459 } |
| 390 | 460 |
| 391 void Draw(gfx::Canvas* canvas) override { | 461 void Draw(Canvas* canvas) override { |
| 392 if (path_.empty()) { | 462 if (path_.empty()) { |
| 393 PaintVectorIcon(canvas, icon_, size_.width(), color_); | 463 PaintVectorIcon(canvas, icon_, size_.width(), color_); |
| 394 if (!badge_.is_empty()) | 464 if (!badge_.is_empty()) |
| 395 PaintVectorIcon(canvas, badge_, size_.width(), color_); | 465 PaintVectorIcon(canvas, badge_, size_.width(), color_); |
| 396 } else { | 466 } else { |
| 397 PaintPath(canvas, path_.data(), size_.width(), color_); | 467 PaintPath(canvas, path_.data(), size_.width(), color_); |
| 398 } | 468 } |
| 399 } | 469 } |
| 400 | 470 |
| 401 private: | 471 private: |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 419 int dip_size, | 489 int dip_size, |
| 420 SkColor color, | 490 SkColor color, |
| 421 const VectorIcon& badge_icon) { | 491 const VectorIcon& badge_icon) { |
| 422 IconDescription description(&icon, dip_size, color, &badge_icon); | 492 IconDescription description(&icon, dip_size, color, &badge_icon); |
| 423 auto iter = images_.find(description); | 493 auto iter = images_.find(description); |
| 424 if (iter != images_.end()) | 494 if (iter != images_.end()) |
| 425 return iter->second; | 495 return iter->second; |
| 426 | 496 |
| 427 ImageSkia icon_image( | 497 ImageSkia icon_image( |
| 428 new VectorIconSource(icon, dip_size, color, badge_icon), | 498 new VectorIconSource(icon, dip_size, color, badge_icon), |
| 429 gfx::Size(dip_size, dip_size)); | 499 Size(dip_size, dip_size)); |
| 430 images_.insert(std::make_pair(description, icon_image)); | 500 images_.insert(std::make_pair(description, icon_image)); |
| 431 return icon_image; | 501 return icon_image; |
| 432 } | 502 } |
| 433 | 503 |
| 434 private: | 504 private: |
| 435 struct IconDescription { | 505 struct IconDescription { |
| 436 IconDescription(const VectorIcon* icon, | 506 IconDescription(const VectorIcon* icon, |
| 437 int dip_size, | 507 int dip_size, |
| 438 SkColor color, | 508 SkColor color, |
| 439 const VectorIcon* badge_icon) | 509 const VectorIcon* badge_icon) |
| 440 : icon(icon), | 510 : icon(icon), |
| 441 dip_size(dip_size), | 511 dip_size(dip_size), |
| 442 color(color), | 512 color(color), |
| 443 badge_icon(badge_icon) {} | 513 badge_icon(badge_icon) {} |
| 444 | 514 |
| 445 bool operator<(const IconDescription& other) const { | 515 bool operator<(const IconDescription& other) const { |
| 446 return std::tie(icon, dip_size, color, badge_icon) < | 516 return std::tie(icon, dip_size, color, badge_icon) < |
| 447 std::tie(other.icon, other.dip_size, other.color, | 517 std::tie(other.icon, other.dip_size, other.color, |
| 448 other.badge_icon); | 518 other.badge_icon); |
| 449 } | 519 } |
| 450 | 520 |
| 451 const gfx::VectorIcon* icon; | 521 const VectorIcon* icon; |
| 452 int dip_size; | 522 int dip_size; |
| 453 SkColor color; | 523 SkColor color; |
| 454 const gfx::VectorIcon* badge_icon; | 524 const VectorIcon* badge_icon; |
| 455 }; | 525 }; |
| 456 | 526 |
| 457 std::map<IconDescription, ImageSkia> images_; | 527 std::map<IconDescription, ImageSkia> images_; |
| 458 | 528 |
| 459 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); | 529 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); |
| 460 }; | 530 }; |
| 461 | 531 |
| 462 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = | 532 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = |
| 463 LAZY_INSTANCE_INITIALIZER; | 533 LAZY_INSTANCE_INITIALIZER; |
| 464 | 534 |
| 465 } // namespace | 535 } // namespace |
| 466 | 536 |
| 467 const VectorIcon kNoneIcon = {}; | 537 const VectorIcon kNoneIcon = {}; |
| 468 | 538 |
| 469 void PaintVectorIcon(Canvas* canvas, const VectorIcon& icon, SkColor color) { | 539 void PaintVectorIcon(Canvas* canvas, |
| 470 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); | |
| 471 } | 545 } |
| 472 | 546 |
| 473 void PaintVectorIcon(Canvas* canvas, | 547 void PaintVectorIcon(Canvas* canvas, |
| 474 const VectorIcon& icon, | 548 const VectorIcon& icon, |
| 475 int dip_size, | 549 int dip_size, |
| 476 SkColor color) { | 550 SkColor color, |
| 551 const base::TimeDelta* elapsed_time) { | |
| 477 DCHECK(!icon.is_empty()); | 552 DCHECK(!icon.is_empty()); |
| 478 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_) | 553 const PathElement* path = (canvas->image_scale() == 1.f && icon.path_1x_) |
| 479 ? icon.path_1x_ | 554 ? icon.path_1x_ |
| 480 : icon.path_; | 555 : icon.path_; |
| 481 PaintPath(canvas, path, dip_size, color); | 556 PaintPath(canvas, path, dip_size, color, elapsed_time); |
| 482 } | 557 } |
| 483 | 558 |
| 484 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { | 559 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { |
| 485 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); | 560 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); |
| 486 } | 561 } |
| 487 | 562 |
| 488 ImageSkia CreateVectorIcon(const VectorIcon& icon, | 563 ImageSkia CreateVectorIcon(const VectorIcon& icon, |
| 489 int dip_size, | 564 int dip_size, |
| 490 SkColor color) { | 565 SkColor color) { |
| 491 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); | 566 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); |
| 492 } | 567 } |
| 493 | 568 |
| 494 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, | 569 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, |
| 495 int dip_size, | 570 int dip_size, |
| 496 SkColor color, | 571 SkColor color, |
| 497 const VectorIcon& badge_icon) { | 572 const VectorIcon& badge_icon) { |
| 498 return icon.is_empty() ? gfx::ImageSkia() | 573 return icon.is_empty() ? ImageSkia() |
| 499 : g_icon_cache.Get().GetOrCreateIcon( | 574 : g_icon_cache.Get().GetOrCreateIcon( |
| 500 icon, dip_size, color, badge_icon); | 575 icon, dip_size, color, badge_icon); |
| 501 } | 576 } |
| 502 | 577 |
| 503 ImageSkia CreateVectorIconFromSource(const std::string& source, | 578 ImageSkia CreateVectorIconFromSource(const std::string& source, |
| 504 int dip_size, | 579 int dip_size, |
| 505 SkColor color) { | 580 SkColor color) { |
| 506 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, | 581 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, |
| 507 color); | 582 color); |
| 508 } | 583 } |
| 509 | 584 |
| 510 int GetDefaultSizeOfVectorIcon(const gfx::VectorIcon& icon) { | 585 int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) { |
| 511 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_; |
| 512 return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg | 587 return one_x_path[0].command == CANVAS_DIMENSIONS ? one_x_path[1].arg |
| 513 : kReferenceSizeDip; | 588 : kReferenceSizeDip; |
| 514 } | 589 } |
| 515 | 590 |
| 591 base::TimeDelta GetDurationOfAnimation(const VectorIcon& icon) { | |
| 592 base::TimeDelta last_motion; | |
| 593 for (PathParser parser(icon.path); parser.CurrentCommand() != END; | |
| 594 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; | |
| 604 } | |
| 605 | |
| 516 } // namespace gfx | 606 } // namespace gfx |
| OLD | NEW |