OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/common/extensions/extension_action.h" | 5 #include "chrome/common/extensions/extension_action.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "chrome/common/badge_util.h" | 10 #include "chrome/common/badge_util.h" |
11 #include "googleurl/src/gurl.h" | 11 #include "googleurl/src/gurl.h" |
12 #include "grit/theme_resources.h" | 12 #include "grit/theme_resources.h" |
13 #include "grit/ui_resources.h" | 13 #include "grit/ui_resources.h" |
14 #include "third_party/skia/include/core/SkBitmap.h" | 14 #include "third_party/skia/include/core/SkBitmap.h" |
15 #include "third_party/skia/include/core/SkCanvas.h" | 15 #include "third_party/skia/include/core/SkCanvas.h" |
16 #include "third_party/skia/include/core/SkDevice.h" | 16 #include "third_party/skia/include/core/SkDevice.h" |
17 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
18 #include "third_party/skia/include/effects/SkGradientShader.h" | 18 #include "third_party/skia/include/effects/SkGradientShader.h" |
19 #include "ui/base/animation/animation_delegate.h" | 19 #include "ui/base/animation/animation_delegate.h" |
20 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
22 #include "ui/gfx/color_utils.h" | 22 #include "ui/gfx/color_utils.h" |
23 #include "ui/gfx/image/image_skia.h" | |
24 #include "ui/gfx/image/image_skia_source.h" | |
23 #include "ui/gfx/rect.h" | 25 #include "ui/gfx/rect.h" |
24 #include "ui/gfx/image/image_skia_source.h" | 26 #include "ui/gfx/image/image_skia_source.h" |
25 #include "ui/gfx/skbitmap_operations.h" | 27 #include "ui/gfx/skbitmap_operations.h" |
26 | 28 |
27 namespace { | 29 namespace { |
28 | 30 |
29 // Different platforms need slightly different constants to look good. | 31 // Different platforms need slightly different constants to look good. |
30 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) | 32 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) |
31 const float kTextSize = 9.0; | 33 const float kTextSize = 9.0; |
32 const int kBottomMargin = 0; | 34 const int kBottomMargin = 0; |
(...skipping 16 matching lines...) Expand all Loading... | |
49 // The padding between the top of the badge and the top of the text. | 51 // The padding between the top of the badge and the top of the text. |
50 const int kTopTextPadding = -1; | 52 const int kTopTextPadding = -1; |
51 #endif | 53 #endif |
52 | 54 |
53 const int kBadgeHeight = 11; | 55 const int kBadgeHeight = 11; |
54 const int kMaxTextWidth = 23; | 56 const int kMaxTextWidth = 23; |
55 // The minimum width for center-aligning the badge. | 57 // The minimum width for center-aligning the badge. |
56 const int kCenterAlignThreshold = 20; | 58 const int kCenterAlignThreshold = 20; |
57 | 59 |
58 | 60 |
59 int Width(const gfx::Image& image) { | 61 int Width(const gfx::ImageSkia& image) { |
60 if (image.IsEmpty()) | 62 return image.size().width(); |
61 return 0; | |
62 return image.ToSkBitmap()->width(); | |
63 } | 63 } |
64 | 64 |
65 class GetAttentionImageSource : public gfx::ImageSkiaSource { | 65 class GetAttentionImageSource : public gfx::ImageSkiaSource { |
66 public: | 66 public: |
67 explicit GetAttentionImageSource(const gfx::Image& icon) | 67 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) |
68 : icon_(*icon.ToImageSkia()) {} | 68 : icon_(icon) {} |
69 | 69 |
70 // gfx::ImageSkiaSource overrides: | 70 // gfx::ImageSkiaSource overrides: |
71 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) | 71 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) |
72 OVERRIDE { | 72 OVERRIDE { |
73 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); | 73 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); |
74 color_utils::HSL shift = {-1, 0, 0.5}; | 74 color_utils::HSL shift = {-1, 0, 0.5}; |
75 return gfx::ImageSkiaRep( | 75 return gfx::ImageSkiaRep( |
76 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), | 76 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), |
77 icon_rep.scale_factor()); | 77 icon_rep.scale_factor()); |
78 } | 78 } |
(...skipping 29 matching lines...) Expand all Loading... | |
108 Done(); | 108 Done(); |
109 } | 109 } |
110 | 110 |
111 void Done() { | 111 void Done() { |
112 delete this; | 112 delete this; |
113 } | 113 } |
114 | 114 |
115 IconAnimation animation_; | 115 IconAnimation animation_; |
116 }; | 116 }; |
117 | 117 |
118 // Source for painting animated skia image. | |
119 class ExtensionAction::AnimatedIconImageSource : public gfx::ImageSkiaSource { | |
120 public: | |
121 AnimatedIconImageSource(const gfx::ImageSkia& image, | |
122 IconAnimationWrapper* animation) | |
123 : image_(image), | |
124 animation_(animation->AsWeakPtr()) { | |
125 } | |
126 | |
127 private: | |
128 virtual ~AnimatedIconImageSource() {} | |
129 | |
130 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale) OVERRIDE { | |
131 gfx::ImageSkiaRep original_rep = image_.GetRepresentation(scale); | |
132 if (!animation_) { | |
133 return original_rep; | |
134 } | |
135 | |
136 // Original representation's scale factor may be different from scale | |
137 // factor passed to this method. We want to use the former (since we are | |
138 // using bitmap for that scale). | |
139 return gfx::ImageSkiaRep( | |
140 animation_->animation()->Apply(original_rep.sk_bitmap()), | |
141 original_rep.scale_factor()); | |
142 } | |
143 | |
144 gfx::ImageSkia image_; | |
145 base::WeakPtr<IconAnimationWrapper> animation_; | |
146 }; | |
147 | |
148 | |
118 const int ExtensionAction::kDefaultTabId = -1; | 149 const int ExtensionAction::kDefaultTabId = -1; |
119 | 150 |
120 ExtensionAction::IconAnimation::IconAnimation( | 151 ExtensionAction::IconAnimation::IconAnimation( |
121 ui::AnimationDelegate* delegate) | 152 ui::AnimationDelegate* delegate) |
122 // 100ms animation at 50fps (so 5 animation frames in total). | 153 // 100ms animation at 50fps (so 5 animation frames in total). |
123 : ui::LinearAnimation(100, 50, delegate) {} | 154 : ui::LinearAnimation(100, 50, delegate) {} |
124 | 155 |
125 ExtensionAction::IconAnimation::~IconAnimation() {} | 156 ExtensionAction::IconAnimation::~IconAnimation() {} |
126 | 157 |
127 const SkBitmap& ExtensionAction::IconAnimation::Apply( | 158 const SkBitmap& ExtensionAction::IconAnimation::Apply( |
pkotwicz
2012/08/07 22:31:22
Can we merge this logic into AnimatedIconSource. (
tbarzic
2012/08/08 02:09:29
added todo..
| |
128 const SkBitmap& icon) const { | 159 const SkBitmap& icon) const { |
129 DCHECK_GT(icon.width(), 0); | 160 DCHECK_GT(icon.width(), 0); |
130 DCHECK_GT(icon.height(), 0); | 161 DCHECK_GT(icon.height(), 0); |
131 | 162 |
132 if (!device_.get() || | 163 if (!device_.get() || |
133 (device_->width() != icon.width()) || | 164 (device_->width() != icon.width()) || |
134 (device_->height() != icon.height())) { | 165 (device_->height() != icon.height())) { |
135 device_.reset(new SkDevice( | 166 device_.reset(new SkDevice( |
136 SkBitmap::kARGB_8888_Config, icon.width(), icon.height(), true)); | 167 SkBitmap::kARGB_8888_Config, icon.width(), icon.height(), true)); |
137 } | 168 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 | 241 |
211 bool ExtensionAction::HasPopup(int tab_id) const { | 242 bool ExtensionAction::HasPopup(int tab_id) const { |
212 return !GetPopupUrl(tab_id).is_empty(); | 243 return !GetPopupUrl(tab_id).is_empty(); |
213 } | 244 } |
214 | 245 |
215 GURL ExtensionAction::GetPopupUrl(int tab_id) const { | 246 GURL ExtensionAction::GetPopupUrl(int tab_id) const { |
216 return GetValue(&popup_url_, tab_id); | 247 return GetValue(&popup_url_, tab_id); |
217 } | 248 } |
218 | 249 |
219 void ExtensionAction::CacheIcon(const std::string& path, | 250 void ExtensionAction::CacheIcon(const std::string& path, |
220 const gfx::Image& icon) { | 251 const gfx::ImageSkia& icon) { |
221 if (!icon.IsEmpty()) | 252 if (!icon.empty()) |
222 path_to_icon_cache_.insert(std::make_pair(path, icon)); | 253 path_to_icon_cache_.insert(std::make_pair(path, icon)); |
223 } | 254 } |
224 | 255 |
225 void ExtensionAction::SetIcon(int tab_id, const SkBitmap& bitmap) { | 256 void ExtensionAction::SetIcon(int tab_id, const gfx::ImageSkia& image) { |
226 SetValue(&icon_, tab_id, gfx::Image(bitmap)); | 257 SetValue(&icon_, tab_id, image); |
227 } | 258 } |
228 | 259 |
229 gfx::Image ExtensionAction::GetIcon(int tab_id) const { | 260 gfx::ImageSkia ExtensionAction::GetIcon(int tab_id) const { |
230 // Check if a specific icon is set for this tab. | 261 // Check if a specific icon is set for this tab. |
231 gfx::Image icon = GetValue(&icon_, tab_id); | 262 gfx::ImageSkia icon = GetValue(&icon_, tab_id); |
232 if (icon.IsEmpty()) { | 263 if (icon.empty()) { |
233 // Need to find an icon from a path. | 264 // Need to find an icon from a path. |
234 const std::string* path = NULL; | 265 const std::string* path = NULL; |
235 // Check if one of the elements of icon_path() was selected. | 266 // Check if one of the elements of icon_path() was selected. |
236 int icon_index = GetIconIndex(tab_id); | 267 int icon_index = GetIconIndex(tab_id); |
237 if (icon_index >= 0) { | 268 if (icon_index >= 0) { |
238 path = &icon_paths()->at(icon_index); | 269 path = &icon_paths()->at(icon_index); |
239 } else { | 270 } else { |
240 // Otherwise, use the default icon. | 271 // Otherwise, use the default icon. |
241 path = &default_icon_path(); | 272 path = &default_icon_path(); |
242 } | 273 } |
243 | 274 |
244 std::map<std::string, gfx::Image>::const_iterator cached_icon = | 275 std::map<std::string, gfx::ImageSkia>::const_iterator cached_icon = |
245 path_to_icon_cache_.find(*path); | 276 path_to_icon_cache_.find(*path); |
246 if (cached_icon != path_to_icon_cache_.end()) { | 277 if (cached_icon != path_to_icon_cache_.end()) { |
247 icon = cached_icon->second; | 278 icon = cached_icon->second; |
248 } else { | 279 } else { |
249 icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 280 icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
250 IDR_EXTENSIONS_FAVICON); | 281 IDR_EXTENSIONS_FAVICON); |
251 } | 282 } |
252 } | 283 } |
253 | 284 |
254 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) { | 285 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) |
255 icon = gfx::Image(gfx::ImageSkia(new GetAttentionImageSource(icon), | 286 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); |
256 icon.ToImageSkia()->size())); | |
257 } | |
258 | 287 |
259 return ApplyIconAnimation(tab_id, icon); | 288 return ApplyIconAnimation(tab_id, icon); |
260 } | 289 } |
261 | 290 |
262 void ExtensionAction::SetIconIndex(int tab_id, int index) { | 291 void ExtensionAction::SetIconIndex(int tab_id, int index) { |
263 if (static_cast<size_t>(index) >= icon_paths_.size()) { | 292 if (static_cast<size_t>(index) >= icon_paths_.size()) { |
264 NOTREACHED(); | 293 NOTREACHED(); |
265 return; | 294 return; |
266 } | 295 } |
267 SetValue(&icon_index_, tab_id, index); | 296 SetValue(&icon_index_, tab_id, index); |
(...skipping 24 matching lines...) Expand all Loading... | |
292 badge_text_.erase(tab_id); | 321 badge_text_.erase(tab_id); |
293 badge_text_color_.erase(tab_id); | 322 badge_text_color_.erase(tab_id); |
294 badge_background_color_.erase(tab_id); | 323 badge_background_color_.erase(tab_id); |
295 appearance_.erase(tab_id); | 324 appearance_.erase(tab_id); |
296 icon_animation_.erase(tab_id); | 325 icon_animation_.erase(tab_id); |
297 } | 326 } |
298 | 327 |
299 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, | 328 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, |
300 const gfx::Rect& bounds, | 329 const gfx::Rect& bounds, |
301 int tab_id) { | 330 int tab_id) { |
302 std::string text = GetBadgeText(tab_id); | 331 ExtensionAction::DoPaintBadge( |
332 canvas, | |
333 bounds, | |
334 GetBadgeText(tab_id), | |
335 GetBadgeTextColor(tab_id), | |
336 GetBadgeBackgroundColor(tab_id), | |
337 Width(GetValue(&icon_, tab_id))); | |
338 } | |
339 | |
340 // static | |
341 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, | |
342 const gfx::Rect& bounds, | |
343 const std::string& text, | |
344 const SkColor& text_color_in, | |
345 const SkColor& background_color_in, | |
346 int icon_width) { | |
303 if (text.empty()) | 347 if (text.empty()) |
304 return; | 348 return; |
305 | 349 |
306 SkColor text_color = GetBadgeTextColor(tab_id); | 350 SkColor text_color = (SkColorGetA(text_color_in) == 0x00) ? |
307 SkColor background_color = GetBadgeBackgroundColor(tab_id); | 351 SK_ColorWHITE : text_color_in; |
308 | 352 |
309 if (SkColorGetA(text_color) == 0x00) | 353 SkColor background_color = (SkColorGetA(background_color_in) == 0x00) ? |
310 text_color = SK_ColorWHITE; | 354 SkColorSetARGB(255, 218, 0, 24) : background_color_in; |
311 | |
312 if (SkColorGetA(background_color) == 0x00) | |
313 background_color = SkColorSetARGB(255, 218, 0, 24); // Default badge color. | |
314 | 355 |
315 canvas->Save(); | 356 canvas->Save(); |
316 | 357 |
317 SkPaint* text_paint = badge_util::GetBadgeTextPaintSingleton(); | 358 SkPaint* text_paint = badge_util::GetBadgeTextPaintSingleton(); |
318 text_paint->setTextSize(SkFloatToScalar(kTextSize)); | 359 text_paint->setTextSize(SkFloatToScalar(kTextSize)); |
319 text_paint->setColor(text_color); | 360 text_paint->setColor(text_color); |
320 | 361 |
321 // Calculate text width. We clamp it to a max size. | 362 // Calculate text width. We clamp it to a max size. |
322 SkScalar text_width = text_paint->measureText(text.c_str(), text.size()); | 363 SkScalar text_width_sk = text_paint->measureText(text.c_str(), text.size()); |
323 text_width = SkIntToScalar( | 364 int text_width = std::min(kMaxTextWidth, SkScalarFloor(text_width_sk)); |
324 std::min(kMaxTextWidth, SkScalarFloor(text_width))); | |
325 | 365 |
326 // Calculate badge size. It is clamped to a min width just because it looks | 366 // Calculate badge size. It is clamped to a min width just because it looks |
327 // silly if it is too skinny. | 367 // silly if it is too skinny. |
328 int badge_width = SkScalarFloor(text_width) + kPadding * 2; | 368 int badge_width = text_width + kPadding * 2; |
329 int icon_width = Width(GetValue(&icon_, tab_id)); | |
330 // Force the pixel width of badge to be either odd (if the icon width is odd) | 369 // Force the pixel width of badge to be either odd (if the icon width is odd) |
331 // or even otherwise. If there is a mismatch you get http://crbug.com/26400. | 370 // or even otherwise. If there is a mismatch you get http://crbug.com/26400. |
332 if (icon_width != 0 && (badge_width % 2 != icon_width % 2)) | 371 if (icon_width != 0 && (badge_width % 2 != icon_width % 2)) |
333 badge_width += 1; | 372 badge_width += 1; |
334 badge_width = std::max(kBadgeHeight, badge_width); | 373 badge_width = std::max(kBadgeHeight, badge_width); |
335 | 374 |
336 // Paint the badge background color in the right location. It is usually | 375 // Paint the badge background color in the right location. It is usually |
337 // right-aligned, but it can also be center-aligned if it is large. | 376 // right-aligned, but it can also be center-aligned if it is large. |
338 SkRect rect; | 377 int rect_height = kBadgeHeight; |
339 rect.fBottom = SkIntToScalar(bounds.bottom() - kBottomMargin); | 378 int rect_y = bounds.bottom() - kBottomMargin - kBadgeHeight; |
340 rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight); | 379 int rect_width = badge_width; |
341 if (badge_width >= kCenterAlignThreshold) { | 380 int rect_x = (badge_width >= kCenterAlignThreshold) ? |
342 rect.fLeft = SkIntToScalar( | 381 (bounds.x() + bounds.width()) / 2 - badge_width / 2 : |
343 SkScalarFloor(SkIntToScalar(bounds.x()) + | 382 bounds.right() - badge_width; |
344 SkIntToScalar(bounds.width()) / 2 - | 383 gfx::Rect rect(rect_x, rect_y, rect_width, rect_height); |
345 SkIntToScalar(badge_width) / 2)); | |
346 rect.fRight = rect.fLeft + SkIntToScalar(badge_width); | |
347 } else { | |
348 rect.fRight = SkIntToScalar(bounds.right()); | |
349 rect.fLeft = rect.fRight - badge_width; | |
350 } | |
351 | 384 |
352 SkPaint rect_paint; | 385 SkPaint rect_paint; |
353 rect_paint.setStyle(SkPaint::kFill_Style); | 386 rect_paint.setStyle(SkPaint::kFill_Style); |
354 rect_paint.setAntiAlias(true); | 387 rect_paint.setAntiAlias(true); |
355 rect_paint.setColor(background_color); | 388 rect_paint.setColor(background_color); |
356 canvas->sk_canvas()->drawRoundRect(rect, SkIntToScalar(2), | 389 canvas->DrawRoundRect(rect, 2, rect_paint); |
357 SkIntToScalar(2), rect_paint); | |
358 | 390 |
359 // Overlay the gradient. It is stretchy, so we do this in three parts. | 391 // Overlay the gradient. It is stretchy, so we do this in three parts. |
360 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 392 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
361 SkBitmap* gradient_left = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_LEFT); | 393 gfx::ImageSkia* gradient_left = rb.GetImageSkiaNamed( |
362 SkBitmap* gradient_right = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_RIGHT); | 394 IDR_BROWSER_ACTION_BADGE_LEFT); |
363 SkBitmap* gradient_center = rb.GetBitmapNamed( | 395 gfx::ImageSkia* gradient_right = rb.GetImageSkiaNamed( |
396 IDR_BROWSER_ACTION_BADGE_RIGHT); | |
397 gfx::ImageSkia* gradient_center = rb.GetImageSkiaNamed( | |
364 IDR_BROWSER_ACTION_BADGE_CENTER); | 398 IDR_BROWSER_ACTION_BADGE_CENTER); |
365 | 399 |
366 canvas->sk_canvas()->drawBitmap(*gradient_left, rect.fLeft, rect.fTop); | 400 canvas->DrawImageInt(*gradient_left, rect.x(), rect.y()); |
367 canvas->TileImageInt(*gradient_center, | 401 canvas->TileImageInt(*gradient_center, |
368 SkScalarFloor(rect.fLeft) + gradient_left->width(), | 402 rect.x() + gradient_left->width(), |
369 SkScalarFloor(rect.fTop), | 403 rect.y(), |
370 SkScalarFloor(rect.width()) - gradient_left->width() - | 404 rect.width() - gradient_left->width() - gradient_right->width(), |
371 gradient_right->width(), | 405 rect.height()); |
372 SkScalarFloor(rect.height())); | 406 canvas->DrawImageInt(*gradient_right, |
373 canvas->sk_canvas()->drawBitmap(*gradient_right, | 407 rect.right() - gradient_right->width(), rect.y()); |
374 rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop); | |
375 | 408 |
376 // Finally, draw the text centered within the badge. We set a clip in case the | 409 // Finally, draw the text centered within the badge. We set a clip in case the |
377 // text was too large. | 410 // text was too large. |
378 rect.fLeft += kPadding; | 411 rect.Inset(kPadding, 0); |
379 rect.fRight -= kPadding; | 412 canvas->ClipRect(rect); |
380 canvas->sk_canvas()->clipRect(rect); | |
381 canvas->sk_canvas()->drawText(text.c_str(), text.size(), | 413 canvas->sk_canvas()->drawText(text.c_str(), text.size(), |
382 rect.fLeft + (rect.width() - text_width) / 2, | 414 rect.x() + (rect.width() - text_width) / 2, |
383 rect.fTop + kTextSize + kTopTextPadding, | 415 rect.y() + kTextSize + kTopTextPadding, |
384 *text_paint); | 416 *text_paint); |
385 canvas->Restore(); | 417 canvas->Restore(); |
386 } | 418 } |
387 | 419 |
388 ExtensionAction::IconAnimationWrapper* ExtensionAction::GetIconAnimationWrapper( | 420 ExtensionAction::IconAnimationWrapper* ExtensionAction::GetIconAnimationWrapper( |
389 int tab_id) const { | 421 int tab_id) const { |
390 std::map<int, base::WeakPtr<IconAnimationWrapper> >::iterator it = | 422 std::map<int, base::WeakPtr<IconAnimationWrapper> >::iterator it = |
391 icon_animation_.find(tab_id); | 423 icon_animation_.find(tab_id); |
392 if (it == icon_animation_.end()) | 424 if (it == icon_animation_.end()) |
393 return NULL; | 425 return NULL; |
(...skipping 14 matching lines...) Expand all Loading... | |
408 return NULL; | 440 return NULL; |
409 } | 441 } |
410 | 442 |
411 base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation( | 443 base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation( |
412 int tab_id) const { | 444 int tab_id) const { |
413 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); | 445 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); |
414 return wrapper ? wrapper->animation()->AsWeakPtr() | 446 return wrapper ? wrapper->animation()->AsWeakPtr() |
415 : base::WeakPtr<IconAnimation>(); | 447 : base::WeakPtr<IconAnimation>(); |
416 } | 448 } |
417 | 449 |
418 gfx::Image ExtensionAction::ApplyIconAnimation(int tab_id, | 450 gfx::ImageSkia ExtensionAction::ApplyIconAnimation( |
419 const gfx::Image& orig) const { | 451 int tab_id, |
420 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); | 452 const gfx::ImageSkia& icon) const { |
421 if (wrapper == NULL) | 453 IconAnimationWrapper* animation_wrapper = GetIconAnimationWrapper(tab_id); |
422 return orig; | 454 if (animation_wrapper == NULL) |
423 return gfx::Image(wrapper->animation()->Apply(*orig.ToSkBitmap())); | 455 return icon; |
456 | |
457 return gfx::ImageSkia(new AnimatedIconImageSource(icon, animation_wrapper), | |
458 icon.size()); | |
424 } | 459 } |
425 | 460 |
426 void ExtensionAction::RunIconAnimation(int tab_id) { | 461 void ExtensionAction::RunIconAnimation(int tab_id) { |
427 IconAnimationWrapper* icon_animation = | 462 IconAnimationWrapper* icon_animation = |
428 new IconAnimationWrapper(); | 463 new IconAnimationWrapper(); |
429 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); | 464 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); |
430 icon_animation->animation()->Start(); | 465 icon_animation->animation()->Start(); |
431 } | 466 } |
OLD | NEW |