* @brief Emits one run [start, start+len) as constant-width body quads with round joins: each * segment is a flat-capped quad extruded hw along its own normal (width never varies with * bend angle, sharp tips stay full-width), and each interior vertex gets an outer-side * round-join fan. Carries the previous direction across degenerate (zero-length) segments. */
| 558 | * round-join fan. Carries the previous direction across degenerate (zero-length) segments. |
| 559 | */ |
| 560 | void Widgets::PlotCurve::emitRun(QSGGeometry::ColoredPoint2D* vertices, |
| 561 | quint32* indices, |
| 562 | int& v, |
| 563 | int& idx, |
| 564 | const QPointF* px, |
| 565 | const qsizetype start, |
| 566 | const qsizetype len, |
| 567 | const double hw) const |
| 568 | { |
| 569 | Q_ASSERT(vertices != nullptr); |
| 570 | Q_ASSERT(indices != nullptr); |
| 571 | Q_ASSERT(len >= 2); |
| 572 | |
| 573 | auto dirAt = [&](const qsizetype i, const QPointF& fallback) { |
| 574 | QPointF dir = fallback; |
| 575 | (void)unitDir(px[start + i], px[start + i + 1], dir); |
| 576 | return dir; |
| 577 | }; |
| 578 | |
| 579 | QPointF prevDir = dirAt(0, QPointF(1, 0)); |
| 580 | for (qsizetype i = 0; i + 1 < len; ++i) { |
| 581 | const QPointF dir = dirAt(i, prevDir); |
| 582 | const QPointF n(-dir.y(), dir.x()); |
| 583 | |
| 584 | const int body = v; |
| 585 | emitCapSection(vertices, v, px[start + i], n, hw, m_color); |
| 586 | emitCapSection(vertices, v, px[start + i + 1], n, hw, m_color); |
| 587 | emitJoinIndices(indices, idx, body, body + 4); |
| 588 | |
| 589 | if (i + 2 < len) { |
| 590 | const QPointF dOut = dirAt(i + 1, dir); |
| 591 | const int nFan = fanSegments(dir, dOut); |
| 592 | if (nFan >= 1) { |
| 593 | const double s = (dir.x() * dOut.y() - dir.y() * dOut.x()) < 0.0 ? 1.0 : -1.0; |
| 594 | const QPointF nOut(-dOut.y(), dOut.x()); |
| 595 | emitFan(vertices, |
| 596 | indices, |
| 597 | v, |
| 598 | idx, |
| 599 | px[start + i + 1], |
| 600 | QPointF(n.x() * s, n.y() * s), |
| 601 | QPointF(nOut.x() * s, nOut.y() * s), |
| 602 | nFan, |
| 603 | hw, |
| 604 | m_color); |
| 605 | } |
| 606 | } |
| 607 | |
| 608 | prevDir = dir; |
| 609 | } |
| 610 | } |
| 611 | |
| 612 | /** |
| 613 | * @brief Rebuilds the ribbon node from the source series: project to pixels once, one |
nothing calls this directly
no test coverage detected