mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
lottie: ++ dashed stroke support
Until now lottie loader supported only a single dash-gap pair, and only the case where only the dash was provided was handled correctly. When both values were provided, the gap was incorrectly increased by the dash value. If more values were supplied, only the last pair was considered. @Issue: https://github.com/thorvg/thorvg/issues/3191
This commit is contained in:
parent
a933465430
commit
391777091c
3 changed files with 45 additions and 34 deletions
|
@ -22,6 +22,13 @@
|
|||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h>
|
||||
#elif defined(__linux__) || defined(__ZEPHYR__)
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgMath.h"
|
||||
|
@ -220,10 +227,15 @@ static void _updateStroke(LottieStroke* stroke, float frameNo, RenderContext* ct
|
|||
ctx->propagator->strokeMiterlimit(stroke->miterLimit);
|
||||
|
||||
if (stroke->dashattr) {
|
||||
float dashes[2];
|
||||
dashes[0] = stroke->dashSize(frameNo, tween, exps);
|
||||
dashes[1] = dashes[0] + stroke->dashGap(frameNo, tween, exps);
|
||||
ctx->propagator->strokeDash(dashes, 2, stroke->dashOffset(frameNo, tween, exps));
|
||||
auto size = stroke->dashattr->size == 1 ? 2 : stroke->dashattr->size;
|
||||
auto dashes = (float*)alloca(size * sizeof(float));
|
||||
for (uint8_t i = 0; i < stroke->dashattr->size; ++i) {
|
||||
auto value = stroke->dashattr->values[i](frameNo, tween, exps);
|
||||
//FIXME: allow the zero value in the engine level.
|
||||
dashes[i] = value < FLT_EPSILON ? 0.01f : value;
|
||||
}
|
||||
if (stroke->dashattr->size == 1) dashes[1] = dashes[0];
|
||||
ctx->propagator->strokeDash(dashes, size, stroke->dashattr->offset(frameNo, tween, exps));
|
||||
} else {
|
||||
ctx->propagator->strokeDash(nullptr, 0);
|
||||
}
|
||||
|
|
|
@ -37,35 +37,39 @@ struct LottieStroke
|
|||
{
|
||||
struct DashAttr
|
||||
{
|
||||
//0: offset, 1: dash, 2: gap
|
||||
LottieFloat value[3] = {0.0f, 0.0f, 0.0f};
|
||||
LottieFloat offset = 0.0f;
|
||||
LottieFloat* values = nullptr;
|
||||
uint8_t size = 0;
|
||||
uint8_t allocated = 0;
|
||||
};
|
||||
|
||||
virtual ~LottieStroke()
|
||||
{
|
||||
if (dashattr) delete[] dashattr->values;
|
||||
delete(dashattr);
|
||||
}
|
||||
|
||||
LottieFloat& dash(int no)
|
||||
|
||||
LottieFloat& dashValue()
|
||||
{
|
||||
if (!dashattr) dashattr = new DashAttr;
|
||||
return dashattr->value[no];
|
||||
|
||||
if (dashattr->size + 1 > dashattr->allocated) {
|
||||
dashattr->allocated = dashattr->size + 2;
|
||||
auto newValues = new LottieFloat[dashattr->allocated];
|
||||
for (uint8_t i = 0; i < dashattr->size; ++i) newValues[i] = LottieFloat(dashattr->values[i]);
|
||||
delete[] dashattr->values;
|
||||
dashattr->values = newValues;
|
||||
}
|
||||
|
||||
float dashOffset(float frameNo, Tween& tween, LottieExpressions* exps)
|
||||
{
|
||||
return dash(0)(frameNo, tween, exps);
|
||||
return dashattr->values[dashattr->size++];
|
||||
}
|
||||
|
||||
float dashSize(float frameNo, Tween& tween, LottieExpressions* exps)
|
||||
{
|
||||
auto d = dash(1)(frameNo, tween, exps);
|
||||
return (d > 0.0f) ? d : 0.0f;
|
||||
}
|
||||
|
||||
float dashGap(float frameNo, Tween& tween, LottieExpressions* exps)
|
||||
LottieFloat& dashOffset()
|
||||
{
|
||||
return dash(2)(frameNo, tween, exps);
|
||||
if (!dashattr) dashattr = new DashAttr;
|
||||
return dashattr->offset;
|
||||
}
|
||||
|
||||
LottieFloat width = 0.0f;
|
||||
|
@ -614,9 +618,8 @@ struct LottieSolidStroke : LottieSolid, LottieStroke
|
|||
{
|
||||
if (width.ix == ix) return &width;
|
||||
if (dashattr) {
|
||||
if (dashattr->value[0].ix == ix) return &dashattr->value[0];
|
||||
if (dashattr->value[1].ix == ix) return &dashattr->value[1];
|
||||
if (dashattr->value[2].ix == ix) return &dashattr->value[2];
|
||||
for (uint8_t i = 0; i < dashattr->size ; ++i)
|
||||
if (dashattr->values[i].ix == ix) return &dashattr->values[i];
|
||||
}
|
||||
return LottieSolid::property(ix);
|
||||
}
|
||||
|
@ -723,9 +726,8 @@ struct LottieGradientStroke : LottieGradient, LottieStroke
|
|||
{
|
||||
if (width.ix == ix) return &width;
|
||||
if (dashattr) {
|
||||
if (dashattr->value[0].ix == ix) return &dashattr->value[0];
|
||||
if (dashattr->value[1].ix == ix) return &dashattr->value[1];
|
||||
if (dashattr->value[2].ix == ix) return &dashattr->value[2];
|
||||
for (uint8_t i = 0; i < dashattr->size ; ++i)
|
||||
if (dashattr->values[i].ix == ix) return &dashattr->values[i];
|
||||
}
|
||||
return LottieGradient::property(ix);
|
||||
}
|
||||
|
|
|
@ -612,15 +612,12 @@ void LottieParser::parseStrokeDash(LottieStroke* stroke)
|
|||
enterArray();
|
||||
while (nextArrayValue()) {
|
||||
enterObject();
|
||||
int idx = 0;
|
||||
const char* style = nullptr;
|
||||
while (auto key = nextObjectKey()) {
|
||||
if (KEY_AS("n")) {
|
||||
auto style = getString();
|
||||
if (!strcmp("o", style)) idx = 0; //offset
|
||||
else if (!strcmp("d", style)) idx = 1; //dash
|
||||
else if (!strcmp("g", style)) idx = 2; //gap
|
||||
} else if (KEY_AS("v")) {
|
||||
parseProperty<LottieProperty::Type::Float>(stroke->dash(idx));
|
||||
if (KEY_AS("n")) style = getString();
|
||||
else if (KEY_AS("v")) {
|
||||
if (style && !strcmp("o", style)) parseProperty<LottieProperty::Type::Float>(stroke->dashOffset());
|
||||
else parseProperty<LottieProperty::Type::Float>(stroke->dashValue());
|
||||
} else skip();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue