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)
{
this->fillRule = FillRule::NonZero;
fillRule = FillRule::NonZero;
for (uint32_t i = 0; i < shapes.count; i++) {
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(path->cmds.data, path->cmds.count, path->pts.data, path->pts.count);
visitShape(trimmedPath);
} else visitShape(shapes[i]->path);
}
this->buildMesh();
this->mergeVertices();
this->simplifyMesh();
this->tessMesh();
buildMesh();
mergeVertices();
simplifyMesh();
tessMesh();
// output triangles
for (auto poly = this->pPolygon; poly; poly = poly->next) {
if (!this->matchFillRule(poly->winding)) continue;
for (auto poly = pPolygon; poly; poly = poly->next) {
if (!matchFillRule(poly->winding)) continue;
if (poly->count < 3) continue;
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
// 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
buffer->index.reserve((pts_count - 2) * 3);
buffer->index.reserve((path.pts.count - 2) * 3);
const Point *firstPt = nullptr;
auto pts = path.pts.data;
for (uint32_t i = 0; i < cmd_count; i++) {
switch (cmds[i]) {
ARRAY_FOREACH(cmd, path.cmds) {
switch (*cmd) {
case PathCommand::MoveTo: {
outlines.push(new VertexList);
auto last = outlines.last();
@ -1537,17 +1507,12 @@ void Stroker::stroke(const RenderShape *rshape, const RenderPath& path)
mStrokeWidth = strokeWidth / mMatrix.e11;
}
auto cmds = path.cmds.data;
auto pts = path.pts.data;
auto cmdCnt = path.cmds.count;
auto ptsCnt = path.pts.count;
const float *patterns = nullptr;
auto offset = 0.0f;
auto patternCnt = rshape->strokeDash(&patterns, &offset);
const float *dash_pattern = nullptr;
auto dash_offset = 0.0f;
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);
if (patternCnt == 0) doStroke(path);
else doDashStroke(path, patterns, patternCnt, 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->index.reserve(pts_count * 3);
mBuffer->vertex.reserve(path.pts.count * 4 + 16);
mBuffer->index.reserve(path.pts.count * 3);
auto validStrokeCap = false;
auto pts = path.pts.data;
for (uint32_t i = 0; i < cmd_count; i++) {
switch (cmds[i]) {
ARRAY_FOREACH(cmd, path.cmds) {
switch (*cmd) {
case PathCommand::MoveTo: {
if (validStrokeCap) { // check this, so we can skip if path only contains move instruction
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{};
Array<Point> dash_pts{};
RenderPath dpath;
dash_cmds.reserve(20 * cmd_count);
dash_pts.reserve(20 * pts_count);
dpath.cmds.reserve(20 * path.cmds.count);
dpath.pts.reserve(20 * path.pts.count);
DashStroke dash(&dash_cmds, &dash_pts, dash_count, dash_pattern, dash_offset);
dash.doStroke(cmds, cmd_count, pts, pts_count);
this->doStroke(dash_cmds.data, dash_cmds.count, dash_pts.data, dash_pts.count);
DashStroke dash(&dpath.cmds, &dpath.pts, patterns, patternCnt, offset);
dash.doStroke(path);
doStroke(dpath);
}
@ -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),
mPts(pts),
mDashCount(dash_count),
mDashPattern(dash_pattern),
mDashOffset(dash_offset),
mDashPattern(patterns),
mDashCount(patternCnt),
mDashOffset(offset),
mCurrLen(),
mCurrIdx(),
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;
auto offset = mDashOffset;
@ -1989,8 +1953,9 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
idx = idx % mDashCount;
}
for (uint32_t i = 0; i < cmd_count; i++) {
switch (*cmds) {
auto pts = path.pts.data;
ARRAY_FOREACH(cmd, path.cmds) {
switch (*cmd) {
case PathCommand::Close: {
this->dashLineTo(mPtStart);
break;
@ -2017,7 +1982,6 @@ void DashStroke::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Poi
}
default: break;
}
cmds++;
}
}

View file

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