mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
Merge 2264d0ca79
into 32c38041db
This commit is contained in:
commit
fb6415e748
3 changed files with 163 additions and 89 deletions
|
@ -38,6 +38,8 @@ struct ExpContent
|
||||||
union {
|
union {
|
||||||
LottieObject* obj;
|
LottieObject* obj;
|
||||||
LottieEffect* effect;
|
LottieEffect* effect;
|
||||||
|
LottieProperty* property;
|
||||||
|
void *data;
|
||||||
};
|
};
|
||||||
float frameNo;
|
float frameNo;
|
||||||
size_t refCnt;
|
size_t refCnt;
|
||||||
|
@ -62,14 +64,14 @@ static const char* EXP_EFFECT= "effect";
|
||||||
static LottieExpressions* exps = nullptr; //singleton instance engine
|
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));
|
auto ret = tvg::malloc<ExpContent*>(sizeof(ExpContent));
|
||||||
data->exp = exp;
|
ret->exp = exp;
|
||||||
data->frameNo = frameNo;
|
ret->frameNo = frameNo;
|
||||||
data->obj = (LottieObject*)obj;
|
ret->data = data;
|
||||||
data->refCnt = refCnt;
|
ret->refCnt = refCnt;
|
||||||
return data;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -472,7 +474,6 @@ static jerry_value_t _muldiv(const jerry_value_t arg1, float arg2)
|
||||||
{
|
{
|
||||||
//1d
|
//1d
|
||||||
if (jerry_value_is_number(arg1)) return jerry_number(jerry_value_as_number(arg1) * arg2);
|
if (jerry_value_is_number(arg1)) return jerry_number(jerry_value_as_number(arg1) * arg2);
|
||||||
|
|
||||||
//2d
|
//2d
|
||||||
return _point2d(_point2d(arg1) * arg2);
|
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)
|
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 data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
|
||||||
auto comp = static_cast<LottieLayer*>(data->obj);
|
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();
|
if (!layer) return jerry_undefined();
|
||||||
|
|
||||||
auto obj = jerry_object();
|
auto obj = jerry_function_external(_layerChild);
|
||||||
jerry_object_set_native_ptr(obj, nullptr, layer);
|
jerry_object_set_native_ptr(obj, &freeCb, _expcontent(data->exp, data->frameNo, layer));
|
||||||
_buildLayer(obj, data->frameNo, layer, comp, data->exp);
|
_buildLayer(obj, data->frameNo, layer, comp, data->exp);
|
||||||
|
|
||||||
return obj;
|
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)
|
static bool _loopOutCommon(LottieExpression* exp, const jerry_value_t args[], const jerry_length_t argsCnt)
|
||||||
{
|
{
|
||||||
exp->loop.mode = LottieExpression::LoopMode::OutCycle;
|
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 (!_loopOutCommon(exp, args, argsCnt)) return jerry_undefined();
|
||||||
|
|
||||||
if (argsCnt > 1) {
|
if (argsCnt > 1) exp->loop.in = exp->comp->frameAtTime(jerry_value_as_number(args[1]));
|
||||||
exp->loop.in = exp->comp->frameAtTime(jerry_value_as_number(args[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto obj = jerry_object();
|
auto obj = jerry_object();
|
||||||
jerry_object_set_native_ptr(obj, nullptr, exp->property);
|
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)
|
static void _buildProperty(float frameNo, jerry_value_t context, LottieExpression* exp)
|
||||||
{
|
{
|
||||||
auto value = _value(frameNo, exp->property);
|
auto value = _value(frameNo, exp->property);
|
||||||
|
@ -1150,7 +1173,7 @@ static void _buildProperty(float frameNo, jerry_value_t context, LottieExpressio
|
||||||
jerry_value_free(effect);
|
jerry_value_free(effect);
|
||||||
|
|
||||||
//expansions per types
|
//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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,56 @@ uint32_t RenderMethod::unref()
|
||||||
/* RenderPath Class Implementation */
|
/* 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)
|
bool RenderPath::bounds(Matrix* m, float* x, float* y, float* w, float* h)
|
||||||
{
|
{
|
||||||
//unexpected
|
//unexpected
|
||||||
|
|
|
@ -118,6 +118,7 @@ struct RenderPath
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bounds(Matrix* m, float* x, float* y, float* w, float* h);
|
bool bounds(Matrix* m, float* x, float* y, float* w, float* h);
|
||||||
|
Point point(float progress);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderTrimPath
|
struct RenderTrimPath
|
||||||
|
|
Loading…
Add table
Reference in a new issue