| Index: chrome/browser/extensions/bookmark_app_helper.cc
|
| diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
|
| index a44c002a1d22e2dee5d1f8573234960223eded56..4288b82de6dbc915708c514248e286d503f8ed95 100644
|
| --- a/chrome/browser/extensions/bookmark_app_helper.cc
|
| +++ b/chrome/browser/extensions/bookmark_app_helper.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "chrome/browser/extensions/bookmark_app_helper.h"
|
|
|
| +#include <cctype>
|
| +
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/extensions/crx_installer.h"
|
| @@ -19,15 +21,81 @@
|
| #include "extensions/common/extension.h"
|
| #include "extensions/common/manifest_handlers/icons_handler.h"
|
| #include "extensions/common/url_pattern.h"
|
| +#include "grit/platform_locale_settings.h"
|
| +#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
| #include "skia/ext/image_operations.h"
|
| #include "skia/ext/platform_canvas.h"
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/canvas.h"
|
| #include "ui/gfx/color_analysis.h"
|
| +#include "ui/gfx/color_utils.h"
|
| +#include "ui/gfx/font.h"
|
| +#include "ui/gfx/font_list.h"
|
| +#include "ui/gfx/image/canvas_image_source.h"
|
| #include "ui/gfx/image/image.h"
|
| #include "ui/gfx/image/image_family.h"
|
| +#include "ui/gfx/rect.h"
|
|
|
| namespace {
|
|
|
| +// Overlays a shortcut icon over the bottom left corner of a given image.
|
| +class GeneratedIconImageSource : public gfx::CanvasImageSource {
|
| + public:
|
| + explicit GeneratedIconImageSource(char letter, SkColor color, int output_size)
|
| + : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false),
|
| + letter_(letter),
|
| + color_(color),
|
| + output_size_(output_size) {}
|
| + virtual ~GeneratedIconImageSource() {}
|
| +
|
| + private:
|
| + // gfx::CanvasImageSource overrides:
|
| + virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
|
| + const unsigned char kLuminanceThreshold = 190;
|
| + const int icon_size = output_size_ * 3 / 4;
|
| + const int icon_inset = output_size_ / 8;
|
| + const size_t border_radius = output_size_ / 16;
|
| + const size_t font_size = output_size_ * 7 / 16;
|
| +
|
| + std::string font_name =
|
| + l10n_util::GetStringUTF8(IDS_SANS_SERIF_FONT_FAMILY);
|
| +#if defined(OS_CHROMEOS)
|
| + const std::string kChromeOSFontFamily = "Noto Sans";
|
| + font_name = kChromeOSFontFamily;
|
| +#endif
|
| +
|
| + // Draw a rounded rect of the given |color|.
|
| + SkPaint background_paint;
|
| + background_paint.setFlags(SkPaint::kAntiAlias_Flag);
|
| + background_paint.setColor(color_);
|
| +
|
| + gfx::Rect icon_rect(icon_inset, icon_inset, icon_size, icon_size);
|
| + canvas->DrawRoundRect(icon_rect, border_radius, background_paint);
|
| +
|
| + // The text rect's size needs to be odd to center the text correctly.
|
| + gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1);
|
| + // Draw the letter onto the rounded rect. The letter's color depends on the
|
| + // luminance of |color|.
|
| + unsigned char luminance = color_utils::GetLuminanceForColor(color_);
|
| + canvas->DrawStringRectWithFlags(
|
| + base::string16(1, std::toupper(letter_)),
|
| + gfx::FontList(gfx::Font(font_name, font_size)),
|
| + luminance > kLuminanceThreshold ? SK_ColorBLACK : SK_ColorWHITE,
|
| + text_rect,
|
| + gfx::Canvas::TEXT_ALIGN_CENTER);
|
| + }
|
| +
|
| + char letter_;
|
| +
|
| + SkColor color_;
|
| +
|
| + int output_size_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(GeneratedIconImageSource);
|
| +};
|
| +
|
| void OnIconsLoaded(
|
| WebApplicationInfo web_app_info,
|
| const base::Callback<void(const WebApplicationInfo&)> callback,
|
| @@ -85,86 +153,18 @@ std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes(
|
| }
|
|
|
| // static
|
| -void BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
|
| - int output_size) {
|
| - std::map<int, SkBitmap>::const_iterator it =
|
| - bitmaps->lower_bound(output_size);
|
| - // Do nothing if there is no icon smaller than the desired size or there is
|
| - // already an icon of |output_size|.
|
| - if (it == bitmaps->begin() || bitmaps->count(output_size))
|
| +void BookmarkAppHelper::GenerateIcon(std::map<int, SkBitmap>* bitmaps,
|
| + int output_size,
|
| + SkColor color,
|
| + char letter) {
|
| + // Do nothing if there is already an icon of |output_size|.
|
| + if (bitmaps->count(output_size))
|
| return;
|
|
|
| - --it;
|
| - // This is the biggest icon smaller than |output_size|.
|
| - const SkBitmap& base_icon = it->second;
|
| -
|
| - const size_t kBorderRadius = 5;
|
| - const size_t kColorStripHeight = 3;
|
| - const SkColor kBorderColor = 0xFFD5D5D5;
|
| - const SkColor kBackgroundColor = 0xFFFFFFFF;
|
| -
|
| - // Create a separate canvas for the color strip.
|
| - scoped_ptr<SkCanvas> color_strip_canvas(
|
| - skia::CreateBitmapCanvas(output_size, output_size, false));
|
| - DCHECK(color_strip_canvas);
|
| -
|
| - // Draw a rounded rect of the |base_icon|'s dominant color.
|
| - SkPaint color_strip_paint;
|
| - color_utils::GridSampler sampler;
|
| - color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
|
| - color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG(
|
| - gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
|
| - 100,
|
| - 665,
|
| - &sampler));
|
| - color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
|
| - kBorderRadius,
|
| - kBorderRadius,
|
| - color_strip_paint);
|
| -
|
| - // Erase the top of the rounded rect to leave a color strip.
|
| - SkPaint clear_paint;
|
| - clear_paint.setColor(SK_ColorTRANSPARENT);
|
| - clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
| - color_strip_canvas->drawRect(
|
| - SkRect::MakeWH(output_size, output_size - kColorStripHeight),
|
| - clear_paint);
|
| -
|
| - // Draw each element to an output canvas.
|
| - scoped_ptr<SkCanvas> canvas(
|
| - skia::CreateBitmapCanvas(output_size, output_size, false));
|
| - DCHECK(canvas);
|
| -
|
| - // Draw the background.
|
| - SkPaint background_paint;
|
| - background_paint.setColor(kBackgroundColor);
|
| - background_paint.setFlags(SkPaint::kAntiAlias_Flag);
|
| - canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
|
| - kBorderRadius,
|
| - kBorderRadius,
|
| - background_paint);
|
| -
|
| - // Draw the color strip.
|
| - canvas->drawBitmap(
|
| - color_strip_canvas->getDevice()->accessBitmap(false), 0, 0);
|
| -
|
| - // Draw the border.
|
| - SkPaint border_paint;
|
| - border_paint.setColor(kBorderColor);
|
| - border_paint.setStyle(SkPaint::kStroke_Style);
|
| - border_paint.setFlags(SkPaint::kAntiAlias_Flag);
|
| - canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
|
| - kBorderRadius,
|
| - kBorderRadius,
|
| - border_paint);
|
| -
|
| - // Draw the centered base icon to the output canvas.
|
| - canvas->drawBitmap(base_icon,
|
| - (output_size - base_icon.width()) / 2,
|
| - (output_size - base_icon.height()) / 2);
|
| -
|
| - const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false);
|
| - generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
|
| + gfx::ImageSkia icon_image(
|
| + new GeneratedIconImageSource(letter, color, output_size),
|
| + gfx::Size(output_size, output_size));
|
| + icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]);
|
| }
|
|
|
| BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
|
| @@ -253,16 +253,42 @@ void BookmarkAppHelper::OnIconsDownloaded(
|
|
|
| // Only generate icons if larger icons don't exist. This means the app
|
| // launcher and the taskbar will do their best downsizing large icons and
|
| - // these container icons are only generated as a last resort against upscaling
|
| - // a smaller icon.
|
| + // these icons are only generated as a last resort against upscaling a smaller
|
| + // icon.
|
| if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
|
| resized_bitmaps.end()) {
|
| - // Generate these from biggest to smallest so we don't end up with
|
| - // concentric container icons.
|
| - for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
|
| - it != generate_sizes.rend();
|
| + GURL app_url = web_app_info_.app_url;
|
| +
|
| + // The letter that will be painted on the generated icon.
|
| + char icon_letter = ' ';
|
| + std::string domain_and_registry(
|
| + net::registry_controlled_domains::GetDomainAndRegistry(
|
| + app_url,
|
| + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
|
| + if (!domain_and_registry.empty()) {
|
| + icon_letter = domain_and_registry[0];
|
| + } else if (!app_url.host().empty()) {
|
| + icon_letter = app_url.host()[0];
|
| + }
|
| +
|
| + // The color that will be used for the icon's background.
|
| + SkColor background_color = SK_ColorBLACK;
|
| + if (resized_bitmaps.size()) {
|
| + color_utils::GridSampler sampler;
|
| + background_color = color_utils::CalculateKMeanColorOfPNG(
|
| + gfx::Image::CreateFrom1xBitmap(resized_bitmaps.begin()->second)
|
| + .As1xPNGBytes(),
|
| + 100,
|
| + 568,
|
| + &sampler);
|
| + }
|
| +
|
| + for (std::set<int>::const_iterator it = generate_sizes.begin();
|
| + it != generate_sizes.end();
|
| ++it) {
|
| - GenerateContainerIcon(&resized_bitmaps, *it);
|
| + GenerateIcon(&resized_bitmaps, *it, background_color, icon_letter);
|
| + // Also generate the 2x resource for this size.
|
| + GenerateIcon(&resized_bitmaps, *it * 2, background_color, icon_letter);
|
| }
|
| }
|
|
|
|
|