15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 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) 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/favicon_base/select_favicon_frames.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <algorithm> 86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <cmath> 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <limits> 106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include <map> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/favicon_base/favicon_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/gfx/image/image_skia_source.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BiggestCandidate(const std::vector<gfx::Size>& candidate_sizes) { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_index = 0; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_area = candidate_sizes[0].GetArea(); 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 1; i < candidate_sizes.size(); ++i) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int area = candidate_sizes[i].GetArea(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (area > max_area) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_area = area; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_index = i; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return max_index; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap SampleNearestNeighbor(const SkBitmap& contents, int desired_size) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap bitmap; 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bitmap.allocN32Pixels(desired_size, desired_size); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents.isOpaque()) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bitmap.eraseARGB(0, 0, 0, 0); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkCanvas canvas(bitmap); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkRect dest(SkRect::MakeWH(desired_size, desired_size)); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas.drawBitmapRect(contents, NULL, dest); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bitmap; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetCandidateIndexWithBestScore( 526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<gfx::Size>& candidate_sizes, 536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int desired_size, 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float* score) { 556d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) DCHECK_NE(desired_size, 0); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to find an exact match. 586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (size_t i = 0; i < candidate_sizes.size(); ++i) { 596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (candidate_sizes[i].width() == desired_size && 606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) candidate_sizes[i].height() == desired_size) { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *score = 1; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Huge favicon bitmaps often have a completely different visual style from 676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // smaller favicon bitmaps. Avoid them. 686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int kHugeEdgeSize = desired_size * 8; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Order of preference: 716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // 1) Bitmaps with width and height smaller than |kHugeEdgeSize|. 7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // 2) Bitmaps which need to be scaled down instead of up. 7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // 3) Bitmaps which do not need to be scaled as much. 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t candidate_index = std::numeric_limits<size_t>::max(); 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) float candidate_score = 0; 766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (size_t i = 0; i < candidate_sizes.size(); ++i) { 776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) float average_edge = 786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) (candidate_sizes[i].width() + candidate_sizes[i].height()) / 2.0f; 7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) float score = 0; 816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (candidate_sizes[i].width() >= kHugeEdgeSize || 826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) candidate_sizes[i].height() >= kHugeEdgeSize) { 836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) score = std::min(1.0f, desired_size / average_edge) * 0.01f; 846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else if (candidate_sizes[i].width() >= desired_size && 856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) candidate_sizes[i].height() >= desired_size) { 866d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) score = desired_size / average_edge * 0.01f + 0.15f; 8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) score = std::min(1.0f, average_edge / desired_size) * 0.01f + 0.1f; 8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (candidate_index == std::numeric_limits<size_t>::max() || 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu score > candidate_score) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) candidate_index = i; 9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) candidate_score = score; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *score = candidate_score; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return candidate_index; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1026d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Represents the index of the best candidate for |desired_size| from the 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |candidate_sizes| passed into GetCandidateIndicesWithBestScores(). 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SelectionResult { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // index in |candidate_sizes| of the best candidate. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1086d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) // The desired size for which |index| is the best candidate. 1096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) int desired_size; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCandidateIndicesWithBestScores( 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<gfx::Size>& candidate_sizes, 1146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float* match_score, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<SelectionResult>* results) { 1176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (candidate_sizes.empty() || desired_sizes.empty()) { 1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (match_score) 1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch *match_score = 0.0f; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector<int>::const_iterator zero_size_it = 1246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::find(desired_sizes.begin(), desired_sizes.end(), 0); 1256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (zero_size_it != desired_sizes.end()) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just return the biggest image available. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectionResult result; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.index = BiggestCandidate(candidate_sizes); 1296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) result.desired_size = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->push_back(result); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_score) 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) *match_score = 1.0f; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float total_score = 0; 1376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (size_t i = 0; i < desired_sizes.size(); ++i) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float score; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectionResult result; 1406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) result.desired_size = desired_sizes[i]; 1416d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) result.index = GetCandidateIndexWithBestScore( 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch candidate_sizes, result.desired_size, &score); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) results->push_back(result); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_score += score; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (match_score) 1486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) *match_score = total_score / desired_sizes.size(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Resize |source_bitmap| 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap GetResizedBitmap(const SkBitmap& source_bitmap, 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Size original_size, 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int desired_size_in_pixel) { 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (desired_size_in_pixel == 0 || 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (original_size.width() == desired_size_in_pixel && 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch original_size.height() == desired_size_in_pixel)) { 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return source_bitmap; 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (desired_size_in_pixel % original_size.width() == 0 && 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_size_in_pixel % original_size.height() == 0) { 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SampleNearestNeighbor(source_bitmap, desired_size_in_pixel); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return skia::ImageOperations::Resize(source_bitmap, 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch skia::ImageOperations::RESIZE_LANCZOS3, 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_size_in_pixel, 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_size_in_pixel); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass FaviconImageSource : public gfx::ImageSkiaSource { 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FaviconImageSource() {} 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual ~FaviconImageSource() {} 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // gfx::ImageSkiaSource: 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::ImageSkiaRep* rep = NULL; 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // gfx::ImageSkia passes one of the resource scale factors. The source 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // should return: 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 1) The ImageSkiaRep with the highest scale if all available 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // scales are smaller than |scale|. 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 2) The ImageSkiaRep with the smallest one that is larger than |scale|. 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Note: Keep this logic consistent with the PNGImageSource in 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // ui/gfx/image.cc. 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(oshima): consolidate these logic into one place. 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (std::vector<gfx::ImageSkiaRep>::const_iterator iter = 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch image_skia_reps_.begin(); 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != image_skia_reps_.end(); ++iter) { 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((*iter).scale() == scale) 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (*iter); 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!rep || rep->scale() < (*iter).scale()) 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rep = &(*iter); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rep->scale() >= scale) 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch break; 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(rep); 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return rep ? *rep : gfx::ImageSkiaRep(); 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void AddImageSkiaRep(const gfx::ImageSkiaRep& rep) { 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch image_skia_reps_.push_back(rep); 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<gfx::ImageSkiaRep> image_skia_reps_; 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(FaviconImageSource); 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const float kSelectFaviconFramesInvalidScore = -1.0f; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdochgfx::ImageSkia CreateFaviconImageSkia( 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<SkBitmap>& bitmaps, 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<gfx::Size>& original_sizes, 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int desired_size_in_dip, 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float* score) { 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<float>& favicon_scales = favicon_base::GetFaviconScales(); 2206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector<int> desired_sizes; 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (desired_size_in_dip == 0) { 2236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) desired_sizes.push_back(0); 2246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (std::vector<float>::const_iterator iter = favicon_scales.begin(); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != favicon_scales.end(); ++iter) { 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_sizes.push_back(ceil(desired_size_in_dip * (*iter))); 2286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 2296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 2306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<SelectionResult> results; 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetCandidateIndicesWithBestScores(original_sizes, 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_sizes, 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch score, 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &results); 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (results.size() == 0) 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::ImageSkia(); 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (desired_size_in_dip == 0) { 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t index = results[0].index; 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1.0f)); 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FaviconImageSource* image_source = new FaviconImageSource; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t index = results[i].index; 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch image_source->AddImageSkiaRep( 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::ImageSkiaRep(GetResizedBitmap(bitmaps[index], 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch original_sizes[index], 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch desired_sizes[i]), 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch favicon_scales[i])); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::ImageSkia(image_source, 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Size(desired_size_in_dip, desired_size_in_dip)); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)void SelectFaviconFrameIndices(const std::vector<gfx::Size>& frame_pixel_sizes, 2596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const std::vector<int>& desired_sizes, 2606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) std::vector<size_t>* best_indices, 2616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) float* match_score) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<SelectionResult> results; 2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GetCandidateIndicesWithBestScores( 2646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) frame_pixel_sizes, desired_sizes, match_score, &results); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<size_t> already_added; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < results.size(); ++i) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index = results[i].index; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetCandidateIndicesWithBestScores() will return duplicate indices if the 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bitmap data with |frame_pixel_sizes[index]| should be used for multiple 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scale factors. Remove duplicates here such that |best_indices| contains 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no duplicates. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (already_added.find(index) == already_added.end()) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) already_added.insert(index); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_indices->push_back(index); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 279