fix(render): convert Trace::width through the UI scale, and fold the controller's tolerance conversion into Style::device()
This commit is contained in:
1 parent
7500fc90d2
commit
69495a3799
7 files changed
+158
-24
No files matched your search
@@ -21,10 +21,11 @@ constexpr f64 kKeyZoomNotches = 1.0;
|
||||
/// kZoomPerNotch: 200 px of drag is one decade, exp(-200 * ln10/200) == 0.1.
|
||||
constexpr f64 kZoomPerPixel = std::numbers::ln10 / 200.0;
|
||||
/// How close the pointer must be to a cursor to grab it, in **logical** pixels: the
|
||||
/// listener's aim is a physical distance, so the device-pixel radius it is compared
|
||||
/// against is this times `Plot::ui_scale()` (see `grab_radius()`). An unscaled
|
||||
/// constant would make grabbing physically harder -- half as forgiving -- on a 2x
|
||||
/// display, which is the defect the scale exists to prevent.
|
||||
/// listener's aim is a physical distance, so it is converted to the device-pixel
|
||||
/// radius the comparison needs through `Style::device()` at the plot's own scale
|
||||
/// (see `cursor_at()`). An unscaled constant would make grabbing physically harder
|
||||
/// -- half as forgiving -- on a 2x display, which is the defect the scale exists to
|
||||
/// prevent.
|
||||
constexpr f32 kCursorHitRadiusLogical = 5.0f;
|
||||
/// A box-zoom selection narrower than this on either side is a click. Logical for
|
||||
/// the same reason: the gesture is the same hand movement on any display.
|
||||
@@ -44,15 +45,6 @@ f64 from_space(f64 v, bool log) noexcept {
|
||||
/// key) zoom in, so the span shrinks by `exp(-notches * kZoomPerNotch)`.
|
||||
f64 zoom_factor(f64 notches) noexcept { return std::exp(-notches * kZoomPerNotch); }
|
||||
|
||||
/// Device pixels per logical unit for the tolerances below. Read from the plot the
|
||||
/// controller already holds -- every forwarded coordinate is in device pixels, and
|
||||
/// the plot is the one that knows what a device pixel is worth -- rather than kept
|
||||
/// as a copy that a host would have to update in step with the renderer's.
|
||||
f32 tolerance_scale(const Plot& plot) noexcept {
|
||||
const f32 scale = plot.ui_scale();
|
||||
return scale > 0.0f ? scale : 1.0f;
|
||||
}
|
||||
|
||||
/// True when a coordinate is one arithmetic can work with. Every event here comes
|
||||
/// from a host, and a host can hand over anything: a toolkit's "no pointer"
|
||||
/// sentinel, a NaN from a degenerate mapping of its own, an infinity from a lost
|
||||
@@ -283,8 +275,9 @@ void Controller::apply_box_zoom() {
|
||||
const Rect sel = selection_;
|
||||
// A selection under a few *logical* pixels on either side is a click: no zoom.
|
||||
// The selection is measured in device pixels like everything the controller is
|
||||
// handed, so the threshold is the logical one at this plot's scale.
|
||||
const f32 min_box = kMinBoxLogical * tolerance_scale(*plot_);
|
||||
// handed, so the threshold is converted at the plot's own scale -- through the one
|
||||
// place that conversion lives, so a change to its fallback is picked up here too.
|
||||
const f32 min_box = plot_->style().device(kMinBoxLogical);
|
||||
if (sel.w < min_box || sel.h < min_box) return;
|
||||
|
||||
// Clamped to the axes rect the transforms are built from, so a drag that left
|
||||
@@ -341,7 +334,7 @@ u64 Controller::cursor_at(f32 px, f32 py) const {
|
||||
const PlotLayout& lay = std::as_const(*plot_).layout();
|
||||
if (!lay.axes.contains(px, py)) return kInvalid;
|
||||
|
||||
const f32 radius = kCursorHitRadiusLogical * tolerance_scale(*plot_);
|
||||
const f32 radius = plot_->style().device(kCursorHitRadiusLogical);
|
||||
u64 best = kInvalid;
|
||||
f32 best_d = 0.0f;
|
||||
for (u32 i = 0; i < plot_->cursor_count(); ++i) {
|
||||
|
||||
Reference in new issue
Block a user