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

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: format Created 6 years, 7 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/image_loader.h" 14 #include "chrome/browser/extensions/image_loader.h"
13 #include "chrome/browser/extensions/tab_helper.h" 15 #include "chrome/browser/extensions/tab_helper.h"
14 #include "chrome/common/extensions/extension_constants.h" 16 #include "chrome/common/extensions/extension_constants.h"
15 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 17 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
16 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h" 19 #include "content/public/browser/notification_source.h"
18 #include "content/public/browser/web_contents.h" 20 #include "content/public/browser/web_contents.h"
19 #include "extensions/common/extension.h" 21 #include "extensions/common/extension.h"
20 #include "extensions/common/manifest_handlers/icons_handler.h" 22 #include "extensions/common/manifest_handlers/icons_handler.h"
21 #include "extensions/common/url_pattern.h" 23 #include "extensions/common/url_pattern.h"
24 #include "grit/platform_locale_settings.h"
25 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
22 #include "skia/ext/image_operations.h" 26 #include "skia/ext/image_operations.h"
23 #include "skia/ext/platform_canvas.h" 27 #include "skia/ext/platform_canvas.h"
24 #include "third_party/skia/include/core/SkBitmap.h" 28 #include "third_party/skia/include/core/SkBitmap.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/canvas.h"
25 #include "ui/gfx/color_analysis.h" 32 #include "ui/gfx/color_analysis.h"
33 #include "ui/gfx/color_utils.h"
34 #include "ui/gfx/font.h"
35 #include "ui/gfx/font_list.h"
36 #include "ui/gfx/image/canvas_image_source.h"
26 #include "ui/gfx/image/image.h" 37 #include "ui/gfx/image/image.h"
27 #include "ui/gfx/image/image_family.h" 38 #include "ui/gfx/image/image_family.h"
39 #include "ui/gfx/rect.h"
28 40
29 namespace { 41 namespace {
30 42
43 // Overlays a shortcut icon over the bottom left corner of a given image.
44 class GeneratedIconImageSource : public gfx::CanvasImageSource {
45 public:
46 explicit GeneratedIconImageSource(char letter, SkColor color, int output_size)
47 : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false),
48 letter_(letter),
49 color_(color),
50 output_size_(output_size) {}
51 virtual ~GeneratedIconImageSource() {}
52
53 private:
54 // gfx::CanvasImageSource overrides:
55 virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
56 const unsigned char kLuminanceThreshold = 190;
57 const int icon_size = output_size_ * 3 / 4;
58 const int icon_inset = output_size_ / 8;
59 const size_t border_radius = output_size_ / 16;
60 const size_t font_size = output_size_ * 7 / 16;
61
62 std::string font_name =
63 l10n_util::GetStringUTF8(IDS_SANS_SERIF_FONT_FAMILY);
64 #if defined(OS_CHROMEOS)
65 const std::string kChromeOSFontFamily = "Noto Sans";
66 font_name = kChromeOSFontFamily;
67 #endif
68
69 // Draw a rounded rect of the given |color|.
70 SkPaint background_paint;
71 background_paint.setFlags(SkPaint::kAntiAlias_Flag);
72 background_paint.setColor(color_);
73
74 gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size);
75 canvas->DrawRoundRect(icon_rect, border_radius, background_paint);
76
77 // The text rect's size needs to be odd to center the text correctly.
78 gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1);
79 // Draw the letter onto the rounded rect. The letter's color depends on the
80 // luminance of |color|.
81 unsigned char luminance = color_utils::GetLuminanceForColor(color_);
82 canvas->DrawStringRectWithFlags(
83 base::string16(1, std::toupper(letter_)),
84 gfx::FontList(gfx::Font(font_name, font_size)),
85 luminance > kLuminanceThreshold ? SK_ColorBLACK : SK_ColorWHITE,
86 text_rect,
87 gfx::Canvas::TEXT_ALIGN_CENTER);
88 }
89
90 char letter_;
91
92 SkColor color_;
93
94 int output_size_;
95
96 DISALLOW_COPY_AND_ASSIGN(GeneratedIconImageSource);
97 };
98
31 void OnIconsLoaded( 99 void OnIconsLoaded(
32 WebApplicationInfo web_app_info, 100 WebApplicationInfo web_app_info,
33 const base::Callback<void(const WebApplicationInfo&)> callback, 101 const base::Callback<void(const WebApplicationInfo&)> callback,
34 const gfx::ImageFamily& image_family) { 102 const gfx::ImageFamily& image_family) {
35 for (gfx::ImageFamily::const_iterator it = image_family.begin(); 103 for (gfx::ImageFamily::const_iterator it = image_family.begin();
36 it != image_family.end(); 104 it != image_family.end();
37 ++it) { 105 ++it) {
38 WebApplicationInfo::IconInfo icon_info; 106 WebApplicationInfo::IconInfo icon_info;
39 icon_info.data = *it->ToSkBitmap(); 107 icon_info.data = *it->ToSkBitmap();
40 icon_info.width = icon_info.data.width(); 108 icon_info.width = icon_info.data.width();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 bitmaps_it->second, 146 bitmaps_it->second,
79 skia::ImageOperations::RESIZE_LANCZOS3, 147 skia::ImageOperations::RESIZE_LANCZOS3,
80 size, 148 size,
81 size); 149 size);
82 } 150 }
83 } 151 }
84 return output_bitmaps; 152 return output_bitmaps;
85 } 153 }
86 154
87 // static 155 // static
88 void BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps, 156 void BookmarkAppHelper::GenerateIcon(std::map<int, SkBitmap>* bitmaps,
89 int output_size) { 157 int output_size,
90 std::map<int, SkBitmap>::const_iterator it = 158 SkColor color,
91 bitmaps->lower_bound(output_size); 159 char letter) {
92 // Do nothing if there is no icon smaller than the desired size or there is 160 // Do nothing if there is already an icon of |output_size|.
93 // already an icon of |output_size|. 161 if (bitmaps->count(output_size))
94 if (it == bitmaps->begin() || bitmaps->count(output_size))
95 return; 162 return;
96 163
97 --it; 164 gfx::ImageSkia icon_image(
98 // This is the biggest icon smaller than |output_size|. 165 new GeneratedIconImageSource(letter, color, output_size),
99 const SkBitmap& base_icon = it->second; 166 gfx::Size(output_size, output_size));
100 167 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]);
101 const size_t kBorderRadius = 5;
102 const size_t kColorStripHeight = 3;
103 const SkColor kBorderColor = 0xFFD5D5D5;
104 const SkColor kBackgroundColor = 0xFFFFFFFF;
105
106 // Create a separate canvas for the color strip.
107 scoped_ptr<SkCanvas> color_strip_canvas(
108 skia::CreateBitmapCanvas(output_size, output_size, false));
109 DCHECK(color_strip_canvas);
110
111 // Draw a rounded rect of the |base_icon|'s dominant color.
112 SkPaint color_strip_paint;
113 color_utils::GridSampler sampler;
114 color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
115 color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG(
116 gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
117 100,
118 665,
119 &sampler));
120 color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
121 kBorderRadius,
122 kBorderRadius,
123 color_strip_paint);
124
125 // Erase the top of the rounded rect to leave a color strip.
126 SkPaint clear_paint;
127 clear_paint.setColor(SK_ColorTRANSPARENT);
128 clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
129 color_strip_canvas->drawRect(
130 SkRect::MakeWH(output_size, output_size - kColorStripHeight),
131 clear_paint);
132
133 // Draw each element to an output canvas.
134 scoped_ptr<SkCanvas> canvas(
135 skia::CreateBitmapCanvas(output_size, output_size, false));
136 DCHECK(canvas);
137
138 // Draw the background.
139 SkPaint background_paint;
140 background_paint.setColor(kBackgroundColor);
141 background_paint.setFlags(SkPaint::kAntiAlias_Flag);
142 canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
143 kBorderRadius,
144 kBorderRadius,
145 background_paint);
146
147 // Draw the color strip.
148 canvas->drawBitmap(
149 color_strip_canvas->getDevice()->accessBitmap(false), 0, 0);
150
151 // Draw the border.
152 SkPaint border_paint;
153 border_paint.setColor(kBorderColor);
154 border_paint.setStyle(SkPaint::kStroke_Style);
155 border_paint.setFlags(SkPaint::kAntiAlias_Flag);
156 canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
157 kBorderRadius,
158 kBorderRadius,
159 border_paint);
160
161 // Draw the centered base icon to the output canvas.
162 canvas->drawBitmap(base_icon,
163 (output_size - base_icon.width()) / 2,
164 (output_size - base_icon.height()) / 2);
165
166 const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false);
167 generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
168 } 168 }
169 169
170 BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service, 170 BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
171 WebApplicationInfo web_app_info, 171 WebApplicationInfo web_app_info,
172 content::WebContents* contents) 172 content::WebContents* contents)
173 : web_app_info_(web_app_info), 173 : web_app_info_(web_app_info),
174 crx_installer_(extensions::CrxInstaller::CreateSilent(service)) { 174 crx_installer_(extensions::CrxInstaller::CreateSilent(service)) {
175 registrar_.Add(this, 175 registrar_.Add(this,
176 chrome::NOTIFICATION_CRX_INSTALLER_DONE, 176 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
177 content::Source<CrxInstaller>(crx_installer_.get())); 177 content::Source<CrxInstaller>(crx_installer_.get()));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 246
247 // Generate container icons from smaller icons. 247 // Generate container icons from smaller icons.
248 const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL, 248 const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL,
249 extension_misc::EXTENSION_ICON_MEDIUM, }; 249 extension_misc::EXTENSION_ICON_MEDIUM, };
250 const std::set<int> generate_sizes( 250 const std::set<int> generate_sizes(
251 kIconSizesToGenerate, 251 kIconSizesToGenerate,
252 kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); 252 kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
253 253
254 // Only generate icons if larger icons don't exist. This means the app 254 // Only generate icons if larger icons don't exist. This means the app
255 // launcher and the taskbar will do their best downsizing large icons and 255 // launcher and the taskbar will do their best downsizing large icons and
256 // these container icons are only generated as a last resort against upscaling 256 // these icons are only generated as a last resort against upscaling a smaller
257 // a smaller icon. 257 // icon.
258 if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) == 258 if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
259 resized_bitmaps.end()) { 259 resized_bitmaps.end()) {
260 // Generate these from biggest to smallest so we don't end up with 260 GURL app_url = web_app_info_.app_url;
261 // concentric container icons. 261
262 for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin(); 262 // The letter that will be painted on the generated icon.
263 it != generate_sizes.rend(); 263 char icon_letter = ' ';
264 std::string domain_and_registry(
265 net::registry_controlled_domains::GetDomainAndRegistry(
266 app_url,
267 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
268 if (!domain_and_registry.empty()) {
269 icon_letter = domain_and_registry[0];
270 } else if (!app_url.host().empty()) {
271 icon_letter = app_url.host()[0];
272 }
273
274 // The color that will be used for the icon's background.
275 SkColor background_color = SK_ColorBLACK;
276 if (resized_bitmaps.size()) {
277 color_utils::GridSampler sampler;
278 background_color = color_utils::CalculateKMeanColorOfPNG(
279 gfx::Image::CreateFrom1xBitmap(resized_bitmaps.begin()->second)
280 .As1xPNGBytes(),
281 100,
282 568,
283 &sampler);
284 }
285
286 for (std::set<int>::const_iterator it = generate_sizes.begin();
287 it != generate_sizes.end();
264 ++it) { 288 ++it) {
265 GenerateContainerIcon(&resized_bitmaps, *it); 289 GenerateIcon(&resized_bitmaps, *it, background_color, icon_letter);
290 // Also generate the 2x resource for this size.
291 GenerateIcon(&resized_bitmaps, *it * 2, background_color, icon_letter);
266 } 292 }
267 } 293 }
268 294
269 // Populate the icon data into the WebApplicationInfo we are using to 295 // Populate the icon data into the WebApplicationInfo we are using to
270 // install the bookmark app. 296 // install the bookmark app.
271 for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it = 297 for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
272 resized_bitmaps.begin(); 298 resized_bitmaps.begin();
273 resized_bitmaps_it != resized_bitmaps.end(); 299 resized_bitmaps_it != resized_bitmaps.end();
274 ++resized_bitmaps_it) { 300 ++resized_bitmaps_it) {
275 WebApplicationInfo::IconInfo icon_info; 301 WebApplicationInfo::IconInfo icon_info;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback)); 373 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback));
348 } 374 }
349 375
350 bool IsValidBookmarkAppUrl(const GURL& url) { 376 bool IsValidBookmarkAppUrl(const GURL& url) {
351 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes); 377 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes);
352 origin_only_pattern.SetMatchAllURLs(true); 378 origin_only_pattern.SetMatchAllURLs(true);
353 return url.is_valid() && origin_only_pattern.MatchesURL(url); 379 return url.is_valid() && origin_only_pattern.MatchesURL(url);
354 } 380 }
355 381
356 } // namespace extensions 382 } // 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