gl_engine: support trimmed fill

This commit changes the API behavior.

@Issue: https://github.com/thorvg/thorvg/issues/3118
This commit is contained in:
Mira Grudzinska 2025-02-19 00:04:57 +09:00 committed by Hermet Park
parent 05a5a7ea0b
commit 8f9527ccf1
3 changed files with 31 additions and 47 deletions

View file

@ -28,11 +28,18 @@
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
{
const RenderPath* path = nullptr;
RenderPath trimmedPath;
if (rshape.trimpath()) {
if (!rshape.stroke->trim.trim(rshape.path, trimmedPath)) return true;
path = &trimmedPath;
} else path = &rshape.path;
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) {
fill.clear();
BWTessellator bwTess{&fill};
bwTess.tessellate(&rshape, matrix);
bwTess.tessellate(*path, matrix);
fillRule = rshape.rule;
bounds = bwTess.bounds();
}
@ -41,7 +48,7 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
stroke.clear();
Stroker stroker{&stroke, matrix};
stroker.stroke(&rshape);
stroker.stroke(&rshape, *path);
bounds = stroker.bounds();
}

View file

@ -850,16 +850,11 @@ Tessellator::~Tessellator()
}
bool Tessellator::tessellate(const RenderShape *rshape, bool antialias)
bool Tessellator::tessellate(const RenderShape *rshape, const RenderPath& path, bool antialias)
{
auto cmds = rshape->path.cmds.data;
auto cmdCnt = rshape->path.cmds.count;
auto pts = rshape->path.pts.data;
auto ptsCnt = rshape->path.pts.count;
this->fillRule = rshape->rule;
this->visitShape(cmds, cmdCnt, pts, ptsCnt);
this->visitShape(path.cmds.data, path.cmds.count, path.pts.data, path.pts.count);
this->buildMesh();
this->mergeVertices();
@ -888,12 +883,14 @@ void Tessellator::tessellate(const Array<const RenderShape *> &shapes)
this->fillRule = FillRule::NonZero;
for (uint32_t i = 0; i < shapes.count; i++) {
auto cmds = shapes[i]->path.cmds.data;
auto cmdCnt = shapes[i]->path.cmds.count;
auto pts = shapes[i]->path.pts.data;
auto ptsCnt = shapes[i]->path.pts.count;
const RenderPath* path = nullptr;
RenderPath trimmedPath;
if (shapes[i]->trimpath()) {
if (!shapes[i]->stroke->trim.trim(shapes[i]->path, trimmedPath)) continue;
path = &trimmedPath;
} else path = &shapes[i]->path;
this->visitShape(cmds, cmdCnt, pts, ptsCnt);
this->visitShape(path->cmds.data, path->cmds.count, path->pts.data, path->pts.count);
}
this->buildMesh();
@ -1527,7 +1524,7 @@ Stroker::Stroker(GlGeometryBuffer* buffer, const Matrix& matrix) : mBuffer(buffe
}
void Stroker::stroke(const RenderShape *rshape)
void Stroker::stroke(const RenderShape *rshape, const RenderPath& path)
{
mMiterLimit = rshape->strokeMiterlimit();
mStrokeCap = rshape->strokeCap();
@ -1540,27 +1537,10 @@ void Stroker::stroke(const RenderShape *rshape)
mStrokeWidth = strokeWidth / mMatrix.e11;
}
PathCommand *cmds, *trimmedCmds = nullptr;
Point *pts, *trimmedPts = nullptr;
uint32_t cmdCnt = 0, ptsCnt = 0;
if (rshape->trimpath()) {
RenderPath trimmedPath;
if (!rshape->stroke->trim.trim(rshape->path, trimmedPath)) return;
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;
}
auto cmds = path.cmds.data;
auto pts = path.pts.data;
auto cmdCnt = path.cmds.count;
auto ptsCnt = path.pts.count;
const float *dash_pattern = nullptr;
auto dash_offset = 0.0f;
@ -1568,9 +1548,6 @@ void Stroker::stroke(const RenderShape *rshape)
if (dashCnt == 0) doStroke(cmds, cmdCnt, pts, ptsCnt);
else doDashStroke(cmds, cmdCnt, pts, ptsCnt, dashCnt, dash_pattern, dash_offset);
tvg::free(trimmedCmds);
tvg::free(trimmedPts);
}
@ -2169,12 +2146,12 @@ BWTessellator::BWTessellator(GlGeometryBuffer* buffer): mBuffer(buffer)
}
void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix)
void BWTessellator::tessellate(const RenderPath& path, const Matrix& matrix)
{
auto cmds = rshape->path.cmds.data;
auto cmdCnt = rshape->path.cmds.count;
auto pts = rshape->path.pts.data;
auto ptsCnt = rshape->path.pts.count;
auto cmds = path.cmds.data;
auto cmdCnt = path.cmds.count;
auto pts = path.pts.data;
auto ptsCnt = path.pts.count;
if (ptsCnt <= 2) return;

View file

@ -43,7 +43,7 @@ class Tessellator final
public:
Tessellator(GlGeometryBuffer* buffer);
~Tessellator();
bool tessellate(const RenderShape *rshape, bool antialias = false);
bool tessellate(const RenderShape *rshape, const RenderPath& path, bool antialias = false);
void tessellate(const Array<const RenderShape*> &shapes);
private:
@ -81,7 +81,7 @@ class Stroker
public:
Stroker(GlGeometryBuffer* buffer, const Matrix& matrix);
~Stroker() = default;
void stroke(const RenderShape *rshape);
void stroke(const RenderShape *rshape, const RenderPath& path);
RenderRegion bounds() const;
private:
@ -148,7 +148,7 @@ class BWTessellator
public:
BWTessellator(GlGeometryBuffer* buffer);
~BWTessellator() = default;
void tessellate(const RenderShape *rshape, const Matrix& matrix);
void tessellate(const RenderPath& path, const Matrix& matrix);
RenderRegion bounds() const;
private: