+
Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 110 additions & 87 deletions src/loaders/lottie/tvgLottieExpressions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct ExpContent
union {
LottieObject* obj;
LottieEffect* effect;
LottieProperty* property;
void *data;
};
float frameNo;
size_t refCnt;
Expand All @@ -62,14 +64,14 @@ static const char* EXP_EFFECT= "effect";
static LottieExpressions* exps = nullptr; //singleton instance engine


static ExpContent* _expcontent(LottieExpression* exp, float frameNo, void* obj, size_t refCnt = 1)
static ExpContent* _expcontent(LottieExpression* exp, float frameNo, void* data, size_t refCnt = 1)
{
auto data = tvg::malloc<ExpContent*>(sizeof(ExpContent));
data->exp = exp;
data->frameNo = frameNo;
data->obj = (LottieObject*)obj;
data->refCnt = refCnt;
return data;
auto ret = tvg::malloc<ExpContent*>(sizeof(ExpContent));
ret->exp = exp;
ret->frameNo = frameNo;
ret->data = data;
ret->refCnt = refCnt;
return ret;
}


Expand Down Expand Up @@ -472,7 +474,6 @@ static jerry_value_t _muldiv(const jerry_value_t arg1, float arg2)
{
//1d
if (jerry_value_is_number(arg1)) return jerry_number(jerry_value_as_number(arg1) * arg2);

//2d
return _point2d(_point2d(arg1) * arg2);
}
Expand Down Expand Up @@ -647,26 +648,114 @@ static jerry_value_t _content(const jerry_call_info_t* info, const jerry_value_t
}


static jerry_value_t _layer(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
static jerry_value_t _createPath(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
//TODO: arg1: points, arg2: inTangents, arg3: outTangents, arg4: isClosed
auto arg1 = jerry_value_to_object(args[0]);
auto pathset = jerry_object_get_native_ptr(arg1, nullptr);
if (!pathset) {
TVGERR("LOTTIE", "failed createPath()");
return jerry_undefined();
}

jerry_value_free(arg1);

auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, pathset);
return obj;
}


static jerry_value_t _points(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
/* TODO: ThorVG prebuilds the path data for performance.
It actually need to constructs the Array<Point> for points, inTangents, outTangents and then return here... */
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
auto comp = static_cast<LottieLayer*>(data->obj);
LottieLayer* layer;

//layer index
auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, data->property);
return obj;
}


static jerry_value_t _pointOnPath(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
auto pathset = static_cast<LottiePathSet*>(data->property);
auto progress = jerry_value_as_number(args[0]);
RenderPath out;
(*pathset)(data->frameNo, out, nullptr, nullptr);
return _point2d(out.point(progress));
}


static void _buildPath(jerry_value_t context, float frameNo, LottieProperty* pathset)
{
auto data = _expcontent(nullptr, frameNo, pathset, 2);

//Trick for fast building path.
auto points = jerry_function_external(_points);
jerry_object_set_native_ptr(points, &freeCb, data);
jerry_object_set_sz(context, "points", points);
jerry_value_free(points);

auto pointOnPath = jerry_function_external(_pointOnPath);
jerry_object_set_native_ptr(pointOnPath, &freeCb, data);
jerry_object_set_sz(context, "pointOnPath", pointOnPath);
jerry_value_free(pointOnPath);

//inTangents
//outTangents
//isClosed
}


static jerry_value_t _layerChild(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
jerry_value_t obj = jerry_undefined();

//find a member by index
if (jerry_value_is_number(args[0])) {
auto idx = (uint16_t)jerry_value_as_int32(args[0]);
layer = comp->layerByIdx(idx);
jerry_value_free(idx);
//layer name
auto idx = (uint32_t)jerry_value_as_int32(args[0]) - 1;
auto children = static_cast<Array<LottieObject*>*>(data->data);
if (idx < children->count) {
obj = jerry_function_external(_layerChild);
jerry_object_set_native_ptr(obj, &freeCb, _expcontent(data->exp, data->frameNo, (*children)[idx]));
}
//find a member by name
} else {
layer = comp->layerById(_idByName(args[0]));
auto name = _name(args[0]);
if (name) {
//for backward compatibility: reserved ADOBE keyword
if (!strcmp(name, "ADBE Root Vectors Group") || !strcmp(name, "ADBE Vectors Group")) {
auto group = static_cast<LottieGroup*>(data->obj);
if (group->type == LottieObject::Type::Group || group->type == LottieObject::Type::Layer) {
obj = jerry_function_external(_layerChild);
jerry_object_set_native_ptr(obj, &freeCb, _expcontent(data->exp, data->frameNo, &group->children));
}
} else if (!strcmp(name, "ADBE Vector Shape")) {
obj = jerry_object();
_buildPath(obj, data->frameNo, &static_cast<LottiePath*>(data->obj)->pathset);
}
tvg::free(name);
}
}
return obj;
}


static jerry_value_t _layer(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
auto comp = static_cast<LottieLayer*>(data->obj);

//either index or name
auto layer = jerry_value_is_number(args[0]) ? comp->layerByIdx((uint16_t)jerry_value_as_int32(args[0])) : comp->layerById(_idByName(args[0]));
if (!layer) return jerry_undefined();

auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, layer);
auto obj = jerry_function_external(_layerChild);
jerry_object_set_native_ptr(obj, &freeCb, _expcontent(data->exp, data->frameNo, layer));
_buildLayer(obj, data->frameNo, layer, comp, data->exp);

return obj;
Expand Down Expand Up @@ -845,7 +934,6 @@ static jerry_value_t _temporalWiggle(const jerry_call_info_t* info, const jerry_
}



static bool _loopOutCommon(LottieExpression* exp, const jerry_value_t args[], const jerry_length_t argsCnt)
{
exp->loop.mode = LottieExpression::LoopMode::OutCycle;
Expand Down Expand Up @@ -888,9 +976,7 @@ static jerry_value_t _loopOutDuration(const jerry_call_info_t* info, const jerry

if (!_loopOutCommon(exp, args, argsCnt)) return jerry_undefined();

if (argsCnt > 1) {
exp->loop.in = exp->comp->frameAtTime(jerry_value_as_number(args[1]));
}
if (argsCnt > 1) exp->loop.in = exp->comp->frameAtTime(jerry_value_as_number(args[1]));

auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, exp->property);
Expand Down Expand Up @@ -976,69 +1062,6 @@ static jerry_value_t _key(const jerry_call_info_t* info, const jerry_value_t arg
}


static jerry_value_t _createPath(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
//TODO: arg1: points, arg2: inTangents, arg3: outTangents, arg4: isClosed
auto arg1 = jerry_value_to_object(args[0]);
auto pathset = jerry_object_get_native_ptr(arg1, nullptr);
if (!pathset) {
TVGERR("LOTTIE", "failed createPath()");
return jerry_undefined();
}

jerry_value_free(arg1);

auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, pathset);
return obj;
}


static jerry_value_t _uniformPath(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
auto pathset = static_cast<LottiePathSet*>(jerry_object_get_native_ptr(info->function, nullptr));

/* TODO: ThorVG prebuilds the path data for performance.
It actually need to constructs the Array<Point> for points, inTangents, outTangents and then return here... */
auto obj = jerry_object();
jerry_object_set_native_ptr(obj, nullptr, pathset);
return obj;
}


static jerry_value_t _isClosed(const jerry_call_info_t* info, const jerry_value_t args[], const jerry_length_t argsCnt)
{
//TODO: Not used
return jerry_boolean(true);
}


static void _buildPath(jerry_value_t context, LottieExpression* exp)
{
//Trick for fast building path.
auto points = jerry_function_external(_uniformPath);
jerry_object_set_native_ptr(points, nullptr, exp->property);
jerry_object_set_sz(context, "points", points);
jerry_value_free(points);

auto inTangents = jerry_function_external(_uniformPath);
jerry_object_set_native_ptr(inTangents, nullptr, exp->property);
jerry_object_set_sz(context, "inTangents", inTangents);
jerry_value_free(inTangents);

auto outTangents = jerry_function_external(_uniformPath);
jerry_object_set_native_ptr(outTangents, nullptr, exp->property);
jerry_object_set_sz(context, "outTangents", outTangents);
jerry_value_free(outTangents);

auto isClosed = jerry_function_external(_isClosed);
jerry_object_set_native_ptr(isClosed, nullptr, exp->property);
jerry_object_set_sz(context, "isClosed", isClosed);
jerry_value_free(isClosed);

}


static void _buildProperty(float frameNo, jerry_value_t context, LottieExpression* exp)
{
auto value = _value(frameNo, exp->property);
Expand Down Expand Up @@ -1150,7 +1173,7 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio
jerry_value_free(effect);

//expansions per types
if (exp->property->type == LottieProperty::Type::PathSet) _buildPath(context, exp);
if (exp->property->type == LottieProperty::Type::PathSet) _buildPath(context, frameNo, exp->property);
}


Expand Down
50 changes: 50 additions & 0 deletions src/renderer/tvgRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,56 @@ bool RenderMethod::viewport(const RenderRegion& vp)
/* RenderPath Class Implementation */
/************************************************************************/

Point RenderPath::point(float progress)
{
if (progress <= 0.0f) return pts.first();
if (progress >= 1.0f) return pts.last();

auto p = pts.data;
auto c = cmds.data;
auto pleng = tvg::length(cmds.data, cmds.count, pts.data, pts.count) * progress;
auto cleng = 0.0f;
Point curr{}, start{}, next{};

while (c < cmds.data + cmds.count) {
switch (*c) {
case PathCommand::MoveTo: {
curr = start = *p;
++p;
++c;
break;
}
case PathCommand::LineTo: {
next = *p;
float segLen = tvg::length(&curr, &next);
if (cleng + segLen >= pleng) return lerp(curr, next, (pleng - cleng) / segLen);
cleng += segLen;
curr = next;
++p;
break;
}
case PathCommand::CubicTo: {
Bezier bz = {curr, *p++, *p++, *p++};
auto segLen = bz.length();
if (cleng + segLen >= pleng) return bz.at((pleng - cleng) / segLen);
cleng += segLen;
curr = bz.end;
break;
}
case PathCommand::Close: {
auto segLen = tvg::length(&curr, &start);
if (cleng + segLen >= pleng) return (curr + (start - curr)) * ((pleng - cleng) / segLen);
cleng += segLen;
curr = start;
break;
}
}
++c;
}
return {};
}


bool RenderPath::bounds(Matrix* m, float* x, float* y, float* w, float* h)
{
//unexpected
Expand Down
1 change: 1 addition & 0 deletions src/renderer/tvgRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ struct RenderPath
}

bool bounds(Matrix* m, float* x, float* y, float* w, float* h);
Point point(float progress);
};

struct RenderTrimPath
Expand Down
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载