wg_engine: fix incorrect geomatry

Fix computation of segments count for cubic curves.
Using screen coordinates of base points, instead of world coordinates
This commit is contained in:
Sergii Liebodkin 2024-06-19 18:54:05 +03:00 committed by Hermet Park
parent 7a76c58057
commit 53de5f2ff7
5 changed files with 19 additions and 10 deletions

View file

@ -87,13 +87,14 @@ void WgPolyline::appendPoint(WgPoint pt)
} }
void WgPolyline::appendCubic(WgPoint p1, WgPoint p2, WgPoint p3) void WgPolyline::appendCubic(WgPoint p1, WgPoint p2, WgPoint p3, size_t nsegs)
{ {
WgPoint p0 = pts.count > 0 ? pts.last() : WgPoint(0.0f, 0.0f); WgPoint p0 = pts.count > 0 ? pts.last() : WgPoint(0.0f, 0.0f);
size_t segs = ((uint32_t)(p0.dist(p3) / 8.0f)); nsegs = nsegs == 0 ? 1 : nsegs;
segs = segs == 0 ? 1 : segs; float dt = 1.0f / (float)nsegs;
for (size_t i = 1; i <= segs; i++) { float t = 0.0f;
float t = i / (float)segs; for (size_t i = 1; i <= nsegs; i++) {
t += dt;
// get cubic spline interpolation coefficients // get cubic spline interpolation coefficients
float t0 = 1.0f * (1.0f - t) * (1.0f - t) * (1.0f - t); float t0 = 1.0f * (1.0f - t) * (1.0f - t) * (1.0f - t);
float t1 = 3.0f * (1.0f - t) * (1.0f - t) * t; float t1 = 3.0f * (1.0f - t) * (1.0f - t) * t;

View file

@ -57,6 +57,7 @@ public:
inline void normalize() { float rlen = 1.0f / length(); x *= rlen; y *= rlen; } inline void normalize() { float rlen = 1.0f / length(); x *= rlen; y *= rlen; }
inline WgPoint normal() const { float rlen = 1.0f / length(); return { x * rlen, y * rlen }; } inline WgPoint normal() const { float rlen = 1.0f / length(); return { x * rlen, y * rlen }; }
inline WgPoint lerp(const WgPoint& p, float t) const { return { x + (p.x - x) * t, y + (p.y - y) * t }; }; inline WgPoint lerp(const WgPoint& p, float t) const { return { x + (p.x - x) * t, y + (p.y - y) * t }; };
inline WgPoint trans(const Matrix& m) const { return { x * m.e11 + y * m.e12, x * m.e21 + y * m.e22 }; };
}; };
struct WgMath struct WgMath
@ -85,7 +86,7 @@ struct WgPolyline
WgPolyline(); WgPolyline();
void appendPoint(WgPoint pt); void appendPoint(WgPoint pt);
void appendCubic(WgPoint p1, WgPoint p2, WgPoint p3); void appendCubic(WgPoint p1, WgPoint p2, WgPoint p3, size_t nsegs = 16);
void trim(WgPolyline* polyline, float trimBegin, float trimEnd) const; void trim(WgPolyline* polyline, float trimBegin, float trimEnd) const;

View file

@ -275,7 +275,7 @@ void WgRenderDataShape::updateBBox(WgPoint pmin, WgPoint pmax)
} }
void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rshape) void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rshape, const RenderTransform* rt)
{ {
releaseMeshes(context); releaseMeshes(context);
strokeFirst = rshape.stroke ? rshape.stroke->strokeFirst : false; strokeFirst = rshape.stroke ? rshape.stroke->strokeFirst : false;
@ -298,10 +298,17 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha
} else if (cmd == PathCommand::Close) { } else if (cmd == PathCommand::Close) {
polyline.close(); polyline.close();
} else if (cmd == PathCommand::CubicTo) { } else if (cmd == PathCommand::CubicTo) {
assert(polyline.pts.count > 0);
WgPoint pt0 = polyline.pts.last().trans(rt->m);
WgPoint pt1 = WgPoint(rshape.path.pts[pntIndex + 0]).trans(rt->m);
WgPoint pt2 = WgPoint(rshape.path.pts[pntIndex + 1]).trans(rt->m);
WgPoint pt3 = WgPoint(rshape.path.pts[pntIndex + 2]).trans(rt->m);
uint32_t nsegs = (uint32_t)(pt0.dist(pt1) + pt1.dist(pt2) + pt2.dist(pt3));
polyline.appendCubic( polyline.appendCubic(
rshape.path.pts[pntIndex + 0], rshape.path.pts[pntIndex + 0],
rshape.path.pts[pntIndex + 1], rshape.path.pts[pntIndex + 1],
rshape.path.pts[pntIndex + 2]); rshape.path.pts[pntIndex + 2],
nsegs / 2);
pntIndex += 3; pntIndex += 3;
} }
} }

View file

@ -108,7 +108,7 @@ struct WgRenderDataShape: public WgRenderDataPaint
FillRule fillRule{}; FillRule fillRule{};
void updateBBox(WgPoint pmin, WgPoint pmax); void updateBBox(WgPoint pmin, WgPoint pmax);
void updateMeshes(WgContext& context, const RenderShape& rshape); void updateMeshes(WgContext& context, const RenderShape& rshape, const RenderTransform* rt);
void updateMeshes(WgContext& context, const WgPolyline* polyline, const RenderStroke* rstroke); void updateMeshes(WgContext& context, const WgPolyline* polyline, const RenderStroke* rstroke);
void releaseMeshes(WgContext& context); void releaseMeshes(WgContext& context);
void release(WgContext& context) override; void release(WgContext& context) override;

View file

@ -77,7 +77,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
// update geometry // update geometry
if ((!data) || (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke))) { if ((!data) || (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke))) {
renderDataShape->updateMeshes(mContext, rshape); renderDataShape->updateMeshes(mContext, rshape, transform);
} }
// update paint settings // update paint settings