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" |
(...skipping 18 matching lines...) Expand all Loading... |
29 static bool scale_images = CommandLine::ForCurrentProcess()->HasSwitch( | 29 static bool scale_images = CommandLine::ForCurrentProcess()->HasSwitch( |
30 switches::kEnableScalingInImageSkiaOperations); | 30 switches::kEnableScalingInImageSkiaOperations); |
31 return scale_images; | 31 return scale_images; |
32 } | 32 } |
33 | 33 |
34 // Creates 2x scaled image of the give |source|. | 34 // Creates 2x scaled image of the give |source|. |
35 ImageSkiaRep Create2XImageSkiaRep(const ImageSkiaRep& source) { | 35 ImageSkiaRep Create2XImageSkiaRep(const ImageSkiaRep& source) { |
36 gfx::Size size(source.GetWidth() * 2.0f, source.GetHeight() * 2.0f); | 36 gfx::Size size(source.GetWidth() * 2.0f, source.GetHeight() * 2.0f); |
37 | 37 |
38 SkBitmap resized_bitmap; | 38 SkBitmap resized_bitmap; |
39 resized_bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), | 39 resized_bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), |
40 size.height()); | 40 size.height()); |
41 if (!resized_bitmap.allocPixels()) | 41 if (!resized_bitmap.allocPixels()) |
42 SK_CRASH(); | 42 SK_CRASH(); |
43 SkCanvas canvas(resized_bitmap); | 43 SkCanvas canvas(resized_bitmap); |
44 SkRect resized_bounds = RectToSkRect(gfx::Rect(size)); | 44 SkRect resized_bounds = RectToSkRect(gfx::Rect(size)); |
45 canvas.drawBitmapRect(source.sk_bitmap(), NULL, resized_bounds); | 45 canvas.drawBitmapRect(source.sk_bitmap(), NULL, resized_bounds); |
46 return ImageSkiaRep(resized_bitmap, ui::SCALE_FACTOR_200P); | 46 return ImageSkiaRep(resized_bitmap, ui::SCALE_FACTOR_200P); |
47 } | 47 } |
48 | 48 |
49 // A utility function to synchronize the scale factor of the two images. | 49 // A utility function to synchronize the scale factor of the two images. |
50 // When the command line option "--disable-scaling-in-image-skia-operation" | 50 // When the command line option "--enable-scaling-in-image-skia-operation" |
51 // is provided, this function will fail if the scale factors of the two images | 51 // is not provided, this function will fail if the scale factors of the two |
52 // are different. This assumes that the platform only supports | 52 // image reps are different. This assumes that the platform only supports |
53 // 1x and 2x scale factors. | 53 // 1x and 2x scale factors. |
54 // TODO(oshima): Remove and replace this with plain CHECK once | 54 // TODO(oshima): Remove and replace this with plain CHECK once |
55 // 2x images for all resources are provided. | 55 // 2x images for all resources are provided. |
56 void MatchScale(ImageSkiaRep* first, ImageSkiaRep* second) { | 56 void MatchScale(ImageSkiaRep* first, ImageSkiaRep* second) { |
57 if (first->scale_factor() != second->scale_factor()) { | 57 if (first->scale_factor() != second->scale_factor()) { |
58 CHECK(ScalingEnabled()); | 58 CHECK(ScalingEnabled()); |
59 ImageSkiaRep* target = NULL; | 59 ImageSkiaRep* target = NULL; |
60 if (first->scale_factor() == ui::SCALE_FACTOR_100P) { | 60 if (first->scale_factor() == ui::SCALE_FACTOR_100P) { |
61 target = first; | 61 target = first; |
62 } else { | 62 } else { |
63 target = second; | 63 target = second; |
64 } | 64 } |
65 *target = Create2XImageSkiaRep(*target); | 65 *target = Create2XImageSkiaRep(*target); |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
| 69 // Returns an image rep for the ImageSkiaSource to return to visually indicate |
| 70 // an error. |
| 71 ImageSkiaRep GetErrorImageRep(ui::ScaleFactor scale_factor) { |
| 72 SkBitmap bitmap; |
| 73 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32, 32); |
| 74 bitmap.allocPixels(); |
| 75 bitmap.eraseColor(SK_ColorRED); |
| 76 return gfx::ImageSkiaRep(bitmap, scale_factor); |
| 77 } |
| 78 |
69 class BlendingImageSource : public gfx::ImageSkiaSource { | 79 class BlendingImageSource : public gfx::ImageSkiaSource { |
70 public: | 80 public: |
71 BlendingImageSource(const ImageSkia& first, | 81 BlendingImageSource(const ImageSkia& first, |
72 const ImageSkia& second, | 82 const ImageSkia& second, |
73 double alpha) | 83 double alpha) |
74 : first_(first), | 84 : first_(first), |
75 second_(second), | 85 second_(second), |
76 alpha_(alpha) { | 86 alpha_(alpha) { |
77 } | 87 } |
78 | 88 |
79 virtual ~BlendingImageSource() { | 89 virtual ~BlendingImageSource() { |
80 } | 90 } |
81 | 91 |
82 // gfx::ImageSkiaSource overrides: | 92 // gfx::ImageSkiaSource overrides: |
83 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 93 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
84 ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor); | 94 ImageSkiaRep first_rep = first_.GetRepresentation(scale_factor); |
85 ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor); | 95 ImageSkiaRep second_rep = second_.GetRepresentation(scale_factor); |
86 MatchScale(&first_rep, &second_rep); | 96 MatchScale(&first_rep, &second_rep); |
| 97 |
| 98 // It is possible for the sizes to be different because the sizes of the |
| 99 // image reps do not have to be related to the sizes of the containing |
| 100 // ImageSkias. |
| 101 if (first_rep.pixel_size() != second_rep.pixel_size()) { |
| 102 LOG(ERROR) << "ImageSkiaRep size mismatch in BlendingImageSource"; |
| 103 return GetErrorImageRep(scale_factor); |
| 104 } |
| 105 |
87 SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap( | 106 SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap( |
88 first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_); | 107 first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_); |
89 return ImageSkiaRep(blended, first_rep.scale_factor()); | 108 return ImageSkiaRep(blended, first_rep.scale_factor()); |
90 } | 109 } |
91 | 110 |
92 private: | 111 private: |
93 const ImageSkia first_; | 112 const ImageSkia first_; |
94 const ImageSkia second_; | 113 const ImageSkia second_; |
95 double alpha_; | 114 double alpha_; |
96 | 115 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 alpha_(alpha) { | 179 alpha_(alpha) { |
161 } | 180 } |
162 | 181 |
163 virtual ~MaskedImageSource() { | 182 virtual ~MaskedImageSource() { |
164 } | 183 } |
165 | 184 |
166 // gfx::ImageSkiaSource overrides: | 185 // gfx::ImageSkiaSource overrides: |
167 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 186 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
168 ImageSkiaRep rgb_rep = rgb_.GetRepresentation(scale_factor); | 187 ImageSkiaRep rgb_rep = rgb_.GetRepresentation(scale_factor); |
169 ImageSkiaRep alpha_rep = alpha_.GetRepresentation(scale_factor); | 188 ImageSkiaRep alpha_rep = alpha_.GetRepresentation(scale_factor); |
170 CHECK_EQ(rgb_rep.pixel_width(), alpha_rep.pixel_width()); | 189 if (rgb_rep.pixel_size() != alpha_rep.pixel_size()) { |
171 CHECK_EQ(rgb_rep.pixel_height(), alpha_rep.pixel_height()); | 190 LOG(ERROR) << "ImageSkiaRep size mismatch in MaskedImageSource"; |
| 191 return GetErrorImageRep(scale_factor); |
| 192 } |
| 193 |
172 return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap( | 194 return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap( |
173 rgb_rep.sk_bitmap(), alpha_rep.sk_bitmap()), | 195 rgb_rep.sk_bitmap(), alpha_rep.sk_bitmap()), |
174 rgb_rep.scale_factor()); | 196 rgb_rep.scale_factor()); |
175 } | 197 } |
176 | 198 |
177 private: | 199 private: |
178 const ImageSkia rgb_; | 200 const ImageSkia rgb_; |
179 const ImageSkia alpha_; | 201 const ImageSkia alpha_; |
180 | 202 |
181 DISALLOW_COPY_AND_ASSIGN(MaskedImageSource); | 203 DISALLOW_COPY_AND_ASSIGN(MaskedImageSource); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 mask_(mask) { | 277 mask_(mask) { |
256 } | 278 } |
257 | 279 |
258 virtual ~ButtonImageSource() { | 280 virtual ~ButtonImageSource() { |
259 } | 281 } |
260 | 282 |
261 // gfx::ImageSkiaSource overrides: | 283 // gfx::ImageSkiaSource overrides: |
262 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { | 284 virtual ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) OVERRIDE { |
263 ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); | 285 ImageSkiaRep image_rep = image_.GetRepresentation(scale_factor); |
264 ImageSkiaRep mask_rep = mask_.GetRepresentation(scale_factor); | 286 ImageSkiaRep mask_rep = mask_.GetRepresentation(scale_factor); |
265 MatchScale(&image_rep, &mask_rep); | 287 if (image_rep.pixel_size() != mask_rep.pixel_size()) { |
| 288 LOG(ERROR) << "ImageSkiaRep size mismatch in ButtonImageSource"; |
| 289 return GetErrorImageRep(scale_factor); |
| 290 } |
| 291 |
266 return ImageSkiaRep( | 292 return ImageSkiaRep( |
267 SkBitmapOperations::CreateButtonBackground(color_, | 293 SkBitmapOperations::CreateButtonBackground(color_, |
268 image_rep.sk_bitmap(), mask_rep.sk_bitmap()), | 294 image_rep.sk_bitmap(), mask_rep.sk_bitmap()), |
269 image_rep.scale_factor()); | 295 image_rep.scale_factor()); |
270 } | 296 } |
271 | 297 |
272 private: | 298 private: |
273 const SkColor color_; | 299 const SkColor color_; |
274 const ImageSkia image_; | 300 const ImageSkia image_; |
275 const ImageSkia mask_; | 301 const ImageSkia mask_; |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 DISALLOW_COPY_AND_ASSIGN(RotatedSource); | 434 DISALLOW_COPY_AND_ASSIGN(RotatedSource); |
409 }; | 435 }; |
410 | 436 |
411 | 437 |
412 } // namespace | 438 } // namespace |
413 | 439 |
414 // static | 440 // static |
415 ImageSkia ImageSkiaOperations::CreateBlendedImage(const ImageSkia& first, | 441 ImageSkia ImageSkiaOperations::CreateBlendedImage(const ImageSkia& first, |
416 const ImageSkia& second, | 442 const ImageSkia& second, |
417 double alpha) { | 443 double alpha) { |
| 444 if (first.isNull() || second.isNull() || first.size() != second.size()) |
| 445 return ImageSkia(); |
| 446 |
418 return ImageSkia(new BlendingImageSource(first, second, alpha), first.size()); | 447 return ImageSkia(new BlendingImageSource(first, second, alpha), first.size()); |
419 } | 448 } |
420 | 449 |
421 // static | 450 // static |
422 ImageSkia ImageSkiaOperations::CreateSuperimposedImage( | 451 ImageSkia ImageSkiaOperations::CreateSuperimposedImage( |
423 const ImageSkia& first, | 452 const ImageSkia& first, |
424 const ImageSkia& second) { | 453 const ImageSkia& second) { |
| 454 if (first.isNull() || second.isNull()) |
| 455 return ImageSkia(); |
| 456 |
425 return ImageSkia(new SuperimposedImageSource(first, second), first.size()); | 457 return ImageSkia(new SuperimposedImageSource(first, second), first.size()); |
426 } | 458 } |
427 | 459 |
428 // static | 460 // static |
429 ImageSkia ImageSkiaOperations::CreateTransparentImage(const ImageSkia& image, | 461 ImageSkia ImageSkiaOperations::CreateTransparentImage(const ImageSkia& image, |
430 double alpha) { | 462 double alpha) { |
| 463 if (image.isNull()) |
| 464 return ImageSkia(); |
| 465 |
431 return ImageSkia(new TransparentImageSource(image, alpha), image.size()); | 466 return ImageSkia(new TransparentImageSource(image, alpha), image.size()); |
432 } | 467 } |
433 | 468 |
434 // static | 469 // static |
435 ImageSkia ImageSkiaOperations::CreateMaskedImage(const ImageSkia& rgb, | 470 ImageSkia ImageSkiaOperations::CreateMaskedImage(const ImageSkia& rgb, |
436 const ImageSkia& alpha) { | 471 const ImageSkia& alpha) { |
| 472 if (rgb.isNull() || alpha.isNull() || rgb.size() != alpha.size()) |
| 473 return ImageSkia(); |
| 474 |
437 return ImageSkia(new MaskedImageSource(rgb, alpha), rgb.size()); | 475 return ImageSkia(new MaskedImageSource(rgb, alpha), rgb.size()); |
438 } | 476 } |
439 | 477 |
440 // static | 478 // static |
441 ImageSkia ImageSkiaOperations::CreateTiledImage(const ImageSkia& source, | 479 ImageSkia ImageSkiaOperations::CreateTiledImage(const ImageSkia& source, |
442 int src_x, int src_y, | 480 int src_x, int src_y, |
443 int dst_w, int dst_h) { | 481 int dst_w, int dst_h) { |
| 482 if (source.isNull()) |
| 483 return ImageSkia(); |
| 484 |
444 return ImageSkia(new TiledImageSource(source, src_x, src_y, dst_w, dst_h), | 485 return ImageSkia(new TiledImageSource(source, src_x, src_y, dst_w, dst_h), |
445 gfx::Size(dst_w, dst_h)); | 486 gfx::Size(dst_w, dst_h)); |
446 } | 487 } |
447 | 488 |
448 // static | 489 // static |
449 ImageSkia ImageSkiaOperations::CreateHSLShiftedImage( | 490 ImageSkia ImageSkiaOperations::CreateHSLShiftedImage( |
450 const ImageSkia& image, | 491 const ImageSkia& image, |
451 const color_utils::HSL& hsl_shift) { | 492 const color_utils::HSL& hsl_shift) { |
| 493 if (image.isNull()) |
| 494 return ImageSkia(); |
| 495 |
452 return ImageSkia(new HSLImageSource(image, hsl_shift), image.size()); | 496 return ImageSkia(new HSLImageSource(image, hsl_shift), image.size()); |
453 } | 497 } |
454 | 498 |
455 // static | 499 // static |
456 ImageSkia ImageSkiaOperations::CreateButtonBackground(SkColor color, | 500 ImageSkia ImageSkiaOperations::CreateButtonBackground(SkColor color, |
457 const ImageSkia& image, | 501 const ImageSkia& image, |
458 const ImageSkia& mask) { | 502 const ImageSkia& mask) { |
| 503 if (image.isNull() || mask.isNull() || image.size() != mask.size()) |
| 504 return ImageSkia(); |
| 505 |
459 return ImageSkia(new ButtonImageSource(color, image, mask), mask.size()); | 506 return ImageSkia(new ButtonImageSource(color, image, mask), mask.size()); |
460 } | 507 } |
461 | 508 |
462 // static | 509 // static |
463 ImageSkia ImageSkiaOperations::ExtractSubset(const ImageSkia& image, | 510 ImageSkia ImageSkiaOperations::ExtractSubset(const ImageSkia& image, |
464 const Rect& subset_bounds) { | 511 const Rect& subset_bounds) { |
465 gfx::Rect clipped_bounds = | 512 gfx::Rect clipped_bounds = |
466 gfx::IntersectRects(subset_bounds, gfx::Rect(image.size())); | 513 gfx::IntersectRects(subset_bounds, gfx::Rect(image.size())); |
467 if (image.isNull() || clipped_bounds.IsEmpty()) { | 514 if (image.isNull() || clipped_bounds.IsEmpty()) { |
468 return ImageSkia(); | 515 return ImageSkia(); |
469 } | 516 } |
470 | 517 |
471 return ImageSkia(new ExtractSubsetImageSource(image, clipped_bounds), | 518 return ImageSkia(new ExtractSubsetImageSource(image, clipped_bounds), |
472 clipped_bounds.size()); | 519 clipped_bounds.size()); |
473 } | 520 } |
474 | 521 |
475 // static | 522 // static |
476 ImageSkia ImageSkiaOperations::CreateResizedImage( | 523 ImageSkia ImageSkiaOperations::CreateResizedImage( |
477 const ImageSkia& source, | 524 const ImageSkia& source, |
478 skia::ImageOperations::ResizeMethod method, | 525 skia::ImageOperations::ResizeMethod method, |
479 const Size& target_dip_size) { | 526 const Size& target_dip_size) { |
| 527 if (source.isNull()) |
| 528 return ImageSkia(); |
| 529 |
480 return ImageSkia(new ResizeSource(source, method, target_dip_size), | 530 return ImageSkia(new ResizeSource(source, method, target_dip_size), |
481 target_dip_size); | 531 target_dip_size); |
482 } | 532 } |
483 | 533 |
484 // static | 534 // static |
485 ImageSkia ImageSkiaOperations::CreateImageWithDropShadow( | 535 ImageSkia ImageSkiaOperations::CreateImageWithDropShadow( |
486 const ImageSkia& source, | 536 const ImageSkia& source, |
487 const ShadowValues& shadows) { | 537 const ShadowValues& shadows) { |
| 538 if (source.isNull()) |
| 539 return ImageSkia(); |
| 540 |
488 const gfx::Insets shadow_padding = -gfx::ShadowValue::GetMargin(shadows); | 541 const gfx::Insets shadow_padding = -gfx::ShadowValue::GetMargin(shadows); |
489 gfx::Size shadow_image_size = source.size(); | 542 gfx::Size shadow_image_size = source.size(); |
490 shadow_image_size.Enlarge(shadow_padding.width(), | 543 shadow_image_size.Enlarge(shadow_padding.width(), |
491 shadow_padding.height()); | 544 shadow_padding.height()); |
492 return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size); | 545 return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size); |
493 } | 546 } |
494 | 547 |
495 // static | 548 // static |
496 ImageSkia ImageSkiaOperations::CreateRotatedImage( | 549 ImageSkia ImageSkiaOperations::CreateRotatedImage( |
497 const ImageSkia& source, | 550 const ImageSkia& source, |
498 SkBitmapOperations::RotationAmount rotation) { | 551 SkBitmapOperations::RotationAmount rotation) { |
| 552 if (source.isNull()) |
| 553 return ImageSkia(); |
| 554 |
499 return ImageSkia(new RotatedSource(source, rotation), | 555 return ImageSkia(new RotatedSource(source, rotation), |
500 SkBitmapOperations::ROTATION_180_CW == rotation ? | 556 SkBitmapOperations::ROTATION_180_CW == rotation ? |
501 source.size() : | 557 source.size() : |
502 gfx::Size(source.height(), source.width())); | 558 gfx::Size(source.height(), source.width())); |
503 | 559 |
504 } | 560 } |
505 | 561 |
506 } // namespace gfx | 562 } // namespace gfx |
OLD | NEW |