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;
|
mStrokeWidth = strokeWidth / mMatrix.e11;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cmds = rshape->path.cmds.data;
|
PathCommand* cmds = nullptr;
|
||||||
auto cmdCnt = rshape->path.cmds.count;
|
Point* pts = nullptr;
|
||||||
auto pts = rshape->path.pts.data;
|
uint32_t cmdCnt, ptsCnt;
|
||||||
auto ptsCnt = rshape->path.pts.count;
|
|
||||||
|
|
||||||
if (rshape->strokeTrim()) {
|
if (rshape->strokeTrim()) rshape->stroke->trim.trim(rshape->path.cmds, rshape->path.pts, cmds, cmdCnt, pts, ptsCnt);
|
||||||
auto begin = 0.0f;
|
else {
|
||||||
auto end = 0.0f;
|
cmds = rshape->path.cmds.data;
|
||||||
rshape->stroke->trim.get(begin, end);
|
cmdCnt = rshape->path.cmds.count;
|
||||||
|
pts = rshape->path.pts.data;
|
||||||
if (begin == end) return;
|
ptsCnt = rshape->path.pts.count;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float *dash_pattern = nullptr;
|
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)
|
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)
|
BWTessellator::BWTessellator(Array<float>* points, Array<uint32_t>* indices): mResPoints(points), mResIndices(indices)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,6 @@ public:
|
||||||
RenderRegion bounds() const;
|
RenderRegion bounds() const;
|
||||||
|
|
||||||
private:
|
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 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);
|
||||||
|
|
||||||
|
@ -145,23 +144,6 @@ private:
|
||||||
Point mPtCur;
|
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
|
class BWTessellator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Reference in a new issue