Chromium Code Reviews| 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 <cmath> | 7 #include <cmath> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 int src_x, | 370 int src_x, |
| 371 int src_y, | 371 int src_y, |
| 372 int src_w, | 372 int src_w, |
| 373 int src_h, | 373 int src_h, |
| 374 int dest_x, | 374 int dest_x, |
| 375 int dest_y, | 375 int dest_y, |
| 376 int dest_w, | 376 int dest_w, |
| 377 int dest_h, | 377 int dest_h, |
| 378 bool filter, | 378 bool filter, |
| 379 const SkPaint& paint) { | 379 const SkPaint& paint) { |
| 380 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && | 380 DrawImageIntHelper(image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, |
| 381 src_y + src_h < std::numeric_limits<int16_t>::max()); | 381 dest_h, filter, paint, image_scale_, false); |
| 382 if (src_w <= 0 || src_h <= 0) { | 382 } |
| 383 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; | |
| 384 return; | |
| 385 } | |
| 386 | 383 |
| 387 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) | 384 void Canvas::DrawImageIntInPixel(const ImageSkia& image, |
| 388 return; | 385 int src_x, |
| 386 int src_y, | |
| 387 int src_w, | |
| 388 int src_h, | |
| 389 int dest_x, | |
| 390 int dest_y, | |
| 391 int dest_w, | |
| 392 int dest_h, | |
| 393 bool filter, | |
| 394 const SkPaint& paint) { | |
| 395 // Logic as below:- | |
| 396 // 1. Translate the destination rectangle with using the current translation | |
|
sky
2014/05/05 14:08:16
nit: remove with.
ananta
2014/05/05 18:53:28
Done.
| |
| 397 // values from the SkCanvas matrix stack. | |
| 398 // 2. Save the current state of the canvas. | |
| 399 // 3. Reset the scales and the translation values in the SkCanvas matrix | |
| 400 // stack top. | |
| 401 // 4. Set the scale in gfx::Canvas instance to 1.0, 1.0. Ideally this should | |
|
sky
2014/05/05 14:08:16
I don't get the 'ideally this sould have been enou
ananta
2014/05/05 18:53:28
I assumed that setting the scale to 1.0 in the SkC
| |
| 402 // have been enough. But is not the case. | |
| 403 // 5. Draw the image. | |
| 404 // 6. Restore the state of the canvas and the SkCanvas matrix stack. | |
| 405 float image_scale = image_scale_; | |
| 406 SkMatrix saved_matrix = canvas_->getTotalMatrix(); | |
| 407 SkMatrix new_matrix = saved_matrix; | |
| 389 | 408 |
| 390 float user_scale_x = static_cast<float>(dest_w) / src_w; | 409 SkRect destination_rect; |
| 391 float user_scale_y = static_cast<float>(dest_h) / src_h; | 410 destination_rect.set(dest_x, dest_y, dest_x + dest_w, dest_y + dest_h); |
|
sky
2014/05/05 14:08:16
These should all be SkIntToScalar I bleieve.
ananta
2014/05/05 18:53:28
Done.
| |
| 411 new_matrix.setScaleX(1.0f); | |
| 412 new_matrix.setScaleY(1.0f); | |
| 413 new_matrix.mapRect(&destination_rect, destination_rect); | |
| 392 | 414 |
| 393 const ImageSkiaRep& image_rep = GetImageRepToPaint(image, | 415 Save(); |
| 394 user_scale_x, user_scale_y); | |
| 395 if (image_rep.is_null()) | |
| 396 return; | |
| 397 | 416 |
| 398 SkRect dest_rect = { SkIntToScalar(dest_x), | 417 // The destination is now in pixel values. No need for further translation. |
| 399 SkIntToScalar(dest_y), | 418 new_matrix.setTranslate(0, 0); |
| 400 SkIntToScalar(dest_x + dest_w), | 419 canvas_->setMatrix(new_matrix); |
| 401 SkIntToScalar(dest_y + dest_h) }; | |
| 402 | 420 |
| 403 if (src_w == dest_w && src_h == dest_h && | 421 Scale(1.0f, 1.0f); |
| 404 user_scale_x == 1.0f && user_scale_y == 1.0f && | |
| 405 image_rep.scale() == 1.0f) { | |
| 406 // Workaround for apparent bug in Skia that causes image to occasionally | |
| 407 // shift. | |
| 408 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; | |
| 409 const SkBitmap& bitmap = image_rep.sk_bitmap(); | |
| 410 canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); | |
| 411 return; | |
| 412 } | |
| 413 | 422 |
| 414 // Make a bitmap shader that contains the bitmap we want to draw. This is | 423 DrawImageIntHelper(image, src_x, src_y, src_w, src_h, destination_rect.x(), |
|
sky
2014/05/05 14:08:16
SkScalarToInt I believe.
ananta
2014/05/05 18:53:28
No function by that name. Replaced with SkScalarRo
| |
| 415 // basically what SkCanvas.drawBitmap does internally, but it gives us | 424 destination_rect.y(), destination_rect.width(), |
| 416 // more control over quality and will use the mipmap in the source image if | 425 destination_rect.height(), filter, paint, image_scale, |
| 417 // it has one, whereas drawBitmap won't. | 426 true); |
| 418 SkMatrix shader_scale; | |
| 419 shader_scale.setScale(SkFloatToScalar(user_scale_x), | |
| 420 SkFloatToScalar(user_scale_y)); | |
| 421 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); | |
| 422 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); | |
| 423 | 427 |
| 424 skia::RefPtr<SkShader> shader = CreateImageRepShader( | 428 // Restore the scale factor and the old state in the canvas. |
| 425 image_rep, | 429 Scale(image_scale, image_scale); |
|
sky
2014/05/05 14:08:16
Doesn't the save save the matrix and scale so that
ananta
2014/05/05 18:53:28
Left the Restore call as is. Removed the rest.
| |
| 426 SkShader::kRepeat_TileMode, | 430 Restore(); |
| 427 shader_scale); | 431 canvas_->setMatrix(saved_matrix); |
| 428 | 432 image_scale_ = image_scale; |
| 429 // Set up our paint to use the shader & release our reference (now just owned | |
| 430 // by the paint). | |
| 431 SkPaint p(paint); | |
| 432 p.setFilterBitmap(filter); | |
| 433 p.setShader(shader.get()); | |
| 434 | |
| 435 // The rect will be filled by the bitmap. | |
| 436 canvas_->drawRect(dest_rect, p); | |
| 437 } | 433 } |
| 438 | 434 |
| 439 void Canvas::DrawImageInPath(const ImageSkia& image, | 435 void Canvas::DrawImageInPath(const ImageSkia& image, |
| 440 int x, | 436 int x, |
| 441 int y, | 437 int y, |
| 442 const SkPath& path, | 438 const SkPath& path, |
| 443 const SkPaint& paint) { | 439 const SkPaint& paint) { |
| 444 const ImageSkiaRep& image_rep = GetImageRepToPaint(image); | 440 const ImageSkiaRep& image_rep = GetImageRepToPaint(image); |
| 445 if (image_rep.is_null()) | 441 if (image_rep.is_null()) |
| 446 return; | 442 return; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 float tile_scale_x, | 494 float tile_scale_x, |
| 499 float tile_scale_y, | 495 float tile_scale_y, |
| 500 int dest_x, | 496 int dest_x, |
| 501 int dest_y, | 497 int dest_y, |
| 502 int w, | 498 int w, |
| 503 int h) { | 499 int h) { |
| 504 if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) | 500 if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) |
| 505 return; | 501 return; |
| 506 | 502 |
| 507 const ImageSkiaRep& image_rep = GetImageRepToPaint( | 503 const ImageSkiaRep& image_rep = GetImageRepToPaint( |
| 508 image, tile_scale_x, tile_scale_y); | 504 image, image_scale_, tile_scale_x, tile_scale_y); |
| 509 if (image_rep.is_null()) | 505 if (image_rep.is_null()) |
| 510 return; | 506 return; |
| 511 | 507 |
| 512 SkMatrix shader_scale; | 508 SkMatrix shader_scale; |
| 513 shader_scale.setScale(SkFloatToScalar(tile_scale_x), | 509 shader_scale.setScale(SkFloatToScalar(tile_scale_x), |
| 514 SkFloatToScalar(tile_scale_y)); | 510 SkFloatToScalar(tile_scale_y)); |
| 515 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); | 511 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); |
| 516 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); | 512 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); |
| 517 | 513 |
| 518 skia::RefPtr<SkShader> shader = CreateImageRepShader( | 514 skia::RefPtr<SkShader> shader = CreateImageRepShader( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), | 552 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), |
| 557 SkIntToScalar(y + h)); | 553 SkIntToScalar(y + h)); |
| 558 } | 554 } |
| 559 | 555 |
| 560 bool Canvas::IntersectsClipRect(const Rect& rect) { | 556 bool Canvas::IntersectsClipRect(const Rect& rect) { |
| 561 return IntersectsClipRectInt(rect.x(), rect.y(), | 557 return IntersectsClipRectInt(rect.x(), rect.y(), |
| 562 rect.width(), rect.height()); | 558 rect.width(), rect.height()); |
| 563 } | 559 } |
| 564 | 560 |
| 565 const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const { | 561 const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const { |
| 566 return GetImageRepToPaint(image, 1.0f, 1.0f); | 562 return GetImageRepToPaint(image, image_scale_, 1.0f, 1.0f); |
| 567 } | 563 } |
| 568 | 564 |
| 569 const ImageSkiaRep& Canvas::GetImageRepToPaint( | 565 const ImageSkiaRep& Canvas::GetImageRepToPaint( |
| 570 const ImageSkia& image, | 566 const ImageSkia& image, |
| 567 float image_scale, | |
| 571 float user_additional_scale_x, | 568 float user_additional_scale_x, |
| 572 float user_additional_scale_y) const { | 569 float user_additional_scale_y) const { |
| 573 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_); | 570 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale); |
| 574 | 571 |
| 575 if (!image_rep.is_null()) { | 572 if (!image_rep.is_null()) { |
| 576 SkMatrix m = canvas_->getTotalMatrix(); | 573 SkMatrix m = canvas_->getTotalMatrix(); |
| 577 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) * | 574 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) * |
| 578 user_additional_scale_x; | 575 user_additional_scale_x; |
| 579 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) * | 576 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) * |
| 580 user_additional_scale_y; | 577 user_additional_scale_y; |
| 581 | 578 |
| 582 float bitmap_scale = image_rep.scale(); | 579 float bitmap_scale = image_rep.scale(); |
| 583 if (scale_x < bitmap_scale || scale_y < bitmap_scale) | 580 if (scale_x < bitmap_scale || scale_y < bitmap_scale) |
| 584 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap(); | 581 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap(); |
| 585 } | 582 } |
| 586 | 583 |
| 587 return image_rep; | 584 return image_rep; |
| 588 } | 585 } |
| 589 | 586 |
| 587 void Canvas::DrawImageIntHelper(const ImageSkia& image, | |
| 588 int src_x, | |
| 589 int src_y, | |
| 590 int src_w, | |
| 591 int src_h, | |
| 592 int dest_x, | |
| 593 int dest_y, | |
| 594 int dest_w, | |
| 595 int dest_h, | |
| 596 bool filter, | |
| 597 const SkPaint& paint, | |
| 598 float image_scale, | |
| 599 bool pixel) { | |
| 600 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && | |
| 601 src_y + src_h < std::numeric_limits<int16_t>::max()); | |
| 602 if (src_w <= 0 || src_h <= 0) { | |
| 603 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; | |
| 604 return; | |
| 605 } | |
| 606 | |
| 607 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) | |
| 608 return; | |
| 609 | |
| 610 float user_scale_x = static_cast<float>(dest_w) / src_w; | |
| 611 float user_scale_y = static_cast<float>(dest_h) / src_h; | |
| 612 | |
| 613 const ImageSkiaRep& image_rep = GetImageRepToPaint(image, | |
| 614 image_scale, user_scale_x, user_scale_y); | |
| 615 if (image_rep.is_null()) | |
| 616 return; | |
| 617 | |
| 618 SkRect dest_rect = { SkIntToScalar(dest_x), | |
| 619 SkIntToScalar(dest_y), | |
| 620 SkIntToScalar(dest_x + dest_w), | |
| 621 SkIntToScalar(dest_y + dest_h) }; | |
| 622 | |
| 623 if (src_w == dest_w && src_h == dest_h && | |
| 624 user_scale_x == 1.0f && user_scale_y == 1.0f && | |
| 625 image_rep.scale() == 1.0f && !pixel) { | |
| 626 // Workaround for apparent bug in Skia that causes image to occasionally | |
| 627 // shift. | |
| 628 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; | |
| 629 const SkBitmap& bitmap = image_rep.sk_bitmap(); | |
| 630 canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); | |
| 631 return; | |
| 632 } | |
| 633 | |
| 634 // Make a bitmap shader that contains the bitmap we want to draw. This is | |
| 635 // basically what SkCanvas.drawBitmap does internally, but it gives us | |
| 636 // more control over quality and will use the mipmap in the source image if | |
| 637 // it has one, whereas drawBitmap won't. | |
| 638 SkMatrix shader_scale; | |
| 639 shader_scale.setScale(SkFloatToScalar(user_scale_x), | |
| 640 SkFloatToScalar(user_scale_y)); | |
| 641 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); | |
| 642 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); | |
| 643 | |
| 644 skia::RefPtr<SkShader> shader = CreateImageRepShaderForScale( | |
| 645 image_rep, | |
| 646 SkShader::kRepeat_TileMode, | |
| 647 shader_scale, | |
| 648 pixel ? 1.0f : image_scale); | |
| 649 | |
| 650 // Set up our paint to use the shader & release our reference (now just owned | |
| 651 // by the paint). | |
| 652 SkPaint p(paint); | |
| 653 p.setFilterBitmap(filter); | |
| 654 p.setShader(shader.get()); | |
| 655 | |
| 656 // The rect will be filled by the bitmap. | |
| 657 canvas_->drawRect(dest_rect, p); | |
| 658 } | |
| 659 | |
| 590 } // namespace gfx | 660 } // namespace gfx |
| OLD | NEW |