mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
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:
parent
75477f502e
commit
c74cd42363
4 changed files with 38 additions and 9 deletions
|
@ -897,7 +897,7 @@ static void _updateTrimpath(TVG_UNUSED LottieGroup* parent, LottieObject** child
|
|||
end = (length * end) + pbegin;
|
||||
}
|
||||
|
||||
P(ctx->propagator)->strokeTrim(begin, end);
|
||||
P(ctx->propagator)->strokeTrim(begin, end, false);
|
||||
|
||||
//TODO: individual or simultaenous mode
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans
|
|||
|
||||
if (mathZero(len)) {
|
||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||
//draw the current line fully
|
||||
} else if (len < dash.curLen) {
|
||||
dash.curLen -= len;
|
||||
if (!dash.curOpGap) {
|
||||
|
@ -114,6 +115,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans
|
|||
}
|
||||
_outlineLineTo(*dash.outline, to, transform);
|
||||
}
|
||||
//draw the current line partially
|
||||
} else {
|
||||
while (len - dash.curLen > 0.0001f) {
|
||||
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};
|
||||
auto len = bezLength(cur);
|
||||
|
||||
//draw the current line fully
|
||||
if (mathZero(len)) {
|
||||
_outlineMoveTo(*dash.outline, &dash.ptCur, transform);
|
||||
} 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);
|
||||
}
|
||||
//draw the current line partially
|
||||
} else {
|
||||
while ((len - dash.curLen) > 0.0001f) {
|
||||
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.curLen = dash.pattern[dash.curIdx] - offset;
|
||||
|
@ -257,7 +269,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
|
||||
//default
|
||||
if (end > begin) {
|
||||
if (begin > 0) dash.cnt += 4;
|
||||
if (begin > 0.0f) dash.cnt += 4;
|
||||
else dash.cnt += 2;
|
||||
//looping
|
||||
} 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[1] = begin;
|
||||
dash.pattern[2] = end - begin;
|
||||
dash.pattern[3] = length - (end - begin);
|
||||
dash.pattern[3] = length - end;
|
||||
}
|
||||
|
||||
trimmed = true;
|
||||
|
@ -304,14 +316,22 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix* trans
|
|||
|
||||
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) {
|
||||
case PathCommand::Close: {
|
||||
_dashClose(dash, transform);
|
||||
break;
|
||||
}
|
||||
case PathCommand::MoveTo: {
|
||||
_dashMoveTo(dash, offIdx, offset, pts, transform);
|
||||
if (rshape->stroke->trim.individual) _dashMoveTo(dash, pts);
|
||||
else _dashMoveTo(dash, offIdx, offset, pts);
|
||||
++pts;
|
||||
break;
|
||||
}
|
||||
|
@ -349,13 +369,19 @@ static float _outlineLength(const RenderShape* rshape)
|
|||
|
||||
const Point* close = nullptr;
|
||||
auto length = 0.0f;
|
||||
auto slength = 0.0f;
|
||||
auto simutaneous = !rshape->stroke->trim.individual;
|
||||
|
||||
//Compute the whole length
|
||||
while (cmdCnt-- > 0) {
|
||||
switch (*cmds) {
|
||||
case PathCommand::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;
|
||||
}
|
||||
case PathCommand::MoveTo: {
|
||||
|
@ -376,7 +402,8 @@ static float _outlineLength(const RenderShape* rshape)
|
|||
}
|
||||
++cmds;
|
||||
}
|
||||
return length;
|
||||
if (simutaneous && slength > length) return slength;
|
||||
else return length;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ struct RenderStroke
|
|||
struct {
|
||||
float begin = 0.0f;
|
||||
float end = 1.0f;
|
||||
bool individual = false;
|
||||
} trim;
|
||||
|
||||
~RenderStroke()
|
||||
|
|
|
@ -203,7 +203,7 @@ struct Shape::Impl
|
|||
return true;
|
||||
}
|
||||
|
||||
bool strokeTrim(float begin, float end)
|
||||
bool strokeTrim(float begin, float end, bool individual)
|
||||
{
|
||||
if (!rs.stroke) {
|
||||
if (begin == 0.0f && end == 1.0f) return true;
|
||||
|
@ -214,6 +214,7 @@ struct Shape::Impl
|
|||
|
||||
rs.stroke->trim.begin = begin;
|
||||
rs.stroke->trim.end = end;
|
||||
rs.stroke->trim.individual = individual;
|
||||
flag |= RenderUpdateFlag::Stroke;
|
||||
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue