// Copyright (c) 2010 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/chromeos/login/rounded_rect_painter.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/canvas_skia.h"
#include "views/border.h"
#include "views/painter.h"
namespace chromeos {
namespace {
const SkColor kScreenTopColor = SkColorSetRGB(250, 251, 251);
const SkColor kScreenBottomColor = SkColorSetRGB(204, 209, 212);
const SkColor kScreenShadowColor = SkColorSetARGB(64, 34, 54, 115);
const SkColor kShadowStrokeColor = 0;
const int kScreenShadow = 10;
static void DrawRoundedRect(
gfx::Canvas* canvas,
int x, int y,
int w, int h,
int corner_radius,
SkColor top_color, SkColor bottom_color,
SkColor stroke_color) {
SkRect rect;
rect.set(
SkIntToScalar(x), SkIntToScalar(y),
SkIntToScalar(x + w), SkIntToScalar(y + h));
SkPath path;
path.addRoundRect(
rect, SkIntToScalar(corner_radius), SkIntToScalar(corner_radius));
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setFlags(SkPaint::kAntiAlias_Flag);
if (top_color != bottom_color) {
SkPoint p[2];
p[0].set(SkIntToScalar(x), SkIntToScalar(y));
p[1].set(SkIntToScalar(x), SkIntToScalar(y + h));
SkColor colors[2] = { top_color, bottom_color };
SkShader* s =
SkGradientShader::CreateLinear(p, colors, NULL, 2,
SkShader::kClamp_TileMode, NULL);
paint.setShader(s);
// Need to unref shader, otherwise never deleted.
s->unref();
} else {
paint.setColor(top_color);
}
canvas->AsCanvasSkia()->drawPath(path, paint);
if (stroke_color != 0) {
// Expand rect by 0.5px so resulting stroke will take the whole pixel.
rect.set(
SkIntToScalar(x) - SK_ScalarHalf,
SkIntToScalar(y) - SK_ScalarHalf,
SkIntToScalar(x + w) + SK_ScalarHalf,
SkIntToScalar(y + h) + SK_ScalarHalf);
paint.setShader(NULL);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(SK_Scalar1));
paint.setColor(stroke_color);
canvas->AsCanvasSkia()->drawRoundRect(
rect,
SkIntToScalar(corner_radius), SkIntToScalar(corner_radius),
paint);
}
}
static void DrawRoundedRectShadow(
gfx::Canvas* canvas,
int x, int y,
int w, int h,
int corner_radius,
int shadow,
SkColor color) {
SkPaint paint;
paint.setFlags(SkPaint::kAntiAlias_Flag);
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(color);
SkMaskFilter* filter = SkBlurMaskFilter::Create(
shadow / 2, SkBlurMaskFilter::kNormal_BlurStyle);
paint.setMaskFilter(filter)->unref();
SkRect rect;
rect.set(
SkIntToScalar(x + shadow / 2), SkIntToScalar(y + shadow / 2),
SkIntToScalar(x + w - shadow / 2), SkIntToScalar(y + h - shadow / 2));
canvas->AsCanvasSkia()->drawRoundRect(
rect,
SkIntToScalar(corner_radius), SkIntToScalar(corner_radius),
paint);
paint.setMaskFilter(NULL);
}
static void DrawRectWithBorder(int w,
int h,
const BorderDefinition* const border,
gfx::Canvas* canvas) {
int padding = border->padding;
SkColor padding_color = border->padding_color;
int shadow = border->shadow;
SkColor shadow_color = border->shadow_color;
int corner_radius = border->corner_radius;
SkColor top_color = border->top_color;
SkColor bottom_color = border->bottom_color;
if (padding > 0) {
SkPaint paint;
paint.setColor(padding_color);
canvas->AsCanvasSkia()->drawRectCoords(
SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(w), SkIntToScalar(h),
paint);
}
if (border->shadow > 0) {
DrawRoundedRectShadow(
canvas,
padding, padding,
w - 2 * padding, h - 2 * padding,
corner_radius,
shadow, shadow_color);
}
DrawRoundedRect(
canvas,
padding + shadow,
padding + shadow - shadow / 3,
w - 2 * padding - 2 * shadow,
h - 2 * padding - 2 * shadow,
corner_radius,
top_color, bottom_color,
shadow ? kShadowStrokeColor : 0);
}
// This Painter can be used to draw a background consistent cross all login
// screens. It draws a rect with padding, shadow and rounded corners.
class RoundedRectPainter : public views::Painter {
public:
explicit RoundedRectPainter(const BorderDefinition* const border)
: border_(border) {
}
virtual void Paint(int w, int h, gfx::Canvas* canvas) {
DrawRectWithBorder(w, h, border_, canvas);
}
private:
const BorderDefinition* const border_;
DISALLOW_COPY_AND_ASSIGN(RoundedRectPainter);
};
// This border can be used to draw shadow and rounded corners across all
// login screens.
class RoundedRectBorder : public views::Border {
public:
explicit RoundedRectBorder(const BorderDefinition* const border)
: border_(border) {
}
virtual void Paint(const views::View& view, gfx::Canvas* canvas) const;
virtual void GetInsets(gfx::Insets* insets) const;
private:
const BorderDefinition* const border_;
DISALLOW_COPY_AND_ASSIGN(RoundedRectBorder);
};
void RoundedRectBorder::Paint(const views::View& view,
gfx::Canvas* canvas) const {
// Don't paint anything. RoundedRectBorder is used to provide insets only.
}
void RoundedRectBorder::GetInsets(gfx::Insets* insets) const {
DCHECK(insets);
int shadow = border_->shadow;
int inset = border_->corner_radius / 2 + border_->padding + shadow;
insets->Set(inset - shadow / 3, inset, inset + shadow / 3, inset);
}
// Simple solid round background.
class RoundedBackground : public views::Background {
public:
explicit RoundedBackground(int corner_radius,
int stroke_width,
const SkColor& background_color,
const SkColor& stroke_color)
: corner_radius_(corner_radius),
stroke_width_(stroke_width),
stroke_color_(stroke_color) {
SetNativeControlColor(background_color);
}
virtual void Paint(gfx::Canvas* canvas, views::View* view) const {
SkRect rect;
rect.iset(0, 0, view->width(), view->height());
SkPath path;
path.addRoundRect(rect,
SkIntToScalar(corner_radius_),
SkIntToScalar(corner_radius_));
// Draw interior.
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setFlags(SkPaint::kAntiAlias_Flag);
paint.setColor(get_color());
canvas->AsCanvasSkia()->drawPath(path, paint);
// Redraw boundary region with correspoinding color.
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(SkIntToScalar(stroke_width_));
paint.setColor(stroke_color_);
canvas->AsCanvasSkia()->drawPath(path, paint);
}
private:
int corner_radius_;
int stroke_width_;
SkColor stroke_color_;
DISALLOW_COPY_AND_ASSIGN(RoundedBackground);
};
} // namespace
// static
const BorderDefinition BorderDefinition::kScreenBorder = {
0,
SK_ColorBLACK,
kScreenShadow,
kScreenShadowColor,
login::kScreenCornerRadius,
kScreenTopColor,
kScreenBottomColor
};
const BorderDefinition BorderDefinition::kUserBorder = {
0,
SK_ColorBLACK,
0,
kScreenShadowColor,
login::kUserCornerRadius,
kScreenTopColor,
kScreenBottomColor
};
views::Painter* CreateWizardPainter(const BorderDefinition* const border) {
return new RoundedRectPainter(border);
}
views::Border* CreateWizardBorder(const BorderDefinition* const border) {
return new RoundedRectBorder(border);
}
views::Background* CreateRoundedBackground(int corner_radius,
int stroke_width,
SkColor background_color,
SkColor stroke_color) {
return new RoundedBackground(
corner_radius, stroke_width, background_color, stroke_color);
}
} // namespace chromeos