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/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"
25 // DashedFocusPainter ----------------------------------------------------------
27 class DashedFocusPainter
: public Painter
{
29 explicit DashedFocusPainter(const gfx::Insets
& insets
);
30 virtual ~DashedFocusPainter();
33 virtual gfx::Size
GetMinimumSize() const OVERRIDE
;
34 virtual void Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) OVERRIDE
;
37 const gfx::Insets insets_
;
39 DISALLOW_COPY_AND_ASSIGN(DashedFocusPainter
);
42 DashedFocusPainter::DashedFocusPainter(const gfx::Insets
& insets
)
46 DashedFocusPainter::~DashedFocusPainter() {
49 gfx::Size
DashedFocusPainter::GetMinimumSize() const {
53 void DashedFocusPainter::Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) {
56 canvas
->DrawFocusRect(rect
);
59 // SolidFocusPainter -----------------------------------------------------------
61 class SolidFocusPainter
: public Painter
{
63 SolidFocusPainter(SkColor color
, const gfx::Insets
& insets
);
64 virtual ~SolidFocusPainter();
67 virtual gfx::Size
GetMinimumSize() const OVERRIDE
;
68 virtual void Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) OVERRIDE
;
72 const gfx::Insets insets_
;
74 DISALLOW_COPY_AND_ASSIGN(SolidFocusPainter
);
77 SolidFocusPainter::SolidFocusPainter(SkColor color
,
78 const gfx::Insets
& insets
)
83 SolidFocusPainter::~SolidFocusPainter() {
86 gfx::Size
SolidFocusPainter::GetMinimumSize() const {
90 void SolidFocusPainter::Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) {
93 canvas
->DrawSolidFocusRect(rect
, color_
);
96 // GradientPainter ------------------------------------------------------------
98 class GradientPainter
: public Painter
{
100 GradientPainter(bool horizontal
,
104 virtual ~GradientPainter();
107 virtual gfx::Size
GetMinimumSize() const OVERRIDE
;
108 virtual void Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) OVERRIDE
;
111 // If |horizontal_| is true then the gradient is painted horizontally.
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_|.
120 DISALLOW_COPY_AND_ASSIGN(GradientPainter
);
123 GradientPainter::GradientPainter(bool horizontal
,
127 : horizontal_(horizontal
),
128 colors_(new SkColor
[count
]),
129 pos_(new SkScalar
[count
]),
131 for (size_t i
= 0; i
< count_
; ++i
) {
133 colors_
[i
] = colors
[i
];
137 GradientPainter::~GradientPainter() {
140 gfx::Size
GradientPainter::GetMinimumSize() const {
144 void GradientPainter::Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) {
149 p
[1].iset(size
.width(), 0);
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 VIEWS_EXPORT ImagePainter
: public Painter
{
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 virtual ~ImagePainter();
178 virtual gfx::Size
GetMinimumSize() const OVERRIDE
;
179 virtual void Paint(gfx::Canvas
* canvas
, const gfx::Size
& size
) OVERRIDE
;
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
));
210 // Painter --------------------------------------------------------------------
215 Painter::~Painter() {
219 void Painter::PaintPainterAt(gfx::Canvas
* canvas
,
221 const gfx::Rect
& rect
) {
222 DCHECK(canvas
&& painter
);
224 canvas
->Translate(rect
.OffsetFromOrigin());
225 painter
->Paint(canvas
, rect
.size());
230 void Painter::PaintFocusPainter(View
* view
,
232 Painter
* focus_painter
) {
233 if (focus_painter
&& view
->HasFocus())
234 PaintPainterAt(canvas
, focus_painter
, view
->GetLocalBounds());
238 Painter
* Painter::CreateHorizontalGradient(SkColor c1
, SkColor c2
) {
242 SkScalar pos
[] = {0, 1};
243 return new GradientPainter(true, colors
, pos
, 2);
247 Painter
* Painter::CreateVerticalGradient(SkColor c1
, SkColor c2
) {
251 SkScalar pos
[] = {0, 1};
252 return new GradientPainter(false, colors
, pos
, 2);
256 Painter
* Painter::CreateVerticalMultiColorGradient(SkColor
* colors
,
259 return new GradientPainter(false, colors
, pos
, count
);
263 Painter
* Painter::CreateImagePainter(const gfx::ImageSkia
& image
,
264 const gfx::Insets
& insets
) {
265 return new ImagePainter(image
, insets
);
269 Painter
* Painter::CreateImageGridPainter(const int image_ids
[]) {
270 return new ImagePainter(image_ids
);
274 scoped_ptr
<Painter
> Painter::CreateDashedFocusPainter() {
275 return scoped_ptr
<Painter
>(new DashedFocusPainter(gfx::Insets())).Pass();
279 scoped_ptr
<Painter
> Painter::CreateDashedFocusPainterWithInsets(
280 const gfx::Insets
& insets
) {
281 return scoped_ptr
<Painter
>(new DashedFocusPainter(insets
)).Pass();
285 scoped_ptr
<Painter
> Painter::CreateSolidFocusPainter(
287 const gfx::Insets
& insets
) {
288 return scoped_ptr
<Painter
>(new SolidFocusPainter(color
, insets
)).Pass();
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 {
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());