mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
gl_engine: ++neat code (#3319)
This commit is contained in:
parent
6f9fd6ff01
commit
24378cc200
2 changed files with 49 additions and 86 deletions
|
@ -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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue