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

Side by Side Diff: chrome/browser/extensions/bookmark_app_helper.cc

Issue 246333006: Implement new bookmark app icon generation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 8 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/extensions/bookmark_app_helper.h" 5 #include "chrome/browser/extensions/bookmark_app_helper.h"
6 6
7 #include <cctype>
8
7 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/chrome_notification_types.h" 10 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/extensions/crx_installer.h" 11 #include "chrome/browser/extensions/crx_installer.h"
10 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/favicon_downloader.h" 13 #include "chrome/browser/extensions/favicon_downloader.h"
12 #include "chrome/browser/extensions/tab_helper.h" 14 #include "chrome/browser/extensions/tab_helper.h"
13 #include "chrome/common/extensions/extension_constants.h" 15 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 16 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
15 #include "content/public/browser/notification_service.h" 17 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
17 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
18 #include "extensions/common/extension.h" 20 #include "extensions/common/extension.h"
19 #include "extensions/common/manifest_handlers/icons_handler.h" 21 #include "extensions/common/manifest_handlers/icons_handler.h"
20 #include "extensions/common/url_pattern.h" 22 #include "extensions/common/url_pattern.h"
23 #include "grit/app_locale_settings.h"
24 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
21 #include "skia/ext/image_operations.h" 25 #include "skia/ext/image_operations.h"
22 #include "skia/ext/platform_canvas.h" 26 #include "skia/ext/platform_canvas.h"
23 #include "third_party/skia/include/core/SkBitmap.h" 27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/gfx/canvas.h"
24 #include "ui/gfx/color_analysis.h" 31 #include "ui/gfx/color_analysis.h"
32 #include "ui/gfx/color_utils.h"
33 #include "ui/gfx/font.h"
34 #include "ui/gfx/font_list.h"
25 #include "ui/gfx/image/image.h" 35 #include "ui/gfx/image/image.h"
36 #include "ui/gfx/rect.h"
26 37
27 namespace extensions { 38 namespace extensions {
28 39
29 // static 40 // static
30 std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes( 41 std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes(
31 const std::vector<SkBitmap>& bitmaps, 42 const std::vector<SkBitmap>& bitmaps,
32 const std::set<int>& sizes) { 43 const std::set<int>& sizes) {
33 std::map<int, SkBitmap> output_bitmaps; 44 std::map<int, SkBitmap> output_bitmaps;
34 std::map<int, SkBitmap> ordered_bitmaps; 45 std::map<int, SkBitmap> ordered_bitmaps;
35 for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin(); 46 for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
(...skipping 20 matching lines...) Expand all
56 bitmaps_it->second, 67 bitmaps_it->second,
57 skia::ImageOperations::RESIZE_LANCZOS3, 68 skia::ImageOperations::RESIZE_LANCZOS3,
58 size, 69 size,
59 size); 70 size);
60 } 71 }
61 } 72 }
62 return output_bitmaps; 73 return output_bitmaps;
63 } 74 }
64 75
65 // static 76 // static
66 void BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps, 77 void BookmarkAppHelper::GenerateIcon(std::map<int, SkBitmap>* bitmaps,
67 int output_size) { 78 int output_size,
68 std::map<int, SkBitmap>::const_iterator it = 79 SkColor color,
69 bitmaps->lower_bound(output_size); 80 char letter) {
70 // Do nothing if there is no icon smaller than the desired size or there is 81 // Do nothing if there is already an icon of |output_size|.
71 // already an icon of |output_size|. 82 if (bitmaps->count(output_size))
72 if (it == bitmaps->begin() || bitmaps->count(output_size))
73 return; 83 return;
74 84
75 --it; 85 const unsigned char kLuminanceThreshold = 190;
76 // This is the biggest icon smaller than |output_size|. 86 const int icon_size = output_size * 3 / 4;
77 const SkBitmap& base_icon = it->second; 87 const int icon_inset = output_size / 8;
88 const size_t border_radius = output_size / 16;
89 const size_t font_size = output_size * 7 / 16;
78 90
79 const size_t kBorderRadius = 5; 91 scoped_ptr<gfx::Canvas> canvas(
80 const size_t kColorStripHeight = 3; 92 new gfx::Canvas(gfx::Size(output_size, output_size), 1.0f, false));
81 const SkColor kBorderColor = 0xFFD5D5D5;
82 const SkColor kBackgroundColor = 0xFFFFFFFF;
83
84 // Create a separate canvas for the color strip.
85 scoped_ptr<SkCanvas> color_strip_canvas(
86 skia::CreateBitmapCanvas(output_size, output_size, false));
87 DCHECK(color_strip_canvas);
88
89 // Draw a rounded rect of the |base_icon|'s dominant color.
90 SkPaint color_strip_paint;
91 color_utils::GridSampler sampler;
92 color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
93 color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG(
94 gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
95 100,
96 665,
97 &sampler));
98 color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
99 kBorderRadius,
100 kBorderRadius,
101 color_strip_paint);
102
103 // Erase the top of the rounded rect to leave a color strip.
104 SkPaint clear_paint;
105 clear_paint.setColor(SK_ColorTRANSPARENT);
106 clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
107 color_strip_canvas->drawRect(
108 SkRect::MakeWH(output_size, output_size - kColorStripHeight),
109 clear_paint);
110
111 // Draw each element to an output canvas.
112 scoped_ptr<SkCanvas> canvas(
113 skia::CreateBitmapCanvas(output_size, output_size, false));
114 DCHECK(canvas); 93 DCHECK(canvas);
115 94
116 // Draw the background. 95 // Draw a rounded rect of the given |color|.
117 SkPaint background_paint; 96 SkPaint background_paint;
118 background_paint.setColor(kBackgroundColor); 97 background_paint.setColor(color);
119 background_paint.setFlags(SkPaint::kAntiAlias_Flag); 98 background_paint.setFlags(SkPaint::kAntiAlias_Flag);
120 canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
121 kBorderRadius,
122 kBorderRadius,
123 background_paint);
124 99
125 // Draw the color strip. 100 gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size);
126 canvas->drawBitmap( 101 canvas->DrawRoundRect(icon_rect, border_radius, background_paint);
127 color_strip_canvas->getDevice()->accessBitmap(false), 0, 0);
128 102
129 // Draw the border. 103 // The text rect's size needs to be odd to center the text correctly.
130 SkPaint border_paint; 104 gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1);
131 border_paint.setColor(kBorderColor); 105 // Draw the letter onto the rounded rect. The letter's color depends on the
132 border_paint.setStyle(SkPaint::kStroke_Style); 106 // luminance of |color|.
133 border_paint.setFlags(SkPaint::kAntiAlias_Flag); 107 unsigned char luminance = color_utils::GetLuminanceForColor(color);
134 canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size), 108 canvas->DrawStringRectWithFlags(
135 kBorderRadius, 109 base::string16(1, std::toupper(letter)),
136 kBorderRadius, 110 gfx::FontList(
137 border_paint); 111 gfx::Font(l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY), font_size)),
112 luminance > kLuminanceThreshold ? SK_ColorBLACK : SK_ColorWHITE,
113 text_rect,
114 gfx::Canvas::TEXT_ALIGN_CENTER);
138 115
139 // Draw the centered base icon to the output canvas. 116 gfx::ImageSkia icon_image(canvas->ExtractImageRep());
140 canvas->drawBitmap(base_icon, 117 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]);
141 (output_size - base_icon.width()) / 2,
142 (output_size - base_icon.height()) / 2);
143
144 const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false);
145 generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
146 } 118 }
147 119
148 BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service, 120 BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
149 WebApplicationInfo web_app_info, 121 WebApplicationInfo web_app_info,
150 content::WebContents* contents) 122 content::WebContents* contents)
151 : web_app_info_(web_app_info), 123 : web_app_info_(web_app_info),
152 crx_installer_(extensions::CrxInstaller::CreateSilent(service)) { 124 crx_installer_(extensions::CrxInstaller::CreateSilent(service)) {
153 registrar_.Add(this, 125 registrar_.Add(this,
154 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 126 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
155 content::Source<CrxInstaller>(crx_installer_.get())); 127 content::Source<CrxInstaller>(crx_installer_.get()));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 196
225 // Generate container icons from smaller icons. 197 // Generate container icons from smaller icons.
226 const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL, 198 const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL,
227 extension_misc::EXTENSION_ICON_MEDIUM, }; 199 extension_misc::EXTENSION_ICON_MEDIUM, };
228 const std::set<int> generate_sizes( 200 const std::set<int> generate_sizes(
229 kIconSizesToGenerate, 201 kIconSizesToGenerate,
230 kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); 202 kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
231 203
232 // Only generate icons if larger icons don't exist. This means the app 204 // Only generate icons if larger icons don't exist. This means the app
233 // launcher and the taskbar will do their best downsizing large icons and 205 // launcher and the taskbar will do their best downsizing large icons and
234 // these container icons are only generated as a last resort against upscaling 206 // these icons are only generated as a last resort against upscaling a smaller
235 // a smaller icon. 207 // icon.
236 if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) == 208 if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
237 resized_bitmaps.end()) { 209 resized_bitmaps.end()) {
238 // Generate these from biggest to smallest so we don't end up with 210 GURL app_url = web_app_info_.app_url;
239 // concentric container icons. 211
240 for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin(); 212 // The letter that will be painted on the generated icon.
241 it != generate_sizes.rend(); 213 char icon_letter = ' ';
214 std::string domain_and_registry(
215 net::registry_controlled_domains::GetDomainAndRegistry(
216 app_url,
217 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
218 if (!domain_and_registry.empty()) {
219 icon_letter = domain_and_registry[0];
220 } else if (!app_url.host().empty()) {
221 icon_letter = app_url.host()[0];
222 }
223
224 // The color that will be used for the icon's background.
225 SkColor background_color = SK_ColorBLACK;
226 if (resized_bitmaps.size()) {
227 color_utils::GridSampler sampler;
228 background_color = color_utils::CalculateKMeanColorOfPNG(
229 gfx::Image::CreateFrom1xBitmap(resized_bitmaps.begin()->second)
230 .As1xPNGBytes(),
231 100,
232 658,
233 &sampler);
234 }
235
236 for (std::set<int>::const_iterator it = generate_sizes.begin();
237 it != generate_sizes.end();
242 ++it) { 238 ++it) {
243 GenerateContainerIcon(&resized_bitmaps, *it); 239 GenerateIcon(&resized_bitmaps, *it, background_color, icon_letter);
240 // Also generate the 2x resource for this size.
benwells 2014/04/24 03:35:58 This seems to be new to this patch. Can you call t
calamity 2014/04/24 04:28:39 Done.
241 GenerateIcon(&resized_bitmaps, *it * 2, background_color, icon_letter);
244 } 242 }
245 } 243 }
246 244
247 // Populate the icon data into the WebApplicationInfo we are using to 245 // Populate the icon data into the WebApplicationInfo we are using to
248 // install the bookmark app. 246 // install the bookmark app.
249 for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it = 247 for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
250 resized_bitmaps.begin(); 248 resized_bitmaps.begin();
251 resized_bitmaps_it != resized_bitmaps.end(); 249 resized_bitmaps_it != resized_bitmaps.end();
252 ++resized_bitmaps_it) { 250 ++resized_bitmaps_it) {
253 WebApplicationInfo::IconInfo icon_info; 251 WebApplicationInfo::IconInfo icon_info;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 installer->InstallWebApp(web_app_info); 290 installer->InstallWebApp(web_app_info);
293 } 291 }
294 292
295 bool IsValidBookmarkAppUrl(const GURL& url) { 293 bool IsValidBookmarkAppUrl(const GURL& url) {
296 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes); 294 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes);
297 origin_only_pattern.SetMatchAllURLs(true); 295 origin_only_pattern.SetMatchAllURLs(true);
298 return url.is_valid() && origin_only_pattern.MatchesURL(url); 296 return url.is_valid() && origin_only_pattern.MatchesURL(url);
299 } 297 }
300 298
301 } // namespace extensions 299 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/bookmark_app_helper.h ('k') | chrome/browser/extensions/bookmark_app_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698