Add ICU message format support
[chromium-blink-merge.git] / ui / views / painter.cc
blob42db547d9a0b1509eab50ce82f5deefdea5f294c
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.
5 #include "ui/views/painter.h"
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/geometry/insets.h"
13 #include "ui/gfx/geometry/point.h"
14 #include "ui/gfx/geometry/rect.h"
15 #include "ui/gfx/image/image.h"
16 #include "ui/gfx/image/image_skia.h"
17 #include "ui/gfx/image/image_skia_operations.h"
18 #include "ui/gfx/nine_image_painter.h"
19 #include "ui/views/view.h"
21 namespace views {
23 namespace {
25 // DashedFocusPainter ----------------------------------------------------------
27 class DashedFocusPainter : public Painter {
28 public:
29 explicit DashedFocusPainter(const gfx::Insets& insets);
30 ~DashedFocusPainter() override;
32 // Painter:
33 gfx::Size GetMinimumSize() const override;
34 void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
36 private:
37 const gfx::Insets insets_;
39 DISALLOW_COPY_AND_ASSIGN(DashedFocusPainter);
42 DashedFocusPainter::DashedFocusPainter(const gfx::Insets& insets)
43 : insets_(insets) {
46 DashedFocusPainter::~DashedFocusPainter() {
49 gfx::Size DashedFocusPainter::GetMinimumSize() const {
50 return gfx::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);
59 // SolidFocusPainter -----------------------------------------------------------
61 class SolidFocusPainter : public Painter {
62 public:
63 SolidFocusPainter(SkColor color, const gfx::Insets& insets);
64 ~SolidFocusPainter() override;
66 // Painter:
67 gfx::Size GetMinimumSize() const override;
68 void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
70 private:
71 const SkColor color_;
72 const gfx::Insets insets_;
74 DISALLOW_COPY_AND_ASSIGN(SolidFocusPainter);
77 SolidFocusPainter::SolidFocusPainter(SkColor color,
78 const gfx::Insets& insets)
79 : color_(color),
80 insets_(insets) {
83 SolidFocusPainter::~SolidFocusPainter() {
86 gfx::Size SolidFocusPainter::GetMinimumSize() const {
87 return gfx::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_);
96 // GradientPainter ------------------------------------------------------------
98 class GradientPainter : public Painter {
99 public:
100 GradientPainter(bool horizontal,
101 SkColor* colors,
102 SkScalar* pos,
103 size_t count);
104 ~GradientPainter() override;
106 // Painter:
107 gfx::Size GetMinimumSize() const override;
108 void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
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_;
120 DISALLOW_COPY_AND_ASSIGN(GradientPainter);
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];
137 GradientPainter::~GradientPainter() {
140 gfx::Size GradientPainter::GetMinimumSize() const {
141 return gfx::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());
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());
158 canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
159 SkIntToScalar(size.width()),
160 SkIntToScalar(size.height()), paint);
163 // ImagePainter ---------------------------------------------------------------
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[]);
172 // Constructs an ImagePainter with the specified image and insets.
173 ImagePainter(const gfx::ImageSkia& image, const gfx::Insets& insets);
175 ~ImagePainter() override;
177 // Painter:
178 gfx::Size GetMinimumSize() const override;
179 void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
181 private:
182 scoped_ptr<gfx::NineImagePainter> nine_painter_;
184 DISALLOW_COPY_AND_ASSIGN(ImagePainter);
187 ImagePainter::ImagePainter(const int image_ids[])
188 : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
191 ImagePainter::ImagePainter(const gfx::ImageSkia& image,
192 const gfx::Insets& insets)
193 : nine_painter_(new gfx::NineImagePainter(image, insets)) {
196 ImagePainter::~ImagePainter() {
199 gfx::Size ImagePainter::GetMinimumSize() const {
200 return nine_painter_->GetMinimumSize();
203 void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
204 nine_painter_->Paint(canvas, gfx::Rect(size));
207 } // namespace
210 // Painter --------------------------------------------------------------------
212 Painter::Painter() {
215 Painter::~Painter() {
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();
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());
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);
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);
255 // static
256 Painter* Painter::CreateVerticalMultiColorGradient(SkColor* colors,
257 SkScalar* pos,
258 size_t count) {
259 return new GradientPainter(false, colors, pos, count);
262 // static
263 Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
264 const gfx::Insets& insets) {
265 return new ImagePainter(image, insets);
268 // static
269 Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
270 return new ImagePainter(image_ids);
273 // static
274 scoped_ptr<Painter> Painter::CreateDashedFocusPainter() {
275 return make_scoped_ptr(new DashedFocusPainter(gfx::Insets()));
278 // static
279 scoped_ptr<Painter> Painter::CreateDashedFocusPainterWithInsets(
280 const gfx::Insets& insets) {
281 return make_scoped_ptr(new DashedFocusPainter(insets));
284 // static
285 scoped_ptr<Painter> Painter::CreateSolidFocusPainter(
286 SkColor color,
287 const gfx::Insets& insets) {
288 return make_scoped_ptr(new SolidFocusPainter(color, insets));
291 // HorizontalPainter ----------------------------------------------------------
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());
301 HorizontalPainter::~HorizontalPainter() {
304 gfx::Size HorizontalPainter::GetMinimumSize() const {
305 return gfx::Size(
306 images_[LEFT]->width() + images_[CENTER]->width() +
307 images_[RIGHT]->width(), images_[LEFT]->height());
310 void HorizontalPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
311 if (size.width() < GetMinimumSize().width())
312 return; // No room to paint.
314 canvas->DrawImageInt(*images_[LEFT], 0, 0);
315 canvas->DrawImageInt(*images_[RIGHT], size.width() - images_[RIGHT]->width(),
317 canvas->TileImageInt(
318 *images_[CENTER], images_[LEFT]->width(), 0,
319 size.width() - images_[LEFT]->width() - images_[RIGHT]->width(),
320 images_[LEFT]->height());
323 } // namespace views