mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
sw_engine: move trimming logic to TrimPath
The trim handling from sw_engine has been removed. Instead the common logic from the TrimPath structure is used. On the sw_engine side, the dashed outline is now used for both: dashed and/or trimmed strokes. @Issue: https://github.com/thorvg/thorvg/issues/2854
This commit is contained in:
parent
669d6dc580
commit
8ed4c2f302
2 changed files with 64 additions and 128 deletions
|
@ -288,7 +288,7 @@ struct SwMpool
|
||||||
{
|
{
|
||||||
SwOutline* outline;
|
SwOutline* outline;
|
||||||
SwOutline* strokeOutline;
|
SwOutline* strokeOutline;
|
||||||
SwOutline* dashOutline;
|
SwOutline* dashOutline; //Trimming treated as a special case of dashing
|
||||||
unsigned allocSize;
|
unsigned allocSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -226,14 +226,6 @@ static void _dashClose(SwDashStroke& dash, 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)
|
static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const Point* pts)
|
||||||
{
|
{
|
||||||
dash.curIdx = offIdx % dash.cnt;
|
dash.curIdx = offIdx % dash.cnt;
|
||||||
|
@ -244,112 +236,36 @@ static void _dashMoveTo(SwDashStroke& dash, uint32_t offIdx, float offset, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _trimPattern(SwDashStroke* dash, const RenderShape* rshape, float length, float trimBegin, float trimEnd)
|
static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix& transform, SwMpool* mpool, unsigned tid, bool trimmed)
|
||||||
{
|
{
|
||||||
auto begin = length * trimBegin;
|
PathCommand *cmds, *trimmedCmds = nullptr;
|
||||||
auto end = length * trimEnd;
|
Point *pts, *trimmedPts = nullptr;
|
||||||
|
uint32_t cmdCnt, ptsCnt;
|
||||||
|
|
||||||
//default
|
if (trimmed) {
|
||||||
if (end > begin) {
|
RenderPath trimmedPath;
|
||||||
if (begin > 0.0f) dash->cnt = 4;
|
if (!rshape->stroke->trim.trim(rshape->path, trimmedPath)) return nullptr;
|
||||||
else dash->cnt = 2;
|
|
||||||
//looping
|
|
||||||
} else dash->cnt = 3;
|
|
||||||
|
|
||||||
if (dash->cnt == 2) {
|
cmds = trimmedCmds = trimmedPath.cmds.data;
|
||||||
dash->pattern[0] = end - begin;
|
cmdCnt = trimmedPath.cmds.count;
|
||||||
dash->pattern[1] = length - (end - begin);
|
pts = trimmedPts = trimmedPath.pts.data;
|
||||||
} else if (dash->cnt == 3) {
|
ptsCnt = trimmedPath.pts.count;
|
||||||
dash->pattern[0] = end;
|
|
||||||
dash->pattern[1] = (begin - end);
|
trimmedPath.cmds.data = nullptr;
|
||||||
dash->pattern[2] = length - begin;
|
trimmedPath.pts.data = nullptr;
|
||||||
} else {
|
} else {
|
||||||
dash->pattern[0] = 0; //zero dash to start with a space.
|
cmds = rshape->path.cmds.data;
|
||||||
dash->pattern[1] = begin;
|
cmdCnt = rshape->path.cmds.count;
|
||||||
dash->pattern[2] = end - begin;
|
pts = rshape->path.pts.data;
|
||||||
dash->pattern[3] = length - end;
|
ptsCnt = rshape->path.pts.count;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static float _outlineLength(const RenderShape* rshape, uint32_t shiftPts, uint32_t shiftCmds, bool subpath)
|
|
||||||
{
|
|
||||||
const PathCommand* cmds = rshape->path.cmds.data + shiftCmds;
|
|
||||||
auto cmdCnt = rshape->path.cmds.count - shiftCmds;
|
|
||||||
const Point* pts = rshape->path.pts.data + shiftPts;
|
|
||||||
auto ptsCnt = rshape->path.pts.count - shiftPts;
|
|
||||||
|
|
||||||
//No actual shape data
|
|
||||||
if (cmdCnt <= 0 || ptsCnt <= 0) return 0.0f;
|
|
||||||
|
|
||||||
const Point* close = nullptr;
|
|
||||||
auto len = 0.0f;
|
|
||||||
|
|
||||||
//must begin with moveTo
|
|
||||||
if (cmds[0] == PathCommand::MoveTo) {
|
|
||||||
close = pts;
|
|
||||||
cmds++;
|
|
||||||
pts++;
|
|
||||||
cmdCnt--;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (cmdCnt-- > 0) {
|
|
||||||
switch (*cmds) {
|
|
||||||
case PathCommand::Close: {
|
|
||||||
len += length(pts - 1, close);
|
|
||||||
if (subpath) return len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PathCommand::MoveTo: {
|
|
||||||
if (subpath) return len;
|
|
||||||
close = pts;
|
|
||||||
++pts;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PathCommand::LineTo: {
|
|
||||||
len += length(pts - 1, pts);
|
|
||||||
++pts;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PathCommand::CubicTo: {
|
|
||||||
len += Bezier{*(pts - 1), *pts, *(pts + 1), *(pts + 2)}.length();
|
|
||||||
pts += 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++cmds;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix& transform, bool trimmed, SwMpool* mpool, unsigned tid)
|
|
||||||
{
|
|
||||||
const PathCommand* cmds = rshape->path.cmds.data;
|
|
||||||
auto cmdCnt = rshape->path.cmds.count;
|
|
||||||
const Point* pts = rshape->path.pts.data;
|
|
||||||
auto ptsCnt = rshape->path.pts.count;
|
|
||||||
|
|
||||||
//No actual shape data
|
//No actual shape data
|
||||||
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
||||||
|
|
||||||
auto startPts = pts;
|
|
||||||
auto startCmds = cmds;
|
|
||||||
|
|
||||||
SwDashStroke dash;
|
SwDashStroke dash;
|
||||||
auto offset = 0.0f;
|
auto offset = 0.0f;
|
||||||
dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset);
|
dash.cnt = rshape->strokeDash((const float**)&dash.pattern, &offset);
|
||||||
auto simultaneous = rshape->stroke->trim.simultaneous;
|
|
||||||
float trimBegin = 0.0f, trimEnd = 1.0f;
|
|
||||||
if (trimmed) rshape->stroke->trim.get(trimBegin, trimEnd);
|
|
||||||
|
|
||||||
if (dash.cnt == 0) {
|
|
||||||
if (trimmed) dash.pattern = (float*)malloc(sizeof(float) * 4);
|
|
||||||
else return nullptr;
|
|
||||||
} else {
|
|
||||||
//TODO: handle dash + trim - for now trimming ignoring is forced
|
|
||||||
trimmed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//offset
|
//offset
|
||||||
auto patternLength = 0.0f;
|
auto patternLength = 0.0f;
|
||||||
|
@ -373,7 +289,6 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix& trans
|
||||||
|
|
||||||
//must begin with moveTo
|
//must begin with moveTo
|
||||||
if (cmds[0] == PathCommand::MoveTo) {
|
if (cmds[0] == PathCommand::MoveTo) {
|
||||||
if (trimmed) _trimPattern(&dash, rshape, _outlineLength(rshape, 0, 0, simultaneous), trimBegin, trimEnd);
|
|
||||||
_dashMoveTo(dash, offIdx, offset, pts);
|
_dashMoveTo(dash, offIdx, offset, pts);
|
||||||
cmds++;
|
cmds++;
|
||||||
pts++;
|
pts++;
|
||||||
|
@ -386,12 +301,7 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix& trans
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::MoveTo: {
|
case PathCommand::MoveTo: {
|
||||||
if (trimmed) {
|
_dashMoveTo(dash, offIdx, offset, pts);
|
||||||
if (simultaneous) {
|
|
||||||
_trimPattern(&dash, rshape, _outlineLength(rshape, pts - startPts, cmds - startCmds, true), trimBegin, trimEnd);
|
|
||||||
_dashMoveTo(dash, offIdx, offset, pts);
|
|
||||||
} else _dashMoveTo(dash, pts);
|
|
||||||
} else _dashMoveTo(dash, offIdx, offset, pts);
|
|
||||||
++pts;
|
++pts;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -409,9 +319,10 @@ static SwOutline* _genDashOutline(const RenderShape* rshape, const Matrix& trans
|
||||||
++cmds;
|
++cmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
_outlineEnd(*dash.outline);
|
free(trimmedCmds);
|
||||||
|
free(trimmedPts);
|
||||||
|
|
||||||
if (trimmed) free(dash.pattern);
|
_outlineEnd(*dash.outline);
|
||||||
|
|
||||||
return dash.outline;
|
return dash.outline;
|
||||||
}
|
}
|
||||||
|
@ -437,18 +348,34 @@ static bool _axisAlignedRect(const SwOutline* outline)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix& transform, SwMpool* mpool, unsigned tid, bool hasComposite)
|
static SwOutline* _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix& transform, SwMpool* mpool, unsigned tid, bool hasComposite, bool trimmed = false)
|
||||||
{
|
{
|
||||||
const PathCommand* cmds = rshape->path.cmds.data;
|
PathCommand *cmds, *trimmedCmds = nullptr;
|
||||||
auto cmdCnt = rshape->path.cmds.count;
|
Point *pts, *trimmedPts = nullptr;
|
||||||
const Point* pts = rshape->path.pts.data;
|
uint32_t cmdCnt, ptsCnt;
|
||||||
auto ptsCnt = rshape->path.pts.count;
|
|
||||||
|
if (trimmed) {
|
||||||
|
RenderPath trimmedPath;
|
||||||
|
if (!rshape->stroke->trim.trim(rshape->path, trimmedPath)) return nullptr;
|
||||||
|
|
||||||
|
cmds = trimmedCmds = trimmedPath.cmds.data;
|
||||||
|
cmdCnt = trimmedPath.cmds.count;
|
||||||
|
pts = trimmedPts = trimmedPath.pts.data;
|
||||||
|
ptsCnt = trimmedPath.pts.count;
|
||||||
|
|
||||||
|
trimmedPath.cmds.data = nullptr;
|
||||||
|
trimmedPath.pts.data = nullptr;
|
||||||
|
} else {
|
||||||
|
cmds = rshape->path.cmds.data;
|
||||||
|
cmdCnt = rshape->path.cmds.count;
|
||||||
|
pts = rshape->path.pts.data;
|
||||||
|
ptsCnt = rshape->path.pts.count;
|
||||||
|
}
|
||||||
|
|
||||||
//No actual shape data
|
//No actual shape data
|
||||||
if (cmdCnt == 0 || ptsCnt == 0) return false;
|
if (cmdCnt == 0 || ptsCnt == 0) return nullptr;
|
||||||
|
|
||||||
shape->outline = mpoolReqOutline(mpool, tid);
|
auto outline = trimmed ? mpoolReqDashOutline(mpool, tid) : mpoolReqOutline(mpool, tid);
|
||||||
auto outline = shape->outline;
|
|
||||||
auto closed = false;
|
auto closed = false;
|
||||||
|
|
||||||
//Generate Outlines
|
//Generate Outlines
|
||||||
|
@ -482,10 +409,12 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix&
|
||||||
if (!closed) _outlineEnd(*outline);
|
if (!closed) _outlineEnd(*outline);
|
||||||
|
|
||||||
outline->fillRule = rshape->rule;
|
outline->fillRule = rshape->rule;
|
||||||
shape->outline = outline;
|
|
||||||
|
|
||||||
shape->fastTrack = (!hasComposite && _axisAlignedRect(shape->outline));
|
free(trimmedCmds);
|
||||||
return true;
|
free(trimmedPts);
|
||||||
|
|
||||||
|
if (!trimmed) shape->fastTrack = (!hasComposite && _axisAlignedRect(outline));
|
||||||
|
return outline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -495,7 +424,8 @@ static bool _genOutline(SwShape* shape, const RenderShape* rshape, const Matrix&
|
||||||
|
|
||||||
bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
|
bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix& transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite)
|
||||||
{
|
{
|
||||||
if (!_genOutline(shape, rshape, transform, mpool, tid, hasComposite)) return false;
|
if (auto out = _genOutline(shape, rshape, transform, mpool, tid, hasComposite)) shape->outline = out;
|
||||||
|
else return false;
|
||||||
if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
|
if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion, shape->fastTrack)) return false;
|
||||||
|
|
||||||
shape->bbox = renderRegion;
|
shape->bbox = renderRegion;
|
||||||
|
@ -581,16 +511,22 @@ bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix&
|
||||||
auto dashStroking = false;
|
auto dashStroking = false;
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
|
|
||||||
//Dash style (+trimming)
|
//Dash style with/without trimming
|
||||||
auto trimmed = rshape->strokeTrim();
|
auto trimmed = rshape->strokeTrim();
|
||||||
if (rshape->stroke->dashCnt > 0 || trimmed) {
|
if (rshape->stroke->dashCnt > 0) {
|
||||||
shapeOutline = _genDashOutline(rshape, transform, trimmed, mpool, tid);
|
shapeOutline = _genDashOutline(rshape, transform, mpool, tid, trimmed);
|
||||||
|
if (!shapeOutline) return false;
|
||||||
|
dashStroking = true;
|
||||||
|
//Trimming
|
||||||
|
} else if (trimmed) {
|
||||||
|
shapeOutline = _genOutline(shape, rshape, transform, mpool, tid, false, true);
|
||||||
if (!shapeOutline) return false;
|
if (!shapeOutline) return false;
|
||||||
dashStroking = true;
|
dashStroking = true;
|
||||||
//Normal style
|
//Normal style
|
||||||
} else {
|
} else {
|
||||||
if (!shape->outline) {
|
if (!shape->outline) {
|
||||||
if (!_genOutline(shape, rshape, transform, mpool, tid, false)) return false;
|
if (auto out = _genOutline(shape, rshape, transform, mpool, tid, false)) shape->outline = out;
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
shapeOutline = shape->outline;
|
shapeOutline = shape->outline;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue