Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: chrome/browser/ui/views/avatar_menu_button.cc

Issue 8709001: Views: Custom drawing for GAIA avatar pictures (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/browser/ui/views/avatar_menu_button.h" 5 #include "chrome/browser/ui/views/avatar_menu_button.h"
6 6
7 #include "chrome/browser/profiles/profile_metrics.h" 7 #include "chrome/browser/profiles/profile_metrics.h"
8 #include "chrome/browser/profiles/profile_info_util.h"
8 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h" 10 #include "chrome/browser/ui/views/avatar_menu_bubble_view.h"
10 #include "chrome/browser/ui/views/frame/browser_view.h" 11 #include "chrome/browser/ui/views/frame/browser_view.h"
11 #include "chrome/browser/ui/views/window.h" 12 #include "chrome/browser/ui/views/window.h"
12 #include "ui/gfx/canvas_skia.h" 13 #include "ui/gfx/canvas_skia.h"
13 #include "ui/views/widget/widget.h" 14 #include "ui/views/widget/widget.h"
14 15
15 16
16 #if defined(OS_WIN) 17 #if defined(OS_WIN)
17 #include <shobjidl.h> 18 #include <shobjidl.h>
18 #include "base/win/scoped_comptr.h" 19 #include "base/win/scoped_comptr.h"
19 #include "base/win/windows_version.h" 20 #include "base/win/windows_version.h"
20 #include "skia/ext/image_operations.h" 21 #include "skia/ext/image_operations.h"
21 #include "ui/gfx/icon_util.h" 22 #include "ui/gfx/icon_util.h"
22 #endif 23 #endif
23 24
24 static inline int Round(double x) { 25 static inline int Round(double x) {
25 return static_cast<int>(x + 0.5); 26 return static_cast<int>(x + 0.5);
26 } 27 }
27 28
28 // The Windows 7 taskbar supports dynamic overlays and effects, we use this 29 // The Windows 7 taskbar supports dynamic overlays and effects, we use this
29 // to ovelay the avatar icon there. The overlay only applies if the taskbar 30 // to ovelay the avatar icon there. The overlay only applies if the taskbar
30 // is in "default large icon mode". This function is a best effort deal so 31 // is in "default large icon mode". This function is a best effort deal so
31 // we bail out silently at any error condition. 32 // we bail out silently at any error condition.
32 // See http://msdn.microsoft.com/en-us/library/dd391696(VS.85).aspx for 33 // See http://msdn.microsoft.com/en-us/library/dd391696(VS.85).aspx for
33 // more information. 34 // more information.
34 void DrawTaskBarDecoration(const Browser* browser, const SkBitmap* bitmap) { 35 void DrawTaskBarDecoration(const Browser* browser, const gfx::Image* image) {
35 #if defined(OS_WIN) && !defined(USE_AURA) 36 #if defined(OS_WIN) && !defined(USE_AURA)
36 if (base::win::GetVersion() < base::win::VERSION_WIN7) 37 if (base::win::GetVersion() < base::win::VERSION_WIN7)
37 return; 38 return;
38 BrowserWindow* bw = browser->window(); 39 BrowserWindow* bw = browser->window();
39 if (!bw) 40 if (!bw)
40 return; 41 return;
41 gfx::NativeWindow window = bw->GetNativeHandle(); 42 gfx::NativeWindow window = bw->GetNativeHandle();
42 if (!window) 43 if (!window)
43 return; 44 return;
44 45
45 base::win::ScopedComPtr<ITaskbarList3> taskbar; 46 base::win::ScopedComPtr<ITaskbarList3> taskbar;
46 HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL, 47 HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL,
47 CLSCTX_INPROC_SERVER); 48 CLSCTX_INPROC_SERVER);
48 if (FAILED(result) || FAILED(taskbar->HrInit())) 49 if (FAILED(result) || FAILED(taskbar->HrInit()))
49 return; 50 return;
50 HICON icon = NULL; 51 HICON icon = NULL;
51 if (bitmap) { 52 if (image) {
53 const SkBitmap* bitmap = image->ToSkBitmap();
52 const SkBitmap* source_bitmap = NULL; 54 const SkBitmap* source_bitmap = NULL;
53 SkBitmap squarer_bitmap; 55 SkBitmap squarer_bitmap;
54 if ((bitmap->width() == 38) && (bitmap->height() == 31)) { 56 if ((bitmap->width() == profiles::kAvatarIconWidth) &&
57 (bitmap->height() == profiles::kAvatarIconHeight)) {
55 // Shave a couple of columns so the bitmap is more square. So when 58 // Shave a couple of columns so the bitmap is more square. So when
56 // resized to a square aspect ratio it looks pretty. 59 // resized to a square aspect ratio it looks pretty.
57 bitmap->extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(2, 0, 34, 31)); 60 int x = 2;
Peter Kasting 2011/11/28 22:01:36 Nit: Wouldn't it make more sense to do something l
sail 2011/11/28 23:09:36 I think that's a good idea. I'm working on a separ
61 bitmap->extractSubset(&squarer_bitmap, SkIRect::MakeXYWH(x, 0,
62 profiles::kAvatarIconWidth - x * 2, profiles::kAvatarIconHeight));
58 source_bitmap = &squarer_bitmap; 63 source_bitmap = &squarer_bitmap;
59 } else { 64 } else {
60 // The bitmaps size has changed. Resize what we have. 65 // The bitmaps size has changed. Resize what we have.
61 source_bitmap = bitmap; 66 source_bitmap = bitmap;
62 } 67 }
63 // Since the target size is so small, we use our best resizer. Never pass 68 // Since the target size is so small, we use our best resizer. Never pass
64 // windows a different size because it will badly hammer it to 16x16. 69 // windows a different size because it will badly hammer it to 16x16.
65 SkBitmap sk_icon = skia::ImageOperations::Resize( 70 SkBitmap sk_icon = skia::ImageOperations::Resize(
66 *source_bitmap, 71 *source_bitmap,
67 skia::ImageOperations::RESIZE_LANCZOS3, 72 skia::ImageOperations::RESIZE_LANCZOS3,
68 16, 16); 73 16, 16);
69 icon = IconUtil::CreateHICONFromSkBitmap(sk_icon); 74 icon = IconUtil::CreateHICONFromSkBitmap(sk_icon);
70 if (!icon) 75 if (!icon)
71 return; 76 return;
72 } 77 }
73 taskbar->SetOverlayIcon(window, icon, L""); 78 taskbar->SetOverlayIcon(window, icon, L"");
74 if (icon) 79 if (icon)
75 DestroyIcon(icon); 80 DestroyIcon(icon);
76 #endif 81 #endif
77 } 82 }
78 83
79 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool has_menu) 84 AvatarMenuButton::AvatarMenuButton(Browser* browser, bool has_menu)
80 : MenuButton(NULL, string16(), this, false), 85 : MenuButton(NULL, string16(), this, false),
81 browser_(browser), 86 browser_(browser),
82 has_menu_(has_menu), 87 has_menu_(has_menu),
83 set_taskbar_decoration_(false) { 88 set_taskbar_decoration_(false),
89 is_gaia_picture_(false),
90 old_height_(0) {
84 // In RTL mode, the avatar icon should be looking the opposite direction. 91 // In RTL mode, the avatar icon should be looking the opposite direction.
85 EnableCanvasFlippingForRTLUI(true); 92 EnableCanvasFlippingForRTLUI(true);
86 } 93 }
87 94
88 AvatarMenuButton::~AvatarMenuButton() { 95 AvatarMenuButton::~AvatarMenuButton() {
89 // During destruction of the browser frame, we might not have a window 96 // During destruction of the browser frame, we might not have a window
90 // so the taskbar button will be removed by windows anyway. 97 // so the taskbar button will be removed by windows anyway.
91 if (browser_->IsAttemptingToCloseBrowser()) 98 if (browser_->IsAttemptingToCloseBrowser())
92 return; 99 return;
93 DrawTaskBarDecoration(browser_, NULL); 100 DrawTaskBarDecoration(browser_, NULL);
94 } 101 }
95 102
96 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) { 103 void AvatarMenuButton::OnPaint(gfx::Canvas* canvas) {
97 const SkBitmap& icon = GetImageToPaint(); 104 if (!icon_.get())
98 if (icon.isNull())
99 return; 105 return;
100 106
107 if (old_height_ != height() || button_icon_.isNull()) {
108 old_height_ = height();
109 button_icon_ = profiles::GetAvatarIconForTitleBar(
110 *icon_, is_gaia_picture_, width(), height());
111 }
112
101 // Scale the image to fit the width of the button. 113 // Scale the image to fit the width of the button.
102 int dst_width = std::min(icon.width(), width()); 114 int dst_width = std::min(button_icon_.width(), width());
103 // Truncate rather than rounding, so that for odd widths we put the extra 115 // Truncate rather than rounding, so that for odd widths we put the extra
104 // pixel on the left. 116 // pixel on the left.
105 int dst_x = (width() - dst_width) / 2; 117 int dst_x = (width() - dst_width) / 2;
106 118
107 // Scale the height and maintain aspect ratio. This means that the 119 // Scale the height and maintain aspect ratio. This means that the
108 // icon may not fit in the view. That's ok, we just vertically center it. 120 // icon may not fit in the view. That's ok, we just vertically center it.
109 float scale = 121 float scale =
110 static_cast<float>(dst_width) / static_cast<float>(icon.width()); 122 static_cast<float>(dst_width) / static_cast<float>(button_icon_.width());
111 // Round here so that we minimize the aspect ratio drift. 123 // Round here so that we minimize the aspect ratio drift.
112 int dst_height = Round(icon.height() * scale); 124 int dst_height = Round(button_icon_.height() * scale);
113 // Round rather than truncating, so that for odd heights we select an extra 125 // Round rather than truncating, so that for odd heights we select an extra
114 // pixel below the image center rather than above. This is because the 126 // pixel below the image center rather than above. This is because the
115 // incognito image has shadows at the top that make the apparent center below 127 // incognito image has shadows at the top that make the apparent center below
116 // the real center. 128 // the real center.
117 int dst_y = Round((height() - dst_height) / 2.0); 129 int dst_y = Round((height() - dst_height) / 2.0);
118 130 canvas->DrawBitmapInt(button_icon_, 0, 0, button_icon_.width(),
119 canvas->DrawBitmapInt(icon, 0, 0, icon.width(), icon.height(), 131 button_icon_.height(), dst_x, dst_y, dst_width, dst_height, false);
120 dst_x, dst_y, dst_width, dst_height, false);
121 132
122 if (set_taskbar_decoration_) { 133 if (set_taskbar_decoration_) {
123 // Drawing the taskbar decoration uses lanczos resizing so we really 134 // Drawing the taskbar decoration uses lanczos resizing so we really
124 // want to do it only once. 135 // want to do it only once.
125 DrawTaskBarDecoration(browser_, &icon); 136 DrawTaskBarDecoration(browser_, icon_.get());
126 set_taskbar_decoration_ = false; 137 set_taskbar_decoration_ = false;
127 } 138 }
128 } 139 }
129 140
130 bool AvatarMenuButton::HitTest(const gfx::Point& point) const { 141 bool AvatarMenuButton::HitTest(const gfx::Point& point) const {
131 if (!has_menu_) 142 if (!has_menu_)
132 return false; 143 return false;
133 return views::MenuButton::HitTest(point); 144 return views::MenuButton::HitTest(point);
134 } 145 }
135 146
136 // If the icon changes, we need to set the taskbar decoration again. 147 void AvatarMenuButton::SetIcon(const gfx::Image& icon, bool is_gaia_picture) {
137 void AvatarMenuButton::SetIcon(const SkBitmap& icon) { 148 icon_.reset(new gfx::Image(icon));
Peter Kasting 2011/11/28 22:01:36 Nit: Why use a scoped_ptr here? Why not just use
sail 2011/11/28 23:09:36 gfx::Image doesn't have a default constructor so i
138 views::MenuButton::SetIcon(icon); 149 button_icon_ = SkBitmap();
150 is_gaia_picture_ = is_gaia_picture;
151 // If the icon changes, we need to set the taskbar decoration again.
139 set_taskbar_decoration_ = true; 152 set_taskbar_decoration_ = true;
140 } 153 }
141 154
142 // views::ViewMenuDelegate implementation 155 // views::ViewMenuDelegate implementation
143 void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) { 156 void AvatarMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
144 ShowAvatarBubble(); 157 ShowAvatarBubble();
145 } 158 }
146 159
147 void AvatarMenuButton::ShowAvatarBubble() { 160 void AvatarMenuButton::ShowAvatarBubble() {
148 if (!has_menu_) 161 if (!has_menu_)
149 return; 162 return;
150 163
151 gfx::Point origin; 164 gfx::Point origin;
152 views::View::ConvertPointToScreen(this, &origin); 165 views::View::ConvertPointToScreen(this, &origin);
153 gfx::Rect bounds(origin, size()); 166 gfx::Rect bounds(origin, size());
154 167
155 AvatarMenuBubbleView* bubble = new AvatarMenuBubbleView(this, 168 AvatarMenuBubbleView* bubble = new AvatarMenuBubbleView(this,
156 views::BubbleBorder::TOP_LEFT, bounds, browser_); 169 views::BubbleBorder::TOP_LEFT, bounds, browser_);
157 browser::CreateViewsBubble(bubble); 170 browser::CreateViewsBubble(bubble);
158 bubble->Show(); 171 bubble->Show();
159 172
160 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::ICON_AVATAR_BUBBLE); 173 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::ICON_AVATAR_BUBBLE);
161 } 174 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698