diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 407c384a..cffd3a88 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -22,6 +22,13 @@ #include #include +#ifdef _WIN32 + #include +#elif defined(__linux__) || defined(__ZEPHYR__) + #include +#else + #include +#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); } diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 4299cda7..f18f8c9f 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -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; + } + + return dashattr->values[dashattr->size++]; } - float dashOffset(float frameNo, Tween& tween, LottieExpressions* exps) - { - return dash(0)(frameNo, tween, exps); - } - float dashSize(float frameNo, Tween& tween, LottieExpressions* exps) + LottieFloat& dashOffset() { - auto d = dash(1)(frameNo, tween, exps); - return (d > 0.0f) ? d : 0.0f; - } - - float dashGap(float frameNo, Tween& tween, LottieExpressions* exps) - { - 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); } diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index b8625f74..e36c9f10 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -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(stroke->dash(idx)); + if (KEY_AS("n")) style = getString(); + else if (KEY_AS("v")) { + if (style && !strcmp("o", style)) parseProperty(stroke->dashOffset()); + else parseProperty(stroke->dashValue()); } else skip(); } }