blob: 730931adc6ff7a1dd1083a91a7a6bfd798bb3335 [file] [log] [blame]
// Copyright 2015 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 "ui/views/animation/ink_drop_painted_layer_delegates.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/gfx/skia_util.h"
namespace views {
////////////////////////////////////////////////////////////////////////////////
//
// BasePaintedLayerDelegate
//
BasePaintedLayerDelegate::BasePaintedLayerDelegate(SkColor color)
: color_(color) {}
BasePaintedLayerDelegate::~BasePaintedLayerDelegate() = default;
gfx::Vector2dF BasePaintedLayerDelegate::GetCenteringOffset() const {
return gfx::RectF(GetPaintedBounds()).CenterPoint().OffsetFromOrigin();
}
void BasePaintedLayerDelegate::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
float new_device_scale_factor) {}
////////////////////////////////////////////////////////////////////////////////
//
// CircleLayerDelegate
//
CircleLayerDelegate::CircleLayerDelegate(SkColor color, int radius)
: BasePaintedLayerDelegate(color), radius_(radius) {}
CircleLayerDelegate::~CircleLayerDelegate() = default;
gfx::RectF CircleLayerDelegate::GetPaintedBounds() const {
const int diameter = radius_ * 2;
return gfx::RectF(0, 0, diameter, diameter);
}
void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
cc::PaintFlags flags;
flags.setColor(color());
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
ui::PaintRecorder recorder(context,
gfx::ToEnclosingRect(GetPaintedBounds()).size());
gfx::Canvas* canvas = recorder.canvas();
canvas->DrawCircle(GetPaintedBounds().CenterPoint(), radius_, flags);
}
////////////////////////////////////////////////////////////////////////////////
//
// RectangleLayerDelegate
//
RectangleLayerDelegate::RectangleLayerDelegate(SkColor color, gfx::SizeF size)
: BasePaintedLayerDelegate(color), size_(size) {}
RectangleLayerDelegate::~RectangleLayerDelegate() = default;
gfx::RectF RectangleLayerDelegate::GetPaintedBounds() const {
return gfx::RectF(size_);
}
void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
cc::PaintFlags flags;
flags.setColor(color());
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
ui::PaintRecorder recorder(context, gfx::ToCeiledSize(size_));
gfx::Canvas* canvas = recorder.canvas();
canvas->DrawRect(GetPaintedBounds(), flags);
}
////////////////////////////////////////////////////////////////////////////////
//
// RoundedRectangleLayerDelegate
//
RoundedRectangleLayerDelegate::RoundedRectangleLayerDelegate(
SkColor color,
const gfx::SizeF& size,
int corner_radius)
: BasePaintedLayerDelegate(color),
size_(size),
corner_radius_(corner_radius) {}
RoundedRectangleLayerDelegate::~RoundedRectangleLayerDelegate() = default;
gfx::RectF RoundedRectangleLayerDelegate::GetPaintedBounds() const {
return gfx::RectF(size_);
}
void RoundedRectangleLayerDelegate::OnPaintLayer(
const ui::PaintContext& context) {
cc::PaintFlags flags;
flags.setColor(color());
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
ui::PaintRecorder recorder(context, gfx::ToCeiledSize(size_));
const float dsf = recorder.canvas()->UndoDeviceScaleFactor();
gfx::RectF rect = GetPaintedBounds();
rect.Scale(dsf);
recorder.canvas()->DrawRoundRect(gfx::ToEnclosingRect(rect),
dsf * corner_radius_, flags);
}
////////////////////////////////////////////////////////////////////////////////
//
// BorderShadowLayerDelegate
//
BorderShadowLayerDelegate::BorderShadowLayerDelegate(
const std::vector<gfx::ShadowValue>& shadows,
const gfx::Rect& shadowed_area_bounds,
SkColor fill_color,
int corner_radius)
: BasePaintedLayerDelegate(gfx::kPlaceholderColor),
shadows_(shadows),
bounds_(shadowed_area_bounds),
fill_color_(fill_color),
corner_radius_(corner_radius) {}
BorderShadowLayerDelegate::~BorderShadowLayerDelegate() = default;
gfx::RectF BorderShadowLayerDelegate::GetPaintedBounds() const {
gfx::Rect total_rect(bounds_);
total_rect.Inset(gfx::ShadowValue::GetMargin(shadows_));
return gfx::RectF(total_rect);
}
gfx::Vector2dF BorderShadowLayerDelegate::GetCenteringOffset() const {
return gfx::RectF(bounds_).CenterPoint().OffsetFromOrigin();
}
void BorderShadowLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
cc::PaintFlags flags;
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setAntiAlias(true);
flags.setColor(fill_color_);
gfx::RectF rrect_bounds =
gfx::RectF(bounds_) - GetPaintedBounds().OffsetFromOrigin();
SkRRect r_rect = SkRRect::MakeRectXY(gfx::RectFToSkRect(rrect_bounds),
corner_radius_, corner_radius_);
// First the fill color.
ui::PaintRecorder recorder(context,
gfx::ToCeiledSize(GetPaintedBounds().size()));
recorder.canvas()->sk_canvas()->drawRRect(r_rect, flags);
// Now the shadow.
flags.setLooper(gfx::CreateShadowDrawLooper(shadows_));
recorder.canvas()->sk_canvas()->clipRRect(r_rect, SkClipOp::kDifference,
true);
recorder.canvas()->sk_canvas()->drawRRect(r_rect, flags);
}
} // namespace views