mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
gl_engine: code refactoring
- introduced GlGeometryBuffer that structure ensures the pairing of vertex and index data. - improved for clean and neat code.
This commit is contained in:
parent
3737632e13
commit
75c9028c19
5 changed files with 181 additions and 224 deletions
|
@ -130,31 +130,35 @@ enum class GlStencilMode {
|
|||
class GlStageBuffer;
|
||||
class GlRenderTask;
|
||||
|
||||
class GlGeometry
|
||||
struct GlGeometryBuffer {
|
||||
Array<float> vertex;
|
||||
Array<uint32_t> index;
|
||||
|
||||
void clear()
|
||||
{
|
||||
vertex.clear();
|
||||
index.clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GlGeometry
|
||||
{
|
||||
public:
|
||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
|
||||
bool tesselate(const RenderSurface* image, RenderUpdateFlag flag);
|
||||
void disableVertex(uint32_t location);
|
||||
bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag);
|
||||
void updateTransform(const Matrix& m);
|
||||
void setViewport(const RenderRegion& viewport);
|
||||
const RenderRegion& getViewport();
|
||||
const Matrix& getTransformMatrix();
|
||||
GlStencilMode getStencilMode(RenderUpdateFlag flag);
|
||||
RenderRegion getBounds() const;
|
||||
|
||||
private:
|
||||
GlGeometryBuffer fill, stroke;
|
||||
Matrix matrix = {};
|
||||
RenderRegion viewport = {};
|
||||
Array<float> fillVertex;
|
||||
Array<float> strokeVertex;
|
||||
Array<uint32_t> fillIndex;
|
||||
Array<uint32_t> strokeIndex;
|
||||
Matrix mMatrix = {};
|
||||
FillRule mFillRule = FillRule::NonZero;
|
||||
RenderRegion mBounds = {};
|
||||
RenderRegion bounds = {};
|
||||
FillRule fillRule = FillRule::NonZero;
|
||||
};
|
||||
|
||||
|
||||
struct GlShape
|
||||
{
|
||||
const RenderShape* rshape = nullptr;
|
||||
|
|
|
@ -25,25 +25,24 @@
|
|||
#include "tvgGlTessellator.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
|
||||
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
|
||||
{
|
||||
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) {
|
||||
fillVertex.clear();
|
||||
fillIndex.clear();
|
||||
fill.clear();
|
||||
|
||||
BWTessellator bwTess{&fillVertex, &fillIndex};
|
||||
bwTess.tessellate(&rshape, mMatrix);
|
||||
mFillRule = rshape.rule;
|
||||
mBounds = bwTess.bounds();
|
||||
BWTessellator bwTess{&fill};
|
||||
bwTess.tessellate(&rshape, matrix);
|
||||
fillRule = rshape.rule;
|
||||
bounds = bwTess.bounds();
|
||||
}
|
||||
|
||||
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform)) {
|
||||
strokeVertex.clear();
|
||||
strokeIndex.clear();
|
||||
stroke.clear();
|
||||
|
||||
Stroker stroke{&strokeVertex, &strokeIndex, mMatrix};
|
||||
stroke.stroke(&rshape);
|
||||
mBounds = stroke.bounds();
|
||||
Stroker stroker{&stroke, matrix};
|
||||
stroker.stroke(&rshape);
|
||||
bounds = stroker.bounds();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -52,11 +51,10 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
|
|||
bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag)
|
||||
{
|
||||
if (flag & RenderUpdateFlag::Image) {
|
||||
fillVertex.clear();
|
||||
fillIndex.clear();
|
||||
fill.clear();
|
||||
|
||||
fillVertex.reserve(5 * 4);
|
||||
fillIndex.reserve(6);
|
||||
fill.vertex.reserve(5 * 4);
|
||||
fill.index.reserve(6);
|
||||
|
||||
float left = 0.f;
|
||||
float top = 0.f;
|
||||
|
@ -64,42 +62,42 @@ bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag)
|
|||
float bottom = image->h;
|
||||
|
||||
// left top point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(top);
|
||||
fill.vertex.push(left);
|
||||
fill.vertex.push(top);
|
||||
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(1.f);
|
||||
fill.vertex.push(0.f);
|
||||
fill.vertex.push(1.f);
|
||||
// left bottom point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(bottom);
|
||||
fill.vertex.push(left);
|
||||
fill.vertex.push(bottom);
|
||||
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(0.f);
|
||||
fill.vertex.push(0.f);
|
||||
fill.vertex.push(0.f);
|
||||
// right top point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(top);
|
||||
fill.vertex.push(right);
|
||||
fill.vertex.push(top);
|
||||
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
fill.vertex.push(1.f);
|
||||
fill.vertex.push(1.f);
|
||||
// right bottom point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(bottom);
|
||||
fill.vertex.push(right);
|
||||
fill.vertex.push(bottom);
|
||||
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
fill.vertex.push(1.f);
|
||||
fill.vertex.push(0.f);
|
||||
|
||||
fillIndex.push(0);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(2);
|
||||
fill.index.push(0);
|
||||
fill.index.push(1);
|
||||
fill.index.push(2);
|
||||
|
||||
fillIndex.push(2);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(3);
|
||||
fill.index.push(2);
|
||||
fill.index.push(1);
|
||||
fill.index.push(3);
|
||||
|
||||
mBounds.x = 0;
|
||||
mBounds.y = 0;
|
||||
mBounds.w = image->w;
|
||||
mBounds.h = image->h;
|
||||
bounds.x = 0;
|
||||
bounds.y = 0;
|
||||
bounds.w = image->w;
|
||||
bounds.h = image->h;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -116,21 +114,11 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
|
|||
{
|
||||
if (flag == RenderUpdateFlag::None) return false;
|
||||
|
||||
Array<float>* vertexBuffer = nullptr;
|
||||
Array<uint32_t>* indexBuffer = nullptr;
|
||||
auto buffer = ((flag & RenderUpdateFlag::Stroke) || (flag & RenderUpdateFlag::GradientStroke)) ? &stroke : &fill;
|
||||
if (buffer->index.empty()) return false;
|
||||
|
||||
if ((flag & RenderUpdateFlag::Stroke) || (flag & RenderUpdateFlag::GradientStroke)) {
|
||||
vertexBuffer = &strokeVertex;
|
||||
indexBuffer = &strokeIndex;
|
||||
} else {
|
||||
vertexBuffer = &fillVertex;
|
||||
indexBuffer = &fillIndex;
|
||||
}
|
||||
|
||||
if (indexBuffer->count == 0) return false;
|
||||
|
||||
uint32_t vertexOffset = gpuBuffer->push(vertexBuffer->data, vertexBuffer->count * sizeof(float));
|
||||
uint32_t indexOffset = gpuBuffer->pushIndex(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
|
||||
auto vertexOffset = gpuBuffer->push(buffer->vertex.data, buffer->vertex.count * sizeof(float));
|
||||
auto indexOffset = gpuBuffer->pushIndex(buffer->index.data, buffer->index.count * sizeof(uint32_t));
|
||||
|
||||
// vertex layout
|
||||
if (flag & RenderUpdateFlag::Image) {
|
||||
|
@ -140,43 +128,19 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
|
|||
} else {
|
||||
task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), vertexOffset});
|
||||
}
|
||||
task->setDrawRange(indexOffset, indexBuffer->count);
|
||||
task->setDrawRange(indexOffset, buffer->index.count);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GlGeometry::updateTransform(const Matrix& m)
|
||||
{
|
||||
mMatrix = m;
|
||||
}
|
||||
|
||||
|
||||
void GlGeometry::setViewport(const RenderRegion& viewport)
|
||||
{
|
||||
this->viewport = viewport;
|
||||
}
|
||||
|
||||
|
||||
const RenderRegion& GlGeometry::getViewport()
|
||||
{
|
||||
return viewport;
|
||||
}
|
||||
|
||||
|
||||
const Matrix& GlGeometry::getTransformMatrix()
|
||||
{
|
||||
return mMatrix;
|
||||
}
|
||||
|
||||
|
||||
GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag)
|
||||
{
|
||||
if (flag & RenderUpdateFlag::Stroke) return GlStencilMode::Stroke;
|
||||
if (flag & RenderUpdateFlag::GradientStroke) return GlStencilMode::Stroke;
|
||||
if (flag & RenderUpdateFlag::Image) return GlStencilMode::None;
|
||||
|
||||
if (mFillRule == FillRule::NonZero) return GlStencilMode::FillNonZero;
|
||||
if (mFillRule == FillRule::EvenOdd) return GlStencilMode::FillEvenOdd;
|
||||
if (fillRule == FillRule::NonZero) return GlStencilMode::FillNonZero;
|
||||
if (fillRule == FillRule::EvenOdd) return GlStencilMode::FillEvenOdd;
|
||||
|
||||
return GlStencilMode::None;
|
||||
}
|
||||
|
@ -184,18 +148,18 @@ GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag)
|
|||
|
||||
RenderRegion GlGeometry::getBounds() const
|
||||
{
|
||||
if (identity(&mMatrix)) {
|
||||
return mBounds;
|
||||
if (identity(&matrix)) {
|
||||
return bounds;
|
||||
} else {
|
||||
Point lt{static_cast<float>(mBounds.x), static_cast<float>(mBounds.y)};
|
||||
Point lb{static_cast<float>(mBounds.x), static_cast<float>(mBounds.y + mBounds.h)};
|
||||
Point rt{static_cast<float>(mBounds.x + mBounds.w), static_cast<float>(mBounds.y)};
|
||||
Point rb{static_cast<float>(mBounds.x + mBounds.w), static_cast<float>(mBounds.y + mBounds.h)};
|
||||
Point lt{static_cast<float>(bounds.x), static_cast<float>(bounds.y)};
|
||||
Point lb{static_cast<float>(bounds.x), static_cast<float>(bounds.y + bounds.h)};
|
||||
Point rt{static_cast<float>(bounds.x + bounds.w), static_cast<float>(bounds.y)};
|
||||
Point rb{static_cast<float>(bounds.x + bounds.w), static_cast<float>(bounds.y + bounds.h)};
|
||||
|
||||
lt *= mMatrix;
|
||||
lb *= mMatrix;
|
||||
rt *= mMatrix;
|
||||
rb *= mMatrix;
|
||||
lt *= matrix;
|
||||
lb *= matrix;
|
||||
rt *= matrix;
|
||||
rb *= matrix;
|
||||
|
||||
float left = min(min(lt.x, lb.x), min(rt.x, rb.x));
|
||||
float top = min(min(lt.y, lb.y), min(rt.y, rb.y));
|
||||
|
@ -208,7 +172,7 @@ RenderRegion GlGeometry::getBounds() const
|
|||
static_cast<int32_t>(ceil(right - floor(left))),
|
||||
static_cast<int32_t>(ceil(bottom - floor(top))),
|
||||
};
|
||||
if (bounds.w < 0 || bounds.h < 0) return mBounds;
|
||||
if (bounds.w < 0 || bounds.h < 0) return this->bounds;
|
||||
else return bounds;
|
||||
}
|
||||
}
|
|
@ -146,7 +146,7 @@ void GlRenderer::initShaders()
|
|||
void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdateFlag flag, int32_t depth)
|
||||
{
|
||||
auto vp = currentPass()->getViewport();
|
||||
auto bbox = sdata.geometry.getViewport();
|
||||
auto bbox = sdata.geometry.viewport;
|
||||
|
||||
bbox.intersect(vp);
|
||||
|
||||
|
@ -186,7 +186,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
|
|||
auto a = MULTIPLY(c.a, sdata.opacity);
|
||||
|
||||
if (flag & RenderUpdateFlag::Stroke) {
|
||||
float strokeWidth = sdata.rshape->strokeWidth() * getScaleFactor(sdata.geometry.getTransformMatrix());
|
||||
float strokeWidth = sdata.rshape->strokeWidth() * getScaleFactor(sdata.geometry.matrix);
|
||||
if (strokeWidth < MIN_GL_STROKE_WIDTH) {
|
||||
float alpha = strokeWidth / MIN_GL_STROKE_WIDTH;
|
||||
a = MULTIPLY(a, static_cast<uint8_t>(alpha * 255));
|
||||
|
@ -194,10 +194,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
|
|||
}
|
||||
|
||||
// matrix buffer
|
||||
const auto& matrix = sdata.geometry.getTransformMatrix();
|
||||
|
||||
float matrix44[16];
|
||||
currentPass()->getMatrix(matrix44, matrix);
|
||||
currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
|
||||
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
|
@ -235,7 +233,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
|
|||
if (complexBlend) {
|
||||
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
|
||||
sdata.geometry.draw(task, &mGpuBuffer, flag);
|
||||
endBlendingCompose(task, sdata.geometry.getTransformMatrix());
|
||||
endBlendingCompose(task, sdata.geometry.matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +241,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
|
|||
void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag, int32_t depth)
|
||||
{
|
||||
auto vp = currentPass()->getViewport();
|
||||
auto bbox = sdata.geometry.getViewport();
|
||||
auto bbox = sdata.geometry.viewport;
|
||||
|
||||
bbox.intersect(vp);
|
||||
|
||||
|
@ -285,14 +283,13 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
}
|
||||
|
||||
// matrix buffer
|
||||
const auto& matrix = sdata.geometry.getTransformMatrix();
|
||||
float invMat4[16];
|
||||
Matrix inv;
|
||||
inverse(&fill->transform(), &inv);
|
||||
GET_MATRIX44(inv, invMat4);
|
||||
|
||||
float matrix44[16];
|
||||
currentPass()->getMatrix(matrix44, matrix);
|
||||
currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
|
||||
|
||||
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
|
||||
|
||||
|
@ -423,7 +420,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
if (complexBlend) {
|
||||
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
|
||||
sdata.geometry.draw(task, &mGpuBuffer, flag);
|
||||
endBlendingCompose(task, sdata.geometry.getTransformMatrix());
|
||||
endBlendingCompose(task, sdata.geometry.matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +479,7 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
|
|||
|
||||
sdata->geometry.draw(clipTask, &mGpuBuffer, RenderUpdateFlag::Path);
|
||||
|
||||
auto bbox = sdata->geometry.getViewport();
|
||||
auto bbox = sdata->geometry.viewport;
|
||||
|
||||
bbox.intersect(vp);
|
||||
|
||||
|
@ -491,11 +488,8 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
|
|||
|
||||
clipTask->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h});
|
||||
|
||||
const auto& matrix = sdata->geometry.getTransformMatrix();
|
||||
|
||||
float matrix44[16];
|
||||
|
||||
currentPass()->getMatrix(matrix44, matrix);
|
||||
currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
|
||||
|
||||
auto loc = clipTask->getProgram()->getUniformBlockIndex("Matrix");
|
||||
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
|
||||
|
@ -1008,7 +1002,7 @@ bool GlRenderer::renderImage(void* data)
|
|||
if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return true;
|
||||
auto vp = currentPass()->getViewport();
|
||||
|
||||
auto bbox = sdata->geometry.getViewport();
|
||||
auto bbox = sdata->geometry.viewport;
|
||||
|
||||
bbox.intersect(vp);
|
||||
|
||||
|
@ -1035,9 +1029,8 @@ bool GlRenderer::renderImage(void* data)
|
|||
if (complexBlend) vp = currentPass()->getViewport();
|
||||
|
||||
// matrix buffer
|
||||
const auto& matrix = sdata->geometry.getTransformMatrix();
|
||||
float matrix44[16];
|
||||
currentPass()->getMatrix(matrix44, matrix);
|
||||
currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
|
@ -1068,7 +1061,7 @@ bool GlRenderer::renderImage(void* data)
|
|||
if (complexBlend) {
|
||||
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
|
||||
sdata->geometry.draw(task, &mGpuBuffer, RenderUpdateFlag::Image);
|
||||
endBlendingCompose(task, sdata->geometry.getTransformMatrix());
|
||||
endBlendingCompose(task, sdata->geometry.matrix);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1085,7 +1078,7 @@ bool GlRenderer::renderShape(RenderData data)
|
|||
|
||||
const auto& vp = currentPass()->getViewport();
|
||||
|
||||
auto bbox = sdata->geometry.getViewport();
|
||||
auto bbox = sdata->geometry.viewport;
|
||||
bbox.intersect(vp);
|
||||
|
||||
if (bbox.w <= 0 || bbox.h <= 0) return true;
|
||||
|
@ -1188,8 +1181,8 @@ RenderData GlRenderer::prepare(RenderSurface* image, RenderData data, const Matr
|
|||
sdata->geometry = GlGeometry();
|
||||
}
|
||||
|
||||
sdata->geometry.updateTransform(transform);
|
||||
sdata->geometry.setViewport(mViewport);
|
||||
sdata->geometry.matrix = transform;
|
||||
sdata->geometry.viewport = mViewport;
|
||||
|
||||
sdata->geometry.tesselate(image, flags);
|
||||
|
||||
|
@ -1243,8 +1236,8 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
|
||||
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
||||
|
||||
sdata->geometry.updateTransform(transform);
|
||||
sdata->geometry.setViewport(mViewport);
|
||||
sdata->geometry.matrix = transform;
|
||||
sdata->geometry.viewport = mViewport;
|
||||
|
||||
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform | RenderUpdateFlag::Path))
|
||||
{
|
||||
|
|
|
@ -798,11 +798,11 @@ static float _downScaleFloat(float v)
|
|||
}
|
||||
|
||||
|
||||
static uint32_t _pushVertex(Array<float> *array, float x, float y)
|
||||
static uint32_t _pushVertex(Array<float>& array, float x, float y)
|
||||
{
|
||||
array->push(x);
|
||||
array->push(y);
|
||||
return (array->count - 2) / 2;
|
||||
array.push(x);
|
||||
array.push(y);
|
||||
return (array.count - 2) / 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -830,13 +830,12 @@ static Orientation _calcOrientation(const Point& dir1, const Point& dir2)
|
|||
}
|
||||
|
||||
|
||||
Tessellator::Tessellator(Array<float> *points, Array<uint32_t> *indices)
|
||||
Tessellator::Tessellator(GlGeometryBuffer* buffer)
|
||||
: pHeap(new ObjectHeap),
|
||||
outlines(),
|
||||
pMesh(new VertexList),
|
||||
pPolygon(),
|
||||
resGlPoints(points),
|
||||
resIndices(indices)
|
||||
buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -917,9 +916,9 @@ void Tessellator::visitShape(const PathCommand *cmds, uint32_t cmd_count, const
|
|||
{
|
||||
// all points at least need to be visit once
|
||||
// so the points count is at least the same as the count in shape
|
||||
resGlPoints->reserve(pts_count * 2);
|
||||
buffer->vertex.reserve(pts_count * 2);
|
||||
// triangle fans, the indices count is at least triangles number * 3
|
||||
resIndices->reserve((pts_count - 2) * 3);
|
||||
buffer->index.reserve((pts_count - 2) * 3);
|
||||
|
||||
const Point *firstPt = nullptr;
|
||||
|
||||
|
@ -1513,17 +1512,17 @@ void Tessellator::emitPoly(MonotonePolygon *poly)
|
|||
void Tessellator::emitTriangle(Vertex *p1, Vertex *p2, Vertex *p3)
|
||||
{
|
||||
// check if index is generated
|
||||
if (p1->index == 0xFFFFFFFF) p1->index = _pushVertex(resGlPoints, _downScaleFloat(p1->point.x), _downScaleFloat(p1->point.y));
|
||||
if (p2->index == 0xFFFFFFFF) p2->index = _pushVertex(resGlPoints, _downScaleFloat(p2->point.x), _downScaleFloat(p2->point.y));
|
||||
if (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(resGlPoints, _downScaleFloat(p3->point.x), _downScaleFloat(p3->point.y));
|
||||
if (p1->index == 0xFFFFFFFF) p1->index = _pushVertex(buffer->vertex, _downScaleFloat(p1->point.x), _downScaleFloat(p1->point.y));
|
||||
if (p2->index == 0xFFFFFFFF) p2->index = _pushVertex(buffer->vertex, _downScaleFloat(p2->point.x), _downScaleFloat(p2->point.y));
|
||||
if (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(buffer->vertex, _downScaleFloat(p3->point.x), _downScaleFloat(p3->point.y));
|
||||
|
||||
resIndices->push(p1->index);
|
||||
resIndices->push(p2->index);
|
||||
resIndices->push(p3->index);
|
||||
buffer->index.push(p1->index);
|
||||
buffer->index.push(p2->index);
|
||||
buffer->index.push(p3->index);
|
||||
}
|
||||
|
||||
|
||||
Stroker::Stroker(Array<float> *points, Array<uint32_t> *indices, const Matrix& matrix) : mResGlPoints(points), mResIndices(indices), mMatrix(matrix)
|
||||
Stroker::Stroker(GlGeometryBuffer* buffer, const Matrix& matrix) : mBuffer(buffer), mMatrix(matrix)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1588,8 +1587,8 @@ RenderRegion Stroker::bounds() const
|
|||
|
||||
void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count)
|
||||
{
|
||||
mResGlPoints->reserve(pts_count * 4 + 16);
|
||||
mResIndices->reserve(pts_count * 3);
|
||||
mBuffer->vertex.reserve(pts_count * 4 + 16);
|
||||
mBuffer->index.reserve(pts_count * 3);
|
||||
|
||||
auto validStrokeCap = false;
|
||||
|
||||
|
@ -1678,10 +1677,10 @@ void Stroker::strokeLineTo(const Point& curr)
|
|||
auto c = curr + normal * strokeRadius();
|
||||
auto d = curr - normal * strokeRadius();
|
||||
|
||||
auto ia = _pushVertex(mResGlPoints, a.x, a.y);
|
||||
auto ib = _pushVertex(mResGlPoints, b.x, b.y);
|
||||
auto ic = _pushVertex(mResGlPoints, c.x, c.y);
|
||||
auto id = _pushVertex(mResGlPoints, d.x, d.y);
|
||||
auto ia = _pushVertex(mBuffer->vertex, a.x, a.y);
|
||||
auto ib = _pushVertex(mBuffer->vertex, b.x, b.y);
|
||||
auto ic = _pushVertex(mBuffer->vertex, c.x, c.y);
|
||||
auto id = _pushVertex(mBuffer->vertex, d.x, d.y);
|
||||
|
||||
/**
|
||||
* a --------- c
|
||||
|
@ -1690,13 +1689,13 @@ void Stroker::strokeLineTo(const Point& curr)
|
|||
* b-----------d
|
||||
*/
|
||||
|
||||
this->mResIndices->push(ia);
|
||||
this->mResIndices->push(ib);
|
||||
this->mResIndices->push(ic);
|
||||
this->mBuffer->index.push(ia);
|
||||
this->mBuffer->index.push(ib);
|
||||
this->mBuffer->index.push(ic);
|
||||
|
||||
this->mResIndices->push(ib);
|
||||
this->mResIndices->push(id);
|
||||
this->mResIndices->push(ic);
|
||||
this->mBuffer->index.push(ib);
|
||||
this->mBuffer->index.push(id);
|
||||
this->mBuffer->index.push(ic);
|
||||
|
||||
if (mStrokeState.prevPt == mStrokeState.firstPt) {
|
||||
// first point after moveTo
|
||||
|
@ -1802,8 +1801,8 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen
|
|||
|
||||
// Fixme: just use bezier curve to calculate step count
|
||||
auto count = _bezierCurveCount(_bezFromArc(prev, curr, strokeRadius()));
|
||||
auto c = _pushVertex(mResGlPoints, center.x, center.y);
|
||||
auto pi = _pushVertex(mResGlPoints, prev.x, prev.y);
|
||||
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
|
||||
auto pi = _pushVertex(mBuffer->vertex, prev.x, prev.y);
|
||||
auto step = 1.f / (count - 1);
|
||||
auto dir = curr - prev;
|
||||
|
||||
|
@ -1814,11 +1813,11 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen
|
|||
normalize(o_dir);
|
||||
|
||||
auto out = center + o_dir * strokeRadius();
|
||||
auto oi = _pushVertex(mResGlPoints, out.x, out.y);
|
||||
auto oi = _pushVertex(mBuffer->vertex, out.x, out.y);
|
||||
|
||||
mResIndices->push(c);
|
||||
mResIndices->push(pi);
|
||||
mResIndices->push(oi);
|
||||
mBuffer->index.push(c);
|
||||
mBuffer->index.push(pi);
|
||||
mBuffer->index.push(oi);
|
||||
|
||||
pi = oi;
|
||||
|
||||
|
@ -1834,19 +1833,19 @@ void Stroker::strokeRoundPoint(const Point &p)
|
|||
{
|
||||
// Fixme: just use bezier curve to calculate step count
|
||||
auto count = _bezierCurveCount(_bezFromArc(p, p, strokeRadius())) * 2;
|
||||
auto c = _pushVertex(mResGlPoints, p.x, p.y);
|
||||
auto c = _pushVertex(mBuffer->vertex, p.x, p.y);
|
||||
auto step = 2 * M_PI / (count - 1);
|
||||
|
||||
for (uint32_t i = 1; i <= static_cast<uint32_t>(count); i++) {
|
||||
float angle = i * step;
|
||||
Point dir = {cos(angle), sin(angle)};
|
||||
Point out = p + dir * strokeRadius();
|
||||
auto oi = _pushVertex(mResGlPoints, out.x, out.y);
|
||||
auto oi = _pushVertex(mBuffer->vertex, out.x, out.y);
|
||||
|
||||
if (oi > 1) {
|
||||
mResIndices->push(c);
|
||||
mResIndices->push(oi);
|
||||
mResIndices->push(oi - 1);
|
||||
mBuffer->index.push(c);
|
||||
mBuffer->index.push(oi);
|
||||
mBuffer->index.push(oi - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1871,18 +1870,18 @@ void Stroker::strokeMiter(const Point& prev, const Point& curr, const Point& cen
|
|||
}
|
||||
|
||||
auto join = center + pe;
|
||||
auto c = _pushVertex(mResGlPoints, center.x, center.y);
|
||||
auto cp1 = _pushVertex(mResGlPoints, prev.x, prev.y);
|
||||
auto cp2 = _pushVertex(mResGlPoints, curr.x, curr.y);
|
||||
auto e = _pushVertex(mResGlPoints, join.x, join.y);
|
||||
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
|
||||
auto cp1 = _pushVertex(mBuffer->vertex, prev.x, prev.y);
|
||||
auto cp2 = _pushVertex(mBuffer->vertex, curr.x, curr.y);
|
||||
auto e = _pushVertex(mBuffer->vertex, join.x, join.y);
|
||||
|
||||
mResIndices->push(c);
|
||||
mResIndices->push(cp1);
|
||||
mResIndices->push(e);
|
||||
mBuffer->index.push(c);
|
||||
mBuffer->index.push(cp1);
|
||||
mBuffer->index.push(e);
|
||||
|
||||
mResIndices->push(e);
|
||||
mResIndices->push(cp2);
|
||||
mResIndices->push(c);
|
||||
mBuffer->index.push(e);
|
||||
mBuffer->index.push(cp2);
|
||||
mBuffer->index.push(c);
|
||||
|
||||
mLeftTop.x = std::min(mLeftTop.x, join.x);
|
||||
mLeftTop.y = std::min(mLeftTop.y, join.y);
|
||||
|
@ -1894,13 +1893,13 @@ void Stroker::strokeMiter(const Point& prev, const Point& curr, const Point& cen
|
|||
|
||||
void Stroker::strokeBevel(const Point& prev, const Point& curr, const Point& center)
|
||||
{
|
||||
auto a = _pushVertex(mResGlPoints, prev.x, prev.y);
|
||||
auto b = _pushVertex(mResGlPoints, curr.x, curr.y);
|
||||
auto c = _pushVertex(mResGlPoints, center.x, center.y);
|
||||
auto a = _pushVertex(mBuffer->vertex, prev.x, prev.y);
|
||||
auto b = _pushVertex(mBuffer->vertex, curr.x, curr.y);
|
||||
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
|
||||
|
||||
mResIndices->push(a);
|
||||
mResIndices->push(b);
|
||||
mResIndices->push(c);
|
||||
mBuffer->index.push(a);
|
||||
mBuffer->index.push(b);
|
||||
mBuffer->index.push(c);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1913,18 +1912,18 @@ void Stroker::strokeSquare(const Point& p, const Point& outDir)
|
|||
auto c = a + outDir * strokeRadius();
|
||||
auto d = b + outDir * strokeRadius();
|
||||
|
||||
auto ai = _pushVertex(mResGlPoints, a.x, a.y);
|
||||
auto bi = _pushVertex(mResGlPoints, b.x, b.y);
|
||||
auto ci = _pushVertex(mResGlPoints, c.x, c.y);
|
||||
auto di = _pushVertex(mResGlPoints, d.x, d.y);
|
||||
auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
|
||||
auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
|
||||
auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
|
||||
auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
|
||||
|
||||
mResIndices->push(ai);
|
||||
mResIndices->push(bi);
|
||||
mResIndices->push(ci);
|
||||
mBuffer->index.push(ai);
|
||||
mBuffer->index.push(bi);
|
||||
mBuffer->index.push(ci);
|
||||
|
||||
mResIndices->push(ci);
|
||||
mResIndices->push(bi);
|
||||
mResIndices->push(di);
|
||||
mBuffer->index.push(ci);
|
||||
mBuffer->index.push(bi);
|
||||
mBuffer->index.push(di);
|
||||
|
||||
mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x)));
|
||||
mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y)));
|
||||
|
@ -1943,18 +1942,18 @@ void Stroker::strokeSquarePoint(const Point& p)
|
|||
auto c = p - offsetX - offsetY;
|
||||
auto d = p + offsetX - offsetY;
|
||||
|
||||
auto ai = _pushVertex(mResGlPoints, a.x, a.y);
|
||||
auto bi = _pushVertex(mResGlPoints, b.x, b.y);
|
||||
auto ci = _pushVertex(mResGlPoints, c.x, c.y);
|
||||
auto di = _pushVertex(mResGlPoints, d.x, d.y);
|
||||
auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
|
||||
auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
|
||||
auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
|
||||
auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
|
||||
|
||||
mResIndices->push(ai);
|
||||
mResIndices->push(bi);
|
||||
mResIndices->push(ci);
|
||||
mBuffer->index.push(ai);
|
||||
mBuffer->index.push(bi);
|
||||
mBuffer->index.push(ci);
|
||||
|
||||
mResIndices->push(ci);
|
||||
mResIndices->push(di);
|
||||
mResIndices->push(ai);
|
||||
mBuffer->index.push(ci);
|
||||
mBuffer->index.push(di);
|
||||
mBuffer->index.push(ai);
|
||||
|
||||
mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x)));
|
||||
mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y)));
|
||||
|
@ -2165,7 +2164,7 @@ void DashStroke::cubicTo(const Point& cnt1, const Point& cnt2, const Point& end)
|
|||
}
|
||||
|
||||
|
||||
BWTessellator::BWTessellator(Array<float>* points, Array<uint32_t>* indices): mResPoints(points), mResIndices(indices)
|
||||
BWTessellator::BWTessellator(GlGeometryBuffer* buffer): mBuffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2182,8 +2181,8 @@ void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix)
|
|||
uint32_t firstIndex = 0;
|
||||
uint32_t prevIndex = 0;
|
||||
|
||||
mResPoints->reserve(ptsCnt * 2);
|
||||
mResIndices->reserve((ptsCnt - 2) * 3);
|
||||
mBuffer->vertex.reserve(ptsCnt * 2);
|
||||
mBuffer->index.reserve((ptsCnt - 2) * 3);
|
||||
|
||||
for (uint32_t i = 0; i < cmdCnt; i++) {
|
||||
switch(cmds[i]) {
|
||||
|
@ -2252,7 +2251,7 @@ RenderRegion BWTessellator::bounds() const
|
|||
|
||||
uint32_t BWTessellator::pushVertex(float x, float y)
|
||||
{
|
||||
auto index = _pushVertex(mResPoints, x, y);
|
||||
auto index = _pushVertex(mBuffer->vertex, x, y);
|
||||
|
||||
if (index == 0) {
|
||||
bbox.max = bbox.min = {x, y};
|
||||
|
@ -2267,9 +2266,9 @@ uint32_t BWTessellator::pushVertex(float x, float y)
|
|||
|
||||
void BWTessellator::pushTriangle(uint32_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
mResIndices->push(a);
|
||||
mResIndices->push(b);
|
||||
mResIndices->push(c);
|
||||
mBuffer->index.push(a);
|
||||
mBuffer->index.push(b);
|
||||
mBuffer->index.push(c);
|
||||
}
|
||||
|
||||
} // namespace tvg
|
||||
|
|
|
@ -41,7 +41,7 @@ struct RenderShape;
|
|||
class Tessellator final
|
||||
{
|
||||
public:
|
||||
Tessellator(Array<float>* points, Array<uint32_t>* indices);
|
||||
Tessellator(GlGeometryBuffer* buffer);
|
||||
~Tessellator();
|
||||
bool tessellate(const RenderShape *rshape, bool antialias = false);
|
||||
void tessellate(const Array<const RenderShape*> &shapes);
|
||||
|
@ -66,11 +66,10 @@ private:
|
|||
Array<VertexList*> outlines;
|
||||
VertexList* pMesh;
|
||||
Polygon* pPolygon;
|
||||
Array<float>* resGlPoints;
|
||||
Array<uint32_t>* resIndices;
|
||||
GlGeometryBuffer* buffer;
|
||||
};
|
||||
|
||||
class Stroker final
|
||||
class Stroker
|
||||
{
|
||||
struct State
|
||||
{
|
||||
|
@ -80,7 +79,7 @@ class Stroker final
|
|||
Point prevPtDir;
|
||||
};
|
||||
public:
|
||||
Stroker(Array<float>* points, Array<uint32_t>* indices, const Matrix& matrix);
|
||||
Stroker(GlGeometryBuffer* buffer, const Matrix& matrix);
|
||||
~Stroker() = default;
|
||||
void stroke(const RenderShape *rshape);
|
||||
RenderRegion bounds() const;
|
||||
|
@ -107,8 +106,7 @@ private:
|
|||
void strokeRound(const Point& p, const Point& outDir);
|
||||
void strokeRoundPoint(const Point& p);
|
||||
|
||||
Array<float>* mResGlPoints;
|
||||
Array<uint32_t>* mResIndices;
|
||||
GlGeometryBuffer* mBuffer;
|
||||
Matrix mMatrix;
|
||||
float mStrokeWidth = MIN_GL_STROKE_WIDTH;
|
||||
float mMiterLimit = 4.f;
|
||||
|
@ -148,7 +146,7 @@ private:
|
|||
class BWTessellator
|
||||
{
|
||||
public:
|
||||
BWTessellator(Array<float>* points, Array<uint32_t>* indices);
|
||||
BWTessellator(GlGeometryBuffer* buffer);
|
||||
~BWTessellator() = default;
|
||||
void tessellate(const RenderShape *rshape, const Matrix& matrix);
|
||||
RenderRegion bounds() const;
|
||||
|
@ -157,8 +155,7 @@ private:
|
|||
uint32_t pushVertex(float x, float y);
|
||||
void pushTriangle(uint32_t a, uint32_t b, uint32_t c);
|
||||
|
||||
Array<float>* mResPoints;
|
||||
Array<uint32_t>* mResIndices;
|
||||
GlGeometryBuffer* mBuffer;
|
||||
BBox bbox = {{}, {}};
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue