mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
loader/lottie: correct a polystar transform.
Properly propagate the transform information to the merged shapes. This corrects the incorrect transformation applied to the subsequent shapes.
This commit is contained in:
parent
3d5c5ef0fa
commit
7b40c741ac
3 changed files with 68 additions and 55 deletions
|
@ -232,7 +232,7 @@ static Shape* _updatePath(LottieGroup* parent, LottiePath* path, int32_t frameNo
|
|||
}
|
||||
|
||||
|
||||
static void _updateStar(LottieGroup* parent, LottiePolyStar* star, int32_t frameNo, Shape* mergingShape)
|
||||
static void _updateStar(LottieGroup* parent, LottiePolyStar* star, Matrix* transform, int32_t frameNo, Shape* mergingShape)
|
||||
{
|
||||
static constexpr auto K_PI = 3.141592f;
|
||||
static constexpr auto POLYSTAR_MAGIC_NUMBER = 0.47829f / 0.28f;
|
||||
|
@ -279,7 +279,9 @@ static void _updateStar(LottieGroup* parent, LottiePolyStar* star, int32_t frame
|
|||
hasRoundness = true;
|
||||
}
|
||||
|
||||
mergingShape->moveTo(x, y);
|
||||
Point in = {x, y};
|
||||
if (transform) mathTransform(transform, &in);
|
||||
mergingShape->moveTo(in.x, in.y);
|
||||
|
||||
for (size_t i = 0; i < numPoints; i++) {
|
||||
auto radius = longSegment ? outerRadius : innerRadius;
|
||||
|
@ -319,22 +321,30 @@ static void _updateStar(LottieGroup* parent, LottiePolyStar* star, int32_t frame
|
|||
cp2x *= partialPointAmount;
|
||||
cp2y *= partialPointAmount;
|
||||
}
|
||||
mergingShape->cubicTo(previousX - cp1x, previousY - cp1y, x + cp2x, y + cp2y, x, y);
|
||||
Point in2 = {previousX - cp1x, previousY - cp1y};
|
||||
Point in3 = {x + cp2x, y + cp2y};
|
||||
Point in4 = {x, y};
|
||||
if (transform) {
|
||||
mathTransform(transform, &in2);
|
||||
mathTransform(transform, &in3);
|
||||
mathTransform(transform, &in4);
|
||||
}
|
||||
mergingShape->cubicTo(in2.x, in2.y, in3.x, in3.y, in4.x, in4.y);
|
||||
} else {
|
||||
mergingShape->lineTo(x, y);
|
||||
Point in = {x, y};
|
||||
if (transform) mathTransform(transform, &in);
|
||||
mergingShape->lineTo(in.x, in.y);
|
||||
}
|
||||
|
||||
angle += dTheta * direction;
|
||||
longSegment = !longSegment;
|
||||
}
|
||||
|
||||
mergingShape->close();
|
||||
}
|
||||
|
||||
|
||||
static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, int32_t frameNo, Shape* mergingShape)
|
||||
static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* transform, int32_t frameNo, Shape* mergingShape)
|
||||
{
|
||||
const static auto POLYGON_MAGIC_NUMBER = 0.25f;
|
||||
static constexpr auto POLYGON_MAGIC_NUMBER = 0.25f;
|
||||
static constexpr auto K_PI = 3.141592f;
|
||||
|
||||
auto ptsCnt = size_t(floor(star->ptsCnt(frameNo)));
|
||||
|
@ -359,7 +369,9 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, int32_t fr
|
|||
hasRoundness = true;
|
||||
}
|
||||
|
||||
mergingShape->moveTo(x, y);
|
||||
Point in = {x, y};
|
||||
if (transform) mathTransform(transform, &in);
|
||||
mergingShape->moveTo(in.x, in.y);
|
||||
|
||||
for (size_t i = 0; i < ptsCnt; i++) {
|
||||
auto previousX = x;
|
||||
|
@ -380,9 +392,19 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, int32_t fr
|
|||
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);
|
||||
Point in2 = {previousX - cp1x, previousY - cp1y};
|
||||
Point in3 = {x + cp2x, y + cp2y};
|
||||
Point in4 = {x, y};
|
||||
if (transform) {
|
||||
mathTransform(transform, &in2);
|
||||
mathTransform(transform, &in3);
|
||||
mathTransform(transform, &in4);
|
||||
}
|
||||
mergingShape->cubicTo(in2.x, in2.y, in3.x, in3.y, in4.x, in4.y);
|
||||
} else {
|
||||
mergingShape->lineTo(x, y);
|
||||
Point in = {x, y};
|
||||
if (transform) mathTransform(transform, &in);
|
||||
mergingShape->lineTo(in.x, in.y);
|
||||
}
|
||||
angle += anglePerPoint * direction;
|
||||
}
|
||||
|
@ -398,21 +420,20 @@ static Shape* _updatePolystar(LottieGroup* parent, LottiePolyStar* star, int32_t
|
|||
parent->scene->push(std::move(newShape));
|
||||
}
|
||||
|
||||
if (star->type == LottiePolyStar::Star) _updateStar(parent, star, frameNo, mergingShape);
|
||||
else _updatePolygon(parent, star, frameNo, mergingShape);
|
||||
//Optimize: Can we skip the individual coords transform?
|
||||
Matrix matrix;
|
||||
mathIdentity(&matrix);
|
||||
auto position = star->position(frameNo);
|
||||
mathTranslate(&matrix, position.x, position.y);
|
||||
mathRotate(&matrix, star->rotation(frameNo) * 2.0f);
|
||||
|
||||
auto identity = mathIdentity((const Matrix*)&matrix);
|
||||
|
||||
if (star->type == LottiePolyStar::Star) _updateStar(parent, star, identity ? nullptr : &matrix, frameNo, mergingShape);
|
||||
else _updatePolygon(parent, star, identity ? nullptr : &matrix, 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -754,38 +754,21 @@ LottieObject* LottieParser::parseObject()
|
|||
auto type = getString();
|
||||
if (!type) return nullptr;
|
||||
|
||||
if (!strcmp(type, "gr")) {
|
||||
return parseGroup();
|
||||
} else if (!strcmp(type, "rc")) {
|
||||
return parseRect();
|
||||
} else if (!strcmp(type, "el")) {
|
||||
return parseEllipse();
|
||||
} else if (!strcmp(type, "tr")) {
|
||||
return parseTransform();
|
||||
} else if (!strcmp(type, "fl")) {
|
||||
return parseSolidFill();
|
||||
} else if (!strcmp(type, "st")) {
|
||||
return parseSolidStroke();
|
||||
} else if (!strcmp(type, "sh")) {
|
||||
return parsePath();
|
||||
} else if (!strcmp(type, "sr")) {
|
||||
TVGERR("LOTTIE", "Polystar(sr) is not supported");
|
||||
return parsePolyStar();
|
||||
} else if (!strcmp(type, "rd")) {
|
||||
return parseRoundedCorner();
|
||||
} else if (!strcmp(type, "gf")) {
|
||||
return parseGradientFill();
|
||||
} else if (!strcmp(type, "gs")) {
|
||||
return parseGradientStroke();
|
||||
} else if (!strcmp(type, "tm")) {
|
||||
TVGERR("LOTTIE", "Trimpath(tm) is not supported");
|
||||
} else if (!strcmp(type, "rp")) {
|
||||
TVGERR("LOTTIE", "Repeater(rp) is not supported yet");
|
||||
} else if (!strcmp(type, "mm")) {
|
||||
TVGERR("LOTTIE", "MergePath(mm) is not supported yet");
|
||||
} else {
|
||||
TVGERR("LOTTIE", "Unkown object type(%s) is given", type);
|
||||
}
|
||||
if (!strcmp(type, "gr")) return parseGroup();
|
||||
else if (!strcmp(type, "rc")) return parseRect();
|
||||
else if (!strcmp(type, "el")) return parseEllipse();
|
||||
else if (!strcmp(type, "tr")) return parseTransform();
|
||||
else if (!strcmp(type, "fl")) return parseSolidFill();
|
||||
else if (!strcmp(type, "st")) return parseSolidStroke();
|
||||
else if (!strcmp(type, "sh")) return parsePath();
|
||||
else if (!strcmp(type, "sr")) return parsePolyStar();
|
||||
else if (!strcmp(type, "rd")) return parseRoundedCorner();
|
||||
else if (!strcmp(type, "gf")) return parseGradientFill();
|
||||
else if (!strcmp(type, "gs")) return parseGradientStroke();
|
||||
else if (!strcmp(type, "tm")) TVGERR("LOTTIE", "Trimpath(tm) is not supported");
|
||||
else if (!strcmp(type, "rp")) TVGERR("LOTTIE", "Repeater(rp) is not supported yet");
|
||||
else if (!strcmp(type, "mm")) TVGERR("LOTTIE", "MergePath(mm) is not supported yet");
|
||||
else TVGERR("LOTTIE", "Unkown object type(%s) is given", type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,15 @@ static inline void mathIdentity(Matrix* m)
|
|||
}
|
||||
|
||||
|
||||
static inline void mathTransform(Matrix* transform, Point* coord)
|
||||
{
|
||||
auto x = coord->x;
|
||||
auto y = coord->y;
|
||||
coord->x = x * transform->e11 + y * transform->e12 + transform->e13;
|
||||
coord->y = x * transform->e21 + y * transform->e22 + transform->e23;
|
||||
}
|
||||
|
||||
|
||||
static inline void mathScale(Matrix* m, float sx, float sy)
|
||||
{
|
||||
m->e11 *= sx;
|
||||
|
|
Loading…
Add table
Reference in a new issue