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) 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)) { if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) {
fill.clear(); fill.clear();
BWTessellator bwTess{&fill}; BWTessellator bwTess{&fill};
bwTess.tessellate(&rshape, matrix); bwTess.tessellate(*path, matrix);
fillRule = rshape.rule; fillRule = rshape.rule;
bounds = bwTess.bounds(); bounds = bwTess.bounds();
} }
@ -41,7 +48,7 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
stroke.clear(); stroke.clear();
Stroker stroker{&stroke, matrix}; Stroker stroker{&stroke, matrix};
stroker.stroke(&rshape); stroker.stroke(&rshape, *path);
bounds = stroker.bounds(); 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->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->buildMesh();
this->mergeVertices(); this->mergeVertices();
@ -888,12 +883,14 @@ void Tessellator::tessellate(const Array<const RenderShape *> &shapes)
this->fillRule = FillRule::NonZero; this->fillRule = FillRule::NonZero;
for (uint32_t i = 0; i < shapes.count; i++) { for (uint32_t i = 0; i < shapes.count; i++) {
auto cmds = shapes[i]->path.cmds.data; const RenderPath* path = nullptr;
auto cmdCnt = shapes[i]->path.cmds.count; RenderPath trimmedPath;
auto pts = shapes[i]->path.pts.data; if (shapes[i]->trimpath()) {
auto ptsCnt = shapes[i]->path.pts.count; 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(); 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(); mMiterLimit = rshape->strokeMiterlimit();
mStrokeCap = rshape->strokeCap(); mStrokeCap = rshape->strokeCap();
@ -1540,27 +1537,10 @@ void Stroker::stroke(const RenderShape *rshape)
mStrokeWidth = strokeWidth / mMatrix.e11; mStrokeWidth = strokeWidth / mMatrix.e11;
} }
PathCommand *cmds, *trimmedCmds = nullptr; auto cmds = path.cmds.data;
Point *pts, *trimmedPts = nullptr; auto pts = path.pts.data;
uint32_t cmdCnt = 0, ptsCnt = 0; auto cmdCnt = path.cmds.count;
auto ptsCnt = path.pts.count;
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;
}
const float *dash_pattern = nullptr; const float *dash_pattern = nullptr;
auto dash_offset = 0.0f; auto dash_offset = 0.0f;
@ -1568,9 +1548,6 @@ void Stroker::stroke(const RenderShape *rshape)
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, dash_offset); 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 cmds = path.cmds.data;
auto cmdCnt = rshape->path.cmds.count; auto cmdCnt = path.cmds.count;
auto pts = rshape->path.pts.data; auto pts = path.pts.data;
auto ptsCnt = rshape->path.pts.count; auto ptsCnt = path.pts.count;
if (ptsCnt <= 2) return; if (ptsCnt <= 2) return;

View file

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