• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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/chromeos/login/rounded_rect_painter.h"
6 
7 #include "base/logging.h"
8 #include "chrome/browser/chromeos/login/helper.h"
9 #include "third_party/skia/include/effects/SkBlurMaskFilter.h"
10 #include "third_party/skia/include/effects/SkGradientShader.h"
11 #include "ui/gfx/canvas_skia.h"
12 #include "views/border.h"
13 #include "views/painter.h"
14 
15 namespace chromeos {
16 
17 namespace {
18 
19 const SkColor kScreenTopColor = SkColorSetRGB(250, 251, 251);
20 const SkColor kScreenBottomColor = SkColorSetRGB(204, 209, 212);
21 const SkColor kScreenShadowColor = SkColorSetARGB(64, 34, 54, 115);
22 const SkColor kShadowStrokeColor = 0;
23 const int kScreenShadow = 10;
24 
DrawRoundedRect(gfx::Canvas * canvas,int x,int y,int w,int h,int corner_radius,SkColor top_color,SkColor bottom_color,SkColor stroke_color)25 static void DrawRoundedRect(
26       gfx::Canvas* canvas,
27       int x, int y,
28       int w, int h,
29       int corner_radius,
30       SkColor top_color, SkColor bottom_color,
31       SkColor stroke_color) {
32   SkRect rect;
33   rect.set(
34       SkIntToScalar(x), SkIntToScalar(y),
35       SkIntToScalar(x + w), SkIntToScalar(y + h));
36   SkPath path;
37   path.addRoundRect(
38       rect, SkIntToScalar(corner_radius), SkIntToScalar(corner_radius));
39   SkPaint paint;
40   paint.setStyle(SkPaint::kFill_Style);
41   paint.setFlags(SkPaint::kAntiAlias_Flag);
42   if (top_color != bottom_color) {
43     SkPoint p[2];
44     p[0].set(SkIntToScalar(x), SkIntToScalar(y));
45     p[1].set(SkIntToScalar(x), SkIntToScalar(y + h));
46     SkColor colors[2] = { top_color, bottom_color };
47     SkShader* s =
48         SkGradientShader::CreateLinear(p, colors, NULL, 2,
49                                        SkShader::kClamp_TileMode, NULL);
50     paint.setShader(s);
51     // Need to unref shader, otherwise never deleted.
52     s->unref();
53   } else {
54     paint.setColor(top_color);
55   }
56   canvas->AsCanvasSkia()->drawPath(path, paint);
57 
58   if (stroke_color != 0) {
59     // Expand rect by 0.5px so resulting stroke will take the whole pixel.
60     rect.set(
61         SkIntToScalar(x) - SK_ScalarHalf,
62         SkIntToScalar(y) - SK_ScalarHalf,
63         SkIntToScalar(x + w) + SK_ScalarHalf,
64         SkIntToScalar(y + h) + SK_ScalarHalf);
65     paint.setShader(NULL);
66     paint.setStyle(SkPaint::kStroke_Style);
67     paint.setStrokeWidth(SkIntToScalar(SK_Scalar1));
68     paint.setColor(stroke_color);
69     canvas->AsCanvasSkia()->drawRoundRect(
70       rect,
71       SkIntToScalar(corner_radius), SkIntToScalar(corner_radius),
72       paint);
73   }
74 }
75 
DrawRoundedRectShadow(gfx::Canvas * canvas,int x,int y,int w,int h,int corner_radius,int shadow,SkColor color)76 static void DrawRoundedRectShadow(
77     gfx::Canvas* canvas,
78     int x, int y,
79     int w, int h,
80     int corner_radius,
81     int shadow,
82     SkColor color) {
83   SkPaint paint;
84   paint.setFlags(SkPaint::kAntiAlias_Flag);
85   paint.setStyle(SkPaint::kFill_Style);
86   paint.setColor(color);
87   SkMaskFilter* filter = SkBlurMaskFilter::Create(
88       shadow / 2, SkBlurMaskFilter::kNormal_BlurStyle);
89   paint.setMaskFilter(filter)->unref();
90   SkRect rect;
91   rect.set(
92       SkIntToScalar(x + shadow / 2), SkIntToScalar(y + shadow / 2),
93       SkIntToScalar(x + w - shadow / 2), SkIntToScalar(y + h - shadow / 2));
94   canvas->AsCanvasSkia()->drawRoundRect(
95       rect,
96       SkIntToScalar(corner_radius), SkIntToScalar(corner_radius),
97       paint);
98   paint.setMaskFilter(NULL);
99 }
100 
DrawRectWithBorder(int w,int h,const BorderDefinition * const border,gfx::Canvas * canvas)101 static void DrawRectWithBorder(int w,
102                                int h,
103                                const BorderDefinition* const border,
104                                gfx::Canvas* canvas) {
105   int padding = border->padding;
106   SkColor padding_color = border->padding_color;
107   int shadow = border->shadow;
108   SkColor shadow_color = border->shadow_color;
109   int corner_radius = border->corner_radius;
110   SkColor top_color = border->top_color;
111   SkColor bottom_color = border->bottom_color;
112   if (padding > 0) {
113     SkPaint paint;
114     paint.setColor(padding_color);
115     canvas->AsCanvasSkia()->drawRectCoords(
116         SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(w), SkIntToScalar(h),
117         paint);
118   }
119   if (border->shadow > 0) {
120     DrawRoundedRectShadow(
121         canvas,
122         padding, padding,
123         w - 2 * padding, h - 2 * padding,
124         corner_radius,
125         shadow, shadow_color);
126   }
127   DrawRoundedRect(
128         canvas,
129         padding + shadow,
130         padding + shadow - shadow / 3,
131         w - 2 * padding - 2 * shadow,
132         h - 2 * padding - 2 * shadow,
133         corner_radius,
134         top_color, bottom_color,
135         shadow ? kShadowStrokeColor : 0);
136 }
137 
138 // This Painter can be used to draw a background consistent cross all login
139 // screens. It draws a rect with padding, shadow and rounded corners.
140 class RoundedRectPainter : public views::Painter {
141  public:
RoundedRectPainter(const BorderDefinition * const border)142   explicit RoundedRectPainter(const BorderDefinition* const border)
143       : border_(border) {
144   }
145 
Paint(int w,int h,gfx::Canvas * canvas)146   virtual void Paint(int w, int h, gfx::Canvas* canvas) {
147     DrawRectWithBorder(w, h, border_, canvas);
148   }
149 
150  private:
151   const BorderDefinition* const border_;
152 
153   DISALLOW_COPY_AND_ASSIGN(RoundedRectPainter);
154 };
155 
156 // This border can be used to draw shadow and rounded corners across all
157 // login screens.
158 class RoundedRectBorder : public views::Border {
159  public:
RoundedRectBorder(const BorderDefinition * const border)160   explicit RoundedRectBorder(const BorderDefinition* const border)
161       : border_(border) {
162   }
163 
164   virtual void Paint(const views::View& view, gfx::Canvas* canvas) const;
165   virtual void GetInsets(gfx::Insets* insets) const;
166 
167  private:
168   const BorderDefinition* const border_;
169 
170   DISALLOW_COPY_AND_ASSIGN(RoundedRectBorder);
171 };
172 
Paint(const views::View & view,gfx::Canvas * canvas) const173 void RoundedRectBorder::Paint(const views::View& view,
174                               gfx::Canvas* canvas) const {
175   // Don't paint anything. RoundedRectBorder is used to provide insets only.
176 }
177 
GetInsets(gfx::Insets * insets) const178 void RoundedRectBorder::GetInsets(gfx::Insets* insets) const {
179   DCHECK(insets);
180   int shadow = border_->shadow;
181   int inset = border_->corner_radius / 2 + border_->padding + shadow;
182   insets->Set(inset - shadow / 3, inset, inset + shadow / 3, inset);
183 }
184 
185 // Simple solid round background.
186 class RoundedBackground : public views::Background {
187  public:
RoundedBackground(int corner_radius,int stroke_width,const SkColor & background_color,const SkColor & stroke_color)188   explicit RoundedBackground(int corner_radius,
189                              int stroke_width,
190                              const SkColor& background_color,
191                              const SkColor& stroke_color)
192       : corner_radius_(corner_radius),
193         stroke_width_(stroke_width),
194         stroke_color_(stroke_color) {
195     SetNativeControlColor(background_color);
196   }
197 
Paint(gfx::Canvas * canvas,views::View * view) const198   virtual void Paint(gfx::Canvas* canvas, views::View* view) const {
199     SkRect rect;
200     rect.iset(0, 0, view->width(), view->height());
201     SkPath path;
202     path.addRoundRect(rect,
203                       SkIntToScalar(corner_radius_),
204                       SkIntToScalar(corner_radius_));
205     // Draw interior.
206     SkPaint paint;
207     paint.setStyle(SkPaint::kFill_Style);
208     paint.setFlags(SkPaint::kAntiAlias_Flag);
209     paint.setColor(get_color());
210     canvas->AsCanvasSkia()->drawPath(path, paint);
211     // Redraw boundary region with correspoinding color.
212     paint.setStyle(SkPaint::kStroke_Style);
213     paint.setStrokeWidth(SkIntToScalar(stroke_width_));
214     paint.setColor(stroke_color_);
215     canvas->AsCanvasSkia()->drawPath(path, paint);
216   }
217 
218  private:
219   int corner_radius_;
220   int stroke_width_;
221   SkColor stroke_color_;
222 
223   DISALLOW_COPY_AND_ASSIGN(RoundedBackground);
224 };
225 
226 }  // namespace
227 
228 // static
229 const BorderDefinition BorderDefinition::kScreenBorder = {
230   0,
231   SK_ColorBLACK,
232   kScreenShadow,
233   kScreenShadowColor,
234   login::kScreenCornerRadius,
235   kScreenTopColor,
236   kScreenBottomColor
237 };
238 
239 const BorderDefinition BorderDefinition::kUserBorder = {
240   0,
241   SK_ColorBLACK,
242   0,
243   kScreenShadowColor,
244   login::kUserCornerRadius,
245   kScreenTopColor,
246   kScreenBottomColor
247 };
248 
CreateWizardPainter(const BorderDefinition * const border)249 views::Painter* CreateWizardPainter(const BorderDefinition* const border) {
250   return new RoundedRectPainter(border);
251 }
252 
CreateWizardBorder(const BorderDefinition * const border)253 views::Border* CreateWizardBorder(const BorderDefinition* const border) {
254   return new RoundedRectBorder(border);
255 }
256 
CreateRoundedBackground(int corner_radius,int stroke_width,SkColor background_color,SkColor stroke_color)257 views::Background* CreateRoundedBackground(int corner_radius,
258                                            int stroke_width,
259                                            SkColor background_color,
260                                            SkColor stroke_color) {
261   return new RoundedBackground(
262       corner_radius, stroke_width, background_color, stroke_color);
263 }
264 
265 }  // namespace chromeos
266