| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 skia::CreatePlatformCanvas(image_rep.pixel_width(), | 47 skia::CreatePlatformCanvas(image_rep.pixel_width(), |
| 48 image_rep.pixel_height(), | 48 image_rep.pixel_height(), |
| 49 is_opaque))), | 49 is_opaque))), |
| 50 canvas_(owned_canvas_.get()) { | 50 canvas_(owned_canvas_.get()) { |
| 51 SkScalar scale_scalar = SkFloatToScalar(image_scale_); | 51 SkScalar scale_scalar = SkFloatToScalar(image_scale_); |
| 52 canvas_->scale(scale_scalar, scale_scalar); | 52 canvas_->scale(scale_scalar, scale_scalar); |
| 53 DrawImageInt(ImageSkia(image_rep), 0, 0); | 53 DrawImageInt(ImageSkia(image_rep), 0, 0); |
| 54 } | 54 } |
| 55 | 55 |
| 56 Canvas::Canvas() | 56 Canvas::Canvas() |
| 57 : image_scale_(1.0), | 57 : image_scale_(1.f), |
| 58 owned_canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))), | 58 owned_canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))), |
| 59 canvas_(owned_canvas_.get()) { | 59 canvas_(owned_canvas_.get()) {} |
| 60 } | |
| 61 | 60 |
| 62 Canvas::Canvas(SkCanvas* canvas, float image_scale) | 61 Canvas::Canvas(SkCanvas* canvas, float image_scale) |
| 63 : image_scale_(image_scale), owned_canvas_(), canvas_(canvas) { | 62 : image_scale_(image_scale), owned_canvas_(), canvas_(canvas) { |
| 64 DCHECK(canvas); | 63 DCHECK(canvas); |
| 65 } | 64 } |
| 66 | 65 |
| 67 Canvas::~Canvas() { | 66 Canvas::~Canvas() { |
| 68 } | 67 } |
| 69 | 68 |
| 70 void Canvas::RecreateBackingCanvas(const Size& size, | 69 void Canvas::RecreateBackingCanvas(const Size& size, |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 int src_x, | 377 int src_x, |
| 379 int src_y, | 378 int src_y, |
| 380 int src_w, | 379 int src_w, |
| 381 int src_h, | 380 int src_h, |
| 382 int dest_x, | 381 int dest_x, |
| 383 int dest_y, | 382 int dest_y, |
| 384 int dest_w, | 383 int dest_w, |
| 385 int dest_h, | 384 int dest_h, |
| 386 bool filter, | 385 bool filter, |
| 387 const SkPaint& paint) { | 386 const SkPaint& paint) { |
| 388 DrawImageIntHelper(image, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, | 387 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_); |
| 389 dest_h, filter, paint, image_scale_, false); | 388 if (image_rep.is_null()) |
| 389 return; |
| 390 DrawImageIntHelper(image_rep, src_x, src_y, src_w, src_h, dest_x, dest_y, |
| 391 dest_w, dest_h, filter, paint, false); |
| 390 } | 392 } |
| 391 | 393 |
| 392 void Canvas::DrawImageIntInPixel(const ImageSkia& image, | 394 void Canvas::DrawImageIntInPixel(const ImageSkiaRep& image_rep, |
| 393 int src_x, | |
| 394 int src_y, | |
| 395 int src_w, | |
| 396 int src_h, | |
| 397 int dest_x, | 395 int dest_x, |
| 398 int dest_y, | 396 int dest_y, |
| 399 int dest_w, | 397 int dest_w, |
| 400 int dest_h, | 398 int dest_h, |
| 401 bool filter, | 399 bool filter, |
| 402 const SkPaint& paint) { | 400 const SkPaint& paint) { |
| 403 // All values passed into this function are in pixels, i.e. no scaling needs | 401 int src_x = 0; |
| 404 // be done. | 402 int src_y = 0; |
| 405 // Logic as below:- | 403 int src_w = image_rep.pixel_width(); |
| 406 // 1. Get the matrix transform from the canvas. | 404 int src_h = image_rep.pixel_height(); |
| 407 // 2. Set the scale in the matrix to 1.0 while honoring the direction of the | 405 DrawImageIntHelper(image_rep, src_x, src_y, src_w, src_h, dest_x, dest_y, |
| 408 // the scale (x/y). Example RTL layouts. | 406 dest_w, dest_h, filter, paint, true); |
| 409 // 3. Round off the X and Y translation components in the matrix. This is to | |
| 410 // reduce floating point errors during rect transformation. This is needed | |
| 411 // for fractional scale factors like 1.25/1.5, etc. | |
| 412 // 4. Save the current state of the canvas and restore the state when going | |
| 413 // out of scope with ScopedCanvas. | |
| 414 // 5. Set the modified matrix in the canvas. This ensures that no scaling | |
| 415 // will be done for draw operations on the canvas. | |
| 416 // 6. Draw the image. | |
| 417 SkMatrix matrix = canvas_->getTotalMatrix(); | |
| 418 | |
| 419 // Ensure that the direction of the x and y scales is preserved. This is | |
| 420 // important for RTL layouts. | |
| 421 matrix.setScaleX(matrix.getScaleX() > 0 ? 1.0f : -1.0f); | |
| 422 matrix.setScaleY(matrix.getScaleY() > 0 ? 1.0f : -1.0f); | |
| 423 | |
| 424 // Floor so that we get consistent rounding. | |
| 425 matrix.setTranslateX(SkScalarFloorToScalar(matrix.getTranslateX())); | |
| 426 matrix.setTranslateY(SkScalarFloorToScalar(matrix.getTranslateY())); | |
| 427 | |
| 428 ScopedCanvas scoper(this); | |
| 429 | |
| 430 canvas_->setMatrix(matrix); | |
| 431 | |
| 432 DrawImageIntHelper(image, | |
| 433 src_x, | |
| 434 src_y, | |
| 435 src_w, | |
| 436 src_h, | |
| 437 dest_x, | |
| 438 dest_y, | |
| 439 dest_w, | |
| 440 dest_h, | |
| 441 filter, | |
| 442 paint, | |
| 443 image_scale_, | |
| 444 true); | |
| 445 } | 407 } |
| 446 | 408 |
| 447 void Canvas::DrawImageInPath(const ImageSkia& image, | 409 void Canvas::DrawImageInPath(const ImageSkia& image, |
| 448 int x, | 410 int x, |
| 449 int y, | 411 int y, |
| 450 const SkPath& path, | 412 const SkPath& path, |
| 451 const SkPaint& paint) { | 413 const SkPaint& paint) { |
| 452 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_); | 414 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_); |
| 453 if (image_rep.is_null()) | 415 if (image_rep.is_null()) |
| 454 return; | 416 return; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 return canvas_->getClipBounds(&clip) && | 509 return canvas_->getClipBounds(&clip) && |
| 548 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), | 510 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), |
| 549 SkIntToScalar(y + h)); | 511 SkIntToScalar(y + h)); |
| 550 } | 512 } |
| 551 | 513 |
| 552 bool Canvas::IntersectsClipRect(const Rect& rect) { | 514 bool Canvas::IntersectsClipRect(const Rect& rect) { |
| 553 return IntersectsClipRectInt(rect.x(), rect.y(), | 515 return IntersectsClipRectInt(rect.x(), rect.y(), |
| 554 rect.width(), rect.height()); | 516 rect.width(), rect.height()); |
| 555 } | 517 } |
| 556 | 518 |
| 557 void Canvas::DrawImageIntHelper(const ImageSkia& image, | 519 void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep, |
| 558 int src_x, | 520 int src_x, |
| 559 int src_y, | 521 int src_y, |
| 560 int src_w, | 522 int src_w, |
| 561 int src_h, | 523 int src_h, |
| 562 int dest_x, | 524 int dest_x, |
| 563 int dest_y, | 525 int dest_y, |
| 564 int dest_w, | 526 int dest_w, |
| 565 int dest_h, | 527 int dest_h, |
| 566 bool filter, | 528 bool filter, |
| 567 const SkPaint& paint, | 529 const SkPaint& paint, |
| 568 float image_scale, | |
| 569 bool pixel) { | 530 bool pixel) { |
| 570 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && | 531 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && |
| 571 src_y + src_h < std::numeric_limits<int16_t>::max()); | 532 src_y + src_h < std::numeric_limits<int16_t>::max()); |
| 572 if (src_w <= 0 || src_h <= 0) { | 533 if (src_w <= 0 || src_h <= 0) { |
| 573 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; | 534 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; |
| 574 return; | 535 return; |
| 575 } | 536 } |
| 576 | 537 |
| 577 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) | 538 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) |
| 578 return; | 539 return; |
| 579 | 540 |
| 580 float user_scale_x = static_cast<float>(dest_w) / src_w; | 541 float user_scale_x = static_cast<float>(dest_w) / src_w; |
| 581 float user_scale_y = static_cast<float>(dest_h) / src_h; | 542 float user_scale_y = static_cast<float>(dest_h) / src_h; |
| 582 | 543 |
| 583 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale); | |
| 584 if (image_rep.is_null()) | |
| 585 return; | |
| 586 | |
| 587 SkRect dest_rect = { SkIntToScalar(dest_x), | 544 SkRect dest_rect = { SkIntToScalar(dest_x), |
| 588 SkIntToScalar(dest_y), | 545 SkIntToScalar(dest_y), |
| 589 SkIntToScalar(dest_x + dest_w), | 546 SkIntToScalar(dest_x + dest_w), |
| 590 SkIntToScalar(dest_y + dest_h) }; | 547 SkIntToScalar(dest_y + dest_h) }; |
| 591 | 548 |
| 592 if (src_w == dest_w && src_h == dest_h && | 549 if (src_w == dest_w && src_h == dest_h && |
| 593 user_scale_x == 1.0f && user_scale_y == 1.0f && | 550 user_scale_x == 1.0f && user_scale_y == 1.0f && |
| 594 image_rep.scale() == 1.0f && !pixel) { | 551 image_rep.scale() == 1.0f && !pixel) { |
| 595 // Workaround for apparent bug in Skia that causes image to occasionally | 552 // Workaround for apparent bug in Skia that causes image to occasionally |
| 596 // shift. | 553 // shift. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 620 // by the paint). | 577 // by the paint). |
| 621 SkPaint p(paint); | 578 SkPaint p(paint); |
| 622 p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality); | 579 p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality); |
| 623 p.setShader(shader.get()); | 580 p.setShader(shader.get()); |
| 624 | 581 |
| 625 // The rect will be filled by the bitmap. | 582 // The rect will be filled by the bitmap. |
| 626 canvas_->drawRect(dest_rect, p); | 583 canvas_->drawRect(dest_rect, p); |
| 627 } | 584 } |
| 628 | 585 |
| 629 } // namespace gfx | 586 } // namespace gfx |
| OLD | NEW |