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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 return canvas_->getClipBounds(&clip) && | 517 return canvas_->getClipBounds(&clip) && |
556 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), | 518 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), |
557 SkIntToScalar(y + h)); | 519 SkIntToScalar(y + h)); |
558 } | 520 } |
559 | 521 |
560 bool Canvas::IntersectsClipRect(const Rect& rect) { | 522 bool Canvas::IntersectsClipRect(const Rect& rect) { |
561 return IntersectsClipRectInt(rect.x(), rect.y(), | 523 return IntersectsClipRectInt(rect.x(), rect.y(), |
562 rect.width(), rect.height()); | 524 rect.width(), rect.height()); |
563 } | 525 } |
564 | 526 |
565 void Canvas::DrawImageIntHelper(const ImageSkia& image, | 527 void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep, |
566 int src_x, | 528 int src_x, |
567 int src_y, | 529 int src_y, |
568 int src_w, | 530 int src_w, |
569 int src_h, | 531 int src_h, |
570 int dest_x, | 532 int dest_x, |
571 int dest_y, | 533 int dest_y, |
572 int dest_w, | 534 int dest_w, |
573 int dest_h, | 535 int dest_h, |
574 bool filter, | 536 bool filter, |
575 const SkPaint& paint, | 537 const SkPaint& paint, |
576 float image_scale, | |
577 bool pixel) { | 538 bool pixel) { |
578 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && | 539 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() && |
579 src_y + src_h < std::numeric_limits<int16_t>::max()); | 540 src_y + src_h < std::numeric_limits<int16_t>::max()); |
580 if (src_w <= 0 || src_h <= 0) { | 541 if (src_w <= 0 || src_h <= 0) { |
581 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; | 542 NOTREACHED() << "Attempting to draw bitmap from an empty rect!"; |
582 return; | 543 return; |
583 } | 544 } |
584 | 545 |
585 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) | 546 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) |
586 return; | 547 return; |
587 | 548 |
588 float user_scale_x = static_cast<float>(dest_w) / src_w; | 549 float user_scale_x = static_cast<float>(dest_w) / src_w; |
589 float user_scale_y = static_cast<float>(dest_h) / src_h; | 550 float user_scale_y = static_cast<float>(dest_h) / src_h; |
590 | 551 |
591 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale); | |
592 if (image_rep.is_null()) | |
593 return; | |
594 | |
595 SkRect dest_rect = { SkIntToScalar(dest_x), | 552 SkRect dest_rect = { SkIntToScalar(dest_x), |
596 SkIntToScalar(dest_y), | 553 SkIntToScalar(dest_y), |
597 SkIntToScalar(dest_x + dest_w), | 554 SkIntToScalar(dest_x + dest_w), |
598 SkIntToScalar(dest_y + dest_h) }; | 555 SkIntToScalar(dest_y + dest_h) }; |
599 | 556 |
600 if (src_w == dest_w && src_h == dest_h && | 557 if (src_w == dest_w && src_h == dest_h && |
601 user_scale_x == 1.0f && user_scale_y == 1.0f && | 558 user_scale_x == 1.0f && user_scale_y == 1.0f && |
602 image_rep.scale() == 1.0f && !pixel) { | 559 image_rep.scale() == 1.0f && !pixel) { |
603 // Workaround for apparent bug in Skia that causes image to occasionally | 560 // Workaround for apparent bug in Skia that causes image to occasionally |
604 // shift. | 561 // shift. |
(...skipping 23 matching lines...) Expand all Loading... |
628 // by the paint). | 585 // by the paint). |
629 SkPaint p(paint); | 586 SkPaint p(paint); |
630 p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality); | 587 p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality); |
631 p.setShader(shader.get()); | 588 p.setShader(shader.get()); |
632 | 589 |
633 // The rect will be filled by the bitmap. | 590 // The rect will be filled by the bitmap. |
634 canvas_->drawRect(dest_rect, p); | 591 canvas_->drawRect(dest_rect, p); |
635 } | 592 } |
636 | 593 |
637 } // namespace gfx | 594 } // namespace gfx |
OLD | NEW |