| Index: ui/gfx/icon_family.cc
|
| diff --git a/ui/gfx/icon_family.cc b/ui/gfx/icon_family.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..092114881768bcfca9419d8d20789343b443b93d
|
| --- /dev/null
|
| +++ b/ui/gfx/icon_family.cc
|
| @@ -0,0 +1,120 @@
|
| +// 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.
|
| +
|
| +#include "ui/gfx/icon_family.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "ui/gfx/image/image.h"
|
| +#include "ui/gfx/image/image_skia.h"
|
| +
|
| +namespace gfx {
|
| +
|
| +IconFamily::IconFamily() {}
|
| +IconFamily::~IconFamily() {}
|
| +
|
| +void IconFamily::Add(const gfx::Image& icon)
|
| +{
|
| + if (icon.IsEmpty())
|
| + return;
|
| + const gfx::ImageSkia* imageskia = icon.ToImageSkia();
|
| + if (imageskia)
|
| + Add(*imageskia);
|
| +}
|
| +
|
| +void IconFamily::Add(const gfx::ImageSkia& icon)
|
| +{
|
| + int width = icon.width();
|
| + int height = icon.height();
|
| + float aspect;
|
| + if (height == 0) {
|
| + // Assume the image is square.
|
| + aspect = 1.0f;
|
| + } else {
|
| + aspect = static_cast<float>(width) / height;
|
| + }
|
| + int size = std::min(width, height);
|
| + map_[MapKey(aspect, size)] = icon;
|
| +}
|
| +
|
| +const gfx::ImageSkia* IconFamily::Get(int width, int height) const
|
| +{
|
| + if (map_.empty())
|
| + return NULL;
|
| +
|
| + float desired_aspect;
|
| + if (height == 0) {
|
| + if (width == 0) {
|
| + // Choose a square image if possible.
|
| + desired_aspect = 1.0f;
|
| + } else {
|
| + // Choose the widest possible aspect ratio (since infinity is not a
|
| + // well-defined concept in C++).
|
| + desired_aspect = (--map_.end())->first.first;
|
| + }
|
| + } else {
|
| + desired_aspect = static_cast<float>(width) / height;
|
| + }
|
| + int desired_size = std::max(width, height);
|
| +
|
| + // Get iterator to images >= and < the desired aspect ratio and size.
|
| + std::map<MapKey, gfx::ImageSkia>::const_iterator greater_or_equal =
|
| + map_.lower_bound(MapKey(desired_aspect, desired_size));
|
| + if (greater_or_equal != map_.end() &&
|
| + greater_or_equal->first.aspect() == desired_aspect) {
|
| + // Exact same aspect ratio, and we have found the smallest image of the same
|
| + // size or greater. This is ideal.
|
| + return &greater_or_equal->second;
|
| + }
|
| +
|
| + float closest_aspect; // Closest aspect ratio to the desired one.
|
| + if (greater_or_equal != map_.begin()) {
|
| + std::map<MapKey, gfx::ImageSkia>::const_iterator less_than =
|
| + greater_or_equal;
|
| + --less_than;
|
| + if (less_than->first.aspect() == desired_aspect) {
|
| + // Exact same aspect ratio, and we have found the largest image smaller
|
| + // than desired.
|
| + return &less_than->second;
|
| + }
|
| +
|
| + float thinner_aspect = less_than->first.aspect();
|
| + DCHECK(thinner_aspect < desired_aspect);
|
| + closest_aspect = thinner_aspect;
|
| + if (greater_or_equal != map_.end()) {
|
| + float wider_aspect = greater_or_equal->first.aspect();
|
| + DCHECK(wider_aspect > desired_aspect);
|
| + if ((wider_aspect - desired_aspect) < (desired_aspect - thinner_aspect))
|
| + closest_aspect = wider_aspect;
|
| + }
|
| + } else {
|
| + // No aspect ratio is less than or equal to desired_aspect.
|
| + DCHECK(greater_or_equal != map_.end());
|
| + closest_aspect = greater_or_equal->first.aspect();
|
| + DCHECK(closest_aspect > desired_aspect);
|
| + }
|
| +
|
| + // Search again, this time with the aspect ratio we know exists.
|
| + greater_or_equal = map_.lower_bound(MapKey(closest_aspect, desired_size));
|
| + if (greater_or_equal != map_.end() &&
|
| + greater_or_equal->first.aspect() == closest_aspect) {
|
| + // We have found the smallest image of the same size or greater.
|
| + return &greater_or_equal->second;
|
| + }
|
| +
|
| + DCHECK(greater_or_equal != map_.begin());
|
| + std::map<MapKey, gfx::ImageSkia>::const_iterator less_than = greater_or_equal;
|
| + --less_than;
|
| + // This must be true because there must be at least one image with
|
| + // closest_aspect.
|
| + DCHECK(less_than->first.aspect() == closest_aspect);
|
| + // We have found the largest image smaller than desired.
|
| + return &less_than->second;
|
| +}
|
| +
|
| +IconFamily::const_iterator::const_iterator(
|
| + const std::map<MapKey, gfx::ImageSkia>::const_iterator& other)
|
| + : map_iterator_(other) {}
|
| +
|
| +} // namespace gfx
|
|
|