feat(plot): per-trace legend with measured layout and swatches

This commit is contained in:
Martino Ferrari committed 2026-09-28 11:56:06 +02:00
1 parent 9dc3b1e5e6
commit 2d51b978d7
9 files changed
+850 -2

No files matched your search

+20
View File
@@ -101,6 +101,13 @@ class Renderer {
/// `Plot::layout()` is computed exactly once, here, and handed to every helper:
/// it runs the auto scale, the strip fixed-point loop and the grid build, so
/// re-deriving it per helper would rebuild the ticks and the grid per helper.
///
/// A legend the plot has is part of the frame: the panel and its swatches are
/// line geometry staged with everything else, the names are glyphs on the text
/// path, and both read the boxes `PlotLayout::legend` measured. It is the last
/// line batch, so the legend cannot be drawn under a trace, and it leaves no GL
/// state of its own -- the frame's blend and its neighbours' scissor already say
/// everything a fill and a hairline border need (see end_frame's residue list).
void draw(Plot& plot);
/// Ends the frame, draining `glGetError()` in a loop so a stale error cannot be
@@ -254,6 +261,14 @@ class Renderer {
/// is texture-bound, so this runs once per frame, after all line geometry.
void flush_text() noexcept;
/// Fills `rect` -- in framebuffer pixels, like `Rect` -- with `color`, in one
/// instance: a horizontal stroke whose width is the rect's height *is* the rect,
/// because a stroke's quad is its perpendicular width and the fragment shader
/// ramps on that perpendicular alone -- the ends are not capped (see
/// `fill_pixels()` in the implementation for why a per-column fill, the way the
/// measurement band fills, is the wrong primitive here). A rect with no width or
/// no height stages nothing.
void fill_pixels(const Rect& rect, Color color);
/// Stages one data-space segment, taking the two axes' log flags into account.
void stage_segment(f64 x0, f64 y0, f64 x1, f64 y1, bool log_x, bool log_y);
/// Stages `n` interleaved `x,y` data-space points (a gathered window).
@@ -290,6 +305,11 @@ class Renderer {
void draw_cursors(const Plot& plot, const PlotLayout& layout);
void draw_measures(const Plot& plot, const PlotLayout& layout);
void draw_annotations(const Plot& plot);
/// The legend: the panel and its swatches as line geometry, the names on the text
/// path. It reads the boxes `Plot::layout()` measured rather than deriving any of
/// them again, so the panel a test asserts and the panel this draws are the same
/// numbers.
void draw_legend(const Plot& plot, const PlotLayout& layout);
/// The built-in backend the renderer owns. Every use of it goes through the
/// `TextBackend` interface -- `self`-typed nowhere -- so swapping it for