This commit is contained in:
Hermet Park 2025-05-23 11:21:40 +09:00 committed by GitHub
commit fb6415e748
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 163 additions and 89 deletions

View file

@ -38,6 +38,8 @@ struct ExpContent
union {
LottieObject* obj;
LottieEffect* effect;
LottieProperty* property;
void *data;
};
float frameNo;
size_t refCnt;
@ -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;
}
@ -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);
}
@ -647,26 +648,114 @@ static jerry_value_t _content(const jerry_call_info_t* info, const jerry_value_t
}
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 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 = (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 {
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);
LottieLayer* layer;
//layer 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
} else {
layer = comp->layerById(_idByName(args[0]));
}
//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;
@ -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;
@ -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);
@ -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);
@ -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);
}

View file

@ -44,6 +44,56 @@ uint32_t RenderMethod::unref()
/* 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

View file

@ -118,6 +118,7 @@ struct RenderPath
}
bool bounds(Matrix* m, float* x, float* y, float* w, float* h);
Point point(float progress);
};
struct RenderTrimPath