diff options
author | liyanhou@chromium.org <liyanhou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-22 01:38:17 +0000 |
---|---|---|
committer | liyanhou@chromium.org <liyanhou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-22 01:38:17 +0000 |
commit | 4969d273abcb706f67a1723f16380403996664c4 (patch) | |
tree | 56cf6b9ee6f363c8efa4a079010a2d4be5e45dc8 | |
parent | b4cb55bbf3119f1e36ec2b28f537b2c45f37e36f (diff) | |
download | chromium_src-4969d273abcb706f67a1723f16380403996664c4.zip chromium_src-4969d273abcb706f67a1723f16380403996664c4.tar.gz chromium_src-4969d273abcb706f67a1723f16380403996664c4.tar.bz2 |
Add app icon masp to notification API
Add an app icon mask (16*16, or 32*32 for retina display) on the bottom right corner of notifications to indicate source of the notification. The app icon is displayed in a way that takes only the alpha channel of the image passed in, masks it with white foreground and grey background.
BUG=284592
Review URL: https://codereview.chromium.org/308053004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@284586 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 101 insertions, 4 deletions
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc index de01be5..8bd5aee 100644 --- a/chrome/browser/extensions/api/notifications/notifications_api.cc +++ b/chrome/browser/extensions/api/notifications/notifications_api.cc @@ -285,6 +285,16 @@ bool NotificationsApiFunction::CreateNotification( // Then, handle any optional data that's been provided. message_center::RichNotificationData optional_fields; + if (options->app_icon_mask_url.get()) { + if (!NotificationBitmapToGfxImage(image_scale, + bitmap_sizes.app_icon_mask_size, + options->app_icon_mask_bitmap.get(), + &optional_fields.small_image)) { + SetError(kUnableToDecodeIconError); + return false; + } + } + if (options->priority.get()) optional_fields.priority = *options->priority; @@ -402,6 +412,14 @@ bool NotificationsApiFunction::UpdateNotification( notification->set_icon(icon); } + gfx::Image app_icon_mask; + if (NotificationBitmapToGfxImage(image_scale, + bitmap_sizes.app_icon_mask_size, + options->app_icon_mask_bitmap.get(), + &app_icon_mask)) { + notification->set_small_image(app_icon_mask); + } + if (options->priority) notification->set_priority(*options->priority); diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl index da95e62..fb1fe65 100644 --- a/chrome/common/extensions/api/notifications.idl +++ b/chrome/common/extensions/api/notifications.idl @@ -53,11 +53,23 @@ namespace notifications { // <em>Required for $(ref:notifications.create)</em> method. TemplateType? type; - // Sender's avatar, app icon, or a thumbnail for image notifications. + // A URL to the sender's avatar, app icon, or a thumbnail for image + // notifications. + // + // URLs can be a data URL, a blob URL, or a URL relative to a resource + // within this extension's .crx file // <em>Required for $(ref:notifications.create)</em> method. DOMString? iconUrl; [nodoc] NotificationBitmap? iconBitmap; + // A URL to the app icon mask. URLs have the same restrictions as + // $(ref:notifications.NotificationOptions.iconUrl iconUrl). + // + // The app icon mask should be in alpha channel, as only the alpha channel + // of the image will be considered. + DOMString? appIconMaskUrl; + [nodoc] NotificationBitmap? appIconMaskBitmap; + // Title of the notification (e.g. sender name for email). // <em>Required for $(ref:notifications.create)</em> method. DOMString? title; @@ -83,7 +95,9 @@ namespace notifications { // Secondary notification content. [nodoc] DOMString? expandedMessage; - // Image thumbnail for image-type notifications. + // A URL to the image thumbnail for image-type notifications. + // URLs have the same restrictions as + // $(ref:notifications.NotificationOptions.iconUrl iconUrl). DOMString? imageUrl; [nodoc] NotificationBitmap? imageBitmap; diff --git a/chrome/common/extensions/api/notifications/notification_style.cc b/chrome/common/extensions/api/notifications/notification_style.cc index 5d2d883..811d9a8 100644 --- a/chrome/common/extensions/api/notifications/notification_style.cc +++ b/chrome/common/extensions/api/notifications/notification_style.cc @@ -6,6 +6,11 @@ #include "ui/message_center/message_center_style.h" +NotificationBitmapSizes::NotificationBitmapSizes() { +} +NotificationBitmapSizes::~NotificationBitmapSizes() { +} + NotificationBitmapSizes GetNotificationBitmapSizes() { NotificationBitmapSizes sizes; sizes.image_size = @@ -16,5 +21,8 @@ NotificationBitmapSizes GetNotificationBitmapSizes() { sizes.button_icon_size = gfx::Size(message_center::kNotificationButtonIconSize, message_center::kNotificationButtonIconSize); + + sizes.app_icon_mask_size = gfx::Size(message_center::kSmallImageSize, + message_center::kSmallImageSize); return sizes; } diff --git a/chrome/common/extensions/api/notifications/notification_style.h b/chrome/common/extensions/api/notifications/notification_style.h index ef4eb19..81bbb2c 100644 --- a/chrome/common/extensions/api/notifications/notification_style.h +++ b/chrome/common/extensions/api/notifications/notification_style.h @@ -10,9 +10,13 @@ // This structure describes the size in DIPs of each type of image rendered // by the notification center within a notification. struct NotificationBitmapSizes { + NotificationBitmapSizes(); + ~NotificationBitmapSizes(); + gfx::Size image_size; gfx::Size icon_size; gfx::Size button_icon_size; + gfx::Size app_icon_mask_size; }; NotificationBitmapSizes GetNotificationBitmapSizes(); diff --git a/chrome/renderer/extensions/notifications_native_handler.cc b/chrome/renderer/extensions/notifications_native_handler.cc index ba0e17a..0100fbd 100644 --- a/chrome/renderer/extensions/notifications_native_handler.cc +++ b/chrome/renderer/extensions/notifications_native_handler.cc @@ -38,6 +38,10 @@ void NotificationsNativeHandler::GetNotificationImageSizes( dict->SetInteger("image.height", bitmap_sizes.image_size.height()); dict->SetInteger("buttonIcon.width", bitmap_sizes.button_icon_size.width()); dict->SetInteger("buttonIcon.height", bitmap_sizes.button_icon_size.height()); + dict->SetInteger("appIconMask.width", + bitmap_sizes.app_icon_mask_size.width()); + dict->SetInteger("appIconMask.height", + bitmap_sizes.app_icon_mask_size.height()); scoped_ptr<content::V8ValueConverter> converter( content::V8ValueConverter::create()); diff --git a/chrome/renderer/resources/extensions/notifications_custom_bindings.js b/chrome/renderer/resources/extensions/notifications_custom_bindings.js index 013628a..eebf290 100644 --- a/chrome/renderer/resources/extensions/notifications_custom_bindings.js +++ b/chrome/renderer/resources/extensions/notifications_custom_bindings.js @@ -40,6 +40,16 @@ function getUrlSpecs(imageSizes, notificationDetails) { }); } + // |appIconMaskUrl| is optional. + if (notificationDetails.appIconMaskUrl) { + $Array.push(urlSpecs, { + path: notificationDetails.appIconMaskUrl, + width: imageSizes.appIconMask.width * imageSizes.scaleFactor, + height: imageSizes.appIconMask.height * imageSizes.scaleFactor, + callback: imageDataSetter(notificationDetails, 'appIconMaskBitmap') + }); + } + // |imageUrl| is optional. if (notificationDetails.imageUrl) { $Array.push(urlSpecs, { diff --git a/ui/message_center/message_center_style.cc b/ui/message_center/message_center_style.cc index 793649a..3413149 100644 --- a/ui/message_center/message_center_style.cc +++ b/ui/message_center/message_center_style.cc @@ -23,6 +23,8 @@ const SkColor kImageBackgroundColor = SkColorSetRGB(0x22, 0x22, 0x22); const SkColor kRegularTextColor = SkColorSetRGB(0x33, 0x33, 0x33); const SkColor kDimTextColor = SkColorSetRGB(0x7f, 0x7f, 0x7f); const SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250); +const SkColor kSmallImageMaskForegroundColor = SK_ColorWHITE; +const SkColor kSmallImageMaskBackgroundColor = SkColorSetRGB(0xa3, 0xa3, 0xa3); // Limits. diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h index 5d11a3b..b6e415e 100644 --- a/ui/message_center/message_center_style.h +++ b/ui/message_center/message_center_style.h @@ -77,6 +77,10 @@ extern const SkColor kIconBackgroundColor; // Used behind icons smaller extern const SkColor kRegularTextColor; // Title, message, ... extern const SkColor kDimTextColor; extern const SkColor kFocusBorderColor; // The focus border. +extern const SkColor + kSmallImageMaskForegroundColor; // Foreground of small icon image. +extern const SkColor + kSmallImageMaskBackgroundColor; // Background of small icon image. // Limits. diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc index 11ff548..3b8900c 100644 --- a/ui/message_center/views/message_view.cc +++ b/ui/message_center/views/message_view.cc @@ -12,6 +12,7 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/image/image_skia_operations.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_style.h" #include "ui/message_center/views/padded_button.h" @@ -31,6 +32,31 @@ const int kCloseIconRightPadding = 5; const int kShadowOffset = 1; const int kShadowBlur = 4; +const gfx::ImageSkia CreateImage(int width, int height, SkColor color) { + SkBitmap bitmap; + bitmap.allocN32Pixels(width, height); + bitmap.eraseColor(color); + return gfx::ImageSkia::CreateFrom1xBitmap(bitmap); +} + +// Take the alpha channel of small_image, mask it with the foreground, +// then add the masked foreground on top of the background +const gfx::ImageSkia GetMaskedSmallImage(const gfx::ImageSkia& small_image) { + int width = small_image.width(); + int height = small_image.height(); + + // Background color grey + const gfx::ImageSkia background = CreateImage( + width, height, message_center::kSmallImageMaskBackgroundColor); + // Foreground color white + const gfx::ImageSkia foreground = CreateImage( + width, height, message_center::kSmallImageMaskForegroundColor); + const gfx::ImageSkia masked_small_image = + gfx::ImageSkiaOperations::CreateMaskedImage(foreground, small_image); + return gfx::ImageSkiaOperations::CreateSuperimposedImage(background, + masked_small_image); +} + } // namespace namespace message_center { @@ -54,8 +80,9 @@ MessageView::MessageView(MessageViewController* controller, views::Background::CreateSolidBackground(kNotificationBackgroundColor)); AddChildView(background_view_); + const gfx::ImageSkia masked_small_image = GetMaskedSmallImage(small_image); views::ImageView* small_image_view = new views::ImageView(); - small_image_view->SetImage(small_image); + small_image_view->SetImage(masked_small_image); small_image_view->SetImageSize(gfx::Size(kSmallImageSize, kSmallImageSize)); // The small image view should be added to view hierarchy by the derived // class. This ensures that it is on top of other views. @@ -84,7 +111,9 @@ MessageView::~MessageView() { } void MessageView::UpdateWithNotification(const Notification& notification) { - small_image_view_->SetImage(notification.small_image().AsImageSkia()); + const gfx::ImageSkia masked_small_image = + GetMaskedSmallImage(notification.small_image().AsImageSkia()); + small_image_view_->SetImage(masked_small_image); display_source_ = notification.display_source(); } diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h index 04f4d97..3ab6f8e 100644 --- a/ui/message_center/views/message_view.h +++ b/ui/message_center/views/message_view.h @@ -7,6 +7,10 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/insets.h" #include "ui/message_center/message_center_export.h" #include "ui/message_center/notification.h" |