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