mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-07 21:23:32 +00:00
gl_engine: apply common trimming logic
The trim-related implementation has been removed and replaced with the one available in common. @Issue: https://github.com/thorvg/thorvg/issues/2854
This commit is contained in:
parent
a046abc47b
commit
11a029c99d
2 changed files with 9 additions and 323 deletions
|
@ -1541,26 +1541,16 @@ void Stroker::stroke(const RenderShape *rshape)
|
|||
mStrokeWidth = strokeWidth / mMatrix.e11;
|
||||
}
|
||||
|
||||
auto cmds = rshape->path.cmds.data;
|
||||
auto cmdCnt = rshape->path.cmds.count;
|
||||
auto pts = rshape->path.pts.data;
|
||||
auto ptsCnt = rshape->path.pts.count;
|
||||
PathCommand* cmds = nullptr;
|
||||
Point* pts = nullptr;
|
||||
uint32_t cmdCnt, ptsCnt;
|
||||
|
||||
if (rshape->strokeTrim()) {
|
||||
auto begin = 0.0f;
|
||||
auto end = 0.0f;
|
||||
rshape->stroke->trim.get(begin, end);
|
||||
|
||||
if (begin == end) return;
|
||||
|
||||
if (begin > end) {
|
||||
doTrimStroke(cmds, cmdCnt, pts, ptsCnt, rshape->stroke->trim.simultaneous, begin, 1.0f);
|
||||
doTrimStroke(cmds, cmdCnt, pts, ptsCnt, rshape->stroke->trim.simultaneous, 0.0f, end);
|
||||
} else {
|
||||
doTrimStroke(cmds, cmdCnt, pts, ptsCnt, rshape->stroke->trim.simultaneous, begin, end);
|
||||
}
|
||||
|
||||
return;
|
||||
if (rshape->strokeTrim()) rshape->stroke->trim.trim(rshape->path.cmds, rshape->path.pts, cmds, cmdCnt, pts, ptsCnt);
|
||||
else {
|
||||
cmds = rshape->path.cmds.data;
|
||||
cmdCnt = rshape->path.cmds.count;
|
||||
pts = rshape->path.pts.data;
|
||||
ptsCnt = rshape->path.pts.count;
|
||||
}
|
||||
|
||||
const float *dash_pattern = nullptr;
|
||||
|
@ -1581,76 +1571,6 @@ RenderRegion Stroker::bounds() const
|
|||
};
|
||||
}
|
||||
|
||||
void Stroker::doTrimStroke(const PathCommand* cmds, uint32_t cmdCnt, const Point* pts, uint32_t ptsCnt, bool simultaneous, float start, float end)
|
||||
{
|
||||
if (simultaneous) {
|
||||
auto startCmds = cmds;
|
||||
auto currCmds = cmds;
|
||||
int ptsNum = 0;
|
||||
for (uint32_t i = 0; i < cmdCnt; i++) {
|
||||
switch (*currCmds) {
|
||||
case PathCommand::MoveTo: {
|
||||
if (currCmds != startCmds) {
|
||||
PathTrim trim{};
|
||||
if (trim.trim(startCmds, currCmds - startCmds, pts, ptsNum, start, end)) {
|
||||
const auto& sCmds = trim.cmds();
|
||||
const auto& sPts = trim.pts();
|
||||
doStroke(sCmds.data, sCmds.count, sPts.data, sPts.count);
|
||||
}
|
||||
startCmds = currCmds;
|
||||
pts += ptsNum;
|
||||
ptsNum = 0;
|
||||
}
|
||||
currCmds++;
|
||||
ptsNum++;
|
||||
break;
|
||||
}
|
||||
case PathCommand::LineTo:
|
||||
currCmds++;
|
||||
ptsNum++;
|
||||
break;
|
||||
case PathCommand::CubicTo:
|
||||
currCmds++;
|
||||
ptsNum += 3;
|
||||
break;
|
||||
case PathCommand::Close: {
|
||||
PathTrim trim{};
|
||||
currCmds++;
|
||||
if (trim.trim(startCmds, currCmds - startCmds, pts, ptsNum, start, end)) {
|
||||
const auto& sCmds = trim.cmds();
|
||||
const auto& sPts = trim.pts();
|
||||
doStroke(sCmds.data, sCmds.count, sPts.data, sPts.count);
|
||||
}
|
||||
startCmds = currCmds;
|
||||
pts += ptsNum;
|
||||
ptsNum = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startCmds != currCmds && ptsNum > 0) {
|
||||
PathTrim trim{};
|
||||
|
||||
if (trim.trim(startCmds, currCmds - startCmds, pts, ptsNum, start, end)) {
|
||||
const auto& sCmds = trim.cmds();
|
||||
const auto& sPts = trim.pts();
|
||||
doStroke(sCmds.data, sCmds.count, sPts.data, sPts.count);
|
||||
}
|
||||
startCmds = currCmds;
|
||||
pts += ptsNum;
|
||||
ptsNum = 0;
|
||||
}
|
||||
} else {
|
||||
PathTrim trim{};
|
||||
if (trim.trim(cmds, cmdCnt, pts, ptsCnt, start, end)) {
|
||||
const auto& sCmds = trim.cmds();
|
||||
const auto& sPts = trim.pts();
|
||||
doStroke(sCmds.data, sCmds.count, sPts.data, sPts.count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count)
|
||||
{
|
||||
|
@ -2209,222 +2129,6 @@ void DashStroke::cubicTo(const Point& cnt1, const Point& cnt2, const Point& end)
|
|||
}
|
||||
|
||||
|
||||
bool PathTrim::trim(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, float start, float end)
|
||||
{
|
||||
if (end - start < 0.0001f) return false;
|
||||
|
||||
auto len = pathLength(cmds, cmd_count, pts, pts_count);
|
||||
if (len < 0.001f) return false;
|
||||
|
||||
auto startLength = len * start;
|
||||
auto endLength = len * end;
|
||||
if (startLength >= endLength) return false;
|
||||
|
||||
trimPath(cmds, cmd_count, pts, pts_count, startLength, endLength);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
float PathTrim::pathLength(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count)
|
||||
{
|
||||
auto len = 0.0f;
|
||||
Point zero = {0.0f, 0.0f};
|
||||
const Point* prev = nullptr;
|
||||
const Point* begin = nullptr;
|
||||
|
||||
for (uint32_t i = 0; i < cmd_count; i++) {
|
||||
switch (cmds[i]) {
|
||||
case PathCommand::MoveTo: {
|
||||
prev = pts;
|
||||
begin = pts;
|
||||
pts++;
|
||||
break;
|
||||
}
|
||||
case PathCommand::LineTo: {
|
||||
if (prev != nullptr) len += length(prev, pts);
|
||||
if (begin == nullptr) begin = pts;
|
||||
prev = pts;
|
||||
pts++;
|
||||
break;
|
||||
}
|
||||
case PathCommand::CubicTo: {
|
||||
if (prev == nullptr || begin == nullptr) {
|
||||
prev = begin = &zero;
|
||||
}
|
||||
Bezier b{ *prev, pts[0], pts[1], pts[2]};
|
||||
len += b.length();
|
||||
prev = pts + 2;
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
case PathCommand::Close: {
|
||||
if (prev != nullptr && begin != nullptr && prev != begin) {
|
||||
len += length(prev, begin);
|
||||
}
|
||||
prev = begin = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
void PathTrim::trimPath(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, float start, float end)
|
||||
{
|
||||
auto pos = 0.0f;
|
||||
Point zero = {0.0f, 0.0f};
|
||||
Point prev = {};
|
||||
Point begin = {};
|
||||
auto closed = true;
|
||||
auto pushedMoveTo = false;
|
||||
auto hasLineTo = false;
|
||||
|
||||
auto handle_line_to = [&](const Point* p1, const Point* p2) {
|
||||
auto currLen = length(p1, p2);
|
||||
if (pos + currLen <= start) {
|
||||
pos += currLen;
|
||||
prev = *p2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos >= end) {
|
||||
prev = *p2;
|
||||
return;
|
||||
}
|
||||
|
||||
Line line{*p1, *p2};
|
||||
|
||||
if (pos < start) {
|
||||
Line left, right;
|
||||
line.split(start - pos, left, right);
|
||||
|
||||
pos += left.length();
|
||||
line = right;
|
||||
}
|
||||
|
||||
if (pos + currLen > end) {
|
||||
Line left, right;
|
||||
line.split(end - pos, left, right);
|
||||
pos += left.length();
|
||||
line = left;
|
||||
}
|
||||
|
||||
if (!pushedMoveTo) {
|
||||
mCmds.push(PathCommand::MoveTo);
|
||||
mPts.push(line.pt1);
|
||||
pushedMoveTo = true;
|
||||
begin = line.pt1;
|
||||
}
|
||||
|
||||
pos += line.length();
|
||||
|
||||
mCmds.push(PathCommand::LineTo);
|
||||
mPts.push(line.pt2);
|
||||
prev = line.pt2;
|
||||
hasLineTo = true;
|
||||
closed = false;
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < cmd_count; i++) {
|
||||
if (pos - end > 0.001f) return; // we are done
|
||||
|
||||
if (pos >= end) return;
|
||||
|
||||
switch (cmds[i]) {
|
||||
case PathCommand::MoveTo: {
|
||||
prev = *pts;
|
||||
begin = *pts;
|
||||
pts++;
|
||||
closed = false;
|
||||
break;
|
||||
}
|
||||
case PathCommand::LineTo: {
|
||||
handle_line_to(&prev, pts);
|
||||
hasLineTo = true;
|
||||
pts++;
|
||||
break;
|
||||
}
|
||||
case PathCommand::CubicTo: {
|
||||
Bezier b{ prev, pts[0], pts[1], pts[2]};
|
||||
|
||||
auto currLen = b.length();
|
||||
if (pos + currLen <= start) {
|
||||
pos += currLen;
|
||||
prev = pts[2];
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos < start) {
|
||||
Bezier left, right;
|
||||
b.split(start - pos, left, right);
|
||||
pos += left.length();
|
||||
b = right;
|
||||
}
|
||||
|
||||
if (pos + currLen > end) {
|
||||
Bezier left, right;
|
||||
b.split(end - pos, left, right);
|
||||
pos += left.length();
|
||||
b = left;
|
||||
}
|
||||
|
||||
if (!pushedMoveTo) {
|
||||
mCmds.push(PathCommand::MoveTo);
|
||||
mPts.push(b.start);
|
||||
pushedMoveTo = true;
|
||||
}
|
||||
|
||||
|
||||
pos += b.length();
|
||||
mCmds.push(PathCommand::CubicTo);
|
||||
mPts.push(b.ctrl1);
|
||||
mPts.push(b.ctrl2);
|
||||
mPts.push(b.end);
|
||||
prev = b.end;
|
||||
hasLineTo = true;
|
||||
closed = false;
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
case PathCommand::Close: {
|
||||
if (closed) break;
|
||||
if (!hasLineTo) {
|
||||
closed = true;
|
||||
pushedMoveTo = false;
|
||||
prev = begin = zero;
|
||||
break;
|
||||
}
|
||||
if (prev == begin) {
|
||||
prev = begin = zero;
|
||||
closed = true;
|
||||
pushedMoveTo = false;
|
||||
break;
|
||||
}
|
||||
auto currLen = length(&prev, &begin);
|
||||
if (currLen + pos < start) {
|
||||
pos += currLen;
|
||||
break;
|
||||
}
|
||||
if (pos + currLen <= end) {
|
||||
mCmds.push(PathCommand::Close);
|
||||
pos += currLen;
|
||||
break;
|
||||
}
|
||||
// handle_line_to(&prev, &begin);
|
||||
closed = true;
|
||||
pushedMoveTo = false;
|
||||
prev = begin = zero;
|
||||
pos += currLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BWTessellator::BWTessellator(Array<float>* points, Array<uint32_t>* indices): mResPoints(points), mResIndices(indices)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -86,7 +86,6 @@ public:
|
|||
RenderRegion bounds() const;
|
||||
|
||||
private:
|
||||
void doTrimStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, bool simultaneous, float start, float end);
|
||||
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);
|
||||
|
||||
|
@ -145,23 +144,6 @@ private:
|
|||
Point mPtCur;
|
||||
};
|
||||
|
||||
class PathTrim
|
||||
{
|
||||
public:
|
||||
PathTrim(): mCmds(), mPts() {}
|
||||
~PathTrim() = default;
|
||||
bool trim(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, float start, float end);
|
||||
const Array<PathCommand>& cmds() const { return mCmds; }
|
||||
const Array<Point>& pts() const { return mPts; }
|
||||
|
||||
private:
|
||||
float pathLength(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count);
|
||||
void trimPath(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, float start, float end);
|
||||
|
||||
Array<PathCommand> mCmds;
|
||||
Array<Point> mPts;
|
||||
};
|
||||
|
||||
class BWTessellator
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Add table
Reference in a new issue