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 |