fix(render): convert Trace::width through the UI scale, and fold the controller's tolerance conversion into Style::device()

This commit is contained in:
Martino Ferrari committed 2026-09-28 12:26:06 +02:00
1 parent 7500fc90d2
commit 69495a3799
7 files changed
+158 -24

No files matched your search

+5 -3
View File
@@ -59,9 +59,11 @@ enum class DragMode {
/// therefore change its *physical* size with the display: a 5 px grab radius is
/// half the hand movement on a 2x panel, so the same cursor becomes harder to
/// catch there. Both tolerances -- the cursor grab radius and the box-zoom click
/// threshold -- are therefore logical constants multiplied by `Plot::ui_scale()`,
/// which is also why the controller reads the scale off the plot it already holds
/// instead of keeping a copy a host would have to keep in step.
/// threshold -- are therefore logical constants, converted through
/// `Style::device()` at the scale of the plot the controller already holds: that is
/// the single place the logical -> device rule lives, and the plot is the one that
/// knows what its device pixel is worth, so the controller keeps no copy of the scale
/// for a host to keep in step.
///
/// The middle-drag axis zoom's per-pixel gain is deliberately *not* in that group:
/// it is a data-navigation sensitivity rather than a size (the wheel and `+`/`-`
+5
View File
@@ -11,6 +11,9 @@ namespace plot {
struct TraceDesc {
const data::Series* series = nullptr;
Color color = Color::hex(0x4FA3FF);
/// The stroke's width in **logical** pixels, like every stroke in `Style` (see
/// that struct's unit rule): the renderer converts it once, so a trace has the
/// same weight against the axis lines whatever the display's DPI.
f32 width = 1.5f;
u32 axis_x = 0, axis_y = 0;
/// What the trace is called, for the legend. Empty means "do not list it", which
@@ -28,6 +31,8 @@ struct TraceDesc {
struct Trace {
const data::Series* series = nullptr;
Color color = Color::hex(0x4FA3FF);
/// Logical pixels, as in `TraceDesc::width`: converted to device pixels by the
/// renderer's one `Style::device()` call per stroke.
f32 width = 1.5f;
u32 axis_x = 0, axis_y = 0;
/// The legend's entry for this trace, empty when it has none. A name does not
+7 -2
View File
@@ -24,8 +24,13 @@ namespace plot::render {
/// chosen LOD level depend on the display and not on the data. It is used raw.
///
/// The same rule classifies the metrics that live outside this struct, which are
/// logical too and converted by the same call: `Legend`'s pad, swatch, gap and
/// margin, and the renderer's marker arm lengths and text offsets.
/// logical too and converted by the same call:
///
/// * `Legend`'s pad, swatch, gap and margin;
/// * `Trace`'s (and `TraceDesc`'s) `width` -- a stroke like `line_width_px`, and
/// the one a plot draws most of, so leaving it raw would invert the
/// trace/axis stroke hierarchy at any scale above 1;
/// * the renderer's marker arm lengths and text offsets.
struct Style {
// --- colours: neither logical nor device, so nothing to scale ------------