diff options
author | Florin Malita <fmalita@chromium.org> | 2018-06-20 11:19:53 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-20 17:17:19 +0000 |
commit | 8c5f9ef801793ec8a95918ad25729de847b119eb (patch) | |
tree | 5340eaadd3779ead10b66eabd21b552f8080941d | |
parent | 75fd449d81ab0b083ca97c5ae4dffb5cb9427fdb (diff) |
[skottie] Fix start-time/stretch-time handling
We currently apply start-time/stretch-time adjustments to the referenced
composition AND to the referencing layer local properties. That last
part is incorrect: the adjustment should only apply to the referenced
composition.
Introduce a specialized composition time mapper to handle t adjustments,
and push the logic down to AttachCompLayer (and out of the generic
AttachLayer).
TBR=
Change-Id: I0ddb86232010a8e7cdac6524aef2eea5823e306d
Reviewed-on: https://skia-review.googlesource.com/136166
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
-rw-r--r-- | modules/skottie/src/Skottie.cpp | 87 |
1 files changed, 47 insertions, 40 deletions
diff --git a/modules/skottie/src/Skottie.cpp b/modules/skottie/src/Skottie.cpp index 71521c6691..a5b4bc8648 100644 --- a/modules/skottie/src/Skottie.cpp +++ b/modules/skottie/src/Skottie.cpp @@ -777,22 +777,49 @@ sk_sp<sksg::RenderNode> AttachAssetRef(const skjson::ObjectValue& jlayer, Attach return asset; } -sk_sp<sksg::RenderNode> AttachCompLayer(const skjson::ObjectValue& jlayer, AttachContext* ctx, - float* time_bias, float* time_scale) { +sk_sp<sksg::RenderNode> AttachCompLayer(const skjson::ObjectValue& jlayer, AttachContext* ctx) { const auto start_time = ParseDefault<float>(jlayer["st"], 0.0f), stretch_time = ParseDefault<float>(jlayer["sr"], 1.0f); + const auto requires_time_mapping = !SkScalarNearlyEqual(start_time , 0) || + !SkScalarNearlyEqual(stretch_time, 1); - *time_bias = -start_time; - *time_scale = sk_ieee_float_divide(1, stretch_time); - if (SkScalarIsNaN(*time_scale)) { - *time_scale = 1; + sksg::AnimatorList local_animators; + AttachContext local_ctx = { ctx->fResources, + ctx->fAssets, + ctx->fDuration, + requires_time_mapping ? local_animators : ctx->fAnimators }; + + auto comp_layer = AttachAssetRef(jlayer, &local_ctx, AttachComposition); + + // Applies a bias/scale t-adjustment to child animators. + class CompTimeMapper final : public sksg::GroupAnimator { + public: + CompTimeMapper(sksg::AnimatorList&& layer_animators, float time_bias, float time_scale) + : INHERITED(std::move(layer_animators)) + , fTimeBias(time_bias) + , fTimeScale(time_scale) {} + + void onTick(float t) override { + this->INHERITED::onTick((t + fTimeBias) * fTimeScale); + } + private: + const float fTimeBias, + fTimeScale; + + using INHERITED = sksg::GroupAnimator; + }; + + if (requires_time_mapping) { + const auto t_bias = -start_time, + t_scale = sk_ieee_float_divide(1, stretch_time); + ctx->fAnimators.push_back(skstd::make_unique<CompTimeMapper>(std::move(local_animators), + t_bias, t_scale)); } - return AttachAssetRef(jlayer, ctx, AttachComposition); + return comp_layer; } -sk_sp<sksg::RenderNode> AttachSolidLayer(const skjson::ObjectValue& jlayer, AttachContext*, - float*, float*) { +sk_sp<sksg::RenderNode> AttachSolidLayer(const skjson::ObjectValue& jlayer, AttachContext*) { const auto size = SkSize::Make(ParseDefault<float>(jlayer["sw"], 0.0f), ParseDefault<float>(jlayer["sh"], 0.0f)); const auto hex = ParseDefault<SkString>(jlayer["sc"], SkString()); @@ -829,20 +856,17 @@ sk_sp<sksg::RenderNode> AttachImageAsset(const skjson::ObjectValue& jimage, Atta SkImage::MakeFromEncoded(SkData::MakeFromStream(resStream.get(), resStream->getLength()))); } -sk_sp<sksg::RenderNode> AttachImageLayer(const skjson::ObjectValue& jlayer, AttachContext* ctx, - float*, float*) { +sk_sp<sksg::RenderNode> AttachImageLayer(const skjson::ObjectValue& jlayer, AttachContext* ctx) { return AttachAssetRef(jlayer, ctx, AttachImageAsset); } -sk_sp<sksg::RenderNode> AttachNullLayer(const skjson::ObjectValue& layer, AttachContext*, - float*, float*) { +sk_sp<sksg::RenderNode> AttachNullLayer(const skjson::ObjectValue& layer, AttachContext*) { // Null layers are used solely to drive dependent transforms, // but we use free-floating sksg::Matrices for that purpose. return nullptr; } -sk_sp<sksg::RenderNode> AttachShapeLayer(const skjson::ObjectValue& layer, AttachContext* ctx, - float*, float*) { +sk_sp<sksg::RenderNode> AttachShapeLayer(const skjson::ObjectValue& layer, AttachContext* ctx) { std::vector<sk_sp<sksg::GeometryNode>> geometryStack; std::vector<GeometryEffectRec> geometryEffectStack; AttachShapeContext shapeCtx(ctx, &geometryStack, &geometryEffectStack, ctx->fAnimators.size()); @@ -858,8 +882,7 @@ sk_sp<sksg::RenderNode> AttachShapeLayer(const skjson::ObjectValue& layer, Attac return shapeNode; } -sk_sp<sksg::RenderNode> AttachTextLayer(const skjson::ObjectValue& layer, AttachContext*, - float*, float*) { +sk_sp<sksg::RenderNode> AttachTextLayer(const skjson::ObjectValue& layer, AttachContext*) { LOG("?? Text layer stub\n"); return nullptr; } @@ -1007,8 +1030,7 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer, AttachLayerContext* layerCtx) { if (!jlayer) return nullptr; - using LayerAttacher = sk_sp<sksg::RenderNode> (*)(const skjson::ObjectValue&, AttachContext*, - float* time_bias, float* time_scale); + using LayerAttacher = sk_sp<sksg::RenderNode> (*)(const skjson::ObjectValue&, AttachContext*); static constexpr LayerAttacher gLayerAttachers[] = { AttachCompLayer, // 'ty': 0 AttachSolidLayer, // 'ty': 1 @@ -1029,12 +1051,8 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer, layerCtx->fCtx->fDuration, layer_animators}; - // Layer attachers may adjust these. - float time_bias = 0, - time_scale = 1; - // Layer content. - auto layer = gLayerAttachers[type](*jlayer, &local_ctx, &time_bias, &time_scale); + auto layer = gLayerAttachers[type](*jlayer, &local_ctx); // Clip layers with explicit dimensions. float w = 0, h = 0; @@ -1062,14 +1080,11 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer, public: LayerController(sksg::AnimatorList&& layer_animators, sk_sp<sksg::OpacityEffect> controlNode, - float in, float out, - float time_bias, float time_scale) + float in, float out) : INHERITED(std::move(layer_animators)) , fControlNode(std::move(controlNode)) , fIn(in) - , fOut(out) - , fTimeBias(time_bias) - , fTimeScale(time_scale) {} + , fOut(out) {} void onTick(float t) override { const auto active = (t >= fIn && t <= fOut); @@ -1079,16 +1094,13 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer, fControlNode->setOpacity(active ? 1 : 0); // Dispatch ticks only while active. - if (active) - this->INHERITED::onTick((t + fTimeBias) * fTimeScale); + if (active) this->INHERITED::onTick(t); } private: const sk_sp<sksg::OpacityEffect> fControlNode; const float fIn, - fOut, - fTimeBias, - fTimeScale; + fOut; using INHERITED = sksg::GroupAnimator; }; @@ -1105,12 +1117,7 @@ sk_sp<sksg::RenderNode> AttachLayer(const skjson::ObjectValue* jlayer, return nullptr; layerCtx->fCtx->fAnimators.push_back( - skstd::make_unique<LayerController>(std::move(layer_animators), - controller_node, - in, - out, - time_bias, - time_scale)); + skstd::make_unique<LayerController>(std::move(layer_animators), controller_node, in, out)); if (ParseDefault<bool>((*jlayer)["td"], false)) { // This layer is a matte. We apply it as a mask to the next layer. |