Revert "[skottie] Initial property setters"
This reverts commit 7903957247
.
Reason for revert: breaking SAN bots
Original change's description:
> [skottie] Initial property setters
>
> Introduce a PropertyObserver to receive property notifications for layer
> and shape nodes.
>
> Properties are communicated using strongly-typed "handles", which act
> as impedance adapters between the AE/BM model and the internal Skottie
> model.
>
> Bug: skia:
> Change-Id: Ieb9be1ff843673f1f4fe900d3774c36956b7c941
> Reviewed-on: https://skia-review.googlesource.com/156186
> Commit-Queue: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Mike Reed <reed@google.com>
TBR=fmalita@chromium.org,reed@google.com
Change-Id: Ic737766e305bb8dff10a817fa37f16fdfa051c93
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/156620
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
41e404746d
commit
39e1d13d35
@ -26,8 +26,6 @@ namespace sksg { class Scene; }
|
||||
|
||||
namespace skottie {
|
||||
|
||||
class PropertyObserver;
|
||||
|
||||
/**
|
||||
* ResourceProvider allows Skottie embedders to control loading of external
|
||||
* Skottie resources -- e.g. images, fonts, nested animations.
|
||||
@ -64,9 +62,6 @@ public:
|
||||
|
||||
class Builder final {
|
||||
public:
|
||||
Builder();
|
||||
~Builder();
|
||||
|
||||
struct Stats {
|
||||
float fTotalLoadTimeMS = 0, // Total animation instantiation time.
|
||||
fJsonParseTimeMS = 0, // Time spent building a JSON DOM.
|
||||
@ -92,14 +87,6 @@ public:
|
||||
*/
|
||||
Builder& setFontManager(sk_sp<SkFontMgr>);
|
||||
|
||||
/**
|
||||
* Specify a PropertyObserver to receive callbacks during parsing.
|
||||
*
|
||||
* See SkottieProperty.h for more details.
|
||||
*
|
||||
*/
|
||||
Builder& setPropertyObserver(sk_sp<PropertyObserver>);
|
||||
|
||||
/**
|
||||
* Animation factories.
|
||||
*/
|
||||
@ -110,7 +97,6 @@ public:
|
||||
private:
|
||||
sk_sp<ResourceProvider> fResourceProvider;
|
||||
sk_sp<SkFontMgr> fFontMgr;
|
||||
sk_sp<PropertyObserver> fPropertyObserver;
|
||||
Stats fStats;
|
||||
};
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkottieProperty_DEFINED
|
||||
#define SkottieProperty_DEFINED
|
||||
|
||||
#include "SkColor.h"
|
||||
#include "SkPoint.h"
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
class SkMatrix;
|
||||
|
||||
namespace sksg {
|
||||
|
||||
class Color;
|
||||
class OpacityEffect;
|
||||
|
||||
} // namespace sksg
|
||||
|
||||
namespace skottie {
|
||||
|
||||
class ColorPropertyHandle;
|
||||
class OpacityPropertyHandle;
|
||||
class TransformPropertyHandle;
|
||||
|
||||
/**
|
||||
* A PropertyObserver can be used to track and manipulate certain properties of "interesting"
|
||||
* Lottie nodes.
|
||||
*
|
||||
* When registered with an animation builder, PropertyObserver receives notifications for
|
||||
* various properties of layer and shape nodes. The |node_name| argument corresponds to the
|
||||
* name ("nm") node property.
|
||||
*/
|
||||
class PropertyObserver : public SkRefCnt {
|
||||
public:
|
||||
template <typename T>
|
||||
using LazyHandle = std::function<std::unique_ptr<T>()>;
|
||||
|
||||
virtual void onColorProperty (const char node_name[],
|
||||
const LazyHandle<ColorPropertyHandle>&);
|
||||
virtual void onOpacityProperty (const char node_name[],
|
||||
const LazyHandle<OpacityPropertyHandle>&);
|
||||
virtual void onTransformProperty(const char node_name[],
|
||||
const LazyHandle<TransformPropertyHandle>&);
|
||||
};
|
||||
|
||||
namespace internal { class AnimationBuilder; }
|
||||
|
||||
class ColorPropertyHandle final {
|
||||
public:
|
||||
~ColorPropertyHandle();
|
||||
|
||||
SkColor getColor() const;
|
||||
void setColor(SkColor);
|
||||
|
||||
private:
|
||||
explicit ColorPropertyHandle(sk_sp<sksg::Color>);
|
||||
|
||||
friend class skottie::internal::AnimationBuilder;
|
||||
|
||||
const sk_sp<sksg::Color> fColor;
|
||||
};
|
||||
|
||||
class OpacityPropertyHandle final {
|
||||
public:
|
||||
~OpacityPropertyHandle();
|
||||
|
||||
float getOpacity() const;
|
||||
void setOpacity(float);
|
||||
|
||||
private:
|
||||
explicit OpacityPropertyHandle(sk_sp<sksg::OpacityEffect>);
|
||||
|
||||
friend class skottie::internal::AnimationBuilder;
|
||||
|
||||
const sk_sp<sksg::OpacityEffect> fOpacity;
|
||||
};
|
||||
|
||||
class TransformAdapter;
|
||||
|
||||
class TransformPropertyHandle final {
|
||||
public:
|
||||
~TransformPropertyHandle();
|
||||
|
||||
SkPoint getAnchorPoint() const;
|
||||
void setAnchorPoint(const SkPoint&);
|
||||
|
||||
SkPoint getPosition() const;
|
||||
void setPosition(const SkPoint&);
|
||||
|
||||
SkVector getScale() const;
|
||||
void setScale(const SkVector&);
|
||||
|
||||
SkScalar getRotation() const;
|
||||
void setRotation(SkScalar);
|
||||
|
||||
SkScalar getSkew() const;
|
||||
void setSkew(SkScalar);
|
||||
|
||||
SkScalar getSkewAxis() const;
|
||||
void setSkewAxis(SkScalar);
|
||||
|
||||
SkMatrix getTotalMatrix() const;
|
||||
|
||||
private:
|
||||
explicit TransformPropertyHandle(sk_sp<TransformAdapter>);
|
||||
|
||||
friend class skottie::internal::AnimationBuilder;
|
||||
|
||||
const sk_sp<TransformAdapter> fTransform;
|
||||
};
|
||||
|
||||
} // namespace skottie
|
||||
|
||||
#endif // SkottieProperty_DEFINED
|
@ -7,10 +7,7 @@
|
||||
_src = get_path_info("src", "abspath")
|
||||
_include = get_path_info("include", "abspath")
|
||||
|
||||
skia_skottie_public = [
|
||||
"$_include/Skottie.h",
|
||||
"$_include/SkottieProperty.h",
|
||||
]
|
||||
skia_skottie_public = [ "$_include/Skottie.h" ]
|
||||
|
||||
skia_skottie_sources = [
|
||||
"$_src/Skottie.cpp",
|
||||
@ -23,7 +20,6 @@ skia_skottie_sources = [
|
||||
"$_src/SkottieLayerEffect.cpp",
|
||||
"$_src/SkottiePriv.h",
|
||||
"$_src/SkottiePrecompLayer.cpp",
|
||||
"$_src/SkottieProperty.cpp",
|
||||
"$_src/SkottieShapeLayer.cpp",
|
||||
"$_src/SkottieTextLayer.cpp",
|
||||
"$_src/SkottieValue.cpp",
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "SkottieAdapter.h"
|
||||
#include "SkottieJson.h"
|
||||
#include "SkottiePriv.h"
|
||||
#include "SkottieProperty.h"
|
||||
#include "SkottieValue.h"
|
||||
|
||||
#include <cmath>
|
||||
@ -84,9 +83,7 @@ sk_sp<sksg::Matrix> AnimationBuilder::attachMatrix(const skjson::ObjectValue& t,
|
||||
adapter->setSkewAxis(sa);
|
||||
}, 0.0f);
|
||||
|
||||
const auto dispatched = this->dispatchTransformProperty(adapter);
|
||||
|
||||
return (bound || dispatched) ? matrix : parentMatrix;
|
||||
return bound ? matrix : parentMatrix;
|
||||
}
|
||||
|
||||
sk_sp<sksg::RenderNode> AnimationBuilder::attachOpacity(const skjson::ObjectValue& jtransform,
|
||||
@ -97,15 +94,16 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachOpacity(const skjson::ObjectValu
|
||||
|
||||
auto opacityNode = sksg::OpacityEffect::Make(childNode);
|
||||
|
||||
const auto bound = this->bindProperty<ScalarValue>(jtransform["o"], ascope,
|
||||
if (!this->bindProperty<ScalarValue>(jtransform["o"], ascope,
|
||||
[opacityNode](const ScalarValue& o) {
|
||||
// BM opacity is [0..100]
|
||||
opacityNode->setOpacity(o * 0.01f);
|
||||
}, 100.0f);
|
||||
const auto dispatched = this->dispatchOpacityProperty(opacityNode);
|
||||
}, 100.0f)) {
|
||||
// We can ignore static full opacity.
|
||||
return childNode;
|
||||
}
|
||||
|
||||
// We can ignore constant full opacity.
|
||||
return (bound || dispatched) ? std::move(opacityNode) : childNode;
|
||||
return std::move(opacityNode);
|
||||
}
|
||||
|
||||
sk_sp<sksg::Path> AnimationBuilder::attachPath(const skjson::Value& jpath,
|
||||
@ -126,23 +124,19 @@ sk_sp<sksg::Color> AnimationBuilder::attachColor(const skjson::ObjectValue& jcol
|
||||
AnimatorScope* ascope,
|
||||
const char prop_name[]) const {
|
||||
auto color_node = sksg::Color::Make(SK_ColorBLACK);
|
||||
|
||||
this->bindProperty<VectorValue>(jcolor[prop_name], ascope,
|
||||
[color_node](const VectorValue& c) {
|
||||
color_node->setColor(ValueTraits<VectorValue>::As<SkColor>(c));
|
||||
});
|
||||
this->dispatchColorProperty(color_node);
|
||||
|
||||
return color_node;
|
||||
}
|
||||
|
||||
AnimationBuilder::AnimationBuilder(sk_sp<ResourceProvider> rp, sk_sp<SkFontMgr> fontmgr,
|
||||
sk_sp<PropertyObserver> pobserver,
|
||||
Animation::Builder::Stats* stats,
|
||||
float duration, float framerate)
|
||||
: fResourceProvider(std::move(rp))
|
||||
, fLazyFontMgr(std::move(fontmgr))
|
||||
, fPropertyObserver(std::move(pobserver))
|
||||
, fStats(stats)
|
||||
, fDuration(duration)
|
||||
, fFrameRate(framerate) {}
|
||||
@ -171,56 +165,6 @@ void AnimationBuilder::parseAssets(const skjson::ArrayValue* jassets) {
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimationBuilder::dispatchColorProperty(const sk_sp<sksg::Color>& c) const {
|
||||
bool dispatched = false;
|
||||
|
||||
if (fPropertyObserver) {
|
||||
fPropertyObserver->onColorProperty(fPropertyObserverContext,
|
||||
[&]() {
|
||||
dispatched = true;
|
||||
return std::unique_ptr<ColorPropertyHandle>(new ColorPropertyHandle(c));
|
||||
});
|
||||
}
|
||||
|
||||
return dispatched;
|
||||
}
|
||||
|
||||
bool AnimationBuilder::dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>& o) const {
|
||||
bool dispatched = false;
|
||||
|
||||
if (fPropertyObserver) {
|
||||
fPropertyObserver->onOpacityProperty(fPropertyObserverContext,
|
||||
[&]() {
|
||||
dispatched = true;
|
||||
return std::unique_ptr<OpacityPropertyHandle>(new OpacityPropertyHandle(o));
|
||||
});
|
||||
}
|
||||
|
||||
return dispatched;
|
||||
}
|
||||
|
||||
bool AnimationBuilder::dispatchTransformProperty(const sk_sp<TransformAdapter>& t) const {
|
||||
bool dispatched = false;
|
||||
|
||||
if (fPropertyObserver) {
|
||||
fPropertyObserver->onTransformProperty(fPropertyObserverContext,
|
||||
[&]() {
|
||||
dispatched = true;
|
||||
return std::unique_ptr<TransformPropertyHandle>(new TransformPropertyHandle(t));
|
||||
});
|
||||
}
|
||||
|
||||
return dispatched;
|
||||
}
|
||||
|
||||
void AnimationBuilder::AutoPropertyTracker::updateContext(PropertyObserver* observer,
|
||||
const skjson::ObjectValue& obj) {
|
||||
|
||||
const skjson::StringValue* name = obj["nm"];
|
||||
|
||||
fBuilder->fPropertyObserverContext = name ? name->begin() : nullptr;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
sk_sp<SkData> ResourceProvider::load(const char[], const char[]) const {
|
||||
@ -231,9 +175,6 @@ sk_sp<SkData> ResourceProvider::loadWebFont(const char[]) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Animation::Builder::Builder() = default;
|
||||
Animation::Builder::~Builder() = default;
|
||||
|
||||
Animation::Builder& Animation::Builder::setResourceProvider(sk_sp<ResourceProvider> rp) {
|
||||
fResourceProvider = std::move(rp);
|
||||
return *this;
|
||||
@ -244,11 +185,6 @@ Animation::Builder& Animation::Builder::setFontManager(sk_sp<SkFontMgr> fmgr) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Animation::Builder& Animation::Builder::setPropertyObserver(sk_sp<PropertyObserver> pobserver) {
|
||||
fPropertyObserver = std::move(pobserver);
|
||||
return *this;
|
||||
}
|
||||
|
||||
sk_sp<Animation> Animation::Builder::make(SkStream* stream) {
|
||||
if (!stream->hasLength()) {
|
||||
// TODO: handle explicit buffering?
|
||||
@ -307,7 +243,7 @@ sk_sp<Animation> Animation::Builder::make(const char* data, size_t data_len) {
|
||||
|
||||
SkASSERT(resolvedProvider);
|
||||
internal::AnimationBuilder builder(std::move(resolvedProvider), fFontMgr,
|
||||
std::move(fPropertyObserver), &fStats, duration, fps);
|
||||
&fStats, duration, fps);
|
||||
auto scene = builder.parse(json);
|
||||
|
||||
const auto t2 = SkTime::GetMSecs();
|
||||
|
@ -43,7 +43,7 @@ void RRectAdapter::apply() {
|
||||
TransformAdapter::TransformAdapter(sk_sp<sksg::Matrix> matrix)
|
||||
: fMatrixNode(std::move(matrix)) {}
|
||||
|
||||
SkMatrix TransformAdapter::totalMatrix() const {
|
||||
void TransformAdapter::apply() {
|
||||
SkMatrix t = SkMatrix::MakeTrans(-fAnchorPoint.x(), -fAnchorPoint.y());
|
||||
|
||||
t.postScale(fScale.x() / 100, fScale.y() / 100); // 100% based
|
||||
@ -51,11 +51,7 @@ SkMatrix TransformAdapter::totalMatrix() const {
|
||||
t.postTranslate(fPosition.x(), fPosition.y());
|
||||
// TODO: skew
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void TransformAdapter::apply() {
|
||||
fMatrixNode->setMatrix(this->totalMatrix());
|
||||
fMatrixNode->setMatrix(t);
|
||||
}
|
||||
|
||||
PolyStarAdapter::PolyStarAdapter(sk_sp<sksg::Path> wrapped_node, Type t)
|
||||
|
@ -32,9 +32,6 @@ class TrimEffect;
|
||||
namespace skottie {
|
||||
|
||||
#define ADAPTER_PROPERTY(p_name, p_type, p_default) \
|
||||
const p_type& get##p_name() const { \
|
||||
return f##p_name; \
|
||||
} \
|
||||
void set##p_name(const p_type& p) { \
|
||||
if (p == f##p_name) return; \
|
||||
f##p_name = p; \
|
||||
@ -96,8 +93,6 @@ public:
|
||||
ADAPTER_PROPERTY(Skew , SkScalar, 0)
|
||||
ADAPTER_PROPERTY(SkewAxis , SkScalar, 0)
|
||||
|
||||
SkMatrix totalMatrix() const;
|
||||
|
||||
private:
|
||||
void apply();
|
||||
|
||||
|
@ -408,8 +408,6 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachLayer(const skjson::ObjectValue*
|
||||
AttachLayerContext* layerCtx) const {
|
||||
if (!jlayer) return nullptr;
|
||||
|
||||
const AutoPropertyTracker apt(this, *jlayer);
|
||||
|
||||
using LayerAttacher = sk_sp<sksg::RenderNode> (AnimationBuilder::*)(const skjson::ObjectValue&,
|
||||
AnimatorScope*) const;
|
||||
static constexpr LayerAttacher gLayerAttachers[] = {
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "Skottie.h"
|
||||
|
||||
#include "SkFontStyle.h"
|
||||
#include "SkottieProperty.h"
|
||||
#include "SkSGScene.h"
|
||||
#include "SkString.h"
|
||||
#include "SkTHash.h"
|
||||
@ -45,8 +44,8 @@ using AnimatorScope = sksg::AnimatorList;
|
||||
|
||||
class AnimationBuilder final : public SkNoncopyable {
|
||||
public:
|
||||
AnimationBuilder(sk_sp<ResourceProvider>, sk_sp<SkFontMgr>, sk_sp<PropertyObserver>,
|
||||
Animation::Builder::Stats*, float duration, float framerate);
|
||||
AnimationBuilder(sk_sp<ResourceProvider>, sk_sp<SkFontMgr>, Animation::Builder::Stats*,
|
||||
float duration, float framerate);
|
||||
|
||||
std::unique_ptr<sksg::Scene> parse(const skjson::ObjectValue&);
|
||||
|
||||
@ -78,7 +77,6 @@ public:
|
||||
|
||||
private:
|
||||
struct AttachLayerContext;
|
||||
struct AttachShapeContext;
|
||||
|
||||
void parseAssets(const skjson::ArrayValue*);
|
||||
void parseFonts (const skjson::ObjectValue* jfonts,
|
||||
@ -89,7 +87,6 @@ private:
|
||||
sk_sp<sksg::RenderNode> attachLayerEffects(const skjson::ArrayValue& jeffects, AnimatorScope*,
|
||||
sk_sp<sksg::RenderNode>) const;
|
||||
|
||||
sk_sp<sksg::RenderNode> attachShape(const skjson::ArrayValue*, AttachShapeContext*) const;
|
||||
sk_sp<sksg::RenderNode> attachAssetRef(const skjson::ObjectValue&, AnimatorScope*,
|
||||
sk_sp<sksg::RenderNode>(AnimationBuilder::*)(const skjson::ObjectValue&,
|
||||
AnimatorScope* ctx) const) const;
|
||||
@ -104,10 +101,6 @@ private:
|
||||
sk_sp<sksg::RenderNode> attachSolidLayer (const skjson::ObjectValue&, AnimatorScope*) const;
|
||||
sk_sp<sksg::RenderNode> attachTextLayer (const skjson::ObjectValue&, AnimatorScope*) const;
|
||||
|
||||
bool dispatchColorProperty(const sk_sp<sksg::Color>&) const;
|
||||
bool dispatchOpacityProperty(const sk_sp<sksg::OpacityEffect>&) const;
|
||||
bool dispatchTransformProperty(const sk_sp<TransformAdapter>&) const;
|
||||
|
||||
// Delay resolving the fontmgr until it is actually needed.
|
||||
struct LazyResolveFontMgr {
|
||||
LazyResolveFontMgr(sk_sp<SkFontMgr> fontMgr) : fFontMgr(std::move(fontMgr)) {}
|
||||
@ -126,37 +119,12 @@ private:
|
||||
sk_sp<SkFontMgr> fFontMgr;
|
||||
};
|
||||
|
||||
class AutoPropertyTracker {
|
||||
public:
|
||||
AutoPropertyTracker(const AnimationBuilder* builder, const skjson::ObjectValue& obj)
|
||||
: fBuilder(builder)
|
||||
, fPrevContext(builder->fPropertyObserverContext) {
|
||||
if (fBuilder->fPropertyObserver) {
|
||||
this->updateContext(builder->fPropertyObserver.get(), obj);
|
||||
}
|
||||
}
|
||||
|
||||
~AutoPropertyTracker() {
|
||||
if (fBuilder->fPropertyObserver) {
|
||||
fBuilder->fPropertyObserverContext = fPrevContext;
|
||||
}
|
||||
}
|
||||
private:
|
||||
void updateContext(PropertyObserver*, const skjson::ObjectValue&);
|
||||
|
||||
const AnimationBuilder* fBuilder;
|
||||
const char* fPrevContext;
|
||||
};
|
||||
|
||||
sk_sp<ResourceProvider> fResourceProvider;
|
||||
LazyResolveFontMgr fLazyFontMgr;
|
||||
sk_sp<PropertyObserver> fPropertyObserver;
|
||||
Animation::Builder::Stats* fStats;
|
||||
const float fDuration,
|
||||
fFrameRate;
|
||||
|
||||
mutable const char* fPropertyObserverContext;
|
||||
|
||||
struct AssetInfo {
|
||||
const skjson::ObjectValue* fAsset;
|
||||
mutable bool fIsAttaching; // Used for cycle detection
|
||||
|
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkottieProperty.h"
|
||||
|
||||
#include "SkottieAdapter.h"
|
||||
#include "SkSGColor.h"
|
||||
#include "SkSGOpacityEffect.h"
|
||||
|
||||
namespace skottie {
|
||||
|
||||
ColorPropertyHandle::ColorPropertyHandle(sk_sp<sksg::Color> color)
|
||||
: fColor(std::move(color)) {
|
||||
SkASSERT(fColor);
|
||||
}
|
||||
|
||||
ColorPropertyHandle::~ColorPropertyHandle() = default;
|
||||
|
||||
SkColor ColorPropertyHandle::getColor() const {
|
||||
return fColor->getColor();
|
||||
}
|
||||
|
||||
void ColorPropertyHandle::setColor(SkColor color) {
|
||||
fColor->setColor(color);
|
||||
}
|
||||
|
||||
OpacityPropertyHandle::OpacityPropertyHandle(sk_sp<sksg::OpacityEffect> opacity)
|
||||
: fOpacity(std::move(opacity)) {
|
||||
SkASSERT(fOpacity);
|
||||
}
|
||||
|
||||
OpacityPropertyHandle::~OpacityPropertyHandle() = default;
|
||||
|
||||
float OpacityPropertyHandle::getOpacity() const {
|
||||
return fOpacity->getOpacity() * 100;
|
||||
}
|
||||
|
||||
void OpacityPropertyHandle::setOpacity(float opacity) {
|
||||
fOpacity->setOpacity(opacity / 100);
|
||||
}
|
||||
|
||||
TransformPropertyHandle::TransformPropertyHandle(sk_sp<TransformAdapter> transform)
|
||||
: fTransform(std::move(transform)) {
|
||||
SkASSERT(fTransform);
|
||||
}
|
||||
|
||||
TransformPropertyHandle::~TransformPropertyHandle() = default;
|
||||
|
||||
SkPoint TransformPropertyHandle::getAnchorPoint() const {
|
||||
return fTransform->getAnchorPoint();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setAnchorPoint(const SkPoint& ap) {
|
||||
fTransform->setAnchorPoint(ap);
|
||||
}
|
||||
|
||||
SkPoint TransformPropertyHandle::getPosition() const {
|
||||
return fTransform->getPosition();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setPosition(const SkPoint& position) {
|
||||
fTransform->setPosition(position);
|
||||
}
|
||||
|
||||
SkVector TransformPropertyHandle::getScale() const {
|
||||
return fTransform->getScale();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setScale(const SkVector& scale) {
|
||||
fTransform->setScale(scale);
|
||||
}
|
||||
|
||||
SkScalar TransformPropertyHandle::getRotation() const {
|
||||
return fTransform->getRotation();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setRotation(SkScalar rotation) {
|
||||
fTransform->setRotation(rotation);
|
||||
}
|
||||
|
||||
SkScalar TransformPropertyHandle::getSkew() const {
|
||||
return fTransform->getSkew();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setSkew(SkScalar skew) {
|
||||
fTransform->setSkew(skew);
|
||||
}
|
||||
|
||||
SkScalar TransformPropertyHandle::getSkewAxis() const {
|
||||
return fTransform->getSkewAxis();
|
||||
}
|
||||
|
||||
void TransformPropertyHandle::setSkewAxis(SkScalar sa) {
|
||||
fTransform->setSkewAxis(sa);
|
||||
}
|
||||
|
||||
SkMatrix TransformPropertyHandle::getTotalMatrix() const {
|
||||
return fTransform->totalMatrix();
|
||||
}
|
||||
|
||||
void PropertyObserver::onColorProperty(const char[],
|
||||
const LazyHandle<ColorPropertyHandle>&) {}
|
||||
|
||||
void PropertyObserver::onOpacityProperty(const char[],
|
||||
const LazyHandle<OpacityPropertyHandle>&) {}
|
||||
|
||||
void PropertyObserver::onTransformProperty(const char[],
|
||||
const LazyHandle<TransformPropertyHandle>&) {}
|
||||
|
||||
} // namespace skottie
|
@ -430,26 +430,26 @@ struct GeometryEffectRec {
|
||||
GeometryEffectAttacherT fAttach;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
struct AnimationBuilder::AttachShapeContext {
|
||||
AttachShapeContext(AnimatorScope* ascope,
|
||||
struct AttachShapeContext {
|
||||
AttachShapeContext(const AnimationBuilder* abuilder,
|
||||
AnimatorScope* ascope,
|
||||
std::vector<sk_sp<sksg::GeometryNode>>* geos,
|
||||
std::vector<GeometryEffectRec>* effects,
|
||||
size_t committedAnimators)
|
||||
: fScope(ascope)
|
||||
: fBuilder(abuilder)
|
||||
, fScope(ascope)
|
||||
, fGeometryStack(geos)
|
||||
, fGeometryEffectStack(effects)
|
||||
, fCommittedAnimators(committedAnimators) {}
|
||||
|
||||
const AnimationBuilder* fBuilder;
|
||||
AnimatorScope* fScope;
|
||||
std::vector<sk_sp<sksg::GeometryNode>>* fGeometryStack;
|
||||
std::vector<GeometryEffectRec>* fGeometryEffectStack;
|
||||
size_t fCommittedAnimators;
|
||||
};
|
||||
|
||||
sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue* jshape,
|
||||
AttachShapeContext* ctx) const {
|
||||
sk_sp<sksg::RenderNode> AttachShape(const skjson::ArrayValue* jshape, AttachShapeContext* ctx) {
|
||||
if (!jshape)
|
||||
return nullptr;
|
||||
|
||||
@ -504,13 +504,11 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
std::vector<sk_sp<sksg::GeometryNode>> geos;
|
||||
std::vector<sk_sp<sksg::RenderNode >> draws;
|
||||
for (auto rec = recs.rbegin(); rec != recs.rend(); ++rec) {
|
||||
const AutoPropertyTracker apt(this, rec->fJson);
|
||||
|
||||
switch (rec->fInfo.fShapeType) {
|
||||
case ShapeType::kGeometry: {
|
||||
SkASSERT(rec->fInfo.fAttacherIndex < SK_ARRAY_COUNT(gGeometryAttachers));
|
||||
if (auto geo = gGeometryAttachers[rec->fInfo.fAttacherIndex](rec->fJson,
|
||||
this,
|
||||
ctx->fBuilder,
|
||||
ctx->fScope)) {
|
||||
geos.push_back(std::move(geo));
|
||||
}
|
||||
@ -520,7 +518,7 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
SkASSERT(rec->fInfo.fAttacherIndex < SK_ARRAY_COUNT(gGeometryEffectAttachers));
|
||||
if (!geos.empty()) {
|
||||
geos = gGeometryEffectAttachers[rec->fInfo.fAttacherIndex](rec->fJson,
|
||||
this,
|
||||
ctx->fBuilder,
|
||||
ctx->fScope,
|
||||
std::move(geos));
|
||||
}
|
||||
@ -531,11 +529,12 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
ctx->fGeometryEffectStack->pop_back();
|
||||
} break;
|
||||
case ShapeType::kGroup: {
|
||||
AttachShapeContext groupShapeCtx(ctx->fScope,
|
||||
AttachShapeContext groupShapeCtx(ctx->fBuilder,
|
||||
ctx->fScope,
|
||||
&geos,
|
||||
ctx->fGeometryEffectStack,
|
||||
ctx->fCommittedAnimators);
|
||||
if (auto subgroup = this->attachShape(rec->fJson["it"], &groupShapeCtx)) {
|
||||
if (auto subgroup = AttachShape(rec->fJson["it"], &groupShapeCtx)) {
|
||||
draws.push_back(std::move(subgroup));
|
||||
SkASSERT(groupShapeCtx.fCommittedAnimators >= ctx->fCommittedAnimators);
|
||||
ctx->fCommittedAnimators = groupShapeCtx.fCommittedAnimators;
|
||||
@ -544,7 +543,7 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
case ShapeType::kPaint: {
|
||||
SkASSERT(rec->fInfo.fAttacherIndex < SK_ARRAY_COUNT(gPaintAttachers));
|
||||
auto paint = gPaintAttachers[rec->fInfo.fAttacherIndex](rec->fJson,
|
||||
this,
|
||||
ctx->fBuilder,
|
||||
ctx->fScope);
|
||||
if (!paint || geos.empty())
|
||||
break;
|
||||
@ -554,7 +553,7 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
// Apply all pending effects from the stack.
|
||||
for (auto it = ctx->fGeometryEffectStack->rbegin();
|
||||
it != ctx->fGeometryEffectStack->rend(); ++it) {
|
||||
drawGeos = it->fAttach(it->fJson, this, ctx->fScope, std::move(drawGeos));
|
||||
drawGeos = it->fAttach(it->fJson, ctx->fBuilder, ctx->fScope, std::move(drawGeos));
|
||||
}
|
||||
|
||||
// If we still have multiple geos, reduce using 'merge'.
|
||||
@ -589,17 +588,16 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
|
||||
sk_sp<sksg::Matrix> shape_matrix;
|
||||
if (jtransform) {
|
||||
const AutoPropertyTracker apt(this, *jtransform);
|
||||
|
||||
// This is tricky due to the interaction with ctx->fCommittedAnimators: we want any
|
||||
// animators related to tranform/opacity to be committed => they must be inserted in front
|
||||
// of the dangling/uncommitted ones.
|
||||
AnimatorScope local_scope;
|
||||
|
||||
if ((shape_matrix = this->attachMatrix(*jtransform, &local_scope, nullptr))) {
|
||||
if ((shape_matrix = ctx->fBuilder->attachMatrix(*jtransform, &local_scope, nullptr))) {
|
||||
shape_wrapper = sksg::Transform::Make(std::move(shape_wrapper), shape_matrix);
|
||||
}
|
||||
shape_wrapper = this->attachOpacity(*jtransform, &local_scope, std::move(shape_wrapper));
|
||||
shape_wrapper = ctx->fBuilder->attachOpacity(*jtransform, &local_scope,
|
||||
std::move(shape_wrapper));
|
||||
|
||||
ctx->fScope->insert(ctx->fScope->begin() + ctx->fCommittedAnimators,
|
||||
std::make_move_iterator(local_scope.begin()),
|
||||
@ -617,12 +615,14 @@ sk_sp<sksg::RenderNode> AnimationBuilder::attachShape(const skjson::ArrayValue*
|
||||
return shape_wrapper;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
sk_sp<sksg::RenderNode> AnimationBuilder::attachShapeLayer(const skjson::ObjectValue& layer,
|
||||
AnimatorScope* ascope) const {
|
||||
std::vector<sk_sp<sksg::GeometryNode>> geometryStack;
|
||||
std::vector<GeometryEffectRec> geometryEffectStack;
|
||||
AttachShapeContext shapeCtx(ascope, &geometryStack, &geometryEffectStack, ascope->size());
|
||||
auto shapeNode = this->attachShape(layer["shapes"], &shapeCtx);
|
||||
AttachShapeContext shapeCtx(this, ascope, &geometryStack, &geometryEffectStack, ascope->size());
|
||||
auto shapeNode = AttachShape(layer["shapes"], &shapeCtx);
|
||||
|
||||
// Trim uncommitted animators: AttachShape consumes effects on the fly, and greedily attaches
|
||||
// geometries => at the end, we can end up with unused geometries, which are nevertheless alive
|
||||
|
@ -5,19 +5,13 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkMatrix.h"
|
||||
#include "Skottie.h"
|
||||
#include "SkottieProperty.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
#include "Test.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace skottie;
|
||||
|
||||
DEF_TEST(Skottie_OssFuzz8956, reporter) {
|
||||
static constexpr char json[] =
|
||||
static constexpr const char json[] =
|
||||
"{\"v\":\" \",\"fr\":3,\"w\":4,\"h\":3,\"layers\":[{\"ty\": 1, \"sw\": 10, \"sh\": 10,"
|
||||
" \"sc\":\"#ffffff\", \"ks\":{\"o\":{\"a\": true, \"k\":"
|
||||
" [{\"t\": 0, \"s\": 0, \"e\": 1, \"i\": {\"x\":[]}}]}}}]}";
|
||||
@ -25,117 +19,5 @@ DEF_TEST(Skottie_OssFuzz8956, reporter) {
|
||||
SkMemoryStream stream(json, strlen(json));
|
||||
|
||||
// Passes if parsing doesn't crash.
|
||||
auto animation = Animation::Make(&stream);
|
||||
}
|
||||
|
||||
DEF_TEST(Skottie_Properties, reporter) {
|
||||
static constexpr char json[] = R"({
|
||||
"v": "5.2.1",
|
||||
"w": 100,
|
||||
"h": 100,
|
||||
"fr": 1,
|
||||
"ip": 0,
|
||||
"op": 1,
|
||||
"layers": [
|
||||
{
|
||||
"ty": 4,
|
||||
"nm": "layer_0",
|
||||
"ind": 0,
|
||||
"ip": 0,
|
||||
"op": 1,
|
||||
"ks": {
|
||||
"o": { "a": 0, "k": 50 }
|
||||
},
|
||||
"shapes": [
|
||||
{
|
||||
"ty": "el",
|
||||
"nm": "geometry_0",
|
||||
"p": { "a": 0, "k": [ 50, 50 ] },
|
||||
"s": { "a": 0, "k": [ 50, 50 ] }
|
||||
},
|
||||
{
|
||||
"ty": "fl",
|
||||
"nm": "fill_0",
|
||||
"c": { "a": 0, "k": [ 1, 0, 0] }
|
||||
},
|
||||
{
|
||||
"ty": "tr",
|
||||
"nm": "shape_transform_0",
|
||||
"o": { "a": 0, "k": 100 },
|
||||
"s": { "a": 0, "k": [ 50, 50 ] }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})";
|
||||
|
||||
class TestPropertyObserver final : public PropertyObserver {
|
||||
public:
|
||||
struct ColorInfo {
|
||||
const char* node_name;
|
||||
SkColor color;
|
||||
};
|
||||
|
||||
struct OpacityInfo {
|
||||
const char* node_name;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
struct TransformInfo {
|
||||
const char* node_name;
|
||||
SkMatrix matrix;
|
||||
};
|
||||
|
||||
void onColorProperty(const char node_name[],
|
||||
const PropertyObserver::LazyHandle<ColorPropertyHandle>& lh) override {
|
||||
fColors.push_back({node_name, lh()->getColor()});
|
||||
}
|
||||
|
||||
void onOpacityProperty(const char node_name[],
|
||||
const PropertyObserver::LazyHandle<OpacityPropertyHandle>& lh) override {
|
||||
fOpacities.push_back({node_name, lh()->getOpacity()});
|
||||
}
|
||||
|
||||
void onTransformProperty(const char node_name[],
|
||||
const PropertyObserver::LazyHandle<TransformPropertyHandle>& lh) override {
|
||||
fTransforms.push_back({node_name, lh()->getTotalMatrix()});
|
||||
}
|
||||
|
||||
const std::vector<ColorInfo>& colors() const { return fColors; }
|
||||
const std::vector<OpacityInfo>& opacities() const { return fOpacities; }
|
||||
const std::vector<TransformInfo>& transforms() const { return fTransforms; }
|
||||
|
||||
private:
|
||||
std::vector<ColorInfo> fColors;
|
||||
std::vector<OpacityInfo> fOpacities;
|
||||
std::vector<TransformInfo> fTransforms;
|
||||
};
|
||||
|
||||
SkMemoryStream stream(json, strlen(json));
|
||||
auto observer = sk_make_sp<TestPropertyObserver>();
|
||||
|
||||
auto animation = skottie::Animation::Builder()
|
||||
.setPropertyObserver(observer)
|
||||
.make(&stream);
|
||||
|
||||
REPORTER_ASSERT(reporter, animation);
|
||||
|
||||
const auto& colors = observer->colors();
|
||||
REPORTER_ASSERT(reporter, colors.size() == 1);
|
||||
REPORTER_ASSERT(reporter, !strcmp(colors[0].node_name, "fill_0"));
|
||||
REPORTER_ASSERT(reporter, colors[0].color == 0xffff0000);
|
||||
|
||||
const auto& opacities = observer->opacities();
|
||||
REPORTER_ASSERT(reporter, opacities.size() == 2);
|
||||
REPORTER_ASSERT(reporter, !strcmp(opacities[0].node_name, "shape_transform_0"));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(opacities[0].opacity, 100));
|
||||
REPORTER_ASSERT(reporter, !strcmp(opacities[1].node_name, "layer_0"));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(opacities[1].opacity, 50));
|
||||
|
||||
const auto& transforms = observer->transforms();
|
||||
REPORTER_ASSERT(reporter, transforms.size() == 2);
|
||||
REPORTER_ASSERT(reporter, !strcmp(transforms[0].node_name, "shape_transform_0"));
|
||||
REPORTER_ASSERT(reporter, transforms[0].matrix == SkMatrix::MakeScale(0.5, 0.5));
|
||||
REPORTER_ASSERT(reporter, !strcmp(transforms[1].node_name, "layer_0"));
|
||||
REPORTER_ASSERT(reporter, transforms[1].matrix == SkMatrix::I());
|
||||
auto animation = skottie::Animation::Make(&stream);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user