Index: ui/gfx/image/image.cc |
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc |
index 0a5564d8d6c023597386e0f2e614e6cca779b6e1..a072ab09328c51c304ba786203a05b7c91ed6490 100644 |
--- a/ui/gfx/image/image.cc |
+++ b/ui/gfx/image/image.cc |
@@ -9,6 +9,7 @@ |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/stl_util.h" |
+#include "base/synchronization/lock.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/gfx/image/image_png_rep.h" |
#include "ui/gfx/image/image_skia.h" |
@@ -30,6 +31,10 @@ namespace gfx { |
namespace internal { |
+class ImageRep; |
+ |
+typedef std::map<Image::RepresentationType, ImageRep*> RepresentationMap; |
+ |
#if defined(OS_IOS) |
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage( |
UIImage* uiimage); |
@@ -301,7 +306,7 @@ class ImageRepCocoa : public ImageRep { |
// 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 base::RefCountedThreadSafe<ImageStorage> { |
public: |
ImageStorage(gfx::Image::RepresentationType default_type) |
: default_representation_type_(default_type), |
@@ -312,22 +317,48 @@ class ImageStorage : public base::RefCounted<ImageStorage> { |
representations_deleter_(&representations_) { |
} |
- gfx::Image::RepresentationType default_representation_type() { |
+ gfx::Image::RepresentationType default_representation_type() const { |
return default_representation_type_; |
} |
- gfx::Image::RepresentationMap& representations() { return representations_; } |
+ |
+ size_t representation_count() const { |
+ base::AutoLock lock(mutex_); |
+ return representations_.size(); |
+ } |
+ |
+ void add_representation(internal::ImageRep* rep) { |
+ base::AutoLock lock(mutex_); |
+ representations_.insert(std::make_pair(rep->type(), rep)); |
+ } |
+ |
+ bool has_representation(Image::RepresentationType type) const { |
+ base::AutoLock lock(mutex_); |
+ return representations_.count(type) != 0; |
+ } |
+ |
+ internal::ImageRep* get_representation( |
+ Image::RepresentationType rep_type) const { |
+ base::AutoLock lock(mutex_); |
+ internal::RepresentationMap::const_iterator it = |
+ representations_.find(rep_type); |
+ if (it == representations_.end()) |
+ return NULL; |
+ return it->second; |
+ } |
#if defined(OS_MACOSX) && !defined(OS_IOS) |
void set_default_representation_color_space(CGColorSpaceRef color_space) { |
+ base::AutoLock lock(mutex_); |
default_representation_color_space_ = color_space; |
} |
- CGColorSpaceRef default_representation_color_space() { |
+ CGColorSpaceRef default_representation_color_space() const { |
+ base::AutoLock lock(mutex_); |
return default_representation_color_space_; |
} |
#endif // defined(OS_MACOSX) && !defined(OS_IOS) |
private: |
- friend class base::RefCounted<ImageStorage>; |
+ friend class base::RefCountedThreadSafe<ImageStorage>; |
~ImageStorage() {} |
@@ -340,14 +371,19 @@ class ImageStorage : public base::RefCounted<ImageStorage> { |
// NSImage. This field exists to compensate for PNGCodec not writing or |
// reading colorspace ancillary chunks. (sRGB, iCCP). |
// Not owned. |
+ // Must hold |mutex_| when accessing. |
CGColorSpaceRef default_representation_color_space_; |
#endif // defined(OS_MACOSX) && !defined(OS_IOS) |
// All the representations of an Image. Size will always be at least one, with |
// more for any converted representations. |
- gfx::Image::RepresentationMap representations_; |
+ // Must hold |mutex_| when accessing. |
+ RepresentationMap representations_; |
- STLValueDeleter<Image::RepresentationMap> representations_deleter_; |
+ STLValueDeleter<RepresentationMap> representations_deleter_; |
+ |
+ // Lock for mutable fields of this object. |
+ mutable base::Lock mutex_; |
DISALLOW_COPY_AND_ASSIGN(ImageStorage); |
}; |
@@ -652,14 +688,14 @@ NSImage* Image::CopyNSImage() const { |
#endif |
bool Image::HasRepresentation(RepresentationType type) const { |
- return storage_.get() && storage_->representations().count(type) != 0; |
+ return storage_.get() && storage_->has_representation(type); |
} |
size_t Image::RepresentationCount() const { |
if (!storage_.get()) |
return 0; |
- return storage_->representations().size(); |
+ return storage_->representation_count(); |
} |
bool Image::IsEmpty() const { |
@@ -707,17 +743,15 @@ Image::RepresentationType Image::DefaultRepresentationType() const { |
internal::ImageRep* Image::GetRepresentation( |
RepresentationType rep_type, bool must_exist) const { |
CHECK(storage_.get()); |
- RepresentationMap::iterator it = storage_->representations().find(rep_type); |
- if (it == storage_->representations().end()) { |
- CHECK(!must_exist); |
- return NULL; |
- } |
- return it->second; |
+ internal::ImageRep* representation = storage_->get_representation(rep_type); |
+ if (must_exist) |
+ CHECK(representation); |
+ return representation; |
} |
void Image::AddRepresentation(internal::ImageRep* rep) const { |
CHECK(storage_.get()); |
- storage_->representations().insert(std::make_pair(rep->type(), rep)); |
+ storage_->add_representation(rep); |
} |
} // namespace gfx |