From 1e9609c6f715197446ed9f1374f47b77e5f951cc Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 17 Oct 2024 20:57:04 +0900 Subject: [PATCH] wg_engine: merged math functions with common issue: https://github.com/thorvg/thorvg/issues/2313 --- src/common/tvgMath.h | 30 +++++ src/renderer/gl_engine/tvgGlTessellator.cpp | 32 +++--- src/renderer/wg_engine/tvgWgGeometry.h | 115 +++++++++++--------- 3 files changed, 109 insertions(+), 68 deletions(-) diff --git a/src/common/tvgMath.h b/src/common/tvgMath.h index 560c8598..3ba74e9f 100644 --- a/src/common/tvgMath.h +++ b/src/common/tvgMath.h @@ -176,6 +176,24 @@ Point normal(const Point& p1, const Point& p2); void normalize(Point& pt); +static inline Point min(const Point& lhs, const Point& rhs) +{ + return {std::min(lhs.x, rhs.x), std::min(lhs.y, rhs.y)}; +} + + +static inline Point max(const Point& lhs, const Point& rhs) +{ + return {std::max(lhs.x, rhs.x), std::max(lhs.y, rhs.y)}; +} + + +static inline float dot(const Point& lhs, const Point& rhs) +{ + return lhs.x * rhs.x + lhs.y * rhs.y; +} + + static inline bool zero(const Point& p) { return tvg::zero(p.x) && tvg::zero(p.y); @@ -200,6 +218,12 @@ static inline float length(const Point& a) } +static inline float length2(const Point& a) +{ + return a.x * a.x + a.y * a.y; +}; + + static inline bool operator==(const Point& lhs, const Point& rhs) { return tvg::equal(lhs.x, rhs.x) && tvg::equal(lhs.y, rhs.y); @@ -266,6 +290,12 @@ static inline Point operator/(const Point& lhs, const float rhs) } +static inline Point operator-(const Point& a) +{ + return {-a.x, -a.y}; +} + + static inline void log(const Point& pt) { TVGLOG("COMMON", "Point: [%f %f]", pt.x, pt.y); diff --git a/src/renderer/gl_engine/tvgGlTessellator.cpp b/src/renderer/gl_engine/tvgGlTessellator.cpp index 3356a939..014bb91f 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.cpp +++ b/src/renderer/gl_engine/tvgGlTessellator.cpp @@ -1756,10 +1756,10 @@ void Stroker::strokeLineTo(const Point& curr) mRightBottom.y = mLeftTop.y = curr.y; } - mLeftTop.x = std::min(mLeftTop.x, min(min(a.x, b.x), min(c.x, d.x))); - mLeftTop.y = std::min(mLeftTop.y, min(min(a.y, b.y), min(c.y, d.y))); - mRightBottom.x = std::max(mRightBottom.x, max(max(a.x, b.x), max(c.x, d.x))); - mRightBottom.y = std::max(mRightBottom.y, max(max(a.y, b.y), max(c.y, d.y))); + 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))); + mRightBottom.x = std::max(mRightBottom.x, std::max(std::max(a.x, b.x), std::max(c.x, d.x))); + mRightBottom.y = std::max(mRightBottom.y, std::max(std::max(a.y, b.y), std::max(c.y, d.y))); } @@ -1839,10 +1839,10 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen { if (_calcOrientation(prev, center, curr) == Orientation::Linear) return; - mLeftTop.x = std::min(mLeftTop.x, min(center.x, min(prev.x, curr.x))); - mLeftTop.y = std::min(mLeftTop.y, min(center.y, min(prev.y, curr.y))); - mRightBottom.x = std::max(mRightBottom.x, max(center.x, max(prev.x, curr.x))); - mRightBottom.y = std::max(mRightBottom.y, max(center.y, max(prev.y, curr.y))); + mLeftTop.x = std::min(mLeftTop.x, std::min(center.x, std::min(prev.x, curr.x))); + mLeftTop.y = std::min(mLeftTop.y, std::min(center.y, std::min(prev.y, curr.y))); + mRightBottom.x = std::max(mRightBottom.x, std::max(center.x, std::max(prev.x, curr.x))); + mRightBottom.y = std::max(mRightBottom.y, std::max(center.y, std::max(prev.y, curr.y))); // Fixme: just use bezier curve to calculate step count auto count = _bezierCurveCount(_bezFromArc(prev, curr, strokeRadius())); @@ -1943,10 +1943,10 @@ void Stroker::strokeSquare(const Point& p, const Point& outDir) mResIndices->push(bi); mResIndices->push(di); - mLeftTop.x = std::min(mLeftTop.x, min(min(a.x, b.x), min(c.x, d.x))); - mLeftTop.y = std::min(mLeftTop.y, min(min(a.y, b.y), min(c.y, d.y))); - mRightBottom.x = std::max(mRightBottom.x, max(max(a.x, b.x), max(c.x, d.x))); - mRightBottom.y = std::max(mRightBottom.y, max(max(a.y, b.y), max(c.y, d.y))); + 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))); + mRightBottom.x = std::max(mRightBottom.x, std::max(std::max(a.x, b.x), std::max(c.x, d.x))); + mRightBottom.y = std::max(mRightBottom.y, std::max(std::max(a.y, b.y), std::max(c.y, d.y))); } @@ -2481,10 +2481,10 @@ uint32_t BWTessellator::pushVertex(float x, float y) mRightBottom.x = mLeftTop.x = x; mRightBottom.y = mLeftTop.y = y; } else { - mLeftTop.x = min(mLeftTop.x, x); - mLeftTop.y = min(mLeftTop.y, y); - mRightBottom.x = max(mRightBottom.x, x); - mRightBottom.y = max(mRightBottom.y , y); + mLeftTop.x = std::min(mLeftTop.x, x); + mLeftTop.y = std::min(mLeftTop.y, y); + mRightBottom.x = std::max(mRightBottom.x, x); + mRightBottom.y = std::max(mRightBottom.y , y); } return index; diff --git a/src/renderer/wg_engine/tvgWgGeometry.h b/src/renderer/wg_engine/tvgWgGeometry.h index 6e99b1fc..8630f609 100755 --- a/src/renderer/wg_engine/tvgWgGeometry.h +++ b/src/renderer/wg_engine/tvgWgGeometry.h @@ -24,26 +24,16 @@ #define _TVG_WG_GEOMETRY_H_ #include -#include #include "tvgMath.h" #include "tvgRender.h" -// base vector operations -static Point operator-(const Point& a) { return {-a.x, -a.y}; } -static inline float length2(const Point& a) { return a.x*a.x+a.y*a.y; }; -static inline float distance2(const Point& a, const Point& b) { return length2(a - b); }; -static inline float distance(const Point& a, const Point& b) { return length(a - b); }; -static inline float dot(const Point& a, const Point& b) { return a.x*b.x + a.y*b.y; }; -static inline Point min(const Point& a, const Point& b) { return { std::min(a.x, b.x), std::min(a.y, b.y) }; }; -static inline Point max(const Point& a, const Point& b) { return { std::max(a.x, b.x), std::max(a.y, b.y) }; }; -static inline Point lerp(const Point& a, const Point& b, float t) { return a * (1.0f - t) + b * t; }; -static inline Point normalize(const Point& a) { float rlen = 1.0f / length(a); return { a.x * rlen, a.y * rlen }; } // default size of vertex and index buffers #define WG_POINTS_COUNT 32768 // simple vertex buffer -struct WgVertexBuffer { +struct WgVertexBuffer +{ Point vbuff[WG_POINTS_COUNT]; // vertex buffer float vdist[WG_POINTS_COUNT]; // distance to previous point float vleng[WG_POINTS_COUNT]; // distance to the first point through all previous points @@ -54,28 +44,33 @@ struct WgVertexBuffer { using onPolylineFn = std::function; // reset buffer - void reset() { + void reset() + { vcount = 0; closed = false; } // get the last point with optional index offset from the end - Point last(size_t offset = 0) const { + Point last(size_t offset = 0) const + { return vbuff[vcount - offset - 1]; } // get the last distance with optional index offset from the end - float lastDist(size_t offset = 0) const { + float lastDist(size_t offset = 0) const + { return vdist[vcount - offset - 1]; } // get total length - float total() const { + float total() const + { return (vcount == 0) ? 0.0f : vleng[vcount-1]; } // get next vertex index by length using binary search - size_t getIndexByLength(float len) const { + size_t getIndexByLength(float len) const + { if (vcount <= 1) return 0; size_t left = 0; size_t right = vcount - 1; @@ -89,7 +84,8 @@ struct WgVertexBuffer { } // get min and max values of the buffer - void getMinMax(Point& pmin, Point& pmax) const { + void getMinMax(Point& pmin, Point& pmax) const + { if (vcount == 0) return; pmax = pmin = vbuff[0]; for (size_t i = 1; i < vcount; i++) { @@ -99,38 +95,43 @@ struct WgVertexBuffer { } // update points distancess to the prev point and total length - void updateDistances() { + void updateDistances() + { if (vcount == 0) return; vdist[0] = 0.0f; vleng[0] = 0.0f; for (size_t i = 1; i < vcount; i++) { - vdist[i] = distance(vbuff[i-1], vbuff[i]); + vdist[i] = length(vbuff[i-1] - vbuff[i]); vleng[i] = vleng[i-1] + vdist[i]; } } // close vertex buffer - void close() { + void close() + { // check if last point is not to close to the first point - if (!tvg::zero(distance2(vbuff[0], last()))) + if (!tvg::zero(length2(vbuff[0] - last()))) append(vbuff[0]); closed = true; } // append point - void append(const Point& p) { + void append(const Point& p) + { vbuff[vcount] = p; vcount++; } // append source vertex buffer in index range from start to end (end not included) - void appendRange(const WgVertexBuffer& buff, size_t start_index, size_t end_index) { + void appendRange(const WgVertexBuffer& buff, size_t start_index, size_t end_index) + { for (size_t i = start_index; i < end_index; i++) append(buff.vbuff[i]); } // append circle (list of triangles) - void appendCircle(float radius) { + void appendCircle(float radius) + { // get approx circle length float clen = 2.0f * radius * MATH_PI; size_t nsegs = std::max((uint32_t)(clen / 8), 16U); @@ -147,9 +148,10 @@ struct WgVertexBuffer { } // append cubic spline - void appendCubic(const Point& v0, const Point& v1, const Point& v2, const Point& v3) { + void appendCubic(const Point& v0, const Point& v1, const Point& v2, const Point& v3) + { // get approx cubic length - float clen = distance(v0, v1) + distance(v1, v2) + distance(v2, v3); + float clen = length(v0 - v1) + length(v1 - v2) + length(v2 - v3); size_t nsegs = std::max((uint32_t)(clen / 8), 16U); // append cubic Bezier bezier{v0, v1, v2, v3}; @@ -158,7 +160,8 @@ struct WgVertexBuffer { } // trim source buffer - void trim(const WgVertexBuffer& buff, float beg, float end) { + void trim(const WgVertexBuffer& buff, float beg, float end) + { // empty buffer guard if (buff.vcount == 0) return; // initialize @@ -183,7 +186,8 @@ struct WgVertexBuffer { // decode path with callback for external prcesses - void decodePath(const RenderShape& rshape, bool update_dist, onPolylineFn onPolyline) { + void decodePath(const RenderShape& rshape, bool update_dist, onPolylineFn onPolyline) + { // decode path reset(); size_t pntIndex = 0; @@ -215,7 +219,8 @@ struct WgVertexBuffer { }; // simple indexed vertex buffer -struct WgVertexBufferInd { +struct WgVertexBufferInd +{ Point vbuff[WG_POINTS_COUNT*16]; Point tbuff[WG_POINTS_COUNT*16]; uint32_t ibuff[WG_POINTS_COUNT*16]; @@ -223,12 +228,14 @@ struct WgVertexBufferInd { size_t icount = 0; // reset buffer - void reset() { + void reset() + { icount = vcount = 0; } // get min and max values of the buffer - void getMinMax(Point& pmin, Point& pmax) const { + void getMinMax(Point& pmin, Point& pmax) const + { if (vcount == 0) return; pmax = pmin = vbuff[0]; for (size_t i = 1; i < vcount; i++) { @@ -238,7 +245,8 @@ struct WgVertexBufferInd { } // append quad - two triangles formed from four points - void appendQuad(const Point& p0, const Point& p1, const Point& p2, const Point& p3) { + void appendQuad(const Point& p0, const Point& p1, const Point& p2, const Point& p3) + { // append vertexes vbuff[vcount+0] = p0; vbuff[vcount+1] = p1; @@ -257,7 +265,8 @@ struct WgVertexBufferInd { } // dash buffer by pattern - void appendStrokesDashed(const WgVertexBuffer& buff, const RenderStroke* rstroke) { + void appendStrokesDashed(const WgVertexBuffer& buff, const RenderStroke* rstroke) + { // dashed buffer WgVertexBuffer dashed; dashed.reset(); @@ -300,7 +309,8 @@ struct WgVertexBufferInd { } // append buffer with optional offset - void appendBuffer(const WgVertexBuffer& buff, Point offset = Point{0.0f, 0.0f}) { + void appendBuffer(const WgVertexBuffer& buff, Point offset = Point{0.0f, 0.0f}) + { for (uint32_t i = 0; i < buff.vcount; i++ ) { vbuff[vcount + i] = buff.vbuff[i] + offset; ibuff[icount + i] = vcount + i; @@ -309,15 +319,15 @@ struct WgVertexBufferInd { icount += buff.vcount; }; - // append line - void appendLine(const Point& v0, const Point& v1, float dist, float halfWidth) { + void appendLine(const Point& v0, const Point& v1, float dist, float halfWidth) + { Point sub = v1 - v0; Point nrm = { +sub.y / dist * halfWidth, -sub.x / dist * halfWidth }; appendQuad(v0 - nrm, v0 + nrm, v1 - nrm, v1 + nrm); } - // append bevel joint - void appendBevel(const Point& v0, const Point& v1, const Point& v2, float dist1, float dist2, float halfWidth) { + void appendBevel(const Point& v0, const Point& v1, const Point& v2, float dist1, float dist2, float halfWidth) + { Point sub1 = v1 - v0; Point sub2 = v2 - v1; Point nrm1 { +sub1.y / dist1 * halfWidth, -sub1.x / dist1 * halfWidth }; @@ -325,15 +335,16 @@ struct WgVertexBufferInd { appendQuad(v1 - nrm1, v1 + nrm1, v1 - nrm2, v1 + nrm2); } - // append miter joint - void appendMiter(const Point& v0, const Point& v1, const Point& v2, float dist1, float dist2, float halfWidth, float miterLimit) { - Point sub1 = v1 - v0; - Point sub2 = v2 - v1; - Point nrm1 { +sub1.y / dist1, -sub1.x / dist1 }; - Point nrm2 { +sub2.y / dist2, -sub2.x / dist2 }; - Point offset1 = nrm1 * halfWidth; - Point offset2 = nrm2 * halfWidth; - Point nrm = normalize(nrm1 + nrm2); + void appendMiter(const Point& v0, const Point& v1, const Point& v2, float dist1, float dist2, float halfWidth, float miterLimit) + { + auto sub1 = v1 - v0; + auto sub2 = v2 - v1; + auto nrm1 = Point{+sub1.y / dist1, -sub1.x / dist1}; + auto nrm2 = Point{+sub2.y / dist2, -sub2.x / dist2}; + auto offset1 = nrm1 * halfWidth; + auto offset2 = nrm2 * halfWidth; + auto nrm = nrm1 + nrm2; + normalize(nrm); float cosine = dot(nrm, nrm1); if (tvg::zero(cosine)) return; float angle = std::acos(dot(nrm1, -nrm2)); @@ -347,16 +358,16 @@ struct WgVertexBufferInd { } } - // append square cap - void appendSquare(Point v0, Point v1, float dist, float halfWidth) { + void appendSquare(Point v0, Point v1, float dist, float halfWidth) + { Point sub = v1 - v0; Point offset = sub / dist * halfWidth; Point nrm = { +offset.y, -offset.x }; appendQuad(v1 - nrm, v1 + nrm, v1 + offset - nrm, v1 + offset + nrm); } - // append strokes - void appendStrokes(const WgVertexBuffer& buff, const RenderStroke* rstroke) { + void appendStrokes(const WgVertexBuffer& buff, const RenderStroke* rstroke) + { assert(rstroke); // empty buffer gueard if (buff.vcount < 2) return;