| 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 "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
| 17 #include "cc/paint/paint_canvas.h" | 17 #include "cc/paint/paint_canvas.h" |
| 18 #include "cc/paint/paint_flags.h" | 18 #include "cc/paint/paint_flags.h" |
| 19 #include "third_party/skia/include/core/SkPath.h" | 19 #include "third_party/skia/include/core/SkPath.h" |
| 20 #include "ui/gfx/animation/tween.h" | 20 #include "ui/gfx/animation/tween.h" |
| 21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/color_palette.h" |
| 22 #include "ui/gfx/image/canvas_image_source.h" | 23 #include "ui/gfx/image/canvas_image_source.h" |
| 23 #include "ui/gfx/scoped_canvas.h" | 24 #include "ui/gfx/scoped_canvas.h" |
| 24 #include "ui/gfx/vector_icon_types.h" | 25 #include "ui/gfx/vector_icon_types.h" |
| 25 | 26 |
| 26 namespace gfx { | 27 namespace gfx { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 31 struct CompareIconDescription { |
| 32 bool operator()(const IconDescription& a, const IconDescription& b) const { |
| 33 const VectorIcon* a_icon = &a.icon; |
| 34 const VectorIcon* b_icon = &b.icon; |
| 35 const VectorIcon* a_badge = &a.badge_icon; |
| 36 const VectorIcon* b_badge = &b.badge_icon; |
| 37 return std::tie(a_icon, a.dip_size, a.color, a.elapsed_time, a_badge) < |
| 38 std::tie(b_icon, b.dip_size, b.color, b.elapsed_time, b_badge); |
| 39 } |
| 40 }; |
| 41 |
| 30 // Helper that simplifies iterating over a sequence of PathElements. | 42 // Helper that simplifies iterating over a sequence of PathElements. |
| 31 class PathParser { | 43 class PathParser { |
| 32 public: | 44 public: |
| 33 PathParser(const PathElement* path_elements) | 45 PathParser(const PathElement* path_elements) |
| 34 : path_elements_(path_elements) {} | 46 : path_elements_(path_elements) {} |
| 35 ~PathParser() {} | 47 ~PathParser() {} |
| 36 | 48 |
| 37 void Advance() { command_index_ += GetArgumentCount() + 1; } | 49 void Advance() { command_index_ += GetArgumentCount() + 1; } |
| 38 | 50 |
| 39 CommandType CurrentCommand() const { | 51 CommandType CurrentCommand() const { |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 if (!clip_rect.isEmpty()) | 442 if (!clip_rect.isEmpty()) |
| 431 canvas->sk_canvas()->clipRect(clip_rect); | 443 canvas->sk_canvas()->clipRect(clip_rect); |
| 432 | 444 |
| 433 DCHECK_EQ(flags_array.size(), paths.size()); | 445 DCHECK_EQ(flags_array.size(), paths.size()); |
| 434 for (size_t i = 0; i < paths.size(); ++i) | 446 for (size_t i = 0; i < paths.size(); ++i) |
| 435 canvas->DrawPath(paths[i], flags_array[i]); | 447 canvas->DrawPath(paths[i], flags_array[i]); |
| 436 } | 448 } |
| 437 | 449 |
| 438 class VectorIconSource : public CanvasImageSource { | 450 class VectorIconSource : public CanvasImageSource { |
| 439 public: | 451 public: |
| 440 VectorIconSource(const VectorIcon& icon, | 452 explicit VectorIconSource(const IconDescription& data) |
| 441 int dip_size, | 453 : CanvasImageSource(Size(data.dip_size, data.dip_size), false), |
| 442 SkColor color, | 454 data_(data) {} |
| 443 const VectorIcon& badge_icon) | |
| 444 : CanvasImageSource(Size(dip_size, dip_size), false), | |
| 445 color_(color), | |
| 446 icon_(icon), | |
| 447 badge_(badge_icon) {} | |
| 448 | 455 |
| 449 VectorIconSource(const std::string& definition, int dip_size, SkColor color) | 456 VectorIconSource(const std::string& definition, int dip_size, SkColor color) |
| 450 : CanvasImageSource(Size(dip_size, dip_size), false), | 457 : CanvasImageSource(Size(dip_size, dip_size), false), |
| 451 color_(color), | 458 data_(kNoneIcon, dip_size, color, base::TimeDelta(), kNoneIcon), |
| 452 icon_(kNoneIcon), | |
| 453 badge_(kNoneIcon), | |
| 454 path_(PathFromSource(definition)) {} | 459 path_(PathFromSource(definition)) {} |
| 455 | 460 |
| 456 ~VectorIconSource() override {} | 461 ~VectorIconSource() override {} |
| 457 | 462 |
| 458 // CanvasImageSource: | 463 // CanvasImageSource: |
| 459 bool HasRepresentationAtAllScales() const override { | 464 bool HasRepresentationAtAllScales() const override { |
| 460 return !icon_.is_empty(); | 465 return !data_.icon.is_empty(); |
| 461 } | 466 } |
| 462 | 467 |
| 463 void Draw(Canvas* canvas) override { | 468 void Draw(Canvas* canvas) override { |
| 464 if (path_.empty()) { | 469 if (path_.empty()) { |
| 465 PaintVectorIcon(canvas, icon_, size_.width(), color_); | 470 PaintVectorIcon(canvas, data_.icon, size_.width(), data_.color, |
| 466 if (!badge_.is_empty()) | 471 data_.elapsed_time); |
| 467 PaintVectorIcon(canvas, badge_, size_.width(), color_); | 472 if (!data_.badge_icon.is_empty()) |
| 473 PaintVectorIcon(canvas, data_.badge_icon, size_.width(), data_.color); |
| 468 } else { | 474 } else { |
| 469 PaintPath(canvas, path_.data(), size_.width(), color_, base::TimeDelta()); | 475 PaintPath(canvas, path_.data(), size_.width(), data_.color, |
| 476 base::TimeDelta()); |
| 470 } | 477 } |
| 471 } | 478 } |
| 472 | 479 |
| 473 private: | 480 private: |
| 474 const SkColor color_; | 481 const IconDescription data_; |
| 475 const VectorIcon& icon_; | |
| 476 const VectorIcon& badge_; | |
| 477 const std::vector<PathElement> path_; | 482 const std::vector<PathElement> path_; |
| 478 | 483 |
| 479 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); | 484 DISALLOW_COPY_AND_ASSIGN(VectorIconSource); |
| 480 }; | 485 }; |
| 481 | 486 |
| 482 // This class caches vector icons (as ImageSkia) so they don't have to be drawn | 487 // This class caches vector icons (as ImageSkia) so they don't have to be drawn |
| 483 // more than once. This also guarantees the backing data for the images returned | 488 // more than once. This also guarantees the backing data for the images returned |
| 484 // by CreateVectorIcon will persist in memory until program termination. | 489 // by CreateVectorIcon will persist in memory until program termination. |
| 485 class VectorIconCache { | 490 class VectorIconCache { |
| 486 public: | 491 public: |
| 487 VectorIconCache() {} | 492 VectorIconCache() {} |
| 488 ~VectorIconCache() {} | 493 ~VectorIconCache() {} |
| 489 | 494 |
| 490 ImageSkia GetOrCreateIcon(const VectorIcon& icon, | 495 ImageSkia GetOrCreateIcon(const IconDescription& description) { |
| 491 int dip_size, | |
| 492 SkColor color, | |
| 493 const VectorIcon& badge_icon) { | |
| 494 IconDescription description(&icon, dip_size, color, &badge_icon); | |
| 495 auto iter = images_.find(description); | 496 auto iter = images_.find(description); |
| 496 if (iter != images_.end()) | 497 if (iter != images_.end()) |
| 497 return iter->second; | 498 return iter->second; |
| 498 | 499 |
| 499 ImageSkia icon_image( | 500 ImageSkia icon_image(new VectorIconSource(description), |
| 500 new VectorIconSource(icon, dip_size, color, badge_icon), | 501 Size(description.dip_size, description.dip_size)); |
| 501 Size(dip_size, dip_size)); | |
| 502 images_.insert(std::make_pair(description, icon_image)); | 502 images_.insert(std::make_pair(description, icon_image)); |
| 503 return icon_image; | 503 return icon_image; |
| 504 } | 504 } |
| 505 | 505 |
| 506 private: | 506 private: |
| 507 struct IconDescription { | 507 std::map<IconDescription, ImageSkia, CompareIconDescription> images_; |
| 508 IconDescription(const VectorIcon* icon, | |
| 509 int dip_size, | |
| 510 SkColor color, | |
| 511 const VectorIcon* badge_icon) | |
| 512 : icon(icon), | |
| 513 dip_size(dip_size), | |
| 514 color(color), | |
| 515 badge_icon(badge_icon) {} | |
| 516 | |
| 517 bool operator<(const IconDescription& other) const { | |
| 518 return std::tie(icon, dip_size, color, badge_icon) < | |
| 519 std::tie(other.icon, other.dip_size, other.color, | |
| 520 other.badge_icon); | |
| 521 } | |
| 522 | |
| 523 const VectorIcon* icon; | |
| 524 int dip_size; | |
| 525 SkColor color; | |
| 526 const VectorIcon* badge_icon; | |
| 527 }; | |
| 528 | |
| 529 std::map<IconDescription, ImageSkia> images_; | |
| 530 | 508 |
| 531 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); | 509 DISALLOW_COPY_AND_ASSIGN(VectorIconCache); |
| 532 }; | 510 }; |
| 533 | 511 |
| 534 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = | 512 static base::LazyInstance<VectorIconCache>::DestructorAtExit g_icon_cache = |
| 535 LAZY_INSTANCE_INITIALIZER; | 513 LAZY_INSTANCE_INITIALIZER; |
| 536 | 514 |
| 537 } // namespace | 515 } // namespace |
| 538 | 516 |
| 517 IconDescription::IconDescription(const IconDescription& other) = default; |
| 518 |
| 519 IconDescription::IconDescription(const VectorIcon& icon, |
| 520 int dip_size, |
| 521 SkColor color, |
| 522 const base::TimeDelta& elapsed_time, |
| 523 const VectorIcon& badge_icon) |
| 524 : icon(icon), |
| 525 dip_size(dip_size), |
| 526 color(color), |
| 527 elapsed_time(elapsed_time), |
| 528 badge_icon(badge_icon) { |
| 529 if (dip_size == 0) |
| 530 this->dip_size = GetDefaultSizeOfVectorIcon(icon); |
| 531 } |
| 532 |
| 533 IconDescription::~IconDescription() {} |
| 534 |
| 539 const VectorIcon kNoneIcon = {}; | 535 const VectorIcon kNoneIcon = {}; |
| 540 | 536 |
| 541 void PaintVectorIcon(Canvas* canvas, | 537 void PaintVectorIcon(Canvas* canvas, |
| 542 const VectorIcon& icon, | 538 const VectorIcon& icon, |
| 543 SkColor color, | 539 SkColor color, |
| 544 const base::TimeDelta& elapsed_time) { | 540 const base::TimeDelta& elapsed_time) { |
| 545 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color, | 541 PaintVectorIcon(canvas, icon, GetDefaultSizeOfVectorIcon(icon), color, |
| 546 elapsed_time); | 542 elapsed_time); |
| 547 } | 543 } |
| 548 | 544 |
| 549 void PaintVectorIcon(Canvas* canvas, | 545 void PaintVectorIcon(Canvas* canvas, |
| 550 const VectorIcon& icon, | 546 const VectorIcon& icon, |
| 551 int dip_size, | 547 int dip_size, |
| 552 SkColor color, | 548 SkColor color, |
| 553 const base::TimeDelta& elapsed_time) { | 549 const base::TimeDelta& elapsed_time) { |
| 554 DCHECK(!icon.is_empty()); | 550 DCHECK(!icon.is_empty()); |
| 555 const PathElement* path = | 551 const PathElement* path = |
| 556 (canvas->image_scale() == 1.f && icon.path_1x) ? icon.path_1x : icon.path; | 552 (canvas->image_scale() == 1.f && icon.path_1x) ? icon.path_1x : icon.path; |
| 557 PaintPath(canvas, path, dip_size, color, elapsed_time); | 553 PaintPath(canvas, path, dip_size, color, elapsed_time); |
| 558 } | 554 } |
| 559 | 555 |
| 556 ImageSkia CreateVectorIcon(const IconDescription& params) { |
| 557 if (params.icon.is_empty()) |
| 558 return gfx::ImageSkia(); |
| 559 |
| 560 return g_icon_cache.Get().GetOrCreateIcon(params); |
| 561 } |
| 562 |
| 560 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { | 563 ImageSkia CreateVectorIcon(const VectorIcon& icon, SkColor color) { |
| 561 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); | 564 return CreateVectorIcon(icon, GetDefaultSizeOfVectorIcon(icon), color); |
| 562 } | 565 } |
| 563 | 566 |
| 564 ImageSkia CreateVectorIcon(const VectorIcon& icon, | 567 ImageSkia CreateVectorIcon(const VectorIcon& icon, |
| 565 int dip_size, | 568 int dip_size, |
| 566 SkColor color) { | 569 SkColor color) { |
| 567 return CreateVectorIconWithBadge(icon, dip_size, color, kNoneIcon); | 570 return CreateVectorIcon( |
| 571 IconDescription(icon, dip_size, color, base::TimeDelta(), kNoneIcon)); |
| 568 } | 572 } |
| 569 | 573 |
| 570 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, | 574 ImageSkia CreateVectorIconWithBadge(const VectorIcon& icon, |
| 571 int dip_size, | 575 int dip_size, |
| 572 SkColor color, | 576 SkColor color, |
| 573 const VectorIcon& badge_icon) { | 577 const VectorIcon& badge_icon) { |
| 574 return icon.is_empty() ? ImageSkia() | 578 return CreateVectorIcon( |
| 575 : g_icon_cache.Get().GetOrCreateIcon( | 579 IconDescription(icon, dip_size, color, base::TimeDelta(), badge_icon)); |
| 576 icon, dip_size, color, badge_icon); | |
| 577 } | 580 } |
| 578 | 581 |
| 579 ImageSkia CreateVectorIconFromSource(const std::string& source, | 582 ImageSkia CreateVectorIconFromSource(const std::string& source, |
| 580 int dip_size, | 583 int dip_size, |
| 581 SkColor color) { | 584 SkColor color) { |
| 582 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, | 585 return CanvasImageSource::MakeImageSkia<VectorIconSource>(source, dip_size, |
| 583 color); | 586 color); |
| 584 } | 587 } |
| 585 | 588 |
| 586 int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) { | 589 int GetDefaultSizeOfVectorIcon(const VectorIcon& icon) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 598 | 601 |
| 599 auto end_time = base::TimeDelta::FromMillisecondsD(parser.GetArgument(0)) + | 602 auto end_time = base::TimeDelta::FromMillisecondsD(parser.GetArgument(0)) + |
| 600 base::TimeDelta::FromMillisecondsD(parser.GetArgument(1)); | 603 base::TimeDelta::FromMillisecondsD(parser.GetArgument(1)); |
| 601 if (end_time > last_motion) | 604 if (end_time > last_motion) |
| 602 last_motion = end_time; | 605 last_motion = end_time; |
| 603 } | 606 } |
| 604 return last_motion; | 607 return last_motion; |
| 605 } | 608 } |
| 606 | 609 |
| 607 } // namespace gfx | 610 } // namespace gfx |
| OLD | NEW |