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 #ifndef UI_GFX_IMAGE_IMAGE_SKIA_H_ 6 #define UI_GFX_IMAGE_IMAGE_SKIA_H_ 7 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/gtest_prod_util.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "ui/base/ui_export.h" 15 #include "ui/gfx/image/image_skia_rep.h" 16 17 namespace gfx { 18 class ImageSkiaSource; 19 class Size; 20 21 namespace internal { 22 class ImageSkiaStorage; 23 } // namespace internal 24 25 namespace test { 26 class TestOnThread; 27 } 28 29 // Container for the same image at different densities, similar to NSImage. 30 // Image height and width are in DIP (Density Indepent Pixel) coordinates. 31 // 32 // ImageSkia should be used whenever possible instead of SkBitmap. 33 // Functions that mutate the image should operate on the gfx::ImageSkiaRep 34 // returned from ImageSkia::GetRepresentation, not on ImageSkia. 35 // 36 // ImageSkia is cheap to copy and intentionally supports copy semantics. 37 class UI_EXPORT ImageSkia { 38 public: 39 typedef std::vector<ImageSkiaRep> ImageSkiaReps; 40 41 // Creates an instance with no bitmaps. 42 ImageSkia(); 43 44 // Creates an instance that will use the |source| to get the image 45 // for scale factors. |size| specifes the size of the image in DIP. 46 // ImageSkia owns |source|. 47 ImageSkia(ImageSkiaSource* source, const gfx::Size& size); 48 49 // Creates an instance that uses the |source|. The constructor loads the image 50 // at |scale_factor| and uses its dimensions to calculate the size in DIP. 51 // ImageSkia owns |source|. 52 ImageSkia(ImageSkiaSource* source, ui::ScaleFactor scale_factor); 53 54 explicit ImageSkia(const gfx::ImageSkiaRep& image_rep); 55 56 // Copies a reference to |other|'s storage. 57 ImageSkia(const ImageSkia& other); 58 59 // Copies a reference to |other|'s storage. 60 ImageSkia& operator=(const ImageSkia& other); 61 62 ~ImageSkia(); 63 64 // Creates an image from the passed in bitmap. 65 // DIP width and height are based on scale factor of 1x. 66 // Adds ref to passed in bitmap. 67 // WARNING: The resulting image will be pixelated when painted on a high 68 // density display. 69 static ImageSkia CreateFrom1xBitmap(const SkBitmap& bitmap); 70 71 // Returns a deep copy of this ImageSkia which has its own storage with 72 // the ImageSkiaRep instances that this ImageSkia currently has. 73 // This can be safely passed to and manipulated by another thread. 74 // Note that this does NOT generate ImageSkiaReps from its source. 75 // If you want to create a deep copy with ImageSkiaReps for supported 76 // scale factors, you need to explicitly call 77 // |EnsureRepsForSupportedScaleFactors()| first. 78 scoped_ptr<ImageSkia> DeepCopy() const; 79 80 // Returns true if this object is backed by the same ImageSkiaStorage as 81 // |other|. Will also return true if both images are isNull(). 82 bool BackedBySameObjectAs(const gfx::ImageSkia& other) const; 83 84 // Adds |image_rep| to the image reps contained by this object. 85 void AddRepresentation(const gfx::ImageSkiaRep& image_rep); 86 87 // Removes the image rep of |scale_factor| if present. 88 void RemoveRepresentation(ui::ScaleFactor scale_factor); 89 90 // Returns true if the object owns an image rep whose density matches 91 // |scale_factor| exactly. 92 bool HasRepresentation(ui::ScaleFactor scale_factor) const; 93 94 // Returns the image rep whose density best matches 95 // |scale_factor|. 96 // Returns a null image rep if the object contains no image reps. 97 const gfx::ImageSkiaRep& GetRepresentation( 98 ui::ScaleFactor scale_factor) const; 99 100 // Make the ImageSkia instance read-only. Note that this only prevent 101 // modification from client code, and the storage may still be 102 // modified by the source if any (thus, it's not thread safe). This 103 // detaches the storage from currently accessing thread, so its safe 104 // to pass it to other thread as long as it is accessed only by that 105 // thread. If this ImageSkia's storage will be accessed by multiple 106 // threads, use |MakeThreadSafe()| method. 107 void SetReadOnly(); 108 109 // Make the image thread safe by making the storage read only and remove 110 // its source if any. All ImageSkia that shares the same storage will also 111 // become thread safe. Note that in order to make it 100% thread safe, 112 // this must be called before it's been passed to anther thread. 113 void MakeThreadSafe(); 114 bool IsThreadSafe() const; 115 116 // Returns true if this is a null object. 117 bool isNull() const { return storage_.get() == NULL; } 118 119 // Width and height of image in DIP coordinate system. 120 int width() const; 121 int height() const; 122 gfx::Size size() const; 123 124 // Returns pointer to 1x bitmap contained by this object. If there is no 1x 125 // bitmap, the bitmap whose scale factor is closest to 1x is returned. 126 // This function should only be used in unittests and on platforms which do 127 // not support scale factors other than 1x. 128 // TODO(pkotwicz): Return null SkBitmap when the object has no 1x bitmap. 129 const SkBitmap* bitmap() const { return &GetBitmap(); } 130 131 // Returns a vector with the image reps contained in this object. 132 // There is no guarantee that this will return all images rep for 133 // supported scale factors. 134 std::vector<gfx::ImageSkiaRep> image_reps() const; 135 136 // When the source is available, generates all ImageReps for 137 // supported scale factors. This method is defined as const as 138 // the state change in the storage is agnostic to the caller. 139 void EnsureRepsForSupportedScaleFactors() const; 140 141 private: 142 friend class test::TestOnThread; 143 FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, EmptyOnThreadTest); 144 FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, StaticOnThreadTest); 145 FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, SourceOnThreadTest); 146 147 // Initialize ImageSkiaStorage with passed in parameters. 148 // If the image rep's bitmap is empty, ImageStorage is set to NULL. 149 void Init(const gfx::ImageSkiaRep& image_rep); 150 151 SkBitmap& GetBitmap() const; 152 153 // Checks if the current thread can read/modify the ImageSkia. 154 bool CanRead() const; 155 bool CanModify() const; 156 157 // Detach the storage from the currently assinged thread 158 // so that other thread can access the storage. 159 void DetachStorageFromThread(); 160 161 // A refptr so that ImageRepSkia can be copied cheaply. 162 scoped_refptr<internal::ImageSkiaStorage> storage_; 163 }; 164 165 } // namespace gfx 166 167 #endif // UI_GFX_IMAGE_IMAGE_SKIA_H_ 168