OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/history/select_favicon_frames.h" | 5 #include "chrome/browser/history/select_favicon_frames.h" |
6 | 6 |
7 #include "skia/ext/image_operations.h" | 7 #include "skia/ext/image_operations.h" |
8 #include "third_party/skia/include/core/SkCanvas.h" | 8 #include "third_party/skia/include/core/SkCanvas.h" |
9 #include "ui/gfx/image/image.h" | 9 #include "ui/gfx/image/image.h" |
10 #include "ui/gfx/image/image_skia.h" | 10 #include "ui/gfx/image/image_skia.h" |
11 #include "ui/gfx/size.h" | 11 #include "ui/gfx/size.h" |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
| 15 // Return gfx::Size vector with the pixel sizes of |bitmaps|. |
15 void SizesFromBitmaps(const std::vector<SkBitmap>& bitmaps, | 16 void SizesFromBitmaps(const std::vector<SkBitmap>& bitmaps, |
16 std::vector<gfx::Size>* sizes) { | 17 std::vector<gfx::Size>* sizes) { |
17 for (size_t i = 0; i < bitmaps.size(); ++i) | 18 for (size_t i = 0; i < bitmaps.size(); ++i) |
18 sizes->push_back(gfx::Size(bitmaps[i].width(), bitmaps[i].height())); | 19 sizes->push_back(gfx::Size(bitmaps[i].width(), bitmaps[i].height())); |
19 } | 20 } |
20 | 21 |
| 22 // Return gfx::Size vector with the pixel sizes of |bitmap_id_sizes|. |
| 23 void SizesFromFaviconBitmapIDSizes( |
| 24 const std::vector<history::FaviconBitmapIDSize>& bitmap_id_sizes, |
| 25 std::vector<gfx::Size>* sizes) { |
| 26 for (size_t i = 0; i < bitmap_id_sizes.size(); ++i) |
| 27 sizes->push_back(bitmap_id_sizes[i].pixel_size); |
| 28 } |
| 29 |
21 size_t BiggestCandidate(const std::vector<gfx::Size>& candidate_sizes) { | 30 size_t BiggestCandidate(const std::vector<gfx::Size>& candidate_sizes) { |
22 size_t max_index = 0; | 31 size_t max_index = 0; |
23 int max_area = candidate_sizes[0].GetArea(); | 32 int max_area = candidate_sizes[0].GetArea(); |
24 for (size_t i = 1; i < candidate_sizes.size(); ++i) { | 33 for (size_t i = 1; i < candidate_sizes.size(); ++i) { |
25 int area = candidate_sizes[i].GetArea(); | 34 int area = candidate_sizes[i].GetArea(); |
26 if (area > max_area) { | 35 if (area > max_area) { |
27 max_area = area; | 36 max_area = area; |
28 max_index = i; | 37 max_index = i; |
29 } | 38 } |
30 } | 39 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 } | 141 } |
133 } | 142 } |
134 *score = 0.1f; | 143 *score = 0.1f; |
135 // c) Else, from the biggest smaller variant. | 144 // c) Else, from the biggest smaller variant. |
136 if (candidate_index == -1) { | 145 if (candidate_index == -1) { |
137 *score = 0; | 146 *score = 0; |
138 candidate_index = BiggestCandidate(candidate_sizes); | 147 candidate_index = BiggestCandidate(candidate_sizes); |
139 } | 148 } |
140 | 149 |
141 const gfx::Size& candidate_size = candidate_sizes[candidate_index]; | 150 const gfx::Size& candidate_size = candidate_sizes[candidate_index]; |
142 bool is_integer_multiple = desired_size % candidate_size.width() == 0 && | 151 if (candidate_size.IsEmpty()) { |
143 desired_size % candidate_size.height() == 0; | 152 *resize_method = NONE; |
144 *resize_method = is_integer_multiple ? SAMPLE_NEAREST_NEIGHBOUR : LANCZOS; | 153 } else if (desired_size % candidate_size.width() == 0 && |
| 154 desired_size % candidate_size.height() == 0) { |
| 155 *resize_method = SAMPLE_NEAREST_NEIGHBOUR; |
| 156 } else { |
| 157 *resize_method = LANCZOS; |
| 158 } |
145 return candidate_index; | 159 return candidate_index; |
146 } | 160 } |
147 | 161 |
148 // Represents the index of the best candidate for a |scale_factor| from the | 162 // Represents the index of the best candidate for a |scale_factor| from the |
149 // |candidate_sizes| passed into GetCandidateIndicesWithBestScores(). | 163 // |candidate_sizes| passed into GetCandidateIndicesWithBestScores(). |
150 struct SelectionResult { | 164 struct SelectionResult { |
151 // index in |candidate_sizes| of the best candidate. | 165 // index in |candidate_sizes| of the best candidate. |
152 size_t index; | 166 size_t index; |
153 | 167 |
154 // The ScaleFactor for which |index| is the best candidate. | 168 // The ScaleFactor for which |index| is the best candidate. |
155 ui::ScaleFactor scale_factor; | 169 ui::ScaleFactor scale_factor; |
156 | 170 |
157 // How the bitmap data that the bitmap with |candidate_sizes[index]| should | 171 // How the bitmap data that the bitmap with |candidate_sizes[index]| should |
158 // be resized for displaying in the UI. | 172 // be resized for displaying in the UI. |
159 ResizeMethod resize_method; | 173 ResizeMethod resize_method; |
160 }; | 174 }; |
161 | 175 |
162 void GetCandidateIndicesWithBestScores( | 176 void GetCandidateIndicesWithBestScores( |
163 const std::vector<gfx::Size>& candidate_sizes, | 177 const std::vector<gfx::Size>& candidate_sizes, |
164 const std::vector<ui::ScaleFactor>& scale_factors, | 178 const std::vector<ui::ScaleFactor>& scale_factors, |
165 int desired_size, | 179 int desired_size, |
166 float* match_score, | 180 float* match_score, |
167 std::vector<SelectionResult>* results) { | 181 std::vector<SelectionResult>* results) { |
168 if (candidate_sizes.empty()) | 182 if (candidate_sizes.empty()) { |
| 183 *match_score = 0.0f; |
169 return; | 184 return; |
| 185 } |
170 | 186 |
171 if (desired_size == 0) { | 187 if (desired_size == 0) { |
172 // Just return the biggest image available. | 188 // Just return the biggest image available. |
173 SelectionResult result; | 189 SelectionResult result; |
174 result.index = BiggestCandidate(candidate_sizes); | 190 result.index = BiggestCandidate(candidate_sizes); |
175 result.scale_factor = ui::SCALE_FACTOR_100P; | 191 result.scale_factor = ui::SCALE_FACTOR_100P; |
176 result.resize_method = NONE; | 192 result.resize_method = NONE; |
177 results->push_back(result); | 193 results->push_back(result); |
178 if (match_score) | 194 if (match_score) |
179 *match_score = 0.8f; | 195 *match_score = 0.8f; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 case LANCZOS: | 233 case LANCZOS: |
218 return skia::ImageOperations::Resize( | 234 return skia::ImageOperations::Resize( |
219 source_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, | 235 source_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, |
220 desired_size_in_pixel, desired_size_in_pixel); | 236 desired_size_in_pixel, desired_size_in_pixel); |
221 } | 237 } |
222 return source_bitmap; | 238 return source_bitmap; |
223 } | 239 } |
224 | 240 |
225 } // namespace | 241 } // namespace |
226 | 242 |
| 243 const float kSelectFaviconFramesInvalidScore = -1.0f; |
| 244 |
227 gfx::ImageSkia SelectFaviconFrames( | 245 gfx::ImageSkia SelectFaviconFrames( |
228 const std::vector<SkBitmap>& bitmaps, | 246 const std::vector<SkBitmap>& bitmaps, |
229 const std::vector<ui::ScaleFactor>& scale_factors, | 247 const std::vector<ui::ScaleFactor>& scale_factors, |
230 int desired_size, | 248 int desired_size, |
231 float* match_score) { | 249 float* match_score) { |
232 std::vector<gfx::Size> candidate_sizes; | 250 std::vector<gfx::Size> candidate_sizes; |
233 SizesFromBitmaps(bitmaps, &candidate_sizes); | 251 SizesFromBitmaps(bitmaps, &candidate_sizes); |
234 | 252 |
235 std::vector<SelectionResult> results; | 253 std::vector<SelectionResult> results; |
236 GetCandidateIndicesWithBestScores(candidate_sizes, scale_factors, | 254 GetCandidateIndicesWithBestScores(candidate_sizes, scale_factors, |
237 desired_size, match_score, &results); | 255 desired_size, match_score, &results); |
238 | 256 |
239 gfx::ImageSkia multi_image; | 257 gfx::ImageSkia multi_image; |
240 for (size_t i = 0; i < results.size(); ++i) { | 258 for (size_t i = 0; i < results.size(); ++i) { |
241 const SelectionResult& result = results[i]; | 259 const SelectionResult& result = results[i]; |
242 SkBitmap resized_bitmap = GetResizedBitmap(bitmaps[result.index], | 260 SkBitmap resized_bitmap = GetResizedBitmap(bitmaps[result.index], |
243 desired_size, result.scale_factor, result.resize_method); | 261 desired_size, result.scale_factor, result.resize_method); |
244 multi_image.AddRepresentation( | 262 multi_image.AddRepresentation( |
245 gfx::ImageSkiaRep(resized_bitmap, result.scale_factor)); | 263 gfx::ImageSkiaRep(resized_bitmap, result.scale_factor)); |
246 } | 264 } |
247 return multi_image; | 265 return multi_image; |
248 } | 266 } |
| 267 |
| 268 void SelectFaviconBitmapIDs( |
| 269 const std::vector<history::FaviconBitmapIDSize>& bitmap_id_sizes, |
| 270 const std::vector<ui::ScaleFactor>& scale_factors, |
| 271 int desired_size, |
| 272 std::vector<history::FaviconBitmapID>* filtered_favicon_bitmap_ids, |
| 273 float* match_score) { |
| 274 std::vector<gfx::Size> candidate_sizes; |
| 275 SizesFromFaviconBitmapIDSizes(bitmap_id_sizes, &candidate_sizes); |
| 276 |
| 277 std::vector<SelectionResult> results; |
| 278 GetCandidateIndicesWithBestScores(candidate_sizes, scale_factors, |
| 279 desired_size, match_score, &results); |
| 280 |
| 281 std::set<history::FaviconBitmapID> already_added; |
| 282 for (size_t i = 0; i < results.size(); ++i) { |
| 283 const SelectionResult& result = results[i]; |
| 284 history::FaviconBitmapID bitmap_id = |
| 285 bitmap_id_sizes[result.index].bitmap_id; |
| 286 |
| 287 // GetCandidateIndicesWithBestScores() will return duplicate indices if the |
| 288 // bitmap data for a |bitmap_id| should be used for multiple scale factors. |
| 289 // Remove duplicates here such that |filtered_favicon_bitmap_ids| contains |
| 290 // no duplicates. |
| 291 if (already_added.find(bitmap_id) == already_added.end()) { |
| 292 already_added.insert(bitmap_id); |
| 293 filtered_favicon_bitmap_ids->push_back(bitmap_id); |
| 294 } |
| 295 } |
| 296 } |
OLD | NEW |