fix(render): environment-aware atlas drift guard, pinned text scale, shipped-atlas coverage

This commit is contained in:
Martino Ferrari committed 2026-09-28 10:54:00 +02:00
1 parent 5ca3587325
commit 1cb5970757
6 files changed
+257 -31

No files matched your search

+55
View File
@@ -426,6 +426,61 @@ class CountFenceWaits {
} // namespace
// The renderer draws a run at the size the style asked for, not at a whole
// multiple of the backend's cell, and it reports what it drew. `axis_font_px()`
// is that report, and the committed atlas is baked at 13 px, so the default
// style's 12 px is a 12/13 scale -- exactly the case the old rule snapped to
// 16 px. No other case sets a size other than the default, and the ones that
// compare a measure compare values scaled by the same factor, so they hold under
// a snapping rule too; this is the one that does not.
PLOT_TEST(axis_text_is_drawn_at_the_requested_em_not_a_whole_multiple) {
plottest::HeadlessContext ctx(kW, kH);
plot::Status st;
PLOT_CHECK(ctx.create(&st));
PLOT_CHECK(plot::gl::load(nullptr));
// The renderer's own backend, for the raw metrics the ratio is taken against.
const plot::render::EmbeddedMonoFont font;
const plot::f32 baked = font.em_px();
const plot::f32 cell = font.height();
plot::Renderer r;
r.style().axis_font_px = 12.0f; // the default style's em, against a 13 px bake
PLOT_CHECK(r.init(&st));
PLOT_CHECK_NEAR(r.axis_font_px(), cell * (12.0f / baked), 1e-3);
PLOT_CHECK(std::fabs(r.axis_font_px() - 16.0f) > 0.2f); // 2 x the old 8 px glyph
PLOT_CHECK(std::fabs(r.axis_font_px() - 17.0f) > 0.2f); // 1 x this cell
plot::Plot p;
p.set_viewport({0.0f, 0.0f, static_cast<plot::f32>(kW), static_cast<plot::f32>(kH)});
p.add_x_axis({"t", {0.0, 1000.0}, true, plot::AxisPlace::Bottom, false});
p.add_y_axis({"v", {-1.0, 1.0}, true, plot::AxisPlace::Left, false});
const plot::Rect viewport{0.0f, 0.0f, static_cast<plot::f32>(kW), static_cast<plot::f32>(kH)};
r.begin_frame(kW, kH, viewport);
r.draw(p);
r.end_frame();
// The plot lays out with the backend the renderer installed, so the size it
// measured with is the size it drew with.
const plot::render::TextBackend* backend = p.text_backend();
PLOT_CHECK(backend != nullptr);
PLOT_CHECK_NEAR(backend->em_px(), 12.0f, 1e-3);
PLOT_CHECK_NEAR(backend->height(), cell * (12.0f / baked), 1e-3);
// `em_px()` is in the wrapper's units, like `height()`: a caller drawing at
// `requested_px / em_px()` reads 12/12 = 1 and cannot scale a second time.
PLOT_CHECK_NEAR(backend->em_px() / backend->height(), baked / cell, 1e-6);
// An exact multiple still lands exactly, and the frame re-reads the style.
r.style().axis_font_px = 26.0f; // 2 x 13
r.begin_frame(kW, kH, viewport);
r.draw(p);
r.end_frame();
PLOT_CHECK_NEAR(p.text_backend()->em_px(), 26.0f, 1e-3);
PLOT_CHECK_NEAR(p.text_backend()->height(), cell * 2.0f, 1e-3);
PLOT_CHECK(plot::gl::glGetError() == plot::gl::GL_NO_ERROR);
ctx.destroy();
}
PLOT_TEST(renders_visible_trace_across_viewport) {
plottest::HeadlessContext ctx(kW, kH);
plot::Status st;