mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-09 14:13:43 +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;
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue