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);
size_t segs = ((uint32_t)(p0.dist(p3) / 8.0f));
segs = segs == 0 ? 1 : segs;
for (size_t i = 1; i <= segs; i++) {
float t = i / (float)segs;
nsegs = nsegs == 0 ? 1 : nsegs;
float dt = 1.0f / (float)nsegs;
float t = 0.0f;
for (size_t i = 1; i <= nsegs; i++) {
t += dt;
// get cubic spline interpolation coefficients
float t0 = 1.0f * (1.0f - t) * (1.0f - t) * (1.0f - 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 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 trans(const Matrix& m) const { return { x * m.e11 + y * m.e12, x * m.e21 + y * m.e22 }; };
};
struct WgMath
@ -85,7 +86,7 @@ struct WgPolyline
WgPolyline();
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;

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);
strokeFirst = rshape.stroke ? rshape.stroke->strokeFirst : false;
@ -298,10 +298,17 @@ void WgRenderDataShape::updateMeshes(WgContext &context, const RenderShape &rsha
} else if (cmd == PathCommand::Close) {
polyline.close();
} 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(
rshape.path.pts[pntIndex + 0],
rshape.path.pts[pntIndex + 1],
rshape.path.pts[pntIndex + 2]);
rshape.path.pts[pntIndex + 2],
nsegs / 2);
pntIndex += 3;
}
}

View file

@ -108,7 +108,7 @@ struct WgRenderDataShape: public WgRenderDataPaint
FillRule fillRule{};
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 releaseMeshes(WgContext& context);
void release(WgContext& context) override;

View file

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