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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gfx/image/image.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/image/image.cc
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index aa3f2b33e6d32e14de1435b0e3cc622a3d16e3e4..a93c4369c32a9611c91eadc524dcc28d794b97fb 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -181,6 +181,8 @@ class ImageRep {
// Deletes the associated pixels of an ImageRep.
virtual ~ImageRep() {}
+ virtual std::unique_ptr<ImageRep> Clone() = 0;
+
// Cast helpers ("fake RTTI").
ImageRepPNG* AsImageRepPNG() {
CHECK_EQ(type_, Image::kImageRepPNG);
@@ -224,6 +226,16 @@ class ImageRepPNG : public ImageRep {
image_png_reps_(image_png_reps) {
}
+ ImageRepPNG(const ImageRepPNG& other)
+ : ImageRep(Image::kImageRepPNG),
+ image_png_reps_(other.image_png_reps_),
+ size_cache_(other.size_cache_ ? new gfx::Size(*other.size_cache_)
+ : nullptr) {}
+
+ std::unique_ptr<ImageRep> Clone() override {
+ return base::WrapUnique(new ImageRepPNG(*this));
+ }
+
~ImageRepPNG() override {}
int Width() const override { return Size().width(); }
@@ -253,8 +265,6 @@ class ImageRepPNG : public ImageRep {
// Cached to avoid having to parse the raw data multiple times.
mutable std::unique_ptr<gfx::Size> size_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
};
class ImageRepSkia : public ImageRep {
@@ -265,7 +275,18 @@ class ImageRepSkia : public ImageRep {
image_(image) {
}
- ~ImageRepSkia() override {}
+ ImageRepSkia(const ImageRepSkia& other)
+ : ImageRep(Image::kImageRepSkia), image_(new ImageSkia(*other.image_)) {}
+
+ std::unique_ptr<ImageRep> Clone() override {
+ return base::WrapUnique(new ImageRepSkia(*this));
+ }
+
+ ~ImageRepSkia() override {
+ // TODO(mgiuca): Obviously bad, but we just leak the pointer because there
+ // is a lot of code depending on this outliving the Image.
+ image_.release();
+ }
int Width() const override { return image_->width(); }
@@ -273,12 +294,16 @@ class ImageRepSkia : public ImageRep {
gfx::Size Size() const override { return image_->size(); }
+ // So... this no longer returns a stable pointer because the Image owns the
+ // ImageSkia and if the local image is destroyed, so is the ImageSkia. Major
+ // problem with this approach: any call to ToImageSkia will now require the
+ // immediate Image object to outlive the ImageSkia*. See
+ // ThemeService::GetImageSkiaNamed, which very deeply relies on the ImageSkia*
+ // outliving the immediate Image object there.
ImageSkia* image() { return image_.get(); }
private:
std::unique_ptr<ImageSkia> image_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageRepSkia);
};
#if defined(OS_IOS)
@@ -290,6 +315,13 @@ class ImageRepCocoaTouch : public ImageRep {
CHECK(image);
}
+ // TODO(mgiuca): |image_| double-free!!! DO NOT SUBMIT.
+ ImageRepCocoaTouch(const ImageRepCocoaTouch& other) = default;
+
+ std::unique_ptr<ImageRep> Clone() override {
+ return base::WrapUnique(new ImageRepCocoaTouch(*this));
+ }
+
~ImageRepCocoaTouch() override {
base::mac::NSObjectRelease(image_);
image_ = nil;
@@ -305,8 +337,6 @@ class ImageRepCocoaTouch : public ImageRep {
private:
UIImage* image_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
};
#elif defined(OS_MACOSX)
class ImageRepCocoa : public ImageRep {
@@ -317,6 +347,13 @@ class ImageRepCocoa : public ImageRep {
CHECK(image);
}
+ // TODO(mgiuca): |image_| double-free!!! DO NOT SUBMIT.
+ ImageRepCocoa(const ImageRepCocoa& other) = default;
+
+ std::unique_ptr<ImageRep> Clone() override {
+ return base::WrapUnique(new ImageRepCocoa(*this));
+ }
+
~ImageRepCocoa() override {
base::mac::NSObjectRelease(image_);
image_ = nil;
@@ -332,15 +369,13 @@ class ImageRepCocoa : public ImageRep {
private:
NSImage* image_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageRepCocoa);
};
#endif // defined(OS_MACOSX)
// The Storage class acts similarly to the pixels in a SkBitmap: the Image
// class holds a refptr instance of Storage, which in turn holds all the
// ImageReps. This way, the Image can be cheaply copied.
-class ImageStorage : public base::RefCounted<ImageStorage> {
+class ImageStorage {
public:
ImageStorage(Image::RepresentationType default_type)
: default_representation_type_(default_type)
@@ -352,6 +387,20 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
{
}
+ ImageStorage(const ImageStorage& other)
+ : default_representation_type_(other.default_representation_type_)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ ,
+ default_representation_color_space_(
+ other.default_representation_color_space_)
+#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+ {
+ for (const auto& item : other.representations_)
+ representations_.insert(std::make_pair(item.first, item.second->Clone()));
+ }
+
+ ~ImageStorage() {}
+
Image::RepresentationType default_representation_type() {
return default_representation_type_;
}
@@ -369,8 +418,6 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
private:
friend class base::RefCounted<ImageStorage>;
- ~ImageStorage() {}
-
// The type of image that was passed to the constructor. This key will always
// exist in the |representations_| map.
Image::RepresentationType default_representation_type_;
@@ -386,8 +433,6 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// All the representations of an Image. Size will always be at least one, with
// more for any converted representations.
Image::RepresentationMap representations_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageStorage);
};
} // namespace internal
@@ -407,13 +452,13 @@ Image::Image(const std::vector<ImagePNGRep>& image_reps) {
if (filtered.empty())
return;
- storage_ = new internal::ImageStorage(Image::kImageRepPNG);
+ storage_.reset(new internal::ImageStorage(Image::kImageRepPNG));
AddRepresentation(base::WrapUnique(new internal::ImageRepPNG(filtered)));
}
Image::Image(const ImageSkia& image) {
if (!image.isNull()) {
- storage_ = new internal::ImageStorage(Image::kImageRepSkia);
+ storage_.reset(new internal::ImageStorage(Image::kImageRepSkia));
AddRepresentation(
base::WrapUnique(new internal::ImageRepSkia(new ImageSkia(image))));
}
@@ -429,17 +474,19 @@ Image::Image(UIImage* image)
#elif defined(OS_MACOSX)
Image::Image(NSImage* image) {
if (image) {
- storage_ = new internal::ImageStorage(Image::kImageRepCocoa);
+ storage_.reset(new internal::ImageStorage(Image::kImageRepCocoa));
AddRepresentation(base::WrapUnique(new internal::ImageRepCocoa(image)));
}
}
#endif
-Image::Image(const Image& other) : storage_(other.storage_) {
-}
+Image::Image(const Image& other)
+ : storage_(other.storage_ ? new internal::ImageStorage(*other.storage_)
+ : nullptr) {}
Image& Image::operator=(const Image& other) {
- storage_ = other.storage_;
+ storage_.reset(other.storage_ ? new internal::ImageStorage(*other.storage_)
+ : nullptr);
return *this;
}
« 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