| 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 |