mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
gl_engine: add offset support in dashed strokes
Offset is correctly applied to dashed strokes, properly shifting the dash pattern. @Issue: https://github.com/thorvg/thorvg/issues/3217 @Issue: https://github.com/thorvg/thorvg/issues/3223 @Issue: https://github.com/thorvg/thorvg/issues/3191
This commit is contained in:
parent
95cd0863eb
commit
acbc3b3ba9
2 changed files with 33 additions and 10 deletions
|
@ -1564,10 +1564,11 @@ void Stroker::stroke(const RenderShape *rshape)
|
||||||
}
|
}
|
||||||
|
|
||||||
const float *dash_pattern = nullptr;
|
const float *dash_pattern = nullptr;
|
||||||
auto dashCnt = rshape->strokeDash(&dash_pattern, nullptr);
|
auto dash_offset = 0.0f;
|
||||||
|
auto dashCnt = rshape->strokeDash(&dash_pattern, &dash_offset);
|
||||||
|
|
||||||
if (dashCnt == 0) doStroke(cmds, cmdCnt, pts, ptsCnt);
|
if (dashCnt == 0) doStroke(cmds, cmdCnt, pts, ptsCnt);
|
||||||
else doDashStroke(cmds, cmdCnt, pts, ptsCnt, dashCnt, dash_pattern);
|
else doDashStroke(cmds, cmdCnt, pts, ptsCnt, dashCnt, dash_pattern, dash_offset);
|
||||||
|
|
||||||
free(trimmedCmds);
|
free(trimmedCmds);
|
||||||
free(trimmedPts);
|
free(trimmedPts);
|
||||||
|
@ -1629,7 +1630,7 @@ void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Stroker::doDashStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count, uint32_t dash_count, const float *dash_pattern)
|
void Stroker::doDashStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count, uint32_t dash_count, const float *dash_pattern, float dash_offset)
|
||||||
{
|
{
|
||||||
Array<PathCommand> dash_cmds{};
|
Array<PathCommand> dash_cmds{};
|
||||||
Array<Point> dash_pts{};
|
Array<Point> dash_pts{};
|
||||||
|
@ -1637,7 +1638,7 @@ void Stroker::doDashStroke(const PathCommand *cmds, uint32_t cmd_count, const Po
|
||||||
dash_cmds.reserve(20 * cmd_count);
|
dash_cmds.reserve(20 * cmd_count);
|
||||||
dash_pts.reserve(20 * pts_count);
|
dash_pts.reserve(20 * pts_count);
|
||||||
|
|
||||||
DashStroke dash(&dash_cmds, &dash_pts, dash_count, dash_pattern);
|
DashStroke dash(&dash_cmds, &dash_pts, dash_count, dash_pattern, dash_offset);
|
||||||
dash.doStroke(cmds, cmd_count, pts, pts_count);
|
dash.doStroke(cmds, cmd_count, pts, pts_count);
|
||||||
|
|
||||||
this->doStroke(dash_cmds.data, dash_cmds.count, dash_pts.data, dash_pts.count);
|
this->doStroke(dash_cmds.data, dash_cmds.count, dash_pts.data, dash_pts.count);
|
||||||
|
@ -1974,11 +1975,12 @@ void Stroker::strokeRound(const Point& p, const Point& outDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t dash_count, const float *dash_pattern)
|
DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t dash_count, const float *dash_pattern, float dash_offset)
|
||||||
: mCmds(cmds),
|
: mCmds(cmds),
|
||||||
mPts(pts),
|
mPts(pts),
|
||||||
mDashCount(dash_count),
|
mDashCount(dash_count),
|
||||||
mDashPattern(dash_pattern),
|
mDashPattern(dash_pattern),
|
||||||
|
mDashOffset(dash_offset),
|
||||||
mCurrLen(),
|
mCurrLen(),
|
||||||
mCurrIdx(),
|
mCurrIdx(),
|
||||||
mCurOpGap(false),
|
mCurOpGap(false),
|
||||||
|
@ -1990,6 +1992,26 @@ DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t das
|
||||||
|
|
||||||
void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count)
|
void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count)
|
||||||
{
|
{
|
||||||
|
int32_t idx = 0;
|
||||||
|
auto offset = mDashOffset;
|
||||||
|
bool gap = false;
|
||||||
|
if (!tvg::zero(mDashOffset)) {
|
||||||
|
auto len = 0.0f;
|
||||||
|
for (auto i = 0; i < mDashCount; ++i) len += mDashPattern[i];
|
||||||
|
if (mDashCount % 2) len *= 2;
|
||||||
|
|
||||||
|
offset = fmodf(offset, len);
|
||||||
|
if (offset < 0) offset += len;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mDashCount * (mDashCount % 2 + 1); ++i, ++idx) {
|
||||||
|
auto curPattern = mDashPattern[i % mDashCount];
|
||||||
|
if (offset < curPattern) break;
|
||||||
|
offset -= curPattern;
|
||||||
|
gap = !gap;
|
||||||
|
}
|
||||||
|
idx = idx % mDashCount;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < cmd_count; i++) {
|
for (uint32_t i = 0; i < cmd_count; i++) {
|
||||||
switch (*cmds) {
|
switch (*cmds) {
|
||||||
case PathCommand::Close: {
|
case PathCommand::Close: {
|
||||||
|
@ -1998,9 +2020,9 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
|
||||||
}
|
}
|
||||||
case PathCommand::MoveTo: {
|
case PathCommand::MoveTo: {
|
||||||
// reset the dash state
|
// reset the dash state
|
||||||
mCurrIdx = 0;
|
mCurrIdx = idx;
|
||||||
mCurrLen = mDashPattern[0];
|
mCurrLen = mDashPattern[idx] - offset;
|
||||||
mCurOpGap = false;
|
mCurOpGap = gap;
|
||||||
mPtStart = mPtCur = *pts;
|
mPtStart = mPtCur = *pts;
|
||||||
pts++;
|
pts++;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -87,7 +87,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count);
|
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count);
|
||||||
void doDashStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, uint32_t dash_count, const float* dash_pattern);
|
void doDashStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, uint32_t dash_count, const float* dash_pattern, float dash_offset);
|
||||||
|
|
||||||
float strokeRadius() const
|
float strokeRadius() const
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,7 @@ private:
|
||||||
class DashStroke
|
class DashStroke
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DashStroke(Array<PathCommand>* cmds, Array<Point>* pts, uint32_t dash_count, const float* dash_pattern);
|
DashStroke(Array<PathCommand>* cmds, Array<Point>* pts, uint32_t dash_count, const float* dash_pattern, float dash_offset);
|
||||||
~DashStroke() = default;
|
~DashStroke() = default;
|
||||||
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count);
|
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count);
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ private:
|
||||||
Array<Point>* mPts;
|
Array<Point>* mPts;
|
||||||
uint32_t mDashCount;
|
uint32_t mDashCount;
|
||||||
const float* mDashPattern;
|
const float* mDashPattern;
|
||||||
|
float mDashOffset;
|
||||||
float mCurrLen;
|
float mCurrLen;
|
||||||
int32_t mCurrIdx;
|
int32_t mCurrIdx;
|
||||||
bool mCurOpGap;
|
bool mCurOpGap;
|
||||||
|
|
Loading…
Add table
Reference in a new issue