OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "ui/gfx/icon_family.h" |
| 6 |
| 7 #include <algorithm> |
| 8 |
| 9 #include "ui/gfx/image/image.h" |
| 10 #include "ui/gfx/image/image_skia.h" |
| 11 |
| 12 namespace gfx { |
| 13 |
| 14 IconFamily::IconFamily() {} |
| 15 IconFamily::~IconFamily() {} |
| 16 |
| 17 void IconFamily::Add(const gfx::Image& icon) |
| 18 { |
| 19 if (icon.IsEmpty()) |
| 20 return; |
| 21 const gfx::ImageSkia* imageskia = icon.ToImageSkia(); |
| 22 if (imageskia) |
| 23 Add(*imageskia); |
| 24 } |
| 25 |
| 26 void IconFamily::Add(const gfx::ImageSkia& icon) |
| 27 { |
| 28 int width = icon.width(); |
| 29 int height = icon.height(); |
| 30 float aspect; |
| 31 if (height == 0) { |
| 32 // Assume the image is square. |
| 33 aspect = 1.0f; |
| 34 } else { |
| 35 aspect = static_cast<float>(width) / height; |
| 36 } |
| 37 int size = std::min(width, height); |
| 38 map_[MapKey(aspect, size)] = icon; |
| 39 } |
| 40 |
| 41 const gfx::ImageSkia* IconFamily::Get(int width, int height) const |
| 42 { |
| 43 if (map_.empty()) |
| 44 return NULL; |
| 45 |
| 46 float desired_aspect; |
| 47 if (height == 0) { |
| 48 if (width == 0) { |
| 49 // Choose a square image if possible. |
| 50 desired_aspect = 1.0f; |
| 51 } else { |
| 52 // Choose the widest possible aspect ratio (since infinity is not a |
| 53 // well-defined concept in C++). |
| 54 desired_aspect = (--map_.end())->first.first; |
| 55 } |
| 56 } else { |
| 57 desired_aspect = static_cast<float>(width) / height; |
| 58 } |
| 59 int desired_size = std::max(width, height); |
| 60 |
| 61 // Get iterator to images >= and < the desired aspect ratio and size. |
| 62 std::map<MapKey, gfx::ImageSkia>::const_iterator greater_or_equal = |
| 63 map_.lower_bound(MapKey(desired_aspect, desired_size)); |
| 64 if (greater_or_equal != map_.end() && |
| 65 greater_or_equal->first.aspect() == desired_aspect) { |
| 66 // Exact same aspect ratio, and we have found the smallest image of the same |
| 67 // size or greater. This is ideal. |
| 68 return &greater_or_equal->second; |
| 69 } |
| 70 |
| 71 float closest_aspect; // Closest aspect ratio to the desired one. |
| 72 if (greater_or_equal != map_.begin()) { |
| 73 std::map<MapKey, gfx::ImageSkia>::const_iterator less_than = |
| 74 greater_or_equal; |
| 75 --less_than; |
| 76 if (less_than->first.aspect() == desired_aspect) { |
| 77 // Exact same aspect ratio, and we have found the largest image smaller |
| 78 // than desired. |
| 79 return &less_than->second; |
| 80 } |
| 81 |
| 82 float thinner_aspect = less_than->first.aspect(); |
| 83 DCHECK(thinner_aspect < desired_aspect); |
| 84 closest_aspect = thinner_aspect; |
| 85 if (greater_or_equal != map_.end()) { |
| 86 float wider_aspect = greater_or_equal->first.aspect(); |
| 87 DCHECK(wider_aspect > desired_aspect); |
| 88 if ((wider_aspect - desired_aspect) < (desired_aspect - thinner_aspect)) |
| 89 closest_aspect = wider_aspect; |
| 90 } |
| 91 } else { |
| 92 // No aspect ratio is less than or equal to desired_aspect. |
| 93 DCHECK(greater_or_equal != map_.end()); |
| 94 closest_aspect = greater_or_equal->first.aspect(); |
| 95 DCHECK(closest_aspect > desired_aspect); |
| 96 } |
| 97 |
| 98 // Search again, this time with the aspect ratio we know exists. |
| 99 greater_or_equal = map_.lower_bound(MapKey(closest_aspect, desired_size)); |
| 100 if (greater_or_equal != map_.end() && |
| 101 greater_or_equal->first.aspect() == closest_aspect) { |
| 102 // We have found the smallest image of the same size or greater. |
| 103 return &greater_or_equal->second; |
| 104 } |
| 105 |
| 106 DCHECK(greater_or_equal != map_.begin()); |
| 107 std::map<MapKey, gfx::ImageSkia>::const_iterator less_than = greater_or_equal; |
| 108 --less_than; |
| 109 // This must be true because there must be at least one image with |
| 110 // closest_aspect. |
| 111 DCHECK(less_than->first.aspect() == closest_aspect); |
| 112 // We have found the largest image smaller than desired. |
| 113 return &less_than->second; |
| 114 } |
| 115 |
| 116 IconFamily::const_iterator::const_iterator( |
| 117 const std::map<MapKey, gfx::ImageSkia>::const_iterator& other) |
| 118 : map_iterator_(other) {} |
| 119 |
| 120 } // namespace gfx |
OLD | NEW |