gl_engine: fix line join while dashing

While dashing, changing the path command each time caused
a new 'move to' command to be added, even when dash segments
across different path commands should have been connected.

@Issue: https://github.com/thorvg/thorvg/issues/3231
This commit is contained in:
Mira Grudzinska 2025-02-25 00:16:02 +01:00
parent 4f7d94cd8b
commit 5114a87e3d
2 changed files with 37 additions and 10 deletions

View file

@ -2200,6 +2200,7 @@ DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t das
mCurrLen(), mCurrLen(),
mCurrIdx(), mCurrIdx(),
mCurOpGap(false), mCurOpGap(false),
mMove(true),
mPtStart(), mPtStart(),
mPtCur() mPtCur()
{ {
@ -2240,6 +2241,7 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
mCurrIdx = idx; mCurrIdx = idx;
mCurrLen = mDashPattern[idx] - offset; mCurrLen = mDashPattern[idx] - offset;
mCurOpGap = gap; mCurOpGap = gap;
mMove = true;
mPtStart = mPtCur = *pts; mPtStart = mPtCur = *pts;
pts++; pts++;
break; break;
@ -2267,24 +2269,32 @@ void DashStroke::dashLineTo(const GlPoint &to)
{ {
float len = detail::_pointLength(mPtCur - to); float len = detail::_pointLength(mPtCur - to);
if (len < mCurrLen) { if (tvg::zero(len)) {
this->moveTo(mPtCur);
} else if (len <= mCurrLen) {
mCurrLen -= len; mCurrLen -= len;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove) {
this->moveTo(mPtCur); this->moveTo(mPtCur);
mMove = false;
}
this->lineTo(to); this->lineTo(to);
} }
} else { } else {
detail::Line curr{mPtCur, to}; detail::Line curr{mPtCur, to};
while (len > mCurrLen) { while (len - mCurrLen > 0.0001f) {
detail::Line right; detail::Line right;
if (mCurrLen > 0.0f) { if (mCurrLen > 0.0f) {
detail::Line left; detail::Line left;
detail::_lineSplitAt(curr, mCurrLen, &left, &right); detail::_lineSplitAt(curr, mCurrLen, &left, &right);
len -= mCurrLen; len -= mCurrLen;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove || mDashPattern[mCurrIdx] - mCurrLen < FLOAT_EPSILON) {
this->moveTo(left.p1); this->moveTo(left.p1);
mMove = false;
}
this->lineTo(left.p2); this->lineTo(left.p2);
} }
} else right = curr; } else right = curr;
@ -2293,10 +2303,14 @@ void DashStroke::dashLineTo(const GlPoint &to)
mCurOpGap = !mCurOpGap; mCurOpGap = !mCurOpGap;
curr = right; curr = right;
mPtCur = curr.p1; mPtCur = curr.p1;
mMove = true;
} }
mCurrLen -= len; mCurrLen -= len;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove) {
this->moveTo(curr.p1); this->moveTo(curr.p1);
mMove = false;
}
this->lineTo(curr.p2); this->lineTo(curr.p2);
} }
@ -2321,21 +2335,29 @@ void DashStroke::dashCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlP
auto len = cur.length(); auto len = cur.length();
if (len < mCurrLen) { if (tvg::zero(len)) {
this->moveTo(mPtCur);
} else if (len <= mCurrLen) {
mCurrLen -= len; mCurrLen -= len;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove) {
this->moveTo(mPtCur); this->moveTo(mPtCur);
mMove = false;
}
this->cubicTo(cnt1, cnt2, end); this->cubicTo(cnt1, cnt2, end);
} }
} else { } else {
while (len > mCurrLen) { while (len - mCurrLen > 0.0001f) {
Bezier right; Bezier right;
if (mCurrLen > 0.0f) { if (mCurrLen > 0.0f) {
Bezier left; Bezier left;
cur.split(mCurrLen, left, right); cur.split(mCurrLen, left, right);
len -= mCurrLen; len -= mCurrLen;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove || mDashPattern[mCurrIdx] - mCurrLen < FLOAT_EPSILON) {
this->moveTo(left.start); this->moveTo(left.start);
mMove = false;
}
this->cubicTo(left.ctrl1, left.ctrl2, left.end); this->cubicTo(left.ctrl1, left.ctrl2, left.end);
} }
} else right = cur; } else right = cur;
@ -2344,11 +2366,15 @@ void DashStroke::dashCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlP
mCurOpGap = !mCurOpGap; mCurOpGap = !mCurOpGap;
cur = right; cur = right;
mPtCur = cur.start; mPtCur = cur.start;
mMove = true;
} }
mCurrLen -= len; mCurrLen -= len;
if (!mCurOpGap) { if (!mCurOpGap) {
if (mMove) {
this->moveTo(cur.start); this->moveTo(cur.start);
mMove = false;
}
this->cubicTo(cur.ctrl1, cur.ctrl2, cur.end); this->cubicTo(cur.ctrl1, cur.ctrl2, cur.end);
} }

View file

@ -187,6 +187,7 @@ private:
float mCurrLen; float mCurrLen;
int32_t mCurrIdx; int32_t mCurrIdx;
bool mCurOpGap; bool mCurOpGap;
bool mMove;
GlPoint mPtStart; GlPoint mPtStart;
GlPoint mPtCur; GlPoint mPtCur;
}; };