Chromium Code Reviews| 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/image/image_skia_operations.h" | 5 #include "ui/gfx/image/image_skia_operations.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "skia/ext/image_operations.h" | 9 #include "skia/ext/image_operations.h" |
| 10 #include "ui/base/layout.h" | 10 #include "ui/base/layout.h" |
| 11 #include "ui/gfx/canvas.h" | 11 #include "ui/gfx/canvas.h" |
| 12 #include "ui/gfx/image/canvas_image_source.h" | 12 #include "ui/gfx/image/canvas_image_source.h" |
| 13 #include "ui/gfx/image/image_skia.h" | 13 #include "ui/gfx/image/image_skia.h" |
| 14 #include "ui/gfx/image/image_skia_rep.h" | 14 #include "ui/gfx/image/image_skia_rep.h" |
| 15 #include "ui/gfx/image/image_skia_source.h" | 15 #include "ui/gfx/image/image_skia_source.h" |
| 16 #include "ui/gfx/insets.h" | 16 #include "ui/gfx/insets.h" |
| 17 #include "ui/gfx/point.h" | |
| 18 #include "ui/gfx/point_conversions.h" | |
| 17 #include "ui/gfx/rect.h" | 19 #include "ui/gfx/rect.h" |
| 18 #include "ui/gfx/rect_conversions.h" | 20 #include "ui/gfx/rect_conversions.h" |
| 19 #include "ui/gfx/size.h" | 21 #include "ui/gfx/size.h" |
| 20 #include "ui/gfx/size_conversions.h" | 22 #include "ui/gfx/size_conversions.h" |
| 21 #include "ui/gfx/skbitmap_operations.h" | 23 #include "ui/gfx/skbitmap_operations.h" |
| 22 #include "ui/gfx/skia_util.h" | 24 #include "ui/gfx/skia_util.h" |
| 23 | 25 |
| 24 namespace gfx { | 26 namespace gfx { |
| 25 namespace { | 27 namespace { |
| 26 | 28 |
| 29 gfx::Rect DIPToPixelBounds(gfx::Rect dip_bounds, float scale) { | |
| 30 return ToEnclosingRect(ScaleRect(dip_bounds, scale)); | |
| 31 } | |
| 32 | |
| 33 gfx::Size DIPToPixelSize(gfx::Size dip_size, float scale) { | |
| 34 return ToCeiledSize(ScaleSize(dip_size, scale)); | |
| 35 } | |
| 36 | |
| 37 ImageSkiaRep CropBitmap(ImageSkiaRep& source, gfx::Rect& bounds) { | |
|
pkotwicz
2013/03/13 04:03:48
Nit: Rename to CropImageSkiaRep
Rename |bound
kevers
2013/03/13 14:36:59
Done.
| |
| 38 SkBitmap result; | |
| 39 bool success = source.sk_bitmap().extractSubset(&result, | |
| 40 RectToSkIRect(bounds)); | |
| 41 DCHECK(success); | |
| 42 return ImageSkiaRep(result, source.scale_factor()); | |
| 43 } | |
| 44 | |
| 27 // Returns an image rep for the ImageSkiaSource to return to visually indicate | 45 // Returns an image rep for the ImageSkiaSource to return to visually indicate |
| 28 // an error. | 46 // an error. |
| 29 ImageSkiaRep GetErrorImageRep(ui::ScaleFactor scale_factor, | 47 ImageSkiaRep GetErrorImageRep(ui::ScaleFactor scale_factor, |
| 30 const gfx::Size& pixel_size) { | 48 const gfx::Size& pixel_size) { |
| 31 SkBitmap bitmap; | 49 SkBitmap bitmap; |
| 32 bitmap.setConfig( | 50 bitmap.setConfig( |
| 33 SkBitmap::kARGB_8888_Config, pixel_size.width(), pixel_size.height()); | 51 SkBitmap::kARGB_8888_Config, pixel_size.width(), pixel_size.height()); |
| 34 bitmap.allocPixels(); | 52 bitmap.allocPixels(); |
| 35 bitmap.eraseColor(SK_ColorRED); | 53 bitmap.eraseColor(SK_ColorRED); |
| 36 return gfx::ImageSkiaRep(bitmap, scale_factor); | 54 return gfx::ImageSkiaRep(bitmap, scale_factor); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 47 second_(second), | 65 second_(second), |
| 48 source_name_(source_name) { | 66 source_name_(source_name) { |
| 49 } | 67 } |
| 50 virtual ~BinaryImageSource() { | 68 virtual ~BinaryImageSource() { |
| 51 } | 69 } |
| 52 | 70 |
| 53 // gfx::ImageSkiaSource overrides: | 71 // gfx::ImageSkiaSource overrides: |
| 54 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 72 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| 55 ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor); | 73 ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor); |
| 56 ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor); | 74 ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor); |
| 57 if (first_rep.pixel_size() != second_rep.pixel_size()) { | 75 gfx::Size first_size = first_rep.pixel_size(); |
| 76 gfx::Size second_size = second_rep.pixel_size(); | |
| 77 // Allow for maximum of 1 pixel mismatch due to rounding errors. | |
|
pkotwicz
2013/03/13 04:03:48
Nit: "due to rounding errors because of a fraction
kevers
2013/03/13 14:36:59
Done.
| |
| 78 int dw = first_size.width() - second_size.width(); | |
| 79 int dh = first_size.height() - second_size.height(); | |
| 80 if (abs(dw) > 1 || abs(dh) > 1) { | |
| 58 DCHECK_NE(first_rep.scale_factor(), second_rep.scale_factor()); | 81 DCHECK_NE(first_rep.scale_factor(), second_rep.scale_factor()); |
| 59 if (first_rep.scale_factor() == second_rep.scale_factor()) { | 82 if (first_rep.scale_factor() == second_rep.scale_factor()) { |
| 60 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; | 83 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; |
| 61 return GetErrorImageRep(first_rep.scale_factor(), | 84 return GetErrorImageRep(first_rep.scale_factor(), |
| 62 first_rep.pixel_size()); | 85 first_rep.pixel_size()); |
| 63 } | 86 } |
| 64 first_rep = first_.GetRepresentation(ui::SCALE_FACTOR_100P); | 87 first_rep = first_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| 65 second_rep = second_.GetRepresentation(ui::SCALE_FACTOR_100P); | 88 second_rep = second_.GetRepresentation(ui::SCALE_FACTOR_100P); |
| 66 DCHECK_EQ(first_rep.pixel_width(), second_rep.pixel_width()); | 89 first_size = first_rep.pixel_size(); |
| 67 DCHECK_EQ(first_rep.pixel_height(), second_rep.pixel_height()); | 90 second_size = second_rep.pixel_size(); |
| 68 if (first_rep.pixel_size() != second_rep.pixel_size()) { | 91 dw = first_size.width() - second_size.width(); |
| 92 dh = first_size.height() - second_size.height(); | |
|
pkotwicz
2013/03/13 04:03:48
Use ImageSkiaRep::pixel_width() and ImageSkiaRep::
kevers
2013/03/13 14:36:59
Done.
| |
| 93 DCHECK_LE(abs(dw), 1); | |
| 94 DCHECK_LE(abs(dh), 1); | |
| 95 if (abs(dw) > 1 || abs(dh) > 1) { | |
| 69 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; | 96 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; |
| 70 return GetErrorImageRep(first_rep.scale_factor(), | 97 return GetErrorImageRep(first_rep.scale_factor(), |
| 71 first_rep.pixel_size()); | 98 first_rep.pixel_size()); |
| 72 } | 99 } |
| 73 } else { | 100 } else { |
| 74 DCHECK_EQ(first_rep.scale_factor(), second_rep.scale_factor()); | 101 DCHECK_EQ(first_rep.scale_factor(), second_rep.scale_factor()); |
| 75 } | 102 } |
| 103 if (dw || dh) { | |
| 104 gfx::Rect bounds = IntersectRects(Rect(first_size), Rect(second_size)); | |
| 105 first_rep = CropBitmap(first_rep, bounds); | |
| 106 second_rep = CropBitmap(second_rep, bounds); | |
| 107 } | |
| 76 return CreateImageSkiaRep(first_rep, second_rep); | 108 return CreateImageSkiaRep(first_rep, second_rep); |
| 77 } | 109 } |
| 78 | 110 |
| 79 // Creates a final image from two ImageSkiaReps. The pixel size of | 111 // Creates a final image from two ImageSkiaReps. The pixel size of |
| 80 // the two images are guaranteed to be the same. | 112 // the two images are guaranteed to be the same. |
| 81 virtual ImageSkiaRep CreateImageSkiaRep( | 113 virtual ImageSkiaRep CreateImageSkiaRep( |
| 82 const ImageSkiaRep& first_rep, | 114 const ImageSkiaRep& first_rep, |
| 83 const ImageSkiaRep& second_rep) const = 0; | 115 const ImageSkiaRep& second_rep) const = 0; |
| 84 | 116 |
| 85 private: | 117 private: |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 dst_h_(dst_h) { | 241 dst_h_(dst_h) { |
| 210 } | 242 } |
| 211 | 243 |
| 212 virtual ~TiledImageSource() { | 244 virtual ~TiledImageSource() { |
| 213 } | 245 } |
| 214 | 246 |
| 215 // gfx::ImageSkiaSource overrides: | 247 // gfx::ImageSkiaSource overrides: |
| 216 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 248 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| 217 ImageSkiaRep source_rep = source_.GetRepresentation(scale_factor); | 249 ImageSkiaRep source_rep = source_.GetRepresentation(scale_factor); |
| 218 float scale = ui::GetScaleFactorScale(source_rep.scale_factor()); | 250 float scale = ui::GetScaleFactorScale(source_rep.scale_factor()); |
| 251 gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_, | |
| 252 dst_h_), scale); | |
|
pkotwicz
2013/03/13 04:03:48
ToEnclosingRect() does something different than us
kevers
2013/03/13 14:36:59
The size resulting from using ToEnclosingRect is a
| |
| 219 return ImageSkiaRep( | 253 return ImageSkiaRep( |
| 220 SkBitmapOperations::CreateTiledBitmap( | 254 SkBitmapOperations::CreateTiledBitmap( |
| 221 source_rep.sk_bitmap(), | 255 source_rep.sk_bitmap(), |
| 222 src_x_ * scale, src_y_ * scale, dst_w_ * scale, dst_h_ * scale), | 256 bounds.x(), bounds.y(), bounds.width(), bounds.height()), |
| 223 source_rep.scale_factor()); | 257 source_rep.scale_factor()); |
| 224 } | 258 } |
| 225 | 259 |
| 226 private: | 260 private: |
| 227 const ImageSkia source_; | 261 const ImageSkia source_; |
| 228 const int src_x_; | 262 const int src_x_; |
| 229 const int src_y_; | 263 const int src_y_; |
| 230 const int dst_w_; | 264 const int dst_w_; |
| 231 const int dst_h_; | 265 const int dst_h_; |
| 232 | 266 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 253 } | 287 } |
| 254 | 288 |
| 255 private: | 289 private: |
| 256 const gfx::ImageSkia image_; | 290 const gfx::ImageSkia image_; |
| 257 const color_utils::HSL hsl_shift_; | 291 const color_utils::HSL hsl_shift_; |
| 258 DISALLOW_COPY_AND_ASSIGN(HSLImageSource); | 292 DISALLOW_COPY_AND_ASSIGN(HSLImageSource); |
| 259 }; | 293 }; |
| 260 | 294 |
| 261 // ImageSkiaSource which uses SkBitmapOperations::CreateButtonBackground | 295 // ImageSkiaSource which uses SkBitmapOperations::CreateButtonBackground |
| 262 // to generate image reps for the target image. | 296 // to generate image reps for the target image. |
| 263 class ButtonImageSource: public gfx::ImageSkiaSource { | 297 class ButtonImageSource: public BinaryImageSource { |
| 264 public: | 298 public: |
| 265 ButtonImageSource(SkColor color, | 299 ButtonImageSource(SkColor color, |
| 266 const ImageSkia& image, | 300 const ImageSkia& image, |
| 267 const ImageSkia& mask) | 301 const ImageSkia& mask) |
| 268 : color_(color), | 302 : BinaryImageSource(image, mask, "ButtonImageSource"), |
| 269 image_(image), | 303 color_(color) { |
| 270 mask_(mask) { | |
| 271 } | 304 } |
| 272 | 305 |
| 273 virtual ~ButtonImageSource() { | 306 virtual ~ButtonImageSource() { |
| 274 } | 307 } |
| 275 | 308 |
| 276 // gfx::ImageSkiaSource overrides: | 309 // BinaryImageSource overrides: |
| 277 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 310 virtual ImageSkiaRep CreateImageSkiaRep( |
| 278 ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); | 311 const ImageSkiaRep& first_rep, |
| 279 ImageSkiaRep mask_rep = mask_.GetRepresentation(scale_factor); | 312 const ImageSkiaRep& second_rep) const OVERRIDE { |
| 280 if (image_rep.scale_factor() != mask_rep.scale_factor()) { | |
| 281 image_rep = image_.GetRepresentation(ui::SCALE_FACTOR_100P); | |
| 282 mask_rep = mask_.GetRepresentation(ui::SCALE_FACTOR_100P); | |
| 283 } | |
| 284 return gfx::ImageSkiaRep( | 313 return gfx::ImageSkiaRep( |
| 285 SkBitmapOperations::CreateButtonBackground(color_, | 314 SkBitmapOperations::CreateButtonBackground(color_, |
| 286 image_rep.sk_bitmap(), mask_rep.sk_bitmap()), | 315 first_rep.sk_bitmap(), second_rep.sk_bitmap()), |
| 287 image_rep.scale_factor()); | 316 first_rep.scale_factor()); |
| 288 } | 317 } |
| 289 | 318 |
| 290 private: | 319 private: |
| 291 const SkColor color_; | 320 const SkColor color_; |
| 292 const ImageSkia image_; | |
| 293 const ImageSkia mask_; | |
| 294 | 321 |
| 295 DISALLOW_COPY_AND_ASSIGN(ButtonImageSource); | 322 DISALLOW_COPY_AND_ASSIGN(ButtonImageSource); |
| 296 }; | 323 }; |
| 297 | 324 |
| 298 // ImageSkiaSource which uses SkBitmap::extractSubset to generate image reps | 325 // ImageSkiaSource which uses SkBitmap::extractSubset to generate image reps |
| 299 // for the target image. | 326 // for the target image. |
| 300 class ExtractSubsetImageSource: public gfx::ImageSkiaSource { | 327 class ExtractSubsetImageSource: public gfx::ImageSkiaSource { |
| 301 public: | 328 public: |
| 302 ExtractSubsetImageSource(const gfx::ImageSkia& image, | 329 ExtractSubsetImageSource(const gfx::ImageSkia& image, |
| 303 const gfx::Rect& subset_bounds) | 330 const gfx::Rect& subset_bounds) |
| 304 : image_(image), | 331 : image_(image), |
| 305 subset_bounds_(subset_bounds) { | 332 subset_bounds_(subset_bounds) { |
| 306 } | 333 } |
| 307 | 334 |
| 308 virtual ~ExtractSubsetImageSource() { | 335 virtual ~ExtractSubsetImageSource() { |
| 309 } | 336 } |
| 310 | 337 |
| 311 // gfx::ImageSkiaSource overrides: | 338 // gfx::ImageSkiaSource overrides: |
| 312 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 339 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| 313 ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); | 340 ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); |
| 314 float scale_to_pixel = ui::GetScaleFactorScale(image_rep.scale_factor()); | 341 float scale_to_pixel = ui::GetScaleFactorScale(image_rep.scale_factor()); |
| 315 SkIRect subset_bounds_in_pixel = RectToSkIRect(ToFlooredRectDeprecated( | 342 Rect subset_bounds_in_pixel = DIPToPixelBounds(subset_bounds_, |
| 316 gfx::ScaleRect(subset_bounds_, scale_to_pixel))); | 343 scale_to_pixel); |
| 317 SkBitmap dst; | 344 return CropBitmap(image_rep, subset_bounds_in_pixel); |
| 318 bool success = image_rep.sk_bitmap().extractSubset(&dst, | |
| 319 subset_bounds_in_pixel); | |
| 320 DCHECK(success); | |
| 321 return gfx::ImageSkiaRep(dst, image_rep.scale_factor()); | |
| 322 } | 345 } |
| 323 | 346 |
| 324 private: | 347 private: |
| 325 const gfx::ImageSkia image_; | 348 const gfx::ImageSkia image_; |
| 326 const gfx::Rect subset_bounds_; | 349 const gfx::Rect subset_bounds_; |
| 327 | 350 |
| 328 DISALLOW_COPY_AND_ASSIGN(ExtractSubsetImageSource); | 351 DISALLOW_COPY_AND_ASSIGN(ExtractSubsetImageSource); |
| 329 }; | 352 }; |
| 330 | 353 |
| 331 // ResizeSource resizes relevant image reps in |source| to |target_dip_size| | 354 // ResizeSource resizes relevant image reps in |source| to |target_dip_size| |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 342 virtual ~ResizeSource() {} | 365 virtual ~ResizeSource() {} |
| 343 | 366 |
| 344 // gfx::ImageSkiaSource overrides: | 367 // gfx::ImageSkiaSource overrides: |
| 345 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 368 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
| 346 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale_factor); | 369 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale_factor); |
| 347 if (image_rep.GetWidth() == target_dip_size_.width() && | 370 if (image_rep.GetWidth() == target_dip_size_.width() && |
| 348 image_rep.GetHeight() == target_dip_size_.height()) | 371 image_rep.GetHeight() == target_dip_size_.height()) |
| 349 return image_rep; | 372 return image_rep; |
| 350 | 373 |
| 351 const float scale = ui::GetScaleFactorScale(scale_factor); | 374 const float scale = ui::GetScaleFactorScale(scale_factor); |
| 352 const Size target_pixel_size = gfx::ToFlooredSize( | 375 const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale); |
| 353 gfx::ScaleSize(target_dip_size_, scale)); | |
| 354 const SkBitmap resized = skia::ImageOperations::Resize( | 376 const SkBitmap resized = skia::ImageOperations::Resize( |
| 355 image_rep.sk_bitmap(), | 377 image_rep.sk_bitmap(), |
| 356 resize_method_, | 378 resize_method_, |
| 357 target_pixel_size.width(), | 379 target_pixel_size.width(), |
| 358 target_pixel_size.height()); | 380 target_pixel_size.height()); |
| 359 return ImageSkiaRep(resized, scale_factor); | 381 return ImageSkiaRep(resized, scale_factor); |
| 360 } | 382 } |
| 361 | 383 |
| 362 private: | 384 private: |
| 363 const ImageSkia source_; | 385 const ImageSkia source_; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 545 return ImageSkia(); | 567 return ImageSkia(); |
| 546 | 568 |
| 547 return ImageSkia(new RotatedSource(source, rotation), | 569 return ImageSkia(new RotatedSource(source, rotation), |
| 548 SkBitmapOperations::ROTATION_180_CW == rotation ? | 570 SkBitmapOperations::ROTATION_180_CW == rotation ? |
| 549 source.size() : | 571 source.size() : |
| 550 gfx::Size(source.height(), source.width())); | 572 gfx::Size(source.height(), source.width())); |
| 551 | 573 |
| 552 } | 574 } |
| 553 | 575 |
| 554 } // namespace gfx | 576 } // namespace gfx |
| OLD | NEW |