| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ui/gfx/image/image_skia_operations.h" | |
| 6 | |
| 7 #include "base/command_line.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "skia/ext/image_operations.h" | |
| 10 #include "ui/gfx/canvas.h" | |
| 11 #include "ui/gfx/image/canvas_image_source.h" | |
| 12 #include "ui/gfx/image/image_skia.h" | |
| 13 #include "ui/gfx/image/image_skia_rep.h" | |
| 14 #include "ui/gfx/image/image_skia_source.h" | |
| 15 #include "ui/gfx/insets.h" | |
| 16 #include "ui/gfx/point.h" | |
| 17 #include "ui/gfx/point_conversions.h" | |
| 18 #include "ui/gfx/rect.h" | |
| 19 #include "ui/gfx/rect_conversions.h" | |
| 20 #include "ui/gfx/size.h" | |
| 21 #include "ui/gfx/size_conversions.h" | |
| 22 #include "ui/gfx/skbitmap_operations.h" | |
| 23 #include "ui/gfx/skia_util.h" | |
| 24 | |
| 25 namespace gfx { | |
| 26 namespace { | |
| 27 | |
| 28 gfx::Size DIPToPixelSize(gfx::Size dip_size, float scale) { | |
| 29 return ToCeiledSize(ScaleSize(dip_size, scale)); | |
| 30 } | |
| 31 | |
| 32 gfx::Rect DIPToPixelBounds(gfx::Rect dip_bounds, float scale) { | |
| 33 return gfx::Rect(ToFlooredPoint(ScalePoint(dip_bounds.origin(), scale)), | |
| 34 DIPToPixelSize(dip_bounds.size(), scale)); | |
| 35 } | |
| 36 | |
| 37 // Returns an image rep for the ImageSkiaSource to return to visually indicate | |
| 38 // an error. | |
| 39 ImageSkiaRep GetErrorImageRep(float scale, const gfx::Size& pixel_size) { | |
| 40 SkBitmap bitmap; | |
| 41 bitmap.allocN32Pixels(pixel_size.width(), pixel_size.height()); | |
| 42 bitmap.eraseColor(SK_ColorRED); | |
| 43 return gfx::ImageSkiaRep(bitmap, scale); | |
| 44 } | |
| 45 | |
| 46 // A base image source class that creates an image from two source images. | |
| 47 // This class guarantees that two ImageSkiaReps have have the same pixel size. | |
| 48 class BinaryImageSource : public gfx::ImageSkiaSource { | |
| 49 protected: | |
| 50 BinaryImageSource(const ImageSkia& first, | |
| 51 const ImageSkia& second, | |
| 52 const char* source_name) | |
| 53 : first_(first), | |
| 54 second_(second), | |
| 55 source_name_(source_name) { | |
| 56 } | |
| 57 ~BinaryImageSource() override {} | |
| 58 | |
| 59 // gfx::ImageSkiaSource overrides: | |
| 60 ImageSkiaRep GetImageForScale(float scale) override { | |
| 61 ImageSkiaRep first_rep = first_.GetRepresentation(scale); | |
| 62 ImageSkiaRep second_rep = second_.GetRepresentation(scale); | |
| 63 if (first_rep.pixel_size() != second_rep.pixel_size()) { | |
| 64 DCHECK_NE(first_rep.scale(), second_rep.scale()); | |
| 65 if (first_rep.scale() == second_rep.scale()) { | |
| 66 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; | |
| 67 return GetErrorImageRep(first_rep.scale(),first_rep.pixel_size()); | |
| 68 } | |
| 69 first_rep = first_.GetRepresentation(1.0f); | |
| 70 second_rep = second_.GetRepresentation(1.0f); | |
| 71 DCHECK_EQ(first_rep.pixel_width(), second_rep.pixel_width()); | |
| 72 DCHECK_EQ(first_rep.pixel_height(), second_rep.pixel_height()); | |
| 73 if (first_rep.pixel_size() != second_rep.pixel_size()) { | |
| 74 LOG(ERROR) << "ImageSkiaRep size mismatch in " << source_name_; | |
| 75 return GetErrorImageRep(first_rep.scale(), first_rep.pixel_size()); | |
| 76 } | |
| 77 } else { | |
| 78 DCHECK_EQ(first_rep.scale(), second_rep.scale()); | |
| 79 } | |
| 80 return CreateImageSkiaRep(first_rep, second_rep); | |
| 81 } | |
| 82 | |
| 83 // Creates a final image from two ImageSkiaReps. The pixel size of | |
| 84 // the two images are guaranteed to be the same. | |
| 85 virtual ImageSkiaRep CreateImageSkiaRep( | |
| 86 const ImageSkiaRep& first_rep, | |
| 87 const ImageSkiaRep& second_rep) const = 0; | |
| 88 | |
| 89 private: | |
| 90 const ImageSkia first_; | |
| 91 const ImageSkia second_; | |
| 92 // The name of a class that implements the BinaryImageSource. | |
| 93 // The subclass is responsible for managing the memory. | |
| 94 const char* source_name_; | |
| 95 | |
| 96 DISALLOW_COPY_AND_ASSIGN(BinaryImageSource); | |
| 97 }; | |
| 98 | |
| 99 class BlendingImageSource : public BinaryImageSource { | |
| 100 public: | |
| 101 BlendingImageSource(const ImageSkia& first, | |
| 102 const ImageSkia& second, | |
| 103 double alpha) | |
| 104 : BinaryImageSource(first, second, "BlendingImageSource"), | |
| 105 alpha_(alpha) { | |
| 106 } | |
| 107 | |
| 108 ~BlendingImageSource() override {} | |
| 109 | |
| 110 // BinaryImageSource overrides: | |
| 111 ImageSkiaRep CreateImageSkiaRep( | |
| 112 const ImageSkiaRep& first_rep, | |
| 113 const ImageSkiaRep& second_rep) const override { | |
| 114 SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap( | |
| 115 first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_); | |
| 116 return ImageSkiaRep(blended, first_rep.scale()); | |
| 117 } | |
| 118 | |
| 119 private: | |
| 120 double alpha_; | |
| 121 | |
| 122 DISALLOW_COPY_AND_ASSIGN(BlendingImageSource); | |
| 123 }; | |
| 124 | |
| 125 class SuperimposedImageSource : public gfx::CanvasImageSource { | |
| 126 public: | |
| 127 SuperimposedImageSource(const ImageSkia& first, | |
| 128 const ImageSkia& second) | |
| 129 : gfx::CanvasImageSource(first.size(), false /* is opaque */), | |
| 130 first_(first), | |
| 131 second_(second) { | |
| 132 } | |
| 133 | |
| 134 ~SuperimposedImageSource() override {} | |
| 135 | |
| 136 // gfx::CanvasImageSource override. | |
| 137 void Draw(Canvas* canvas) override { | |
| 138 canvas->DrawImageInt(first_, 0, 0); | |
| 139 canvas->DrawImageInt(second_, | |
| 140 (first_.width() - second_.width()) / 2, | |
| 141 (first_.height() - second_.height()) / 2); | |
| 142 } | |
| 143 | |
| 144 private: | |
| 145 const ImageSkia first_; | |
| 146 const ImageSkia second_; | |
| 147 | |
| 148 DISALLOW_COPY_AND_ASSIGN(SuperimposedImageSource); | |
| 149 }; | |
| 150 | |
| 151 class TransparentImageSource : public gfx::ImageSkiaSource { | |
| 152 public: | |
| 153 TransparentImageSource(const ImageSkia& image, double alpha) | |
| 154 : image_(image), | |
| 155 alpha_(alpha) { | |
| 156 } | |
| 157 | |
| 158 ~TransparentImageSource() override {} | |
| 159 | |
| 160 private: | |
| 161 // gfx::ImageSkiaSource overrides: | |
| 162 ImageSkiaRep GetImageForScale(float scale) override { | |
| 163 ImageSkiaRep image_rep = image_.GetRepresentation(scale); | |
| 164 SkBitmap alpha; | |
| 165 alpha.allocN32Pixels(image_rep.pixel_width(), | |
| 166 image_rep.pixel_height()); | |
| 167 alpha.eraseColor(SkColorSetARGB(alpha_ * 255, 0, 0, 0)); | |
| 168 return ImageSkiaRep( | |
| 169 SkBitmapOperations::CreateMaskedBitmap(image_rep.sk_bitmap(), alpha), | |
| 170 image_rep.scale()); | |
| 171 } | |
| 172 | |
| 173 ImageSkia image_; | |
| 174 double alpha_; | |
| 175 | |
| 176 DISALLOW_COPY_AND_ASSIGN(TransparentImageSource); | |
| 177 }; | |
| 178 | |
| 179 class MaskedImageSource : public BinaryImageSource { | |
| 180 public: | |
| 181 MaskedImageSource(const ImageSkia& rgb, const ImageSkia& alpha) | |
| 182 : BinaryImageSource(rgb, alpha, "MaskedImageSource") { | |
| 183 } | |
| 184 | |
| 185 ~MaskedImageSource() override {} | |
| 186 | |
| 187 // BinaryImageSource overrides: | |
| 188 ImageSkiaRep CreateImageSkiaRep( | |
| 189 const ImageSkiaRep& first_rep, | |
| 190 const ImageSkiaRep& second_rep) const override { | |
| 191 return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap( | |
| 192 first_rep.sk_bitmap(), second_rep.sk_bitmap()), | |
| 193 first_rep.scale()); | |
| 194 } | |
| 195 | |
| 196 private: | |
| 197 DISALLOW_COPY_AND_ASSIGN(MaskedImageSource); | |
| 198 }; | |
| 199 | |
| 200 class TiledImageSource : public gfx::ImageSkiaSource { | |
| 201 public: | |
| 202 TiledImageSource(const ImageSkia& source, | |
| 203 int src_x, int src_y, | |
| 204 int dst_w, int dst_h) | |
| 205 : source_(source), | |
| 206 src_x_(src_x), | |
| 207 src_y_(src_y), | |
| 208 dst_w_(dst_w), | |
| 209 dst_h_(dst_h) { | |
| 210 } | |
| 211 | |
| 212 ~TiledImageSource() override {} | |
| 213 | |
| 214 // gfx::ImageSkiaSource overrides: | |
| 215 ImageSkiaRep GetImageForScale(float scale) override { | |
| 216 ImageSkiaRep source_rep = source_.GetRepresentation(scale); | |
| 217 gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_, | |
| 218 dst_h_), source_rep.scale()); | |
| 219 return ImageSkiaRep( | |
| 220 SkBitmapOperations::CreateTiledBitmap( | |
| 221 source_rep.sk_bitmap(), | |
| 222 bounds.x(), bounds.y(), bounds.width(), bounds.height()), | |
| 223 source_rep.scale()); | |
| 224 } | |
| 225 | |
| 226 private: | |
| 227 const ImageSkia source_; | |
| 228 const int src_x_; | |
| 229 const int src_y_; | |
| 230 const int dst_w_; | |
| 231 const int dst_h_; | |
| 232 | |
| 233 DISALLOW_COPY_AND_ASSIGN(TiledImageSource); | |
| 234 }; | |
| 235 | |
| 236 class HSLImageSource : public gfx::ImageSkiaSource { | |
| 237 public: | |
| 238 HSLImageSource(const ImageSkia& image, | |
| 239 const color_utils::HSL& hsl_shift) | |
| 240 : image_(image), | |
| 241 hsl_shift_(hsl_shift) { | |
| 242 } | |
| 243 | |
| 244 ~HSLImageSource() override {} | |
| 245 | |
| 246 // gfx::ImageSkiaSource overrides: | |
| 247 ImageSkiaRep GetImageForScale(float scale) override { | |
| 248 ImageSkiaRep image_rep = image_.GetRepresentation(scale); | |
| 249 return gfx::ImageSkiaRep( | |
| 250 SkBitmapOperations::CreateHSLShiftedBitmap(image_rep.sk_bitmap(), | |
| 251 hsl_shift_), image_rep.scale()); | |
| 252 } | |
| 253 | |
| 254 private: | |
| 255 const gfx::ImageSkia image_; | |
| 256 const color_utils::HSL hsl_shift_; | |
| 257 DISALLOW_COPY_AND_ASSIGN(HSLImageSource); | |
| 258 }; | |
| 259 | |
| 260 // ImageSkiaSource which uses SkBitmapOperations::CreateButtonBackground | |
| 261 // to generate image reps for the target image. The image and mask can be | |
| 262 // diferent sizes (crbug.com/171725). | |
| 263 class ButtonImageSource: public gfx::ImageSkiaSource { | |
| 264 public: | |
| 265 ButtonImageSource(SkColor color, | |
| 266 const ImageSkia& image, | |
| 267 const ImageSkia& mask) | |
| 268 : color_(color), | |
| 269 image_(image), | |
| 270 mask_(mask) { | |
| 271 } | |
| 272 | |
| 273 ~ButtonImageSource() override {} | |
| 274 | |
| 275 // gfx::ImageSkiaSource overrides: | |
| 276 ImageSkiaRep GetImageForScale(float scale) override { | |
| 277 ImageSkiaRep image_rep = image_.GetRepresentation(scale); | |
| 278 ImageSkiaRep mask_rep = mask_.GetRepresentation(scale); | |
| 279 if (image_rep.scale() != mask_rep.scale()) { | |
| 280 image_rep = image_.GetRepresentation(1.0f); | |
| 281 mask_rep = mask_.GetRepresentation(1.0f); | |
| 282 } | |
| 283 return gfx::ImageSkiaRep( | |
| 284 SkBitmapOperations::CreateButtonBackground(color_, | |
| 285 image_rep.sk_bitmap(), mask_rep.sk_bitmap()), | |
| 286 image_rep.scale()); | |
| 287 } | |
| 288 | |
| 289 private: | |
| 290 const SkColor color_; | |
| 291 const ImageSkia image_; | |
| 292 const ImageSkia mask_; | |
| 293 | |
| 294 DISALLOW_COPY_AND_ASSIGN(ButtonImageSource); | |
| 295 }; | |
| 296 | |
| 297 // ImageSkiaSource which uses SkBitmap::extractSubset to generate image reps | |
| 298 // for the target image. | |
| 299 class ExtractSubsetImageSource: public gfx::ImageSkiaSource { | |
| 300 public: | |
| 301 ExtractSubsetImageSource(const gfx::ImageSkia& image, | |
| 302 const gfx::Rect& subset_bounds) | |
| 303 : image_(image), | |
| 304 subset_bounds_(subset_bounds) { | |
| 305 } | |
| 306 | |
| 307 ~ExtractSubsetImageSource() override {} | |
| 308 | |
| 309 // gfx::ImageSkiaSource overrides: | |
| 310 ImageSkiaRep GetImageForScale(float scale) override { | |
| 311 ImageSkiaRep image_rep = image_.GetRepresentation(scale); | |
| 312 SkIRect subset_bounds_in_pixel = RectToSkIRect( | |
| 313 DIPToPixelBounds(subset_bounds_, image_rep.scale())); | |
| 314 SkBitmap dst; | |
| 315 bool success = image_rep.sk_bitmap().extractSubset(&dst, | |
| 316 subset_bounds_in_pixel); | |
| 317 DCHECK(success); | |
| 318 return gfx::ImageSkiaRep(dst, image_rep.scale()); | |
| 319 } | |
| 320 | |
| 321 private: | |
| 322 const gfx::ImageSkia image_; | |
| 323 const gfx::Rect subset_bounds_; | |
| 324 | |
| 325 DISALLOW_COPY_AND_ASSIGN(ExtractSubsetImageSource); | |
| 326 }; | |
| 327 | |
| 328 // ResizeSource resizes relevant image reps in |source| to |target_dip_size| | |
| 329 // for requested scale factors. | |
| 330 class ResizeSource : public ImageSkiaSource { | |
| 331 public: | |
| 332 ResizeSource(const ImageSkia& source, | |
| 333 skia::ImageOperations::ResizeMethod method, | |
| 334 const Size& target_dip_size) | |
| 335 : source_(source), | |
| 336 resize_method_(method), | |
| 337 target_dip_size_(target_dip_size) { | |
| 338 } | |
| 339 ~ResizeSource() override {} | |
| 340 | |
| 341 // gfx::ImageSkiaSource overrides: | |
| 342 ImageSkiaRep GetImageForScale(float scale) override { | |
| 343 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); | |
| 344 if (image_rep.GetWidth() == target_dip_size_.width() && | |
| 345 image_rep.GetHeight() == target_dip_size_.height()) | |
| 346 return image_rep; | |
| 347 | |
| 348 const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale); | |
| 349 const SkBitmap resized = skia::ImageOperations::Resize( | |
| 350 image_rep.sk_bitmap(), | |
| 351 resize_method_, | |
| 352 target_pixel_size.width(), | |
| 353 target_pixel_size.height()); | |
| 354 return ImageSkiaRep(resized, scale); | |
| 355 } | |
| 356 | |
| 357 private: | |
| 358 const ImageSkia source_; | |
| 359 skia::ImageOperations::ResizeMethod resize_method_; | |
| 360 const Size target_dip_size_; | |
| 361 | |
| 362 DISALLOW_COPY_AND_ASSIGN(ResizeSource); | |
| 363 }; | |
| 364 | |
| 365 // DropShadowSource generates image reps with drop shadow for image reps in | |
| 366 // |source| that represent requested scale factors. | |
| 367 class DropShadowSource : public ImageSkiaSource { | |
| 368 public: | |
| 369 DropShadowSource(const ImageSkia& source, | |
| 370 const ShadowValues& shadows_in_dip) | |
| 371 : source_(source), | |
| 372 shaodws_in_dip_(shadows_in_dip) { | |
| 373 } | |
| 374 ~DropShadowSource() override {} | |
| 375 | |
| 376 // gfx::ImageSkiaSource overrides: | |
| 377 ImageSkiaRep GetImageForScale(float scale) override { | |
| 378 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); | |
| 379 | |
| 380 ShadowValues shadows_in_pixel; | |
| 381 for (size_t i = 0; i < shaodws_in_dip_.size(); ++i) | |
| 382 shadows_in_pixel.push_back(shaodws_in_dip_[i].Scale(scale)); | |
| 383 | |
| 384 const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow( | |
| 385 image_rep.sk_bitmap(), | |
| 386 shadows_in_pixel); | |
| 387 return ImageSkiaRep(shadow_bitmap, image_rep.scale()); | |
| 388 } | |
| 389 | |
| 390 private: | |
| 391 const ImageSkia source_; | |
| 392 const ShadowValues shaodws_in_dip_; | |
| 393 | |
| 394 DISALLOW_COPY_AND_ASSIGN(DropShadowSource); | |
| 395 }; | |
| 396 | |
| 397 // RotatedSource generates image reps that are rotations of those in | |
| 398 // |source| that represent requested scale factors. | |
| 399 class RotatedSource : public ImageSkiaSource { | |
| 400 public: | |
| 401 RotatedSource(const ImageSkia& source, | |
| 402 SkBitmapOperations::RotationAmount rotation) | |
| 403 : source_(source), | |
| 404 rotation_(rotation) { | |
| 405 } | |
| 406 ~RotatedSource() override {} | |
| 407 | |
| 408 // gfx::ImageSkiaSource overrides: | |
| 409 ImageSkiaRep GetImageForScale(float scale) override { | |
| 410 const ImageSkiaRep& image_rep = source_.GetRepresentation(scale); | |
| 411 const SkBitmap rotated_bitmap = | |
| 412 SkBitmapOperations::Rotate(image_rep.sk_bitmap(), rotation_); | |
| 413 return ImageSkiaRep(rotated_bitmap, image_rep.scale()); | |
| 414 } | |
| 415 | |
| 416 private: | |
| 417 const ImageSkia source_; | |
| 418 const SkBitmapOperations::RotationAmount rotation_; | |
| 419 | |
| 420 DISALLOW_COPY_AND_ASSIGN(RotatedSource); | |
| 421 }; | |
| 422 | |
| 423 | |
| 424 } // namespace | |
| 425 | |
| 426 // static | |
| 427 ImageSkia ImageSkiaOperations::CreateBlendedImage(const ImageSkia& first, | |
| 428 const ImageSkia& second, | |
| 429 double alpha) { | |
| 430 if (first.isNull() || second.isNull()) | |
| 431 return ImageSkia(); | |
| 432 | |
| 433 return ImageSkia(new BlendingImageSource(first, second, alpha), first.size()); | |
| 434 } | |
| 435 | |
| 436 // static | |
| 437 ImageSkia ImageSkiaOperations::CreateSuperimposedImage( | |
| 438 const ImageSkia& first, | |
| 439 const ImageSkia& second) { | |
| 440 if (first.isNull() || second.isNull()) | |
| 441 return ImageSkia(); | |
| 442 | |
| 443 return ImageSkia(new SuperimposedImageSource(first, second), first.size()); | |
| 444 } | |
| 445 | |
| 446 // static | |
| 447 ImageSkia ImageSkiaOperations::CreateTransparentImage(const ImageSkia& image, | |
| 448 double alpha) { | |
| 449 if (image.isNull()) | |
| 450 return ImageSkia(); | |
| 451 | |
| 452 return ImageSkia(new TransparentImageSource(image, alpha), image.size()); | |
| 453 } | |
| 454 | |
| 455 // static | |
| 456 ImageSkia ImageSkiaOperations::CreateMaskedImage(const ImageSkia& rgb, | |
| 457 const ImageSkia& alpha) { | |
| 458 if (rgb.isNull() || alpha.isNull()) | |
| 459 return ImageSkia(); | |
| 460 | |
| 461 return ImageSkia(new MaskedImageSource(rgb, alpha), rgb.size()); | |
| 462 } | |
| 463 | |
| 464 // static | |
| 465 ImageSkia ImageSkiaOperations::CreateTiledImage(const ImageSkia& source, | |
| 466 int src_x, int src_y, | |
| 467 int dst_w, int dst_h) { | |
| 468 if (source.isNull()) | |
| 469 return ImageSkia(); | |
| 470 | |
| 471 return ImageSkia(new TiledImageSource(source, src_x, src_y, dst_w, dst_h), | |
| 472 gfx::Size(dst_w, dst_h)); | |
| 473 } | |
| 474 | |
| 475 // static | |
| 476 ImageSkia ImageSkiaOperations::CreateHSLShiftedImage( | |
| 477 const ImageSkia& image, | |
| 478 const color_utils::HSL& hsl_shift) { | |
| 479 if (image.isNull()) | |
| 480 return ImageSkia(); | |
| 481 | |
| 482 return ImageSkia(new HSLImageSource(image, hsl_shift), image.size()); | |
| 483 } | |
| 484 | |
| 485 // static | |
| 486 ImageSkia ImageSkiaOperations::CreateButtonBackground(SkColor color, | |
| 487 const ImageSkia& image, | |
| 488 const ImageSkia& mask) { | |
| 489 if (image.isNull() || mask.isNull()) | |
| 490 return ImageSkia(); | |
| 491 | |
| 492 return ImageSkia(new ButtonImageSource(color, image, mask), mask.size()); | |
| 493 } | |
| 494 | |
| 495 // static | |
| 496 ImageSkia ImageSkiaOperations::ExtractSubset(const ImageSkia& image, | |
| 497 const Rect& subset_bounds) { | |
| 498 gfx::Rect clipped_bounds = | |
| 499 gfx::IntersectRects(subset_bounds, gfx::Rect(image.size())); | |
| 500 if (image.isNull() || clipped_bounds.IsEmpty()) { | |
| 501 return ImageSkia(); | |
| 502 } | |
| 503 | |
| 504 return ImageSkia(new ExtractSubsetImageSource(image, clipped_bounds), | |
| 505 clipped_bounds.size()); | |
| 506 } | |
| 507 | |
| 508 // static | |
| 509 ImageSkia ImageSkiaOperations::CreateResizedImage( | |
| 510 const ImageSkia& source, | |
| 511 skia::ImageOperations::ResizeMethod method, | |
| 512 const Size& target_dip_size) { | |
| 513 if (source.isNull()) | |
| 514 return ImageSkia(); | |
| 515 | |
| 516 return ImageSkia(new ResizeSource(source, method, target_dip_size), | |
| 517 target_dip_size); | |
| 518 } | |
| 519 | |
| 520 // static | |
| 521 ImageSkia ImageSkiaOperations::CreateImageWithDropShadow( | |
| 522 const ImageSkia& source, | |
| 523 const ShadowValues& shadows) { | |
| 524 if (source.isNull()) | |
| 525 return ImageSkia(); | |
| 526 | |
| 527 const gfx::Insets shadow_padding = -gfx::ShadowValue::GetMargin(shadows); | |
| 528 gfx::Size shadow_image_size = source.size(); | |
| 529 shadow_image_size.Enlarge(shadow_padding.width(), | |
| 530 shadow_padding.height()); | |
| 531 return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size); | |
| 532 } | |
| 533 | |
| 534 // static | |
| 535 ImageSkia ImageSkiaOperations::CreateRotatedImage( | |
| 536 const ImageSkia& source, | |
| 537 SkBitmapOperations::RotationAmount rotation) { | |
| 538 if (source.isNull()) | |
| 539 return ImageSkia(); | |
| 540 | |
| 541 return ImageSkia(new RotatedSource(source, rotation), | |
| 542 SkBitmapOperations::ROTATION_180_CW == rotation ? | |
| 543 source.size() : | |
| 544 gfx::Size(source.height(), source.width())); | |
| 545 | |
| 546 } | |
| 547 | |
| 548 } // namespace gfx | |
| OLD | NEW |