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