1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_GFX_IMAGE_IMAGE_SKIA_H_
#define UI_GFX_IMAGE_IMAGE_SKIA_H_
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
class SkBitmap;
namespace gfx {
class ImageSkiaRep;
class ImageSkiaSource;
class Size;
namespace internal {
class ImageSkiaStorage;
} // namespace internal
namespace test {
class TestOnThread;
}
// Container for the same image at different densities, similar to NSImage.
// Image height and width are in DIP (Density Indepent Pixel) coordinates.
//
// ImageSkia should be used whenever possible instead of SkBitmap.
// Functions that mutate the image should operate on the gfx::ImageSkiaRep
// returned from ImageSkia::GetRepresentation, not on ImageSkia.
//
// NOTE: This class should *not* be used to store multiple logical sizes of an
// image (e.g., small, medium and large versions of an icon); use an ImageFamily
// for that. An ImageSkia represents an image of a single logical size, with
// potentially many different densities for high-DPI displays.
//
// ImageSkia is cheap to copy and intentionally supports copy semantics.
class COMPONENT_EXPORT(GFX) ImageSkia {
public:
typedef std::vector<ImageSkiaRep> ImageSkiaReps;
// Creates an instance with no bitmaps.
ImageSkia();
// Creates an instance that will use the |source| to get the image
// for scale factors. |size| specifes the size of the image in DIP.
ImageSkia(std::unique_ptr<ImageSkiaSource> source, const gfx::Size& size);
// Creates an instance that uses the |source|. The constructor loads the image
// at |scale| and uses its dimensions to calculate the size in DIP.
ImageSkia(std::unique_ptr<ImageSkiaSource> source, float scale);
// This constructor is explicitly deleted to ensure callers don't accidentally
// pass an int and have it converted to float.
ImageSkia(std::unique_ptr<ImageSkiaSource> source, int dont_use) = delete;
explicit ImageSkia(const gfx::ImageSkiaRep& image_rep);
// Copies a reference to |other|'s storage.
ImageSkia(const ImageSkia& other);
// Copies a reference to |other|'s storage.
ImageSkia& operator=(const ImageSkia& other);
~ImageSkia();
// Creates an image from the passed in bitmap, which is designed for display
// at the device scale factor given in `scale`. The DIP width and height will
// be based on that scale factor. A scale factor of 0 is equivalent to
// calling CreateFrom1xBitmap(), which indicates the bitmap is not scaled.
// The `bitmap`, if present, will be made immutable. If the `bitmap` is
// uninitialized, empty, or null then the returned ImageSkia will be
// default-constructed and empty.
// WARNING: If the device scale factory differs from the scale given here,
// the resulting image will be pixelated when displayed.
static ImageSkia CreateFromBitmap(const SkBitmap& bitmap, float scale);
// Creates an image from the passed in bitmap. The DIP width and height will
// be based on scale factor of 1x. The `bitmap`, if present, will be made
// immutable. If the bitmap is uninitialized, empty, or null then the
// returned ImageSkia will be default-constructed and empty.
// WARNING: The resulting image will be pixelated when painted on a high
// density display.
static ImageSkia CreateFrom1xBitmap(const SkBitmap& bitmap);
// Returns a deep copy of this ImageSkia which has its own storage with
// the ImageSkiaRep instances that this ImageSkia currently has.
// This can be safely passed to and manipulated by another thread.
// Note that this does NOT generate ImageSkiaReps from its source.
// If you want to create a deep copy with ImageSkiaReps for supported
// scale factors, you need to explicitly call
// |EnsureRepsForSupportedScales()| first.
ImageSkia DeepCopy() const;
// Returns true if this object is backed by the same ImageSkiaStorage as
// |other|. Will also return true if both images are isNull().
bool BackedBySameObjectAs(const gfx::ImageSkia& other) const;
// Returns a pointer that identifies the backing ImageSkiaStorage. Comparing
// the results of this method from two ImageSkia objects is equivalent to
// using BackedBySameObjectAs().
const void* GetBackingObject() const;
// Adds |image_rep| to the image reps contained by this object.
void AddRepresentation(const gfx::ImageSkiaRep& image_rep);
// Removes the image rep of |scale| if present.
void RemoveRepresentation(float scale);
// Returns true if the object owns an image rep whose density matches
// |scale| exactly.
bool HasRepresentation(float scale) const;
// Returns the image rep whose density best matches |scale|.
// Returns a null image rep if the object contains no image reps.
const gfx::ImageSkiaRep& GetRepresentation(float scale) const;
// Make the ImageSkia instance read-only. Note that this only prevent
// modification from client code, and the storage may still be
// modified by the source if any (thus, it's not thread safe). This
// detaches the storage from currently accessing sequence, so its safe
// to pass it to another sequence as long as it is accessed only by that
// sequence. If this ImageSkia's storage will be accessed by multiple
// sequences, use |MakeThreadSafe()| method.
void SetReadOnly();
// Make the image thread safe by making the storage read only and remove
// its source if any. All ImageSkia that shares the same storage will also
// become thread safe. Note that in order to make it 100% thread safe,
// this must be called before it's been passed to another sequence.
void MakeThreadSafe();
bool IsThreadSafe() const;
// Returns true if this is a null object.
bool isNull() const { return storage_.get() == NULL; }
// Width and height of image in DIP coordinate system.
int width() const;
int height() const;
gfx::Size size() const;
// Returns pointer to 1x bitmap contained by this object. If there is no 1x
// bitmap, the bitmap whose scale factor is closest to 1x is returned.
// This function should only be used in unittests and on platforms which do
// not support scale factors other than 1x.
// TODO(pkotwicz): Return null SkBitmap when the object has no 1x bitmap.
const SkBitmap* bitmap() const { return &GetBitmap(); }
// Returns a vector with the image reps contained in this object.
// There is no guarantee that this will return all images rep for
// supported scale factors.
std::vector<gfx::ImageSkiaRep> image_reps() const;
// When the source is available, generates all ImageReps for
// supported scale factors. This method is defined as const as
// the state change in the storage is agnostic to the caller.
void EnsureRepsForSupportedScales() const;
// Clears cached representations for non-supported scale factors that are
// based on |scale|.
void RemoveUnsupportedRepresentationsForScale(float scale);
// Returns true if the image storage is uniquely owned.
bool IsUniquelyOwned() const;
private:
friend class test::TestOnThread;
FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, EmptyOnThreadTest);
FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, StaticOnThreadTest);
FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, SourceOnThreadTest);
// Initialize ImageSkiaStorage with passed in parameters.
// If the image rep's bitmap is empty, ImageStorage is set to NULL.
void Init(const gfx::ImageSkiaRep& image_rep);
const SkBitmap& GetBitmap() const;
// Checks if the current sequence can read/modify the ImageSkia.
bool CanRead() const;
bool CanModify() const;
// Detach the storage from the currently assigned sequence
// so that other sequence can access the storage.
void DetachStorageFromSequence();
// A refptr so that ImageRepSkia can be copied cheaply.
scoped_refptr<internal::ImageSkiaStorage> storage_;
};
} // namespace gfx
#endif // UI_GFX_IMAGE_IMAGE_SKIA_H_
|