| Index: chrome/common/extensions/extension_action.cc
|
| diff --git a/chrome/common/extensions/extension_action.cc b/chrome/common/extensions/extension_action.cc
|
| index d211778e89ab4230eb2e17c51d7369f991445c5e..ee6abbfde7ce5dec0ed58bdb8c6f70996916108c 100644
|
| --- a/chrome/common/extensions/extension_action.cc
|
| +++ b/chrome/common/extensions/extension_action.cc
|
| @@ -20,6 +20,8 @@
|
| #include "ui/base/resource/resource_bundle.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/color_utils.h"
|
| +#include "ui/gfx/image/image_skia.h"
|
| +#include "ui/gfx/image/image_skia_source.h"
|
| #include "ui/gfx/rect.h"
|
| #include "ui/gfx/image/image_skia_source.h"
|
| #include "ui/gfx/skbitmap_operations.h"
|
| @@ -56,16 +58,14 @@ const int kMaxTextWidth = 23;
|
| const int kCenterAlignThreshold = 20;
|
|
|
|
|
| -int Width(const gfx::Image& image) {
|
| - if (image.IsEmpty())
|
| - return 0;
|
| - return image.ToSkBitmap()->width();
|
| +int Width(const gfx::ImageSkia& image) {
|
| + return image.size().width();
|
| }
|
|
|
| class GetAttentionImageSource : public gfx::ImageSkiaSource {
|
| public:
|
| - explicit GetAttentionImageSource(const gfx::Image& icon)
|
| - : icon_(*icon.ToImageSkia()) {}
|
| + explicit GetAttentionImageSource(const gfx::ImageSkia& icon)
|
| + : icon_(icon) {}
|
|
|
| // gfx::ImageSkiaSource overrides:
|
| virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor)
|
| @@ -115,6 +115,37 @@ class ExtensionAction::IconAnimationWrapper
|
| IconAnimation animation_;
|
| };
|
|
|
| +// Source for painting animated skia image.
|
| +class ExtensionAction::AnimatedIconImageSource : public gfx::ImageSkiaSource {
|
| + public:
|
| + AnimatedIconImageSource(const gfx::ImageSkia& image,
|
| + IconAnimationWrapper* animation)
|
| + : image_(image),
|
| + animation_(animation->AsWeakPtr()) {
|
| + }
|
| +
|
| + private:
|
| + virtual ~AnimatedIconImageSource() {}
|
| +
|
| + virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale) OVERRIDE {
|
| + gfx::ImageSkiaRep original_rep = image_.GetRepresentation(scale);
|
| + if (!animation_) {
|
| + return original_rep;
|
| + }
|
| +
|
| + // Original representation's scale factor may be different from scale
|
| + // factor passed to this method. We want to use the former (since we are
|
| + // using bitmap for that scale).
|
| + return gfx::ImageSkiaRep(
|
| + animation_->animation()->Apply(original_rep.sk_bitmap()),
|
| + original_rep.scale_factor());
|
| + }
|
| +
|
| + gfx::ImageSkia image_;
|
| + base::WeakPtr<IconAnimationWrapper> animation_;
|
| +};
|
| +
|
| +
|
| const int ExtensionAction::kDefaultTabId = -1;
|
|
|
| ExtensionAction::IconAnimation::IconAnimation(
|
| @@ -217,19 +248,19 @@ GURL ExtensionAction::GetPopupUrl(int tab_id) const {
|
| }
|
|
|
| void ExtensionAction::CacheIcon(const std::string& path,
|
| - const gfx::Image& icon) {
|
| - if (!icon.IsEmpty())
|
| + const gfx::ImageSkia& icon) {
|
| + if (!icon.empty())
|
| path_to_icon_cache_.insert(std::make_pair(path, icon));
|
| }
|
|
|
| -void ExtensionAction::SetIcon(int tab_id, const SkBitmap& bitmap) {
|
| - SetValue(&icon_, tab_id, gfx::Image(bitmap));
|
| +void ExtensionAction::SetIcon(int tab_id, const gfx::ImageSkia& image) {
|
| + SetValue(&icon_, tab_id, image);
|
| }
|
|
|
| -gfx::Image ExtensionAction::GetIcon(int tab_id) const {
|
| +gfx::ImageSkia ExtensionAction::GetIcon(int tab_id) const {
|
| // Check if a specific icon is set for this tab.
|
| - gfx::Image icon = GetValue(&icon_, tab_id);
|
| - if (icon.IsEmpty()) {
|
| + gfx::ImageSkia icon = GetValue(&icon_, tab_id);
|
| + if (icon.empty()) {
|
| // Need to find an icon from a path.
|
| const std::string* path = NULL;
|
| // Check if one of the elements of icon_path() was selected.
|
| @@ -241,20 +272,18 @@ gfx::Image ExtensionAction::GetIcon(int tab_id) const {
|
| path = &default_icon_path();
|
| }
|
|
|
| - std::map<std::string, gfx::Image>::const_iterator cached_icon =
|
| + std::map<std::string, gfx::ImageSkia>::const_iterator cached_icon =
|
| path_to_icon_cache_.find(*path);
|
| if (cached_icon != path_to_icon_cache_.end()) {
|
| icon = cached_icon->second;
|
| } else {
|
| - icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
|
| + icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
|
| IDR_EXTENSIONS_FAVICON);
|
| }
|
| }
|
|
|
| - if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) {
|
| - icon = gfx::Image(gfx::ImageSkia(new GetAttentionImageSource(icon),
|
| - icon.ToImageSkia()->size()));
|
| - }
|
| + if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION)
|
| + icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size());
|
|
|
| return ApplyIconAnimation(tab_id, icon);
|
| }
|
| @@ -299,18 +328,30 @@ void ExtensionAction::ClearAllValuesForTab(int tab_id) {
|
| void ExtensionAction::PaintBadge(gfx::Canvas* canvas,
|
| const gfx::Rect& bounds,
|
| int tab_id) {
|
| - std::string text = GetBadgeText(tab_id);
|
| + ExtensionAction::DoPaintBadge(
|
| + canvas,
|
| + bounds,
|
| + GetBadgeText(tab_id),
|
| + GetBadgeTextColor(tab_id),
|
| + GetBadgeBackgroundColor(tab_id),
|
| + Width(GetValue(&icon_, tab_id)));
|
| +}
|
| +
|
| +// static
|
| +void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas,
|
| + const gfx::Rect& bounds,
|
| + const std::string& text,
|
| + const SkColor& text_color_in,
|
| + const SkColor& background_color_in,
|
| + int icon_width) {
|
| if (text.empty())
|
| return;
|
|
|
| - SkColor text_color = GetBadgeTextColor(tab_id);
|
| - SkColor background_color = GetBadgeBackgroundColor(tab_id);
|
| -
|
| - if (SkColorGetA(text_color) == 0x00)
|
| - text_color = SK_ColorWHITE;
|
| + SkColor text_color = (SkColorGetA(text_color_in) == 0x00) ?
|
| + SK_ColorWHITE : text_color_in;
|
|
|
| - if (SkColorGetA(background_color) == 0x00)
|
| - background_color = SkColorSetARGB(255, 218, 0, 24); // Default badge color.
|
| + SkColor background_color = (SkColorGetA(background_color_in) == 0x00) ?
|
| + SkColorSetARGB(255, 218, 0, 24) : background_color_in;
|
|
|
| canvas->Save();
|
|
|
| @@ -319,14 +360,12 @@ void ExtensionAction::PaintBadge(gfx::Canvas* canvas,
|
| text_paint->setColor(text_color);
|
|
|
| // Calculate text width. We clamp it to a max size.
|
| - SkScalar text_width = text_paint->measureText(text.c_str(), text.size());
|
| - text_width = SkIntToScalar(
|
| - std::min(kMaxTextWidth, SkScalarFloor(text_width)));
|
| + SkScalar text_width_sk = text_paint->measureText(text.c_str(), text.size());
|
| + int text_width = std::min(kMaxTextWidth, SkScalarFloor(text_width_sk));
|
|
|
| // Calculate badge size. It is clamped to a min width just because it looks
|
| // silly if it is too skinny.
|
| - int badge_width = SkScalarFloor(text_width) + kPadding * 2;
|
| - int icon_width = Width(GetValue(&icon_, tab_id));
|
| + int badge_width = text_width + kPadding * 2;
|
| // Force the pixel width of badge to be either odd (if the icon width is odd)
|
| // or even otherwise. If there is a mismatch you get http://crbug.com/26400.
|
| if (icon_width != 0 && (badge_width % 2 != icon_width % 2))
|
| @@ -335,52 +374,45 @@ void ExtensionAction::PaintBadge(gfx::Canvas* canvas,
|
|
|
| // Paint the badge background color in the right location. It is usually
|
| // right-aligned, but it can also be center-aligned if it is large.
|
| - SkRect rect;
|
| - rect.fBottom = SkIntToScalar(bounds.bottom() - kBottomMargin);
|
| - rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight);
|
| - if (badge_width >= kCenterAlignThreshold) {
|
| - rect.fLeft = SkIntToScalar(
|
| - SkScalarFloor(SkIntToScalar(bounds.x()) +
|
| - SkIntToScalar(bounds.width()) / 2 -
|
| - SkIntToScalar(badge_width) / 2));
|
| - rect.fRight = rect.fLeft + SkIntToScalar(badge_width);
|
| - } else {
|
| - rect.fRight = SkIntToScalar(bounds.right());
|
| - rect.fLeft = rect.fRight - badge_width;
|
| - }
|
| + int rect_height = kBadgeHeight;
|
| + int rect_y = bounds.bottom() - kBottomMargin - kBadgeHeight;
|
| + int rect_width = badge_width;
|
| + int rect_x = (badge_width >= kCenterAlignThreshold) ?
|
| + (bounds.x() + bounds.width()) / 2 - badge_width / 2 :
|
| + bounds.right() - badge_width;
|
| + gfx::Rect rect(rect_x, rect_y, rect_width, rect_height);
|
|
|
| SkPaint rect_paint;
|
| rect_paint.setStyle(SkPaint::kFill_Style);
|
| rect_paint.setAntiAlias(true);
|
| rect_paint.setColor(background_color);
|
| - canvas->sk_canvas()->drawRoundRect(rect, SkIntToScalar(2),
|
| - SkIntToScalar(2), rect_paint);
|
| + canvas->DrawRoundRect(rect, 2, rect_paint);
|
|
|
| // Overlay the gradient. It is stretchy, so we do this in three parts.
|
| ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - SkBitmap* gradient_left = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_LEFT);
|
| - SkBitmap* gradient_right = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_RIGHT);
|
| - SkBitmap* gradient_center = rb.GetBitmapNamed(
|
| + gfx::ImageSkia* gradient_left = rb.GetImageSkiaNamed(
|
| + IDR_BROWSER_ACTION_BADGE_LEFT);
|
| + gfx::ImageSkia* gradient_right = rb.GetImageSkiaNamed(
|
| + IDR_BROWSER_ACTION_BADGE_RIGHT);
|
| + gfx::ImageSkia* gradient_center = rb.GetImageSkiaNamed(
|
| IDR_BROWSER_ACTION_BADGE_CENTER);
|
|
|
| - canvas->sk_canvas()->drawBitmap(*gradient_left, rect.fLeft, rect.fTop);
|
| + canvas->DrawImageInt(*gradient_left, rect.x(), rect.y());
|
| canvas->TileImageInt(*gradient_center,
|
| - SkScalarFloor(rect.fLeft) + gradient_left->width(),
|
| - SkScalarFloor(rect.fTop),
|
| - SkScalarFloor(rect.width()) - gradient_left->width() -
|
| - gradient_right->width(),
|
| - SkScalarFloor(rect.height()));
|
| - canvas->sk_canvas()->drawBitmap(*gradient_right,
|
| - rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop);
|
| + rect.x() + gradient_left->width(),
|
| + rect.y(),
|
| + rect.width() - gradient_left->width() - gradient_right->width(),
|
| + rect.height());
|
| + canvas->DrawImageInt(*gradient_right,
|
| + rect.right() - gradient_right->width(), rect.y());
|
|
|
| // Finally, draw the text centered within the badge. We set a clip in case the
|
| // text was too large.
|
| - rect.fLeft += kPadding;
|
| - rect.fRight -= kPadding;
|
| - canvas->sk_canvas()->clipRect(rect);
|
| + rect.Inset(kPadding, 0);
|
| + canvas->ClipRect(rect);
|
| canvas->sk_canvas()->drawText(text.c_str(), text.size(),
|
| - rect.fLeft + (rect.width() - text_width) / 2,
|
| - rect.fTop + kTextSize + kTopTextPadding,
|
| + rect.x() + (rect.width() - text_width) / 2,
|
| + rect.y() + kTextSize + kTopTextPadding,
|
| *text_paint);
|
| canvas->Restore();
|
| }
|
| @@ -415,12 +447,15 @@ base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation(
|
| : base::WeakPtr<IconAnimation>();
|
| }
|
|
|
| -gfx::Image ExtensionAction::ApplyIconAnimation(int tab_id,
|
| - const gfx::Image& orig) const {
|
| - IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id);
|
| - if (wrapper == NULL)
|
| - return orig;
|
| - return gfx::Image(wrapper->animation()->Apply(*orig.ToSkBitmap()));
|
| +gfx::ImageSkia ExtensionAction::ApplyIconAnimation(
|
| + int tab_id,
|
| + const gfx::ImageSkia& icon) const {
|
| + IconAnimationWrapper* animation_wrapper = GetIconAnimationWrapper(tab_id);
|
| + if (animation_wrapper == NULL)
|
| + return icon;
|
| +
|
| + return gfx::ImageSkia(new AnimatedIconImageSource(icon, animation_wrapper),
|
| + icon.size());
|
| }
|
|
|
| void ExtensionAction::RunIconAnimation(int tab_id) {
|
|
|