| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/image/image_skia_operations.h" | 5 #include "ui/gfx/image/image_skia_operations.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "skia/ext/image_operations.h" | 12 #include "skia/ext/image_operations.h" |
| 13 #include "third_party/skia/include/core/SkClipOp.h" |
| 13 #include "third_party/skia/include/core/SkDrawLooper.h" | 14 #include "third_party/skia/include/core/SkDrawLooper.h" |
| 14 #include "ui/gfx/canvas.h" | 15 #include "ui/gfx/canvas.h" |
| 15 #include "ui/gfx/geometry/insets.h" | 16 #include "ui/gfx/geometry/insets.h" |
| 16 #include "ui/gfx/geometry/point.h" | 17 #include "ui/gfx/geometry/point.h" |
| 17 #include "ui/gfx/geometry/point_conversions.h" | 18 #include "ui/gfx/geometry/point_conversions.h" |
| 18 #include "ui/gfx/geometry/rect.h" | 19 #include "ui/gfx/geometry/rect.h" |
| 19 #include "ui/gfx/geometry/rect_conversions.h" | 20 #include "ui/gfx/geometry/rect_conversions.h" |
| 20 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" |
| 21 #include "ui/gfx/geometry/size_conversions.h" | 22 #include "ui/gfx/geometry/size_conversions.h" |
| 22 #include "ui/gfx/image/canvas_image_source.h" | 23 #include "ui/gfx/image/canvas_image_source.h" |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 skia::ImageOperations::ResizeMethod resize_method_; | 364 skia::ImageOperations::ResizeMethod resize_method_; |
| 364 const Size target_dip_size_; | 365 const Size target_dip_size_; |
| 365 | 366 |
| 366 DISALLOW_COPY_AND_ASSIGN(ResizeSource); | 367 DISALLOW_COPY_AND_ASSIGN(ResizeSource); |
| 367 }; | 368 }; |
| 368 | 369 |
| 369 // DropShadowSource generates image reps with drop shadow for image reps in | 370 // DropShadowSource generates image reps with drop shadow for image reps in |
| 370 // |source| that represent requested scale factors. | 371 // |source| that represent requested scale factors. |
| 371 class DropShadowSource : public ImageSkiaSource { | 372 class DropShadowSource : public ImageSkiaSource { |
| 372 public: | 373 public: |
| 373 DropShadowSource(const ImageSkia& source, | 374 DropShadowSource(const ImageSkia& source, const ShadowValues& shadows_in_dip) |
| 374 const ShadowValues& shadows_in_dip) | 375 : source_(source), shadows_in_dip_(shadows_in_dip) {} |
| 375 : source_(source), | |
| 376 shaodws_in_dip_(shadows_in_dip) { | |
| 377 } | |
| 378 ~DropShadowSource() override {} | 376 ~DropShadowSource() override {} |
| 379 | 377 |
| 380 // gfx::ImageSkiaSource overrides: | 378 // gfx::ImageSkiaSource overrides: |
| 381 ImageSkiaRep GetImageForScale(float scale) override { | 379 ImageSkiaRep GetImageForScale(float scale) override { |
| 382 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); | 380 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); |
| 383 | 381 |
| 384 ShadowValues shadows_in_pixel; | 382 ShadowValues shadows_in_pixel; |
| 385 for (size_t i = 0; i < shaodws_in_dip_.size(); ++i) | 383 for (size_t i = 0; i < shadows_in_dip_.size(); ++i) |
| 386 shadows_in_pixel.push_back(shaodws_in_dip_[i].Scale(scale)); | 384 shadows_in_pixel.push_back(shadows_in_dip_[i].Scale(scale)); |
| 387 | 385 |
| 388 const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow( | 386 const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow( |
| 389 image_rep.sk_bitmap(), | 387 image_rep.sk_bitmap(), |
| 390 shadows_in_pixel); | 388 shadows_in_pixel); |
| 391 return ImageSkiaRep(shadow_bitmap, image_rep.scale()); | 389 return ImageSkiaRep(shadow_bitmap, image_rep.scale()); |
| 392 } | 390 } |
| 393 | 391 |
| 394 private: | 392 private: |
| 395 const ImageSkia source_; | 393 const ImageSkia source_; |
| 396 const ShadowValues shaodws_in_dip_; | 394 const ShadowValues shadows_in_dip_; |
| 397 | 395 |
| 398 DISALLOW_COPY_AND_ASSIGN(DropShadowSource); | 396 DISALLOW_COPY_AND_ASSIGN(DropShadowSource); |
| 399 }; | 397 }; |
| 400 | 398 |
| 401 // An image source that is 1dp wide, suitable for tiling horizontally. | 399 class ShadowNineboxSource : public CanvasImageSource { |
| 400 public: |
| 401 ShadowNineboxSource(const std::vector<ShadowValue>& shadows, |
| 402 float corner_radius) |
| 403 : CanvasImageSource(CalculateSize(shadows, corner_radius), false), |
| 404 shadows_(shadows), |
| 405 corner_radius_(corner_radius) { |
| 406 DCHECK(!shadows.empty()); |
| 407 } |
| 408 ~ShadowNineboxSource() override {} |
| 409 |
| 410 // CanvasImageSource overrides: |
| 411 void Draw(Canvas* canvas) override { |
| 412 SkPaint paint; |
| 413 paint.setLooper(CreateShadowDrawLooperCorrectBlur(shadows_)); |
| 414 Insets insets = -ShadowValue::GetMargin(shadows_); |
| 415 gfx::Rect bounds(size()); |
| 416 bounds.Inset(insets); |
| 417 SkRRect r_rect = SkRRect::MakeRectXY(gfx::RectToSkRect(bounds), |
| 418 corner_radius_, corner_radius_); |
| 419 |
| 420 // Clip out the center so it's not painted with the shadow. |
| 421 canvas->sk_canvas()->clipRRect(r_rect, kDifference_SkClipOp, true); |
| 422 // Clipping alone is not enough --- due to anti aliasing there will still be |
| 423 // some of the fill color in the rounded corners. We must make the fill |
| 424 // color transparent. |
| 425 paint.setColor(SK_ColorTRANSPARENT); |
| 426 canvas->sk_canvas()->drawRRect(r_rect, paint); |
| 427 } |
| 428 |
| 429 private: |
| 430 static Size CalculateSize(const std::vector<ShadowValue>& shadows, |
| 431 float corner_radius) { |
| 432 // The "content" area (the middle tile in the 3x3 grid) is a single pixel. |
| 433 gfx::Rect bounds(0, 0, 1, 1); |
| 434 // We need enough space to render the full range of blur. |
| 435 bounds.Inset(-ShadowValue::GetBlurRegion(shadows)); |
| 436 // We also need space for the full roundrect corner rounding. |
| 437 bounds.Inset(-gfx::Insets(corner_radius)); |
| 438 return bounds.size(); |
| 439 } |
| 440 |
| 441 const std::vector<ShadowValue> shadows_; |
| 442 |
| 443 const float corner_radius_; |
| 444 |
| 445 DISALLOW_COPY_AND_ASSIGN(ShadowNineboxSource); |
| 446 }; |
| 447 |
| 448 // An image source that is 1px wide, suitable for tiling horizontally. |
| 402 class HorizontalShadowSource : public CanvasImageSource { | 449 class HorizontalShadowSource : public CanvasImageSource { |
| 403 public: | 450 public: |
| 404 HorizontalShadowSource(const std::vector<ShadowValue>& shadows, | 451 HorizontalShadowSource(const std::vector<ShadowValue>& shadows, |
| 405 bool fades_down) | 452 bool fades_down) |
| 406 : CanvasImageSource(Size(1, GetHeightForShadows(shadows)), false), | 453 : CanvasImageSource(Size(1, GetHeightForShadows(shadows)), false), |
| 407 shadows_(shadows), | 454 shadows_(shadows), |
| 408 fades_down_(fades_down) {} | 455 fades_down_(fades_down) {} |
| 409 ~HorizontalShadowSource() override {} | 456 ~HorizontalShadowSource() override {} |
| 410 | 457 |
| 411 // CanvasImageSource overrides: | 458 // CanvasImageSource overrides: |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 return ImageSkia(); | 632 return ImageSkia(); |
| 586 | 633 |
| 587 const gfx::Insets shadow_padding = -gfx::ShadowValue::GetMargin(shadows); | 634 const gfx::Insets shadow_padding = -gfx::ShadowValue::GetMargin(shadows); |
| 588 gfx::Size shadow_image_size = source.size(); | 635 gfx::Size shadow_image_size = source.size(); |
| 589 shadow_image_size.Enlarge(shadow_padding.width(), | 636 shadow_image_size.Enlarge(shadow_padding.width(), |
| 590 shadow_padding.height()); | 637 shadow_padding.height()); |
| 591 return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size); | 638 return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size); |
| 592 } | 639 } |
| 593 | 640 |
| 594 // static | 641 // static |
| 642 ImageSkia ImageSkiaOperations::CreateShadowNinebox(const ShadowValues& shadows, |
| 643 float corner_radius) { |
| 644 auto source = new ShadowNineboxSource(shadows, corner_radius); |
| 645 return ImageSkia(source, source->size()); |
| 646 } |
| 647 |
| 648 // static |
| 595 ImageSkia ImageSkiaOperations::CreateHorizontalShadow( | 649 ImageSkia ImageSkiaOperations::CreateHorizontalShadow( |
| 596 const std::vector<ShadowValue>& shadows, | 650 const std::vector<ShadowValue>& shadows, |
| 597 bool fades_down) { | 651 bool fades_down) { |
| 598 HorizontalShadowSource* source = | 652 auto source = new HorizontalShadowSource(shadows, fades_down); |
| 599 new HorizontalShadowSource(shadows, fades_down); | |
| 600 return ImageSkia(source, source->size()); | 653 return ImageSkia(source, source->size()); |
| 601 } | 654 } |
| 602 | 655 |
| 603 // static | 656 // static |
| 604 ImageSkia ImageSkiaOperations::CreateRotatedImage( | 657 ImageSkia ImageSkiaOperations::CreateRotatedImage( |
| 605 const ImageSkia& source, | 658 const ImageSkia& source, |
| 606 SkBitmapOperations::RotationAmount rotation) { | 659 SkBitmapOperations::RotationAmount rotation) { |
| 607 if (source.isNull()) | 660 if (source.isNull()) |
| 608 return ImageSkia(); | 661 return ImageSkia(); |
| 609 | 662 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 620 if (icon.isNull()) | 673 if (icon.isNull()) |
| 621 return ImageSkia(); | 674 return ImageSkia(); |
| 622 | 675 |
| 623 if (badge.isNull()) | 676 if (badge.isNull()) |
| 624 return icon; | 677 return icon; |
| 625 | 678 |
| 626 return ImageSkia(new IconWithBadgeSource(icon, badge), icon.size()); | 679 return ImageSkia(new IconWithBadgeSource(icon, badge), icon.size()); |
| 627 } | 680 } |
| 628 | 681 |
| 629 } // namespace gfx | 682 } // namespace gfx |
| OLD | NEW |