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

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

Issue 10799014: Add support for PNG representation in gfx::Image (Closed) Base URL: http://git.chromium.org/chromium/src.git@bookmark-sync
Patch Set: Created 8 years, 5 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
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/image/image.h" 5 #include "ui/gfx/image/image.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "third_party/skia/include/core/SkBitmap.h" 11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "ui/gfx/codec/png_codec.h"
13 #include "ui/gfx/image/image_png.h"
12 #include "ui/gfx/image/image_skia.h" 14 #include "ui/gfx/image/image_skia.h"
13 #include "ui/gfx/size.h" 15 #include "ui/gfx/size.h"
14 16
15 #if defined(TOOLKIT_GTK) 17 #if defined(TOOLKIT_GTK)
16 #include <gdk-pixbuf/gdk-pixbuf.h> 18 #include <gdk-pixbuf/gdk-pixbuf.h>
17 #include <gdk/gdk.h> 19 #include <gdk/gdk.h>
18 #include <glib-object.h> 20 #include <glib-object.h>
19 #include "ui/gfx/canvas.h" 21 #include "ui/gfx/canvas.h"
20 #include "ui/gfx/gtk_util.h" 22 #include "ui/gfx/gtk_util.h"
21 #include "ui/gfx/image/cairo_cached_surface.h" 23 #include "ui/gfx/image/cairo_cached_surface.h"
(...skipping 12 matching lines...) Expand all
34 gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf), 36 gfx::Canvas canvas(gfx::Size(gdk_pixbuf_get_width(pixbuf),
35 gdk_pixbuf_get_height(pixbuf)), false); 37 gdk_pixbuf_get_height(pixbuf)), false);
36 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas()); 38 skia::ScopedPlatformPaint scoped_platform_paint(canvas.sk_canvas());
37 cairo_t* cr = scoped_platform_paint.GetPlatformSurface(); 39 cairo_t* cr = scoped_platform_paint.GetPlatformSurface();
38 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); 40 gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
39 cairo_paint(cr); 41 cairo_paint(cr);
40 return ImageSkia(SkBitmap(canvas.ExtractBitmap())); 42 return ImageSkia(SkBitmap(canvas.ExtractBitmap()));
41 } 43 }
42 #endif 44 #endif
43 45
46 const ImageSkia ImageSkiaFromImagePNG(const ImagePNG& png) {
47 SkBitmap bitmap;
48 if (!gfx::PNGCodec::Decode(&png.Image().front(), png.Image().size(), &bitmap))
49 LOG(WARNING) << "Unable to decode PNG, returning empty bitmap";
50 return ImageSkia(bitmap);
51 }
52
53 class ImageRepPNG;
44 class ImageRepSkia; 54 class ImageRepSkia;
45 class ImageRepGdk; 55 class ImageRepGdk;
46 class ImageRepCairo; 56 class ImageRepCairo;
47 class ImageRepCocoa; 57 class ImageRepCocoa;
48 58
49 // An ImageRep is the object that holds the backing memory for an Image. Each 59 // An ImageRep is the object that holds the backing memory for an Image. Each
50 // RepresentationType has an ImageRep subclass that is responsible for freeing 60 // RepresentationType has an ImageRep subclass that is responsible for freeing
51 // the memory that the ImageRep holds. When an ImageRep is created, it expects 61 // the memory that the ImageRep holds. When an ImageRep is created, it expects
52 // to take ownership of the image, without having to retain it or increase its 62 // to take ownership of the image, without having to retain it or increase its
53 // reference count. 63 // reference count.
54 class ImageRep { 64 class ImageRep {
55 public: 65 public:
56 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {} 66 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {}
57 67
58 // Deletes the associated pixels of an ImageRep. 68 // Deletes the associated pixels of an ImageRep.
59 virtual ~ImageRep() {} 69 virtual ~ImageRep() {}
60 70
61 // Cast helpers ("fake RTTI"). 71 // Cast helpers ("fake RTTI").
72 ImageRepPNG* AsImageRepPNG() {
73 CHECK_EQ(type_, Image::kImageRepPNG);
74 return reinterpret_cast<ImageRepPNG*>(this);
75 }
76
62 ImageRepSkia* AsImageRepSkia() { 77 ImageRepSkia* AsImageRepSkia() {
63 CHECK_EQ(type_, Image::kImageRepSkia); 78 CHECK_EQ(type_, Image::kImageRepSkia);
64 return reinterpret_cast<ImageRepSkia*>(this); 79 return reinterpret_cast<ImageRepSkia*>(this);
65 } 80 }
66 81
67 #if defined(TOOLKIT_GTK) 82 #if defined(TOOLKIT_GTK)
68 ImageRepGdk* AsImageRepGdk() { 83 ImageRepGdk* AsImageRepGdk() {
69 CHECK_EQ(type_, Image::kImageRepGdk); 84 CHECK_EQ(type_, Image::kImageRepGdk);
70 return reinterpret_cast<ImageRepGdk*>(this); 85 return reinterpret_cast<ImageRepGdk*>(this);
71 } 86 }
(...skipping 10 matching lines...) Expand all
82 return reinterpret_cast<ImageRepCocoa*>(this); 97 return reinterpret_cast<ImageRepCocoa*>(this);
83 } 98 }
84 #endif 99 #endif
85 100
86 Image::RepresentationType type() const { return type_; } 101 Image::RepresentationType type() const { return type_; }
87 102
88 private: 103 private:
89 Image::RepresentationType type_; 104 Image::RepresentationType type_;
90 }; 105 };
91 106
107 class ImageRepPNG : public ImageRep {
108 public:
109 explicit ImageRepPNG(const ImagePNG& png)
110 : ImageRep(Image::kImageRepPNG),
111 image_(png) {
112 }
113
114 virtual ~ImageRepPNG() {
115 }
116
117 const ImagePNG& image() const { return image_; }
118
119 private:
120 ImagePNG image_;
121
122 DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
123 };
124
92 class ImageRepSkia : public ImageRep { 125 class ImageRepSkia : public ImageRep {
93 public: 126 public:
94 // Takes ownership of |image|. 127 // Takes ownership of |image|.
95 explicit ImageRepSkia(ImageSkia* image) 128 explicit ImageRepSkia(ImageSkia* image)
96 : ImageRep(Image::kImageRepSkia), 129 : ImageRep(Image::kImageRepSkia),
97 image_(image) { 130 image_(image) {
98 } 131 }
99 132
100 virtual ~ImageRepSkia() { 133 virtual ~ImageRepSkia() {
101 } 134 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 245
213 friend class base::RefCounted<ImageStorage>; 246 friend class base::RefCounted<ImageStorage>;
214 }; 247 };
215 248
216 } // namespace internal 249 } // namespace internal
217 250
218 Image::Image() { 251 Image::Image() {
219 // |storage_| is NULL for empty Images. 252 // |storage_| is NULL for empty Images.
220 } 253 }
221 254
255 Image::Image(const ImagePNG& image)
256 : storage_(new internal::ImageStorage(Image::kImageRepPNG)) {
257 internal::ImageRepPNG* rep = new internal::ImageRepPNG(image);
258 AddRepresentation(rep);
259 }
260
222 Image::Image(const ImageSkia& image) 261 Image::Image(const ImageSkia& image)
223 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) { 262 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
224 internal::ImageRepSkia* rep = new internal::ImageRepSkia( 263 internal::ImageRepSkia* rep = new internal::ImageRepSkia(
225 new ImageSkia(image)); 264 new ImageSkia(image));
226 AddRepresentation(rep); 265 AddRepresentation(rep);
227 } 266 }
228 267
229 Image::Image(const ImageSkiaRep& image_skia_rep) 268 Image::Image(const ImageSkiaRep& image_skia_rep)
230 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) { 269 : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
231 internal::ImageRepSkia* rep = 270 internal::ImageRepSkia* rep =
(...skipping 28 matching lines...) Expand all
260 } 299 }
261 300
262 Image& Image::operator=(const Image& other) { 301 Image& Image::operator=(const Image& other) {
263 storage_ = other.storage_; 302 storage_ = other.storage_;
264 return *this; 303 return *this;
265 } 304 }
266 305
267 Image::~Image() { 306 Image::~Image() {
268 } 307 }
269 308
309 const ImagePNG* Image::ToImagePNG() const {
310 internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
311 if (!rep) {
312 switch (DefaultRepresentationType()) {
313 // For both native types, ensure that there is an ImageRepSkia and fall
314 // through to that case
315 #if defined(TOOLKIT_GTK)
316 case kImageRepGdk:
317 ToImageSkia();
318 #elif defined(OS_MACOSX)
319 case kImageRepCocoa:
320 ToImageSkia();
321 #endif
322 case kImageRepSkia: {
323 internal::ImageRepSkia* skia_rep =
324 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
325 rep = new internal::ImageRepPNG(
326 ImagePNG::FromSkBitmap(skia_rep->image()->bitmap()));
327 break;
328 }
329 default:
330 NOTREACHED();
331 }
332 CHECK(rep);
333 AddRepresentation(rep);
334 }
335 return &rep->AsImageRepPNG()->image();
336 }
337
270 const SkBitmap* Image::ToSkBitmap() const { 338 const SkBitmap* Image::ToSkBitmap() const {
271 // Possibly create and cache an intermediate ImageRepSkia. 339 // Possibly create and cache an intermediate ImageRepSkia.
272 return ToImageSkia()->bitmap(); 340 return ToImageSkia()->bitmap();
273 } 341 }
274 342
275 const ImageSkia* Image::ToImageSkia() const { 343 const ImageSkia* Image::ToImageSkia() const {
276 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false); 344 internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
277 if (!rep) { 345 if (!rep) {
346 switch (DefaultRepresentationType()) {
347 case kImageRepPNG: {
348 internal::ImageRepPNG* png_rep =
349 GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
350 rep = new internal::ImageRepSkia(new ImageSkia(
351 internal::ImageSkiaFromImagePNG(png_rep->image())));
352 break;
353 }
278 #if defined(TOOLKIT_GTK) 354 #if defined(TOOLKIT_GTK)
279 internal::ImageRepGdk* native_rep = 355 case kImageRepGdk: {
280 GetRepresentation(kImageRepGdk, true)->AsImageRepGdk(); 356 internal::ImageRepGdk* native_rep =
281 rep = new internal::ImageRepSkia(new ImageSkia( 357 GetRepresentation(kImageRepGdk, true)->AsImageRepGdk();
282 internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf()))); 358 rep = new internal::ImageRepSkia(new ImageSkia(
359 internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
360 break;
361 }
283 #elif defined(OS_MACOSX) 362 #elif defined(OS_MACOSX)
284 internal::ImageRepCocoa* native_rep = 363 case kImageRepCocoa: {
285 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa(); 364 internal::ImageRepCocoa* native_rep =
286 rep = new internal::ImageRepSkia(new ImageSkia( 365 GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
287 ImageSkiaFromNSImage(native_rep->image()))); 366 rep = new internal::ImageRepSkia(new ImageSkia(
367 ImageSkiaFromNSImage(native_rep->image())));
368 break;
369 }
288 #endif 370 #endif
371 default:
372 NOTREACHED();
373 }
289 CHECK(rep); 374 CHECK(rep);
290 AddRepresentation(rep); 375 AddRepresentation(rep);
291 } 376 }
292 return rep->AsImageRepSkia()->image(); 377 return rep->AsImageRepSkia()->image();
293 } 378 }
294 379
295 #if defined(TOOLKIT_GTK) 380 #if defined(TOOLKIT_GTK)
296 GdkPixbuf* Image::ToGdkPixbuf() const { 381 GdkPixbuf* Image::ToGdkPixbuf() const {
297 internal::ImageRep* rep = GetRepresentation(kImageRepGdk, false); 382 internal::ImageRep* rep = GetRepresentation(kImageRepGdk, false);
298 if (!rep) { 383 if (!rep) {
299 internal::ImageRepSkia* skia_rep = 384 switch (DefaultRepresentationType()) {
300 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia(); 385 case kImageRepPNG:
301 rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap( 386 // Ensure that there is an ImageRepSkia and fall through to that case.
302 *skia_rep->image()->bitmap())); 387 ToImageSkia();
388 case kImageRepSkia: {
389 internal::ImageRepSkia* skia_rep =
390 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
391 rep = new internal::ImageRepGdk(gfx::GdkPixbufFromSkBitmap(
392 *skia_rep->image()->bitmap()));
393 break;
394 }
395 default:
396 NOTREACHED();
397 }
303 CHECK(rep); 398 CHECK(rep);
304 AddRepresentation(rep); 399 AddRepresentation(rep);
305 } 400 }
306 return rep->AsImageRepGdk()->pixbuf(); 401 return rep->AsImageRepGdk()->pixbuf();
307 } 402 }
308 403
309 CairoCachedSurface* const Image::ToCairo() const { 404 CairoCachedSurface* const Image::ToCairo() const {
310 internal::ImageRep* rep = GetRepresentation(kImageRepCairo, false); 405 internal::ImageRep* rep = GetRepresentation(kImageRepCairo, false);
311 if (!rep) { 406 if (!rep) {
312 // Handle any-to-Cairo conversion. This may create and cache an intermediate 407 // Handle any-to-Cairo conversion. This may create and cache an intermediate
313 // pixbuf before sending the data to the display server. 408 // pixbuf before sending the data to the display server.
314 rep = new internal::ImageRepCairo(ToGdkPixbuf()); 409 rep = new internal::ImageRepCairo(ToGdkPixbuf());
315 CHECK(rep); 410 CHECK(rep);
316 AddRepresentation(rep); 411 AddRepresentation(rep);
317 } 412 }
318 return rep->AsImageRepCairo()->surface(); 413 return rep->AsImageRepCairo()->surface();
319 } 414 }
320 #endif 415 #endif
321 416
322 #if defined(OS_MACOSX) 417 #if defined(OS_MACOSX)
323 NSImage* Image::ToNSImage() const { 418 NSImage* Image::ToNSImage() const {
324 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false); 419 internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
325 if (!rep) { 420 if (!rep) {
326 internal::ImageRepSkia* skia_rep = 421 switch (DefaultRepresentationType()) {
327 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia(); 422 case kImageRepPNG:
328 NSImage* image = NSImageFromImageSkia(*skia_rep->image()); 423 // Ensure that there is a ImageRepSkia and fall through to that case.
329 base::mac::NSObjectRetain(image); 424 ToImageSkia();
330 rep = new internal::ImageRepCocoa(image); 425 case kImageRepSkia: {
426 internal::ImageRepSkia* skia_rep =
427 GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
428 NSImage* image = NSImageFromImageSkia(*skia_rep->image());
429 base::mac::NSObjectRetain(image);
430 rep = new internal::ImageRepCocoa(image);
431 break;
432 }
433 default:
434 NOTREACHED();
435 }
331 CHECK(rep); 436 CHECK(rep);
332 AddRepresentation(rep); 437 AddRepresentation(rep);
333 } 438 }
334 return rep->AsImageRepCocoa()->image(); 439 return rep->AsImageRepCocoa()->image();
335 } 440 }
336 #endif 441 #endif
337 442
443 ImagePNG* Image::CopyImagePNG() const {
444 return new ImagePNG(*ToImagePNG());
445 }
446
338 ImageSkia* Image::CopyImageSkia() const { 447 ImageSkia* Image::CopyImageSkia() const {
339 return new ImageSkia(*ToImageSkia()); 448 return new ImageSkia(*ToImageSkia());
340 } 449 }
341 450
342 SkBitmap* Image::CopySkBitmap() const { 451 SkBitmap* Image::CopySkBitmap() const {
343 return new SkBitmap(*ToSkBitmap()); 452 return new SkBitmap(*ToSkBitmap());
344 } 453 }
345 454
346 #if defined(TOOLKIT_GTK) 455 #if defined(TOOLKIT_GTK)
347 GdkPixbuf* Image::CopyGdkPixbuf() const { 456 GdkPixbuf* Image::CopyGdkPixbuf() const {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 } 512 }
404 return it->second; 513 return it->second;
405 } 514 }
406 515
407 void Image::AddRepresentation(internal::ImageRep* rep) const { 516 void Image::AddRepresentation(internal::ImageRep* rep) const {
408 CHECK(storage_.get()); 517 CHECK(storage_.get());
409 storage_->representations().insert(std::make_pair(rep->type(), rep)); 518 storage_->representations().insert(std::make_pair(rep->type(), rep));
410 } 519 }
411 520
412 } // namespace gfx 521 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/image/image.h ('k') | ui/gfx/image/image_png.h » ('j') | ui/gfx/image/image_png.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698