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