diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-24 21:57:46 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-24 21:57:46 +0000 |
commit | e40d04ad09472f40837011cf9746f71af8a3924a (patch) | |
tree | 3a9e1202c0058f32396d334ee15f642a7779ee32 /components/favicon_base | |
parent | 3c1759548dece0cc6cac2e359920d55c801163ce (diff) | |
download | chromium_src-e40d04ad09472f40837011cf9746f71af8a3924a.zip chromium_src-e40d04ad09472f40837011cf9746f71af8a3924a.tar.gz chromium_src-e40d04ad09472f40837011cf9746f71af8a3924a.tar.bz2 |
Create ImageSkia for favicons that can be scaled to one that is not in resource scales.
Replaces SelectFaviconFrames with new function because new ImageSkia instance should be able to handle all cases.
This depends on https://codereview.chromium.org/335233003/.
BUG=376367,381601
TEST=WIP
Review URL: https://codereview.chromium.org/346013002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279507 0039d316-1c4b-4281-b951-d872f2087c98
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 |