1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/csspaint/nativepaint/native_css_paint_definition.h"
#include "third_party/blink/renderer/core/animation/animation_time_delta.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/interpolable_value.h"
#include "third_party/blink/renderer/core/css/css_value.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
namespace blink {
NativeCssPaintDefinition::NativeCssPaintDefinition(
LocalFrame* local_root,
PaintWorkletInput::PaintWorkletInputType type)
: NativePaintDefinition(local_root, type) {}
bool NativeCssPaintDefinition::CanGetValueFromKeyframe(
const Element* element,
const PropertySpecificKeyframe* frame,
const KeyframeEffectModelBase* model,
ValueFilter filter) {
if (model->IsStringKeyframeEffectModel()) {
DCHECK(frame->IsCSSPropertySpecificKeyframe());
const CSSValue* value = To<CSSPropertySpecificKeyframe>(frame)->Value();
return filter(element, value, nullptr);
} else {
DCHECK(frame->IsTransitionPropertySpecificKeyframe());
const TransitionKeyframe::PropertySpecificKeyframe* keyframe =
To<TransitionKeyframe::PropertySpecificKeyframe>(frame);
InterpolableValue* value =
keyframe->GetValue()->Value().interpolable_value.Get();
return filter(element, nullptr, value);
}
}
Animation* NativeCssPaintDefinition::GetAnimationForProperty(
const Element* element,
const CSSProperty& property,
ValueFilter filter) {
if (!element->GetElementAnimations()) {
return nullptr;
}
Animation* compositable_animation = nullptr;
// We'd composite only if it is the only animation of its type on
// this element.
unsigned count = 0;
for (const auto& animation : element->GetElementAnimations()->Animations()) {
if (animation.key->CalculateAnimationPlayState() ==
V8AnimationPlayState::Enum::kIdle ||
!animation.key->Affects(*element, property)) {
continue;
}
count++;
compositable_animation = animation.key;
}
if (!compositable_animation || count > 1) {
return nullptr;
}
if (!AnimationIsValidForPaintWorklets(compositable_animation, element,
property, filter)) {
return nullptr;
}
return compositable_animation;
}
bool NativeCssPaintDefinition::AnimationIsValidForPaintWorklets(
Animation* compositable_animation,
const Element* element,
const CSSProperty& property,
ValueFilter filter) {
const AnimationEffect* effect = compositable_animation->effect();
// TODO(crbug.com/1429770): Implement positive delay fix for bgcolor.
if (effect->SpecifiedTiming().start_delay.AsTimeValue().InSecondsF() > 0.f) {
if (property.PropertyID() != CSSPropertyID::kClipPath) {
return false;
}
}
DCHECK(effect->IsKeyframeEffect());
const KeyframeEffectModelBase* model =
static_cast<const KeyframeEffect*>(effect)->Model();
if (model->AffectedByUnderlyingAnimations()) {
return false;
}
const PropertySpecificKeyframeVector* frames =
model->GetPropertySpecificKeyframes(PropertyHandle(property));
DCHECK_GE(frames->size(), 2u);
for (const auto& frame : *frames) {
if (!CanGetValueFromKeyframe(element, frame, model, filter)) {
return false;
}
}
return true;
}
bool NativeCssPaintDefinition::DefaultValueFilter(
const Element* element,
const CSSValue* value,
const InterpolableValue* interpolable_value) {
return value || interpolable_value;
}
std::optional<double> NativeCssPaintDefinition::Progress(
const std::optional<double>& main_thread_progress,
const CompositorPaintWorkletJob::AnimatedPropertyValues&
animated_property_values) {
std::optional<double> progress = main_thread_progress;
// Override the progress from the main thread if the animation has been
// started on the compositor.
if (!animated_property_values.empty()) {
DCHECK_EQ(animated_property_values.size(), 1u);
const auto& entry = animated_property_values.begin();
progress = entry->second.float_value.value();
}
return progress;
}
} // namespace blink
|