mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
lottie: support layer effect & gaussian blur
issue: https://github.com/thorvg/thorvg/issues/2718
This commit is contained in:
parent
ece0d8c7e1
commit
ab8b4ef73e
7 changed files with 148 additions and 5 deletions
|
@ -1191,6 +1191,24 @@ bool LottieBuilder::updateMatte(LottieComposition* comp, float frameNo, Scene* s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LottieBuilder::updateEffect(LottieLayer* layer, float frameNo)
|
||||||
|
{
|
||||||
|
if (layer->effects.count == 0) return;
|
||||||
|
|
||||||
|
for (auto ef = layer->effects.begin(); ef < layer->effects.end(); ++ef) {
|
||||||
|
if (!(*ef)->enable) continue;
|
||||||
|
switch ((*ef)->type) {
|
||||||
|
case LottieEffect::GaussianBlur: {
|
||||||
|
auto effect = static_cast<LottieGaussianBlur*>(*ef);
|
||||||
|
layer->scene->push(SceneEffect::GaussianBlur, sqrt(effect->blurness(frameNo)), effect->direction(frameNo) - 1, effect->wrap(frameNo), 50);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LottieBuilder::updateLayer(LottieComposition* comp, Scene* scene, LottieLayer* layer, float frameNo)
|
void LottieBuilder::updateLayer(LottieComposition* comp, Scene* scene, LottieLayer* layer, float frameNo)
|
||||||
{
|
{
|
||||||
layer->scene = nullptr;
|
layer->scene = nullptr;
|
||||||
|
@ -1246,6 +1264,8 @@ void LottieBuilder::updateLayer(LottieComposition* comp, Scene* scene, LottieLay
|
||||||
|
|
||||||
layer->scene->blend(layer->blendMethod);
|
layer->scene->blend(layer->blendMethod);
|
||||||
|
|
||||||
|
updateEffect(layer, frameNo);
|
||||||
|
|
||||||
//the given matte source was composited by the target earlier.
|
//the given matte source was composited by the target earlier.
|
||||||
if (!layer->matteSrc) scene->push(cast(layer->scene));
|
if (!layer->matteSrc) scene->push(cast(layer->scene));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,7 @@ struct LottieBuilder
|
||||||
void build(LottieComposition* comp);
|
void build(LottieComposition* comp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateEffect(LottieLayer* layer, float frameNo);
|
||||||
void updateLayer(LottieComposition* comp, Scene* scene, LottieLayer* layer, float frameNo);
|
void updateLayer(LottieComposition* comp, Scene* scene, LottieLayer* layer, float frameNo);
|
||||||
bool updateMatte(LottieComposition* comp, float frameNo, Scene* scene, LottieLayer* layer);
|
bool updateMatte(LottieComposition* comp, float frameNo, Scene* scene, LottieLayer* layer);
|
||||||
void updatePrecomp(LottieComposition* comp, LottieLayer* precomp, float frameNo);
|
void updatePrecomp(LottieComposition* comp, LottieLayer* precomp, float frameNo);
|
||||||
|
|
|
@ -400,6 +400,10 @@ LottieLayer::~LottieLayer()
|
||||||
delete(*m);
|
delete(*m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto e = effects.begin(); e < effects.end(); ++e) {
|
||||||
|
delete(*e);
|
||||||
|
}
|
||||||
|
|
||||||
delete(transform);
|
delete(transform);
|
||||||
free(name);
|
free(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,33 @@ struct LottieStroke
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct LottieEffect
|
||||||
|
{
|
||||||
|
enum Type : uint8_t
|
||||||
|
{
|
||||||
|
GaussianBlur = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~LottieEffect() {}
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
bool enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct LottieGaussianBlur : LottieEffect
|
||||||
|
{
|
||||||
|
LottieSlider blurness = 0.0f;
|
||||||
|
LottieCheckbox direction = 0;
|
||||||
|
LottieCheckbox wrap = 0;
|
||||||
|
|
||||||
|
LottieGaussianBlur()
|
||||||
|
{
|
||||||
|
type = GaussianBlur;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LottieMask
|
struct LottieMask
|
||||||
{
|
{
|
||||||
LottiePathSet pathset;
|
LottiePathSet pathset;
|
||||||
|
@ -737,6 +764,7 @@ struct LottieLayer : LottieGroup
|
||||||
LottieLayer* comp = nullptr; //Precompositor, current layer is belonges.
|
LottieLayer* comp = nullptr; //Precompositor, current layer is belonges.
|
||||||
LottieTransform* transform = nullptr;
|
LottieTransform* transform = nullptr;
|
||||||
Array<LottieMask*> masks;
|
Array<LottieMask*> masks;
|
||||||
|
Array<LottieEffect*> effects;
|
||||||
LottieLayer* matteTarget = nullptr;
|
LottieLayer* matteTarget = nullptr;
|
||||||
|
|
||||||
LottieRenderPooler<tvg::Shape> statical; //static pooler for solid fill and clipper
|
LottieRenderPooler<tvg::Shape> statical; //static pooler for solid fill and clipper
|
||||||
|
|
|
@ -57,6 +57,15 @@ static unsigned long _int2str(int num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LottieEffect* LottieParser::getEffect(int type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case 29: return new LottieGaussianBlur;
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CompositeMethod LottieParser::getMaskMethod(bool inversed)
|
CompositeMethod LottieParser::getMaskMethod(bool inversed)
|
||||||
{
|
{
|
||||||
auto mode = getString();
|
auto mode = getString();
|
||||||
|
@ -263,6 +272,19 @@ void LottieParser::getValue(Array<Point>& pts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LottieParser::getValue(int8_t& val)
|
||||||
|
{
|
||||||
|
if (peekType() == kArrayType) {
|
||||||
|
enterArray();
|
||||||
|
if (nextArrayValue()) val = getInt();
|
||||||
|
//discard rest
|
||||||
|
while (nextArrayValue()) getInt();
|
||||||
|
} else {
|
||||||
|
val = getFloat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LottieParser::getValue(uint8_t& val)
|
void LottieParser::getValue(uint8_t& val)
|
||||||
{
|
{
|
||||||
if (peekType() == kArrayType) {
|
if (peekType() == kArrayType) {
|
||||||
|
@ -1233,6 +1255,70 @@ void LottieParser::parseMasks(LottieLayer* layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LottieParser::parseGaussianBlur(LottieGaussianBlur* effect)
|
||||||
|
{
|
||||||
|
int idx = 0; //blurness -> direction -> wrap
|
||||||
|
enterArray();
|
||||||
|
while (nextArrayValue()) {
|
||||||
|
enterObject();
|
||||||
|
while (auto key = nextObjectKey()) {
|
||||||
|
if (KEY_AS("v")) {
|
||||||
|
enterObject();
|
||||||
|
while (auto key = nextObjectKey()) {
|
||||||
|
if (KEY_AS("k")) {
|
||||||
|
if (idx == 0) parsePropertyInternal(effect->blurness);
|
||||||
|
else if (idx == 1) parsePropertyInternal(effect->direction);
|
||||||
|
else if (idx == 2) parsePropertyInternal(effect->wrap);
|
||||||
|
++idx;
|
||||||
|
} else skip(key);
|
||||||
|
}
|
||||||
|
} else skip(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LottieParser::parseEffect(LottieEffect* effect)
|
||||||
|
{
|
||||||
|
switch (effect->type) {
|
||||||
|
case LottieEffect::GaussianBlur: {
|
||||||
|
parseGaussianBlur(static_cast<LottieGaussianBlur*>(effect));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LottieParser::parseEffects(LottieLayer* layer)
|
||||||
|
{
|
||||||
|
auto invalid = true;
|
||||||
|
|
||||||
|
enterArray();
|
||||||
|
while (nextArrayValue()) {
|
||||||
|
LottieEffect* effect = nullptr;
|
||||||
|
enterObject();
|
||||||
|
while (auto key = nextObjectKey()) {
|
||||||
|
//type must be priortized.
|
||||||
|
if (KEY_AS("ty"))
|
||||||
|
{
|
||||||
|
effect = getEffect(getInt());
|
||||||
|
if (!effect) break;
|
||||||
|
else invalid = false;
|
||||||
|
}
|
||||||
|
else if (effect && KEY_AS("en")) effect->enable = getInt();
|
||||||
|
else if (effect && KEY_AS("ef")) parseEffect(effect);
|
||||||
|
else skip(key);
|
||||||
|
}
|
||||||
|
//TODO: remove when all effects were guaranteed.
|
||||||
|
if (invalid) {
|
||||||
|
TVGLOG("LOTTIE", "Not supported Layer Effect = %d", (int)effect->type);
|
||||||
|
while (auto key = nextObjectKey()) skip(key);
|
||||||
|
} else layer->effects.push(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LottieLayer* LottieParser::parseLayer(LottieLayer* precomp)
|
LottieLayer* LottieParser::parseLayer(LottieLayer* precomp)
|
||||||
{
|
{
|
||||||
auto layer = new LottieLayer;
|
auto layer = new LottieLayer;
|
||||||
|
@ -1278,11 +1364,7 @@ LottieLayer* LottieParser::parseLayer(LottieLayer* precomp)
|
||||||
else if (KEY_AS("refId")) layer->rid = djb2Encode(getString());
|
else if (KEY_AS("refId")) layer->rid = djb2Encode(getString());
|
||||||
else if (KEY_AS("td")) layer->matteSrc = getInt(); //used for matte layer
|
else if (KEY_AS("td")) layer->matteSrc = getInt(); //used for matte layer
|
||||||
else if (KEY_AS("t")) parseText(layer->children);
|
else if (KEY_AS("t")) parseText(layer->children);
|
||||||
else if (KEY_AS("ef"))
|
else if (KEY_AS("ef")) parseEffects(layer);
|
||||||
{
|
|
||||||
TVGLOG("LOTTIE", "layer effect(ef) is not supported!");
|
|
||||||
skip(key);
|
|
||||||
}
|
|
||||||
else skip(key);
|
else skip(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ private:
|
||||||
StrokeJoin getStrokeJoin();
|
StrokeJoin getStrokeJoin();
|
||||||
CompositeMethod getMaskMethod(bool inversed);
|
CompositeMethod getMaskMethod(bool inversed);
|
||||||
LottieInterpolator* getInterpolator(const char* key, Point& in, Point& out);
|
LottieInterpolator* getInterpolator(const char* key, Point& in, Point& out);
|
||||||
|
LottieEffect* getEffect(int type);
|
||||||
|
|
||||||
void getInterpolatorPoint(Point& pt);
|
void getInterpolatorPoint(Point& pt);
|
||||||
void getPathSet(LottiePathSet& path);
|
void getPathSet(LottiePathSet& path);
|
||||||
|
@ -60,6 +61,7 @@ private:
|
||||||
void getValue(ColorStop& color);
|
void getValue(ColorStop& color);
|
||||||
void getValue(float& val);
|
void getValue(float& val);
|
||||||
void getValue(uint8_t& val);
|
void getValue(uint8_t& val);
|
||||||
|
void getValue(int8_t& val);
|
||||||
void getValue(RGB24& color);
|
void getValue(RGB24& color);
|
||||||
bool getValue(Point& pt);
|
bool getValue(Point& pt);
|
||||||
|
|
||||||
|
@ -93,12 +95,15 @@ private:
|
||||||
LottieFont* parseFont();
|
LottieFont* parseFont();
|
||||||
LottieMarker* parseMarker();
|
LottieMarker* parseMarker();
|
||||||
|
|
||||||
|
void parseGaussianBlur(LottieGaussianBlur* effect);
|
||||||
|
|
||||||
bool parseDirection(LottieShape* shape, const char* key);
|
bool parseDirection(LottieShape* shape, const char* key);
|
||||||
bool parseCommon(LottieObject* obj, const char* key);
|
bool parseCommon(LottieObject* obj, const char* key);
|
||||||
void parseObject(Array<LottieObject*>& parent);
|
void parseObject(Array<LottieObject*>& parent);
|
||||||
void parseShapes(Array<LottieObject*>& parent);
|
void parseShapes(Array<LottieObject*>& parent);
|
||||||
void parseText(Array<LottieObject*>& parent);
|
void parseText(Array<LottieObject*>& parent);
|
||||||
void parseMasks(LottieLayer* layer);
|
void parseMasks(LottieLayer* layer);
|
||||||
|
void parseEffects(LottieLayer* layer);
|
||||||
void parseTimeRemap(LottieLayer* layer);
|
void parseTimeRemap(LottieLayer* layer);
|
||||||
void parseStrokeDash(LottieStroke* stroke);
|
void parseStrokeDash(LottieStroke* stroke);
|
||||||
void parseGradient(LottieGradient* gradient, const char* key);
|
void parseGradient(LottieGradient* gradient, const char* key);
|
||||||
|
@ -107,6 +112,7 @@ private:
|
||||||
void parseFonts();
|
void parseFonts();
|
||||||
void parseChars(Array<LottieGlyph*>& glyphs);
|
void parseChars(Array<LottieGlyph*>& glyphs);
|
||||||
void parseMarkers();
|
void parseMarkers();
|
||||||
|
void parseEffect(LottieEffect* effect);
|
||||||
void postProcess(Array<LottieGlyph*>& glyphs);
|
void postProcess(Array<LottieGlyph*>& glyphs);
|
||||||
|
|
||||||
//Current parsing context
|
//Current parsing context
|
||||||
|
|
|
@ -832,5 +832,7 @@ using LottiePoint = LottieGenericProperty<Point>;
|
||||||
using LottieFloat = LottieGenericProperty<float>;
|
using LottieFloat = LottieGenericProperty<float>;
|
||||||
using LottieOpacity = LottieGenericProperty<uint8_t>;
|
using LottieOpacity = LottieGenericProperty<uint8_t>;
|
||||||
using LottieColor = LottieGenericProperty<RGB24>;
|
using LottieColor = LottieGenericProperty<RGB24>;
|
||||||
|
using LottieSlider = LottieFloat;
|
||||||
|
using LottieCheckbox = LottieGenericProperty<int8_t>;
|
||||||
|
|
||||||
#endif //_TVG_LOTTIE_PROPERTY_H_
|
#endif //_TVG_LOTTIE_PROPERTY_H_
|
||||||
|
|
Loading…
Add table
Reference in a new issue