#pragma once #include #include #include #include namespace ZShell::internal { // Shared curve construction for SparklineContent (QPainter) and LineGraphItem // (QCanvasPainter). Input and output coordinates are logical (item-local); // device-pixel quantization happens inside so a stroke lands on whole pixel // columns and its edges are not interpolated across several columns. Keeping the // math in one place means both graphs align and smooth their lines identically, // whatever backend they paint through. inline qint64 toDev(qreal logical, qreal dpr) { return std::llround(logical * dpr); } inline qreal fromDev(qint64 device, qreal dpr) { return qreal(device) / dpr; } // Snap a line center so a whole-pixel-wide stroke sits on pixel boundaries when // the device width is even and on pixel centers when it is odd. qreal snapLine(qreal logical, qint64 widthDev, qreal dpr); // Catmull-Rom control points for the segment points[i] -> points[i + 1], with the // control y clamped to the segment's own y span so a curve never overshoots past // its endpoints. When curveSmoothing is off (or there are too few points) the // tangents are flat. void segmentControls( const QVector& points, int i, bool curveSmoothing, QPointF& c1, QPointF& c2); // y of the cubic bezier p1-c1-c2-p2 at targetX, found by bisection on t. qreal cubicY( const QPointF& p1, const QPointF& c1, const QPointF& c2, const QPointF& p2, qreal targetX); // The curve point at targetX on the polyline, interpolating across the segment // that contains it. Assumes points ascend in x. QPointF pointAtX( const QVector& points, qreal targetX, bool curveSmoothing); // A dense polyline through points, adding one vertex per device-pixel column // inside each segment so an edge never interpolates across several columns. The // result starts at points.first() and ends at points.last(). points must ascend in // x and hold at least two entries. Backends consume it as a moveTo/lineTo chain. QVector curveVertices( const QVector& points, qreal dpr, bool curveSmoothing); } // namespace ZShell::internal