• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DashedFocusPainter(const gfx::Insets & insets)42 DashedFocusPainter::DashedFocusPainter(const gfx::Insets& insets)
43     : insets_(insets) {
44 }
45 
~DashedFocusPainter()46 DashedFocusPainter::~DashedFocusPainter() {
47 }
48 
GetMinimumSize() const49 gfx::Size DashedFocusPainter::GetMinimumSize() const {
50   return gfx::Size();
51 }
52 
Paint(gfx::Canvas * canvas,const gfx::Size & size)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 
SolidFocusPainter(SkColor color,const gfx::Insets & insets)77 SolidFocusPainter::SolidFocusPainter(SkColor color,
78                                      const gfx::Insets& insets)
79     : color_(color),
80       insets_(insets) {
81 }
82 
~SolidFocusPainter()83 SolidFocusPainter::~SolidFocusPainter() {
84 }
85 
GetMinimumSize() const86 gfx::Size SolidFocusPainter::GetMinimumSize() const {
87   return gfx::Size();
88 }
89 
Paint(gfx::Canvas * canvas,const gfx::Size & size)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 
GradientPainter(bool horizontal,SkColor * colors,SkScalar * pos,size_t count)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 
~GradientPainter()137 GradientPainter::~GradientPainter() {
138 }
139 
GetMinimumSize() const140 gfx::Size GradientPainter::GetMinimumSize() const {
141   return gfx::Size();
142 }
143 
Paint(gfx::Canvas * canvas,const gfx::Size & size)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 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 
ImagePainter(const int image_ids[])187 ImagePainter::ImagePainter(const int image_ids[])
188     : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
189 }
190 
ImagePainter(const gfx::ImageSkia & image,const gfx::Insets & insets)191 ImagePainter::ImagePainter(const gfx::ImageSkia& image,
192                            const gfx::Insets& insets)
193     : nine_painter_(new gfx::NineImagePainter(image, insets)) {
194 }
195 
~ImagePainter()196 ImagePainter::~ImagePainter() {
197 }
198 
GetMinimumSize() const199 gfx::Size ImagePainter::GetMinimumSize() const {
200   return nine_painter_->GetMinimumSize();
201 }
202 
Paint(gfx::Canvas * canvas,const gfx::Size & size)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 
Painter()212 Painter::Painter() {
213 }
214 
~Painter()215 Painter::~Painter() {
216 }
217 
218 // static
PaintPainterAt(gfx::Canvas * canvas,Painter * painter,const gfx::Rect & rect)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
PaintFocusPainter(View * view,gfx::Canvas * canvas,Painter * focus_painter)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
CreateHorizontalGradient(SkColor c1,SkColor c2)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
CreateVerticalGradient(SkColor c1,SkColor c2)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
CreateVerticalMultiColorGradient(SkColor * colors,SkScalar * pos,size_t count)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
CreateImagePainter(const gfx::ImageSkia & image,const gfx::Insets & insets)263 Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
264                                      const gfx::Insets& insets) {
265   return new ImagePainter(image, insets);
266 }
267 
268 // static
CreateImageGridPainter(const int image_ids[])269 Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
270   return new ImagePainter(image_ids);
271 }
272 
273 // static
CreateDashedFocusPainter()274 scoped_ptr<Painter> Painter::CreateDashedFocusPainter() {
275   return scoped_ptr<Painter>(new DashedFocusPainter(gfx::Insets())).Pass();
276 }
277 
278 // static
CreateDashedFocusPainterWithInsets(const gfx::Insets & insets)279 scoped_ptr<Painter> Painter::CreateDashedFocusPainterWithInsets(
280     const gfx::Insets& insets) {
281   return scoped_ptr<Painter>(new DashedFocusPainter(insets)).Pass();
282 }
283 
284 // static
CreateSolidFocusPainter(SkColor color,const gfx::Insets & insets)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 
HorizontalPainter(const int image_resource_names[])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 
~HorizontalPainter()301 HorizontalPainter::~HorizontalPainter() {
302 }
303 
GetMinimumSize() const304 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 
Paint(gfx::Canvas * canvas,const gfx::Size & size)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