Implement MoveFileLocal (with creating a snapshot).
[chromium-blink-merge.git] / ui / gfx / image / image_family.cc
blob04f516b869ff91c54e30d78d333e136f35ed1dfa
1 // Copyright 2013 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.
5 #include "ui/gfx/image/image_family.h"
7 #include <cmath>
9 #include "ui/gfx/geometry/size.h"
10 #include "ui/gfx/image/image.h"
11 #include "ui/gfx/image/image_skia.h"
13 namespace gfx {
15 ImageFamily::const_iterator::const_iterator() {}
17 ImageFamily::const_iterator::const_iterator(const const_iterator& other)
18 : map_iterator_(other.map_iterator_) {}
20 ImageFamily::const_iterator::const_iterator(
21 const std::map<MapKey, gfx::Image>::const_iterator& other)
22 : map_iterator_(other) {}
24 ImageFamily::const_iterator::~const_iterator() {}
26 ImageFamily::ImageFamily() {}
27 ImageFamily::~ImageFamily() {}
29 void ImageFamily::Add(const gfx::Image& image) {
30 gfx::Size size = image.Size();
31 if (size.IsEmpty()) {
32 map_[MapKey(1.0f, 0)] = image;
33 } else {
34 float aspect = static_cast<float>(size.width()) / size.height();
35 DCHECK_GT(aspect, 0.0f);
36 map_[MapKey(aspect, size.width())] = image;
40 void ImageFamily::Add(const gfx::ImageSkia& image_skia) {
41 Add(gfx::Image(image_skia));
44 const gfx::Image* ImageFamily::GetBest(int width, int height) const {
45 if (map_.empty())
46 return NULL;
48 // If either |width| or |height| is 0, both are.
49 float desired_aspect;
50 if (height == 0 || width == 0) {
51 desired_aspect = 1.0f;
52 height = 0;
53 width = 0;
54 } else {
55 desired_aspect = static_cast<float>(width) / height;
57 DCHECK_GT(desired_aspect, 0.0f);
59 float closest_aspect = GetClosestAspect(desired_aspect);
61 // If thinner than desired, search for images with width such that the
62 // corresponding height is greater than or equal to the desired |height|.
63 int desired_width = closest_aspect <= desired_aspect ?
64 width : static_cast<int>(ceilf(height * closest_aspect));
66 // Get the best-sized image with the aspect ratio.
67 return GetWithExactAspect(closest_aspect, desired_width);
70 float ImageFamily::GetClosestAspect(float desired_aspect) const {
71 // Find the two aspect ratios on either side of |desired_aspect|.
72 std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
73 map_.lower_bound(MapKey(desired_aspect, 0));
74 // Early exit optimization if there is an exact match.
75 if (greater_or_equal != map_.end() &&
76 greater_or_equal->first.aspect() == desired_aspect) {
77 return desired_aspect;
80 // No exact match; |greater_or_equal| will point to the first image with
81 // aspect ratio >= |desired_aspect|, and |less_than| will point to the last
82 // image with aspect ratio < |desired_aspect|.
83 if (greater_or_equal != map_.begin()) {
84 std::map<MapKey, gfx::Image>::const_iterator less_than =
85 greater_or_equal;
86 --less_than;
87 float thinner_aspect = less_than->first.aspect();
88 DCHECK_GT(thinner_aspect, 0.0f);
89 DCHECK_LT(thinner_aspect, desired_aspect);
90 if (greater_or_equal != map_.end()) {
91 float wider_aspect = greater_or_equal->first.aspect();
92 DCHECK_GT(wider_aspect, desired_aspect);
93 if ((wider_aspect / desired_aspect) < (desired_aspect / thinner_aspect))
94 return wider_aspect;
96 return thinner_aspect;
97 } else {
98 // No aspect ratio is less than or equal to |desired_aspect|.
99 DCHECK(greater_or_equal != map_.end());
100 float wider_aspect = greater_or_equal->first.aspect();
101 DCHECK_GT(wider_aspect, desired_aspect);
102 return wider_aspect;
106 const gfx::Image* ImageFamily::GetBest(const gfx::Size& size) const {
107 return GetBest(size.width(), size.height());
110 const gfx::Image* ImageFamily::GetWithExactAspect(float aspect,
111 int width) const {
112 // Find the two images of given aspect ratio on either side of |width|.
113 std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
114 map_.lower_bound(MapKey(aspect, width));
115 if (greater_or_equal != map_.end() &&
116 greater_or_equal->first.aspect() == aspect) {
117 // We have found the smallest image of the same size or greater.
118 return &greater_or_equal->second;
121 DCHECK(greater_or_equal != map_.begin());
122 std::map<MapKey, gfx::Image>::const_iterator less_than = greater_or_equal;
123 --less_than;
124 // This must be true because there must be at least one image with |aspect|.
125 DCHECK_EQ(less_than->first.aspect(), aspect);
126 // We have found the largest image smaller than desired.
127 return &less_than->second;
130 } // namespace gfx