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 <cmath> | |
8 | |
7 #include "components/favicon_base/favicon_types.h" | 9 #include "components/favicon_base/favicon_types.h" |
8 #include "components/favicon_base/select_favicon_frames.h" | 10 #include "components/favicon_base/select_favicon_frames.h" |
9 #include "skia/ext/image_operations.h" | 11 #include "skia/ext/image_operations.h" |
10 #include "third_party/skia/include/core/SkBitmap.h" | 12 #include "third_party/skia/include/core/SkBitmap.h" |
11 #include "third_party/skia/include/core/SkCanvas.h" | 13 #include "third_party/skia/include/core/SkCanvas.h" |
12 #include "ui/gfx/codec/png_codec.h" | 14 #include "ui/gfx/codec/png_codec.h" |
13 #include "ui/gfx/favicon_size.h" | 15 #include "ui/gfx/favicon_size.h" |
14 #include "ui/gfx/image/image_png_rep.h" | 16 #include "ui/gfx/image/image_png_rep.h" |
15 #include "ui/gfx/image/image_skia.h" | 17 #include "ui/gfx/image/image_skia.h" |
16 #include "ui/gfx/size.h" | 18 #include "ui/gfx/size.h" |
17 | 19 |
18 #if defined(OS_MACOSX) && !defined(OS_IOS) | 20 #if defined(OS_MACOSX) && !defined(OS_IOS) |
19 #include "base/mac/mac_util.h" | 21 #include "base/mac/mac_util.h" |
20 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 22 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
21 | 23 |
22 namespace favicon_base { | 24 namespace favicon_base { |
23 namespace { | 25 namespace { |
24 | 26 |
25 // Creates image reps of DIP size |favicon_size| for the subset of | 27 // Creates image reps of DIP size |favicon_size| for the subset of |
26 // |scale_factors| for which the image reps can be created without resizing | 28 // |scale_factors| for which the image reps can be created without resizing |
27 // or decoding the bitmap data. | 29 // or decoding the bitmap data. |
28 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing( | 30 std::vector<gfx::ImagePNGRep> SelectFaviconFramesFromPNGsWithoutResizing( |
29 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, | 31 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, |
30 const std::vector<ui::ScaleFactor>& scale_factors, | 32 const std::vector<float>& favicon_scales, |
31 int favicon_size) { | 33 int favicon_size) { |
32 std::vector<gfx::ImagePNGRep> png_reps; | 34 std::vector<gfx::ImagePNGRep> png_reps; |
33 if (png_data.empty()) | 35 if (png_data.empty()) |
34 return png_reps; | 36 return png_reps; |
35 | 37 |
36 // A |favicon_size| of 0 indicates that the largest frame is desired. | 38 // A |favicon_size| of 0 indicates that the largest frame is desired. |
37 if (favicon_size == 0) { | 39 if (favicon_size == 0) { |
38 int maximum_area = 0; | 40 int maximum_area = 0; |
39 scoped_refptr<base::RefCountedMemory> best_candidate; | 41 scoped_refptr<base::RefCountedMemory> best_candidate; |
40 for (size_t i = 0; i < png_data.size(); ++i) { | 42 for (size_t i = 0; i < png_data.size(); ++i) { |
41 int area = png_data[i].pixel_size.GetArea(); | 43 int area = png_data[i].pixel_size.GetArea(); |
42 if (area > maximum_area) { | 44 if (area > maximum_area) { |
43 maximum_area = area; | 45 maximum_area = area; |
44 best_candidate = png_data[i].bitmap_data; | 46 best_candidate = png_data[i].bitmap_data; |
45 } | 47 } |
46 } | 48 } |
47 png_reps.push_back(gfx::ImagePNGRep(best_candidate, 1.0f)); | 49 png_reps.push_back(gfx::ImagePNGRep(best_candidate, 1.0f)); |
48 return png_reps; | 50 return png_reps; |
49 } | 51 } |
50 | 52 |
51 // Cache the scale factor for each pixel size as |scale_factors| may contain | 53 // Cache the scale factor for each pixel size as |scale_factors| may contain |
52 // any of GetFaviconScaleFactors() which may include scale factors not | 54 // any of GetFaviconScaleFactors() which may include scale factors not |
53 // supported by the platform. (ui::GetSupportedScaleFactor() cannot be used.) | 55 // supported by the platform. (ui::GetSupportedScaleFactor() cannot be used.) |
54 std::map<int, ui::ScaleFactor> desired_pixel_sizes; | 56 std::map<int, float> desired_pixel_sizes; |
55 for (size_t i = 0; i < scale_factors.size(); ++i) { | 57 for (size_t i = 0; i < favicon_scales.size(); ++i) { |
56 int pixel_size = | 58 int pixel_size = std::floor(favicon_size * favicon_scales[i]); |
pkotwicz
2014/06/18 15:46:33
We should ceil instead.
oshima
2014/06/18 17:17:19
Done.
| |
57 floor(favicon_size * ui::GetScaleForScaleFactor(scale_factors[i])); | 59 desired_pixel_sizes[pixel_size] = favicon_scales[i]; |
58 desired_pixel_sizes[pixel_size] = scale_factors[i]; | |
59 } | 60 } |
60 | 61 |
61 for (size_t i = 0; i < png_data.size(); ++i) { | 62 for (size_t i = 0; i < png_data.size(); ++i) { |
62 if (!png_data[i].is_valid()) | 63 if (!png_data[i].is_valid()) |
63 continue; | 64 continue; |
64 | 65 |
65 const gfx::Size& pixel_size = png_data[i].pixel_size; | 66 const gfx::Size& pixel_size = png_data[i].pixel_size; |
66 if (pixel_size.width() != pixel_size.height()) | 67 if (pixel_size.width() != pixel_size.height()) |
67 continue; | 68 continue; |
68 | 69 |
69 std::map<int, ui::ScaleFactor>::iterator it = | 70 std::map<int, float>::iterator it = |
70 desired_pixel_sizes.find(pixel_size.width()); | 71 desired_pixel_sizes.find(pixel_size.width()); |
71 if (it == desired_pixel_sizes.end()) | 72 if (it == desired_pixel_sizes.end()) |
72 continue; | 73 continue; |
73 | 74 |
74 png_reps.push_back(gfx::ImagePNGRep( | 75 png_reps.push_back(gfx::ImagePNGRep(png_data[i].bitmap_data, it->second)); |
75 png_data[i].bitmap_data, ui::GetScaleForScaleFactor(it->second))); | |
76 } | 76 } |
77 | 77 |
78 return png_reps; | 78 return png_reps; |
79 } | 79 } |
80 | 80 |
81 // Returns a resampled bitmap of | 81 // Returns a resampled bitmap of |
82 // |desired_size_in_pixel| x |desired_size_in_pixel| by resampling the best | 82 // |desired_size_in_pixel| x |desired_size_in_pixel| by resampling the best |
83 // bitmap out of |input_bitmaps|. ResizeBitmapByDownsamplingIfPossible() is | 83 // bitmap out of |input_bitmaps|. ResizeBitmapByDownsamplingIfPossible() is |
84 // similar to SelectFaviconFrames() but it operates on bitmaps which have | 84 // similar to SelectFaviconFrames() but it operates on bitmaps which have |
85 // already been resampled via SelectFaviconFrames(). | 85 // already been resampled via SelectFaviconFrames(). |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 return bitmap; | 129 return bitmap; |
130 } | 130 } |
131 return skia::ImageOperations::Resize(best_bitmap, | 131 return skia::ImageOperations::Resize(best_bitmap, |
132 skia::ImageOperations::RESIZE_LANCZOS3, | 132 skia::ImageOperations::RESIZE_LANCZOS3, |
133 desired_size_in_pixel, | 133 desired_size_in_pixel, |
134 desired_size_in_pixel); | 134 desired_size_in_pixel); |
135 } | 135 } |
136 | 136 |
137 } // namespace | 137 } // namespace |
138 | 138 |
139 std::vector<ui::ScaleFactor> GetFaviconScaleFactors() { | 139 std::vector<float> GetFaviconScales() { |
140 const float kScale1x = 1.0f; | 140 const std::vector<ui::ScaleFactor>& resource_scale_factors = |
141 std::vector<ui::ScaleFactor> favicon_scale_factors = | |
142 ui::GetSupportedScaleFactors(); | 141 ui::GetSupportedScaleFactors(); |
143 | 142 |
144 // The scale factors returned from ui::GetSupportedScaleFactors() are sorted. | 143 std::vector<float> favicon_scales(1, 1.0f); |
145 // Insert the 1x scale factor such that GetFaviconScaleFactors() is sorted as | 144 for (size_t i = 0; i < resource_scale_factors.size(); ++i) { |
146 // well. | 145 if (resource_scale_factors[i] != ui::SCALE_FACTOR_100P) |
147 size_t insert_index = favicon_scale_factors.size(); | 146 favicon_scales.push_back( |
148 for (size_t i = 0; i < favicon_scale_factors.size(); ++i) { | 147 ui::GetScaleForScaleFactor(resource_scale_factors[i])); |
149 float scale = ui::GetScaleForScaleFactor(favicon_scale_factors[i]); | |
150 if (scale == kScale1x) { | |
151 return favicon_scale_factors; | |
152 } else if (scale > kScale1x) { | |
153 insert_index = i; | |
154 break; | |
155 } | |
156 } | 148 } |
157 // TODO(ios): 100p should not be necessary on iOS retina devices. However | 149 |
158 // the sync service only supports syncing 100p favicons. Until sync supports | 150 return favicon_scales; |
159 // other scales 100p is needed in the list of scale factors to retrieve and | |
160 // store the favicons in both 100p for sync and 200p for display. cr/160503. | |
161 favicon_scale_factors.insert(favicon_scale_factors.begin() + insert_index, | |
162 ui::SCALE_FACTOR_100P); | |
pkotwicz
2014/06/18 15:46:33
The TODO for ios should stay
oshima
2014/06/18 17:17:19
Done.
| |
163 return favicon_scale_factors; | |
164 } | 151 } |
165 | 152 |
166 void SetFaviconColorSpace(gfx::Image* image) { | 153 void SetFaviconColorSpace(gfx::Image* image) { |
167 #if defined(OS_MACOSX) && !defined(OS_IOS) | 154 #if defined(OS_MACOSX) && !defined(OS_IOS) |
168 image->SetSourceColorSpace(base::mac::GetSystemColorSpace()); | 155 image->SetSourceColorSpace(base::mac::GetSystemColorSpace()); |
169 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | 156 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
170 } | 157 } |
171 | 158 |
172 gfx::Image SelectFaviconFramesFromPNGs( | 159 gfx::Image SelectFaviconFramesFromPNGs( |
173 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, | 160 const std::vector<favicon_base::FaviconRawBitmapResult>& png_data, |
174 const std::vector<ui::ScaleFactor>& scale_factors, | 161 const std::vector<float>& favicon_scales, |
175 int favicon_size) { | 162 int favicon_size) { |
176 // Create image reps for as many scale factors as possible without resizing | 163 // Create image reps for as many scale factors as possible without resizing |
177 // the bitmap data or decoding it. FaviconHandler stores already resized | 164 // the bitmap data or decoding it. FaviconHandler stores already resized |
178 // favicons into history so no additional resizing should be needed in the | 165 // favicons into history so no additional resizing should be needed in the |
179 // common case. | 166 // common case. |
180 // Creating the gfx::Image from |png_data| without resizing or decoding if | 167 // Creating the gfx::Image from |png_data| without resizing or decoding if |
181 // possible is important because: | 168 // possible is important because: |
182 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to | 169 // - Sync does a byte-to-byte comparison of gfx::Image::As1xPNGBytes() to |
183 // the data it put into the database in order to determine whether any | 170 // the data it put into the database in order to determine whether any |
184 // updates should be pushed to sync. | 171 // updates should be pushed to sync. |
185 // - The decoding occurs on the UI thread and the decoding can be a | 172 // - The decoding occurs on the UI thread and the decoding can be a |
186 // significant performance hit if a user has many bookmarks. | 173 // significant performance hit if a user has many bookmarks. |
187 // TODO(pkotwicz): Move the decoding off the UI thread. | 174 // TODO(pkotwicz): Move the decoding off the UI thread. |
188 std::vector<gfx::ImagePNGRep> png_reps = | 175 std::vector<gfx::ImagePNGRep> png_reps = |
189 SelectFaviconFramesFromPNGsWithoutResizing( | 176 SelectFaviconFramesFromPNGsWithoutResizing( |
190 png_data, scale_factors, favicon_size); | 177 png_data, favicon_scales, favicon_size); |
191 | 178 |
192 // SelectFaviconFramesFromPNGsWithoutResizing() should have selected the | 179 // SelectFaviconFramesFromPNGsWithoutResizing() should have selected the |
193 // largest favicon if |favicon_size| == 0. | 180 // largest favicon if |favicon_size| == 0. |
194 if (favicon_size == 0) | 181 if (favicon_size == 0) |
195 return gfx::Image(png_reps); | 182 return gfx::Image(png_reps); |
196 | 183 |
197 std::vector<ui::ScaleFactor> scale_factors_to_generate = scale_factors; | 184 std::vector<float> favicon_scales_to_generate = favicon_scales; |
198 for (size_t i = 0; i < png_reps.size(); ++i) { | 185 for (size_t i = 0; i < png_reps.size(); ++i) { |
pkotwicz
2014/06/18 15:46:33
You can use std::find() here now?
oshima
2014/06/18 17:17:19
let me do it in separate CL. I'd like to keep this
| |
199 for (int j = static_cast<int>(scale_factors_to_generate.size()) - 1; j >= 0; | 186 for (int j = static_cast<int>(favicon_scales_to_generate.size()) - 1; |
187 j >= 0; | |
200 --j) { | 188 --j) { |
201 if (png_reps[i].scale == | 189 if (png_reps[i].scale == favicon_scales_to_generate[j]) { |
202 ui::GetScaleForScaleFactor(scale_factors_to_generate[j])) { | 190 favicon_scales_to_generate.erase(favicon_scales_to_generate.begin() + |
203 scale_factors_to_generate.erase(scale_factors_to_generate.begin() + j); | 191 j); |
204 } | 192 } |
205 } | 193 } |
206 } | 194 } |
207 | 195 |
208 if (scale_factors_to_generate.empty()) | 196 if (favicon_scales_to_generate.empty()) |
209 return gfx::Image(png_reps); | 197 return gfx::Image(png_reps); |
210 | 198 |
211 std::vector<SkBitmap> bitmaps; | 199 std::vector<SkBitmap> bitmaps; |
212 for (size_t i = 0; i < png_data.size(); ++i) { | 200 for (size_t i = 0; i < png_data.size(); ++i) { |
213 if (!png_data[i].is_valid()) | 201 if (!png_data[i].is_valid()) |
214 continue; | 202 continue; |
215 | 203 |
216 SkBitmap bitmap; | 204 SkBitmap bitmap; |
217 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), | 205 if (gfx::PNGCodec::Decode(png_data[i].bitmap_data->front(), |
218 png_data[i].bitmap_data->size(), | 206 png_data[i].bitmap_data->size(), |
219 &bitmap)) { | 207 &bitmap)) { |
220 bitmaps.push_back(bitmap); | 208 bitmaps.push_back(bitmap); |
221 } | 209 } |
222 } | 210 } |
223 | 211 |
224 if (bitmaps.empty()) | 212 if (bitmaps.empty()) |
225 return gfx::Image(); | 213 return gfx::Image(); |
226 | 214 |
227 gfx::ImageSkia resized_image_skia; | 215 gfx::ImageSkia resized_image_skia; |
228 for (size_t i = 0; i < scale_factors_to_generate.size(); ++i) { | 216 for (size_t i = 0; i < favicon_scales_to_generate.size(); ++i) { |
229 float scale = ui::GetScaleForScaleFactor(scale_factors_to_generate[i]); | 217 float scale = favicon_scales_to_generate[i]; |
230 int desired_size_in_pixel = ceil(favicon_size * scale); | 218 int desired_size_in_pixel = ceil(favicon_size * scale); |
231 SkBitmap bitmap = | 219 SkBitmap bitmap = |
232 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel); | 220 ResizeBitmapByDownsamplingIfPossible(bitmaps, desired_size_in_pixel); |
233 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); | 221 resized_image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); |
234 } | 222 } |
235 | 223 |
236 if (png_reps.empty()) | 224 if (png_reps.empty()) |
237 return gfx::Image(resized_image_skia); | 225 return gfx::Image(resized_image_skia); |
238 | 226 |
239 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps = | 227 std::vector<gfx::ImageSkiaRep> resized_image_skia_reps = |
240 resized_image_skia.image_reps(); | 228 resized_image_skia.image_reps(); |
241 for (size_t i = 0; i < resized_image_skia_reps.size(); ++i) { | 229 for (size_t i = 0; i < resized_image_skia_reps.size(); ++i) { |
242 scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes()); | 230 scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes()); |
243 if (gfx::PNGCodec::EncodeBGRASkBitmap( | 231 if (gfx::PNGCodec::EncodeBGRASkBitmap( |
244 resized_image_skia_reps[i].sk_bitmap(), | 232 resized_image_skia_reps[i].sk_bitmap(), |
245 false, | 233 false, |
246 &png_bytes->data())) { | 234 &png_bytes->data())) { |
247 png_reps.push_back( | 235 png_reps.push_back( |
248 gfx::ImagePNGRep(png_bytes, resized_image_skia_reps[i].scale())); | 236 gfx::ImagePNGRep(png_bytes, resized_image_skia_reps[i].scale())); |
249 } | 237 } |
250 } | 238 } |
251 | 239 |
252 return gfx::Image(png_reps); | 240 return gfx::Image(png_reps); |
253 } | 241 } |
254 | 242 |
255 } // namespace favicon_base | 243 } // namespace favicon_base |
OLD | NEW |