diff options
-rw-r--r-- | chrome/browser/favicon/favicon_handler.cc | 9 | ||||
-rw-r--r-- | chrome/browser/favicon/favicon_service.cc | 9 | ||||
-rw-r--r-- | chrome/browser/history/select_favicon_frames_unittest.cc | 137 | ||||
-rw-r--r-- | chrome/browser/ui/views/create_application_shortcut_view.cc | 25 | ||||
-rw-r--r-- | components/favicon_base/select_favicon_frames.cc | 152 | ||||
-rw-r--r-- | components/favicon_base/select_favicon_frames.h | 17 |
6 files changed, 209 insertions, 140 deletions
diff --git a/chrome/browser/favicon/favicon_handler.cc b/chrome/browser/favicon/favicon_handler.cc index dade696..18fa447 100644 --- a/chrome/browser/favicon/favicon_handler.cc +++ b/chrome/browser/favicon/favicon_handler.cc @@ -427,11 +427,10 @@ void FaviconHandler::OnDidDownloadFavicon( if (index != -1) image_skia = gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1)); } else { - image_skia = SelectFaviconFrames(bitmaps, - original_bitmap_sizes, - favicon_base::GetFaviconScales(), - preferred_icon_size(), - &score); + image_skia = CreateFaviconImageSkia(bitmaps, + original_bitmap_sizes, + preferred_icon_size(), + &score); } if (!image_skia.isNull()) { diff --git a/chrome/browser/favicon/favicon_service.cc b/chrome/browser/favicon/favicon_service.cc index 4df4387..994a62a 100644 --- a/chrome/browser/favicon/favicon_service.cc +++ b/chrome/browser/favicon/favicon_service.cc @@ -312,7 +312,15 @@ void FaviconService::SetFavicons(const GURL& page_url, image_skia.EnsureRepsForSupportedScales(); const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps(); std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data; + const std::vector<float> favicon_scales = favicon_base::GetFaviconScales(); for (size_t i = 0; i < image_reps.size(); ++i) { + // Don't save if the scale isn't one of supported favicon scale. + if (std::find(favicon_scales.begin(), + favicon_scales.end(), + image_reps[i].scale()) == favicon_scales.end()) { + continue; + } + scoped_refptr<base::RefCountedBytes> bitmap_data( new base::RefCountedBytes()); if (gfx::PNGCodec::EncodeBGRASkBitmap(image_reps[i].sk_bitmap(), @@ -328,7 +336,6 @@ void FaviconService::SetFavicons(const GURL& page_url, favicon_bitmap_data.push_back(bitmap_data_element); } } - history_service_->SetFavicons(page_url, icon_type, favicon_bitmap_data); } diff --git a/chrome/browser/history/select_favicon_frames_unittest.cc b/chrome/browser/history/select_favicon_frames_unittest.cc index 543dc21..822f4fa 100644 --- a/chrome/browser/history/select_favicon_frames_unittest.cc +++ b/chrome/browser/history/select_favicon_frames_unittest.cc @@ -7,22 +7,30 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/layout.h" #include "ui/gfx/image/image_skia.h" using std::vector; namespace { -vector<float> FaviconScale1x() { - return vector<float>(1, 1.0f); -} +const ui::ScaleFactor FaviconScaleFactor1x[] = { + ui::SCALE_FACTOR_100P, +}; -vector<float> FaviconScale1x2x() { - vector<float> scales; - scales.push_back(1.0f); - scales.push_back(2.0f); - return scales; -} +const ui::ScaleFactor FaviconScaleFactor1xAnd2x[] = { + ui::SCALE_FACTOR_100P, + ui::SCALE_FACTOR_200P, +}; + +#define SCOPED_FAVICON_SCALE_FACTOR(list) \ + ui::test::ScopedSetSupportedScaleFactors scoped( \ + std::vector<ui::ScaleFactor>(list, list + arraysize(list))) + +#define SCOPED_FAVICON_SCALE_FACTOR_1X \ + SCOPED_FAVICON_SCALE_FACTOR(FaviconScaleFactor1x) +#define SCOPED_FAVICON_SCALE_FACTOR_1XAND2X \ + SCOPED_FAVICON_SCALE_FACTOR(FaviconScaleFactor1xAnd2x) // Return gfx::Size vector with the pixel sizes of |bitmaps|. vector<gfx::Size> SizesFromBitmaps(const vector<SkBitmap>& bitmaps) { @@ -68,8 +76,8 @@ TEST(SelectFaviconFramesTest, ZeroSizePicksLargest) { bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 48, 48)); bitmaps.push_back(MakeBitmap(SK_ColorBLUE, 32, 32)); - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x(), 0, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 0, NULL); EXPECT_EQ(1u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); EXPECT_EQ(48, image.width()); @@ -79,28 +87,44 @@ TEST(SelectFaviconFramesTest, ZeroSizePicksLargest) { } TEST(SelectFaviconFramesTest, _16From16) { + SCOPED_FAVICON_SCALE_FACTOR_1X; + vector<SkBitmap> bitmaps; bitmaps.push_back(MakeBitmap(SK_ColorRED, 15, 15)); bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 16, 16)); bitmaps.push_back(MakeBitmap(SK_ColorBLUE, 17, 17)); - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x(), 16, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 16, NULL); + image.EnsureRepsForSupportedScales(); EXPECT_EQ(1u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); EXPECT_EQ(16, image.width()); EXPECT_EQ(16, image.height()); EXPECT_EQ(SK_ColorGREEN, GetColor1x(image)); + +#if !defined(OS_IOS) + const gfx::ImageSkiaRep& rep = image.GetRepresentation(1.5f); + EXPECT_EQ(1.5f, rep.scale()); + EXPECT_EQ(16, rep.GetWidth()); + EXPECT_EQ(16, rep.GetHeight()); + EXPECT_EQ(24, rep.pixel_width()); + EXPECT_EQ(24, rep.pixel_height()); + EXPECT_EQ(2u, image.image_reps().size()); +#endif } TEST(SelectFaviconFramesTest, _16From17) { + SCOPED_FAVICON_SCALE_FACTOR_1X; + vector<SkBitmap> bitmaps; bitmaps.push_back(MakeBitmap(SK_ColorRED, 15, 15)); bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 17, 17)); // Should resample from the bigger candidate. - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x(), 16, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 16, NULL); + image.EnsureRepsForSupportedScales(); EXPECT_EQ(1u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); EXPECT_EQ(16, image.width()); @@ -109,14 +133,17 @@ TEST(SelectFaviconFramesTest, _16From17) { } TEST(SelectFaviconFramesTest, _16From15) { + SCOPED_FAVICON_SCALE_FACTOR_1X; + vector<SkBitmap> bitmaps; bitmaps.push_back(MakeBitmap(SK_ColorRED, 14, 14)); bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 15, 15)); // If nothing else is available, should resample from the next smaller // candidate. - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x(), 16, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 16, NULL); + image.EnsureRepsForSupportedScales(); EXPECT_EQ(1u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); EXPECT_EQ(16, image.width()); @@ -125,11 +152,13 @@ TEST(SelectFaviconFramesTest, _16From15) { } TEST(SelectFaviconFramesTest, _16From16_Scale2x_32_From_16) { + SCOPED_FAVICON_SCALE_FACTOR_1XAND2X; vector<SkBitmap> bitmaps; bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 16, 16)); - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x2x(), 16, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 16, NULL); + image.EnsureRepsForSupportedScales(); EXPECT_EQ(2u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); ASSERT_TRUE(image.HasRepresentation(2.0f)); @@ -140,12 +169,15 @@ TEST(SelectFaviconFramesTest, _16From16_Scale2x_32_From_16) { } TEST(SelectFaviconFramesTest, _16From16_Scale2x_32_From_32) { + SCOPED_FAVICON_SCALE_FACTOR_1XAND2X; + vector<SkBitmap> bitmaps; bitmaps.push_back(MakeBitmap(SK_ColorGREEN, 16, 16)); bitmaps.push_back(MakeBitmap(SK_ColorBLUE, 32, 32)); - gfx::ImageSkia image = SelectFaviconFrames(bitmaps, - SizesFromBitmaps(bitmaps), FaviconScale1x2x(), 16, NULL); + gfx::ImageSkia image = CreateFaviconImageSkia(bitmaps, + SizesFromBitmaps(bitmaps), 16, NULL); + image.EnsureRepsForSupportedScales(); EXPECT_EQ(2u, image.image_reps().size()); ASSERT_TRUE(image.HasRepresentation(1.0f)); ASSERT_TRUE(image.HasRepresentation(2.0f)); @@ -153,21 +185,32 @@ TEST(SelectFaviconFramesTest, _16From16_Scale2x_32_From_32) { EXPECT_EQ(16, image.height()); EXPECT_EQ(SK_ColorGREEN, GetColor1x(image)); EXPECT_EQ(SK_ColorBLUE, GetColor2x(image)); + +#if !defined(OS_IOS) + const gfx::ImageSkiaRep& rep = image.GetRepresentation(1.5f); + EXPECT_EQ(1.5f, rep.scale()); + EXPECT_EQ(16, rep.GetWidth()); + EXPECT_EQ(16, rep.GetHeight()); + EXPECT_EQ(24, rep.pixel_width()); + EXPECT_EQ(24, rep.pixel_height()); + EXPECT_EQ(3u, image.image_reps().size()); +#endif } TEST(SelectFaviconFramesTest, ExactMatchBetterThanLargeBitmap) { float score1; vector<SkBitmap> bitmaps1; bitmaps1.push_back(MakeBitmap(SK_ColorGREEN, 48, 48)); - SelectFaviconFrames(bitmaps1, - SizesFromBitmaps(bitmaps1), FaviconScale1x2x(), 16, &score1); + CreateFaviconImageSkia( + bitmaps1, + SizesFromBitmaps(bitmaps1), 16, &score1); float score2; vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 16, 16)); bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 32, 32)); - SelectFaviconFrames(bitmaps2, - SizesFromBitmaps(bitmaps2), FaviconScale1x2x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, + SizesFromBitmaps(bitmaps2), 16, &score2); EXPECT_GT(score2, score1); } @@ -176,26 +219,26 @@ TEST(SelectFaviconFramesTest, UpsampleABitBetterThanHugeBitmap) { float score1; vector<SkBitmap> bitmaps1; bitmaps1.push_back(MakeBitmap(SK_ColorGREEN, 128, 128)); - SelectFaviconFrames(bitmaps1, - SizesFromBitmaps(bitmaps1), FaviconScale1x2x(), 16, &score1); + CreateFaviconImageSkia(bitmaps1, + SizesFromBitmaps(bitmaps1), 16, &score1); float score2; vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 24, 24)); - SelectFaviconFrames(bitmaps2, - SizesFromBitmaps(bitmaps2), FaviconScale1x2x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, + SizesFromBitmaps(bitmaps2), 16, &score2); float score3; vector<SkBitmap> bitmaps3; bitmaps3.push_back(MakeBitmap(SK_ColorGREEN, 16, 16)); - SelectFaviconFrames(bitmaps3, - SizesFromBitmaps(bitmaps3), FaviconScale1x2x(), 16, &score3); + CreateFaviconImageSkia(bitmaps3, + SizesFromBitmaps(bitmaps3), 16, &score3); float score4; vector<SkBitmap> bitmaps4; bitmaps4.push_back(MakeBitmap(SK_ColorGREEN, 15, 15)); - SelectFaviconFrames(bitmaps4, - SizesFromBitmaps(bitmaps4), FaviconScale1x2x(), 16, &score4); + CreateFaviconImageSkia(bitmaps4, + SizesFromBitmaps(bitmaps4), 16, &score4); EXPECT_GT(score2, score1); EXPECT_GT(score3, score1); @@ -206,14 +249,14 @@ TEST(SelectFaviconFramesTest, DownsamplingBetterThanUpsampling) { float score1; vector<SkBitmap> bitmaps1; bitmaps1.push_back(MakeBitmap(SK_ColorGREEN, 8, 8)); - SelectFaviconFrames(bitmaps1, - SizesFromBitmaps(bitmaps1), FaviconScale1x(), 16, &score1); + CreateFaviconImageSkia(bitmaps1, + SizesFromBitmaps(bitmaps1), 16, &score1); float score2; vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 24, 24)); - SelectFaviconFrames(bitmaps2, - SizesFromBitmaps(bitmaps2), FaviconScale1x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, + SizesFromBitmaps(bitmaps2), 16, &score2); EXPECT_GT(score2, score1); } @@ -222,14 +265,14 @@ TEST(SelectFaviconFramesTest, DownsamplingLessIsBetter) { float score1; vector<SkBitmap> bitmaps1; bitmaps1.push_back(MakeBitmap(SK_ColorGREEN, 34, 34)); - SelectFaviconFrames(bitmaps1, - SizesFromBitmaps(bitmaps1), FaviconScale1x2x(), 16, &score1); + CreateFaviconImageSkia(bitmaps1, + SizesFromBitmaps(bitmaps1), 16, &score1); float score2; vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 33, 33)); - SelectFaviconFrames(bitmaps2, - SizesFromBitmaps(bitmaps2), FaviconScale1x2x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, + SizesFromBitmaps(bitmaps2), 16, &score2); EXPECT_GT(score2, score1); } @@ -238,14 +281,14 @@ TEST(SelectFaviconFramesTest, UpsamplingLessIsBetter) { float score1; vector<SkBitmap> bitmaps1; bitmaps1.push_back(MakeBitmap(SK_ColorGREEN, 8, 8)); - SelectFaviconFrames(bitmaps1, - SizesFromBitmaps(bitmaps1), FaviconScale1x2x(), 16, &score1); + CreateFaviconImageSkia(bitmaps1, + SizesFromBitmaps(bitmaps1), 16, &score1); float score2; vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 9, 9)); - SelectFaviconFrames(bitmaps2, - SizesFromBitmaps(bitmaps2), FaviconScale1x2x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, + SizesFromBitmaps(bitmaps2), 16, &score2); EXPECT_GT(score2, score1); } @@ -258,14 +301,14 @@ TEST(SelectFaviconFramesTest, ScoreDeterminedByOriginalSizes) { vector<gfx::Size> sizes1; sizes1.push_back(gfx::Size(256, 256)); float score1; - SelectFaviconFrames(bitmaps1, sizes1, FaviconScale1x(), 16, &score1); + CreateFaviconImageSkia(bitmaps1, sizes1, 16, &score1); vector<SkBitmap> bitmaps2; bitmaps2.push_back(MakeBitmap(SK_ColorGREEN, 15, 15)); vector<gfx::Size> sizes2; sizes2.push_back(gfx::Size(15, 15)); float score2; - SelectFaviconFrames(bitmaps2, sizes2, FaviconScale1x(), 16, &score2); + CreateFaviconImageSkia(bitmaps2, sizes2, 16, &score2); EXPECT_GT(score2, score1); } diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index 550faa4..360c908 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc @@ -495,24 +495,13 @@ void CreateUrlApplicationShortcutView::DidDownloadFavicon( return; pending_download_id_ = -1; - SkBitmap image; - - if (!bitmaps.empty()) { - std::vector<int> requested_sizes_in_pixel; - float scale = ui::GetScaleFactorForNativeView( - web_contents_->GetRenderViewHost()->GetView()->GetNativeView()); - requested_sizes_in_pixel.push_back(ceil(requested_size * scale)); - std::vector<size_t> closest_indices; - SelectFaviconFrameIndices(original_bitmap_sizes, - requested_sizes_in_pixel, - &closest_indices, - NULL); - size_t closest_index = closest_indices[0]; - image = bitmaps[closest_index]; - } - - if (!image.isNull()) { - shortcut_info_.favicon.Add(gfx::ImageSkia::CreateFrom1xBitmap(image)); + gfx::ImageSkia image_skia = CreateFaviconImageSkia( + bitmaps, + original_bitmap_sizes, + requested_size, + NULL); + if (!image_skia.isNull()) { + shortcut_info_.favicon.Add(image_skia); static_cast<AppInfoView*>(app_info_)->UpdateIcon(shortcut_info_.favicon); } else { FetchIcon(); diff --git a/components/favicon_base/select_favicon_frames.cc b/components/favicon_base/select_favicon_frames.cc index 0315408..3122365 100644 --- a/components/favicon_base/select_favicon_frames.cc +++ b/components/favicon_base/select_favicon_frames.cc @@ -10,10 +10,12 @@ #include <map> #include <set> +#include "components/favicon_base/favicon_util.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_skia_source.h" #include "ui/gfx/size.h" namespace { @@ -47,13 +49,10 @@ SkBitmap SampleNearestNeighbor(const SkBitmap& contents, int desired_size) { return bitmap; } -enum ResizeMethod { NONE, SAMPLE_NEAREST_NEIGHBOUR, LANCZOS }; - size_t GetCandidateIndexWithBestScore( const std::vector<gfx::Size>& candidate_sizes, int desired_size, - float* score, - ResizeMethod* resize_method) { + float* score) { DCHECK_NE(desired_size, 0); // Try to find an exact match. @@ -61,7 +60,6 @@ size_t GetCandidateIndexWithBestScore( if (candidate_sizes[i].width() == desired_size && candidate_sizes[i].height() == desired_size) { *score = 1; - *resize_method = NONE; return i; } } @@ -99,17 +97,6 @@ size_t GetCandidateIndexWithBestScore( } *score = candidate_score; - // Integer multiples are built using nearest neighbor sampling. Otherwise, - // Lanczos scaling is used. - const gfx::Size& candidate_size = candidate_sizes[candidate_index]; - if (candidate_size.IsEmpty()) { - *resize_method = NONE; - } else if (desired_size % candidate_size.width() == 0 && - desired_size % candidate_size.height() == 0) { - *resize_method = SAMPLE_NEAREST_NEIGHBOUR; - } else { - *resize_method = LANCZOS; - } return candidate_index; } @@ -121,10 +108,6 @@ struct SelectionResult { // The desired size for which |index| is the best candidate. int desired_size; - - // How the bitmap data that the bitmap with |candidate_sizes[index]| should - // be resized for displaying in the UI. - ResizeMethod resize_method; }; void GetCandidateIndicesWithBestScores( @@ -145,7 +128,6 @@ void GetCandidateIndicesWithBestScores( SelectionResult result; result.index = BiggestCandidate(candidate_sizes); result.desired_size = 0; - result.resize_method = NONE; results->push_back(result); if (match_score) *match_score = 1.0f; @@ -158,7 +140,7 @@ void GetCandidateIndicesWithBestScores( SelectionResult result; result.desired_size = desired_sizes[i]; result.index = GetCandidateIndexWithBestScore( - candidate_sizes, result.desired_size, &score, &result.resize_method); + candidate_sizes, result.desired_size, &score); results->push_back(result); total_score += score; } @@ -167,65 +149,111 @@ void GetCandidateIndicesWithBestScores( *match_score = total_score / desired_sizes.size(); } -// Resize |source_bitmap| using |resize_method|. +// Resize |source_bitmap| SkBitmap GetResizedBitmap(const SkBitmap& source_bitmap, - int desired_size, - ResizeMethod resize_method) { - switch (resize_method) { - case NONE: - return source_bitmap; - case SAMPLE_NEAREST_NEIGHBOUR: - return SampleNearestNeighbor(source_bitmap, desired_size); - case LANCZOS: - return skia::ImageOperations::Resize( - source_bitmap, - skia::ImageOperations::RESIZE_LANCZOS3, - desired_size, - desired_size); + gfx::Size original_size, + int desired_size_in_pixel) { + if (desired_size_in_pixel == 0 || + (original_size.width() == desired_size_in_pixel && + original_size.height() == desired_size_in_pixel)) { + return source_bitmap; + } + if (desired_size_in_pixel % original_size.width() == 0 && + desired_size_in_pixel % original_size.height() == 0) { + return SampleNearestNeighbor(source_bitmap, desired_size_in_pixel); } - return source_bitmap; + return skia::ImageOperations::Resize(source_bitmap, + skia::ImageOperations::RESIZE_LANCZOS3, + desired_size_in_pixel, + desired_size_in_pixel); } +class FaviconImageSource : public gfx::ImageSkiaSource { + public: + FaviconImageSource() {} + virtual ~FaviconImageSource() {} + + // gfx::ImageSkiaSource: + virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE { + const gfx::ImageSkiaRep* rep = NULL; + // gfx::ImageSkia passes one of the resource scale factors. The source + // should return: + // 1) The ImageSkiaRep with the highest scale if all available + // scales are smaller than |scale|. + // 2) The ImageSkiaRep with the smallest one that is larger than |scale|. + // Note: Keep this logic consistent with the PNGImageSource in + // ui/gfx/image.cc. + // TODO(oshima): consolidate these logic into one place. + for (std::vector<gfx::ImageSkiaRep>::const_iterator iter = + image_skia_reps_.begin(); + iter != image_skia_reps_.end(); ++iter) { + if ((*iter).scale() == scale) + return (*iter); + if (!rep || rep->scale() < (*iter).scale()) + rep = &(*iter); + if (rep->scale() >= scale) + break; + } + DCHECK(rep); + return rep ? *rep : gfx::ImageSkiaRep(); + } + + void AddImageSkiaRep(const gfx::ImageSkiaRep& rep) { + image_skia_reps_.push_back(rep); + } + + private: + std::vector<gfx::ImageSkiaRep> image_skia_reps_; + DISALLOW_COPY_AND_ASSIGN(FaviconImageSource); +}; + } // namespace const float kSelectFaviconFramesInvalidScore = -1.0f; -gfx::ImageSkia SelectFaviconFrames(const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& original_sizes, - const std::vector<float>& favicon_scales, - int desired_size_in_dip, - float* match_score) { +gfx::ImageSkia CreateFaviconImageSkia( + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& original_sizes, + int desired_size_in_dip, + float* score) { + + const std::vector<float>& favicon_scales = favicon_base::GetFaviconScales(); std::vector<int> desired_sizes; - std::map<int, float> scale_map; + if (desired_size_in_dip == 0) { desired_sizes.push_back(0); - scale_map[0] = 1.0f; } else { - for (size_t i = 0; i < favicon_scales.size(); ++i) { - float scale = favicon_scales[i]; - int desired_size = ceil(desired_size_in_dip * scale); - desired_sizes.push_back(desired_size); - scale_map[desired_size] = scale; + for (std::vector<float>::const_iterator iter = favicon_scales.begin(); + iter != favicon_scales.end(); ++iter) { + desired_sizes.push_back(ceil(desired_size_in_dip * (*iter))); } } std::vector<SelectionResult> results; - GetCandidateIndicesWithBestScores( - original_sizes, desired_sizes, match_score, &results); + GetCandidateIndicesWithBestScores(original_sizes, + desired_sizes, + score, + &results); + if (results.size() == 0) + return gfx::ImageSkia(); + + if (desired_size_in_dip == 0) { + size_t index = results[0].index; + return gfx::ImageSkia(gfx::ImageSkiaRep(bitmaps[index], 1.0f)); + } + + FaviconImageSource* image_source = new FaviconImageSource; - gfx::ImageSkia multi_image; for (size_t i = 0; i < results.size(); ++i) { - const SelectionResult& result = results[i]; - SkBitmap resized_bitmap = GetResizedBitmap( - bitmaps[result.index], result.desired_size, result.resize_method); - - std::map<int, float>::const_iterator it = - scale_map.find(result.desired_size); - DCHECK(it != scale_map.end()); - float scale = it->second; - multi_image.AddRepresentation(gfx::ImageSkiaRep(resized_bitmap, scale)); + size_t index = results[i].index; + image_source->AddImageSkiaRep( + gfx::ImageSkiaRep(GetResizedBitmap(bitmaps[index], + original_sizes[index], + desired_sizes[i]), + favicon_scales[i])); } - return multi_image; + return gfx::ImageSkia(image_source, + gfx::Size(desired_size_in_dip, desired_size_in_dip)); } void SelectFaviconFrameIndices(const std::vector<gfx::Size>& frame_pixel_sizes, diff --git a/components/favicon_base/select_favicon_frames.h b/components/favicon_base/select_favicon_frames.h index 9c1b80e..81d39d85 100644 --- a/components/favicon_base/select_favicon_frames.h +++ b/components/favicon_base/select_favicon_frames.h @@ -21,8 +21,9 @@ class Size; extern const float kSelectFaviconFramesInvalidScore; // Takes a list of all bitmaps found in a .ico file, and creates an -// ImageSkia that's |desired_size_in_dip| x |desired_size_in_dip| big. This -// function adds a representation at every entry in |favicon_scales|. +// ImageSkia that's |desired_size_in_dip| x |desired_size_in_dip| big. +// Bitmaps are selected by using |SelectFaviconFrameIndices| and the +// platform's supported favicon scales (favicon_base::GetFaviconScales()). // If |desired_size_in_dip| is 0, the largest bitmap is returned unmodified. // |original_sizes| are the original sizes of the bitmaps. (For instance, // WebContents::DownloadImage() does resampling if it is passed a max size.) @@ -34,11 +35,13 @@ extern const float kSelectFaviconFramesInvalidScore; // If the resampling algorithm is modified, the resampling done in // FaviconUtil::SelectFaviconFramesFromPNGs() should probably be modified too as // it inspired by this method. -gfx::ImageSkia SelectFaviconFrames(const std::vector<SkBitmap>& bitmaps, - const std::vector<gfx::Size>& original_sizes, - const std::vector<float>& favicon_scales, - int desired_size_in_dip, - float* score); +// If an unsupported scale (not in the favicon_base::GetFaviconScales()) +// is requested, the ImageSkia will automatically scales using lancoz3. +gfx::ImageSkia CreateFaviconImageSkia( + const std::vector<SkBitmap>& bitmaps, + const std::vector<gfx::Size>& original_sizes, + int desired_size_in_dip, + float* score); // Takes a list of the pixel sizes of a favicon's favicon bitmaps and returns // the indices of the best sizes to use to create an ImageSkia with |