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/gfx/gfx_export.h"
15#include "ui/gfx/image/image_skia_rep.h"
16
17namespace gfx {
18class ImageSkiaSource;
19class Size;
20
21namespace internal {
22class ImageSkiaStorage;
23}  // namespace internal
24
25namespace test {
26class 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.
37class GFX_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| and uses its dimensions to calculate the size in DIP. ImageSkia
51  // owns |source|.
52  ImageSkia(ImageSkiaSource* source, float scale);
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  // Changes the value of GetSupportedScales() to |scales|.
65  static void SetSupportedScales(const std::vector<float>& scales);
66
67  // Returns a vector with the scale factors which are supported by this
68  // platform, in ascending order.
69  static const std::vector<float>& GetSupportedScales();
70
71  // Returns the maximum scale supported by this platform.
72  static float GetMaxSupportedScale();
73
74  // Creates an image from the passed in bitmap.
75  // DIP width and height are based on scale factor of 1x.
76  // Adds ref to passed in bitmap.
77  // WARNING: The resulting image will be pixelated when painted on a high
78  // density display.
79  static ImageSkia CreateFrom1xBitmap(const SkBitmap& bitmap);
80
81  // Returns true when ImageSkia looks up the resource pack with the closest
82  // scale factor and rescale the fetched image.
83  static bool IsDSFScalingInImageSkiaEnabled();
84
85  // Returns a deep copy of this ImageSkia which has its own storage with
86  // the ImageSkiaRep instances that this ImageSkia currently has.
87  // This can be safely passed to and manipulated by another thread.
88  // Note that this does NOT generate ImageSkiaReps from its source.
89  // If you want to create a deep copy with ImageSkiaReps for supported
90  // scale factors, you need to explicitly call
91  // |EnsureRepsForSupportedScales()| first.
92  scoped_ptr<ImageSkia> DeepCopy() const;
93
94  // Returns true if this object is backed by the same ImageSkiaStorage as
95  // |other|. Will also return true if both images are isNull().
96  bool BackedBySameObjectAs(const gfx::ImageSkia& other) const;
97
98  // Adds |image_rep| to the image reps contained by this object.
99  void AddRepresentation(const gfx::ImageSkiaRep& image_rep);
100
101  // Removes the image rep of |scale| if present.
102  void RemoveRepresentation(float scale);
103
104  // Returns true if the object owns an image rep whose density matches
105  // |scale| exactly.
106  bool HasRepresentation(float scale) const;
107
108  // Returns the image rep whose density best matches |scale|.
109  // Returns a null image rep if the object contains no image reps.
110  const gfx::ImageSkiaRep& GetRepresentation(float scale) const;
111
112  // Make the ImageSkia instance read-only. Note that this only prevent
113  // modification from client code, and the storage may still be
114  // modified by the source if any (thus, it's not thread safe).  This
115  // detaches the storage from currently accessing thread, so its safe
116  // to pass it to other thread as long as it is accessed only by that
117  // thread. If this ImageSkia's storage will be accessed by multiple
118  // threads, use |MakeThreadSafe()| method.
119  void SetReadOnly();
120
121  // Make the image thread safe by making the storage read only and remove
122  // its source if any. All ImageSkia that shares the same storage will also
123  // become thread safe. Note that in order to make it 100% thread safe,
124  // this must be called before it's been passed to anther thread.
125  void MakeThreadSafe();
126  bool IsThreadSafe() const;
127
128  // Returns true if this is a null object.
129  bool isNull() const { return storage_.get() == NULL; }
130
131  // Width and height of image in DIP coordinate system.
132  int width() const;
133  int height() const;
134  gfx::Size size() const;
135
136  // Returns pointer to 1x bitmap contained by this object. If there is no 1x
137  // bitmap, the bitmap whose scale factor is closest to 1x is returned.
138  // This function should only be used in unittests and on platforms which do
139  // not support scale factors other than 1x.
140  // TODO(pkotwicz): Return null SkBitmap when the object has no 1x bitmap.
141  const SkBitmap* bitmap() const { return &GetBitmap(); }
142
143  // Returns a vector with the image reps contained in this object.
144  // There is no guarantee that this will return all images rep for
145  // supported scale factors.
146  std::vector<gfx::ImageSkiaRep> image_reps() const;
147
148  // When the source is available, generates all ImageReps for
149  // supported scale factors. This method is defined as const as
150  // the state change in the storage is agnostic to the caller.
151  void EnsureRepsForSupportedScales() const;
152
153 private:
154  friend class test::TestOnThread;
155  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, EmptyOnThreadTest);
156  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, StaticOnThreadTest);
157  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, SourceOnThreadTest);
158
159  // Initialize ImageSkiaStorage with passed in parameters.
160  // If the image rep's bitmap is empty, ImageStorage is set to NULL.
161  void Init(const gfx::ImageSkiaRep& image_rep);
162
163  SkBitmap& GetBitmap() const;
164
165  // Checks if the current thread can read/modify the ImageSkia.
166  bool CanRead() const;
167  bool CanModify() const;
168
169  // Detach the storage from the currently assinged thread
170  // so that other thread can access the storage.
171  void DetachStorageFromThread();
172
173  // A refptr so that ImageRepSkia can be copied cheaply.
174  scoped_refptr<internal::ImageSkiaStorage> storage_;
175};
176
177}  // namespace gfx
178
179#endif  // UI_GFX_IMAGE_IMAGE_SKIA_H_
180