OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/favicon_base/favicon_util.h" | 5 #include "components/favicon_base/favicon_util.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "ui/gfx/image/image_png_rep.h" | 23 #include "ui/gfx/image/image_png_rep.h" |
24 #include "ui/gfx/image/image_skia.h" | 24 #include "ui/gfx/image/image_skia.h" |
25 | 25 |
26 #if defined(OS_MACOSX) && !defined(OS_IOS) | 26 #if defined(OS_MACOSX) && !defined(OS_IOS) |
27 #include "base/mac/mac_util.h" | 27 #include "base/mac/mac_util.h" |
28 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 28 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
29 | 29 |
30 namespace favicon_base { | 30 namespace favicon_base { |
31 namespace { | 31 namespace { |
32 | 32 |
| 33 gfx::Image SelectLargestFrame( |
| 34 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data) { |
| 35 if (png_data.empty()) |
| 36 return gfx::Image(); |
| 37 |
| 38 int maximum_area = 0; |
| 39 scoped_refptr<base::RefCountedMemory> best_candidate; |
| 40 for (size_t i = 0; i < png_data.size(); ++i) { |
| 41 int area = png_data[i].pixel_size.GetArea(); |
| 42 if (area > maximum_area) { |
| 43 maximum_area = area; |
| 44 best_candidate = png_data[i].bitmap_data; |
| 45 } |
| 46 } |
| 47 return gfx::Image({gfx::ImagePNGRep(best_candidate, 1.0f)}); |
| 48 } |
| 49 |
33 // Creates image reps of DIP size |favicon_size| for the subset of | 50 // Creates image reps of DIP size |favicon_size| for the subset of |
34 // |favicon_scales| for which the image reps can be created without resizing | 51 // |favicon_scales| for which the image reps can be created without resizing |
35 // or decoding the bitmap data. | 52 // or decoding the bitmap data. |
36 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing( | 53 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing( |
37 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, | 54 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, |
38 const std::vector<float>& favicon_scales, | 55 std::map<int, float> desired_pixel_sizes) { |
39 int favicon_size) { | |
40 TRACE_EVENT0("browser", | 56 TRACE_EVENT0("browser", |
41 "FaviconUtil::SelectFaviconFramesFromPNGsWithoutResizing"); | 57 "FaviconUtil::SelectFaviconFramesFromPNGsWithoutResizing"); |
42 std::vector<gfx::ImagePNGRep> png_reps; | 58 std::vector<gfx::ImagePNGRep> png_reps; |
43 if (png_data.empty()) | 59 if (png_data.empty()) |
44 return png_reps; | 60 return png_reps; |
45 | 61 |
46 // A |favicon_size| of 0 indicates that the largest frame is desired. | |
47 if (favicon_size == 0) { | |
48 int maximum_area = 0; | |
49 scoped_refptr<base::RefCountedMemory> best_candidate; | |
50 for (size_t i = 0; i < png_data.size(); ++i) { | |
51 int area = png_data[i].pixel_size.GetArea(); | |
52 if (area > maximum_area) { | |
53 maximum_area = area; | |
54 best_candidate = png_data[i].bitmap_data; | |
55 } | |
56 } | |
57 png_reps.push_back(gfx::ImagePNGRep(best_candidate, 1.0f)); | |
58 return png_reps; | |
59 } | |
60 | |
61 // Build a map which will be used to determine the scale used to | |
62 // create a bitmap with given pixel size. | |
63 std::map<int, float> desired_pixel_sizes; | |
64 for (size_t i = 0; i < favicon_scales.size(); ++i) { | |
65 int pixel_size = | |
66 static_cast<int>(std::ceil(favicon_size * favicon_scales[i])); | |
67 desired_pixel_sizes[pixel_size] = favicon_scales[i]; | |
68 } | |
69 | |
70 for (size_t i = 0; i < png_data.size(); ++i) { | 62 for (size_t i = 0; i < png_data.size(); ++i) { |
71 if (!png_data[i].is_valid()) | 63 if (!png_data[i].is_valid()) |
72 continue; | 64 continue; |
73 | 65 |
74 const gfx::Size& pixel_size = png_data[i].pixel_size; | 66 const gfx::Size& pixel_size = png_data[i].pixel_size; |
75 if (pixel_size.width() != pixel_size.height()) | 67 if (pixel_size.width() != pixel_size.height()) |
76 continue; | 68 continue; |
77 | 69 |
78 std::map<int, float>::iterator it = | 70 std::map<int, float>::iterator it = |
79 desired_pixel_sizes.find(pixel_size.width()); | 71 desired_pixel_sizes.find(pixel_size.width()); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 image->SetSourceColorSpace(base::mac::GetSystemColorSpace()); | 156 image->SetSourceColorSpace(base::mac::GetSystemColorSpace()); |
165 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 157 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
166 } | 158 } |
167 | 159 |
168 gfx::Image SelectFaviconFramesFromPNGs( | 160 gfx::Image SelectFaviconFramesFromPNGs( |
169 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, | 161 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, |
170 const std::vector<float>& favicon_scales, | 162 const std::vector<float>& favicon_scales, |
171 int favicon_size) { | 163 int favicon_size) { |
172 TRACE_EVENT0("browser", "FaviconUtil::SelectFaviconFramesFromPNGs"); | 164 TRACE_EVENT0("browser", "FaviconUtil::SelectFaviconFramesFromPNGs"); |
173 | 165 |
| 166 // A |favicon_size| of 0 indicates that the largest frame is desired. |
| 167 if (favicon_size == 0) { |
| 168 return SelectLargestFrame(png_data); |
| 169 } |
| 170 |
| 171 // Build a map which will be used to determine the scale used to |
| 172 // create a bitmap with given pixel size. |
| 173 std::map<int, float> desired_pixel_sizes; |
| 174 for (size_t i = 0; i < favicon_scales.size(); ++i) { |
| 175 int pixel_size = |
| 176 static_cast<int>(std::ceil(favicon_size * favicon_scales[i])); |
| 177 desired_pixel_sizes[pixel_size] = favicon_scales[i]; |
| 178 } |
| 179 |
| 180 return SelectFaviconFramesForPixelSizesFromPNGs(png_data, |
| 181 desired_pixel_sizes); |
| 182 } |
| 183 |
| 184 gfx::Image SelectFaviconFramesForPixelSizesFromPNGs( |
| 185 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, |
| 186 const std::map<int, float>& desired_pixel_sizes) { |
174 // Create image reps for as many scales as possible without resizing | 187 // Create image reps for as many scales as possible without resizing |
175 // the bitmap data or decoding it. FaviconHandler stores already resized | 188 // the bitmap data or decoding it. FaviconHandler stores already resized |
176 // favicons into history so no additional resizing should be needed in the | 189 // favicons into history so no additional resizing should be needed in the |
177 // common case. | 190 // common case. |
178 // Creating the gfx::Image from |png_data| without resizing or decoding if | 191 // Creating the gfx::Image from |png_data| without resizing or decoding if |
179 // possible is important because: | 192 // possible is important because: |
180 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to | 193 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to |
181 // the data it put into the database in order to determine whether any | 194 // the data it put into the database in order to determine whether any |
182 // updates should be pushed to sync. | 195 // updates should be pushed to sync. |
183 // - The decoding occurs on the UI thread and the decoding can be a | 196 // - The decoding occurs on the UI thread and the decoding can be a |
184 // significant performance hit if a user has many bookmarks. | 197 // significant performance hit if a user has many bookmarks. |
185 // TODO(pkotwicz): Move the decoding off the UI thread. | 198 // TODO(pkotwicz): Move the decoding off the UI thread. |
186 std::vector<gfx::ImagePNGRep> png_reps = | 199 std::vector<gfx::ImagePNGRep> png_reps = |
187 SelectFaviconFramesFromPNGsWithoutResizing( | 200 SelectFaviconFramesFromPNGsWithoutResizing(png_data, desired_pixel_sizes); |
188 png_data, favicon_scales, favicon_size); | |
189 | 201 |
190 // SelectFaviconFramesFromPNGsWithoutResizing() should have selected the | 202 std::map<int, float> favicon_scales_to_generate = desired_pixel_sizes; |
191 // largest favicon if |favicon_size| == 0. | |
192 if (favicon_size == 0) | |
193 return gfx::Image(png_reps); | |
194 | |
195 std::vector<float> favicon_scales_to_generate = favicon_scales; | |
196 for (size_t i = 0; i < png_reps.size(); ++i) { | 203 for (size_t i = 0; i < png_reps.size(); ++i) { |
197 std::vector<float>::iterator iter = std::find( | 204 favicon_scales_to_generate.erase( |
198 favicon_scales_to_generate.begin(), | 205 favicon_scales_to_generate.find(png_reps[i].Size().width())); |
199 favicon_scales_to_generate.end(), | |
200 png_reps[i].scale); | |
201 if (iter != favicon_scales_to_generate.end()) | |
202 favicon_scales_to_generate.erase(iter); | |
203 } | 206 } |
204 | 207 |
205 if (favicon_scales_to_generate.empty()) | 208 if (favicon_scales_to_generate.empty()) |
206 return gfx::Image(png_reps); | 209 return gfx::Image(png_reps); |
207 | 210 |
208 std::vector<SkBitmap> bitmaps; | 211 std::vector<SkBitmap> bitmaps; |
209 for (size_t i = 0; i < png_data.size(); ++i) { | 212 for (size_t i = 0; i < png_data.size(); ++i) { |
210 if (!png_data[i].is_valid()) | 213 if (!png_data[i].is_valid()) |
211 continue; | 214 continue; |
212 | 215 |
213 SkBitmap bitmap; | 216 SkBitmap bitmap; |
214 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), | 217 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), |
215 png_data[i].bitmap_data->size(), | 218 png_data[i].bitmap_data->size(), |
216 &bitmap)) { | 219 &bitmap)) { |
217 bitmaps.push_back(bitmap); | 220 bitmaps.push_back(bitmap); |
218 } | 221 } |
219 } | 222 } |
220 | 223 |
221 if (bitmaps.empty()) | 224 if (bitmaps.empty()) |
222 return gfx::Image(); | 225 return gfx::Image(); |
223 | 226 |
224 gfx::ImageSkia resized_image_skia; | 227 gfx::ImageSkia resized_image_skia; |
225 for (size_t i = 0; i < favicon_scales_to_generate.size(); ++i) { | 228 for (const auto& scale_to_generate : favicon_scales_to_generate) { |
226 float scale = favicon_scales_to_generate[i]; | 229 float scale = scale_to_generate.second; |
227 int desired_size_in_pixel = | 230 int desired_size_in_pixel = scale_to_generate.first; |
228 static_cast<int>(std::ceil(favicon_size * scale)); | |
229 SkBitmap bitmap = | 231 SkBitmap bitmap = |
230 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel); | 232 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel); |
231 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); | 233 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); |
232 } | 234 } |
233 | 235 |
234 if (png_reps.empty()) | 236 if (png_reps.empty()) |
235 return gfx::Image(resized_image_skia); | 237 return gfx::Image(resized_image_skia); |
236 | 238 |
237 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps = | 239 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps = |
238 resized_image_skia.image_reps(); | 240 resized_image_skia.image_reps(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 | 291 |
290 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector( | 292 bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector( |
291 &resized_bitmap_data); | 293 &resized_bitmap_data); |
292 bitmap_result.pixel_size = | 294 bitmap_result.pixel_size = |
293 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); | 295 gfx::Size(desired_size_in_pixel, desired_size_in_pixel); |
294 | 296 |
295 return bitmap_result; | 297 return bitmap_result; |
296 } | 298 } |
297 | 299 |
298 } // namespace favicon_base | 300 } // namespace favicon_base |
OLD | NEW |