blob: 84ab395d343825eac93ab6262b0d3557b495016b [file] [log] [blame]
[email protected]fa8cfb02012-01-13 00:27:411// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]3127f6632012-03-17 00:14:065#include "ui/gfx/canvas.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]8ad3c5a2013-10-10 09:57:197#include <cmath>
[email protected]e1981f432008-08-12 15:22:138#include <limits>
9
[email protected]7cf1b6ce2010-03-20 06:37:0110#include "base/i18n/rtl.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/logging.h"
[email protected]757a8eb42011-12-21 20:25:2212#include "third_party/skia/include/core/SkBitmap.h"
pkasting954f76a2016-02-25 01:11:0013#include "third_party/skia/include/core/SkPath.h"
tomhudson399950b2016-05-11 11:00:1314#include "third_party/skia/include/core/SkRefCnt.h"
[email protected]0f4fe842010-07-23 22:23:5915#include "third_party/skia/include/effects/SkGradientShader.h"
[email protected]ad8d9d52013-08-22 07:20:0516#include "ui/gfx/font_list.h"
tfarina3b0452d2014-12-31 15:20:0917#include "ui/gfx/geometry/rect.h"
skye7da6042014-09-10 22:19:3718#include "ui/gfx/geometry/rect_conversions.h"
mgiuca9a713fe12015-11-10 02:53:3019#include "ui/gfx/geometry/rect_f.h"
sky005605e2014-10-02 20:35:1220#include "ui/gfx/geometry/safe_integer_conversions.h"
tfarinaebe974f02015-01-03 04:25:3221#include "ui/gfx/geometry/size_conversions.h"
sky005605e2014-10-02 20:35:1222#include "ui/gfx/scoped_canvas.h"
[email protected]79ea54a2011-10-26 01:47:3623#include "ui/gfx/skia_util.h"
[email protected]b9b1e7a42011-05-17 15:29:5124#include "ui/gfx/transform.h"
initial.commit09911bf2008-07-26 23:55:2925
[email protected]82522512009-05-15 07:37:2926namespace gfx {
27
[email protected]50b66262013-09-24 03:25:4828Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
tomhudson748157f72016-02-04 18:49:5629 : image_scale_(image_scale) {
danakjddaec912015-09-25 19:38:4030 Size pixel_size = ScaleToCeiledSize(size, image_scale);
tomhudson399950b2016-05-11 11:00:1331 canvas_ = sk_sp<SkCanvas>(skia::CreatePlatformCanvas(pixel_size.width(),
32 pixel_size.height(),
33 is_opaque));
moshayedi6a8df302015-10-21 20:02:5734#if !defined(USE_CAIRO)
35 // skia::PlatformCanvas instances are initialized to 0 by Cairo, but
36 // uninitialized on other platforms.
[email protected]3b2591a2012-06-27 17:58:4137 if (!is_opaque)
tomhudson748157f72016-02-04 18:49:5638 canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
[email protected]3b2591a2012-06-27 17:58:4139#endif
40
[email protected]50b66262013-09-24 03:25:4841 SkScalar scale_scalar = SkFloatToScalar(image_scale);
42 canvas_->scale(scale_scalar, scale_scalar);
[email protected]3b2591a2012-06-27 17:58:4143}
44
[email protected]3127f6632012-03-17 00:14:0645Canvas::Canvas()
danakj4bfbb342015-10-29 23:38:2546 : image_scale_(1.f),
tomhudson399950b2016-05-11 11:00:1347 canvas_(sk_sp<SkCanvas>(skia::CreatePlatformCanvas(0, 0, false))) {}
[email protected]be172ba82011-10-05 19:05:0748
tomhudson399950b2016-05-11 11:00:1349Canvas::Canvas(sk_sp<SkCanvas> canvas, float image_scale)
50 : image_scale_(image_scale), canvas_(std::move(canvas)) {
51 DCHECK(canvas_);
[email protected]de13f352012-07-24 16:51:1652}
53
danakj8fa739b62015-05-12 02:10:0654Canvas::~Canvas() {
[email protected]3b2591a2012-06-27 17:58:4155}
56
[email protected]ad8d9d52013-08-22 07:20:0557void Canvas::RecreateBackingCanvas(const Size& size,
[email protected]50b66262013-09-24 03:25:4858 float image_scale,
[email protected]3b2591a2012-06-27 17:58:4159 bool is_opaque) {
[email protected]50b66262013-09-24 03:25:4860 image_scale_ = image_scale;
danakjddaec912015-09-25 19:38:4061 Size pixel_size = ScaleToFlooredSize(size, image_scale);
tomhudson399950b2016-05-11 11:00:1362 canvas_ = sk_sp<SkCanvas>(skia::CreatePlatformCanvas(pixel_size.width(),
63 pixel_size.height(),
64 is_opaque));
[email protected]50b66262013-09-24 03:25:4865 SkScalar scale_scalar = SkFloatToScalar(image_scale);
66 canvas_->scale(scale_scalar, scale_scalar);
[email protected]be172ba82011-10-05 19:05:0767}
68
[email protected]f286f772010-07-21 18:28:2069// static
[email protected]ad8d9d52013-08-22 07:20:0570void Canvas::SizeStringInt(const base::string16& text,
[email protected]8ad3c5a2013-10-10 09:57:1971 const FontList& font_list,
72 int* width,
73 int* height,
74 int line_height,
75 int flags) {
pkastingbc91db52014-10-21 20:35:4276 float fractional_width = static_cast<float>(*width);
77 float factional_height = static_cast<float>(*height);
[email protected]8ad3c5a2013-10-10 09:57:1978 SizeStringFloat(text, font_list, &fractional_width,
79 &factional_height, line_height, flags);
pkastingbc91db52014-10-21 20:35:4280 *width = ToCeiledInt(fractional_width);
81 *height = ToCeiledInt(factional_height);
[email protected]8ad3c5a2013-10-10 09:57:1982}
83
84// static
[email protected]ad8d9d52013-08-22 07:20:0585int Canvas::GetStringWidth(const base::string16& text,
86 const FontList& font_list) {
[email protected]7c613752012-01-24 21:08:5187 int width = 0, height = 0;
[email protected]ad8d9d52013-08-22 07:20:0588 SizeStringInt(text, font_list, &width, &height, 0, NO_ELLIPSIS);
89 return width;
90}
91
92// static
[email protected]8ad3c5a2013-10-10 09:57:1993float Canvas::GetStringWidthF(const base::string16& text,
94 const FontList& font_list) {
95 float width = 0, height = 0;
96 SizeStringFloat(text, font_list, &width, &height, 0, NO_ELLIPSIS);
97 return width;
98}
99
100// static
[email protected]3127f6632012-03-17 00:14:06101int Canvas::DefaultCanvasTextAlignment() {
102 return base::i18n::IsRTL() ? TEXT_ALIGN_RIGHT : TEXT_ALIGN_LEFT;
[email protected]f286f772010-07-21 18:28:20103}
104
[email protected]ad8d9d52013-08-22 07:20:05105ImageSkiaRep Canvas::ExtractImageRep() const {
[email protected]74db48eb2010-06-25 16:33:23106 // Make a bitmap to return, and a canvas to draw into it. We don't just want
107 // to call extractSubset or the copy constructor, since we want an actual copy
108 // of the bitmap.
tomhudson15223e92015-11-23 21:52:54109 const SkISize size = canvas_->getBaseLayerSize();
[email protected]74db48eb2010-06-25 16:33:23110 SkBitmap result;
[email protected]8dca6e02014-03-04 04:21:39111 result.allocN32Pixels(size.width(), size.height());
[email protected]74db48eb2010-06-25 16:33:23112
[email protected]8dca6e02014-03-04 04:21:39113 canvas_->readPixels(&result, 0, 0);
[email protected]50b66262013-09-24 03:25:48114 return ImageSkiaRep(result, image_scale_);
[email protected]3b2591a2012-06-27 17:58:41115}
116
[email protected]ad8d9d52013-08-22 07:20:05117void Canvas::DrawDashedRect(const Rect& rect, SkColor color) {
[email protected]399be842014-07-15 01:05:15118 if (rect.IsEmpty())
119 return;
[email protected]edc844a2012-03-09 04:33:14120 // Create a 2D bitmap containing alternating on/off pixels - we do this
121 // so that you never get two pixels of the same color around the edges
122 // of the focus rect (this may mean that opposing edges of the rect may
123 // have a dot pattern out of phase to each other).
124 static SkColor last_color;
125 static SkBitmap* dots = NULL;
126 if (!dots || last_color != color) {
127 int col_pixels = 32;
128 int row_pixels = 32;
129
130 delete dots;
131 last_color = color;
132 dots = new SkBitmap;
[email protected]8dca6e02014-03-04 04:21:39133 dots->allocN32Pixels(col_pixels, row_pixels);
[email protected]edc844a2012-03-09 04:33:14134 dots->eraseARGB(0, 0, 0, 0);
135
136 uint32_t* dot = dots->getAddr32(0, 0);
137 for (int i = 0; i < row_pixels; i++) {
138 for (int u = 0; u < col_pixels; u++) {
139 if ((u % 2 + i % 2) % 2 != 0) {
140 dot[i * row_pixels + u] = color;
141 }
142 }
143 }
144 }
145
reed642d8f92016-03-11 12:59:03146 // Make a shader for the bitmap with an origin of the box we'll draw.
[email protected]edc844a2012-03-09 04:33:14147 SkPaint paint;
reed642d8f92016-03-11 12:59:03148 paint.setShader(SkShader::MakeBitmapShader(*dots, SkShader::kRepeat_TileMode,
149 SkShader::kRepeat_TileMode));
[email protected]edc844a2012-03-09 04:33:14150
[email protected]ad8d9d52013-08-22 07:20:05151 DrawRect(Rect(rect.x(), rect.y(), rect.width(), 1), paint);
152 DrawRect(Rect(rect.x(), rect.y() + rect.height() - 1, rect.width(), 1),
[email protected]edc844a2012-03-09 04:33:14153 paint);
[email protected]ad8d9d52013-08-22 07:20:05154 DrawRect(Rect(rect.x(), rect.y(), 1, rect.height()), paint);
155 DrawRect(Rect(rect.x() + rect.width() - 1, rect.y(), 1, rect.height()),
[email protected]edc844a2012-03-09 04:33:14156 paint);
157}
158
danakjda764372015-10-30 19:25:16159float Canvas::UndoDeviceScaleFactor() {
pkasting0ca0ebd42015-10-14 02:19:02160 SkScalar scale_factor = 1.0f / image_scale_;
161 canvas_->scale(scale_factor, scale_factor);
162 return image_scale_;
163}
164
danakjda764372015-10-30 19:25:16165void Canvas::Save() {
166 canvas_->save();
167}
168
avic89eb8d42015-12-23 08:08:18169void Canvas::SaveLayerAlpha(uint8_t alpha) {
[email protected]be172ba82011-10-05 19:05:07170 canvas_->saveLayerAlpha(NULL, alpha);
[email protected]bd026802010-06-29 22:08:44171}
172
avic89eb8d42015-12-23 08:08:18173void Canvas::SaveLayerAlpha(uint8_t alpha, const Rect& layer_bounds) {
[email protected]ad8d9d52013-08-22 07:20:05174 SkRect bounds(RectToSkRect(layer_bounds));
[email protected]be172ba82011-10-05 19:05:07175 canvas_->saveLayerAlpha(&bounds, alpha);
[email protected]bd026802010-06-29 22:08:44176}
177
[email protected]3127f6632012-03-17 00:14:06178void Canvas::Restore() {
[email protected]be172ba82011-10-05 19:05:07179 canvas_->restore();
[email protected]bd026802010-06-29 22:08:44180}
181
[email protected]a91031712014-03-03 15:41:16182void Canvas::ClipRect(const Rect& rect) {
183 canvas_->clipRect(RectToSkRect(rect));
initial.commit09911bf2008-07-26 23:55:29184}
185
[email protected]d26b905c2014-05-26 16:43:44186void Canvas::ClipPath(const SkPath& path, bool do_anti_alias) {
187 canvas_->clipPath(path, SkRegion::kIntersect_Op, do_anti_alias);
[email protected]a91031712014-03-03 15:41:16188}
189
190bool Canvas::IsClipEmpty() const {
191 return canvas_->isClipEmpty();
[email protected]ffdd1fd2012-04-09 23:24:41192}
193
[email protected]ad8d9d52013-08-22 07:20:05194bool Canvas::GetClipBounds(Rect* bounds) {
[email protected]ffdd1fd2012-04-09 23:24:41195 SkRect out;
skye7da6042014-09-10 22:19:37196 if (canvas_->getClipBounds(&out)) {
197 *bounds = ToEnclosingRect(SkRectToRectF(out));
198 return true;
199 }
200 *bounds = gfx::Rect();
201 return false;
[email protected]ffdd1fd2012-04-09 23:24:41202}
203
[email protected]ad8d9d52013-08-22 07:20:05204void Canvas::Translate(const Vector2d& offset) {
[email protected]ceb36f7d2012-10-31 18:33:24205 canvas_->translate(SkIntToScalar(offset.x()), SkIntToScalar(offset.y()));
initial.commit09911bf2008-07-26 23:55:29206}
207
[email protected]3127f6632012-03-17 00:14:06208void Canvas::Scale(int x_scale, int y_scale) {
[email protected]80277112011-10-27 12:29:21209 canvas_->scale(SkIntToScalar(x_scale), SkIntToScalar(y_scale));
initial.commit09911bf2008-07-26 23:55:29210}
211
[email protected]ffdd1fd2012-04-09 23:24:41212void Canvas::DrawColor(SkColor color) {
213 DrawColor(color, SkXfermode::kSrcOver_Mode);
214}
215
216void Canvas::DrawColor(SkColor color, SkXfermode::Mode mode) {
217 canvas_->drawColor(color, mode);
218}
219
[email protected]ad8d9d52013-08-22 07:20:05220void Canvas::FillRect(const Rect& rect, SkColor color) {
[email protected]b8bdc422012-02-01 21:44:40221 FillRect(rect, color, SkXfermode::kSrcOver_Mode);
[email protected]602627cc2010-11-24 19:14:57222}
223
[email protected]ad8d9d52013-08-22 07:20:05224void Canvas::FillRect(const Rect& rect,
[email protected]1b81ff22012-03-24 22:04:42225 SkColor color,
[email protected]3127f6632012-03-17 00:14:06226 SkXfermode::Mode mode) {
initial.commit09911bf2008-07-26 23:55:29227 SkPaint paint;
228 paint.setColor(color);
229 paint.setStyle(SkPaint::kFill_Style);
[email protected]602627cc2010-11-24 19:14:57230 paint.setXfermodeMode(mode);
[email protected]3acc6422011-12-17 16:31:31231 DrawRect(rect, paint);
initial.commit09911bf2008-07-26 23:55:29232}
233
[email protected]ad8d9d52013-08-22 07:20:05234void Canvas::DrawRect(const Rect& rect, SkColor color) {
[email protected]3acc6422011-12-17 16:31:31235 DrawRect(rect, color, SkXfermode::kSrcOver_Mode);
initial.commit09911bf2008-07-26 23:55:29236}
237
[email protected]ad8d9d52013-08-22 07:20:05238void Canvas::DrawRect(const Rect& rect,
[email protected]1b81ff22012-03-24 22:04:42239 SkColor color,
[email protected]3127f6632012-03-17 00:14:06240 SkXfermode::Mode mode) {
initial.commit09911bf2008-07-26 23:55:29241 SkPaint paint;
242 paint.setColor(color);
243 paint.setStyle(SkPaint::kStroke_Style);
[email protected]a64691f22009-04-07 16:15:56244 // Set a stroke width of 0, which will put us down the stroke rect path. If
245 // we set a stroke width of 1, for example, this will internally create a
246 // path and fill it, which causes problems near the edge of the canvas.
247 paint.setStrokeWidth(SkIntToScalar(0));
[email protected]8860e4f52009-06-25 01:01:52248 paint.setXfermodeMode(mode);
initial.commit09911bf2008-07-26 23:55:29249
[email protected]3acc6422011-12-17 16:31:31250 DrawRect(rect, paint);
[email protected]55a0ffd82010-08-18 20:20:05251}
252
[email protected]ad8d9d52013-08-22 07:20:05253void Canvas::DrawRect(const Rect& rect, const SkPaint& paint) {
[email protected]3acc6422011-12-17 16:31:31254 canvas_->drawIRect(RectToSkIRect(rect), paint);
initial.commit09911bf2008-07-26 23:55:29255}
256
[email protected]ad8d9d52013-08-22 07:20:05257void Canvas::DrawPoint(const Point& p1, const SkPaint& paint) {
[email protected]ffdd1fd2012-04-09 23:24:41258 canvas_->drawPoint(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), paint);
259}
260
[email protected]ad8d9d52013-08-22 07:20:05261void Canvas::DrawLine(const Point& p1, const Point& p2, SkColor color) {
estade397c9b92016-05-26 15:28:58262 DrawLine(PointF(p1), PointF(p2), color);
263}
264
265void Canvas::DrawLine(const PointF& p1, const PointF& p2, SkColor color) {
[email protected]74eb4cee2009-04-15 14:41:48266 SkPaint paint;
267 paint.setColor(color);
268 paint.setStrokeWidth(SkIntToScalar(1));
[email protected]ffdd1fd2012-04-09 23:24:41269 DrawLine(p1, p2, paint);
270}
271
[email protected]ad8d9d52013-08-22 07:20:05272void Canvas::DrawLine(const Point& p1, const Point& p2, const SkPaint& paint) {
estade397c9b92016-05-26 15:28:58273 DrawLine(PointF(p1), PointF(p2), paint);
274}
275
276void Canvas::DrawLine(const PointF& p1,
277 const PointF& p2,
278 const SkPaint& paint) {
279 canvas_->drawLine(SkFloatToScalar(p1.x()), SkFloatToScalar(p1.y()),
280 SkFloatToScalar(p2.x()), SkFloatToScalar(p2.y()), paint);
[email protected]74eb4cee2009-04-15 14:41:48281}
282
[email protected]ad8d9d52013-08-22 07:20:05283void Canvas::DrawCircle(const Point& center_point,
[email protected]ffdd1fd2012-04-09 23:24:41284 int radius,
285 const SkPaint& paint) {
286 canvas_->drawCircle(SkIntToScalar(center_point.x()),
287 SkIntToScalar(center_point.y()), SkIntToScalar(radius), paint);
288}
289
estade104196ec2016-06-02 01:37:53290void Canvas::DrawCircle(const PointF& center_point,
291 float radius,
292 const SkPaint& paint) {
293 canvas_->drawCircle(SkFloatToScalar(center_point.x()),
294 SkFloatToScalar(center_point.y()), radius, paint);
295}
296
[email protected]ad8d9d52013-08-22 07:20:05297void Canvas::DrawRoundRect(const Rect& rect,
[email protected]ffdd1fd2012-04-09 23:24:41298 int radius,
299 const SkPaint& paint) {
300 canvas_->drawRoundRect(RectToSkRect(rect), SkIntToScalar(radius),
301 SkIntToScalar(radius), paint);
302}
303
mgiuca9a713fe12015-11-10 02:53:30304void Canvas::DrawRoundRect(const RectF& rect,
305 float radius,
306 const SkPaint& paint) {
307 canvas_->drawRoundRect(RectFToSkRect(rect), SkFloatToScalar(radius),
308 SkFloatToScalar(radius), paint);
309}
310
[email protected]ffdd1fd2012-04-09 23:24:41311void Canvas::DrawPath(const SkPath& path, const SkPaint& paint) {
312 canvas_->drawPath(path, paint);
313}
314
[email protected]ad8d9d52013-08-22 07:20:05315void Canvas::DrawFocusRect(const Rect& rect) {
[email protected]edc844a2012-03-09 04:33:14316 DrawDashedRect(rect, SK_ColorGRAY);
initial.commit09911bf2008-07-26 23:55:29317}
318
[email protected]5db93a12013-12-02 21:07:31319void Canvas::DrawSolidFocusRect(const Rect& rect, SkColor color) {
320 SkPaint paint;
321 paint.setColor(color);
322 paint.setStrokeWidth(SkIntToScalar(1));
323 // Note: We cannot use DrawRect since it would create a path and fill it which
324 // would cause problems near the edge of the canvas.
325 int x1 = std::min(rect.x(), rect.right());
326 int x2 = std::max(rect.x(), rect.right());
327 int y1 = std::min(rect.y(), rect.bottom());
328 int y2 = std::max(rect.y(), rect.bottom());
329 DrawLine(Point(x1, y1), Point(x2, y1), paint);
330 DrawLine(Point(x1, y2), Point(x2, y2), paint);
331 DrawLine(Point(x1, y1), Point(x1, y2), paint);
332 DrawLine(Point(x2, y1), Point(x2, y2 + 1), paint);
333}
334
[email protected]ad8d9d52013-08-22 07:20:05335void Canvas::DrawImageInt(const ImageSkia& image, int x, int y) {
[email protected]35d53342012-05-16 21:30:12336 SkPaint paint;
[email protected]243cac7d2012-06-07 13:29:20337 DrawImageInt(image, x, y, paint);
initial.commit09911bf2008-07-26 23:55:29338}
339
avic89eb8d42015-12-23 08:08:18340void Canvas::DrawImageInt(const ImageSkia& image, int x, int y, uint8_t a) {
[email protected]2885cb32012-10-03 19:41:11341 SkPaint paint;
342 paint.setAlpha(a);
343 DrawImageInt(image, x, y, paint);
344}
345
[email protected]ad8d9d52013-08-22 07:20:05346void Canvas::DrawImageInt(const ImageSkia& image,
347 int x,
348 int y,
[email protected]243cac7d2012-06-07 13:29:20349 const SkPaint& paint) {
[email protected]1358f272014-05-10 02:48:00350 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
[email protected]8232da6b2012-07-02 19:41:15351 if (image_rep.is_null())
[email protected]35d53342012-05-16 21:30:12352 return;
[email protected]8232da6b2012-07-02 19:41:15353 const SkBitmap& bitmap = image_rep.sk_bitmap();
[email protected]50b66262013-09-24 03:25:48354 float bitmap_scale = image_rep.scale();
[email protected]35d53342012-05-16 21:30:12355
sky005605e2014-10-02 20:35:12356 ScopedCanvas scoper(this);
[email protected]35d53342012-05-16 21:30:12357 canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
358 SkFloatToScalar(1.0f / bitmap_scale));
359 canvas_->drawBitmap(bitmap,
360 SkFloatToScalar(x * bitmap_scale),
[email protected]bfc6a9b2012-05-23 18:11:05361 SkFloatToScalar(y * bitmap_scale),
362 &paint);
initial.commit09911bf2008-07-26 23:55:29363}
364
[email protected]ad8d9d52013-08-22 07:20:05365void Canvas::DrawImageInt(const ImageSkia& image,
366 int src_x,
367 int src_y,
368 int src_w,
369 int src_h,
370 int dest_x,
371 int dest_y,
372 int dest_w,
373 int dest_h,
[email protected]243cac7d2012-06-07 13:29:20374 bool filter) {
initial.commit09911bf2008-07-26 23:55:29375 SkPaint p;
[email protected]243cac7d2012-06-07 13:29:20376 DrawImageInt(image, src_x, src_y, src_w, src_h, dest_x, dest_y,
377 dest_w, dest_h, filter, p);
initial.commit09911bf2008-07-26 23:55:29378}
379
[email protected]ad8d9d52013-08-22 07:20:05380void Canvas::DrawImageInt(const ImageSkia& image,
381 int src_x,
382 int src_y,
383 int src_w,
384 int src_h,
385 int dest_x,
386 int dest_y,
387 int dest_w,
388 int dest_h,
[email protected]243cac7d2012-06-07 13:29:20389 bool filter,
390 const SkPaint& paint) {
danakj4bfbb342015-10-29 23:38:25391 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
392 if (image_rep.is_null())
393 return;
danakjf01075882016-01-06 19:39:32394 bool remove_image_scale = true;
danakj4bfbb342015-10-29 23:38:25395 DrawImageIntHelper(image_rep, src_x, src_y, src_w, src_h, dest_x, dest_y,
danakjf01075882016-01-06 19:39:32396 dest_w, dest_h, filter, paint, remove_image_scale);
[email protected]54bc2462014-05-06 05:10:58397}
initial.commit09911bf2008-07-26 23:55:29398
danakj4bfbb342015-10-29 23:38:25399void Canvas::DrawImageIntInPixel(const ImageSkiaRep& image_rep,
[email protected]54bc2462014-05-06 05:10:58400 int dest_x,
401 int dest_y,
402 int dest_w,
403 int dest_h,
404 bool filter,
405 const SkPaint& paint) {
danakj4bfbb342015-10-29 23:38:25406 int src_x = 0;
407 int src_y = 0;
408 int src_w = image_rep.pixel_width();
409 int src_h = image_rep.pixel_height();
danakjf01075882016-01-06 19:39:32410 // Don't remove image scale here, this function is used to draw the
411 // (already scaled) |image_rep| at a 1:1 scale with the canvas.
412 bool remove_image_scale = false;
danakj4bfbb342015-10-29 23:38:25413 DrawImageIntHelper(image_rep, src_x, src_y, src_w, src_h, dest_x, dest_y,
danakjf01075882016-01-06 19:39:32414 dest_w, dest_h, filter, paint, remove_image_scale);
initial.commit09911bf2008-07-26 23:55:29415}
416
[email protected]ad8d9d52013-08-22 07:20:05417void Canvas::DrawImageInPath(const ImageSkia& image,
[email protected]8232da6b2012-07-02 19:41:15418 int x,
419 int y,
420 const SkPath& path,
421 const SkPaint& paint) {
[email protected]1358f272014-05-10 02:48:00422 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
[email protected]8232da6b2012-07-02 19:41:15423 if (image_rep.is_null())
424 return;
425
426 SkMatrix matrix;
427 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
[email protected]8232da6b2012-07-02 19:41:15428 SkPaint p(paint);
tomhudson2b45cf92016-03-31 14:10:15429 p.setShader(CreateImageRepShader(image_rep,
430 SkShader::kRepeat_TileMode,
431 matrix));
[email protected]8232da6b2012-07-02 19:41:15432 canvas_->drawPath(path, p);
433}
434
[email protected]ad8d9d52013-08-22 07:20:05435void Canvas::DrawStringRect(const base::string16& text,
436 const FontList& font_list,
437 SkColor color,
438 const Rect& display_rect) {
439 DrawStringRectWithFlags(text, font_list, color, display_rect,
440 DefaultCanvasTextAlignment());
441}
442
443void Canvas::DrawStringRectWithFlags(const base::string16& text,
444 const FontList& font_list,
445 SkColor color,
446 const Rect& display_rect,
447 int flags) {
448 DrawStringRectWithShadows(text, font_list, color, display_rect, 0, flags,
449 ShadowValues());
450}
451
[email protected]ad8d9d52013-08-22 07:20:05452void Canvas::TileImageInt(const ImageSkia& image,
453 int x,
454 int y,
455 int w,
456 int h) {
[email protected]35d53342012-05-16 21:30:12457 TileImageInt(image, 0, 0, x, y, w, h);
[email protected]b42a7752009-02-04 01:02:00458}
459
[email protected]ad8d9d52013-08-22 07:20:05460void Canvas::TileImageInt(const ImageSkia& image,
461 int src_x,
462 int src_y,
463 int dest_x,
464 int dest_y,
465 int w,
466 int h) {
[email protected]2a3115e2012-05-25 23:27:04467 TileImageInt(image, src_x, src_y, 1.0f, 1.0f, dest_x, dest_y, w, h);
468}
469
[email protected]ad8d9d52013-08-22 07:20:05470void Canvas::TileImageInt(const ImageSkia& image,
471 int src_x,
472 int src_y,
473 float tile_scale_x,
474 float tile_scale_y,
475 int dest_x,
476 int dest_y,
477 int w,
478 int h) {
pkasting954f76a2016-02-25 01:11:00479 SkRect dest_rect = { SkIntToScalar(dest_x),
480 SkIntToScalar(dest_y),
481 SkIntToScalar(dest_x + w),
482 SkIntToScalar(dest_y + h) };
483 if (!IntersectsClipRect(dest_rect))
initial.commit09911bf2008-07-26 23:55:29484 return;
485
pkasting954f76a2016-02-25 01:11:00486 SkPaint paint;
487 if (InitSkPaintForTiling(image, src_x, src_y, tile_scale_x, tile_scale_y,
488 dest_x, dest_y, &paint))
489 canvas_->drawRect(dest_rect, paint);
490}
491
492bool Canvas::InitSkPaintForTiling(const ImageSkia& image,
493 int src_x,
494 int src_y,
495 float tile_scale_x,
496 float tile_scale_y,
497 int dest_x,
498 int dest_y,
499 SkPaint* paint) {
[email protected]1358f272014-05-10 02:48:00500 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
[email protected]8232da6b2012-07-02 19:41:15501 if (image_rep.is_null())
pkasting954f76a2016-02-25 01:11:00502 return false;
[email protected]35d53342012-05-16 21:30:12503
[email protected]2a3115e2012-05-25 23:27:04504 SkMatrix shader_scale;
505 shader_scale.setScale(SkFloatToScalar(tile_scale_x),
506 SkFloatToScalar(tile_scale_y));
[email protected]8232da6b2012-07-02 19:41:15507 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
508 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
[email protected]2a3115e2012-05-25 23:27:04509
pkasting954f76a2016-02-25 01:11:00510 paint->setShader(CreateImageRepShader(image_rep, SkShader::kRepeat_TileMode,
tomhudsona7bbd0df2016-03-31 22:57:58511 shader_scale));
pkasting954f76a2016-02-25 01:11:00512 paint->setXfermodeMode(SkXfermode::kSrcOver_Mode);
513 return true;
initial.commit09911bf2008-07-26 23:55:29514}
515
[email protected]0f0453e2012-10-14 18:15:35516void Canvas::Transform(const gfx::Transform& transform) {
[email protected]be172ba82011-10-05 19:05:07517 canvas_->concat(transform.matrix());
[email protected]36df22b2011-02-24 21:47:56518}
519
pkasting954f76a2016-02-25 01:11:00520bool Canvas::IntersectsClipRect(const SkRect& rect) {
[email protected]f286f772010-07-21 18:28:20521 SkRect clip;
pkasting954f76a2016-02-25 01:11:00522 return canvas_->getClipBounds(&clip) && clip.intersects(rect);
[email protected]0834e1b12012-04-11 02:23:56523}
524
danakj4bfbb342015-10-29 23:38:25525void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep,
[email protected]54bc2462014-05-06 05:10:58526 int src_x,
527 int src_y,
528 int src_w,
529 int src_h,
530 int dest_x,
531 int dest_y,
532 int dest_w,
533 int dest_h,
534 bool filter,
535 const SkPaint& paint,
danakjf01075882016-01-06 19:39:32536 bool remove_image_scale) {
[email protected]54bc2462014-05-06 05:10:58537 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
538 src_y + src_h < std::numeric_limits<int16_t>::max());
539 if (src_w <= 0 || src_h <= 0) {
540 NOTREACHED() << "Attempting to draw bitmap from an empty rect!";
541 return;
542 }
543
[email protected]54bc2462014-05-06 05:10:58544 SkRect dest_rect = { SkIntToScalar(dest_x),
545 SkIntToScalar(dest_y),
546 SkIntToScalar(dest_x + dest_w),
547 SkIntToScalar(dest_y + dest_h) };
pkasting954f76a2016-02-25 01:11:00548 if (!IntersectsClipRect(dest_rect))
549 return;
550
551 float user_scale_x = static_cast<float>(dest_w) / src_w;
552 float user_scale_y = static_cast<float>(dest_h) / src_h;
[email protected]54bc2462014-05-06 05:10:58553
[email protected]54bc2462014-05-06 05:10:58554 // Make a bitmap shader that contains the bitmap we want to draw. This is
555 // basically what SkCanvas.drawBitmap does internally, but it gives us
556 // more control over quality and will use the mipmap in the source image if
557 // it has one, whereas drawBitmap won't.
558 SkMatrix shader_scale;
559 shader_scale.setScale(SkFloatToScalar(user_scale_x),
560 SkFloatToScalar(user_scale_y));
561 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
562 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
563
[email protected]54bc2462014-05-06 05:10:58564 SkPaint p(paint);
reed55801f242015-03-17 13:16:24565 p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality);
tomhudson2b45cf92016-03-31 14:10:15566 p.setShader(CreateImageRepShaderForScale(
567 image_rep, SkShader::kRepeat_TileMode, shader_scale,
568 remove_image_scale ? image_rep.scale() : 1.f));
[email protected]54bc2462014-05-06 05:10:58569
570 // The rect will be filled by the bitmap.
571 canvas_->drawRect(dest_rect, p);
572}
573
[email protected]82522512009-05-15 07:37:29574} // namespace gfx