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