blob: 0f8b1e5f85702661c30fe587eac555d6cd236082 [file] [log] [blame]
// 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