image_family.h revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef UI_GFX_IMAGE_IMAGE_FAMILY_H_ 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define UI_GFX_IMAGE_IMAGE_FAMILY_H_ 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <iterator> 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <map> 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <utility> 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/gfx_export.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace gfx { 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ImageSkia; 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class Size; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A collection of images at different sizes. The images should be different 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// representations of the same basic concept (for example, an icon) at various 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// sizes and (optionally) aspect ratios. A method is provided for finding the 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// most appropriate image to fit in a given rectangle. 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// NOTE: This is not appropriate for storing an image at a single logical pixel 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// size, with high-DPI bitmap versions; use an Image or ImageSkia for that. Each 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// image in an ImageFamily should have a different logical size (and may also 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// include high-DPI representations). 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class GFX_EXPORT ImageFamily { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // An <aspect ratio, DIP width> pair. 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // A 0x0 image has aspect ratio 1.0. 0xN and Nx0 images are treated as 0x0. 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) struct MapKey : std::pair<float, int> { 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MapKey(float aspect, int width) 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) : std::pair<float, int>(aspect, width) {} 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) float aspect() const { return first; } 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int width() const { return second; } 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) }; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Type for iterating over all images in the family, in order. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Dereferencing this iterator returns a gfx::Image. 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) class GFX_EXPORT const_iterator : 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::iterator<std::bidirectional_iterator_tag, const gfx::Image> { 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator(); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator(const const_iterator& other); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator& operator++() { 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++map_iterator_; 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *this; 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator operator++(int /*unused*/) { 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator result(*this); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++(*this); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator& operator--() { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) --map_iterator_; 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *this; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator operator--(int /*unused*/) { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator result(*this); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) --(*this); 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool operator==(const const_iterator& other) const { 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return map_iterator_ == other.map_iterator_; 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool operator!=(const const_iterator& other) const { 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return map_iterator_ != other.map_iterator_; 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image& operator*() const { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return map_iterator_->second; 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image* operator->() const { 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return &**this; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) friend class ImageFamily; 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit const_iterator( 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::map<MapKey, gfx::Image>::const_iterator& other); 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::map<MapKey, gfx::Image>::const_iterator map_iterator_; 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ImageFamily(); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ~ImageFamily(); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets an iterator to the first image. 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator begin() const { return const_iterator(map_.begin()); } 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets an iterator to one after the last image. 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const_iterator end() const { return const_iterator(map_.end()); } 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Determines whether the image family has no images in it. 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool empty() const { return map_.empty(); } 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Removes all images from the family. 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void clear() { return map_.clear(); } 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Adds an image to the family. If another image is already present at the 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // same size, it will be overwritten. 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Add(const gfx::Image& image); 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Adds an image to the family. If another image is already present at the 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // same size, it will be overwritten. 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void Add(const gfx::ImageSkia& image_skia); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets the best image to use in a rectangle of |width|x|height|. 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets an image at the same aspect ratio as |width|:|height|, if possible, or 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // if not, the closest aspect ratio. Among images of that aspect ratio, 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // returns the smallest image with both its width and height bigger or equal 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // to the requested size. If none exists, returns the largest image of that 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // aspect ratio. If there are no images in the family, returns NULL. 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image* GetBest(int width, int height) const; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets the best image to use in a rectangle of |size|. 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets an image at the same aspect ratio as |size.width()|:|size.height()|, 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // if possible, or if not, the closest aspect ratio. Among images of that 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // aspect ratio, returns the smallest image with both its width and height 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // bigger or equal to the requested size. If none exists, returns the largest 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // image of that aspect ratio. If there are no images in the family, returns 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // NULL. 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image* GetBest(const gfx::Size& size) const; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Find the closest aspect ratio in the map to |desired_aspect|. 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Ties are broken by the thinner aspect. 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |map_| must not be empty. |desired_aspect| must be > 0.0. 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) float GetClosestAspect(float desired_aspect) const; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Gets an image with aspect ratio |aspect|, at the best size for |width|. 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Returns the smallest image of aspect ratio |aspect| with its width bigger 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // or equal to |width|. If none exists, returns the largest image of aspect 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ratio |aspect|. Behavior is undefined if there is not at least one image in 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |map_| of aspect ratio |aspect|. 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::Image* GetWithExactAspect(float aspect, int width) const; 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Map from (aspect ratio, width) to image. 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::map<MapKey, gfx::Image> map_; 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace gfx 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // UI_GFX_IMAGE_IMAGE_FAMILY_H_ 157