loader/lottie: support the polystar property.

This commit is contained in:
Hermet Park 2023-08-22 16:17:49 +09:00
parent 001c1c06fc
commit 68f4193378
15 changed files with 195 additions and 9 deletions

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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

File diff suppressed because one or more lines are too long

View file

@ -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: {