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/canvas_image_source.h" | |
24 #include "ui/gfx/image/image_skia.h" | |
25 #include "ui/gfx/image/image_skia_source.h" | |
23 #include "ui/gfx/rect.h" | 26 #include "ui/gfx/rect.h" |
27 #include "ui/gfx/size.h" | |
24 #include "ui/gfx/image/image_skia_source.h" | 28 #include "ui/gfx/image/image_skia_source.h" |
25 #include "ui/gfx/skbitmap_operations.h" | 29 #include "ui/gfx/skbitmap_operations.h" |
26 | 30 |
27 namespace { | 31 namespace { |
28 | 32 |
29 // Different platforms need slightly different constants to look good. | 33 // Different platforms need slightly different constants to look good. |
30 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) | 34 #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) |
31 const float kTextSize = 9.0; | 35 const float kTextSize = 9.0; |
32 const int kBottomMargin = 0; | 36 const int kBottomMargin = 0; |
33 const int kPadding = 2; | 37 const int kPadding = 2; |
(...skipping 14 matching lines...) Expand all Loading... | |
48 const int kPadding = 2; | 52 const int kPadding = 2; |
49 // The padding between the top of the badge and the top of the text. | 53 // The padding between the top of the badge and the top of the text. |
50 const int kTopTextPadding = -1; | 54 const int kTopTextPadding = -1; |
51 #endif | 55 #endif |
52 | 56 |
53 const int kBadgeHeight = 11; | 57 const int kBadgeHeight = 11; |
54 const int kMaxTextWidth = 23; | 58 const int kMaxTextWidth = 23; |
55 // The minimum width for center-aligning the badge. | 59 // The minimum width for center-aligning the badge. |
56 const int kCenterAlignThreshold = 20; | 60 const int kCenterAlignThreshold = 20; |
57 | 61 |
58 | |
59 int Width(const gfx::Image& image) { | |
60 if (image.IsEmpty()) | |
61 return 0; | |
62 return image.ToSkBitmap()->width(); | |
63 } | |
64 | |
65 class GetAttentionImageSource : public gfx::ImageSkiaSource { | 62 class GetAttentionImageSource : public gfx::ImageSkiaSource { |
66 public: | 63 public: |
67 explicit GetAttentionImageSource(const gfx::Image& icon) | 64 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) |
68 : icon_(*icon.ToImageSkia()) {} | 65 : icon_(icon) {} |
69 | 66 |
70 // gfx::ImageSkiaSource overrides: | 67 // gfx::ImageSkiaSource overrides: |
71 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) | 68 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) |
72 OVERRIDE { | 69 OVERRIDE { |
73 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); | 70 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); |
74 color_utils::HSL shift = {-1, 0, 0.5}; | 71 color_utils::HSL shift = {-1, 0, 0.5}; |
75 return gfx::ImageSkiaRep( | 72 return gfx::ImageSkiaRep( |
76 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), | 73 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift), |
77 icon_rep.scale_factor()); | 74 icon_rep.scale_factor()); |
78 } | 75 } |
(...skipping 29 matching lines...) Expand all Loading... | |
108 Done(); | 105 Done(); |
109 } | 106 } |
110 | 107 |
111 void Done() { | 108 void Done() { |
112 delete this; | 109 delete this; |
113 } | 110 } |
114 | 111 |
115 IconAnimation animation_; | 112 IconAnimation animation_; |
116 }; | 113 }; |
117 | 114 |
115 // TODO(tbarzic): Merge AnimationIconImageSource and IconAnimation together. | |
116 // Source for painting animated skia image. | |
117 class AnimatedIconImageSource : public gfx::ImageSkiaSource { | |
118 public: | |
119 AnimatedIconImageSource(const gfx::ImageSkia& image, | |
120 ExtensionAction::IconAnimation* animation) | |
121 : image_(image), | |
122 animation_(animation->AsWeakPtr()) { | |
123 } | |
124 | |
125 private: | |
126 virtual ~AnimatedIconImageSource() {} | |
127 | |
128 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale) OVERRIDE { | |
129 gfx::ImageSkiaRep original_rep = image_.GetRepresentation(scale); | |
130 if (!animation_) | |
131 return original_rep; | |
132 | |
133 // Original representation's scale factor may be different from scale | |
134 // factor passed to this method. We want to use the former (since we are | |
135 // using bitmap for that scale). | |
136 return gfx::ImageSkiaRep( | |
137 animation_->Apply(original_rep.sk_bitmap()), | |
138 original_rep.scale_factor()); | |
139 } | |
140 | |
141 gfx::ImageSkia image_; | |
142 base::WeakPtr<ExtensionAction::IconAnimation> animation_; | |
143 | |
144 DISALLOW_COPY_AND_ASSIGN(AnimatedIconImageSource); | |
145 }; | |
146 | |
147 // CanvasImageSource for creating browser action icon with a badge. | |
148 class ExtensionAction::IconWithBadgeImageSource | |
149 : public gfx::CanvasImageSource { | |
150 public: | |
151 IconWithBadgeImageSource(const gfx::ImageSkia& icon, | |
152 const gfx::Size& spacing, | |
153 const std::string& text, | |
154 const SkColor& text_color, | |
155 const SkColor& background_color) | |
156 : gfx::CanvasImageSource(icon.size(), false), | |
157 icon_(icon), | |
158 spacing_(spacing), | |
159 text_(text), | |
160 text_color_(text_color), | |
161 background_color_(background_color) { | |
162 } | |
163 | |
164 virtual ~IconWithBadgeImageSource() {} | |
165 | |
166 private: | |
167 virtual void Draw(gfx::Canvas* canvas) OVERRIDE { | |
168 canvas->DrawImageInt(icon_, 0, 0, SkPaint()); | |
169 | |
170 gfx::Rect bounds(size_.width() + spacing_.width(), | |
171 size_.height() + spacing_.height()); | |
172 | |
173 // Draw a badge on the provided browser action icon's canvas. | |
174 ExtensionAction::DoPaintBadge(canvas, bounds, text_, text_color_, | |
175 background_color_, size_.width()); | |
176 } | |
177 | |
178 // Browser action icon image. | |
179 gfx::ImageSkia icon_; | |
180 // Extra spacing for badge compared to icon bounds. | |
181 gfx::Size spacing_; | |
182 // Text to be displayed on the badge. | |
183 std::string text_; | |
184 // Color of badge text. | |
185 SkColor text_color_; | |
186 // Color of the badge. | |
187 SkColor background_color_; | |
188 | |
189 DISALLOW_COPY_AND_ASSIGN(IconWithBadgeImageSource); | |
190 }; | |
191 | |
192 | |
118 const int ExtensionAction::kDefaultTabId = -1; | 193 const int ExtensionAction::kDefaultTabId = -1; |
119 | 194 |
120 ExtensionAction::IconAnimation::IconAnimation( | 195 ExtensionAction::IconAnimation::IconAnimation( |
121 ui::AnimationDelegate* delegate) | 196 ui::AnimationDelegate* delegate) |
122 // 100ms animation at 50fps (so 5 animation frames in total). | 197 // 100ms animation at 50fps (so 5 animation frames in total). |
123 : ui::LinearAnimation(100, 50, delegate) {} | 198 : ui::LinearAnimation(1000, 50, delegate) {} |
124 | 199 |
125 ExtensionAction::IconAnimation::~IconAnimation() {} | 200 ExtensionAction::IconAnimation::~IconAnimation() {} |
126 | 201 |
127 const SkBitmap& ExtensionAction::IconAnimation::Apply( | 202 const SkBitmap& ExtensionAction::IconAnimation::Apply( |
128 const SkBitmap& icon) const { | 203 const SkBitmap& icon) const { |
129 DCHECK_GT(icon.width(), 0); | 204 DCHECK_GT(icon.width(), 0); |
130 DCHECK_GT(icon.height(), 0); | 205 DCHECK_GT(icon.height(), 0); |
131 | 206 |
132 if (!device_.get() || | 207 if (!device_.get() || |
133 (device_->width() != icon.width()) || | 208 (device_->width() != icon.width()) || |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
213 return !GetPopupUrl(tab_id).is_empty(); | 288 return !GetPopupUrl(tab_id).is_empty(); |
214 } | 289 } |
215 | 290 |
216 GURL ExtensionAction::GetPopupUrl(int tab_id) const { | 291 GURL ExtensionAction::GetPopupUrl(int tab_id) const { |
217 return GetValue(&popup_url_, tab_id); | 292 return GetValue(&popup_url_, tab_id); |
218 } | 293 } |
219 | 294 |
220 void ExtensionAction::CacheIcon(const std::string& path, | 295 void ExtensionAction::CacheIcon(const std::string& path, |
221 const gfx::Image& icon) { | 296 const gfx::Image& icon) { |
222 if (!icon.IsEmpty()) | 297 if (!icon.IsEmpty()) |
223 path_to_icon_cache_.insert(std::make_pair(path, icon)); | 298 path_to_icon_cache_.insert(std::make_pair(path, *icon.ToImageSkia())); |
224 } | 299 } |
225 | 300 |
226 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { | 301 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { |
227 SetValue(&icon_, tab_id, image); | 302 SetValue(&icon_, tab_id, *image.ToImageSkia()); |
228 } | 303 } |
229 | 304 |
230 gfx::Image ExtensionAction::GetIcon(int tab_id) const { | 305 gfx::Image ExtensionAction::GetIcon(int tab_id) const { |
231 // Check if a specific icon is set for this tab. | 306 // Check if a specific icon is set for this tab. |
232 gfx::Image icon = GetValue(&icon_, tab_id); | 307 gfx::ImageSkia icon = GetValue(&icon_, tab_id); |
233 if (icon.IsEmpty()) { | 308 if (icon.empty()) { |
234 // Need to find an icon from a path. | 309 // Need to find an icon from a path. |
235 const std::string* path = NULL; | 310 const std::string* path = NULL; |
236 // Check if one of the elements of icon_path() was selected. | 311 // Check if one of the elements of icon_path() was selected. |
237 int icon_index = GetIconIndex(tab_id); | 312 int icon_index = GetIconIndex(tab_id); |
238 if (icon_index >= 0) { | 313 if (icon_index >= 0) { |
239 path = &icon_paths()->at(icon_index); | 314 path = &icon_paths()->at(icon_index); |
240 } else { | 315 } else { |
241 // Otherwise, use the default icon. | 316 // Otherwise, use the default icon. |
242 path = &default_icon_path(); | 317 path = &default_icon_path(); |
243 } | 318 } |
244 | 319 |
245 std::map<std::string, gfx::Image>::const_iterator cached_icon = | 320 std::map<std::string, gfx::ImageSkia>::const_iterator cached_icon = |
246 path_to_icon_cache_.find(*path); | 321 path_to_icon_cache_.find(*path); |
247 if (cached_icon != path_to_icon_cache_.end()) { | 322 if (cached_icon != path_to_icon_cache_.end()) { |
248 icon = cached_icon->second; | 323 icon = cached_icon->second; |
249 } else { | 324 } else { |
250 icon = ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 325 icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
251 IDR_EXTENSIONS_FAVICON); | 326 IDR_EXTENSIONS_FAVICON); |
252 } | 327 } |
253 } | 328 } |
254 | 329 |
255 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) { | 330 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) |
256 icon = gfx::Image(gfx::ImageSkia(new GetAttentionImageSource(icon), | 331 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); |
257 icon.ToImageSkia()->size())); | |
258 } | |
259 | 332 |
260 return ApplyIconAnimation(tab_id, icon); | 333 return gfx::Image(ApplyIconAnimation(tab_id, icon)); |
261 } | 334 } |
262 | 335 |
263 void ExtensionAction::SetIconIndex(int tab_id, int index) { | 336 void ExtensionAction::SetIconIndex(int tab_id, int index) { |
264 if (static_cast<size_t>(index) >= icon_paths_.size()) { | 337 if (static_cast<size_t>(index) >= icon_paths_.size()) { |
265 NOTREACHED(); | 338 NOTREACHED(); |
266 return; | 339 return; |
267 } | 340 } |
268 SetValue(&icon_index_, tab_id, index); | 341 SetValue(&icon_index_, tab_id, index); |
269 } | 342 } |
270 | 343 |
(...skipping 22 matching lines...) Expand all Loading... | |
293 badge_text_.erase(tab_id); | 366 badge_text_.erase(tab_id); |
294 badge_text_color_.erase(tab_id); | 367 badge_text_color_.erase(tab_id); |
295 badge_background_color_.erase(tab_id); | 368 badge_background_color_.erase(tab_id); |
296 appearance_.erase(tab_id); | 369 appearance_.erase(tab_id); |
297 icon_animation_.erase(tab_id); | 370 icon_animation_.erase(tab_id); |
298 } | 371 } |
299 | 372 |
300 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, | 373 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, |
301 const gfx::Rect& bounds, | 374 const gfx::Rect& bounds, |
302 int tab_id) { | 375 int tab_id) { |
303 std::string text = GetBadgeText(tab_id); | 376 ExtensionAction::DoPaintBadge( |
377 canvas, | |
378 bounds, | |
379 GetBadgeText(tab_id), | |
380 GetBadgeTextColor(tab_id), | |
381 GetBadgeBackgroundColor(tab_id), | |
382 GetValue(&icon_, tab_id).size().width()); | |
383 } | |
384 | |
385 gfx::ImageSkia ExtensionAction::GetIconWithBadge( | |
386 const gfx::ImageSkia& icon, | |
387 int tab_id, | |
388 const gfx::Size& spacing) const { | |
389 if (tab_id < 0) | |
390 return icon; | |
391 | |
392 return gfx::ImageSkia( | |
393 new IconWithBadgeImageSource(icon, | |
394 spacing, | |
395 GetBadgeText(tab_id), | |
396 GetBadgeTextColor(tab_id), | |
397 GetBadgeBackgroundColor(tab_id)), | |
398 icon.size()); | |
399 } | |
400 | |
401 // static | |
402 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, | |
403 const gfx::Rect& bounds, | |
404 const std::string& text, | |
405 const SkColor& text_color_in, | |
406 const SkColor& background_color_in, | |
407 int icon_width) { | |
304 if (text.empty()) | 408 if (text.empty()) |
305 return; | 409 return; |
306 | 410 |
307 SkColor text_color = GetBadgeTextColor(tab_id); | 411 SkColor text_color = text_color_in; |
308 SkColor background_color = GetBadgeBackgroundColor(tab_id); | 412 if (SkColorGetA(text_color_in) == 0x00) |
309 | |
310 if (SkColorGetA(text_color) == 0x00) | |
311 text_color = SK_ColorWHITE; | 413 text_color = SK_ColorWHITE; |
312 | 414 |
313 if (SkColorGetA(background_color) == 0x00) | 415 SkColor background_color = background_color_in; |
314 background_color = SkColorSetARGB(255, 218, 0, 24); // Default badge color. | 416 if (SkColorGetA(background_color_in) == 0x00) |
417 background_color = SkColorSetARGB(255, 218, 0, 24); | |
315 | 418 |
316 canvas->Save(); | 419 canvas->Save(); |
317 | 420 |
318 SkPaint* text_paint = badge_util::GetBadgeTextPaintSingleton(); | 421 SkPaint* text_paint = badge_util::GetBadgeTextPaintSingleton(); |
319 text_paint->setTextSize(SkFloatToScalar(kTextSize)); | 422 text_paint->setTextSize(SkFloatToScalar(kTextSize)); |
320 text_paint->setColor(text_color); | 423 text_paint->setColor(text_color); |
321 | 424 |
322 // Calculate text width. We clamp it to a max size. | 425 // Calculate text width. We clamp it to a max size. |
323 SkScalar text_width = text_paint->measureText(text.c_str(), text.size()); | 426 SkScalar sk_text_width = text_paint->measureText(text.c_str(), text.size()); |
324 text_width = SkIntToScalar( | 427 int text_width = std::min(kMaxTextWidth, SkScalarFloor(sk_text_width)); |
325 std::min(kMaxTextWidth, SkScalarFloor(text_width))); | |
326 | 428 |
327 // Calculate badge size. It is clamped to a min width just because it looks | 429 // Calculate badge size. It is clamped to a min width just because it looks |
328 // silly if it is too skinny. | 430 // silly if it is too skinny. |
329 int badge_width = SkScalarFloor(text_width) + kPadding * 2; | 431 int badge_width = text_width + kPadding * 2; |
330 int icon_width = Width(GetValue(&icon_, tab_id)); | |
331 // Force the pixel width of badge to be either odd (if the icon width is odd) | 432 // Force the pixel width of badge to be either odd (if the icon width is odd) |
332 // or even otherwise. If there is a mismatch you get http://crbug.com/26400. | 433 // or even otherwise. If there is a mismatch you get http://crbug.com/26400. |
333 if (icon_width != 0 && (badge_width % 2 != icon_width % 2)) | 434 if (icon_width != 0 && (badge_width % 2 != icon_width % 2)) |
334 badge_width += 1; | 435 badge_width += 1; |
335 badge_width = std::max(kBadgeHeight, badge_width); | 436 badge_width = std::max(kBadgeHeight, badge_width); |
336 | 437 |
337 // Paint the badge background color in the right location. It is usually | 438 // Paint the badge background color in the right location. It is usually |
338 // right-aligned, but it can also be center-aligned if it is large. | 439 // right-aligned, but it can also be center-aligned if it is large. |
339 SkRect rect; | 440 int rect_height = kBadgeHeight; |
340 rect.fBottom = SkIntToScalar(bounds.bottom() - kBottomMargin); | 441 int rect_y = bounds.bottom() - kBottomMargin - kBadgeHeight; |
341 rect.fTop = rect.fBottom - SkIntToScalar(kBadgeHeight); | 442 int rect_width = badge_width; |
342 if (badge_width >= kCenterAlignThreshold) { | 443 int rect_x = (badge_width >= kCenterAlignThreshold) ? |
343 rect.fLeft = SkIntToScalar( | 444 (bounds.x() + bounds.width()) / 2 - badge_width / 2 : |
344 SkScalarFloor(SkIntToScalar(bounds.x()) + | 445 bounds.right() - badge_width; |
345 SkIntToScalar(bounds.width()) / 2 - | 446 gfx::Rect rect(rect_x, rect_y, rect_width, rect_height); |
Finnur
2012/09/06 16:05:47
I believe this caused a regression:
http://code.go
| |
346 SkIntToScalar(badge_width) / 2)); | |
347 rect.fRight = rect.fLeft + SkIntToScalar(badge_width); | |
348 } else { | |
349 rect.fRight = SkIntToScalar(bounds.right()); | |
350 rect.fLeft = rect.fRight - badge_width; | |
351 } | |
352 | 447 |
353 SkPaint rect_paint; | 448 SkPaint rect_paint; |
354 rect_paint.setStyle(SkPaint::kFill_Style); | 449 rect_paint.setStyle(SkPaint::kFill_Style); |
355 rect_paint.setAntiAlias(true); | 450 rect_paint.setAntiAlias(true); |
356 rect_paint.setColor(background_color); | 451 rect_paint.setColor(background_color); |
357 canvas->sk_canvas()->drawRoundRect(rect, SkIntToScalar(2), | 452 canvas->DrawRoundRect(rect, 2, rect_paint); |
358 SkIntToScalar(2), rect_paint); | |
359 | 453 |
360 // Overlay the gradient. It is stretchy, so we do this in three parts. | 454 // Overlay the gradient. It is stretchy, so we do this in three parts. |
361 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 455 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
362 SkBitmap* gradient_left = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_LEFT); | 456 gfx::ImageSkia* gradient_left = rb.GetImageSkiaNamed( |
363 SkBitmap* gradient_right = rb.GetBitmapNamed(IDR_BROWSER_ACTION_BADGE_RIGHT); | 457 IDR_BROWSER_ACTION_BADGE_LEFT); |
364 SkBitmap* gradient_center = rb.GetBitmapNamed( | 458 gfx::ImageSkia* gradient_right = rb.GetImageSkiaNamed( |
459 IDR_BROWSER_ACTION_BADGE_RIGHT); | |
460 gfx::ImageSkia* gradient_center = rb.GetImageSkiaNamed( | |
365 IDR_BROWSER_ACTION_BADGE_CENTER); | 461 IDR_BROWSER_ACTION_BADGE_CENTER); |
366 | 462 |
367 canvas->sk_canvas()->drawBitmap(*gradient_left, rect.fLeft, rect.fTop); | 463 canvas->DrawImageInt(*gradient_left, rect.x(), rect.y()); |
368 canvas->TileImageInt(*gradient_center, | 464 canvas->TileImageInt(*gradient_center, |
369 SkScalarFloor(rect.fLeft) + gradient_left->width(), | 465 rect.x() + gradient_left->width(), |
370 SkScalarFloor(rect.fTop), | 466 rect.y(), |
371 SkScalarFloor(rect.width()) - gradient_left->width() - | 467 rect.width() - gradient_left->width() - gradient_right->width(), |
372 gradient_right->width(), | 468 rect.height()); |
373 SkScalarFloor(rect.height())); | 469 canvas->DrawImageInt(*gradient_right, |
374 canvas->sk_canvas()->drawBitmap(*gradient_right, | 470 rect.right() - gradient_right->width(), rect.y()); |
375 rect.fRight - SkIntToScalar(gradient_right->width()), rect.fTop); | |
376 | 471 |
377 // Finally, draw the text centered within the badge. We set a clip in case the | 472 // Finally, draw the text centered within the badge. We set a clip in case the |
378 // text was too large. | 473 // text was too large. |
379 rect.fLeft += kPadding; | 474 rect.Inset(kPadding, 0); |
380 rect.fRight -= kPadding; | 475 canvas->ClipRect(rect); |
381 canvas->sk_canvas()->clipRect(rect); | |
382 canvas->sk_canvas()->drawText(text.c_str(), text.size(), | 476 canvas->sk_canvas()->drawText(text.c_str(), text.size(), |
383 rect.fLeft + (rect.width() - text_width) / 2, | 477 rect.x() + (rect.width() - text_width) / 2, |
384 rect.fTop + kTextSize + kTopTextPadding, | 478 rect.y() + kTextSize + kTopTextPadding, |
385 *text_paint); | 479 *text_paint); |
386 canvas->Restore(); | 480 canvas->Restore(); |
387 } | 481 } |
388 | 482 |
389 ExtensionAction::IconAnimationWrapper* ExtensionAction::GetIconAnimationWrapper( | 483 ExtensionAction::IconAnimationWrapper* ExtensionAction::GetIconAnimationWrapper( |
390 int tab_id) const { | 484 int tab_id) const { |
391 std::map<int, base::WeakPtr<IconAnimationWrapper> >::iterator it = | 485 std::map<int, base::WeakPtr<IconAnimationWrapper> >::iterator it = |
392 icon_animation_.find(tab_id); | 486 icon_animation_.find(tab_id); |
393 if (it == icon_animation_.end()) | 487 if (it == icon_animation_.end()) |
394 return NULL; | 488 return NULL; |
(...skipping 14 matching lines...) Expand all Loading... | |
409 return NULL; | 503 return NULL; |
410 } | 504 } |
411 | 505 |
412 base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation( | 506 base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation( |
413 int tab_id) const { | 507 int tab_id) const { |
414 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); | 508 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); |
415 return wrapper ? wrapper->animation()->AsWeakPtr() | 509 return wrapper ? wrapper->animation()->AsWeakPtr() |
416 : base::WeakPtr<IconAnimation>(); | 510 : base::WeakPtr<IconAnimation>(); |
417 } | 511 } |
418 | 512 |
419 gfx::Image ExtensionAction::ApplyIconAnimation(int tab_id, | 513 gfx::ImageSkia ExtensionAction::ApplyIconAnimation( |
420 const gfx::Image& orig) const { | 514 int tab_id, |
421 IconAnimationWrapper* wrapper = GetIconAnimationWrapper(tab_id); | 515 const gfx::ImageSkia& icon) const { |
422 if (wrapper == NULL) | 516 IconAnimationWrapper* animation_wrapper = GetIconAnimationWrapper(tab_id); |
423 return orig; | 517 if (animation_wrapper == NULL) |
424 return gfx::Image(wrapper->animation()->Apply(*orig.ToSkBitmap())); | 518 return icon; |
519 | |
520 return gfx::ImageSkia( | |
521 new AnimatedIconImageSource(icon, animation_wrapper->animation()), | |
522 icon.size()); | |
425 } | 523 } |
426 | 524 |
427 void ExtensionAction::RunIconAnimation(int tab_id) { | 525 void ExtensionAction::RunIconAnimation(int tab_id) { |
428 IconAnimationWrapper* icon_animation = | 526 IconAnimationWrapper* icon_animation = |
429 new IconAnimationWrapper(); | 527 new IconAnimationWrapper(); |
430 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); | 528 icon_animation_[tab_id] = icon_animation->AsWeakPtr(); |
431 icon_animation->animation()->Start(); | 529 icon_animation->animation()->Start(); |
432 } | 530 } |
OLD | NEW |