image_family.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_family.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/image/image.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/size.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace gfx { 145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)ImageFamily::const_iterator::const_iterator() {} 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ImageFamily::const_iterator::const_iterator(const const_iterator& other) 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : map_iterator_(other.map_iterator_) {} 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ImageFamily::const_iterator::const_iterator( 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::map<MapKey, gfx::Image>::const_iterator& other) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : map_iterator_(other) {} 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochImageFamily::ImageFamily() {} 250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)ImageFamily::~ImageFamily() {} 260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ImageFamily::Add(const gfx::Image& image) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size size = image.Size(); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size.IsEmpty()) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_[MapKey(1.0f, 0)] = image; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) float aspect = static_cast<float>(size.width()) / size.height(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(aspect, 0.0f); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_[MapKey(aspect, size.width())] = image; 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ImageFamily::Add(const gfx::ImageSkia& image_skia) { 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Add(gfx::Image(image_skia)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst gfx::Image* ImageFamily::GetBest(int width, int height) const { 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (map_.empty()) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If either |width| or |height| is 0, both are. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float desired_aspect; 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (height == 0 || width == 0) { 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) desired_aspect = 1.0f; 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) height = 0; 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) width = 0; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_aspect = static_cast<float>(width) / height; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_GT(desired_aspect, 0.0f); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) float closest_aspect = GetClosestAspect(desired_aspect); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If thinner than desired, search for images with width such that the 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corresponding height is greater than or equal to the desired |height|. 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int desired_width = closest_aspect <= desired_aspect ? 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) width : static_cast<int>(ceilf(height * closest_aspect)); 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the best-sized image with the aspect ratio. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWithExactAspect(closest_aspect, desired_width); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float ImageFamily::GetClosestAspect(float desired_aspect) const { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the two aspect ratios on either side of |desired_aspect|. 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::map<MapKey, gfx::Image>::const_iterator greater_or_equal = 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) map_.lower_bound(MapKey(desired_aspect, 0)); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Early exit optimization if there is an exact match. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (greater_or_equal != map_.end() && 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) greater_or_equal->first.aspect() == desired_aspect) { 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return desired_aspect; 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // No exact match; |greater_or_equal| will point to the first image with 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // aspect ratio >= |desired_aspect|, and |less_than| will point to the last 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // image with aspect ratio < |desired_aspect|. 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (greater_or_equal != map_.begin()) { 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::map<MapKey, gfx::Image>::const_iterator less_than = 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) greater_or_equal; 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) --less_than; 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float thinner_aspect = less_than->first.aspect(); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_GT(thinner_aspect, 0.0f); 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(thinner_aspect, desired_aspect); 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (greater_or_equal != map_.end()) { 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float wider_aspect = greater_or_equal->first.aspect(); 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_GT(wider_aspect, desired_aspect); 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if ((wider_aspect / desired_aspect) < (desired_aspect / thinner_aspect)) 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return wider_aspect; 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return thinner_aspect; 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // No aspect ratio is less than or equal to |desired_aspect|. 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(greater_or_equal != map_.end()); 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float wider_aspect = greater_or_equal->first.aspect(); 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK_GT(wider_aspect, desired_aspect); 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return wider_aspect; 1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const gfx::Image* ImageFamily::GetBest(const gfx::Size& size) const { 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return GetBest(size.width(), size.height()); 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const gfx::Image* ImageFamily::GetWithExactAspect(float aspect, 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int width) const { 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Find the two images of given aspect ratio on either side of |width|. 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::map<MapKey, gfx::Image>::const_iterator greater_or_equal = 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) map_.lower_bound(MapKey(aspect, width)); 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (greater_or_equal != map_.end() && 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) greater_or_equal->first.aspect() == aspect) { 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We have found the smallest image of the same size or greater. 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return &greater_or_equal->second; 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(greater_or_equal != map_.begin()); 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::map<MapKey, gfx::Image>::const_iterator less_than = greater_or_equal; 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) --less_than; 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This must be true because there must be at least one image with |aspect|. 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_EQ(less_than->first.aspect(), aspect); 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We have found the largest image smaller than desired. 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return &less_than->second; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} // namespace gfx 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)