37class Vec2KeyframeAnimator final :
public KeyframeAnimator {
44 Vec2KeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
45 std::vector<SpatialValue> vs,
Vec2Value* vec_target,
float* rot_target)
47 , fValues(
std::move(vs))
48 , fVecTarget(vec_target)
49 , fRotTarget(rot_target) {}
53 auto changed = (new_vec_value != *fVecTarget);
54 *fVecTarget = new_vec_value;
59 changed |= new_rot_value != *fRotTarget;
60 *fRotTarget = new_rot_value;
66 StateChanged onSeek(
float t)
override {
67 auto get_lerp_info = [
this](
float t) {
68 auto lerp_info = this->getLERPInfo(t);
76 const auto vidx = lerp_info.vrec0.idx;
77 if (fRotTarget && vidx == fValues.size() - 1 && vidx > 0) {
79 SkASSERT(lerp_info.vrec1.idx == vidx);
84 lerp_info.vrec0 = {vidx - 1};
93 const auto lerp_info = get_lerp_info(t);
95 const auto& v0 = fValues[lerp_info.vrec0.idx];
101 const float len = v0.cmeasure->length(),
103 if (v0.cmeasure->getPosTan(
distance, &
pos, &tan)) {
107 if (distance < 0 || distance >
len) {
110 pos += tan * overshoot;
117 const auto& v1 = fValues[lerp_info.vrec1.idx];
118 const auto tan = v1.v2 - v0.v2;
120 return this->
update(
Lerp(v0.v2, v1.v2, lerp_info.weight), tan);
123 const std::vector<Vec2KeyframeAnimator::SpatialValue> fValues;
130class Vec2ExpressionAnimator final :
public Animator {
132 Vec2ExpressionAnimator(
sk_sp<ExpressionEvaluator<std::vector<float>>> expression_evaluator,
134 : fExpressionEvaluator(
std::move(expression_evaluator))
135 , fTarget(target_value) {}
139 StateChanged onSeek(
float t)
override {
140 auto old_value = *fTarget;
142 std::vector<float>
result = fExpressionEvaluator->evaluate(t);
146 return *fTarget != old_value;
153class Vec2AnimatorBuilder final :
public AnimatorBuilder {
155 Vec2AnimatorBuilder(
Vec2Value* vec_target,
float* rot_target)
157 , fVecTarget(vec_target)
158 , fRotTarget(rot_target) {}
164 fValues.reserve(jkfs.
size());
165 if (!this->parseKeyframes(abuilder, jkfs)) {
168 fValues.shrink_to_fit();
171 new Vec2KeyframeAnimator(std::move(fKFs),
178 sk_sp<Animator> makeFromExpression(ExpressionManager& em,
const char* expr)
override {
180 em.createArrayExpressionEvaluator(expr);
181 return sk_make_sp<Vec2ExpressionAnimator>(expression_evaluator, fVecTarget);
184 bool parseValue(
const AnimationBuilder&,
const skjson::Value& jv)
const override {
189 void backfill_spatial(
const Vec2KeyframeAnimator::SpatialValue& val) {
191 auto& prev_val = fValues.back();
194 if (val.v2 == prev_val.v2) {
200 auto check_vecs = [](
const SkV2& v0,
const SkV2& v1) {
202 v1_len2 = v1.lengthSquared();
205 if (v0_len2 < v1_len2) {
211 const auto dot = v0.
dot(v1);
215 if (check_vecs(val.v2 - prev_val.v2, fTo) &&
216 check_vecs(prev_val.v2 - val.v2, fTi)) {
224 p.moveTo (prev_val.v2.x , prev_val.v2.y);
225 p.cubicTo(prev_val.v2.x + fTo.
x, prev_val.v2.y + fTo.
y,
226 val.v2.x + fTi.
x, val.v2.y + fTi.
y,
231 bool parseKFValue(
const AnimationBuilder&,
234 Keyframe::Value* v)
override {
235 Vec2KeyframeAnimator::SpatialValue val;
240 if (fPendingSpatial) {
241 this->backfill_spatial(val);
245 fTi = ParseDefault<SkV2>(jkf[
"ti"], {0,0});
246 fTo = ParseDefault<SkV2>(jkf[
"to"], {0,0});
247 fPendingSpatial = fTi !=
SkV2{0,0} || fTo !=
SkV2{0,0};
249 if (fValues.empty() || val.v2 != fValues.back().v2 || fPendingSpatial) {
250 fValues.push_back(std::move(val));
253 v->idx =
SkToU32(fValues.size() - 1);
258 std::vector<Vec2KeyframeAnimator::SpatialValue> fValues;
263 bool fPendingSpatial =
false;
279 abuilder.fSlotManager->trackVec2Value(
SkString(sid->begin()), v,
sk_ref_sp(
this));
282 if (!ParseDefault<bool>((*jprop)[
"s"],
false)) {
284 Vec2AnimatorBuilder
builder(v, orientation);
285 return this->bindImpl(abuilder, jprop,
builder);
289 bool boundX = this->
bind(abuilder, (*jprop)[
"x"], &v->
x);
290 bool boundY = this->
bind(abuilder, (*jprop)[
"y"], &v->
y);
291 return boundX || boundY;
#define INHERITED(method,...)
sk_sp< T > sk_ref_sp(T *obj)
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkRadiansToDegrees(radians)
constexpr uint32_t SkToU32(S x)
sk_sp< SkContourMeasure > cmeasure
sk_sp< SkContourMeasure > next()
bool bindAutoOrientable(const AnimationBuilder &abuilder, const skjson::ObjectValue *jobject, SkV2 *v, float *orientation)
bool bind(const AnimationBuilder &, const skjson::ObjectValue *, T *)
static float max(float r, float g, float b)
void SK_API Parse(Metadata &metadata, const SkData *data)
T Lerp(const T &a, const T &b, float t)
const skjson::StringValue * ParseSlotID(const skjson::ObjectValue *jobj)
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
SkScalar dot(SkV2 v) const
SkScalar lengthSquared() const