From 8f9527ccf187b5a34b77a3f7c302e72469258838 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 19 Feb 2025 00:04:57 +0900 Subject: [PATCH] gl_engine: support trimmed fill This commit changes the API behavior. @Issue: https://github.com/thorvg/thorvg/issues/3118 --- src/renderer/gl_engine/tvgGlGeometry.cpp | 11 +++- src/renderer/gl_engine/tvgGlTessellator.cpp | 61 +++++++-------------- src/renderer/gl_engine/tvgGlTessellator.h | 6 +- 3 files changed, 31 insertions(+), 47 deletions(-) diff --git a/src/renderer/gl_engine/tvgGlGeometry.cpp b/src/renderer/gl_engine/tvgGlGeometry.cpp index c4d4a9ed..43e3a235 100644 --- a/src/renderer/gl_engine/tvgGlGeometry.cpp +++ b/src/renderer/gl_engine/tvgGlGeometry.cpp @@ -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(); } diff --git a/src/renderer/gl_engine/tvgGlTessellator.cpp b/src/renderer/gl_engine/tvgGlTessellator.cpp index 48527aaf..fa2e944d 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.cpp +++ b/src/renderer/gl_engine/tvgGlTessellator.cpp @@ -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 &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; diff --git a/src/renderer/gl_engine/tvgGlTessellator.h b/src/renderer/gl_engine/tvgGlTessellator.h index c1c6489f..522e2b87 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.h +++ b/src/renderer/gl_engine/tvgGlTessellator.h @@ -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 &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: