mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
lottie: implement skew transformation
Added support for skew transformation by a specified angle around a specified axis. Applied to layers and shapes, not to repeaters. @Issue: https://github.com/thorvg/thorvg/issues/2262
This commit is contained in:
parent
baaae5e416
commit
dc6ddd83f5
3 changed files with 50 additions and 2 deletions
|
@ -129,6 +129,42 @@ static void _rotationZ(Matrix* m, float degree)
|
|||
}
|
||||
|
||||
|
||||
static void _skew(Matrix* m, float angleDeg, float axisDeg)
|
||||
{
|
||||
auto angle = -mathDeg2Rad(angleDeg);
|
||||
float tanVal = tanf(angle);
|
||||
|
||||
axisDeg = fmod(axisDeg, 180.0f);
|
||||
if (fabsf(axisDeg) < 0.01f || fabsf(axisDeg - 180.0f) < 0.01f || fabsf(axisDeg + 180.0f) < 0.01f) {
|
||||
float cosVal = cosf(mathDeg2Rad(axisDeg));
|
||||
auto B = cosVal * cosVal * tanVal;
|
||||
m->e12 += B * m->e11;
|
||||
m->e22 += B * m->e21;
|
||||
return;
|
||||
} else if (fabsf(axisDeg - 90.0f) < 0.01f || fabsf(axisDeg + 90.0f) < 0.01f) {
|
||||
float sinVal = -sinf(mathDeg2Rad(axisDeg));
|
||||
auto C = sinVal * sinVal * tanVal;
|
||||
m->e11 -= C * m->e12;
|
||||
m->e21 -= C * m->e22;
|
||||
return;
|
||||
}
|
||||
|
||||
auto axis = -mathDeg2Rad(axisDeg);
|
||||
float cosVal = cosf(axis);
|
||||
float sinVal = sinf(axis);
|
||||
auto A = sinVal * cosVal * tanVal;
|
||||
auto B = cosVal * cosVal * tanVal;
|
||||
auto C = sinVal * sinVal * tanVal;
|
||||
|
||||
auto e11 = m->e11;
|
||||
auto e21 = m->e21;
|
||||
m->e11 = (1.0f - A) * e11 - C * m->e12;
|
||||
m->e12 = B * e11 + (1.0f + A) * m->e12;
|
||||
m->e21 = (1.0f - A) * e21 - C * m->e22;
|
||||
m->e22 = B * e21 + (1.0f + A) * m->e22;
|
||||
}
|
||||
|
||||
|
||||
static bool _updateTransform(LottieTransform* transform, float frameNo, bool autoOrient, Matrix& matrix, uint8_t& opacity, LottieExpressions* exps)
|
||||
{
|
||||
mathIdentity(&matrix);
|
||||
|
@ -154,6 +190,16 @@ static bool _updateTransform(LottieTransform* transform, float frameNo, bool aut
|
|||
_rotateX(&matrix, transform->rotationEx->x(frameNo, exps));
|
||||
}
|
||||
|
||||
auto skewAngle = transform->skewAngle(frameNo, exps);
|
||||
if (fabsf(skewAngle) > 0.01f) {
|
||||
// For angles where tangent explodes, the shape degenerates into an infinitely thin line.
|
||||
// This is handled by zeroing out the matrix due to finite numerical precision.
|
||||
skewAngle = fmod(skewAngle, 180.0f);
|
||||
if (fabsf(skewAngle - 90.0f) < 0.01f || fabsf(skewAngle + 90.0f) < 0.01f) return false;
|
||||
auto skewAxis = transform->skewAxis(frameNo, exps);
|
||||
_skew(&matrix, skewAngle, skewAxis);
|
||||
}
|
||||
|
||||
auto scale = transform->scale(frameNo, exps);
|
||||
mathScaleR(&matrix, scale.x * 0.01f, scale.y * 0.01f);
|
||||
|
||||
|
|
|
@ -338,6 +338,8 @@ struct LottieTransform : LottieObject
|
|||
LottiePoint scale = Point{100.0f, 100.0f};
|
||||
LottiePoint anchor = Point{0.0f, 0.0f};
|
||||
LottieOpacity opacity = 255;
|
||||
LottieFloat skewAngle = 0.0f;
|
||||
LottieFloat skewAxis = 0.0f;
|
||||
|
||||
SeparateCoord* coords = nullptr; //either a position or separate coordinates
|
||||
RotationEx* rotationEx = nullptr; //extension for 3d rotation
|
||||
|
|
|
@ -585,8 +585,8 @@ LottieTransform* LottieParser::parseTransform(bool ddd)
|
|||
else if (transform->rotationEx && KEY_AS("ry")) parseProperty<LottieProperty::Type::Float>(transform->rotationEx->y);
|
||||
else if (transform->rotationEx && KEY_AS("rz")) parseProperty<LottieProperty::Type::Float>(transform->rotation);
|
||||
else if (KEY_AS("nm")) transform->name = getStringCopy();
|
||||
//else if (KEY_AS("sk")) //TODO: skew
|
||||
//else if (KEY_AS("sa")) //TODO: skew axis
|
||||
else if (KEY_AS("sk")) parseProperty<LottieProperty::Type::Float>(transform->skewAngle);
|
||||
else if (KEY_AS("sa")) parseProperty<LottieProperty::Type::Float>(transform->skewAxis);
|
||||
else skip(key);
|
||||
}
|
||||
transform->prepare();
|
||||
|
|
Loading…
Add table
Reference in a new issue