// 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 "ui/compositor/layer_animation_element.h" #include #include "base/compiler_specific.h" #include "base/strings/stringprintf.h" #include "cc/animation/animation_id_provider.h" #include "cc/animation/keyframe_model.h" #include "ui/compositor/float_animation_curve_adapter.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_delegate.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/transform_animation_curve_adapter.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/interpolated_transform.h" namespace ui { namespace { // Pause ----------------------------------------------------------------------- class Pause : public LayerAnimationElement { public: Pause(AnimatableProperties properties, base::TimeDelta duration) : LayerAnimationElement(properties, duration) { } Pause(const Pause&) = delete; Pause& operator=(const Pause&) = delete; ~Pause() override {} private: std::string DebugName() const override { return "Pause"; } void OnStart(LayerAnimationDelegate* delegate) override {} bool OnProgress(double t, LayerAnimationDelegate* delegate) override { return false; } void OnGetTarget(TargetValue* target) const override {} void OnAbort(LayerAnimationDelegate* delegate) override {} }; // InterpolatedTransformTransition --------------------------------------------- class InterpolatedTransformTransition : public LayerAnimationElement { public: InterpolatedTransformTransition( std::unique_ptr interpolated_transform, base::TimeDelta duration) : LayerAnimationElement(TRANSFORM, duration), interpolated_transform_(std::move(interpolated_transform)) {} InterpolatedTransformTransition(const InterpolatedTransformTransition&) = delete; InterpolatedTransformTransition& operator=( const InterpolatedTransformTransition&) = delete; ~InterpolatedTransformTransition() override {} protected: std::string DebugName() const override { return "InterpolatedTransformTransition"; } void OnStart(LayerAnimationDelegate* delegate) override {} bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetTransformFromAnimation( interpolated_transform_->Interpolate(static_cast(t)), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->transform = interpolated_transform_->Interpolate(1.0f); } void OnAbort(LayerAnimationDelegate* delegate) override {} private: std::unique_ptr interpolated_transform_; }; // BoundsTransition ------------------------------------------------------------ class BoundsTransition : public LayerAnimationElement { public: BoundsTransition(const gfx::Rect& target, base::TimeDelta duration) : LayerAnimationElement(BOUNDS, duration), target_(target) { } BoundsTransition(const BoundsTransition&) = delete; BoundsTransition& operator=(const BoundsTransition&) = delete; ~BoundsTransition() override {} protected: std::string DebugName() const override { return "BoundsTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetBoundsForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetBoundsFromAnimation( gfx::Tween::RectValueBetween(t, start_, target_), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->bounds = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: gfx::Rect start_; const gfx::Rect target_; }; // VisibilityTransition -------------------------------------------------------- class VisibilityTransition : public LayerAnimationElement { public: VisibilityTransition(bool target, base::TimeDelta duration) : LayerAnimationElement(VISIBILITY, duration), start_(false), target_(target) { } VisibilityTransition(const VisibilityTransition&) = delete; VisibilityTransition& operator=(const VisibilityTransition&) = delete; ~VisibilityTransition() override {} protected: std::string DebugName() const override { return "VisibilityTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetVisibilityForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetVisibilityFromAnimation(t == 1.0 ? target_ : start_, PropertyChangeReason::FROM_ANIMATION); return t == 1.0; } void OnGetTarget(TargetValue* target) const override { target->visibility = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: bool start_; const bool target_; }; // BrightnessTransition -------------------------------------------------------- class BrightnessTransition : public LayerAnimationElement { public: BrightnessTransition(float target, base::TimeDelta duration) : LayerAnimationElement(BRIGHTNESS, duration), start_(0.0f), target_(target) { } BrightnessTransition(const BrightnessTransition&) = delete; BrightnessTransition& operator=(const BrightnessTransition&) = delete; ~BrightnessTransition() override {} protected: std::string DebugName() const override { return "BrightnessTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetBrightnessForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetBrightnessFromAnimation( gfx::Tween::FloatValueBetween(t, start_, target_), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->brightness = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: float start_; const float target_; }; // GrayscaleTransition --------------------------------------------------------- class GrayscaleTransition : public LayerAnimationElement { public: GrayscaleTransition(float target, base::TimeDelta duration) : LayerAnimationElement(GRAYSCALE, duration), start_(0.0f), target_(target) { } GrayscaleTransition(const GrayscaleTransition&) = delete; GrayscaleTransition& operator=(const GrayscaleTransition&) = delete; ~GrayscaleTransition() override {} protected: std::string DebugName() const override { return "GrayscaleTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetGrayscaleForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetGrayscaleFromAnimation( gfx::Tween::FloatValueBetween(t, start_, target_), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->grayscale = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: float start_; const float target_; }; // ColorTransition ------------------------------------------------------------- class ColorTransition : public LayerAnimationElement { public: ColorTransition(SkColor target, base::TimeDelta duration) : LayerAnimationElement(COLOR, duration), start_(SK_ColorBLACK), target_(target) { } ColorTransition(const ColorTransition&) = delete; ColorTransition& operator=(const ColorTransition&) = delete; ~ColorTransition() override {} protected: std::string DebugName() const override { return "ColorTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetColorForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetColorFromAnimation( gfx::Tween::ColorValueBetween(t, start_, target_), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->color = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: SkColor start_; const SkColor target_; }; // ClipRectTransition ---------------------------------------------------------- class ClipRectTransition : public LayerAnimationElement { public: ClipRectTransition(const gfx::Rect& target, base::TimeDelta duration) : LayerAnimationElement(CLIP, duration), target_(target) {} ClipRectTransition(const ClipRectTransition&) = delete; ClipRectTransition& operator=(const ClipRectTransition&) = delete; ~ClipRectTransition() override {} protected: std::string DebugName() const override { return "ClipRectTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetClipRectForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetClipRectFromAnimation( gfx::Tween::RectValueBetween(t, start_, target_), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->clip_rect = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: gfx::Rect start_; const gfx::Rect target_; }; // RoundedCornersTransition ---------------------------------------------------- class RoundedCornersTransition : public LayerAnimationElement { public: RoundedCornersTransition(const gfx::RoundedCornersF& target, base::TimeDelta duration) : LayerAnimationElement(ROUNDED_CORNERS, duration), target_(target) {} RoundedCornersTransition(const RoundedCornersTransition&) = delete; RoundedCornersTransition& operator=(const RoundedCornersTransition&) = delete; ~RoundedCornersTransition() override = default; protected: std::string DebugName() const override { return "RoundedCornersTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetRoundedCornersForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { delegate->SetRoundedCornersFromAnimation( gfx::RoundedCornersF( gfx::Tween::FloatValueBetween(t, start_.upper_left(), target_.upper_left()), gfx::Tween::FloatValueBetween(t, start_.upper_right(), target_.upper_right()), gfx::Tween::FloatValueBetween(t, start_.lower_right(), target_.lower_right()), gfx::Tween::FloatValueBetween(t, start_.lower_left(), target_.lower_left())), PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->rounded_corners = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: gfx::RoundedCornersF start_; gfx::RoundedCornersF target_; }; // GradientMaskTransition ---------------------------------------------------- class GradientMaskTransition : public LayerAnimationElement { public: GradientMaskTransition(const gfx::LinearGradient& target, base::TimeDelta duration) : LayerAnimationElement(GRADIENT_MASK, duration), target_(target) {} GradientMaskTransition(const GradientMaskTransition&) = delete; GradientMaskTransition& operator=(const GradientMaskTransition&) = delete; ~GradientMaskTransition() override = default; protected: std::string DebugName() const override { return "GradientMaskTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetGradientMaskForAnimation(); } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { auto gradient_mask = gfx::LinearGradient( gfx::Tween::FloatValueBetween(t, start_.angle(), target_.angle())); DCHECK_EQ(start_.step_count(), target_.step_count()); for (auto i = 0; i < static_cast(start_.step_count()); ++i) { gradient_mask.AddStep( gfx::Tween::FloatValueBetween(t, start_.steps()[i].fraction, target_.steps()[i].fraction), gfx::Tween::IntValueBetween(t, start_.steps()[i].alpha, target_.steps()[i].alpha)); } delegate->SetGradientMaskFromAnimation( gradient_mask, PropertyChangeReason::FROM_ANIMATION); return true; } void OnGetTarget(TargetValue* target) const override { target->gradient_mask = target_; } void OnAbort(LayerAnimationDelegate* delegate) override {} private: gfx::LinearGradient start_; const gfx::LinearGradient target_; }; // ThreadedLayerAnimationElement ----------------------------------------------- class ThreadedLayerAnimationElement : public LayerAnimationElement { public: ThreadedLayerAnimationElement(AnimatableProperties properties, base::TimeDelta duration) : LayerAnimationElement(properties, duration) { } ThreadedLayerAnimationElement(const ThreadedLayerAnimationElement&) = delete; ThreadedLayerAnimationElement& operator=( const ThreadedLayerAnimationElement&) = delete; ~ThreadedLayerAnimationElement() override {} bool IsThreaded(LayerAnimationDelegate* delegate) const override { return !duration().is_zero(); } protected: explicit ThreadedLayerAnimationElement(const LayerAnimationElement& element) : LayerAnimationElement(element) { } std::string DebugName() const override { return "ThreadedLayerAnimationElement"; } bool OnProgress(double t, LayerAnimationDelegate* delegate) override { if (t < 1.0) return false; if (Started() && IsThreaded(delegate)) { LayerThreadedAnimationDelegate* threaded = delegate->GetThreadedAnimationDelegate(); DCHECK(threaded); threaded->RemoveThreadedAnimation(keyframe_model_id()); } OnEnd(delegate); return true; } void OnAbort(LayerAnimationDelegate* delegate) override { if (delegate && Started() && IsThreaded(delegate)) { LayerThreadedAnimationDelegate* threaded = delegate->GetThreadedAnimationDelegate(); DCHECK(threaded); threaded->RemoveThreadedAnimation(keyframe_model_id()); } } void RequestEffectiveStart(LayerAnimationDelegate* delegate) override { DCHECK(animation_group_id()); if (!IsThreaded(delegate)) { set_effective_start_time(requested_start_time()); return; } set_effective_start_time(base::TimeTicks()); std::unique_ptr keyframe_model = CreateCCKeyframeModel(); keyframe_model->set_needs_synchronized_start_time(true); LayerThreadedAnimationDelegate* threaded = delegate->GetThreadedAnimationDelegate(); DCHECK(threaded); threaded->AddThreadedAnimation(std::move(keyframe_model)); } virtual void OnEnd(LayerAnimationDelegate* delegate) = 0; virtual std::unique_ptr CreateCCKeyframeModel() = 0; }; // ThreadedOpacityTransition --------------------------------------------------- class ThreadedOpacityTransition : public ThreadedLayerAnimationElement { public: ThreadedOpacityTransition(float target, base::TimeDelta duration) : ThreadedLayerAnimationElement(OPACITY, duration), start_(0.0f), target_(target) { } ThreadedOpacityTransition(const ThreadedOpacityTransition&) = delete; ThreadedOpacityTransition& operator=(const ThreadedOpacityTransition&) = delete; ~ThreadedOpacityTransition() override {} protected: std::string DebugName() const override { return "ThreadedOpacityTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetOpacityForAnimation(); delegate->SetOpacityFromAnimation(delegate->GetOpacityForAnimation(), PropertyChangeReason::FROM_ANIMATION); } void OnAbort(LayerAnimationDelegate* delegate) override { if (delegate && Started()) { ThreadedLayerAnimationElement::OnAbort(delegate); delegate->SetOpacityFromAnimation( gfx::Tween::FloatValueBetween( gfx::Tween::CalculateValue(tween_type(), last_progressed_fraction()), start_, target_), PropertyChangeReason::FROM_ANIMATION); } } void OnEnd(LayerAnimationDelegate* delegate) override { delegate->SetOpacityFromAnimation(target_, PropertyChangeReason::FROM_ANIMATION); } std::unique_ptr CreateCCKeyframeModel() override { // Ensures that we don't remove and add a model with the same id in a single // frame. UpdateKeyframeModelId(); std::unique_ptr animation_curve( new FloatAnimationCurveAdapter(tween_type(), start_, target_, duration())); std::unique_ptr keyframe_model(cc::KeyframeModel::Create( std::move(animation_curve), keyframe_model_id(), animation_group_id(), cc::KeyframeModel::TargetPropertyId(cc::TargetProperty::OPACITY))); return keyframe_model; } void OnGetTarget(TargetValue* target) const override { target->opacity = target_; } bool IsThreaded(LayerAnimationDelegate* delegate) const override { // If the start and target values are the same, we do not create cc // animation so that we will not create render pass in this case. // http://crbug.com/764575. if (duration().is_zero()) return false; if (Started()) return start_ != target_; return delegate->GetOpacityForAnimation() != target_; } private: float start_; const float target_; }; // ThreadedTransformTransition ------------------------------------------------- class ThreadedTransformTransition : public ThreadedLayerAnimationElement { public: ThreadedTransformTransition(const gfx::Transform& target, base::TimeDelta duration) : ThreadedLayerAnimationElement(TRANSFORM, duration), target_(target) { } ThreadedTransformTransition(const ThreadedTransformTransition&) = delete; ThreadedTransformTransition& operator=(const ThreadedTransformTransition&) = delete; ~ThreadedTransformTransition() override {} protected: std::string DebugName() const override { return "ThreadedTransformTransition"; } void OnStart(LayerAnimationDelegate* delegate) override { start_ = delegate->GetTransformForAnimation(); delegate->SetTransformFromAnimation(delegate->GetTransformForAnimation(), PropertyChangeReason::FROM_ANIMATION); } void OnAbort(LayerAnimationDelegate* delegate) override { if (delegate && Started()) { ThreadedLayerAnimationElement::OnAbort(delegate); delegate->SetTransformFromAnimation( gfx::Tween::TransformValueBetween( gfx::Tween::CalculateValue(tween_type(), last_progressed_fraction()), start_, target_), PropertyChangeReason::FROM_ANIMATION); } } void OnEnd(LayerAnimationDelegate* delegate) override { delegate->SetTransformFromAnimation(target_, PropertyChangeReason::FROM_ANIMATION); } std::unique_ptr CreateCCKeyframeModel() override { // Ensures that we don't remove and add a model with the same id in a single // frame. UpdateKeyframeModelId(); std::unique_ptr animation_curve( new TransformAnimationCurveAdapter(tween_type(), start_, target_, duration())); std::unique_ptr keyframe_model(cc::KeyframeModel::Create( std::move(animation_curve), keyframe_model_id(), animation_group_id(), cc::KeyframeModel::TargetPropertyId(cc::TargetProperty::TRANSFORM))); return keyframe_model; } void OnGetTarget(TargetValue* target) const override { target->transform = target_; } private: gfx::Transform start_; const gfx::Transform target_; }; } // namespace // LayerAnimationElement::TargetValue ------------------------------------------ LayerAnimationElement::TargetValue::TargetValue() : opacity(0.0f), visibility(false), brightness(0.0f), grayscale(0.0f), color(SK_ColorBLACK) { } LayerAnimationElement::TargetValue::TargetValue( const LayerAnimationDelegate* delegate) : bounds(delegate ? delegate->GetBoundsForAnimation() : gfx::Rect()), transform(delegate ? delegate->GetTransformForAnimation() : gfx::Transform()), opacity(delegate ? delegate->GetOpacityForAnimation() : 0.0f), visibility(delegate ? delegate->GetVisibilityForAnimation() : false), brightness(delegate ? delegate->GetBrightnessForAnimation() : 0.0f), grayscale(delegate ? delegate->GetGrayscaleForAnimation() : 0.0f), color(delegate ? delegate->GetColorForAnimation() : SK_ColorTRANSPARENT), clip_rect(delegate ? delegate->GetClipRectForAnimation() : gfx::Rect()), rounded_corners(delegate ? delegate->GetRoundedCornersForAnimation() : gfx::RoundedCornersF()), gradient_mask(delegate ? delegate->GetGradientMaskForAnimation() : gfx::LinearGradient::GetEmpty()) {} // LayerAnimationElement ------------------------------------------------------- LayerAnimationElement::LayerAnimationElement(AnimatableProperties properties, base::TimeDelta duration) : first_frame_(true), properties_(properties), duration_(GetEffectiveDuration(duration)), tween_type_(gfx::Tween::LINEAR), keyframe_model_id_(cc::AnimationIdProvider::NextKeyframeModelId()), animation_group_id_(0), last_progressed_fraction_(0.0) {} LayerAnimationElement::LayerAnimationElement( const LayerAnimationElement& element) : first_frame_(element.first_frame_), properties_(element.properties_), duration_(element.duration_), tween_type_(element.tween_type_), keyframe_model_id_(cc::AnimationIdProvider::NextKeyframeModelId()), animation_group_id_(element.animation_group_id_), last_progressed_fraction_(element.last_progressed_fraction_) {} LayerAnimationElement::~LayerAnimationElement() = default; void LayerAnimationElement::Start(LayerAnimationDelegate* delegate, int animation_group_id) { DCHECK(requested_start_time_ != base::TimeTicks()); DCHECK(first_frame_); animation_group_id_ = animation_group_id; last_progressed_fraction_ = 0.0; OnStart(delegate); RequestEffectiveStart(delegate); first_frame_ = false; } bool LayerAnimationElement::Progress(base::TimeTicks now, LayerAnimationDelegate* delegate) { DCHECK(requested_start_time_ != base::TimeTicks()); DCHECK(!first_frame_); bool need_draw; double t = 1.0; if ((effective_start_time_ == base::TimeTicks()) || (now < effective_start_time_)) { // This hasn't actually started yet. need_draw = false; last_progressed_fraction_ = 0.0; return need_draw; } base::TimeDelta elapsed = now - effective_start_time_; if ((duration_.is_positive()) && (elapsed < duration_)) t = elapsed / duration_; base::WeakPtr alive(weak_ptr_factory_.GetWeakPtr()); need_draw = OnProgress(gfx::Tween::CalculateValue(tween_type_, t), delegate); if (!alive) return need_draw; first_frame_ = t == 1.0; last_progressed_fraction_ = t; return need_draw; } bool LayerAnimationElement::IsFinished(base::TimeTicks time, base::TimeDelta* total_duration) { // If an effective start has been requested but the effective start time // hasn't yet been set, the keyframe_model is not finished, regardless of the // value of |time|. if (!first_frame_ && (effective_start_time_ == base::TimeTicks())) return false; base::TimeDelta queueing_delay; if (!first_frame_) queueing_delay = effective_start_time_ - requested_start_time_; base::TimeDelta elapsed = time - requested_start_time_; if (elapsed >= duration_ + queueing_delay) { *total_duration = duration_ + queueing_delay; return true; } return false; } bool LayerAnimationElement::ProgressToEnd(LayerAnimationDelegate* delegate) { if (first_frame_) OnStart(delegate); base::WeakPtr alive(weak_ptr_factory_.GetWeakPtr()); bool need_draw = OnProgress(1.0, delegate); if (!alive) return need_draw; last_progressed_fraction_ = 1.0; first_frame_ = true; return need_draw; } void LayerAnimationElement::GetTargetValue(TargetValue* target) const { OnGetTarget(target); } bool LayerAnimationElement::IsThreaded(LayerAnimationDelegate* delegate) const { return false; } void LayerAnimationElement::Abort(LayerAnimationDelegate* delegate) { OnAbort(delegate); first_frame_ = true; } void LayerAnimationElement::RequestEffectiveStart( LayerAnimationDelegate* delegate) { DCHECK(requested_start_time_ != base::TimeTicks()); effective_start_time_ = requested_start_time_; } std::string LayerAnimationElement::ToString() const { // TODO(wkorman): Add support for subclasses to tack on more info // beyond just their name. return base::StringPrintf( "LayerAnimationElement{name=%s, id=%d, group=%d, " "last_progressed_fraction=%0.2f}", DebugName().c_str(), keyframe_model_id_, animation_group_id_, last_progressed_fraction_); } void LayerAnimationElement::UpdateKeyframeModelId() { keyframe_model_id_ = cc::AnimationIdProvider::NextKeyframeModelId(); } std::string LayerAnimationElement::DebugName() const { return "Default"; } // static LayerAnimationElement::AnimatableProperty LayerAnimationElement::ToAnimatableProperty(cc::TargetProperty::Type property) { switch (property) { case cc::TargetProperty::TRANSFORM: return TRANSFORM; case cc::TargetProperty::OPACITY: return OPACITY; default: NOTREACHED(); return AnimatableProperty(); } } // static std::string LayerAnimationElement::AnimatablePropertiesToString( AnimatableProperties properties) { std::string str; int property_count = 0; for (unsigned i = FIRST_PROPERTY; i != SENTINEL; i = i << 1) { if (i & properties) { LayerAnimationElement::AnimatableProperty property = static_cast(i); if (property_count > 0) str.append("|"); // TODO(wkorman): Consider reworking enum definition to follow // #define pattern that includes easier string output. switch (property) { case UNKNOWN: str.append("UNKNOWN"); break; case TRANSFORM: str.append("TRANSFORM"); break; case BOUNDS: str.append("BOUNDS"); break; case OPACITY: str.append("OPACITY"); break; case VISIBILITY: str.append("VISIBILITY"); break; case BRIGHTNESS: str.append("BRIGHTNESS"); break; case GRAYSCALE: str.append("GRAYSCALE"); break; case COLOR: str.append("COLOR"); break; case CLIP: str.append("CLIP"); break; case ROUNDED_CORNERS: str.append("ROUNDED_CORNERS"); break; case GRADIENT_MASK: str.append("GRADIENT_MASK"); break; case SENTINEL: NOTREACHED(); break; } property_count++; } } return str; } // static base::TimeDelta LayerAnimationElement::GetEffectiveDuration( const base::TimeDelta& duration) { if (ScopedAnimationDurationScaleMode::duration_multiplier() == 0) return base::TimeDelta(); return duration * ScopedAnimationDurationScaleMode::duration_multiplier(); } // static std::unique_ptr LayerAnimationElement::CreateTransformElement(const gfx::Transform& transform, base::TimeDelta duration) { return std::make_unique(transform, duration); } // static std::unique_ptr LayerAnimationElement::CreateInterpolatedTransformElement( std::unique_ptr interpolated_transform, base::TimeDelta duration) { return std::make_unique( std::move(interpolated_transform), duration); } // static std::unique_ptr LayerAnimationElement::CreateBoundsElement(const gfx::Rect& bounds, base::TimeDelta duration) { return std::make_unique(bounds, duration); } // static std::unique_ptr LayerAnimationElement::CreateOpacityElement(float opacity, base::TimeDelta duration) { return std::make_unique(opacity, duration); } // static std::unique_ptr LayerAnimationElement::CreateVisibilityElement(bool visibility, base::TimeDelta duration) { return std::make_unique(visibility, duration); } // static std::unique_ptr LayerAnimationElement::CreateBrightnessElement(float brightness, base::TimeDelta duration) { return std::make_unique(brightness, duration); } // static std::unique_ptr LayerAnimationElement::CreateGrayscaleElement(float grayscale, base::TimeDelta duration) { return std::make_unique(grayscale, duration); } // static std::unique_ptr LayerAnimationElement::CreatePauseElement(AnimatableProperties properties, base::TimeDelta duration) { return std::make_unique(properties, duration); } // static std::unique_ptr LayerAnimationElement::CreateColorElement(SkColor color, base::TimeDelta duration) { return std::make_unique(color, duration); } std::unique_ptr LayerAnimationElement::CreateClipRectElement(const gfx::Rect& clip_rect, base::TimeDelta duration) { return std::make_unique(clip_rect, duration); } std::unique_ptr LayerAnimationElement::CreateRoundedCornersElement( const gfx::RoundedCornersF& rounded_corners, base::TimeDelta duration) { return std::make_unique(rounded_corners, duration); } std::unique_ptr LayerAnimationElement::CreateGradientMaskElement( const gfx::LinearGradient& gradient_mask, base::TimeDelta duration) { return std::make_unique(gradient_mask, duration); } } // namespace ui