diff options
Diffstat (limited to 'components/favicon_base')
-rw-r--r-- | components/favicon_base/select_favicon_frames.cc | 152 | ||||
-rw-r--r-- | components/favicon_base/select_favicon_frames.h | 17 |
2 files changed, 100 insertions, 69 deletions
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 |