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) { |