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

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

Issue 1873463004: gfx::Image: Made Image objects shallow-copy their representations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 7 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
« no previous file with comments | « ui/gfx/image/image.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 // the memory that the ImageRep holds. When an ImageRep is created, it expects 174 // the memory that the ImageRep holds. When an ImageRep is created, it expects
175 // to take ownership of the image, without having to retain it or increase its 175 // to take ownership of the image, without having to retain it or increase its
176 // reference count. 176 // reference count.
177 class ImageRep { 177 class ImageRep {
178 public: 178 public:
179 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {} 179 explicit ImageRep(Image::RepresentationType rep) : type_(rep) {}
180 180
181 // Deletes the associated pixels of an ImageRep. 181 // Deletes the associated pixels of an ImageRep.
182 virtual ~ImageRep() {} 182 virtual ~ImageRep() {}
183 183
184 virtual std::unique_ptr<ImageRep> Clone() = 0;
185
184 // Cast helpers ("fake RTTI"). 186 // Cast helpers ("fake RTTI").
185 ImageRepPNG* AsImageRepPNG() { 187 ImageRepPNG* AsImageRepPNG() {
186 CHECK_EQ(type_, Image::kImageRepPNG); 188 CHECK_EQ(type_, Image::kImageRepPNG);
187 return reinterpret_cast<ImageRepPNG*>(this); 189 return reinterpret_cast<ImageRepPNG*>(this);
188 } 190 }
189 191
190 ImageRepSkia* AsImageRepSkia() { 192 ImageRepSkia* AsImageRepSkia() {
191 CHECK_EQ(type_, Image::kImageRepSkia); 193 CHECK_EQ(type_, Image::kImageRepSkia);
192 return reinterpret_cast<ImageRepSkia*>(this); 194 return reinterpret_cast<ImageRepSkia*>(this);
193 } 195 }
(...skipping 23 matching lines...) Expand all
217 class ImageRepPNG : public ImageRep { 219 class ImageRepPNG : public ImageRep {
218 public: 220 public:
219 ImageRepPNG() : ImageRep(Image::kImageRepPNG) { 221 ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
220 } 222 }
221 223
222 ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps) 224 ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps)
223 : ImageRep(Image::kImageRepPNG), 225 : ImageRep(Image::kImageRepPNG),
224 image_png_reps_(image_png_reps) { 226 image_png_reps_(image_png_reps) {
225 } 227 }
226 228
229 ImageRepPNG(const ImageRepPNG& other)
230 : ImageRep(Image::kImageRepPNG),
231 image_png_reps_(other.image_png_reps_),
232 size_cache_(other.size_cache_ ? new gfx::Size(*other.size_cache_)
233 : nullptr) {}
234
235 std::unique_ptr<ImageRep> Clone() override {
236 return base::WrapUnique(new ImageRepPNG(*this));
237 }
238
227 ~ImageRepPNG() override {} 239 ~ImageRepPNG() override {}
228 240
229 int Width() const override { return Size().width(); } 241 int Width() const override { return Size().width(); }
230 242
231 int Height() const override { return Size().height(); } 243 int Height() const override { return Size().height(); }
232 244
233 gfx::Size Size() const override { 245 gfx::Size Size() const override {
234 // Read the PNG data to get the image size, caching it. 246 // Read the PNG data to get the image size, caching it.
235 if (!size_cache_) { 247 if (!size_cache_) {
236 for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin(); 248 for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
237 it != image_reps().end(); ++it) { 249 it != image_reps().end(); ++it) {
238 if (it->scale == 1.0f) { 250 if (it->scale == 1.0f) {
239 size_cache_.reset(new gfx::Size(it->Size())); 251 size_cache_.reset(new gfx::Size(it->Size()));
240 return *size_cache_; 252 return *size_cache_;
241 } 253 }
242 } 254 }
243 size_cache_.reset(new gfx::Size); 255 size_cache_.reset(new gfx::Size);
244 } 256 }
245 257
246 return *size_cache_; 258 return *size_cache_;
247 } 259 }
248 260
249 const std::vector<ImagePNGRep>& image_reps() const { return image_png_reps_; } 261 const std::vector<ImagePNGRep>& image_reps() const { return image_png_reps_; }
250 262
251 private: 263 private:
252 std::vector<ImagePNGRep> image_png_reps_; 264 std::vector<ImagePNGRep> image_png_reps_;
253 265
254 // Cached to avoid having to parse the raw data multiple times. 266 // Cached to avoid having to parse the raw data multiple times.
255 mutable std::unique_ptr<gfx::Size> size_cache_; 267 mutable std::unique_ptr<gfx::Size> size_cache_;
256
257 DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
258 }; 268 };
259 269
260 class ImageRepSkia : public ImageRep { 270 class ImageRepSkia : public ImageRep {
261 public: 271 public:
262 // Takes ownership of |image|. 272 // Takes ownership of |image|.
263 explicit ImageRepSkia(ImageSkia* image) 273 explicit ImageRepSkia(ImageSkia* image)
264 : ImageRep(Image::kImageRepSkia), 274 : ImageRep(Image::kImageRepSkia),
265 image_(image) { 275 image_(image) {
266 } 276 }
267 277
268 ~ImageRepSkia() override {} 278 ImageRepSkia(const ImageRepSkia& other)
279 : ImageRep(Image::kImageRepSkia), image_(new ImageSkia(*other.image_)) {}
280
281 std::unique_ptr<ImageRep> Clone() override {
282 return base::WrapUnique(new ImageRepSkia(*this));
283 }
284
285 ~ImageRepSkia() override {
286 // TODO(mgiuca): Obviously bad, but we just leak the pointer because there
287 // is a lot of code depending on this outliving the Image.
288 image_.release();
289 }
269 290
270 int Width() const override { return image_->width(); } 291 int Width() const override { return image_->width(); }
271 292
272 int Height() const override { return image_->height(); } 293 int Height() const override { return image_->height(); }
273 294
274 gfx::Size Size() const override { return image_->size(); } 295 gfx::Size Size() const override { return image_->size(); }
275 296
297 // So... this no longer returns a stable pointer because the Image owns the
298 // ImageSkia and if the local image is destroyed, so is the ImageSkia. Major
299 // problem with this approach: any call to ToImageSkia will now require the
300 // immediate Image object to outlive the ImageSkia*. See
301 // ThemeService::GetImageSkiaNamed, which very deeply relies on the ImageSkia*
302 // outliving the immediate Image object there.
276 ImageSkia* image() { return image_.get(); } 303 ImageSkia* image() { return image_.get(); }
277 304
278 private: 305 private:
279 std::unique_ptr<ImageSkia> image_; 306 std::unique_ptr<ImageSkia> image_;
280
281 DISALLOW_COPY_AND_ASSIGN(ImageRepSkia);
282 }; 307 };
283 308
284 #if defined(OS_IOS) 309 #if defined(OS_IOS)
285 class ImageRepCocoaTouch : public ImageRep { 310 class ImageRepCocoaTouch : public ImageRep {
286 public: 311 public:
287 explicit ImageRepCocoaTouch(UIImage* image) 312 explicit ImageRepCocoaTouch(UIImage* image)
288 : ImageRep(Image::kImageRepCocoaTouch), 313 : ImageRep(Image::kImageRepCocoaTouch),
289 image_(image) { 314 image_(image) {
290 CHECK(image); 315 CHECK(image);
291 } 316 }
292 317
318 // TODO(mgiuca): |image_| double-free!!! DO NOT SUBMIT.
319 ImageRepCocoaTouch(const ImageRepCocoaTouch& other) = default;
320
321 std::unique_ptr<ImageRep> Clone() override {
322 return base::WrapUnique(new ImageRepCocoaTouch(*this));
323 }
324
293 ~ImageRepCocoaTouch() override { 325 ~ImageRepCocoaTouch() override {
294 base::mac::NSObjectRelease(image_); 326 base::mac::NSObjectRelease(image_);
295 image_ = nil; 327 image_ = nil;
296 } 328 }
297 329
298 int Width() const override { return Size().width(); } 330 int Width() const override { return Size().width(); }
299 331
300 int Height() const override { return Size().height(); } 332 int Height() const override { return Size().height(); }
301 333
302 gfx::Size Size() const override { return internal::UIImageSize(image_); } 334 gfx::Size Size() const override { return internal::UIImageSize(image_); }
303 335
304 UIImage* image() const { return image_; } 336 UIImage* image() const { return image_; }
305 337
306 private: 338 private:
307 UIImage* image_; 339 UIImage* image_;
308
309 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
310 }; 340 };
311 #elif defined(OS_MACOSX) 341 #elif defined(OS_MACOSX)
312 class ImageRepCocoa : public ImageRep { 342 class ImageRepCocoa : public ImageRep {
313 public: 343 public:
314 explicit ImageRepCocoa(NSImage* image) 344 explicit ImageRepCocoa(NSImage* image)
315 : ImageRep(Image::kImageRepCocoa), 345 : ImageRep(Image::kImageRepCocoa),
316 image_(image) { 346 image_(image) {
317 CHECK(image); 347 CHECK(image);
318 } 348 }
319 349
350 // TODO(mgiuca): |image_| double-free!!! DO NOT SUBMIT.
351 ImageRepCocoa(const ImageRepCocoa& other) = default;
352
353 std::unique_ptr<ImageRep> Clone() override {
354 return base::WrapUnique(new ImageRepCocoa(*this));
355 }
356
320 ~ImageRepCocoa() override { 357 ~ImageRepCocoa() override {
321 base::mac::NSObjectRelease(image_); 358 base::mac::NSObjectRelease(image_);
322 image_ = nil; 359 image_ = nil;
323 } 360 }
324 361
325 int Width() const override { return Size().width(); } 362 int Width() const override { return Size().width(); }
326 363
327 int Height() const override { return Size().height(); } 364 int Height() const override { return Size().height(); }
328 365
329 gfx::Size Size() const override { return internal::NSImageSize(image_); } 366 gfx::Size Size() const override { return internal::NSImageSize(image_); }
330 367
331 NSImage* image() const { return image_; } 368 NSImage* image() const { return image_; }
332 369
333 private: 370 private:
334 NSImage* image_; 371 NSImage* image_;
335
336 DISALLOW_COPY_AND_ASSIGN(ImageRepCocoa);
337 }; 372 };
338 #endif // defined(OS_MACOSX) 373 #endif // defined(OS_MACOSX)
339 374
340 // The Storage class acts similarly to the pixels in a SkBitmap: the Image 375 // The Storage class acts similarly to the pixels in a SkBitmap: the Image
341 // class holds a refptr instance of Storage, which in turn holds all the 376 // class holds a refptr instance of Storage, which in turn holds all the
342 // ImageReps. This way, the Image can be cheaply copied. 377 // ImageReps. This way, the Image can be cheaply copied.
343 class ImageStorage : public base::RefCounted<ImageStorage> { 378 class ImageStorage {
344 public: 379 public:
345 ImageStorage(Image::RepresentationType default_type) 380 ImageStorage(Image::RepresentationType default_type)
346 : default_representation_type_(default_type) 381 : default_representation_type_(default_type)
347 #if defined(OS_MACOSX) && !defined(OS_IOS) 382 #if defined(OS_MACOSX) && !defined(OS_IOS)
348 , 383 ,
349 default_representation_color_space_( 384 default_representation_color_space_(
350 base::mac::GetGenericRGBColorSpace()) 385 base::mac::GetGenericRGBColorSpace())
351 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 386 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
352 { 387 {
353 } 388 }
354 389
390 ImageStorage(const ImageStorage& other)
391 : default_representation_type_(other.default_representation_type_)
392 #if defined(OS_MACOSX) && !defined(OS_IOS)
393 ,
394 default_representation_color_space_(
395 other.default_representation_color_space_)
396 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
397 {
398 for (const auto& item : other.representations_)
399 representations_.insert(std::make_pair(item.first, item.second->Clone()));
400 }
401
402 ~ImageStorage() {}
403
355 Image::RepresentationType default_representation_type() { 404 Image::RepresentationType default_representation_type() {
356 return default_representation_type_; 405 return default_representation_type_;
357 } 406 }
358 Image::RepresentationMap& representations() { return representations_; } 407 Image::RepresentationMap& representations() { return representations_; }
359 408
360 #if defined(OS_MACOSX) && !defined(OS_IOS) 409 #if defined(OS_MACOSX) && !defined(OS_IOS)
361 void set_default_representation_color_space(CGColorSpaceRef color_space) { 410 void set_default_representation_color_space(CGColorSpaceRef color_space) {
362 default_representation_color_space_ = color_space; 411 default_representation_color_space_ = color_space;
363 } 412 }
364 CGColorSpaceRef default_representation_color_space() { 413 CGColorSpaceRef default_representation_color_space() {
365 return default_representation_color_space_; 414 return default_representation_color_space_;
366 } 415 }
367 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 416 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
368 417
369 private: 418 private:
370 friend class base::RefCounted<ImageStorage>; 419 friend class base::RefCounted<ImageStorage>;
371 420
372 ~ImageStorage() {}
373
374 // The type of image that was passed to the constructor. This key will always 421 // The type of image that was passed to the constructor. This key will always
375 // exist in the |representations_| map. 422 // exist in the |representations_| map.
376 Image::RepresentationType default_representation_type_; 423 Image::RepresentationType default_representation_type_;
377 424
378 #if defined(OS_MACOSX) && !defined(OS_IOS) 425 #if defined(OS_MACOSX) && !defined(OS_IOS)
379 // The default representation's colorspace. This is used for converting to 426 // The default representation's colorspace. This is used for converting to
380 // NSImage. This field exists to compensate for PNGCodec not writing or 427 // NSImage. This field exists to compensate for PNGCodec not writing or
381 // reading colorspace ancillary chunks. (sRGB, iCCP). 428 // reading colorspace ancillary chunks. (sRGB, iCCP).
382 // Not owned. 429 // Not owned.
383 CGColorSpaceRef default_representation_color_space_; 430 CGColorSpaceRef default_representation_color_space_;
384 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 431 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
385 432
386 // All the representations of an Image. Size will always be at least one, with 433 // All the representations of an Image. Size will always be at least one, with
387 // more for any converted representations. 434 // more for any converted representations.
388 Image::RepresentationMap representations_; 435 Image::RepresentationMap representations_;
389
390 DISALLOW_COPY_AND_ASSIGN(ImageStorage);
391 }; 436 };
392 437
393 } // namespace internal 438 } // namespace internal
394 439
395 Image::Image() { 440 Image::Image() {
396 // |storage_| is NULL for empty Images. 441 // |storage_| is NULL for empty Images.
397 } 442 }
398 443
399 Image::Image(const std::vector<ImagePNGRep>& image_reps) { 444 Image::Image(const std::vector<ImagePNGRep>& image_reps) {
400 // Do not store obviously invalid ImagePNGReps. 445 // Do not store obviously invalid ImagePNGReps.
401 std::vector<ImagePNGRep> filtered; 446 std::vector<ImagePNGRep> filtered;
402 for (size_t i = 0; i < image_reps.size(); ++i) { 447 for (size_t i = 0; i < image_reps.size(); ++i) {
403 if (image_reps[i].raw_data.get() && image_reps[i].raw_data->size()) 448 if (image_reps[i].raw_data.get() && image_reps[i].raw_data->size())
404 filtered.push_back(image_reps[i]); 449 filtered.push_back(image_reps[i]);
405 } 450 }
406 451
407 if (filtered.empty()) 452 if (filtered.empty())
408 return; 453 return;
409 454
410 storage_ = new internal::ImageStorage(Image::kImageRepPNG); 455 storage_.reset(new internal::ImageStorage(Image::kImageRepPNG));
411 AddRepresentation(base::WrapUnique(new internal::ImageRepPNG(filtered))); 456 AddRepresentation(base::WrapUnique(new internal::ImageRepPNG(filtered)));
412 } 457 }
413 458
414 Image::Image(const ImageSkia& image) { 459 Image::Image(const ImageSkia& image) {
415 if (!image.isNull()) { 460 if (!image.isNull()) {
416 storage_ = new internal::ImageStorage(Image::kImageRepSkia); 461 storage_.reset(new internal::ImageStorage(Image::kImageRepSkia));
417 AddRepresentation( 462 AddRepresentation(
418 base::WrapUnique(new internal::ImageRepSkia(new ImageSkia(image)))); 463 base::WrapUnique(new internal::ImageRepSkia(new ImageSkia(image))));
419 } 464 }
420 } 465 }
421 466
422 #if defined(OS_IOS) 467 #if defined(OS_IOS)
423 Image::Image(UIImage* image) 468 Image::Image(UIImage* image)
424 : storage_(new internal::ImageStorage(Image::kImageRepCocoaTouch)) { 469 : storage_(new internal::ImageStorage(Image::kImageRepCocoaTouch)) {
425 if (image) 470 if (image)
426 AddRepresentation( 471 AddRepresentation(
427 base::WrapUnique(new internal::ImageRepCocoaTouch(image))); 472 base::WrapUnique(new internal::ImageRepCocoaTouch(image)));
428 } 473 }
429 #elif defined(OS_MACOSX) 474 #elif defined(OS_MACOSX)
430 Image::Image(NSImage* image) { 475 Image::Image(NSImage* image) {
431 if (image) { 476 if (image) {
432 storage_ = new internal::ImageStorage(Image::kImageRepCocoa); 477 storage_.reset(new internal::ImageStorage(Image::kImageRepCocoa));
433 AddRepresentation(base::WrapUnique(new internal::ImageRepCocoa(image))); 478 AddRepresentation(base::WrapUnique(new internal::ImageRepCocoa(image)));
434 } 479 }
435 } 480 }
436 #endif 481 #endif
437 482
438 Image::Image(const Image& other) : storage_(other.storage_) { 483 Image::Image(const Image& other)
439 } 484 : storage_(other.storage_ ? new internal::ImageStorage(*other.storage_)
485 : nullptr) {}
440 486
441 Image& Image::operator=(const Image& other) { 487 Image& Image::operator=(const Image& other) {
442 storage_ = other.storage_; 488 storage_.reset(other.storage_ ? new internal::ImageStorage(*other.storage_)
489 : nullptr);
443 return *this; 490 return *this;
444 } 491 }
445 492
446 Image::~Image() { 493 Image::~Image() {
447 } 494 }
448 495
449 // static 496 // static
450 Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) { 497 Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
451 return Image(ImageSkia::CreateFrom1xBitmap(bitmap)); 498 return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
452 } 499 }
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 storage_->representations().insert(std::make_pair(type, std::move(rep))); 804 storage_->representations().insert(std::make_pair(type, std::move(rep)));
758 805
759 // insert should not fail (implies that there was already a representation of 806 // insert should not fail (implies that there was already a representation of
760 // that type in the map). 807 // that type in the map).
761 CHECK(result.second) << "type was already in map."; 808 CHECK(result.second) << "type was already in map.";
762 809
763 return result.first->second.get(); 810 return result.first->second.get();
764 } 811 }
765 812
766 } // namespace gfx 813 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/image/image.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698