gl_engine: ++neat code (#3319)

This commit is contained in:
Hermet Park 2025-03-11 19:16:58 +09:00 committed by GitHub
parent 6f9fd6ff01
commit 24378cc200
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 49 additions and 86 deletions

View file

@ -850,77 +850,47 @@ Tessellator::~Tessellator()
} }
bool Tessellator::tessellate(const RenderShape *rshape, const RenderPath& path, bool antialias)
{
this->fillRule = rshape->rule;
this->visitShape(path.cmds.data, path.cmds.count, path.pts.data, path.pts.count);
this->buildMesh();
this->mergeVertices();
if (!this->simplifyMesh()) return false;
if (!this->tessMesh()) return false;
// output triangles
for (auto poly = this->pPolygon; poly; poly = poly->next) {
if (!this->matchFillRule(poly->winding)) continue;
if (poly->count < 3) continue;
for (auto m = poly->head; m; m = m->next) {
this->emitPoly(m);
}
}
if (antialias) {
// TODO extract outline from current polygon list and generate aa edges
}
return true;
}
void Tessellator::tessellate(const Array<const RenderShape*> &shapes) void Tessellator::tessellate(const Array<const RenderShape*> &shapes)
{ {
this->fillRule = FillRule::NonZero; fillRule = FillRule::NonZero;
for (uint32_t i = 0; i < shapes.count; i++) { for (uint32_t i = 0; i < shapes.count; i++) {
const RenderPath* path = nullptr;
RenderPath trimmedPath; RenderPath trimmedPath;
if (shapes[i]->trimpath()) { if (shapes[i]->trimpath()) {
if (!shapes[i]->stroke->trim.trim(shapes[i]->path, trimmedPath)) continue; if (!shapes[i]->stroke->trim.trim(shapes[i]->path, trimmedPath)) continue;
path = &trimmedPath; visitShape(trimmedPath);
} else path = &shapes[i]->path; } else visitShape(shapes[i]->path);
this->visitShape(path->cmds.data, path->cmds.count, path->pts.data, path->pts.count);
} }
this->buildMesh(); buildMesh();
this->mergeVertices(); mergeVertices();
this->simplifyMesh(); simplifyMesh();
this->tessMesh(); tessMesh();
// output triangles // output triangles
for (auto poly = this->pPolygon; poly; poly = poly->next) { for (auto poly = pPolygon; poly; poly = poly->next) {
if (!this->matchFillRule(poly->winding)) continue; if (!matchFillRule(poly->winding)) continue;
if (poly->count < 3) continue; if (poly->count < 3) continue;
for (auto m = poly->head; m; m = m->next) { for (auto m = poly->head; m; m = m->next) {
this->emitPoly(m); emitPoly(m);
} }
} }
} }
void Tessellator::visitShape(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count) void Tessellator::visitShape(const RenderPath& path)
{ {
// all points at least need to be visit once // all points at least need to be visit once
// so the points count is at least the same as the count in shape // so the points count is at least the same as the count in shape
buffer->vertex.reserve(pts_count * 2); buffer->vertex.reserve(path.pts.count * 2);
// triangle fans, the indices count is at least triangles number * 3 // triangle fans, the indices count is at least triangles number * 3
buffer->index.reserve((pts_count - 2) * 3); buffer->index.reserve((path.pts.count - 2) * 3);
const Point *firstPt = nullptr; const Point *firstPt = nullptr;
auto pts = path.pts.data;
for (uint32_t i = 0; i < cmd_count; i++) { ARRAY_FOREACH(cmd, path.cmds) {
switch (cmds[i]) { switch (*cmd) {
case PathCommand::MoveTo: { case PathCommand::MoveTo: {
outlines.push(new VertexList); outlines.push(new VertexList);
auto last = outlines.last(); auto last = outlines.last();
@ -1537,17 +1507,12 @@ void Stroker::stroke(const RenderShape *rshape, const RenderPath& path)
mStrokeWidth = strokeWidth / mMatrix.e11; mStrokeWidth = strokeWidth / mMatrix.e11;
} }
auto cmds = path.cmds.data; const float *patterns = nullptr;
auto pts = path.pts.data; auto offset = 0.0f;
auto cmdCnt = path.cmds.count; auto patternCnt = rshape->strokeDash(&patterns, &offset);
auto ptsCnt = path.pts.count;
const float *dash_pattern = nullptr; if (patternCnt == 0) doStroke(path);
auto dash_offset = 0.0f; else doDashStroke(path, patterns, patternCnt, offset);
auto dashCnt = rshape->strokeDash(&dash_pattern, &dash_offset);
if (dashCnt == 0) doStroke(cmds, cmdCnt, pts, ptsCnt);
else doDashStroke(cmds, cmdCnt, pts, ptsCnt, dashCnt, dash_pattern, dash_offset);
} }
@ -1562,15 +1527,16 @@ RenderRegion Stroker::bounds() const
} }
void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count) void Stroker::doStroke(const RenderPath& path)
{ {
mBuffer->vertex.reserve(pts_count * 4 + 16); mBuffer->vertex.reserve(path.pts.count * 4 + 16);
mBuffer->index.reserve(pts_count * 3); mBuffer->index.reserve(path.pts.count * 3);
auto validStrokeCap = false; auto validStrokeCap = false;
auto pts = path.pts.data;
for (uint32_t i = 0; i < cmd_count; i++) { ARRAY_FOREACH(cmd, path.cmds) {
switch (cmds[i]) { switch (*cmd) {
case PathCommand::MoveTo: { case PathCommand::MoveTo: {
if (validStrokeCap) { // check this, so we can skip if path only contains move instruction if (validStrokeCap) { // check this, so we can skip if path only contains move instruction
strokeCap(); strokeCap();
@ -1606,18 +1572,16 @@ void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point
} }
void Stroker::doDashStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count, uint32_t dash_count, const float *dash_pattern, float dash_offset) void Stroker::doDashStroke(const RenderPath& path, const float *patterns, uint32_t patternCnt, float offset)
{ {
Array<PathCommand> dash_cmds{}; RenderPath dpath;
Array<Point> dash_pts{};
dash_cmds.reserve(20 * cmd_count); dpath.cmds.reserve(20 * path.cmds.count);
dash_pts.reserve(20 * pts_count); dpath.pts.reserve(20 * path.pts.count);
DashStroke dash(&dash_cmds, &dash_pts, dash_count, dash_pattern, dash_offset); DashStroke dash(&dpath.cmds, &dpath.pts, patterns, patternCnt, offset);
dash.doStroke(cmds, cmd_count, pts, pts_count); dash.doStroke(path);
doStroke(dpath);
this->doStroke(dash_cmds.data, dash_cmds.count, dash_pts.data, dash_pts.count);
} }
@ -1951,12 +1915,12 @@ void Stroker::strokeRound(const Point& p, const Point& outDir)
} }
DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t dash_count, const float *dash_pattern, float dash_offset) DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, const float *patterns, uint32_t patternCnt, float offset)
: mCmds(cmds), : mCmds(cmds),
mPts(pts), mPts(pts),
mDashCount(dash_count), mDashPattern(patterns),
mDashPattern(dash_pattern), mDashCount(patternCnt),
mDashOffset(dash_offset), mDashOffset(offset),
mCurrLen(), mCurrLen(),
mCurrIdx(), mCurrIdx(),
mCurOpGap(false), mCurOpGap(false),
@ -1967,7 +1931,7 @@ DashStroke::DashStroke(Array<PathCommand> *cmds, Array<Point> *pts, uint32_t das
} }
void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count) void DashStroke::doStroke(const RenderPath& path)
{ {
int32_t idx = 0; int32_t idx = 0;
auto offset = mDashOffset; auto offset = mDashOffset;
@ -1989,8 +1953,9 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
idx = idx % mDashCount; idx = idx % mDashCount;
} }
for (uint32_t i = 0; i < cmd_count; i++) { auto pts = path.pts.data;
switch (*cmds) { ARRAY_FOREACH(cmd, path.cmds) {
switch (*cmd) {
case PathCommand::Close: { case PathCommand::Close: {
this->dashLineTo(mPtStart); this->dashLineTo(mPtStart);
break; break;
@ -2017,7 +1982,6 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
} }
default: break; default: break;
} }
cmds++;
} }
} }

View file

@ -43,11 +43,10 @@ class Tessellator final
public: public:
Tessellator(GlGeometryBuffer* buffer); Tessellator(GlGeometryBuffer* buffer);
~Tessellator(); ~Tessellator();
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:
void visitShape(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count); void visitShape(const RenderPath& path);
void buildMesh(); void buildMesh();
void mergeVertices(); void mergeVertices();
bool simplifyMesh(); bool simplifyMesh();
@ -85,8 +84,8 @@ public:
RenderRegion bounds() const; RenderRegion bounds() const;
private: private:
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count); void doStroke(const RenderPath& path);
void doDashStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count, uint32_t dash_count, const float* dash_pattern, float dash_offset); void doDashStroke(const RenderPath& path, const float* patterns, uint32_t patternCnt, float offset);
float strokeRadius() const float strokeRadius() const
{ {
@ -120,9 +119,9 @@ private:
class DashStroke class DashStroke
{ {
public: public:
DashStroke(Array<PathCommand>* cmds, Array<Point>* pts, uint32_t dash_count, const float* dash_pattern, float dash_offset); DashStroke(Array<PathCommand>* cmds, Array<Point>* pts, const float* patterns, uint32_t patternCnt, float offset);
~DashStroke() = default; ~DashStroke() = default;
void doStroke(const PathCommand* cmds, uint32_t cmd_count, const Point* pts, uint32_t pts_count); void doStroke(const RenderPath& path);
private: private:
void dashLineTo(const Point& pt); void dashLineTo(const Point& pt);
@ -133,8 +132,8 @@ private:
Array<PathCommand>* mCmds; Array<PathCommand>* mCmds;
Array<Point>* mPts; Array<Point>* mPts;
uint32_t mDashCount;
const float* mDashPattern; const float* mDashPattern;
uint32_t mDashCount;
float mDashOffset; float mDashOffset;
float mCurrLen; float mCurrLen;
int32_t mCurrIdx; int32_t mCurrIdx;