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