blob: 0814268107e85faf8091cd87da05bbfb7653a634 [file] [log] [blame]
// Copyright 2017 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 "ash/login/ui/animated_rounded_image_view.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/skia_util.h"
namespace ash {
AnimatedRoundedImageView::AnimatedRoundedImageView(const gfx::Size& size,
int corner_radius)
: image_size_(size), corner_radius_(corner_radius) {}
AnimatedRoundedImageView::~AnimatedRoundedImageView() = default;
void AnimatedRoundedImageView::SetAnimation(const AnimationFrames& animation) {
frames_.clear();
frames_.reserve(animation.size());
for (AnimationFrame frame : animation) {
// Try to get the best image quality for the animation.
frame.image = gfx::ImageSkiaOperations::CreateResizedImage(
frame.image, skia::ImageOperations::RESIZE_BEST, image_size_);
DCHECK(frame.image.bitmap()->isImmutable());
frames_.emplace_back(frame);
}
StartOrStopAnimation();
}
void AnimatedRoundedImageView::SetImage(const gfx::ImageSkia& image) {
AnimationFrame frame;
frame.image = image;
SetAnimation({frame});
}
void AnimatedRoundedImageView::SetAnimationEnabled(bool enabled) {
should_animate_ = enabled;
StartOrStopAnimation();
}
gfx::Size AnimatedRoundedImageView::CalculatePreferredSize() const {
return gfx::Size(image_size_.width() + GetInsets().width(),
image_size_.height() + GetInsets().height());
}
void AnimatedRoundedImageView::OnPaint(gfx::Canvas* canvas) {
if (frames_.empty())
return;
View::OnPaint(canvas);
gfx::Rect image_bounds(GetContentsBounds());
image_bounds.ClampToCenteredSize(GetPreferredSize());
const SkScalar kRadius[8] = {
SkIntToScalar(corner_radius_), SkIntToScalar(corner_radius_),
SkIntToScalar(corner_radius_), SkIntToScalar(corner_radius_),
SkIntToScalar(corner_radius_), SkIntToScalar(corner_radius_),
SkIntToScalar(corner_radius_), SkIntToScalar(corner_radius_)};
SkPath path;
path.addRoundRect(gfx::RectToSkRect(image_bounds), kRadius);
cc::PaintFlags flags;
flags.setAntiAlias(true);
canvas->DrawImageInPath(frames_[active_frame_].image, image_bounds.x(),
image_bounds.y(), path, flags);
}
void AnimatedRoundedImageView::StartOrStopAnimation() {
// If animation is disabled or if there are less than 2 frames, show a static
// image.
if (!should_animate_ || frames_.size() < 2) {
active_frame_ = 0;
update_frame_timer_.Stop();
SchedulePaint();
return;
}
// Start animation.
active_frame_ = -1;
UpdateAnimationFrame();
}
void AnimatedRoundedImageView::UpdateAnimationFrame() {
DCHECK(!frames_.empty());
// Note: |active_frame_| may be invalid.
active_frame_ = (active_frame_ + 1) % frames_.size();
SchedulePaint();
// Schedule next frame update.
update_frame_timer_.Start(
FROM_HERE, frames_[active_frame_].duration,
base::BindRepeating(&AnimatedRoundedImageView::UpdateAnimationFrame,
base::Unretained(this)));
}
} // namespace ash