refactor(render): share the readout panel and swatch drawing with the legend
This commit is contained in:
1 parent
29824b6919
commit
10d5129fbf
2 files changed
+54
-56
No files matched your search
@@ -487,6 +487,18 @@ class Renderer {
|
||||
/// 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 backplate the legend and the crosshair's readout share: the frame's background at
|
||||
/// `kLegendPanelAlpha` over `panel`, with a one-device-pixel border in `border` around the
|
||||
/// outermost pixels the fill covers (the crisp-hairline rule -- a border drawn on the measured
|
||||
/// rect's fractional edges is lit half-heartedly, and a frame bright on three sides and dim on the
|
||||
/// fourth reads as a mistake). One helper, two callers: the border's colour is the only thing a
|
||||
/// legend panel and a readout panel do not share.
|
||||
void draw_readout_panel(const Rect& panel, Color border);
|
||||
/// One trace's colour swatch in `box`, opaque whatever the trace's own alpha is: a swatch drawn at
|
||||
/// a trace's 15% would be the least legible thing in the frame, and the swatch is the one element
|
||||
/// that says which colour an entry or a readout row *is*. The legend's entries and the crosshair's
|
||||
/// rows both read it from here.
|
||||
void draw_swatch(const Plot& plot, u32 trace, const Rect& box);
|
||||
/// The crosshair's **lines and markers**: the vertical and horizontal strokes and a small
|
||||
/// cross at each trace's intersection.
|
||||
///
|
||||
|
||||
+42
-56
@@ -1138,29 +1138,10 @@ void Renderer::draw_legend(const Plot& plot, const PlotLayout& layout) {
|
||||
const LegendLayout& legend = layout.legend;
|
||||
if (legend.rows.empty()) return;
|
||||
|
||||
const Rect& panel = legend.panel;
|
||||
if (plot.legend().frame) {
|
||||
// The panel first, so every entry is on top of it: the frame's own background
|
||||
// at a partial alpha, which dims whatever it covers instead of erasing it.
|
||||
Color background = style_.background;
|
||||
background.a *= kLegendPanelAlpha;
|
||||
fill_pixels(panel, background);
|
||||
// The border frames the pixels the fill covers, not the measured rect's own
|
||||
// fractional edges: those are wherever the names happened to measure to, and a
|
||||
// hairline drawn on one is lit half-heartedly -- a frame bright on three sides and
|
||||
// dim on the fourth reads as a mistake. These are the outermost lit columns and
|
||||
// rows the fill's span rounds out to (the same rounding the fill itself does), so
|
||||
// every side of the frame is one crisp hairline.
|
||||
const f32 left = std::ceil(panel.x - 0.5f) + 0.5f;
|
||||
const f32 right = std::ceil(panel.right() - 0.5f) - 0.5f;
|
||||
const f32 top = std::ceil(panel.y - 0.5f) + 0.5f;
|
||||
const f32 bottom = std::ceil(panel.bottom() - 0.5f) - 0.5f;
|
||||
lines_.add_segment({left, top}, {right, top});
|
||||
lines_.add_segment({left, bottom}, {right, bottom});
|
||||
lines_.add_segment({left, top}, {left, bottom});
|
||||
lines_.add_segment({right, top}, {right, bottom});
|
||||
flush_lines(pixel_mapping(), style_.axis_line, style_.device(1.0f));
|
||||
}
|
||||
// The panel first, so every entry is on top of it. A legend's border is the frame's axis colour;
|
||||
// the readout's is the crosshair's own (see draw_crosshair_readout), which is the only thing that
|
||||
// differs between the two panels -- so it is the one parameter the shared helper takes.
|
||||
if (plot.legend().frame) draw_readout_panel(legend.panel, style_.axis_line);
|
||||
|
||||
for (const LegendRow& row : legend.rows) {
|
||||
// The truncation row names no trace: it has no swatch to colour and its text is
|
||||
@@ -1170,16 +1151,43 @@ void Renderer::draw_legend(const Plot& plot, const PlotLayout& layout) {
|
||||
stage_text({row.name.x, row.name.y}, kLegendEllipsis);
|
||||
continue;
|
||||
}
|
||||
// Opaque whatever the trace's own alpha is: a swatch drawn at a trace's 15% would
|
||||
// be the least legible thing in the frame, and the swatch is the one element that
|
||||
// says which colour a legend entry *is*.
|
||||
Color swatch = plot.trace(row.trace).color;
|
||||
swatch.a = 1.0f;
|
||||
fill_pixels(row.swatch, swatch);
|
||||
draw_swatch(plot, row.trace, row.swatch);
|
||||
stage_text({row.name.x, row.name.y}, plot.trace(row.trace).name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::draw_readout_panel(const Rect& panel, Color border) {
|
||||
if (!(panel.w > 0.0f) || !(panel.h > 0.0f)) return;
|
||||
// The frame's own background at a partial alpha, which dims whatever it covers instead of erasing
|
||||
// it -- the one backplate both readout panels use.
|
||||
Color background = style_.background;
|
||||
background.a *= kLegendPanelAlpha;
|
||||
fill_pixels(panel, background);
|
||||
// The border frames the pixels the fill covers, not the measured rect's own fractional edges:
|
||||
// those are wherever the content happened to measure to, and a hairline drawn on one is lit
|
||||
// half-heartedly -- a frame bright on three sides and dim on the fourth reads as a mistake. These
|
||||
// are the outermost lit columns and rows the fill's span rounds out to (the same rounding the fill
|
||||
// itself does), so every side of the frame is one crisp hairline.
|
||||
const f32 left = std::ceil(panel.x - 0.5f) + 0.5f;
|
||||
const f32 right = std::ceil(panel.right() - 0.5f) - 0.5f;
|
||||
const f32 top = std::ceil(panel.y - 0.5f) + 0.5f;
|
||||
const f32 bottom = std::ceil(panel.bottom() - 0.5f) - 0.5f;
|
||||
lines_.add_segment({left, top}, {right, top});
|
||||
lines_.add_segment({left, bottom}, {right, bottom});
|
||||
lines_.add_segment({left, top}, {left, bottom});
|
||||
lines_.add_segment({right, top}, {right, bottom});
|
||||
flush_lines(pixel_mapping(), border, style_.device(1.0f));
|
||||
}
|
||||
|
||||
void Renderer::draw_swatch(const Plot& plot, u32 trace, const Rect& box) {
|
||||
// Opaque whatever the trace's own alpha is: a swatch drawn at a trace's 15% would be the least
|
||||
// legible thing in the frame, and the swatch is the one element that says which colour an entry or
|
||||
// a readout row *is*. One rule, used by the legend and by the crosshair's readout alike.
|
||||
Color swatch = plot.trace(trace).color;
|
||||
swatch.a = 1.0f;
|
||||
fill_pixels(box, swatch);
|
||||
}
|
||||
|
||||
void Renderer::draw_crosshair_lines(const Plot& plot, const PlotLayout& layout) {
|
||||
const CrosshairLayout& crosshair = layout.crosshair;
|
||||
if (!crosshair.active) return;
|
||||
@@ -1225,36 +1233,14 @@ void Renderer::draw_crosshair_readout(const Plot& plot, const PlotLayout& layout
|
||||
const CrosshairLayout& crosshair = layout.crosshair;
|
||||
if (!crosshair.active) return;
|
||||
|
||||
// The readout: the same backplate a legend has -- the frame's background at a partial
|
||||
// alpha, so the data stays legible through it -- with its border in the crosshair's own
|
||||
// colour, which is what makes the panel read as part of the instrument that placed it
|
||||
// rather than as a second legend.
|
||||
if (crosshair.panel.w > 0.0f && crosshair.panel.h > 0.0f) {
|
||||
const Rect& panel = crosshair.panel;
|
||||
Color background = style_.background;
|
||||
background.a *= kLegendPanelAlpha;
|
||||
fill_pixels(panel, background);
|
||||
// The crisp-hairline rule of the legend's border: the outermost *lit* columns and rows of
|
||||
// the fill's span, not the measured rect's fractional edges, so all four sides are one
|
||||
// hairline rather than three bright ones and a dim one.
|
||||
const f32 left = std::ceil(panel.x - 0.5f) + 0.5f;
|
||||
const f32 right = std::ceil(panel.right() - 0.5f) - 0.5f;
|
||||
const f32 top = std::ceil(panel.y - 0.5f) + 0.5f;
|
||||
const f32 bottom = std::ceil(panel.bottom() - 0.5f) - 0.5f;
|
||||
lines_.add_segment({left, top}, {right, top});
|
||||
lines_.add_segment({left, bottom}, {right, bottom});
|
||||
lines_.add_segment({left, top}, {left, bottom});
|
||||
lines_.add_segment({right, top}, {right, bottom});
|
||||
flush_lines(pixel_mapping(), style_.crosshair, style_.device(1.0f));
|
||||
}
|
||||
// The readout: the same backplate a legend has (the shared `draw_readout_panel()`), with its
|
||||
// border in the crosshair's own colour -- which is what makes the panel read as part of the
|
||||
// instrument that placed it rather than as a second legend.
|
||||
draw_readout_panel(crosshair.panel, style_.crosshair);
|
||||
|
||||
for (const CrosshairRow& row : crosshair.rows) {
|
||||
if (!row.listed) continue;
|
||||
// The swatch is the trace's colour opaque, as a legend's is: it is the one element that
|
||||
// says which signal the row is about.
|
||||
Color swatch = plot.trace(row.trace).color;
|
||||
swatch.a = 1.0f;
|
||||
fill_pixels(row.swatch, swatch);
|
||||
draw_swatch(plot, row.trace, row.swatch);
|
||||
stage_text({row.label_box.x, row.label_box.y}, row.label.c_str());
|
||||
// A row with no sample at this x has no value to write -- and it is *not* written as a
|
||||
// zero or a dash: the box is empty and the number is simply absent (see CrosshairRow).
|
||||
|
||||
Reference in new issue
Block a user