sw_engine: revised the trimpath dash line logic

Support the TrimPath modes (individual/simultaneous)
internally in the engine to handle them efficiently.
This commit is contained in:
Hermet Park 2024-03-31 12:40:44 +09:00 committed by Hermet Park
parent 75477f502e
commit c74cd42363
4 changed files with 38 additions and 9 deletions

View file

@ -897,7 +897,7 @@ static void _updateTrimpath(TVG_UNUSED LottieGroup* parent, LottieObject** child
end = (length * end) + pbegin; end = (length * end) + pbegin;
} }
P(ctx->propagator)->strokeTrim(begin, end); P(ctx->propagator)->strokeTrim(begin, end, false);
//TODO: individual or simultaenous mode //TODO: individual or simultaenous mode
} }

View file

@ -105,6 +105,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans
if (mathZero(len)) { if (mathZero(len)) {
_outlineMoveTo(*dash.outline, &dash.ptCur, transform); _outlineMoveTo(*dash.outline, &dash.ptCur, transform);
//draw the current line fully
} else if (len < dash.curLen) { } else if (len < dash.curLen) {
dash.curLen -= len; dash.curLen -= len;
if (!dash.curOpGap) { if (!dash.curOpGap) {
@ -114,6 +115,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans
} }
_outlineLineTo(*dash.outline, to, transform); _outlineLineTo(*dash.outline, to, transform);
} }
//draw the current line partially
} else { } else {
while (len - dash.curLen > 0.0001f) { while (len - dash.curLen > 0.0001f) {
Line left, right; Line left, right;
@ -162,6 +164,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to}; Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to};
auto len = bezLength(cur); auto len = bezLength(cur);
//draw the current line fully
if (mathZero(len)) { if (mathZero(len)) {
_outlineMoveTo(*dash.outline, &dash.ptCur, transform); _outlineMoveTo(*dash.outline, &dash.ptCur, transform);
} else if (len < dash.curLen) { } else if (len < dash.curLen) {
@ -173,6 +176,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct
} }
_outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform); _outlineCubicTo(*dash.outline, ctrl1, ctrl2, to, transform);
} }
//draw the current line partially
} else { } else {
while ((len - dash.curLen) > 0.0001f) { while ((len - dash.curLen) > 0.0001f) {
Bezier left, right; Bezier left, right;
@ -222,7 +226,15 @@ static void _dashClose(SwDashStroke& dash, const Matrix* transform)
} }
static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts, const Matrix* transform) static void _dashMoveTo(SwDashStroke& dash, const Point* pts)
{
dash.ptCur = *pts;
dash.ptStart = *pts;
dash.move = true;
}
static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts)
{ {
dash.curIdx = offIdx % dash.cnt; dash.curIdx = offIdx % dash.cnt;
dash.curLen = dash.pattern[dash.curIdx] - offset; dash.curLen = dash.pattern[dash.curIdx] - offset;
@ -257,7 +269,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
//default //default
if (end > begin) { if (end > begin) {
if (begin > 0) dash.cnt += 4; if (begin > 0.0f) dash.cnt += 4;
else dash.cnt += 2; else dash.cnt += 2;
//looping //looping
} else dash.cnt += 3; } else dash.cnt += 3;
@ -275,7 +287,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
dash.pattern[0] = 0; //zero dash to start with a space. dash.pattern[0] = 0; //zero dash to start with a space.
dash.pattern[1] = begin; dash.pattern[1] = begin;
dash.pattern[2] = end - begin; dash.pattern[2] = end - begin;
dash.pattern[3] = length - (end - begin); dash.pattern[3] = length - end;
} }
trimmed = true; trimmed = true;
@ -304,14 +316,22 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
dash.outline = mpoolReqDashOutline(mpool, tid); dash.outline = mpoolReqDashOutline(mpool, tid);
while (cmdCnt-- > 0) { //must begin with moveTo
if (cmds[0] == PathCommand::MoveTo) {
_dashMoveTo(dash, offIdx, offset, pts);
cmds++;
pts++;
}
while (--cmdCnt > 0) {
switch (*cmds) { switch (*cmds) {
case PathCommand::Close: { case PathCommand::Close: {
_dashClose(dash, transform); _dashClose(dash, transform);
break; break;
} }
case PathCommand::MoveTo: { case PathCommand::MoveTo: {
_dashMoveTo(dash, offIdx, offset, pts, transform); if (rshape->stroke->trim.individual) _dashMoveTo(dash, pts);
else _dashMoveTo(dash, offIdx, offset, pts);
++pts; ++pts;
break; break;
} }
@ -349,13 +369,19 @@ static float _outlineLength(const RenderShape* rshape)
const Point* close = nullptr; const Point* close = nullptr;
auto length = 0.0f; auto length = 0.0f;
auto slength = 0.0f;
auto simutaneous = !rshape->stroke->trim.individual;
//Compute the whole length //Compute the whole length
while (cmdCnt-- > 0) { while (cmdCnt-- > 0) {
switch (*cmds) { switch (*cmds) {
case PathCommand::Close: { case PathCommand::Close: {
length += mathLength(pts - 1, close); length += mathLength(pts - 1, close);
++pts; //retrieve the max length of the shape if the simultaneous mode.
if (simutaneous && slength < length) {
slength = length;
length = 0.0f;
}
break; break;
} }
case PathCommand::MoveTo: { case PathCommand::MoveTo: {
@ -376,7 +402,8 @@ static float _outlineLength(const RenderShape* rshape)
} }
++cmds; ++cmds;
} }
return length; if (simutaneous && slength > length) return slength;
else return length;
} }

View file

@ -161,6 +161,7 @@ struct RenderStroke
struct { struct {
float begin = 0.0f; float begin = 0.0f;
float end = 1.0f; float end = 1.0f;
bool individual = false;
} trim; } trim;
~RenderStroke() ~RenderStroke()

View file

@ -203,7 +203,7 @@ struct Shape::Impl
return true; return true;
} }
bool strokeTrim(float begin, float end) bool strokeTrim(float begin, float end, bool individual)
{ {
if (!rs.stroke) { if (!rs.stroke) {
if (begin == 0.0f && end == 1.0f) return true; if (begin == 0.0f && end == 1.0f) return true;
@ -214,6 +214,7 @@ struct Shape::Impl
rs.stroke->trim.begin = begin; rs.stroke->trim.begin = begin;
rs.stroke->trim.end = end; rs.stroke->trim.end = end;
rs.stroke->trim.individual = individual;
flag |= RenderUpdateFlag::Stroke; flag |= RenderUpdateFlag::Stroke;
return true; return true;