Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / profiles / profile_avatar_icon_util.cc
blob6a3e613c32db248382f69d8de46a1fd7377d683d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
7 #include "base/file_util.h"
8 #include "base/format_macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "grit/generated_resources.h"
15 #include "grit/theme_resources.h"
16 #include "third_party/skia/include/core/SkPaint.h"
17 #include "third_party/skia/include/core/SkPath.h"
18 #include "third_party/skia/include/core/SkScalar.h"
19 #include "third_party/skia/include/core/SkXfermode.h"
20 #include "ui/base/resource/resource_bundle.h"
21 #include "ui/gfx/canvas.h"
22 #include "ui/gfx/image/canvas_image_source.h"
23 #include "ui/gfx/image/image.h"
24 #include "ui/gfx/image/image_skia_operations.h"
26 // Helper methods for transforming and drawing avatar icons.
27 namespace {
29 // Determine what the scaled height of the avatar icon should be for a
30 // specified width, to preserve the aspect ratio.
31 int GetScaledAvatarHeightForWidth(int width, const gfx::ImageSkia& avatar) {
32 // Multiply the width by the inverted aspect ratio (height over
33 // width), and then add 0.5 to ensure the int truncation rounds nicely.
34 int scaled_height = width *
35 ((float) avatar.height() / (float) avatar.width()) + 0.5f;
36 return scaled_height;
39 // A CanvasImageSource that draws a sized and positioned avatar with an
40 // optional border independently of the scale factor.
41 class AvatarImageSource : public gfx::CanvasImageSource {
42 public:
43 enum AvatarPosition {
44 POSITION_CENTER,
45 POSITION_BOTTOM_CENTER,
48 enum AvatarBorder {
49 BORDER_NONE,
50 BORDER_NORMAL,
51 BORDER_ETCHED,
54 AvatarImageSource(gfx::ImageSkia avatar,
55 const gfx::Size& canvas_size,
56 int width,
57 AvatarPosition position,
58 AvatarBorder border);
59 virtual ~AvatarImageSource();
61 // CanvasImageSource override:
62 virtual void Draw(gfx::Canvas* canvas) OVERRIDE;
64 private:
65 gfx::ImageSkia avatar_;
66 const gfx::Size canvas_size_;
67 const int width_;
68 const int height_;
69 const AvatarPosition position_;
70 const AvatarBorder border_;
72 DISALLOW_COPY_AND_ASSIGN(AvatarImageSource);
75 AvatarImageSource::AvatarImageSource(gfx::ImageSkia avatar,
76 const gfx::Size& canvas_size,
77 int width,
78 AvatarPosition position,
79 AvatarBorder border)
80 : gfx::CanvasImageSource(canvas_size, false),
81 canvas_size_(canvas_size),
82 width_(width),
83 height_(GetScaledAvatarHeightForWidth(width, avatar)),
84 position_(position),
85 border_(border) {
86 avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
87 avatar, skia::ImageOperations::RESIZE_BEST,
88 gfx::Size(width_, height_));
91 AvatarImageSource::~AvatarImageSource() {
94 void AvatarImageSource::Draw(gfx::Canvas* canvas) {
95 // Center the avatar horizontally.
96 int x = (canvas_size_.width() - width_) / 2;
97 int y;
99 if (position_ == POSITION_CENTER) {
100 // Draw the avatar centered on the canvas.
101 y = (canvas_size_.height() - height_) / 2;
102 } else {
103 // Draw the avatar on the bottom center of the canvas, leaving 1px below.
104 y = canvas_size_.height() - height_ - 1;
107 canvas->DrawImageInt(avatar_, x, y);
109 // The border should be square.
110 int border_size = std::max(width_, height_);
111 // Reset the x and y for the square border.
112 x = (canvas_size_.width() - border_size) / 2;
113 y = (canvas_size_.height() - border_size) / 2;
115 if (border_ == BORDER_NORMAL) {
116 // Draw a gray border on the inside of the avatar.
117 SkColor border_color = SkColorSetARGB(83, 0, 0, 0);
119 // Offset the rectangle by a half pixel so the border is drawn within the
120 // appropriate pixels no matter the scale factor. Subtract 1 from the right
121 // and bottom sizes to specify the endpoints, yielding -0.5.
122 SkPath path;
123 path.addRect(SkFloatToScalar(x + 0.5f), // left
124 SkFloatToScalar(y + 0.5f), // top
125 SkFloatToScalar(x + border_size - 0.5f), // right
126 SkFloatToScalar(y + border_size - 0.5f)); // bottom
128 SkPaint paint;
129 paint.setColor(border_color);
130 paint.setStyle(SkPaint::kStroke_Style);
131 paint.setStrokeWidth(SkIntToScalar(1));
133 canvas->DrawPath(path, paint);
134 } else if (border_ == BORDER_ETCHED) {
135 // Give the avatar an etched look by drawing a highlight on the bottom and
136 // right edges.
137 SkColor shadow_color = SkColorSetARGB(83, 0, 0, 0);
138 SkColor highlight_color = SkColorSetARGB(96, 255, 255, 255);
140 SkPaint paint;
141 paint.setStyle(SkPaint::kStroke_Style);
142 paint.setStrokeWidth(SkIntToScalar(1));
144 SkPath path;
146 // Left and top shadows. To support higher scale factors than 1, position
147 // the orthogonal dimension of each line on the half-pixel to separate the
148 // pixel. For a vertical line, this means adding 0.5 to the x-value.
149 path.moveTo(SkFloatToScalar(x + 0.5f), SkIntToScalar(y + height_));
151 // Draw up to the top-left. Stop with the y-value at a half-pixel.
152 path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-height_ + 0.5f));
154 // Draw right to the top-right, stopping within the last pixel.
155 path.rLineTo(SkFloatToScalar(width_ - 0.5f), SkIntToScalar(0));
157 paint.setColor(shadow_color);
158 canvas->DrawPath(path, paint);
160 path.reset();
162 // Bottom and right highlights. Note that the shadows own the shared corner
163 // pixels, so reduce the sizes accordingly.
164 path.moveTo(SkIntToScalar(x + 1), SkFloatToScalar(y + height_ - 0.5f));
166 // Draw right to the bottom-right.
167 path.rLineTo(SkFloatToScalar(width_ - 1.5f), SkIntToScalar(0));
169 // Draw up to the top-right.
170 path.rLineTo(SkIntToScalar(0), SkFloatToScalar(-height_ + 1.5f));
172 paint.setColor(highlight_color);
173 canvas->DrawPath(path, paint);
177 } // namespace
179 namespace profiles {
181 struct IconResourceInfo {
182 int resource_id;
183 const char* filename;
186 const int kAvatarIconWidth = 38;
187 const int kAvatarIconHeight = 38;
188 const SkColor kAvatarTutorialBackgroundColor = SkColorSetRGB(0x42, 0x85, 0xf4);
189 const SkColor kAvatarTutorialContentTextColor = SkColorSetRGB(0xc6, 0xda, 0xfc);
190 const SkColor kAvatarBubbleAccountsBackgroundColor =
191 SkColorSetRGB(0xf3, 0xf3, 0xf3);
193 const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_";
194 const char kGAIAPictureFileName[] = "Google Profile Picture.png";
195 const char kHighResAvatarFolderName[] = "Avatars";
197 // This avatar does not exist on the server, the high res copy is in the build.
198 const char kNoHighResAvatar[] = "NothingToDownload";
200 // The size of the function-static kDefaultAvatarIconResources array below.
201 const size_t kDefaultAvatarIconsCount = 27;
203 // The first 8 icons are generic.
204 const size_t kGenericAvatarIconsCount = 8;
206 // The avatar used as a placeholder (grey silhouette).
207 const int kPlaceholderAvatarIcon = 26;
209 gfx::Image GetSizedAvatarIcon(const gfx::Image& image,
210 bool is_rectangle,
211 int width, int height) {
212 if (!is_rectangle && image.Height() <= height)
213 return image;
215 gfx::Size size(width, height);
217 // Source for a centered, sized icon. GAIA images get a border.
218 scoped_ptr<gfx::ImageSkiaSource> source(
219 new AvatarImageSource(
220 *image.ToImageSkia(),
221 size,
222 std::min(width, height),
223 AvatarImageSource::POSITION_CENTER,
224 AvatarImageSource::BORDER_NONE));
226 return gfx::Image(gfx::ImageSkia(source.release(), size));
229 gfx::Image GetAvatarIconForMenu(const gfx::Image& image,
230 bool is_rectangle) {
231 return GetSizedAvatarIcon(
232 image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight);
235 gfx::Image GetAvatarIconForWebUI(const gfx::Image& image,
236 bool is_rectangle) {
237 return GetSizedAvatarIcon(image, is_rectangle,
238 kAvatarIconWidth, kAvatarIconHeight);
241 gfx::Image GetAvatarIconForTitleBar(const gfx::Image& image,
242 bool is_gaia_image,
243 int dst_width,
244 int dst_height) {
245 // The image requires no border or resizing.
246 if (!is_gaia_image && image.Height() <= kAvatarIconHeight)
247 return image;
249 int size = std::min(std::min(kAvatarIconWidth, kAvatarIconHeight),
250 std::min(dst_width, dst_height));
251 gfx::Size dst_size(dst_width, dst_height);
253 // Source for a sized icon drawn at the bottom center of the canvas,
254 // with an etched border (for GAIA images).
255 scoped_ptr<gfx::ImageSkiaSource> source(
256 new AvatarImageSource(
257 *image.ToImageSkia(),
258 dst_size,
259 size,
260 AvatarImageSource::POSITION_BOTTOM_CENTER,
261 is_gaia_image ? AvatarImageSource::BORDER_ETCHED :
262 AvatarImageSource::BORDER_NONE));
264 return gfx::Image(gfx::ImageSkia(source.release(), dst_size));
267 // Helper methods for accessing, transforming and drawing avatar icons.
268 size_t GetDefaultAvatarIconCount() {
269 return kDefaultAvatarIconsCount;
272 size_t GetGenericAvatarIconCount() {
273 return kGenericAvatarIconsCount;
276 int GetPlaceholderAvatarIndex() {
277 return kPlaceholderAvatarIcon;
280 int GetPlaceholderAvatarIconResourceID() {
281 return IDR_PROFILE_AVATAR_26;
284 const IconResourceInfo* GetDefaultAvatarIconResourceInfo(size_t index) {
285 static const IconResourceInfo resource_info[kDefaultAvatarIconsCount] = {
286 { IDR_PROFILE_AVATAR_0, "avatar_generic.png"},
287 { IDR_PROFILE_AVATAR_1, "avatar_generic_aqua.png"},
288 { IDR_PROFILE_AVATAR_2, "avatar_generic_blue.png"},
289 { IDR_PROFILE_AVATAR_3, "avatar_generic_green.png"},
290 { IDR_PROFILE_AVATAR_4, "avatar_generic_orange.png"},
291 { IDR_PROFILE_AVATAR_5, "avatar_generic_purple.png"},
292 { IDR_PROFILE_AVATAR_6, "avatar_generic_red.png"},
293 { IDR_PROFILE_AVATAR_7, "avatar_generic_yellow.png"},
294 { IDR_PROFILE_AVATAR_8, "avatar_secret_agent.png"},
295 { IDR_PROFILE_AVATAR_9, "avatar_superhero.png"},
296 { IDR_PROFILE_AVATAR_10, "avatar_volley_ball.png"},
297 { IDR_PROFILE_AVATAR_11, "avatar_businessman.png"},
298 { IDR_PROFILE_AVATAR_12, "avatar_ninja.png"},
299 { IDR_PROFILE_AVATAR_13, "avatar_alien.png"},
300 { IDR_PROFILE_AVATAR_14, "avatar_smiley.png"},
301 { IDR_PROFILE_AVATAR_15, "avatar_flower.png"},
302 { IDR_PROFILE_AVATAR_16, "avatar_pizza.png"},
303 { IDR_PROFILE_AVATAR_17, "avatar_soccer.png"},
304 { IDR_PROFILE_AVATAR_18, "avatar_burger.png"},
305 { IDR_PROFILE_AVATAR_19, "avatar_cat.png"},
306 { IDR_PROFILE_AVATAR_20, "avatar_cupcake.png"},
307 { IDR_PROFILE_AVATAR_21, "avatar_dog.png"},
308 { IDR_PROFILE_AVATAR_22, "avatar_horse.png"},
309 { IDR_PROFILE_AVATAR_23, "avatar_margarita.png"},
310 { IDR_PROFILE_AVATAR_24, "avatar_note.png"},
311 { IDR_PROFILE_AVATAR_25, "avatar_sun_cloud.png"},
312 { IDR_PROFILE_AVATAR_26, kNoHighResAvatar},
314 return &resource_info[index];
317 int GetDefaultAvatarIconResourceIDAtIndex(size_t index) {
318 DCHECK(IsDefaultAvatarIconIndex(index));
319 return GetDefaultAvatarIconResourceInfo(index)->resource_id;
322 const char* GetDefaultAvatarIconFileNameAtIndex(size_t index) {
323 DCHECK(index < kDefaultAvatarIconsCount);
324 return GetDefaultAvatarIconResourceInfo(index)->filename;
327 const char* GetNoHighResAvatarFileName() {
328 return kNoHighResAvatar;
331 base::FilePath GetPathOfHighResAvatarAtIndex(size_t index) {
332 std::string file_name = GetDefaultAvatarIconResourceInfo(index)->filename;
333 base::FilePath user_data_dir;
334 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
335 return user_data_dir.AppendASCII(
336 kHighResAvatarFolderName).AppendASCII(file_name);
339 std::string GetDefaultAvatarIconUrl(size_t index) {
340 DCHECK(IsDefaultAvatarIconIndex(index));
341 return base::StringPrintf("%s%" PRIuS, kDefaultUrlPrefix, index);
344 bool IsDefaultAvatarIconIndex(size_t index) {
345 return index < kDefaultAvatarIconsCount;
348 bool IsDefaultAvatarIconUrl(const std::string& url, size_t* icon_index) {
349 DCHECK(icon_index);
350 if (url.find(kDefaultUrlPrefix) != 0)
351 return false;
353 int int_value = -1;
354 if (base::StringToInt(base::StringPiece(url.begin() +
355 strlen(kDefaultUrlPrefix),
356 url.end()),
357 &int_value)) {
358 if (int_value < 0 ||
359 int_value >= static_cast<int>(kDefaultAvatarIconsCount))
360 return false;
361 *icon_index = int_value;
362 return true;
365 return false;
368 } // namespace profiles