Chromium Code Reviews| Index: ui/gfx/image/image_skia_operations.cc |
| diff --git a/ui/gfx/image/image_skia_operations.cc b/ui/gfx/image/image_skia_operations.cc |
| index 4b5612ea063bc1376556b58dee5e03e80b9ffe23..ec9fb47c67b29bb20ba700b88f81f5f989b76f18 100644 |
| --- a/ui/gfx/image/image_skia_operations.cc |
| +++ b/ui/gfx/image/image_skia_operations.cc |
| @@ -14,6 +14,8 @@ |
| #include "ui/gfx/image/image_skia_rep.h" |
| #include "ui/gfx/image/image_skia_source.h" |
| #include "ui/gfx/insets.h" |
| +#include "ui/gfx/point.h" |
| +#include "ui/gfx/point_conversions.h" |
| #include "ui/gfx/rect.h" |
| #include "ui/gfx/rect_conversions.h" |
| #include "ui/gfx/size.h" |
| @@ -24,6 +26,23 @@ |
| namespace gfx { |
| namespace { |
| +gfx::Rect DIPToPixelBounds(gfx::Rect dip_bounds, float scale) { |
| + return ToEnclosingRect(ScaleRect(dip_bounds, scale)); |
| +} |
| + |
| +gfx::Size DIPToPixelSize(gfx::Size dip_size, float scale) { |
| + return ToCeiledSize(ScaleSize(dip_size, scale)); |
| +} |
| + |
| +ImageSkiaRep CropImageSkiaRep(ImageSkiaRep& source, |
| + gfx::Rect& bounds_in_pixel) { |
| + SkBitmap result; |
| + bool success = source.sk_bitmap().extractSubset(&result, |
| + RectToSkIRect(bounds_in_pixel)); |
| + DCHECK(success); |
| + return ImageSkiaRep(result, source.scale_factor()); |
| +} |
| + |
| // Returns an image rep for the ImageSkiaSource to return to visually indicate |
| // an error. |
| ImageSkiaRep GetErrorImageRep(ui::ScaleFactor scale_factor, |
| @@ -54,7 +73,11 @@ class BinaryImageSource : public gfx::ImageSkiaSource { |
| virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor); |
| ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor); |
| - if (first_rep.pixel_size() != second_rep.pixel_size()) { |
| + // Allow for maximum of 1 pixel mismatch due to rounding errors when using |
| + // fractional scale factors. |
| + int dw = first_rep.pixel_width() - second_rep.pixel_width(); |
| + int dh = first_rep.pixel_height() - second_rep.pixel_height(); |
|
oshima
2013/03/13 14:47:52
drive-by question: where / in which process the ro
|
| + if (abs(dw) > 1 || abs(dh) > 1) { |
| DCHECK_NE(first_rep.scale_factor(), second_rep.scale_factor()); |
| if (first_rep.scale_factor() == second_rep.scale_factor()) { |
| LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; |
| @@ -63,9 +86,11 @@ class BinaryImageSource : public gfx::ImageSkiaSource { |
| } |
| first_rep = first_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| second_rep = second_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| - DCHECK_EQ(first_rep.pixel_width(), second_rep.pixel_width()); |
| - DCHECK_EQ(first_rep.pixel_height(), second_rep.pixel_height()); |
| - if (first_rep.pixel_size() != second_rep.pixel_size()) { |
| + dw = first_rep.pixel_width() - second_rep.pixel_width(); |
| + dh = first_rep.pixel_height() - second_rep.pixel_height(); |
| + DCHECK_LE(abs(dw), 1); |
| + DCHECK_LE(abs(dh), 1); |
| + if (abs(dw) > 1 || abs(dh) > 1) { |
| LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; |
| return GetErrorImageRep(first_rep.scale_factor(), |
| first_rep.pixel_size()); |
| @@ -73,6 +98,12 @@ class BinaryImageSource : public gfx::ImageSkiaSource { |
| } else { |
| DCHECK_EQ(first_rep.scale_factor(), second_rep.scale_factor()); |
| } |
| + if (dw || dh) { |
| + gfx::Rect bounds = IntersectRects(Rect(first_rep.pixel_size()), |
| + Rect(second_rep.pixel_size())); |
| + first_rep = CropImageSkiaRep(first_rep, bounds); |
| + second_rep = CropImageSkiaRep(second_rep, bounds); |
| + } |
| return CreateImageSkiaRep(first_rep, second_rep); |
| } |
| @@ -216,10 +247,12 @@ class TiledImageSource : public gfx::ImageSkiaSource { |
| virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| ImageSkiaRep source_rep = source_.GetRepresentation(scale_factor); |
| float scale = ui::GetScaleFactorScale(source_rep.scale_factor()); |
| + gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_, |
| + dst_h_), scale); |
| return ImageSkiaRep( |
| SkBitmapOperations::CreateTiledBitmap( |
| source_rep.sk_bitmap(), |
| - src_x_ * scale, src_y_ * scale, dst_w_ * scale, dst_h_ * scale), |
| + bounds.x(), bounds.y(), bounds.width(), bounds.height()), |
| source_rep.scale_factor()); |
| } |
| @@ -260,37 +293,30 @@ class HSLImageSource : public gfx::ImageSkiaSource { |
| // ImageSkiaSource which uses SkBitmapOperations::CreateButtonBackground |
| // to generate image reps for the target image. |
| -class ButtonImageSource: public gfx::ImageSkiaSource { |
| +class ButtonImageSource: public BinaryImageSource { |
| public: |
| ButtonImageSource(SkColor color, |
| const ImageSkia& image, |
| const ImageSkia& mask) |
| - : color_(color), |
| - image_(image), |
| - mask_(mask) { |
| + : BinaryImageSource(image, mask, "ButtonImageSource"), |
| + color_(color) { |
| } |
| virtual ~ButtonImageSource() { |
| } |
| - // gfx::ImageSkiaSource overrides: |
| - virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| - ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); |
| - ImageSkiaRep mask_rep = mask_.GetRepresentation(scale_factor); |
| - if (image_rep.scale_factor() != mask_rep.scale_factor()) { |
| - image_rep = image_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| - mask_rep = mask_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| - } |
| + // BinaryImageSource overrides: |
| + virtual ImageSkiaRep CreateImageSkiaRep( |
| + const ImageSkiaRep& first_rep, |
| + const ImageSkiaRep& second_rep) const OVERRIDE { |
| return gfx::ImageSkiaRep( |
| SkBitmapOperations::CreateButtonBackground(color_, |
| - image_rep.sk_bitmap(), mask_rep.sk_bitmap()), |
| - image_rep.scale_factor()); |
| + first_rep.sk_bitmap(), second_rep.sk_bitmap()), |
| + first_rep.scale_factor()); |
| } |
| private: |
| const SkColor color_; |
| - const ImageSkia image_; |
| - const ImageSkia mask_; |
| DISALLOW_COPY_AND_ASSIGN(ButtonImageSource); |
| }; |
| @@ -312,13 +338,9 @@ class ExtractSubsetImageSource: public gfx::ImageSkiaSource { |
| virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); |
| float scale_to_pixel = ui::GetScaleFactorScale(image_rep.scale_factor()); |
| - SkIRect subset_bounds_in_pixel = RectToSkIRect(ToFlooredRectDeprecated( |
| - gfx::ScaleRect(subset_bounds_, scale_to_pixel))); |
| - SkBitmap dst; |
| - bool success = image_rep.sk_bitmap().extractSubset(&dst, |
| - subset_bounds_in_pixel); |
| - DCHECK(success); |
| - return gfx::ImageSkiaRep(dst, image_rep.scale_factor()); |
| + Rect subset_bounds_in_pixel = DIPToPixelBounds(subset_bounds_, |
| + scale_to_pixel); |
| + return CropImageSkiaRep(image_rep, subset_bounds_in_pixel); |
| } |
| private: |
| @@ -349,8 +371,7 @@ class ResizeSource : public ImageSkiaSource { |
| return image_rep; |
| const float scale = ui::GetScaleFactorScale(scale_factor); |
| - const Size target_pixel_size = gfx::ToFlooredSize( |
| - gfx::ScaleSize(target_dip_size_, scale)); |
| + const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale); |
| const SkBitmap resized = skia::ImageOperations::Resize( |
| image_rep.sk_bitmap(), |
| resize_method_, |