Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / views / painter.cc
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   ~DashedFocusPainter() override;
31
32   // Painter:
33   gfx::Size GetMinimumSize() const override;
34   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   ~SolidFocusPainter() override;
65
66   // Painter:
67   gfx::Size GetMinimumSize() const override;
68   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   ~GradientPainter() override;
105
106   // Painter:
107   gfx::Size GetMinimumSize() const override;
108   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 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   ~ImagePainter() override;
176
177   // Painter:
178   gfx::Size GetMinimumSize() const override;
179   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