File: image_family.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (184 lines) | stat: -rw-r--r-- 6,613 bytes parent folder | download | duplicates (5)
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright 2013 The Chromium Authors
// 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 "base/component_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 COMPONENT_EXPORT(GFX) 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 COMPONENT_EXPORT(GFX) const_iterator {
   public:
    using iterator_category = std::bidirectional_iterator_tag;
    using value_type = const gfx::Image;
    using difference_type = std::ptrdiff_t;
    using pointer = const gfx::Image*;
    using reference = const gfx::Image&;

    const_iterator();

    const_iterator(const const_iterator& other);

    ~const_iterator();

    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;
    }

    friend bool operator==(const const_iterator&,
                           const const_iterator&) = default;

    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(ImageFamily&& other);

  // Even though the Images in the family are copyable (reference-counted), the
  // family itself should not be implicitly copied, as it would result in a
  // shallow clone of the entire map and updates to many reference counts.
  // ImageFamily can be explicitly Clone()d, but std::move is preferred.
  ImageFamily(const ImageFamily&) = delete;
  ImageFamily& operator=(const ImageFamily&) = delete;

  ~ImageFamily();

  ImageFamily& operator=(ImageFamily&& other);

  // 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(); }

  // Creates a shallow copy of the family. The Images inside share their backing
  // store with the original Images.
  ImageFamily Clone() const;

  // 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;

  // Gets an image of size |width|x|height|. If no image of that exact size
  // exists, chooses the nearest larger image using GetBest() and scales it to
  // the desired size. If there are no images in the family, returns an empty
  // image.
  gfx::Image CreateExact(int width, int height) const;

  // Gets an image of size |size|. If no image of that exact size exists,
  // chooses the nearest larger image using GetBest() and scales it to the
  // desired size. If there are no images in the family, returns an empty image.
  gfx::Image CreateExact(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_