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
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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_FAMILY_H_
#define UI_GFX_IMAGE_IMAGE_FAMILY_H_
#include <iterator>
#include <map>
#include <utility>
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/image/image.h"
namespace gfx {
class ImageSkia;
class Size;
// A collection of images at different sizes. The images should be different
// representations of the same basic concept (for example, an icon) at various
// sizes and (optionally) aspect ratios. A method is provided for finding the
// most appropriate image to fit in a given rectangle.
//
// NOTE: This is not appropriate for storing an image at a single logical pixel
// size, with high-DPI bitmap versions; use an Image or ImageSkia for that. Each
// image in an ImageFamily should have a different logical size (and may also
// include high-DPI representations).
class UI_EXPORT ImageFamily {
private:
// An <aspect ratio, DIP width> pair.
// A 0x0 image has aspect ratio 1.0. 0xN and Nx0 images are treated as 0x0.
struct MapKey : std::pair<float, int> {
MapKey(float aspect, int width)
: std::pair<float, int>(aspect, width) {}
float aspect() const { return first; }
int width() const { return second; }
};
public:
// Type for iterating over all images in the family, in order.
// Dereferencing this iterator returns a gfx::Image.
class UI_EXPORT const_iterator :
std::iterator<std::bidirectional_iterator_tag, const gfx::Image> {
public:
const_iterator();
const_iterator(const const_iterator& other);
const_iterator& operator++() {
++map_iterator_;
return *this;
}
const_iterator operator++(int /*unused*/) {
const_iterator result(*this);
++(*this);
return result;
}
const_iterator& operator--() {
--map_iterator_;
return *this;
}
const_iterator operator--(int /*unused*/) {
const_iterator result(*this);
--(*this);
return result;
}
bool operator==(const const_iterator& other) const {
return map_iterator_ == other.map_iterator_;
}
bool operator!=(const const_iterator& other) const {
return map_iterator_ != other.map_iterator_;
}
const gfx::Image& operator*() const {
return map_iterator_->second;
}
const gfx::Image* operator->() const {
return &**this;
}
private:
friend class ImageFamily;
explicit const_iterator(
const std::map<MapKey, gfx::Image>::const_iterator& other);
std::map<MapKey, gfx::Image>::const_iterator map_iterator_;
};
ImageFamily();
~ImageFamily();
// Gets an iterator to the first image.
const_iterator begin() const { return const_iterator(map_.begin()); }
// Gets an iterator to one after the last image.
const_iterator end() const { return const_iterator(map_.end()); }
// Determines whether the image family has no images in it.
bool empty() const { return map_.empty(); }
// Removes all images from the family.
void clear() { return map_.clear(); }
// Adds an image to the family. If another image is already present at the
// same size, it will be overwritten.
void Add(const gfx::Image& image);
// Adds an image to the family. If another image is already present at the
// same size, it will be overwritten.
void Add(const gfx::ImageSkia& image_skia);
// Gets the best image to use in a rectangle of |width|x|height|.
// Gets an image at the same aspect ratio as |width|:|height|, if possible, or
// if not, the closest aspect ratio. Among images of that aspect ratio,
// returns the smallest image with both its width and height bigger or equal
// to the requested size. If none exists, returns the largest image of that
// aspect ratio. If there are no images in the family, returns NULL.
const gfx::Image* GetBest(int width, int height) const;
// Gets the best image to use in a rectangle of |size|.
// Gets an image at the same aspect ratio as |size.width()|:|size.height()|,
// if possible, or if not, the closest aspect ratio. Among images of that
// aspect ratio, returns the smallest image with both its width and height
// bigger or equal to the requested size. If none exists, returns the largest
// image of that aspect ratio. If there are no images in the family, returns
// NULL.
const gfx::Image* GetBest(const gfx::Size& size) const;
private:
// Find the closest aspect ratio in the map to |desired_aspect|.
// Ties are broken by the thinner aspect.
// |map_| must not be empty. |desired_aspect| must be > 0.0.
float GetClosestAspect(float desired_aspect) const;
// Gets an image with aspect ratio |aspect|, at the best size for |width|.
// Returns the smallest image of aspect ratio |aspect| with its width bigger
// or equal to |width|. If none exists, returns the largest image of aspect
// ratio |aspect|. Behavior is undefined if there is not at least one image in
// |map_| of aspect ratio |aspect|.
const gfx::Image* GetWithExactAspect(float aspect, int width) const;
// Map from (aspect ratio, width) to image.
std::map<MapKey, gfx::Image> map_;
};
} // namespace gfx
#endif // UI_GFX_IMAGE_IMAGE_FAMILY_H_
|