Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: ui/gfx/canvas.cc

Issue 262773010: Fix images drawn with the NineImagePainter class in high DPI. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased to tip Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/gfx/nine_image_painter.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 using the current translation
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.
402 // 5. Draw the image.
403 // 6. Restore the state of the canvas and the SkCanvas matrix stack.
404 SkMatrix matrix = canvas_->getTotalMatrix();
389 405
390 float user_scale_x = static_cast<float>(dest_w) / src_w; 406 SkRect destination_rect;
391 float user_scale_y = static_cast<float>(dest_h) / src_h; 407 destination_rect.set(SkIntToScalar(dest_x),
392
393 const ImageSkiaRep& image_rep = GetImageRepToPaint(image,
394 user_scale_x, user_scale_y);
395 if (image_rep.is_null())
396 return;
397
398 SkRect dest_rect = { SkIntToScalar(dest_x),
399 SkIntToScalar(dest_y), 408 SkIntToScalar(dest_y),
400 SkIntToScalar(dest_x + dest_w), 409 SkIntToScalar(dest_x + dest_w),
401 SkIntToScalar(dest_y + dest_h) }; 410 SkIntToScalar(dest_y + dest_h));
411 matrix.setScaleX(1.0f);
412 matrix.setScaleY(1.0f);
413 matrix.mapRect(&destination_rect, destination_rect);
oshima 2014/05/06 06:44:01 This doesn't seem to work if the canvas is rotated
402 414
403 if (src_w == dest_w && src_h == dest_h && 415 Save();
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 416
414 // Make a bitmap shader that contains the bitmap we want to draw. This is 417 // The destination is now in pixel values. No need for further translation.
415 // basically what SkCanvas.drawBitmap does internally, but it gives us 418 matrix.setTranslate(0, 0);
416 // more control over quality and will use the mipmap in the source image if 419 canvas_->setMatrix(matrix);
417 // it has one, whereas drawBitmap won't.
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 420
424 skia::RefPtr<SkShader> shader = CreateImageRepShader( 421 DrawImageIntHelper(image,
425 image_rep, 422 src_x,
426 SkShader::kRepeat_TileMode, 423 src_y,
427 shader_scale); 424 src_w,
425 src_h,
426 SkScalarRoundToInt(destination_rect.x()),
427 SkScalarRoundToInt(destination_rect.y()),
428 SkScalarRoundToInt(destination_rect.width()),
429 SkScalarRoundToInt(destination_rect.height()),
430 filter,
431 paint,
432 image_scale_,
433 true);
428 434
429 // Set up our paint to use the shader & release our reference (now just owned 435 // Restore the state of the canvas.
430 // by the paint). 436 Restore();
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 } 437 }
438 438
439 void Canvas::DrawImageInPath(const ImageSkia& image, 439 void Canvas::DrawImageInPath(const ImageSkia& image,
440 int x, 440 int x,
441 int y, 441 int y,
442 const SkPath& path, 442 const SkPath& path,
443 const SkPaint& paint) { 443 const SkPaint& paint) {
444 const ImageSkiaRep& image_rep = GetImageRepToPaint(image); 444 const ImageSkiaRep& image_rep = GetImageRepToPaint(image);
445 if (image_rep.is_null()) 445 if (image_rep.is_null())
446 return; 446 return;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 float tile_scale_x, 498 float tile_scale_x,
499 float tile_scale_y, 499 float tile_scale_y,
500 int dest_x, 500 int dest_x,
501 int dest_y, 501 int dest_y,
502 int w, 502 int w,
503 int h) { 503 int h) {
504 if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) 504 if (!IntersectsClipRectInt(dest_x, dest_y, w, h))
505 return; 505 return;
506 506
507 const ImageSkiaRep& image_rep = GetImageRepToPaint( 507 const ImageSkiaRep& image_rep = GetImageRepToPaint(
508 image, tile_scale_x, tile_scale_y); 508 image, image_scale_, tile_scale_x, tile_scale_y);
509 if (image_rep.is_null()) 509 if (image_rep.is_null())
510 return; 510 return;
511 511
512 SkMatrix shader_scale; 512 SkMatrix shader_scale;
513 shader_scale.setScale(SkFloatToScalar(tile_scale_x), 513 shader_scale.setScale(SkFloatToScalar(tile_scale_x),
514 SkFloatToScalar(tile_scale_y)); 514 SkFloatToScalar(tile_scale_y));
515 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); 515 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
516 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); 516 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
517 517
518 skia::RefPtr<SkShader> shader = CreateImageRepShader( 518 skia::RefPtr<SkShader> shader = CreateImageRepShader(
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), 556 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
557 SkIntToScalar(y + h)); 557 SkIntToScalar(y + h));
558 } 558 }
559 559
560 bool Canvas::IntersectsClipRect(const Rect& rect) { 560 bool Canvas::IntersectsClipRect(const Rect& rect) {
561 return IntersectsClipRectInt(rect.x(), rect.y(), 561 return IntersectsClipRectInt(rect.x(), rect.y(),
562 rect.width(), rect.height()); 562 rect.width(), rect.height());
563 } 563 }
564 564
565 const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const { 565 const ImageSkiaRep& Canvas::GetImageRepToPaint(const ImageSkia& image) const {
566 return GetImageRepToPaint(image, 1.0f, 1.0f); 566 return GetImageRepToPaint(image, image_scale_, 1.0f, 1.0f);
567 } 567 }
568 568
569 const ImageSkiaRep& Canvas::GetImageRepToPaint( 569 const ImageSkiaRep& Canvas::GetImageRepToPaint(
570 const ImageSkia& image, 570 const ImageSkia& image,
571 float image_scale,
571 float user_additional_scale_x, 572 float user_additional_scale_x,
572 float user_additional_scale_y) const { 573 float user_additional_scale_y) const {
573 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_); 574 const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale);
574 575
575 if (!image_rep.is_null()) { 576 if (!image_rep.is_null()) {
576 SkMatrix m = canvas_->getTotalMatrix(); 577 SkMatrix m = canvas_->getTotalMatrix();
577 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) * 578 float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) *
578 user_additional_scale_x; 579 user_additional_scale_x;
579 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) * 580 float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) *
580 user_additional_scale_y; 581 user_additional_scale_y;
581 582
582 float bitmap_scale = image_rep.scale(); 583 float bitmap_scale = image_rep.scale();
583 if (scale_x < bitmap_scale || scale_y < bitmap_scale) 584 if (scale_x < bitmap_scale || scale_y < bitmap_scale)
584 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap(); 585 const_cast<SkBitmap&>(image_rep.sk_bitmap()).buildMipMap();
585 } 586 }
586 587
587 return image_rep; 588 return image_rep;
588 } 589 }
589 590
591 void Canvas::DrawImageIntHelper(const ImageSkia& image,
592 int src_x,
593 int src_y,
594 int src_w,
595 int src_h,
596 int dest_x,
597 int dest_y,
598 int dest_w,
599 int dest_h,
600 bool filter,
601 const SkPaint& paint,
602 float image_scale,
603 bool pixel) {
604 DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
605 src_y + src_h < std::numeric_limits<int16_t>::max());
606 if (src_w <= 0 || src_h <= 0) {
607 NOTREACHED() << "Attempting to draw bitmap from an empty rect!";
608 return;
609 }
610
611 if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h))
612 return;
613
614 float user_scale_x = static_cast<float>(dest_w) / src_w;
615 float user_scale_y = static_cast<float>(dest_h) / src_h;
616
617 const ImageSkiaRep& image_rep = GetImageRepToPaint(image,
618 image_scale, user_scale_x, user_scale_y);
619 if (image_rep.is_null())
620 return;
621
622 SkRect dest_rect = { SkIntToScalar(dest_x),
623 SkIntToScalar(dest_y),
624 SkIntToScalar(dest_x + dest_w),
625 SkIntToScalar(dest_y + dest_h) };
626
627 if (src_w == dest_w && src_h == dest_h &&
628 user_scale_x == 1.0f && user_scale_y == 1.0f &&
629 image_rep.scale() == 1.0f && !pixel) {
630 // Workaround for apparent bug in Skia that causes image to occasionally
631 // shift.
632 SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
633 const SkBitmap& bitmap = image_rep.sk_bitmap();
634 canvas_->drawBitmapRect(bitmap, &src_rect, dest_rect, &paint);
635 return;
636 }
637
638 // Make a bitmap shader that contains the bitmap we want to draw. This is
639 // basically what SkCanvas.drawBitmap does internally, but it gives us
640 // more control over quality and will use the mipmap in the source image if
641 // it has one, whereas drawBitmap won't.
642 SkMatrix shader_scale;
643 shader_scale.setScale(SkFloatToScalar(user_scale_x),
644 SkFloatToScalar(user_scale_y));
645 shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
646 shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
647
648 skia::RefPtr<SkShader> shader = CreateImageRepShaderForScale(
649 image_rep,
650 SkShader::kRepeat_TileMode,
651 shader_scale,
652 pixel ? 1.0f : image_scale);
653
654 // Set up our paint to use the shader & release our reference (now just owned
655 // by the paint).
656 SkPaint p(paint);
657 p.setFilterBitmap(filter);
658 p.setShader(shader.get());
659
660 // The rect will be filled by the bitmap.
661 canvas_->drawRect(dest_rect, p);
662 }
663
590 } // namespace gfx 664 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/gfx/nine_image_painter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698