1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/profiles/profile_info_util.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia_operations.h"
namespace profiles {
const int kAvatarIconWidth = 38;
const int kAvatarIconHeight = 31;
const int kAvatarIconPadding = 2;
namespace internal {
// A CanvasImageSource that draws a sized and positioned avatar with an
// optional border independently of the scale factor.
class AvatarImageSource : public gfx::CanvasImageSource {
public:
enum AvatarPosition {
POSITION_CENTER,
POSITION_BOTTOM_CENTER,
};
enum AvatarBorder {
BORDER_NONE,
BORDER_NORMAL,
BORDER_ETCHED,
};
AvatarImageSource(gfx::ImageSkia avatar,
const gfx::Size& canvas_size,
int size,
AvatarPosition position,
AvatarBorder border);
virtual ~AvatarImageSource();
// CanvasImageSource override:
virtual void Draw(gfx::Canvas* canvas) OVERRIDE;
private:
gfx::ImageSkia avatar_;
const gfx::Size canvas_size_;
const int size_;
const AvatarPosition position_;
const AvatarBorder border_;
DISALLOW_COPY_AND_ASSIGN(AvatarImageSource);
};
AvatarImageSource::AvatarImageSource(gfx::ImageSkia avatar,
const gfx::Size& canvas_size,
int size,
AvatarPosition position,
AvatarBorder border)
: gfx::CanvasImageSource(canvas_size, false),
canvas_size_(canvas_size),
size_(size - kAvatarIconPadding),
position_(position),
border_(border) {
// Resize the avatar to the desired square size.
avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
avatar, skia::ImageOperations::RESIZE_BEST, gfx::Size(size_, size_));
}
AvatarImageSource::~AvatarImageSource() {
}
void AvatarImageSource::Draw(gfx::Canvas* canvas) {
// Center the avatar horizontally.
int x = (canvas_size_.width() - size_) / 2;
int y;
if (position_ == POSITION_CENTER) {
// Draw the avatar centered on the canvas.
y = (canvas_size_.height() - size_) / 2;
} else {
// Draw the avatar on the bottom center of the canvas, leaving 1px below.
y = canvas_size_.height() - size_ - 1;
}
canvas->DrawImageInt(avatar_, x, y);
if (border_ == BORDER_NORMAL) {
// Draw a gray border on the inside of the avatar.
SkColor border_color = SkColorSetARGB(83, 0, 0, 0);
// Offset the rectangle by a half pixel so the border is drawn within the
// appropriate pixels no matter the scale factor. Subtract 1 from the right
// and bottom sizes to specify the endpoints, yielding -0.5.
SkPath path;
path.addRect(SkFloatToScalar(x + 0.5f), // left
SkFloatToScalar(y + 0.5f), // top
SkFloatToScalar(x + size_ - 0.5f), // right
SkFloatToScalar(y + size_ - 0.5f)); // bottom
SkPaint paint;
paint.setColor(border_color);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(1));
canvas->DrawPath(path, paint);
} else if (border_ == BORDER_ETCHED) {
// Give the avatar an etched look by drawing a highlight on the bottom and
// right edges.
SkColor shadow_color = SkColorSetARGB(83, 0, 0, 0);
SkColor highlight_color = SkColorSetARGB(96, 255, 255, 255);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(1));
SkPath path;
// Left and top shadows. To support higher scale factors than 1, position
// the orthogonal dimension of each line on the half-pixel to separate the
// pixel. For a vertical line, this means adding 0.5 to the x-value.
path.moveTo(SkFloatToScalar(x + 0.5f), SkIntToScalar(y + size_));
// Draw up to the top-left. Stop with the y-value at a half-pixel.
path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-size_ + 0.5f));
// Draw right to the top-right, stopping within the last pixel.
path.rLineTo(SkFloatToScalar(size_ - 0.5f), SkIntToScalar(0));
paint.setColor(shadow_color);
canvas->DrawPath(path, paint);
path.reset();
// Bottom and right highlights. Note that the shadows own the shared corner
// pixels, so reduce the sizes accordingly.
path.moveTo(SkIntToScalar(x + 1), SkFloatToScalar(y + size_ - 0.5f));
// Draw right to the bottom-right.
path.rLineTo(SkFloatToScalar(size_ - 1.5f), SkIntToScalar(0));
// Draw up to the top-right.
path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-size_ + 1.5f));
paint.setColor(highlight_color);
canvas->DrawPath(path, paint);
}
}
} // namespace internal
gfx::Image GetSizedAvatarIconWithBorder(const gfx::Image& image,
bool is_rectangle,
int width, int height) {
if (!is_rectangle)
return image;
gfx::Size size(width, height);
// Source for a centered, sized icon with a border.
scoped_ptr<gfx::ImageSkiaSource> source(
new internal::AvatarImageSource(
*image.ToImageSkia(),
size,
std::min(width, height),
internal::AvatarImageSource::POSITION_CENTER,
internal::AvatarImageSource::BORDER_NORMAL));
return gfx::Image(gfx::ImageSkia(source.release(), size));
}
gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
bool is_rectangle) {
return GetSizedAvatarIconWithBorder(
image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight);
}
gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
bool is_rectangle) {
if (!is_rectangle)
return image;
gfx::Size size(kAvatarIconWidth, kAvatarIconHeight);
// Source for a centered, sized icon.
scoped_ptr<gfx::ImageSkiaSource> source(
new internal::AvatarImageSource(
*image.ToImageSkia(),
size,
std::min(kAvatarIconWidth, kAvatarIconHeight),
internal::AvatarImageSource::POSITION_CENTER,
internal::AvatarImageSource::BORDER_NONE));
return gfx::Image(gfx::ImageSkia(source.release(), size));
}
gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
bool is_rectangle,
int dst_width,
int dst_height) {
if (!is_rectangle)
return image;
int size = std::min(std::min(kAvatarIconWidth, kAvatarIconHeight),
std::min(dst_width, dst_height));
gfx::Size dst_size(dst_width, dst_height);
// Source for a sized icon drawn at the bottom center of the canvas,
// with an etched border.
scoped_ptr<gfx::ImageSkiaSource> source(
new internal::AvatarImageSource(
*image.ToImageSkia(),
dst_size,
size,
internal::AvatarImageSource::POSITION_BOTTOM_CENTER,
internal::AvatarImageSource::BORDER_ETCHED));
return gfx::Image(gfx::ImageSkia(source.release(), dst_size));
}
} // namespace profiles
|