OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/canvas.h" | 5 #include "ui/gfx/canvas.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 } | 247 } |
248 | 248 |
249 void Canvas::DrawPath(const SkPath& path, const SkPaint& paint) { | 249 void Canvas::DrawPath(const SkPath& path, const SkPaint& paint) { |
250 canvas_->drawPath(path, paint); | 250 canvas_->drawPath(path, paint); |
251 } | 251 } |
252 | 252 |
253 void Canvas::DrawFocusRect(const gfx::Rect& rect) { | 253 void Canvas::DrawFocusRect(const gfx::Rect& rect) { |
254 DrawDashedRect(rect, SK_ColorGRAY); | 254 DrawDashedRect(rect, SK_ColorGRAY); |
255 } | 255 } |
256 | 256 |
257 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { | 257 void Canvas::DrawBitmapInt(const gfx::ImageSkia& image, int x, int y) { |
258 canvas_->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y)); | 258 SkPaint paint; |
| 259 DrawBitmapInt(image, x, y, paint); |
259 } | 260 } |
260 | 261 |
261 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, | 262 void Canvas::DrawBitmapInt(const gfx::ImageSkia& image, |
262 int x, int y, | 263 int x, int y, |
263 const SkPaint& paint) { | 264 const SkPaint& paint) { |
264 canvas_->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint); | 265 const SkBitmap* bitmap = GetBitmapToPaint(image); |
| 266 if (bitmap == NULL) |
| 267 return; |
| 268 |
| 269 float bitmap_scale_x = static_cast<float>(bitmap->width()) / image.width(); |
| 270 float bitmap_scale_y = static_cast<float>(bitmap->height()) / image.height(); |
| 271 |
| 272 canvas_->save(); |
| 273 canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale_x), |
| 274 SkFloatToScalar(1.0f / bitmap_scale_y)); |
| 275 canvas_->drawBitmap(*bitmap, |
| 276 SkFloatToScalar(x * bitmap_scale_x), |
| 277 SkFloatToScalar(y * bitmap_scale_y)); |
| 278 canvas_->restore(); |
265 } | 279 } |
266 | 280 |
267 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, | 281 void Canvas::DrawBitmapInt(const gfx::ImageSkia& image, |
268 int src_x, int src_y, int src_w, int src_h, | 282 int src_x, int src_y, int src_w, int src_h, |
269 int dest_x, int dest_y, int dest_w, int dest_h, | 283 int dest_x, int dest_y, int dest_w, int dest_h, |
270 bool filter) { | 284 bool filter) { |
271 SkPaint p; | 285 SkPaint p; |
272 DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y, | 286 DrawBitmapInt(image, src_x, src_y, src_w, src_h, dest_x, dest_y, |
273 dest_w, dest_h, filter, p); | 287 dest_w, dest_h, filter, p); |
274 } | 288 } |
275 | 289 |
276 void Canvas::DrawBitmapInt(const SkBitmap& bitmap, | 290 void Canvas::DrawBitmapInt(const gfx::ImageSkia& image, |
277 int src_x, int src_y, int src_w, int src_h, | 291 int src_x, int src_y, int src_w, int src_h, |
278 int dest_x, int dest_y, int dest_w, int dest_h, | 292 int dest_x, int dest_y, int dest_w, int dest_h, |
279 bool filter, | 293 bool filter, |
280 const SkPaint& paint) { | 294 const SkPaint& paint) { |
281 DrawBitmapFloat(bitmap, static_cast<float>(src_x), static_cast<float>(src_y), | |
282 static_cast<float>(src_w), static_cast<float>(src_h), | |
283 static_cast<float>(dest_x), static_cast<float>(dest_y), | |
284 static_cast<float>(dest_w), static_cast<float>(dest_h), | |
285 filter, paint); | |
286 } | |
287 | |
288 void Canvas::DrawBitmapFloat(const SkBitmap& bitmap, | |
289 float src_x, float src_y, float src_w, float src_h, | |
290 float dest_x, float dest_y, float dest_w, float dest_h, | |
291 bool filter, | |
292 const SkPaint& paint) { | |
293 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && | 295 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && |
294 src_y + src_h < std::numeric_limits<int16_t>::max()); | 296 src_y + src_h < std::numeric_limits<int16_t>::max()); |
295 if (src_w <= 0 || src_h <= 0) { | 297 if (src_w <= 0 || src_h <= 0) { |
296 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; | 298 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; |
297 return; | 299 return; |
298 } | 300 } |
299 | 301 |
300 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) | 302 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) |
301 return; | 303 return; |
302 | 304 |
303 SkRect dest_rect = { SkFloatToScalar(dest_x), | 305 const SkBitmap* bitmap = GetBitmapToPaint(image); |
304 SkFloatToScalar(dest_y), | 306 if (bitmap == NULL) { |
305 SkFloatToScalar(dest_x + dest_w), | 307 return; |
306 SkFloatToScalar(dest_y + dest_h) }; | 308 } |
307 | 309 |
308 if (src_w == dest_w && src_h == dest_h) { | 310 if (dest_w < src_w || dest_h < src_h) |
| 311 const_cast<SkBitmap*>(bitmap)->buildMipMap(); |
| 312 |
| 313 float bitmap_scale_x = static_cast<float>(bitmap->width()) / image.width(); |
| 314 float bitmap_scale_y = static_cast<float>(bitmap->height()) / image.height(); |
| 315 |
| 316 SkRect dest_rect = { SkIntToScalar(dest_x), |
| 317 SkIntToScalar(dest_y), |
| 318 SkIntToScalar(dest_x + dest_w), |
| 319 SkIntToScalar(dest_y + dest_h) }; |
| 320 |
| 321 if (src_w == dest_w && src_h == dest_h && |
| 322 bitmap_scale_x == 1.0f && bitmap_scale_y == 1.0f) { |
309 // Workaround for apparent bug in Skia that causes image to occasionally | 323 // Workaround for apparent bug in Skia that causes image to occasionally |
310 // shift. | 324 // shift. |
311 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; | 325 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; |
312 canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); | 326 canvas_->drawBitmapRect(*bitmap, &src_rect, dest_rect, &paint); |
313 return; | 327 return; |
314 } | 328 } |
315 | 329 |
316 // Make a bitmap shader that contains the bitmap we want to draw. This is | 330 // Make a bitmap shader that contains the bitmap we want to draw. This is |
317 // basically what SkCanvas.drawBitmap does internally, but it gives us | 331 // basically what SkCanvas.drawBitmap does internally, but it gives us |
318 // more control over quality and will use the mipmap in the source image if | 332 // more control over quality and will use the mipmap in the source image if |
319 // it has one, whereas drawBitmap won't. | 333 // it has one, whereas drawBitmap won't. |
320 SkShader* shader = SkShader::CreateBitmapShader(bitmap, | 334 SkShader* shader = SkShader::CreateBitmapShader(*bitmap, |
321 SkShader::kRepeat_TileMode, | 335 SkShader::kRepeat_TileMode, |
322 SkShader::kRepeat_TileMode); | 336 SkShader::kRepeat_TileMode); |
323 SkMatrix shader_scale; | 337 SkMatrix shader_scale; |
324 shader_scale.setScale(SkFloatToScalar(dest_w / src_w), | 338 shader_scale.setScale(SkFloatToScalar(static_cast<float>(dest_w) / src_w), |
325 SkFloatToScalar(dest_h / src_h)); | 339 SkFloatToScalar(static_cast<float>(dest_h) / src_h)); |
326 shader_scale.preTranslate(SkFloatToScalar(-src_x), SkFloatToScalar(-src_y)); | 340 shader_scale.preTranslate(SkFloatToScalar(-src_x * bitmap_scale_x), |
327 shader_scale.postTranslate(SkFloatToScalar(dest_x), SkFloatToScalar(dest_y)); | 341 SkFloatToScalar(-src_y * bitmap_scale_y)); |
| 342 shader_scale.postTranslate(SkFloatToScalar(dest_x * bitmap_scale_x), |
| 343 SkFloatToScalar(dest_y * bitmap_scale_y)); |
| 344 shader_scale.postScale(1.0f / bitmap_scale_x, 1.0f / bitmap_scale_y); |
328 shader->setLocalMatrix(shader_scale); | 345 shader->setLocalMatrix(shader_scale); |
329 | 346 |
330 // Set up our paint to use the shader & release our reference (now just owned | 347 // Set up our paint to use the shader & release our reference (now just owned |
331 // by the paint). | 348 // by the paint). |
332 SkPaint p(paint); | 349 SkPaint p(paint); |
333 p.setFilterBitmap(filter); | 350 p.setFilterBitmap(filter); |
334 p.setShader(shader); | 351 p.setShader(shader); |
335 shader->unref(); | 352 shader->unref(); |
336 | 353 |
337 // The rect will be filled by the bitmap. | 354 // The rect will be filled by the bitmap. |
(...skipping 21 matching lines...) Expand all Loading... |
359 int x, int y, int w, int h, | 376 int x, int y, int w, int h, |
360 int flags) { | 377 int flags) { |
361 DrawStringWithShadows(text, | 378 DrawStringWithShadows(text, |
362 font, | 379 font, |
363 color, | 380 color, |
364 gfx::Rect(x, y, w, h), | 381 gfx::Rect(x, y, w, h), |
365 flags, | 382 flags, |
366 std::vector<ShadowValue>()); | 383 std::vector<ShadowValue>()); |
367 } | 384 } |
368 | 385 |
369 void Canvas::TileImageInt(const SkBitmap& bitmap, | 386 void Canvas::TileImageInt(const gfx::ImageSkia& image, |
370 int x, int y, int w, int h) { | 387 int x, int y, int w, int h) { |
371 TileImageInt(bitmap, 0, 0, x, y, w, h); | 388 TileImageInt(image, 0, 0, x, y, w, h); |
372 } | 389 } |
373 | 390 |
374 void Canvas::TileImageInt(const SkBitmap& bitmap, | 391 void Canvas::TileImageInt(const gfx::ImageSkia& image, |
375 int src_x, int src_y, | 392 int src_x, int src_y, |
376 int dest_x, int dest_y, int w, int h) { | 393 int dest_x, int dest_y, int w, int h) { |
377 if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) | 394 if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) |
378 return; | 395 return; |
379 | 396 |
| 397 const SkBitmap* bitmap = GetBitmapToPaint(image); |
| 398 if (bitmap == NULL) |
| 399 return; |
| 400 |
| 401 float bitmap_scale_x = static_cast<float>(bitmap->width()) / image.width(); |
| 402 float bitmap_scale_y = static_cast<float>(bitmap->height()) / image.height(); |
| 403 |
380 SkPaint paint; | 404 SkPaint paint; |
381 | 405 |
382 SkShader* shader = SkShader::CreateBitmapShader(bitmap, | 406 SkShader* shader = SkShader::CreateBitmapShader(*bitmap, |
383 SkShader::kRepeat_TileMode, | 407 SkShader::kRepeat_TileMode, |
384 SkShader::kRepeat_TileMode); | 408 SkShader::kRepeat_TileMode); |
385 paint.setShader(shader); | 409 paint.setShader(shader); |
386 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | 410 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); |
387 | 411 |
388 // CreateBitmapShader returns a Shader with a reference count of one, we | 412 // CreateBitmapShader returns a Shader with a reference count of one, we |
389 // need to unref after paint takes ownership of the shader. | 413 // need to unref after paint takes ownership of the shader. |
390 shader->unref(); | 414 shader->unref(); |
391 canvas_->save(); | 415 canvas_->save(); |
392 canvas_->translate(SkIntToScalar(dest_x - src_x), | 416 canvas_->translate(SkIntToScalar(dest_x - src_x), |
393 SkIntToScalar(dest_y - src_y)); | 417 SkIntToScalar(dest_y - src_y)); |
394 ClipRect(gfx::Rect(src_x, src_y, w, h)); | 418 ClipRect(gfx::Rect(src_x, src_y, w, h)); |
| 419 canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale_x), |
| 420 SkFloatToScalar(1.0f / bitmap_scale_y)); |
395 canvas_->drawPaint(paint); | 421 canvas_->drawPaint(paint); |
396 canvas_->restore(); | 422 canvas_->restore(); |
397 } | 423 } |
398 | 424 |
399 gfx::NativeDrawingContext Canvas::BeginPlatformPaint() { | 425 gfx::NativeDrawingContext Canvas::BeginPlatformPaint() { |
400 return skia::BeginPlatformPaint(canvas_); | 426 return skia::BeginPlatformPaint(canvas_); |
401 } | 427 } |
402 | 428 |
403 void Canvas::EndPlatformPaint() { | 429 void Canvas::EndPlatformPaint() { |
404 skia::EndPlatformPaint(canvas_); | 430 skia::EndPlatformPaint(canvas_); |
405 } | 431 } |
406 | 432 |
407 void Canvas::Transform(const ui::Transform& transform) { | 433 void Canvas::Transform(const ui::Transform& transform) { |
408 canvas_->concat(transform.matrix()); | 434 canvas_->concat(transform.matrix()); |
409 } | 435 } |
410 | 436 |
411 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { | 437 bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { |
412 SkRect clip; | 438 SkRect clip; |
413 return canvas_->getClipBounds(&clip) && | 439 return canvas_->getClipBounds(&clip) && |
414 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), | 440 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), |
415 SkIntToScalar(y + h)); | 441 SkIntToScalar(y + h)); |
416 } | 442 } |
417 | 443 |
418 bool Canvas::IntersectsClipRect(const gfx::Rect& rect) { | 444 bool Canvas::IntersectsClipRect(const gfx::Rect& rect) { |
419 return IntersectsClipRectInt(rect.x(), rect.y(), | 445 return IntersectsClipRectInt(rect.x(), rect.y(), |
420 rect.width(), rect.height()); | 446 rect.width(), rect.height()); |
421 } | 447 } |
422 | 448 |
| 449 const SkBitmap* Canvas::GetBitmapToPaint(const gfx::ImageSkia& image) const { |
| 450 SkMatrix m = canvas_->getTotalMatrix(); |
| 451 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())); |
| 452 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())); |
| 453 |
| 454 const SkBitmap* to_paint = image.GetBitmapForScale(scale_x, scale_y); |
| 455 |
| 456 if (to_paint != NULL) { |
| 457 DCHECK(to_paint->width() >= image.width() && |
| 458 to_paint->height() >= image.height()); |
| 459 if (scale_x < 1.0f || scale_y < 1.0f) |
| 460 const_cast<SkBitmap*>(to_paint)->buildMipMap(); |
| 461 } |
| 462 |
| 463 return to_paint; |
| 464 } |
| 465 |
423 } // namespace gfx | 466 } // namespace gfx |
OLD | NEW |