mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
loader/lottie: support the polystar property.
This commit is contained in:
parent
001c1c06fc
commit
68f4193378
15 changed files with 195 additions and 9 deletions
|
@ -29,8 +29,8 @@
|
|||
/* Drawing Commands */
|
||||
/************************************************************************/
|
||||
|
||||
#define NUM_PER_ROW 8
|
||||
#define NUM_PER_COL 8
|
||||
#define NUM_PER_ROW 9
|
||||
#define NUM_PER_COL 9
|
||||
#define SIZE (WIDTH/NUM_PER_ROW)
|
||||
|
||||
static int counter = 0;
|
||||
|
|
File diff suppressed because one or more lines are too long
1
src/examples/images/alien.json
Normal file
1
src/examples/images/alien.json
Normal file
File diff suppressed because one or more lines are too long
1
src/examples/images/confettiBird.json
Normal file
1
src/examples/images/confettiBird.json
Normal file
File diff suppressed because one or more lines are too long
1
src/examples/images/customer.json
Normal file
1
src/examples/images/customer.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
{"v":"4.6.10","fr":15,"ip":0,"op":155,"w":1080,"h":1920,"nm":"background","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1160,880]},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect"},{"ty":"st","c":{"a":0,"k":[0.9960784,0.7843137,0.145098,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":6},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"gf","o":{"a":0,"k":100},"r":1,"g":{"p":3,"k":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[0,0.511,0.89,0.283,0.5,0.334,0.873,0.583,1,0.156,0.857,0.882],"e":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[0,0.726,0.283,0.89,0.5,0.441,0.356,0.886,1,0.156,0.429,0.882],"e":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[0,0.89,0.283,0.283,0.5,0.886,0.553,0.219,1,0.882,0.823,0.156],"e":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[0,0,0.312,0.737,0.5,0.078,0.597,0.754,1,0.156,0.882,0.771],"e":[0,0.51,0.89,0.282,0.5,0.333,0.873,0.582,1,0.157,0.855,0.882]},{"t":120}]}},"s":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[-430.769,-404.573],"e":[23.726,-364.48],"to":[75.7491683959961,6.68213844299316],"ti":[-123.915840148926,-8.51547145843506]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[23.726,-364.48],"e":[312.726,-353.48],"to":[123.915840148926,8.51547145843506],"ti":[-1.00208830833435,-1.83333337306976]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[312.726,-353.48],"e":[29.739,-353.48],"to":[1.00208830833435,1.83333337306976],"ti":[120.055290222168,0.60746711492538]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[29.739,-353.48],"e":[-407.606,-357.125],"to":[-120.055290222168,-0.60746711492538],"ti":[72.8907089233398,0.60746711492538]},{"t":120}]},"e":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[374.412,342.611],"e":[22.822,357.191],"to":[-58.5984153747559,2.42986845970154],"ti":[132.520950317383,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":31,"s":[22.822,357.191],"e":[-420.714,389.994],"to":[-132.520950317383,7.89707231521606],"ti":[-4.68509674072266,-7.89707231521606]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":61,"s":[-420.714,389.994],"e":[50.932,404.573],"to":[4.68509674072266,7.89707231521606],"ti":[-132.918350219727,4.25226974487305]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":91,"s":[50.932,404.573],"e":[376.797,364.48],"to":[132.918350219727,-4.25226974487305],"ti":[-54.3107261657715,6.68213844299316]},{"t":120}]},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[93.29,219.491],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":155,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":1,"nm":"Deep Red Solid 1","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[540,960,0]},"a":{"a":0,"k":[540,960,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"sw":1080,"sh":1920,"sc":"#be2a2a","ip":0,"op":155,"st":0,"bm":0,"sr":1}]}
|
File diff suppressed because one or more lines are too long
1
src/examples/images/lolo.json
Normal file
1
src/examples/images/lolo.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
src/examples/images/polystar.json
Normal file
1
src/examples/images/polystar.json
Normal file
File diff suppressed because one or more lines are too long
1
src/examples/images/polystar_anim.json
Normal file
1
src/examples/images/polystar_anim.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"v":"5.1.17","fr":29.9700012207031,"ip":0,"op":150.000006109625,"w":300,"h":300,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[152,152,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"sr","sy":1,"d":2,"pt":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[5],"e":[11]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":90,"s":[11],"e":[15]},{"t":146.000005946702}],"ix":3},"p":{"a":0,"k":[0,0],"ix":4},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[64]},{"t":90.0000036657751}],"ix":5},"ir":{"a":0,"k":106,"ix":6},"is":{"a":0,"k":231,"ix":8},"or":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[102],"e":[142]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":90,"s":[142],"e":[34]},{"t":146.000005946702}],"ix":7},"os":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[79],"e":[265]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":90,"s":[265],"e":[88]},{"t":146.000005946702}],"ix":9},"ix":1,"nm":"Polystar Path 1","mn":"ADBE Vector Shape - Star","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Stroke 2","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":150.000006109625,"st":0,"bm":0}],"markers":[]}
|
File diff suppressed because one or more lines are too long
1
src/examples/images/starburst.json
Normal file
1
src/examples/images/starburst.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -231,6 +231,191 @@ static Shape* _updatePath(LottieGroup* parent, LottiePath* path, int32_t frameNo
|
|||
}
|
||||
|
||||
|
||||
static void _updateStar(LottieGroup* parent, LottiePolyStar* star, int32_t frameNo, Shape* mergingShape)
|
||||
{
|
||||
static constexpr auto K_PI = 3.141592f;
|
||||
static constexpr auto POLYSTAR_MAGIC_NUMBER = 0.47829f / 0.28f;
|
||||
|
||||
auto ptsCnt = star->ptsCnt(frameNo);
|
||||
auto innerRadius = star->innerRadius(frameNo);
|
||||
auto outerRadius = star->outerRadius(frameNo);
|
||||
auto innerRoundness = star->innerRoundness(frameNo) * 0.01f;
|
||||
auto outerRoundness = star->outerRoundness(frameNo) * 0.01f;
|
||||
|
||||
auto angle = -90.0f * K_PI / 180.0f;
|
||||
auto partialPointRadius = 0.0f;
|
||||
auto anglePerPoint = (2.0f * K_PI / ptsCnt);
|
||||
auto halfAnglePerPoint = anglePerPoint * 0.5f;
|
||||
auto partialPointAmount = ptsCnt - floorf(ptsCnt);
|
||||
auto longSegment = false;
|
||||
auto numPoints = size_t(ceilf(ptsCnt) * 2);
|
||||
auto direction = star->direction ? 1.0f : -1.0f;
|
||||
auto hasRoundness = false;
|
||||
|
||||
float x, y;
|
||||
|
||||
if (!mathZero(partialPointAmount)) {
|
||||
angle += halfAnglePerPoint * (1.0f - partialPointAmount) * direction;
|
||||
}
|
||||
|
||||
if (!mathZero(partialPointAmount)) {
|
||||
partialPointRadius = innerRadius + partialPointAmount * (outerRadius - innerRadius);
|
||||
x = partialPointRadius * cosf(angle);
|
||||
y = partialPointRadius * sinf(angle);
|
||||
angle += anglePerPoint * partialPointAmount * 0.5f * direction;
|
||||
} else {
|
||||
x = outerRadius * cosf(angle);
|
||||
y = outerRadius * sinf(angle);
|
||||
angle += halfAnglePerPoint * direction;
|
||||
}
|
||||
|
||||
if (mathZero(innerRoundness) && mathZero(outerRoundness)) {
|
||||
P(mergingShape)->rs.path.pts.reserve(numPoints + 2);
|
||||
P(mergingShape)->rs.path.cmds.reserve(numPoints + 3);
|
||||
} else {
|
||||
P(mergingShape)->rs.path.pts.reserve(numPoints * 3 + 2);
|
||||
P(mergingShape)->rs.path.cmds.reserve(numPoints + 3);
|
||||
hasRoundness = true;
|
||||
}
|
||||
|
||||
mergingShape->moveTo(x, y);
|
||||
|
||||
for (size_t i = 0; i < numPoints; i++) {
|
||||
auto radius = longSegment ? outerRadius : innerRadius;
|
||||
auto dTheta = halfAnglePerPoint;
|
||||
if (!mathZero(partialPointRadius) && i == numPoints - 2) {
|
||||
dTheta = anglePerPoint * partialPointAmount * 0.5f;
|
||||
}
|
||||
if (!mathZero(partialPointRadius) && i == numPoints - 1) {
|
||||
radius = partialPointRadius;
|
||||
}
|
||||
auto previousX = x;
|
||||
auto previousY = y;
|
||||
x = radius * cosf(angle);
|
||||
y = radius * sinf(angle);
|
||||
|
||||
if (hasRoundness) {
|
||||
auto cp1Theta = (atan2f(previousY, previousX) - K_PI / 2.0f * direction);
|
||||
auto cp1Dx = cosf(cp1Theta);
|
||||
auto cp1Dy = sinf(cp1Theta);
|
||||
auto cp2Theta = (atan2f(y, x) - K_PI / 2.0f * direction);
|
||||
auto cp2Dx = cosf(cp2Theta);
|
||||
auto cp2Dy = sinf(cp2Theta);
|
||||
|
||||
auto cp1Roundness = longSegment ? innerRoundness : outerRoundness;
|
||||
auto cp2Roundness = longSegment ? outerRoundness : innerRoundness;
|
||||
auto cp1Radius = longSegment ? innerRadius : outerRadius;
|
||||
auto cp2Radius = longSegment ? outerRadius : innerRadius;
|
||||
|
||||
auto cp1x = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * cp1Dx / ptsCnt;
|
||||
auto cp1y = cp1Radius * cp1Roundness * POLYSTAR_MAGIC_NUMBER * cp1Dy / ptsCnt;
|
||||
auto cp2x = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * cp2Dx / ptsCnt;
|
||||
auto cp2y = cp2Radius * cp2Roundness * POLYSTAR_MAGIC_NUMBER * cp2Dy / ptsCnt;
|
||||
|
||||
if (!mathZero(partialPointAmount) && ((i == 0) || (i == numPoints - 1))) {
|
||||
cp1x *= partialPointAmount;
|
||||
cp1y *= partialPointAmount;
|
||||
cp2x *= partialPointAmount;
|
||||
cp2y *= partialPointAmount;
|
||||
}
|
||||
mergingShape->cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
|
||||
} else {
|
||||
mergingShape->lineTo(x, y);
|
||||
}
|
||||
|
||||
angle += dTheta * direction;
|
||||
longSegment = !longSegment;
|
||||
}
|
||||
|
||||
mergingShape->close();
|
||||
}
|
||||
|
||||
|
||||
static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, int32_t frameNo, Shape* mergingShape)
|
||||
{
|
||||
const static auto POLYGON_MAGIC_NUMBER = 0.25f;
|
||||
static constexpr auto K_PI = 3.141592f;
|
||||
|
||||
auto ptsCnt = size_t(floor(star->ptsCnt(frameNo)));
|
||||
auto radius = star->outerRadius(frameNo);
|
||||
auto roundness = star->outerRoundness(frameNo) * 0.01f;
|
||||
|
||||
auto angle = -90.0f * K_PI / 180.0f;
|
||||
auto anglePerPoint = 2.0f * K_PI / float(ptsCnt);
|
||||
auto direction = star->direction ? 1.0f : -1.0f;
|
||||
auto hasRoundness = false;
|
||||
auto x = radius * cosf(angle);
|
||||
auto y = radius * sinf(angle);
|
||||
|
||||
angle += anglePerPoint * direction;
|
||||
|
||||
if (mathZero(roundness)) {
|
||||
P(mergingShape)->rs.path.pts.reserve(ptsCnt + 2);
|
||||
P(mergingShape)->rs.path.cmds.reserve(ptsCnt + 3);
|
||||
} else {
|
||||
P(mergingShape)->rs.path.pts.reserve(ptsCnt * 3 + 2);
|
||||
P(mergingShape)->rs.path.cmds.reserve(ptsCnt + 3);
|
||||
hasRoundness = true;
|
||||
}
|
||||
|
||||
mergingShape->moveTo(x, y);
|
||||
|
||||
for (size_t i = 0; i < ptsCnt; i++) {
|
||||
auto previousX = x;
|
||||
auto previousY = y;
|
||||
x = (radius * cosf(angle));
|
||||
y = (radius * sinf(angle));
|
||||
|
||||
if (hasRoundness) {
|
||||
auto cp1Theta = atan2f(previousY, previousX) - K_PI * 0.5f * direction;
|
||||
auto cp1Dx = cosf(cp1Theta);
|
||||
auto cp1Dy = sinf(cp1Theta);
|
||||
auto cp2Theta = atan2f(y, x) - K_PI * 0.5f * direction;
|
||||
auto cp2Dx = cosf(cp2Theta);
|
||||
auto cp2Dy = sinf(cp2Theta);
|
||||
|
||||
auto cp1x = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dx;
|
||||
auto cp1y = radius * roundness * POLYGON_MAGIC_NUMBER * cp1Dy;
|
||||
auto cp2x = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dx;
|
||||
auto cp2y = radius * roundness * POLYGON_MAGIC_NUMBER * cp2Dy;
|
||||
|
||||
mergingShape->cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
|
||||
} else {
|
||||
mergingShape->lineTo(x, y);
|
||||
}
|
||||
angle += anglePerPoint * direction;
|
||||
}
|
||||
mergingShape->close();
|
||||
}
|
||||
|
||||
|
||||
static Shape* _updatePolystar(LottieGroup* parent, LottiePolyStar* star, int32_t frameNo, Shape* baseShape, Shape* mergingShape)
|
||||
{
|
||||
if (!mergingShape) {
|
||||
auto newShape = cast<Shape>(baseShape->duplicate());
|
||||
mergingShape = newShape.get();
|
||||
parent->scene->push(std::move(newShape));
|
||||
}
|
||||
|
||||
if (star->type == LottiePolyStar::Star) _updateStar(parent, star, frameNo, mergingShape);
|
||||
else _updatePolygon(parent, star, frameNo, mergingShape);
|
||||
|
||||
P(mergingShape)->update(RenderUpdateFlag::Path);
|
||||
|
||||
auto pos = star->position(frameNo);
|
||||
auto rotation = star->rotation(frameNo);
|
||||
|
||||
if (rotation == 0.0f && pos.x == 0.0f && pos.y == 0.0f) return mergingShape;
|
||||
|
||||
auto matrix = mergingShape->transform();
|
||||
mathTranslate(&matrix, pos.x, pos.y);
|
||||
mathRotate(&matrix, rotation * 2.0f);
|
||||
mergingShape->transform(matrix);
|
||||
|
||||
return mergingShape;
|
||||
}
|
||||
|
||||
|
||||
static void _updateImage(LottieGroup* parent, LottieImage* image, int32_t frameNo, Paint* baseShape)
|
||||
{
|
||||
auto picture = image->picture;
|
||||
|
@ -308,7 +493,7 @@ static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseSha
|
|||
break;
|
||||
}
|
||||
case LottieObject::Polystar: {
|
||||
TVGERR("LOTTIE", "TODO: update Polystar");
|
||||
mergingShape = _updatePolystar(parent, static_cast<LottiePolyStar*>(*child), frameNo, baseShape, mergingShape);
|
||||
break;
|
||||
}
|
||||
case LottieObject::Image: {
|
||||
|
|
Loading…
Add table
Reference in a new issue