mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
loader/lottie: enhanced the coverage of the rounded corner feature.
Rounded corners should now be applied not only to rectangles but also to path strokes. This enhancement changes the stroke join style to round when a rounded corner is present. Indeed, rounded corners ensure the accurate calculation of roundness based on the join style. However, this patch has not yet been designed to handle it.
This commit is contained in:
parent
1112444bd2
commit
7c669f622f
3 changed files with 42 additions and 51 deletions
|
@ -31,7 +31,7 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseShape);
|
||||
static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseShape, float roundedCorner);
|
||||
static void _updateLayer(LottieLayer* root, LottieLayer* layer, int32_t frameNo);
|
||||
static bool _buildPrecomp(LottieComposition* comp, LottieGroup* parent);
|
||||
|
||||
|
@ -108,7 +108,7 @@ static Shape* _updateTransform(Paint* paint, LottieTransform* transform, int32_t
|
|||
}
|
||||
|
||||
|
||||
static Shape* _updateGroup(LottieGroup* parent, LottieGroup* group, int32_t frameNo, Shape* baseShape)
|
||||
static Shape* _updateGroup(LottieGroup* parent, LottieGroup* group, int32_t frameNo, Shape* baseShape, float roundedCorner)
|
||||
{
|
||||
//Prepare render data
|
||||
group->scene = parent->scene;
|
||||
|
@ -127,7 +127,7 @@ static Shape* _updateGroup(LottieGroup* parent, LottieGroup* group, int32_t fram
|
|||
#endif
|
||||
}
|
||||
|
||||
_updateChildren(group, frameNo, baseShape);
|
||||
_updateChildren(group, frameNo, baseShape, roundedCorner);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -185,21 +185,23 @@ static Shape* _updateStroke(LottieGradientStroke* stroke, int32_t frameNo, Shape
|
|||
}
|
||||
|
||||
|
||||
static Shape* _updateRect(LottieGroup* parent, LottieRect* rect, int32_t frameNo, Shape* baseShape, Shape* mergingShape)
|
||||
static Shape* _updateRect(LottieGroup* parent, LottieRect* rect, int32_t frameNo, Shape* baseShape, Shape* mergingShape, float roundedCorner)
|
||||
{
|
||||
auto position = rect->position(frameNo);
|
||||
auto size = rect->size(frameNo);
|
||||
auto roundness = rect->roundness(frameNo);
|
||||
if (roundness != 0) {
|
||||
if (roundness > size.x * 0.5f) roundness = size.x * 0.5f;
|
||||
if (roundness > size.y * 0.5f) roundness = size.y * 0.5f;
|
||||
auto round = rect->radius(frameNo);
|
||||
if (roundedCorner > round) round = roundedCorner;
|
||||
|
||||
if (round > 0.0f) {
|
||||
if (round > size.x * 0.5f) round = size.x * 0.5f;
|
||||
if (round > size.y * 0.5f) round = size.y * 0.5f;
|
||||
}
|
||||
if (!mergingShape) {
|
||||
auto newShape = cast<Shape>(baseShape->duplicate());
|
||||
mergingShape = newShape.get();
|
||||
parent->scene->push(std::move(newShape));
|
||||
}
|
||||
mergingShape->appendRect(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y, roundness, roundness);
|
||||
mergingShape->appendRect(position.x - size.x * 0.5f, position.y - size.y * 0.5f, size.x, size.y, round, round);
|
||||
return mergingShape;
|
||||
}
|
||||
|
||||
|
@ -218,7 +220,7 @@ static Shape* _updateEllipse(LottieGroup* parent, LottieEllipse* ellipse, int32_
|
|||
}
|
||||
|
||||
|
||||
static Shape* _updatePath(LottieGroup* parent, LottiePath* path, int32_t frameNo, Shape* baseShape, Shape* mergingShape)
|
||||
static Shape* _updatePath(LottieGroup* parent, LottiePath* path, int32_t frameNo, Shape* baseShape, Shape* mergingShape, float roundedCorner)
|
||||
{
|
||||
if (!mergingShape) {
|
||||
auto newShape = cast<Shape>(baseShape->duplicate());
|
||||
|
@ -228,6 +230,12 @@ static Shape* _updatePath(LottieGroup* parent, LottiePath* path, int32_t frameNo
|
|||
if (path->pathset(frameNo, P(mergingShape)->rs.path.cmds, P(mergingShape)->rs.path.pts)) {
|
||||
P(mergingShape)->update(RenderUpdateFlag::Path);
|
||||
}
|
||||
|
||||
if (roundedCorner > 1.0f && P(mergingShape)->rs.stroke) {
|
||||
TVGERR("LOTTIE", "FIXME: Path roundesss should be applied properly!");
|
||||
P(mergingShape)->rs.stroke->join = StrokeJoin::Round;
|
||||
}
|
||||
|
||||
return mergingShape;
|
||||
}
|
||||
|
||||
|
@ -465,7 +473,15 @@ static void _updateImage(LottieGroup* parent, LottieImage* image, int32_t frameN
|
|||
}
|
||||
|
||||
|
||||
static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseShape)
|
||||
static float _updateRoundedCorner(LottieRoundedCorner* roundedCorner, int32_t frameNo, float baseValue)
|
||||
{
|
||||
auto round = roundedCorner->radius(frameNo);
|
||||
if (baseValue > round) round = baseValue;
|
||||
return round;
|
||||
}
|
||||
|
||||
|
||||
static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseShape, float roundedCorner)
|
||||
{
|
||||
if (parent->children.empty()) return;
|
||||
|
||||
|
@ -479,7 +495,7 @@ static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseSha
|
|||
for (auto child = parent->children.end() - 1; child >= parent->children.data; --child) {
|
||||
switch ((*child)->type) {
|
||||
case LottieObject::Group: {
|
||||
mergingShape = _updateGroup(parent, static_cast<LottieGroup*>(*child), frameNo, baseShape);
|
||||
mergingShape = _updateGroup(parent, static_cast<LottieGroup*>(*child), frameNo, baseShape, roundedCorner);
|
||||
break;
|
||||
}
|
||||
case LottieObject::Transform: {
|
||||
|
@ -503,7 +519,7 @@ static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseSha
|
|||
break;
|
||||
}
|
||||
case LottieObject::Rect: {
|
||||
mergingShape = _updateRect(parent, static_cast<LottieRect*>(*child), frameNo, baseShape, mergingShape);
|
||||
mergingShape = _updateRect(parent, static_cast<LottieRect*>(*child), frameNo, baseShape, mergingShape, roundedCorner);
|
||||
break;
|
||||
}
|
||||
case LottieObject::Ellipse: {
|
||||
|
@ -511,13 +527,17 @@ static void _updateChildren(LottieGroup* parent, int32_t frameNo, Shape* baseSha
|
|||
break;
|
||||
}
|
||||
case LottieObject::Path: {
|
||||
mergingShape = _updatePath(parent, static_cast<LottiePath*>(*child), frameNo, baseShape, mergingShape);
|
||||
mergingShape = _updatePath(parent, static_cast<LottiePath*>(*child), frameNo, baseShape, mergingShape, roundedCorner);
|
||||
break;
|
||||
}
|
||||
case LottieObject::Polystar: {
|
||||
mergingShape = _updatePolystar(parent, static_cast<LottiePolyStar*>(*child), frameNo, baseShape, mergingShape);
|
||||
break;
|
||||
}
|
||||
case LottieObject::RoundedCorner: {
|
||||
roundedCorner = _updateRoundedCorner(static_cast<LottieRoundedCorner*>(*child), frameNo, roundedCorner);
|
||||
break;
|
||||
}
|
||||
case LottieObject::Image: {
|
||||
_updateImage(parent, static_cast<LottieImage*>(*child), frameNo, baseShape);
|
||||
break;
|
||||
|
@ -615,7 +635,7 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, int32_t frameNo)
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
_updateChildren(layer, rFrameNo, nullptr);
|
||||
_updateChildren(layer, rFrameNo, nullptr, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,6 @@ struct LottieRoundedCorner : LottieObject
|
|||
LottieObject::type = LottieObject::RoundedCorner;
|
||||
if (radius.frames) statical = false;
|
||||
}
|
||||
|
||||
LottieFloat radius = 0.0f;
|
||||
};
|
||||
|
||||
|
@ -184,18 +183,12 @@ struct LottieRect : LottieShape
|
|||
void prepare()
|
||||
{
|
||||
LottieObject::type = LottieObject::Rect;
|
||||
if (position.frames || size.frames || round.frames) statical = false;
|
||||
if (position.frames || size.frames || radius.frames) statical = false;
|
||||
}
|
||||
|
||||
float roundness(int32_t frameNo)
|
||||
{
|
||||
return roundedCorner ? roundedCorner->radius(frameNo) : round(frameNo);
|
||||
}
|
||||
|
||||
LottieRoundedCorner* roundedCorner = nullptr;
|
||||
LottiePosition position = Point{0.0f, 0.0f};
|
||||
LottiePoint size = Point{0.0f, 0.0f};
|
||||
LottieFloat round = 0.0f;
|
||||
LottieFloat radius = 0.0f; //rounded corner radius
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -40,24 +40,6 @@ static char* _int2str(int num)
|
|||
}
|
||||
|
||||
|
||||
static void _updateRoundedCorner(LottieGroup* parent, LottieRoundedCorner* roundedCorner)
|
||||
{
|
||||
for (auto child = parent->children.data; child < parent->children.end(); ++child) {
|
||||
auto obj = *child;
|
||||
if (obj->type == LottieObject::Rect) {
|
||||
auto rect = static_cast<LottieRect*>(obj);
|
||||
rect->roundedCorner = roundedCorner;
|
||||
rect->statical &= roundedCorner->statical;
|
||||
parent->statical &= roundedCorner->statical;
|
||||
continue;
|
||||
}
|
||||
if (obj->type == LottieObject::Group || obj->type == LottieObject::Layer) {
|
||||
_updateRoundedCorner(static_cast<LottieGroup*>(obj), roundedCorner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CompositeMethod LottieParser::getMaskMethod(bool inversed)
|
||||
{
|
||||
switch (getString()[0]) {
|
||||
|
@ -484,7 +466,7 @@ LottieRect* LottieParser::parseRect()
|
|||
if (!strcmp(key, "d")) rect->direction = getInt();
|
||||
else if (!strcmp(key, "s")) parseProperty(rect->size);
|
||||
else if (!strcmp(key, "p")) parseProperty(rect->position);
|
||||
else if (!strcmp(key, "r")) parseProperty(rect->round);
|
||||
else if (!strcmp(key, "r")) parseProperty(rect->radius);
|
||||
else if (!strcmp(key, "nm")) rect->name = getStringCopy();
|
||||
else if (!strcmp(key, "hd")) rect->hidden = getBool();
|
||||
else skip(key);
|
||||
|
@ -787,14 +769,10 @@ void LottieParser::parseObject(LottieGroup* parent)
|
|||
enterObject();
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (!strcmp(key, "ty")) {
|
||||
auto child = parseObject();
|
||||
if (child && !child->hidden) {
|
||||
//propagate the rounded corner properties.
|
||||
if (child->type == LottieObject::RoundedCorner) {
|
||||
_updateRoundedCorner(parent, static_cast<LottieRoundedCorner*>(child));
|
||||
}
|
||||
parent->children.push(child);
|
||||
} else delete(child);
|
||||
if (auto child = parseObject()) {
|
||||
if (child->hidden) delete(child);
|
||||
else parent->children.push(child);
|
||||
}
|
||||
} else skip(key);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue