perf(charts): fill chart areas in one linear pass

The filled sparklines and the market price chart built their area fill
with PathFillConcave, which runs a per-scanline pass over the whole
filled region. For a simple area under an x-monotone curve that work is
unnecessary.

- A new helper fills the area between an x-monotone polyline and a
  horizontal baseline directly as a triangle strip, in one pass over the
  points. The market sparklines, the market price chart and the mining
  hashrate sparkline all use it. The fill is flat and non-anti-aliased;
  the anti-aliased curve drawn on top hides the stepped top edge, and
  the faint side and bottom edges are imperceptible at these alphas.

Tests: the strip's vertex and index counts, index bounds, and that its
triangle area matches the trapezoid area under the polyline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 13:30:20 -05:00
co-authored by Claude Opus 4.8
parent 969718e03a
commit c5b325a752
5 changed files with 61 additions and 13 deletions
+2 -8
View File
@@ -183,10 +183,7 @@ static void pfDrawSparklineFilled(ImDrawList* dl, ImVec2 mn, ImVec2 mx,
std::vector<ImVec2> pts;
if (!pfProjectSeries(hist, mn, mx, pts)) return;
int n = (int)pts.size();
for (int i = 0; i < n; i++) dl->PathLineTo(pts[i]);
dl->PathLineTo(ImVec2(pts[n - 1].x, mx.y));
dl->PathLineTo(ImVec2(pts[0].x, mx.y));
dl->PathFillConcave(WithAlpha(lineCol, 28));
FillUnderPolyline(dl, pts.data(), n, mx.y, WithAlpha(lineCol, 28));
dl->AddPolyline(pts.data(), n, WithAlpha(lineCol, 220), ImDrawFlags_None, 1.4f * dp);
}
@@ -1826,10 +1823,7 @@ static void mktDrawPriceChart(const MktCtx& cx)
points[i] = ImVec2(plotLeft + t * plotW, yOf(s_mkt.history[i]));
}
// Flat translucent area fill under the curve (matches the portfolio group sparklines).
for (size_t i = 0; i < n; i++) dl->PathLineTo(points[i]);
dl->PathLineTo(ImVec2(points[n - 1].x, plotBottom));
dl->PathLineTo(ImVec2(points[0].x, plotBottom));
dl->PathFillConcave(WithAlpha(dirCol, 28));
FillUnderPolyline(dl, points.data(), (int)n, plotBottom, WithAlpha(dirCol, 28));
// Line (no per-point dots — a clean curve).
dl->AddPolyline(points.data(), (int)points.size(), lineCol, ImDrawFlags_None, S.drawElement("tabs.market", "chart-line-thickness").size);
}