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
|
// Copyright 2016 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/core/animation/keyframe.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_timeline_range_offset.h"
#include "third_party/blink/renderer/core/animation/effect_model.h"
#include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h"
#include "third_party/blink/renderer/core/animation/timeline_range.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
const double Keyframe::kNullComputedOffset =
std::numeric_limits<double>::quiet_NaN();
Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(
double offset,
scoped_refptr<TimingFunction> easing,
EffectModel::CompositeOperation composite)
: offset_(offset), easing_(std::move(easing)), composite_(composite) {
DCHECK(std::isfinite(offset));
if (!easing_)
easing_ = LinearTimingFunction::Shared();
}
Interpolation* Keyframe::PropertySpecificKeyframe::CreateInterpolation(
const PropertyHandle& property_handle,
const Keyframe::PropertySpecificKeyframe& end) const {
// const_cast to take refs.
return MakeGarbageCollected<InvalidatableInterpolation>(
property_handle, const_cast<PropertySpecificKeyframe*>(this),
const_cast<PropertySpecificKeyframe*>(&end));
}
Vector<PropertyHandle> Keyframe::PropertiesVector() const {
Vector<PropertyHandle> result;
const auto& properties = Properties();
result.ReserveInitialCapacity(properties.size());
for (const auto& property : properties) {
result.push_back(property);
}
return result;
}
void Keyframe::AddKeyframePropertiesToV8Object(V8ObjectBuilder& object_builder,
Element* element) const {
// If the keyframe has a timeline offset add it instead of offset.
if (timeline_offset_) {
TimelineRangeOffset* timeline_range_offset = TimelineRangeOffset::Create();
timeline_range_offset->setRangeName(timeline_offset_->name);
DCHECK(timeline_offset_->offset.IsPercent());
timeline_range_offset->setOffset(
CSSUnitValue::Create(timeline_offset_->offset.Percent(),
CSSPrimitiveValue::UnitType::kPercentage));
object_builder.Add("offset", timeline_range_offset);
} else if (offset_) {
object_builder.AddNumber("offset", offset_.value());
} else {
object_builder.AddNull("offset");
}
object_builder.AddString("easing", easing_->ToString());
if (composite_) {
object_builder.AddString(
"composite", V8CompositeOperation(EffectModel::CompositeOperationToEnum(
composite_.value()))
.AsCStr());
} else {
object_builder.AddString("composite", "auto");
}
}
bool Keyframe::ResolveTimelineOffset(const TimelineRange& timeline_range,
double range_start,
double range_end) {
if (!timeline_offset_) {
return false;
}
double relative_offset =
timeline_range.ToFractionalOffset(timeline_offset_.value());
double range = range_end - range_start;
if (!range) {
if (offset_) {
offset_.reset();
computed_offset_ = kNullComputedOffset;
return true;
}
} else {
double resolved_offset = (relative_offset - range_start) / range;
if (!offset_ || offset_.value() != resolved_offset) {
offset_ = resolved_offset;
computed_offset_ = resolved_offset;
return true;
}
}
return false;
}
/* static */
bool Keyframe::LessThan(const Member<Keyframe>& a, const Member<Keyframe>& b) {
std::optional first =
a->ComputedOffset().has_value() ? a->ComputedOffset() : a->Offset();
std::optional second =
b->ComputedOffset().has_value() ? b->ComputedOffset() : b->Offset();
if (first < second) {
return true;
}
if (first > second) {
return false;
}
if (a->original_index_ < b->original_index_) {
return true;
}
return false;
}
} // namespace blink
|