Home | History | Annotate | Download | only in views
      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
      3 // found in the LICENSE file.
      4 
      5 #include "ui/views/painter.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "third_party/skia/include/effects/SkGradientShader.h"
     10 #include "ui/base/resource/resource_bundle.h"
     11 #include "ui/gfx/canvas.h"
     12 #include "ui/gfx/image/image.h"
     13 #include "ui/gfx/image/image_skia.h"
     14 #include "ui/gfx/image/image_skia_operations.h"
     15 #include "ui/gfx/insets.h"
     16 #include "ui/gfx/nine_image_painter.h"
     17 #include "ui/gfx/point.h"
     18 #include "ui/gfx/rect.h"
     19 #include "ui/views/view.h"
     20 
     21 namespace views {
     22 
     23 namespace {
     24 
     25 // DashedFocusPainter ----------------------------------------------------------
     26 
     27 class DashedFocusPainter : public Painter {
     28  public:
     29   explicit DashedFocusPainter(const gfx::Insets& insets);
     30   virtual ~DashedFocusPainter();
     31 
     32   // Painter:
     33   virtual gfx::Size GetMinimumSize() const OVERRIDE;
     34   virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
     35 
     36  private:
     37   const gfx::Insets insets_;
     38 
     39   DISALLOW_COPY_AND_ASSIGN(DashedFocusPainter);
     40 };
     41 
     42 DashedFocusPainter::DashedFocusPainter(const gfx::Insets& insets)
     43     : insets_(insets) {
     44 }
     45 
     46 DashedFocusPainter::~DashedFocusPainter() {
     47 }
     48 
     49 gfx::Size DashedFocusPainter::GetMinimumSize() const {
     50   return gfx::Size();
     51 }
     52 
     53 void DashedFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
     54   gfx::Rect rect(size);
     55   rect.Inset(insets_);
     56   canvas->DrawFocusRect(rect);
     57 }
     58 
     59 // SolidFocusPainter -----------------------------------------------------------
     60 
     61 class SolidFocusPainter : public Painter {
     62  public:
     63   SolidFocusPainter(SkColor color, const gfx::Insets& insets);
     64   virtual ~SolidFocusPainter();
     65 
     66   // Painter:
     67   virtual gfx::Size GetMinimumSize() const OVERRIDE;
     68   virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
     69 
     70  private:
     71   const SkColor color_;
     72   const gfx::Insets insets_;
     73 
     74   DISALLOW_COPY_AND_ASSIGN(SolidFocusPainter);
     75 };
     76 
     77 SolidFocusPainter::SolidFocusPainter(SkColor color,
     78                                      const gfx::Insets& insets)
     79     : color_(color),
     80       insets_(insets) {
     81 }
     82 
     83 SolidFocusPainter::~SolidFocusPainter() {
     84 }
     85 
     86 gfx::Size SolidFocusPainter::GetMinimumSize() const {
     87   return gfx::Size();
     88 }
     89 
     90 void SolidFocusPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
     91   gfx::Rect rect(size);
     92   rect.Inset(insets_);
     93   canvas->DrawSolidFocusRect(rect, color_);
     94 }
     95 
     96 // GradientPainter ------------------------------------------------------------
     97 
     98 class GradientPainter : public Painter {
     99  public:
    100   GradientPainter(bool horizontal,
    101                   SkColor* colors,
    102                   SkScalar* pos,
    103                   size_t count);
    104   virtual ~GradientPainter();
    105 
    106   // Painter:
    107   virtual gfx::Size GetMinimumSize() const OVERRIDE;
    108   virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
    109 
    110  private:
    111   // If |horizontal_| is true then the gradient is painted horizontally.
    112   bool horizontal_;
    113   // The gradient colors.
    114   scoped_ptr<SkColor[]> colors_;
    115   // The relative positions of the corresponding gradient colors.
    116   scoped_ptr<SkScalar[]> pos_;
    117   // The number of elements in |colors_| and |pos_|.
    118   size_t count_;
    119 
    120   DISALLOW_COPY_AND_ASSIGN(GradientPainter);
    121 };
    122 
    123 GradientPainter::GradientPainter(bool horizontal,
    124                                  SkColor* colors,
    125                                  SkScalar* pos,
    126                                  size_t count)
    127     : horizontal_(horizontal),
    128       colors_(new SkColor[count]),
    129       pos_(new SkScalar[count]),
    130       count_(count) {
    131   for (size_t i = 0; i < count_; ++i) {
    132     pos_[i] = pos[i];
    133     colors_[i] = colors[i];
    134   }
    135 }
    136 
    137 GradientPainter::~GradientPainter() {
    138 }
    139 
    140 gfx::Size GradientPainter::GetMinimumSize() const {
    141   return gfx::Size();
    142 }
    143 
    144 void GradientPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
    145   SkPaint paint;
    146   SkPoint p[2];
    147   p[0].iset(0, 0);
    148   if (horizontal_)
    149     p[1].iset(size.width(), 0);
    150   else
    151     p[1].iset(0, size.height());
    152 
    153   skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
    154       p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode));
    155   paint.setStyle(SkPaint::kFill_Style);
    156   paint.setShader(s.get());
    157 
    158   canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
    159                                       SkIntToScalar(size.width()),
    160                                       SkIntToScalar(size.height()), paint);
    161 }
    162 
    163 // ImagePainter ---------------------------------------------------------------
    164 
    165 // ImagePainter stores and paints nine images as a scalable grid.
    166 class VIEWS_EXPORT ImagePainter : public Painter {
    167  public:
    168   // Constructs an ImagePainter with the specified image resource ids.
    169   // See CreateImageGridPainter()'s comment regarding image ID count and order.
    170   explicit ImagePainter(const int image_ids[]);
    171 
    172   // Constructs an ImagePainter with the specified image and insets.
    173   ImagePainter(const gfx::ImageSkia& image, const gfx::Insets& insets);
    174 
    175   virtual ~ImagePainter();
    176 
    177   // Painter:
    178   virtual gfx::Size GetMinimumSize() const OVERRIDE;
    179   virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
    180 
    181  private:
    182   scoped_ptr<gfx::NineImagePainter> nine_painter_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(ImagePainter);
    185 };
    186 
    187 ImagePainter::ImagePainter(const int image_ids[])
    188     : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
    189 }
    190 
    191 ImagePainter::ImagePainter(const gfx::ImageSkia& image,
    192                            const gfx::Insets& insets)
    193     : nine_painter_(new gfx::NineImagePainter(image, insets)) {
    194 }
    195 
    196 ImagePainter::~ImagePainter() {
    197 }
    198 
    199 gfx::Size ImagePainter::GetMinimumSize() const {
    200   return nine_painter_->GetMinimumSize();
    201 }
    202 
    203 void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
    204   nine_painter_->Paint(canvas, gfx::Rect(size));
    205 }
    206 
    207 }  // namespace
    208 
    209 
    210 // Painter --------------------------------------------------------------------
    211 
    212 Painter::Painter() {
    213 }
    214 
    215 Painter::~Painter() {
    216 }
    217 
    218 // static
    219 void Painter::PaintPainterAt(gfx::Canvas* canvas,
    220                              Painter* painter,
    221                              const gfx::Rect& rect) {
    222   DCHECK(canvas && painter);
    223   canvas->Save();
    224   canvas->Translate(rect.OffsetFromOrigin());
    225   painter->Paint(canvas, rect.size());
    226   canvas->Restore();
    227 }
    228 
    229 // static
    230 void Painter::PaintFocusPainter(View* view,
    231                                 gfx::Canvas* canvas,
    232                                 Painter* focus_painter) {
    233   if (focus_painter && view->HasFocus())
    234     PaintPainterAt(canvas, focus_painter, view->GetLocalBounds());
    235 }
    236 
    237 // static
    238 Painter* Painter::CreateHorizontalGradient(SkColor c1, SkColor c2) {
    239   SkColor colors[2];
    240   colors[0] = c1;
    241   colors[1] = c2;
    242   SkScalar pos[] = {0, 1};
    243   return new GradientPainter(true, colors, pos, 2);
    244 }
    245 
    246 // static
    247 Painter* Painter::CreateVerticalGradient(SkColor c1, SkColor c2) {
    248   SkColor colors[2];
    249   colors[0] = c1;
    250   colors[1] = c2;
    251   SkScalar pos[] = {0, 1};
    252   return new GradientPainter(false, colors, pos, 2);
    253 }
    254 
    255 // static
    256 Painter* Painter::CreateVerticalMultiColorGradient(SkColor* colors,
    257                                                    SkScalar* pos,
    258                                                    size_t count) {
    259   return new GradientPainter(false, colors, pos, count);
    260 }
    261 
    262 // static
    263 Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
    264                                      const gfx::Insets& insets) {
    265   return new ImagePainter(image, insets);
    266 }
    267 
    268 // static
    269 Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
    270   return new ImagePainter(image_ids);
    271 }
    272 
    273 // static
    274 scoped_ptr<Painter> Painter::CreateDashedFocusPainter() {
    275   return scoped_ptr<Painter>(new DashedFocusPainter(gfx::Insets())).Pass();
    276 }
    277 
    278 // static
    279 scoped_ptr<Painter> Painter::CreateDashedFocusPainterWithInsets(
    280     const gfx::Insets& insets) {
    281   return scoped_ptr<Painter>(new DashedFocusPainter(insets)).Pass();
    282 }
    283 
    284 // static
    285 scoped_ptr<Painter> Painter::CreateSolidFocusPainter(
    286     SkColor color,
    287     const gfx::Insets& insets) {
    288   return scoped_ptr<Painter>(new SolidFocusPainter(color, insets)).Pass();
    289 }
    290 
    291 // HorizontalPainter ----------------------------------------------------------
    292 
    293 HorizontalPainter::HorizontalPainter(const int image_resource_names[]) {
    294   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    295   for (int i = 0; i < 3; ++i)
    296     images_[i] = rb.GetImageNamed(image_resource_names[i]).ToImageSkia();
    297   DCHECK_EQ(images_[LEFT]->height(), images_[CENTER]->height());
    298   DCHECK_EQ(images_[LEFT]->height(), images_[RIGHT]->height());
    299 }
    300 
    301 HorizontalPainter::~HorizontalPainter() {
    302 }
    303 
    304 gfx::Size HorizontalPainter::GetMinimumSize() const {
    305   return gfx::Size(
    306       images_[LEFT]->width() + images_[CENTER]->width() +
    307           images_[RIGHT]->width(), images_[LEFT]->height());
    308 }
    309 
    310 void HorizontalPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
    311   if (size.width() < GetMinimumSize().width())
    312     return;  // No room to paint.
    313 
    314   canvas->DrawImageInt(*images_[LEFT], 0, 0);
    315   canvas->DrawImageInt(*images_[RIGHT], size.width() - images_[RIGHT]->width(),
    316                        0);
    317   canvas->TileImageInt(
    318       *images_[CENTER], images_[LEFT]->width(), 0,
    319       size.width() - images_[LEFT]->width() - images_[RIGHT]->width(),
    320       images_[LEFT]->height());
    321 }
    322 
    323 }  // namespace views
    324