[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / ui / views / painter.cc
blobc46854b3727e368902ec4b6d7d8b396204d480d0
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/point.h"
17 #include "ui/gfx/rect.h"
19 namespace views {
21 namespace {
23 class GradientPainter : public Painter {
24 public:
25 GradientPainter(bool horizontal,
26 SkColor* colors,
27 SkScalar* pos,
28 size_t count)
29 : horizontal_(horizontal),
30 count_(count) {
31 pos_.reset(new SkScalar[count_]);
32 colors_.reset(new SkColor[count_]);
34 for (size_t i = 0; i < count_; ++i) {
35 pos_[i] = pos[i];
36 colors_[i] = colors[i];
40 virtual ~GradientPainter() {}
42 // Overridden from Painter:
43 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE {
44 SkPaint paint;
45 SkPoint p[2];
46 p[0].iset(0, 0);
47 if (horizontal_)
48 p[1].iset(size.width(), 0);
49 else
50 p[1].iset(0, size.height());
52 skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
53 p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode, NULL));
54 paint.setStyle(SkPaint::kFill_Style);
55 paint.setShader(s.get());
56 // Need to unref shader, otherwise never deleted.
58 canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
59 SkIntToScalar(size.width()),
60 SkIntToScalar(size.height()), paint);
63 private:
64 // If |horizontal_| is true then the gradiant is painted horizontally.
65 bool horizontal_;
66 // The gradient colors.
67 scoped_array<SkColor> colors_;
68 // The relative positions of the corresponding gradient colors.
69 scoped_array<SkScalar> pos_;
70 // The number of elements in |colors_| and |pos_|.
71 size_t count_;
73 DISALLOW_COPY_AND_ASSIGN(GradientPainter);
76 // ImagePainter stores and paints nine images as a scalable grid.
77 class VIEWS_EXPORT ImagePainter : public Painter {
78 public:
79 // Construct an ImagePainter with the specified image resource ids.
80 // See CreateImageGridPainter()'s comment regarding image ID count and order.
81 explicit ImagePainter(const int image_ids[]);
82 // Construct an ImagePainter with the specified image and insets.
83 ImagePainter(const gfx::ImageSkia& image, const gfx::Insets& insets);
85 virtual ~ImagePainter();
87 // Returns true if the images are empty.
88 bool IsEmpty() const;
90 // Overridden from Painter:
91 virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
93 private:
94 // Images must share widths by column and heights by row as depicted below.
95 // Coordinates along the X and Y axes are used for construction and painting.
96 // x0 x1 x2 x3
97 // y0__|____|____|____|
98 // y1__|_i0_|_i1_|_i2_|
99 // y2__|_i3_|_i4_|_i5_|
100 // y3__|_i6_|_i7_|_i8_|
101 gfx::ImageSkia images_[9];
103 DISALLOW_COPY_AND_ASSIGN(ImagePainter);
106 ImagePainter::ImagePainter(const int image_ids[]) {
107 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
108 for (size_t i = 0; i < 9; ++i)
109 images_[i] = *rb.GetImageSkiaNamed(image_ids[i]);
112 ImagePainter::ImagePainter(const gfx::ImageSkia& image,
113 const gfx::Insets& insets) {
114 DCHECK_GE(image.width(), insets.width());
115 DCHECK_GE(image.height(), insets.height());
117 // Extract subsets of the original image to match the |images_| format.
118 const int x[] =
119 { 0, insets.left(), image.width() - insets.right(), image.width() };
120 const int y[] =
121 { 0, insets.top(), image.height() - insets.bottom(), image.height() };
123 for (size_t j = 0; j < 3; ++j) {
124 for (size_t i = 0; i < 3; ++i) {
125 images_[i + j * 3] = gfx::ImageSkiaOperations::ExtractSubset(image,
126 gfx::Rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]));
131 ImagePainter::~ImagePainter() {
134 bool ImagePainter::IsEmpty() const {
135 return images_[0].isNull();
138 void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
139 if (IsEmpty())
140 return;
142 // Paint image subsets in accordance with the |images_| format.
143 const gfx::Rect rect(size);
144 const int x[] = { rect.x(), rect.x() + images_[0].width(),
145 rect.right() - images_[2].width(), rect.right() };
146 const int y[] = { rect.y(), rect.y() + images_[0].height(),
147 rect.bottom() - images_[6].height(), rect.bottom() };
149 canvas->DrawImageInt(images_[0], x[0], y[0]);
150 canvas->TileImageInt(images_[1], x[1], y[0], x[2] - x[1], y[1] - y[0]);
151 canvas->DrawImageInt(images_[2], x[2], y[0]);
152 canvas->TileImageInt(images_[3], x[0], y[1], x[1] - x[0], y[2] - y[1]);
153 canvas->DrawImageInt(
154 images_[4], 0, 0, images_[4].width(), images_[4].height(),
155 x[1], y[1], x[2] - x[1], y[2] - y[1], false);
156 canvas->TileImageInt(images_[5], x[2], y[1], x[3] - x[2], y[2] - y[1]);
157 canvas->DrawImageInt(images_[6], 0, y[2]);
158 canvas->TileImageInt(images_[7], x[1], y[2], x[2] - x[1], y[3] - y[2]);
159 canvas->DrawImageInt(images_[8], x[2], y[2]);
162 } // namespace
164 // static
165 void Painter::PaintPainterAt(gfx::Canvas* canvas,
166 Painter* painter,
167 const gfx::Rect& rect) {
168 DCHECK(canvas && painter);
169 canvas->Save();
170 canvas->Translate(rect.OffsetFromOrigin());
171 painter->Paint(canvas, rect.size());
172 canvas->Restore();
175 // static
176 Painter* Painter::CreateHorizontalGradient(SkColor c1, SkColor c2) {
177 SkColor colors[2];
178 colors[0] = c1;
179 colors[1] = c2;
180 SkScalar pos[] = {0, 1};
181 return new GradientPainter(true, colors, pos, 2);
184 // static
185 Painter* Painter::CreateVerticalGradient(SkColor c1, SkColor c2) {
186 SkColor colors[2];
187 colors[0] = c1;
188 colors[1] = c2;
189 SkScalar pos[] = {0, 1};
190 return new GradientPainter(false, colors, pos, 2);
193 // static
194 Painter* Painter::CreateVerticalMultiColorGradient(SkColor* colors,
195 SkScalar* pos,
196 size_t count) {
197 return new GradientPainter(false, colors, pos, count);
200 // static
201 Painter* Painter::CreateImagePainter(const gfx::ImageSkia& image,
202 const gfx::Insets& insets) {
203 return new ImagePainter(image, insets);
206 // static
207 Painter* Painter::CreateImageGridPainter(const int image_ids[]) {
208 return new ImagePainter(image_ids);
211 HorizontalPainter::HorizontalPainter(const int image_resource_names[]) {
212 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
213 for (int i = 0; i < 3; ++i)
214 images_[i] = rb.GetImageNamed(image_resource_names[i]).ToImageSkia();
215 height_ = images_[LEFT]->height();
216 DCHECK(images_[LEFT]->height() == images_[RIGHT]->height() &&
217 images_[LEFT]->height() == images_[CENTER]->height());
220 void HorizontalPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
221 if (size.width() < (images_[LEFT]->width() + images_[CENTER]->width() +
222 images_[RIGHT]->width())) {
223 // No room to paint.
224 return;
226 canvas->DrawImageInt(*images_[LEFT], 0, 0);
227 canvas->DrawImageInt(*images_[RIGHT],
228 size.width() - images_[RIGHT]->width(), 0);
229 canvas->TileImageInt(*images_[CENTER], images_[LEFT]->width(), 0,
230 size.width() - images_[LEFT]->width() - images_[RIGHT]->width(), height_);
233 } // namespace views