Create VectorExpressionAnimator

Change-Id: I9ac04e316fd5cc21f9400ff56cf6bc6db77ca046
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/444871
Commit-Queue: Avinash Parchuri <aparchur@google.com>
Reviewed-by: Avinash Parchuri <aparchur@google.com>
Reviewed-by: Florin Malita <fmalita@google.com>
This commit is contained in:
Kyle Carlstrom 2021-09-01 14:24:48 -07:00 committed by SkCQ
parent 907c593fad
commit 0bfac0127c
3 changed files with 142 additions and 10 deletions

View File

@ -54,12 +54,16 @@ bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
return false;
}
const auto& jpropA = (*jprop)["a"];
const auto& jpropK = (*jprop)["k"];
// Handle expressions on the property.
if (const skjson::StringValue* expr = (*jprop)["x"]) {
if (!abuilder.expression_manager()) {
abuilder.log(Logger::Level::kWarning, jprop,
"Expression encountered but ExpressionManager not provided.");
} else {
builder.parseValue(abuilder, jpropK);
sk_sp<Animator> expression_animator = builder.makeFromExpression(
*abuilder.expression_manager(),
expr->begin());
@ -70,9 +74,6 @@ bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
}
}
const auto& jpropA = (*jprop)["a"];
const auto& jpropK = (*jprop)["k"];
// Older Json versions don't have an "a" animation marker.
// For those, we attempt to parse both ways.
if (!ParseDefault<bool>(jpropA, false)) {

View File

@ -142,6 +142,33 @@ private:
using INHERITED = KeyframeAnimator;
};
class VectorExpressionAnimator final : public Animator {
public:
VectorExpressionAnimator(sk_sp<ExpressionEvaluator<std::vector<float>>> expression_evaluator,
std::vector<float>* target_value)
: fExpressionEvaluator(std::move(expression_evaluator))
, fTarget(target_value) {}
private:
StateChanged onSeek(float t) override {
std::vector<float> result = fExpressionEvaluator->evaluate(t);
bool changed = false;
for (size_t i = 0; i < fTarget->size(); i++) {
// Use 0 as a default if the result is too small.
float val = i >= result.size() ? 0 : result[i];
if (!SkScalarNearlyEqual(val, (*fTarget)[i])) {
changed = true;
}
(*fTarget)[i] = val;
}
return changed;
}
sk_sp<ExpressionEvaluator<std::vector<float>>> fExpressionEvaluator;
std::vector<float>* fTarget;
};
} // namespace
VectorAnimatorBuilder::VectorAnimatorBuilder(std::vector<float>* target,
@ -189,8 +216,10 @@ sk_sp<KeyframeAnimator> VectorAnimatorBuilder::makeFromKeyframes(const Animation
fTarget));
}
sk_sp<Animator> VectorAnimatorBuilder::makeFromExpression(ExpressionManager&, const char*) {
return nullptr;
sk_sp<Animator> VectorAnimatorBuilder::makeFromExpression(ExpressionManager& em, const char* expr) {
sk_sp<ExpressionEvaluator<std::vector<SkScalar>>> expression_evaluator =
em.createArrayExpressionEvaluator(expr);
return sk_make_sp<VectorExpressionAnimator>(expression_evaluator, fTarget);
}
bool VectorAnimatorBuilder::parseValue(const AnimationBuilder&,

View File

@ -25,7 +25,7 @@ public:
class FakeVectorExpressionEvaluator : public ExpressionEvaluator<std::vector<float>> {
public:
std::vector<float> evaluate(float t) override {
return {1.0f, 2.0f};
return {0.1f, 0.2f, 0.3f, 1.0f};
}
};
@ -59,12 +59,18 @@ class FakePropertyObserver : public PropertyObserver {
transform_handle_.reset(transform_handle().release());
}
void onColorProperty(const char node_name[],
const LazyHandle<ColorPropertyHandle>& color_handle) override {
color_handle_.reset(color_handle().release());
}
std::unique_ptr<OpacityPropertyHandle> opacity_handle_;
std::unique_ptr<TransformPropertyHandle> transform_handle_;
std::unique_ptr<ColorPropertyHandle> color_handle_;
};
} // namespace
DEF_TEST(Skottie_ScalarExpression, r) {
DEF_TEST(Skottie_Expression, r) {
static constexpr char json[] =
R"({
"v": "5.2.1",
@ -124,10 +130,105 @@ DEF_TEST(Skottie_ScalarExpression, r) {
"l": 2
}
},
"ef": [
{
"ty": 21,
"nm": "Fill",
"np": 9,
"mn": "ADBE Fill",
"ix": 1,
"en": 1,
"ef": [
{
"ty": 10,
"nm": "Fill Mask",
"mn": "ADBE Fill-0001",
"ix": 1,
"v": {
"a": 0,
"k": 0,
"ix": 1
}
},
{
"ty": 7,
"nm": "All Masks",
"mn": "ADBE Fill-0007",
"ix": 2,
"v": {
"a": 0,
"k": 0,
"ix": 2
}
},
{
"ty": 2,
"nm": "Color",
"mn": "ADBE Fill-0002",
"ix": 3,
"v": {
"a": 0,
"k": [
1,
0,
0,
1
],
"ix": 3,
"x": "fake; return value is specified by the FakeArrayExpressionEvaluator."
}
},
{
"ty": 7,
"nm": "Invert",
"mn": "ADBE Fill-0006",
"ix": 4,
"v": {
"a": 0,
"k": 0,
"ix": 4
}
},
{
"ty": 0,
"nm": "Horizontal Feather",
"mn": "ADBE Fill-0003",
"ix": 5,
"v": {
"a": 0,
"k": 0,
"ix": 5
}
},
{
"ty": 0,
"nm": "Vertical Feather",
"mn": "ADBE Fill-0004",
"ix": 6,
"v": {
"a": 0,
"k": 0,
"ix": 6
}
},
{
"ty": 0,
"nm": "Opacity",
"mn": "ADBE Fill-0005",
"ix": 7,
"v": {
"a": 0,
"k": 1,
"ix": 7
}
}
]
}
],
"ao": 0,
"sw": 100,
"sh": 100,
"sc": "#51251d",
"sc": "#000000",
"st": 0,
"bm": 0
}
@ -150,6 +251,7 @@ DEF_TEST(Skottie_ScalarExpression, r) {
REPORTER_ASSERT(r, SkScalarNearlyEqual(observer->opacity_handle_->get(), 7.0f));
SkPoint anchor_point = observer->transform_handle_->get().fAnchorPoint;
REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fX, 1.0f));
REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fY, 2.0f));
REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fX, 0.1f));
REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fY, 0.2f));
REPORTER_ASSERT(r, (observer->color_handle_->get() == SkColor4f{0.1f, 0.2f, 0.3f, 1.0f}.toSkColor()));
}