Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: gfx/canvas.cc

Issue 2862025: Canvas refactoring part 2.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gfx/canvas.h ('k') | gfx/canvas_2.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 "gfx/canvas.h"
6
7 #include <limits>
8
9 #include "base/i18n/rtl.h"
10 #include "base/logging.h"
11 #include "gfx/font.h"
12 #include "gfx/rect.h"
13 #include "third_party/skia/include/core/SkShader.h"
14
15 #if defined(OS_WIN)
16 #include "gfx/canvas_paint.h"
17 #endif
18
19 namespace gfx {
20
21 bool Canvas::GetClipRect(gfx::Rect* r) {
22 SkRect clip;
23 if (!getClipBounds(&clip)) {
24 if (r)
25 r->SetRect(0, 0, 0, 0);
26 return false;
27 }
28 r->SetRect(SkScalarRound(clip.fLeft), SkScalarRound(clip.fTop),
29 SkScalarRound(clip.fRight - clip.fLeft),
30 SkScalarRound(clip.fBottom - clip.fTop));
31 return true;
32 }
33
34 bool Canvas::ClipRectInt(int x, int y, int w, int h) {
35 SkRect new_clip;
36 new_clip.set(SkIntToScalar(x), SkIntToScalar(y),
37 SkIntToScalar(x + w), SkIntToScalar(y + h));
38 return clipRect(new_clip);
39 }
40
41 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) {
42 SkRect clip;
43 return getClipBounds(&clip) &&
44 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
45 SkIntToScalar(y + h));
46 }
47
48 void Canvas::TranslateInt(int x, int y) {
49 translate(SkIntToScalar(x), SkIntToScalar(y));
50 }
51
52 void Canvas::ScaleInt(int x, int y) {
53 scale(SkIntToScalar(x), SkIntToScalar(y));
54 }
55
56 void Canvas::FillRectInt(const SkColor& color, int x, int y, int w, int h) {
57 SkPaint paint;
58 paint.setColor(color);
59 paint.setStyle(SkPaint::kFill_Style);
60 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
61 FillRectInt(x, y, w, h, paint);
62 }
63
64 void Canvas::FillRectInt(int x, int y, int w, int h, const SkPaint& paint) {
65 SkIRect rc = {x, y, x + w, y + h};
66 drawIRect(rc, paint);
67 }
68
69 void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h) {
70 DrawRectInt(color, x, y, w, h, SkXfermode::kSrcOver_Mode);
71 }
72
73 void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h,
74 SkXfermode::Mode mode) {
75 SkPaint paint;
76 paint.setColor(color);
77 paint.setStyle(SkPaint::kStroke_Style);
78 // Set a stroke width of 0, which will put us down the stroke rect path. If
79 // we set a stroke width of 1, for example, this will internally create a
80 // path and fill it, which causes problems near the edge of the canvas.
81 paint.setStrokeWidth(SkIntToScalar(0));
82 paint.setXfermodeMode(mode);
83
84 SkIRect rc = {x, y, x + w, y + h};
85 drawIRect(rc, paint);
86 }
87
88 void Canvas::DrawLineInt(const SkColor& color, int x1, int y1, int x2, int y2) {
89 SkPaint paint;
90 paint.setColor(color);
91 paint.setStrokeWidth(SkIntToScalar(1));
92 drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2),
93 SkIntToScalar(y2), paint);
94 }
95
96 void Canvas::DrawFocusRect(int x, int y, int width, int height) {
97 // Create a 2D bitmap containing alternating on/off pixels - we do this
98 // so that you never get two pixels of the same color around the edges
99 // of the focus rect (this may mean that opposing edges of the rect may
100 // have a dot pattern out of phase to each other).
101 static SkBitmap* dots = NULL;
102 if (!dots) {
103 int col_pixels = 32;
104 int row_pixels = 32;
105
106 dots = new SkBitmap;
107 dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels);
108 dots->allocPixels();
109 dots->eraseARGB(0, 0, 0, 0);
110
111 uint32_t* dot = dots->getAddr32(0, 0);
112 for (int i = 0; i < row_pixels; i++) {
113 for (int u = 0; u < col_pixels; u++) {
114 if ((u % 2 + i % 2) % 2 != 0) {
115 dot[i * row_pixels + u] = SK_ColorGRAY;
116 }
117 }
118 }
119 }
120
121 // First the horizontal lines.
122
123 // Make a shader for the bitmap with an origin of the box we'll draw. This
124 // shader is refcounted and will have an initial refcount of 1.
125 SkShader* shader = SkShader::CreateBitmapShader(
126 *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
127 // Assign the shader to the paint & release our reference. The paint will
128 // now own the shader and the shader will be destroyed when the paint goes
129 // out of scope.
130 SkPaint paint;
131 paint.setShader(shader);
132 shader->unref();
133
134 SkRect rect;
135 rect.set(SkIntToScalar(x), SkIntToScalar(y),
136 SkIntToScalar(x + width), SkIntToScalar(y + 1));
137 drawRect(rect, paint);
138 rect.set(SkIntToScalar(x), SkIntToScalar(y + height - 1),
139 SkIntToScalar(x + width), SkIntToScalar(y + height));
140 drawRect(rect, paint);
141
142 rect.set(SkIntToScalar(x), SkIntToScalar(y),
143 SkIntToScalar(x + 1), SkIntToScalar(y + height));
144 drawRect(rect, paint);
145 rect.set(SkIntToScalar(x + width - 1), SkIntToScalar(y),
146 SkIntToScalar(x + width), SkIntToScalar(y + height));
147 drawRect(rect, paint);
148 }
149
150 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) {
151 drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y));
152 }
153
154 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y,
155 const SkPaint& paint) {
156 drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint);
157 }
158
159 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y,
160 int src_w, int src_h, int dest_x, int dest_y,
161 int dest_w, int dest_h,
162 bool filter) {
163 SkPaint p;
164 DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y,
165 dest_w, dest_h, filter, p);
166 }
167
168 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y,
169 int src_w, int src_h, int dest_x, int dest_y,
170 int dest_w, int dest_h,
171 bool filter, const SkPaint& paint) {
172 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
173 src_y + src_h < std::numeric_limits<int16_t>::max());
174 if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) {
175 NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!";
176 return;
177 }
178
179 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h))
180 return;
181
182 SkRect dest_rect = { SkIntToScalar(dest_x),
183 SkIntToScalar(dest_y),
184 SkIntToScalar(dest_x + dest_w),
185 SkIntToScalar(dest_y + dest_h) };
186
187 if (src_w == dest_w && src_h == dest_h) {
188 // Workaround for apparent bug in Skia that causes image to occasionally
189 // shift.
190 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
191 drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
192 return;
193 }
194
195 // Make a bitmap shader that contains the bitmap we want to draw. This is
196 // basically what SkCanvas.drawBitmap does internally, but it gives us
197 // more control over quality and will use the mipmap in the source image if
198 // it has one, whereas drawBitmap won't.
199 SkShader* shader = SkShader::CreateBitmapShader(bitmap,
200 SkShader::kRepeat_TileMode,
201 SkShader::kRepeat_TileMode);
202 SkMatrix shader_scale;
203 shader_scale.setScale(SkFloatToScalar(static_cast<float>(dest_w) / src_w),
204 SkFloatToScalar(static_cast<float>(dest_h) / src_h));
205 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
206 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
207 shader->setLocalMatrix(shader_scale);
208
209 // Set up our paint to use the shader & release our reference (now just owned
210 // by the paint).
211 SkPaint p(paint);
212 p.setFilterBitmap(filter);
213 p.setShader(shader);
214 shader->unref();
215
216 // The rect will be filled by the bitmap.
217 drawRect(dest_rect, p);
218 }
219
220 void Canvas::DrawStringInt(const std::wstring& text,
221 const gfx::Font& font,
222 const SkColor& color,
223 int x, int y, int w, int h) {
224 DrawStringInt(text, font, color, x, y, w, h,
225 gfx::Canvas::DefaultCanvasTextAlignment());
226 }
227
228 void Canvas::DrawStringInt(const std::wstring& text,
229 const gfx::Font& font,
230 const SkColor& color,
231 const gfx::Rect& display_rect) {
232 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(),
233 display_rect.width(), display_rect.height());
234 }
235
236 void Canvas::TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h) {
237 TileImageInt(bitmap, 0, 0, x, y, w, h);
238 }
239
240 void Canvas::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y,
241 int dest_x, int dest_y, int w, int h) {
242 if (!IntersectsClipRectInt(dest_x, dest_y, w, h))
243 return;
244
245 SkPaint paint;
246
247 SkShader* shader = SkShader::CreateBitmapShader(bitmap,
248 SkShader::kRepeat_TileMode,
249 SkShader::kRepeat_TileMode);
250 paint.setShader(shader);
251 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
252
253 // CreateBitmapShader returns a Shader with a reference count of one, we
254 // need to unref after paint takes ownership of the shader.
255 shader->unref();
256 save();
257 translate(SkIntToScalar(dest_x - src_x), SkIntToScalar(dest_y - src_y));
258 ClipRectInt(src_x, src_y, w, h);
259 drawPaint(paint);
260 restore();
261 }
262
263 SkBitmap Canvas::ExtractBitmap() const {
264 const SkBitmap& device_bitmap = getDevice()->accessBitmap(false);
265
266 // Make a bitmap to return, and a canvas to draw into it. We don't just want
267 // to call extractSubset or the copy constuctor, since we want an actual copy
268 // of the bitmap.
269 SkBitmap result;
270 device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config);
271 return result;
272 }
273
274 Canvas* Canvas::AsCanvas() {
275 return this;
276 }
277
278 // static
279 int Canvas::DefaultCanvasTextAlignment() {
280 if (!base::i18n::IsRTL())
281 return gfx::Canvas::TEXT_ALIGN_LEFT;
282 return gfx::Canvas::TEXT_ALIGN_RIGHT;
283 }
284
285 ////////////////////////////////////////////////////////////////////////////////
286 // Canvas2, public:
287
288 Canvas2* Canvas2::CreateCanvas() {
289 return new Canvas;
290 }
291
292 Canvas2* Canvas2::CreateCanvas(int width, int height, bool is_opaque) {
293 return new Canvas(width, height, is_opaque);
294 }
295
296 #if defined(OS_WIN)
297 // TODO(beng): move to canvas_win.cc, etc.
298 class CanvasPaintWin : public CanvasPaint, public CanvasPaint2 {
299 public:
300 CanvasPaintWin(gfx::NativeView view) : CanvasPaint(view) {}
301
302 // Overridden from CanvasPaint2:
303 virtual bool IsValid() const {
304 return isEmpty();
305 }
306
307 virtual gfx::Rect GetInvalidRect() const {
308 return gfx::Rect(paintStruct().rcPaint);
309 }
310
311 virtual Canvas2* AsCanvas2() {
312 return this;
313 }
314 };
315 #endif
316
317 CanvasPaint2* CanvasPaint2::CreateCanvasPaint(gfx::NativeView view) {
318 #if defined(OS_WIN)
319 return new CanvasPaintWin(view);
320 #else
321 return NULL;
322 #endif
323 }
324
325 } // namespace gfx
OLDNEW
« no previous file with comments | « gfx/canvas.h ('k') | gfx/canvas_2.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698