Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: chrome/browser/manifest/manifest_icon_selector.cc

Issue 2662103002: Refactor ManifestIconSelector and update it for Manifest.icon.purpose (Closed)
Patch Set: Addressing comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "chrome/browser/manifest/manifest_icon_selector.h" 5 #include "chrome/browser/manifest/manifest_icon_selector.h"
6 6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <cmath>
11 #include <limits> 7 #include <limits>
12 8
9 #include "base/stl_util.h"
13 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
14 #include "components/mime_util/mime_util.h" 11 #include "components/mime_util/mime_util.h"
15 #include "content/public/browser/web_contents.h"
16 12
17 using content::Manifest; 13 // static
14 GURL ManifestIconSelector::FindBestMatchingIcon(
15 const std::vector<content::Manifest::Icon>& icons,
16 int ideal_icon_size_in_px,
17 int minimum_icon_size_in_px,
18 content::Manifest::Icon::IconPurpose purpose) {
19 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
18 20
19 ManifestIconSelector::ManifestIconSelector(int ideal_icon_size_in_px, 21 // Icon with exact matching size has priority over icon with size "any", which
20 int minimum_icon_size_in_px) 22 // has priority over icon with closest matching size.
21 : ideal_icon_size_in_px_(ideal_icon_size_in_px), 23 int latest_size_any_index = -1;
22 minimum_icon_size_in_px_(minimum_icon_size_in_px) { 24 int closest_size_match_index = -1;
23 } 25 int best_delta_in_size = std::numeric_limits<int>::min();
24
25 bool ManifestIconSelector::IconSizesContainsPreferredSize(
26 const std::vector<gfx::Size>& sizes) const {
27 for (size_t i = 0; i < sizes.size(); ++i) {
28 if (sizes[i].height() != sizes[i].width())
29 continue;
30 if (sizes[i].width() == ideal_icon_size_in_px_)
31 return true;
32 }
33
34 return false;
35 }
36
37 bool ManifestIconSelector::IconSizesContainsBiggerThanMinimumSize(
38 const std::vector<gfx::Size>& sizes) const {
39 for (size_t i = 0; i < sizes.size(); ++i) {
40 if (sizes[i].height() != sizes[i].width())
41 continue;
42 if (sizes[i].width() >= minimum_icon_size_in_px_)
43 return true;
44 }
45 return false;
46 }
47
48 int ManifestIconSelector::FindClosestIconToIdealSize(
49 const std::vector<content::Manifest::Icon>& icons) const {
50 int best_index = -1;
51 int best_delta = std::numeric_limits<int>::min();
52 26
53 for (size_t i = 0; i < icons.size(); ++i) { 27 for (size_t i = 0; i < icons.size(); ++i) {
54 const std::vector<gfx::Size>& sizes = icons[i].sizes; 28 const auto& icon = icons[i];
55 for (size_t j = 0; j < sizes.size(); ++j) { 29
56 if (sizes[j].height() != sizes[j].width()) 30 // Check for supported image MIME types.
31 if (!icon.type.empty() &&
32 !mime_util::IsSupportedImageMimeType(base::UTF16ToUTF8(icon.type))) {
33 continue;
34 }
35
36 // Check for icon purpose.
37 if (!base::ContainsValue(icon.purpose, purpose))
38 continue;
39
40 // Check for size constraints.
41 for (const gfx::Size& size : icon.sizes) {
42 // Check for size "any". Return this icon if no better one is found.
43 if (size.IsEmpty()) {
44 latest_size_any_index = i;
57 continue; 45 continue;
58 int delta = sizes[j].width() - ideal_icon_size_in_px_; 46 }
59 if (delta == 0) 47
60 return i; 48 // Check for squareness.
61 if (best_delta > 0 && delta < 0) 49 if (size.width() != size.height())
62 continue; 50 continue;
63 if ((best_delta > 0 && delta < best_delta) || 51
64 (best_delta < 0 && delta > best_delta)) { 52 // Check for minimum size.
65 best_index = i; 53 if (size.width() < minimum_icon_size_in_px)
66 best_delta = delta; 54 continue;
55
56 // Check for ideal size. Return this icon immediately.
57 if (size.width() == ideal_icon_size_in_px)
58 return icon.src;
59
60 // Check for closest match.
61 int delta = size.width() - ideal_icon_size_in_px;
62
63 // Smallest icon larger than ideal size has priority over largest icon
64 // smaller than ideal size.
65 if (best_delta_in_size > 0 && delta < 0)
66 continue;
67
68 if ((best_delta_in_size > 0 && delta < best_delta_in_size) ||
69 (best_delta_in_size < 0 && delta > best_delta_in_size)) {
70 closest_size_match_index = i;
71 best_delta_in_size = delta;
67 } 72 }
68 } 73 }
69 } 74 }
70 75
71 return best_index; 76 if (latest_size_any_index != -1)
77 return icons[latest_size_any_index].src;
78 else if (closest_size_match_index != -1)
79 return icons[closest_size_match_index].src;
80 else
81 return GURL();
72 } 82 }
73
74 int ManifestIconSelector::FindBestMatchingIcon(
75 const std::vector<content::Manifest::Icon>& icons) const {
76 int best_index = -1;
77
78 // The first pass is to find the ideal icon - one with the exact right size.
79 for (size_t i = 0; i < icons.size(); ++i) {
80 if (IconSizesContainsPreferredSize(icons[i].sizes))
81 return i;
82
83 // If there is an icon size 'any', keep it on the side and only use it if
84 // nothing better is found.
85 if (IconSizesContainsAny(icons[i].sizes))
86 best_index = i;
87 }
88 if (best_index != -1)
89 return best_index;
90
91 // The last pass will try to find the smallest icon larger than the ideal
92 // size, or the largest icon smaller than the ideal size.
93 best_index = FindClosestIconToIdealSize(icons);
94
95 if (best_index != -1 &&
96 IconSizesContainsBiggerThanMinimumSize(icons[best_index].sizes))
97 return best_index;
98
99 return -1;
100 }
101
102
103 // static
104 bool ManifestIconSelector::IconSizesContainsAny(
105 const std::vector<gfx::Size>& sizes) {
106 for (size_t i = 0; i < sizes.size(); ++i) {
107 if (sizes[i].IsEmpty())
108 return true;
109 }
110 return false;
111 }
112
113 // static
114 std::vector<Manifest::Icon> ManifestIconSelector::FilterIconsByType(
115 const std::vector<content::Manifest::Icon>& icons) {
116 std::vector<Manifest::Icon> result;
117
118 for (size_t i = 0; i < icons.size(); ++i) {
119 if (icons[i].type.empty() ||
120 mime_util::IsSupportedImageMimeType(base::UTF16ToUTF8(icons[i].type))) {
121 result.push_back(icons[i]);
122 }
123 }
124
125 return result;
126 }
127
128 // static
129 GURL ManifestIconSelector::FindBestMatchingIcon(
130 const std::vector<Manifest::Icon>& unfiltered_icons,
131 const int ideal_icon_size_in_px,
132 const int minimum_icon_size_in_px) {
133 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
134
135 std::vector<Manifest::Icon> icons =
136 ManifestIconSelector::FilterIconsByType(unfiltered_icons);
137
138 ManifestIconSelector selector(ideal_icon_size_in_px,
139 minimum_icon_size_in_px);
140 int index = selector.FindBestMatchingIcon(icons);
141 if (index == -1)
142 return GURL();
143 return icons[index].src;
144 }
OLDNEW
« no previous file with comments | « chrome/browser/manifest/manifest_icon_selector.h ('k') | chrome/browser/manifest/manifest_icon_selector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698