15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_GFX_IMAGE_IMAGE_SKIA_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_GFX_IMAGE_IMAGE_SKIA_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gfx_export.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_rep.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImageSkiaSource;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Size;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImageSkiaStorage;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace test {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestOnThread;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Container for the same image at different densities, similar to NSImage.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Image height and width are in DIP (Density Indepent Pixel) coordinates.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageSkia should be used whenever possible instead of SkBitmap.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions that mutate the image should operate on the gfx::ImageSkiaRep
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returned from ImageSkia::GetRepresentation, not on ImageSkia.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ImageSkia is cheap to copy and intentionally supports copy semantics.
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class GFX_EXPORT ImageSkia {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<ImageSkiaRep> ImageSkiaReps;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates an instance with no bitmaps.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageSkia();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates an instance that will use the |source| to get the image
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for scale factors. |size| specifes the size of the image in DIP.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ImageSkia owns |source|.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageSkia(ImageSkiaSource* source, const gfx::Size& size);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates an instance that uses the |source|. The constructor loads the image
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // at |scale| and uses its dimensions to calculate the size in DIP. ImageSkia
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // owns |source|.
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageSkia(ImageSkiaSource* source, float scale);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ImageSkia(const gfx::ImageSkiaRep& image_rep);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copies a reference to |other|'s storage.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageSkia(const ImageSkia& other);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copies a reference to |other|'s storage.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ImageSkia& operator=(const ImageSkia& other);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ImageSkia();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Changes the value of GetSupportedScales() to |scales|.
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static void SetSupportedScales(const std::vector<float>& scales);
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns a vector with the scale factors which are supported by this
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // platform, in ascending order.
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static const std::vector<float>& GetSupportedScales();
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns the maximum scale supported by this platform.
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static float GetMaxSupportedScale();
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates an image from the passed in bitmap.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // DIP width and height are based on scale factor of 1x.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Adds ref to passed in bitmap.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // WARNING: The resulting image will be pixelated when painted on a high
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // density display.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static ImageSkia CreateFrom1xBitmap(const SkBitmap& bitmap);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Returns true when ImageSkia looks up the resource pack with the closest
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // scale factor and rescale the fetched image.
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static bool IsDSFScalingInImageSkiaEnabled();
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a deep copy of this ImageSkia which has its own storage with
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the ImageSkiaRep instances that this ImageSkia currently has.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can be safely passed to and manipulated by another thread.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this does NOT generate ImageSkiaReps from its source.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If you want to create a deep copy with ImageSkiaReps for supported
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scale factors, you need to explicitly call
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |EnsureRepsForSupportedScales()| first.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ImageSkia> DeepCopy() const;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if this object is backed by the same ImageSkiaStorage as
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |other|. Will also return true if both images are isNull().
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool BackedBySameObjectAs(const gfx::ImageSkia& other) const;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds |image_rep| to the image reps contained by this object.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddRepresentation(const gfx::ImageSkiaRep& image_rep);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Removes the image rep of |scale| if present.
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void RemoveRepresentation(float scale);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the object owns an image rep whose density matches
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // |scale| exactly.
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool HasRepresentation(float scale) const;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns the image rep whose density best matches |scale|.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a null image rep if the object contains no image reps.
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const gfx::ImageSkiaRep& GetRepresentation(float scale) const;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the ImageSkia instance read-only. Note that this only prevent
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modification from client code, and the storage may still be
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modified by the source if any (thus, it's not thread safe).  This
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // detaches the storage from currently accessing thread, so its safe
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to pass it to other thread as long as it is accessed only by that
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread. If this ImageSkia's storage will be accessed by multiple
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads, use |MakeThreadSafe()| method.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetReadOnly();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the image thread safe by making the storage read only and remove
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // its source if any. All ImageSkia that shares the same storage will also
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // become thread safe. Note that in order to make it 100% thread safe,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this must be called before it's been passed to anther thread.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MakeThreadSafe();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsThreadSafe() const;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if this is a null object.
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool isNull() const { return storage_.get() == NULL; }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Width and height of image in DIP coordinate system.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width() const;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int height() const;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size size() const;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns pointer to 1x bitmap contained by this object. If there is no 1x
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bitmap, the bitmap whose scale factor is closest to 1x is returned.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function should only be used in unittests and on platforms which do
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not support scale factors other than 1x.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(pkotwicz): Return null SkBitmap when the object has no 1x bitmap.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkBitmap* bitmap() const { return &GetBitmap(); }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a vector with the image reps contained in this object.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no guarantee that this will return all images rep for
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // supported scale factors.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<gfx::ImageSkiaRep> image_reps() const;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the source is available, generates all ImageReps for
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // supported scale factors. This method is defined as const as
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the state change in the storage is agnostic to the caller.
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void EnsureRepsForSupportedScales() const;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class test::TestOnThread;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, EmptyOnThreadTest);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, StaticOnThreadTest);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(ImageSkiaTest, SourceOnThreadTest);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize ImageSkiaStorage with passed in parameters.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the image rep's bitmap is empty, ImageStorage is set to NULL.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Init(const gfx::ImageSkiaRep& image_rep);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap& GetBitmap() const;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks if the current thread can read/modify the ImageSkia.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanRead() const;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CanModify() const;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detach the storage from the currently assinged thread
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so that other thread can access the storage.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DetachStorageFromThread();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A refptr so that ImageRepSkia can be copied cheaply.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<internal::ImageSkiaStorage> storage_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // UI_GFX_IMAGE_IMAGE_SKIA_H_
180