Index: chrome/browser/manifest/manifest_icon_selector.cc |
diff --git a/chrome/browser/manifest/manifest_icon_selector.cc b/chrome/browser/manifest/manifest_icon_selector.cc |
index 7e3bd1f900508d23abdba6ff4efb41443fff4285..67f9024c47ad8a5508585c0f04cc4f0d96bc83a8 100644 |
--- a/chrome/browser/manifest/manifest_icon_selector.cc |
+++ b/chrome/browser/manifest/manifest_icon_selector.cc |
@@ -4,6 +4,8 @@ |
#include "chrome/browser/manifest/manifest_icon_selector.h" |
+#include <algorithm> |
+#include <cmath> |
#include <limits> |
#include "base/strings/utf_string_conversions.h" |
@@ -13,8 +15,10 @@ |
using content::Manifest; |
-ManifestIconSelector::ManifestIconSelector(float preferred_icon_size_in_pixels) |
- : preferred_icon_size_in_pixels_(preferred_icon_size_in_pixels) { |
+ManifestIconSelector::ManifestIconSelector(float preferred_icon_size_in_pixels, |
+ float minimum_icon_size_in_pixels) |
+ : preferred_icon_size_in_pixels_(preferred_icon_size_in_pixels), |
+ minimum_icon_size_in_pixels_(minimum_icon_size_in_pixels) { |
} |
bool ManifestIconSelector::IconSizesContainsPreferredSize( |
@@ -29,10 +33,21 @@ bool ManifestIconSelector::IconSizesContainsPreferredSize( |
return false; |
} |
-GURL ManifestIconSelector::FindBestMatchingIconForDensity( |
+bool ManifestIconSelector::IconSizesContainsBiggerThanMinimumSize( |
+ const std::vector<gfx::Size>& sizes) { |
+ for (size_t i = 0; i < sizes.size(); ++i) { |
+ if (sizes[i].height() != sizes[i].width()) |
+ continue; |
+ if (sizes[i].width() >= minimum_icon_size_in_pixels_) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+int ManifestIconSelector::FindBestMatchingIconForDensity( |
const std::vector<content::Manifest::Icon>& icons, |
float density) { |
- GURL url; |
+ int best_index = -1; |
int best_delta = std::numeric_limits<int>::min(); |
for (size_t i = 0; i < icons.size(); ++i) { |
@@ -45,67 +60,77 @@ GURL ManifestIconSelector::FindBestMatchingIconForDensity( |
continue; |
int delta = sizes[j].width() - preferred_icon_size_in_pixels_; |
if (delta == 0) |
- return icons[i].src; |
+ return i; |
if (best_delta > 0 && delta < 0) |
continue; |
if ((best_delta > 0 && delta < best_delta) || |
(best_delta < 0 && delta > best_delta)) { |
- url = icons[i].src; |
+ best_index = i; |
best_delta = delta; |
} |
} |
} |
- return url; |
+ return best_index; |
} |
-GURL ManifestIconSelector::FindBestMatchingIcon( |
- const std::vector<content::Manifest::Icon>& unfiltered_icons, |
+int ManifestIconSelector::FindBestMatchingIcon( |
+ const std::vector<content::Manifest::Icon>& icons, |
float density) { |
- GURL url; |
- std::vector<Manifest::Icon> icons = FilterIconsByType(unfiltered_icons); |
+ int best_index = -1; |
// The first pass is to find the ideal icon. That icon is of the right size |
// with the default density or the device's density. |
for (size_t i = 0; i < icons.size(); ++i) { |
if (icons[i].density == density && |
IconSizesContainsPreferredSize(icons[i].sizes)) { |
- return icons[i].src; |
+ return i; |
} |
// If there is an icon with the right size but not the right density, keep |
// it on the side and only use it if nothing better is found. |
if (icons[i].density == Manifest::Icon::kDefaultDensity && |
IconSizesContainsPreferredSize(icons[i].sizes)) { |
- url = icons[i].src; |
+ best_index = i; |
} |
} |
+ if (best_index != -1) |
+ return best_index; |
+ |
// The second pass is to find an icon with 'any'. The current device scale |
// factor is preferred. Otherwise, the default scale factor is used. |
for (size_t i = 0; i < icons.size(); ++i) { |
if (icons[i].density == density && |
IconSizesContainsAny(icons[i].sizes)) { |
- return icons[i].src; |
+ return i; |
} |
// If there is an icon with 'any' but not the right density, keep it on the |
// side and only use it if nothing better is found. |
if (icons[i].density == Manifest::Icon::kDefaultDensity && |
IconSizesContainsAny(icons[i].sizes)) { |
- url = icons[i].src; |
+ best_index = i; |
} |
} |
+ if (best_index != -1) |
+ return best_index; |
+ |
// The last pass will try to find the best suitable icon for the device's |
// scale factor. If none, another pass will be run using kDefaultDensity. |
- if (!url.is_valid()) |
- url = FindBestMatchingIconForDensity(icons, density); |
- if (!url.is_valid()) |
- url = FindBestMatchingIconForDensity(icons, |
- Manifest::Icon::kDefaultDensity); |
- |
- return url; |
+ best_index = FindBestMatchingIconForDensity(icons, density); |
+ if (best_index != -1 && |
+ IconSizesContainsBiggerThanMinimumSize(icons[best_index].sizes)) |
+ return best_index; |
+ |
+ best_index = FindBestMatchingIconForDensity(icons, |
+ Manifest::Icon::kDefaultDensity); |
+ if (best_index != -1 && |
+ IconSizesContainsBiggerThanMinimumSize(icons[best_index].sizes)) |
+ return best_index; |
+ |
+ return -1; |
} |
@@ -116,7 +141,6 @@ bool ManifestIconSelector::IconSizesContainsAny( |
if (sizes[i].IsEmpty()) |
return true; |
} |
- |
return false; |
} |
@@ -146,6 +170,18 @@ GURL ManifestIconSelector::FindBestMatchingIcon( |
const float preferred_icon_size_in_pixels = |
preferred_icon_size_in_dp * device_scale_factor; |
- ManifestIconSelector selector(preferred_icon_size_in_pixels); |
- return selector.FindBestMatchingIcon(unfiltered_icons, device_scale_factor); |
+ const int minimum_scale_factor = std::max( |
+ static_cast<int>(floor(device_scale_factor - 1)), 1); |
+ const float minimum_icon_size_in_pixels = |
+ preferred_icon_size_in_dp * minimum_scale_factor; |
+ |
+ std::vector<Manifest::Icon> icons = |
+ ManifestIconSelector::FilterIconsByType(unfiltered_icons); |
+ |
+ ManifestIconSelector selector(preferred_icon_size_in_pixels, |
+ minimum_icon_size_in_pixels); |
+ int index = selector.FindBestMatchingIcon(icons, device_scale_factor); |
+ if (index == -1) |
+ return GURL(); |
+ return icons[index].src; |
} |