mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-15 12:34:30 +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
7968b9668e
commit
1354613d59
3 changed files with 47 additions and 37 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"
|
||||
|
@ -230,10 +237,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, exps);
|
||||
dashes[1] = dashes[0] + stroke->dashGap(frameNo, exps);
|
||||
P(ctx->propagator)->strokeDash(dashes, 2, stroke->dashOffset(frameNo, 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, 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];
|
||||
P(ctx->propagator)->strokeDash(dashes, size, stroke->dashattr->offset(frameNo, exps));
|
||||
} else {
|
||||
ctx->propagator->stroke(nullptr, 0);
|
||||
}
|
||||
|
|
|
@ -37,36 +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, LottieExpressions* exps)
|
||||
{
|
||||
return dash(0)(frameNo, exps);
|
||||
return dashattr->values[dashattr->size++];
|
||||
}
|
||||
|
||||
float dashGap(float frameNo, LottieExpressions* exps)
|
||||
{
|
||||
return dash(2)(frameNo, exps);
|
||||
}
|
||||
|
||||
float dashSize(float frameNo, LottieExpressions* exps)
|
||||
LottieFloat& dashOffset()
|
||||
{
|
||||
auto d = dash(1)(frameNo, exps);
|
||||
if (d == 0.0f) return 0.1f;
|
||||
else return d;
|
||||
if (!dashattr) dashattr = new DashAttr;
|
||||
return dashattr->offset;
|
||||
}
|
||||
|
||||
LottieFloat width = 0.0f;
|
||||
|
@ -615,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);
|
||||
}
|
||||
|
@ -724,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);
|
||||
}
|
||||
|
|
|
@ -651,15 +651,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(key);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue