Chromium Code Reviews| Index: ui/gfx/image/image_skia_operations.cc |
| diff --git a/ui/gfx/image/image_skia_operations.cc b/ui/gfx/image/image_skia_operations.cc |
| index 383623515779eeec0d85494df9ad7216c27f2f4c..531af2403527aee632cf7c2b65fb7912cdff9ed8 100644 |
| --- a/ui/gfx/image/image_skia_operations.cc |
| +++ b/ui/gfx/image/image_skia_operations.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "skia/ext/image_operations.h" |
| +#include "third_party/skia/include/core/SkClipOp.h" |
| #include "third_party/skia/include/core/SkDrawLooper.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/geometry/insets.h" |
| @@ -370,11 +371,8 @@ class ResizeSource : public ImageSkiaSource { |
| // |source| that represent requested scale factors. |
| class DropShadowSource : public ImageSkiaSource { |
| public: |
| - DropShadowSource(const ImageSkia& source, |
| - const ShadowValues& shadows_in_dip) |
| - : source_(source), |
| - shaodws_in_dip_(shadows_in_dip) { |
| - } |
| + DropShadowSource(const ImageSkia& source, const ShadowValues& shadows_in_dip) |
| + : source_(source), shadows_in_dip_(shadows_in_dip) {} |
| ~DropShadowSource() override {} |
| // gfx::ImageSkiaSource overrides: |
| @@ -382,8 +380,8 @@ class DropShadowSource : public ImageSkiaSource { |
| const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); |
| ShadowValues shadows_in_pixel; |
| - for (size_t i = 0; i < shaodws_in_dip_.size(); ++i) |
| - shadows_in_pixel.push_back(shaodws_in_dip_[i].Scale(scale)); |
| + for (size_t i = 0; i < shadows_in_dip_.size(); ++i) |
| + shadows_in_pixel.push_back(shadows_in_dip_[i].Scale(scale)); |
| const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow( |
| image_rep.sk_bitmap(), |
| @@ -393,12 +391,61 @@ class DropShadowSource : public ImageSkiaSource { |
| private: |
| const ImageSkia source_; |
| - const ShadowValues shaodws_in_dip_; |
| + const ShadowValues shadows_in_dip_; |
| DISALLOW_COPY_AND_ASSIGN(DropShadowSource); |
| }; |
| -// An image source that is 1dp wide, suitable for tiling horizontally. |
| +class ShadowNineboxSource : public CanvasImageSource { |
| + public: |
| + ShadowNineboxSource(const std::vector<ShadowValue>& shadows, |
| + float corner_radius) |
| + : CanvasImageSource(CalculateSize(shadows, corner_radius), false), |
| + shadows_(shadows), |
| + corner_radius_(corner_radius) { |
| + DCHECK(!shadows.empty()); |
| + } |
| + ~ShadowNineboxSource() override {} |
| + |
| + // CanvasImageSource overrides: |
| + void Draw(Canvas* canvas) override { |
| + SkPaint paint; |
| + paint.setLooper(CreateShadowDrawLooperCorrectBlur(shadows_)); |
| + Insets insets = -ShadowValue::GetMargin(shadows_); |
| + gfx::Rect bounds(size()); |
| + bounds.Inset(insets); |
| + SkRRect r_rect = SkRRect::MakeRectXY(gfx::RectToSkRect(bounds), |
| + corner_radius_, corner_radius_); |
| + |
| + // Clip out the center so it's not painted with the shadow. |
| + canvas->sk_canvas()->clipRRect(r_rect, kDifference_SkClipOp, true); |
| + // Clipping alone is not enough --- due to anti aliasing there will still be |
| + // some of the fill color in the rounded corners. We must make the fill |
| + // color transparent. |
| + paint.setColor(SK_ColorTRANSPARENT); |
| + canvas->sk_canvas()->drawRRect(r_rect, paint); |
| + } |
| + |
| + private: |
| + static Size CalculateSize(const std::vector<ShadowValue>& shadows, |
| + float corner_radius) { |
| + // The "content" area (the middle tile in the 3x3 grid) is a single pixel. |
| + gfx::Rect bounds(0, 0, 1, 1); |
| + // We need enough space to render the full range of blur. |
| + bounds.Inset(-ShadowValue::GetBlurRegion(shadows)); |
| + // We also need space for the full roundrect corner rounding. |
| + bounds.Inset(-gfx::Insets(corner_radius)); |
| + return bounds.size(); |
| + } |
| + |
| + const std::vector<ShadowValue> shadows_; |
| + |
| + float corner_radius_; |
|
sky
2016/12/07 16:39:32
const
Evan Stade
2016/12/07 18:55:00
Done.
|
| + |
| + DISALLOW_COPY_AND_ASSIGN(ShadowNineboxSource); |
| +}; |
| + |
| +// An image source that is 1px wide, suitable for tiling horizontally. |
| class HorizontalShadowSource : public CanvasImageSource { |
| public: |
| HorizontalShadowSource(const std::vector<ShadowValue>& shadows, |
| @@ -592,11 +639,17 @@ ImageSkia ImageSkiaOperations::CreateImageWithDropShadow( |
| } |
| // static |
| +ImageSkia ImageSkiaOperations::CreateShadowNinebox(const ShadowValues& shadows, |
| + float corner_radius) { |
| + auto source = new ShadowNineboxSource(shadows, corner_radius); |
| + return ImageSkia(source, source->size()); |
| +} |
| + |
| +// static |
| ImageSkia ImageSkiaOperations::CreateHorizontalShadow( |
| const std::vector<ShadowValue>& shadows, |
| bool fades_down) { |
| - HorizontalShadowSource* source = |
| - new HorizontalShadowSource(shadows, fades_down); |
| + auto source = new HorizontalShadowSource(shadows, fades_down); |
| return ImageSkia(source, source->size()); |
| } |