style(grid): the minor grid is thinner, dashed and blended into the background
Subdivisions used to be drawn exactly like the labelled lines -- same width, same opacity -- so a plot dense enough to need them read as two competing sets of ticks. The minor class is now three things the style states explicitly: - grid_minor_width 1.0 -> 0.75, a sub-pixel logical width. At 1x that is expressed as reduced coverage through the anti-aliased ramp; on a HiDPI display the line is literally narrower. - grid_minor_dash_on/_off (new, 3/3): dashed by default, off == 0 draws it solid, the same convention as the crosshair's and a trace's dash. The dash is a fragment-shader discard, so no geometry is added -- the vertices are the line either way. - grid_minor carries alpha (0x1C2126 at 50%), and the line shader applies u_color.a, so it blends into the background instead of sitting on it. Together that is about a fifth of the ink a major line leaves along its length, which is what gives the eye one grid to read instead of two. The major class is untouched: it stays the structure. Tests: a new pixel test (the_minor_grid_is_thinner_dashed_and_dimmer_than_the_major) asserts a major column is inked top-to-bottom while a minor one alternates, and that the minor's ink sits closer to the background than the major's. Three existing tests counted the minor class as "most of eight rows" of its exact colour; two now take their floor from the style (minor_line_ink: width x alpha x duty), and the width test states the dash and alpha away because widths are its subject. 361 cases, 0 failed.
This commit is contained in:
1 parent
f3fb500068
commit
01e410bd74
5 files changed
+202
-13
No files matched your search
@@ -30,7 +30,9 @@ run touched a GPU, so read it as an upper bound and a record of the software pat
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- grid with independent major/minor line classes (`Style::grid_major_visible`,
|
- grid with independent major/minor line classes (`Style::grid_major_visible`,
|
||||||
`grid_minor_visible`);
|
`grid_minor_visible`), each with its own colour, width and (for the minors) dash — the
|
||||||
|
subdivisions default to thinner, dashed and alpha-blended, so they read as texture under the
|
||||||
|
labelled grid rather than as a second set of ticks;
|
||||||
- x and y axes, with a vertical (bottom-to-top) y-axis title;
|
- x and y axes, with a vertical (bottom-to-top) y-axis title;
|
||||||
- cursors in both orientations — vertical markers and horizontal rulers;
|
- cursors in both orientations — vertical markers and horizontal rulers;
|
||||||
- draggable regions and measurement bands with exact interval statistics;
|
- draggable regions and measurement bands with exact interval statistics;
|
||||||
|
|||||||
+15
-2
@@ -37,7 +37,7 @@ Colours (neither logical nor device — nothing to scale):
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `background` | `0x101418` | frame clear colour and legend/readout panel base |
|
| `background` | `0x101418` | frame clear colour and legend/readout panel base |
|
||||||
| `grid_major` | `0x2A3038` | major (labelled-tick) grid lines |
|
| `grid_major` | `0x2A3038` | major (labelled-tick) grid lines |
|
||||||
| `grid_minor` | `0x1C2126` | minor (subdivision) grid lines |
|
| `grid_minor` | `0x1C2126` at 50% alpha | minor (subdivision) grid lines |
|
||||||
| `axis_line` | `0x8A94A6` | axis lines |
|
| `axis_line` | `0x8A94A6` | axis lines |
|
||||||
| `axis_text` | `0xC8D0DC` | tick labels and axis titles |
|
| `axis_text` | `0xC8D0DC` | tick labels and axis titles |
|
||||||
| `cursor` | `0xFFB020` | cursor markers; also the hovered/grab highlight |
|
| `cursor` | `0xFFB020` | cursor markers; also the hovered/grab highlight |
|
||||||
@@ -57,7 +57,9 @@ Logical metrics (scaled by `device()`):
|
|||||||
| `axis_font_px` | `12.0` | logical em the axis text is drawn at |
|
| `axis_font_px` | `12.0` | logical em the axis text is drawn at |
|
||||||
| `grid_label_pad` | `4.0` | gap between a tick label and the axes, and the inset inside a title strip |
|
| `grid_label_pad` | `4.0` | gap between a tick label and the axes, and the inset inside a title strip |
|
||||||
| `grid_major_width` | `1.0` | width of a major grid line |
|
| `grid_major_width` | `1.0` | width of a major grid line |
|
||||||
| `grid_minor_width` | `1.0` | width of a minor grid line |
|
| `grid_minor_width` | `0.75` | width of a minor grid line (sub-pixel on purpose) |
|
||||||
|
| `grid_minor_dash_on` | `3.0` | minor grid dash: ink length in logical pixels |
|
||||||
|
| `grid_minor_dash_off` | `3.0` | minor grid dash: gap; `0` draws the minor grid solid |
|
||||||
| `grid_major_visible` | `true` | stage the major grid at all |
|
| `grid_major_visible` | `true` | stage the major grid at all |
|
||||||
| `grid_minor_visible` | `true` | stage the minor grid at all |
|
| `grid_minor_visible` | `true` | stage the minor grid at all |
|
||||||
| `line_width_px` | `1.5` | width of the strokes framing the data (axis lines, cursor markers) |
|
| `line_width_px` | `1.5` | width of the strokes framing the data (axis lines, cursor markers) |
|
||||||
@@ -91,6 +93,17 @@ transparent. `Grid` therefore carries both classes' geometry whatever the style
|
|||||||
caller that draws the grid itself applies the same two switches. `Grid::vertical` and
|
caller that draws the grid itself applies the same two switches. `Grid::vertical` and
|
||||||
`Grid::horizontal` (both `true`) control which directions emit lines at all.
|
`Grid::horizontal` (both `true`) control which directions emit lines at all.
|
||||||
|
|
||||||
|
The labelled class is the **structure** and the subdivisions are **texture**, and the minor
|
||||||
|
grid's three defaults are what makes that read: it is thinner than the major hairline
|
||||||
|
(`grid_minor_width`, a sub-pixel width that at 1x is expressed as coverage and on a HiDPI
|
||||||
|
display as a narrower line), its colour carries an **alpha** so it blends into the
|
||||||
|
background instead of sitting on it, and it is **dashed** (`grid_minor_dash_on`/`_off`) so an
|
||||||
|
unlabelled line at an unlabelled position is never mistaken for a labelled one. Together
|
||||||
|
those put a minor line at roughly a fifth of a major line's ink — at full opacity and the
|
||||||
|
same width a dense minor grid reads as a second set of ticks. The dash is a fragment-shader
|
||||||
|
discard, not extra geometry: the vertices are the line either way. Set
|
||||||
|
`grid_minor_dash_off = 0` for the old solid subdivision.
|
||||||
|
|
||||||
## The crosshair's dash
|
## The crosshair's dash
|
||||||
|
|
||||||
`crosshair_dash_on`/`crosshair_dash_off` are the fragment shader's discard pattern, so no
|
`crosshair_dash_on`/`crosshair_dash_off` are the fragment shader's discard pattern, so no
|
||||||
|
|||||||
@@ -39,7 +39,13 @@ struct Style {
|
|||||||
|
|
||||||
Color background = Color::hex(0x101418);
|
Color background = Color::hex(0x101418);
|
||||||
Color grid_major = Color::hex(0x2A3038);
|
Color grid_major = Color::hex(0x2A3038);
|
||||||
Color grid_minor = Color::hex(0x1C2126);
|
/// The minor grid's colour, **with an alpha** so it blends into the background rather than
|
||||||
|
/// sitting on it: a subdivision is a reading aid, and at full opacity a dense minor grid
|
||||||
|
/// reads as a second set of ticks competing with the labelled one. The line shader applies
|
||||||
|
/// `u_color.a` (see `src/render/shaders.cpp`), so this one blends and the major -- opaque at
|
||||||
|
/// 0x2A3038 -- stays the structure the eye picks out. Together with `grid_minor_width` and
|
||||||
|
/// the dash below, the defaults put a minor line at roughly a fifth of a major line's ink.
|
||||||
|
Color grid_minor = Color::hex(0x1C2126, 0.5f);
|
||||||
Color axis_line = Color::hex(0x8A94A6);
|
Color axis_line = Color::hex(0x8A94A6);
|
||||||
Color axis_text = Color::hex(0xC8D0DC);
|
Color axis_text = Color::hex(0xC8D0DC);
|
||||||
Color cursor = Color::hex(0xFFB020);
|
Color cursor = Color::hex(0xFFB020);
|
||||||
@@ -97,9 +103,23 @@ struct Style {
|
|||||||
/// costs nothing rather than being drawn transparent (spec §11). The colours
|
/// costs nothing rather than being drawn transparent (spec §11). The colours
|
||||||
/// above are already per class.
|
/// above are already per class.
|
||||||
f32 grid_major_width = 1.0f; ///< logical width of a major (labelled-tick) line.
|
f32 grid_major_width = 1.0f; ///< logical width of a major (labelled-tick) line.
|
||||||
f32 grid_minor_width = 1.0f; ///< logical width of a minor (subdivision) line.
|
/// Logical width of a minor (subdivision) line: **thinner than the major hairline**, and
|
||||||
|
/// sub-pixel on purpose. At 1x that is expressed as *coverage* -- the anti-aliased ramp
|
||||||
|
/// (`line_aa_px`) lights one column at roughly three quarters of the ink -- and on a HiDPI
|
||||||
|
/// display as a line that is literally narrower. The point is hierarchy: the labelled grid is
|
||||||
|
/// structure, the subdivisions are texture.
|
||||||
|
f32 grid_minor_width = 0.75f;
|
||||||
bool grid_major_visible = true; ///< stage the major grid at all.
|
bool grid_major_visible = true; ///< stage the major grid at all.
|
||||||
bool grid_minor_visible = true; ///< stage the minor grid at all.
|
bool grid_minor_visible = true; ///< stage the minor grid at all.
|
||||||
|
/// The minor grid's dash, in logical pixels: ink length and gap. **`off == 0` draws it
|
||||||
|
/// solid** -- the same convention as the crosshair's and a trace's dash -- which is what a
|
||||||
|
/// caller that wants the old solid subdivision states. Dashed is the default because an
|
||||||
|
/// unlabelled line at an unlabelled position should never be mistaken for a labelled one, and
|
||||||
|
/// because a broken line carries less weight over data than a continuous one. The dash is a
|
||||||
|
/// fragment discard, never extra geometry, so a dense minor grid costs no more vertices for
|
||||||
|
/// being dashed.
|
||||||
|
f32 grid_minor_dash_on = 3.0f;
|
||||||
|
f32 grid_minor_dash_off = 3.0f;
|
||||||
f32 line_width_px = 1.5f; ///< logical width of the strokes framing the data
|
f32 line_width_px = 1.5f; ///< logical width of the strokes framing the data
|
||||||
///< (axis lines, cursor markers).
|
///< (axis lines, cursor markers).
|
||||||
/// Logical half-width of the anti-aliased fringe the line shader blends at
|
/// Logical half-width of the anti-aliased fringe the line shader blends at
|
||||||
|
|||||||
+13
-4
@@ -798,7 +798,7 @@ void Renderer::draw_grid(const Plot& plot) {
|
|||||||
// to draw rather than being drawn transparent. Majors first, minors over them, as
|
// to draw rather than being drawn transparent. Majors first, minors over them, as
|
||||||
// the single group order always did. `LineBatch::clear()` keeps its capacity, so
|
// the single group order always did. `LineBatch::clear()` keeps its capacity, so
|
||||||
// the second pass re-uses the first one's storage.
|
// the second pass re-uses the first one's storage.
|
||||||
const auto draw_class = [&](bool major, bool visible, Color color, f32 width) {
|
const auto draw_class = [&](bool major, bool visible, Color color, f32 width, Vec2 dash) {
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -808,12 +808,21 @@ void Renderer::draw_grid(const Plot& plot) {
|
|||||||
}
|
}
|
||||||
// Snapped: a grid line is chrome at a round *data* value, and a hairline that
|
// Snapped: a grid line is chrome at a round *data* value, and a hairline that
|
||||||
// straddles two columns reads as a grey smear and shimmers as the view pans.
|
// straddles two columns reads as a grey smear and shimmers as the view pans.
|
||||||
flush_lines(map, color, width, Vec2{}, true);
|
flush_lines(map, color, width, dash, true);
|
||||||
};
|
};
|
||||||
draw_class(true, style_.grid_major_visible, style_.grid_major,
|
draw_class(true, style_.grid_major_visible, style_.grid_major,
|
||||||
style_.device(style_.grid_major_width));
|
style_.device(style_.grid_major_width), Vec2{});
|
||||||
|
// The minor grid's dash rides the same per-draw uniform the crosshair and a dashed trace use,
|
||||||
|
// and `off == 0` is the solid default. Each line starts its own pattern (the dash distance is
|
||||||
|
// per-segment), and every segment here is built from the range's minimum, so the dashes of the
|
||||||
|
// vertical lines line up with each other -- the grid reads as one texture rather than as a
|
||||||
|
// jumble of unrelated dashes.
|
||||||
|
const Vec2 minor_dash = style_.grid_minor_dash_off > 0.0f
|
||||||
|
? Vec2{style_.device(style_.grid_minor_dash_on),
|
||||||
|
style_.device(style_.grid_minor_dash_off)}
|
||||||
|
: Vec2{};
|
||||||
draw_class(false, style_.grid_minor_visible, style_.grid_minor,
|
draw_class(false, style_.grid_minor_visible, style_.grid_minor,
|
||||||
style_.device(style_.grid_minor_width));
|
style_.device(style_.grid_minor_width), minor_dash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------- axis chrome
|
// ------------------------------------------------------------- axis chrome
|
||||||
|
|||||||
+149
-4
@@ -1150,6 +1150,129 @@ PLOT_TEST(draws_cursors_measure_band_and_annotations) {
|
|||||||
// No trace and no minor grid, so the only thing drawn inside the rect is the major
|
// No trace and no minor grid, so the only thing drawn inside the rect is the major
|
||||||
// grid and the one colour it is drawn in; the rect is inset so the axis lines on
|
// grid and the one colour it is drawn in; the rect is inset so the axis lines on
|
||||||
// its own edges, which are a different colour, stay out of the scan.
|
// its own edges, which are a different colour, stay out of the scan.
|
||||||
|
/// The minor grid is a *subdivision*, and the style says so three ways: thinner, dashed and
|
||||||
|
/// blended into the background. Found by reading a frame whose minor grid read as a second set
|
||||||
|
/// of ticks -- at full opacity and the same width as the labelled grid there was no hierarchy
|
||||||
|
/// to see.
|
||||||
|
///
|
||||||
|
/// The frame holds no trace, so inside `axes` the only elements are the two grid classes and
|
||||||
|
/// the background. A row off the horizontal lines then classifies every column by inspection:
|
||||||
|
/// background, an opaque major line (`pixel_is`, the same exactness `grid_hairlines_land_on_whole_pixels`
|
||||||
|
/// leans on), or the minor's blend -- which at these defaults is the only non-background pixel
|
||||||
|
/// in the frame that is neither. Width is checked as *coverage* rather than as a pixel count,
|
||||||
|
/// because at 1x a sub-pixel logical width is exactly a dimmer stroke: the ink is one column
|
||||||
|
/// either way, so `grid_minor_width` can only show up in how brightly that column is lit. On a
|
||||||
|
/// HiDPI display the same width is literally narrower.
|
||||||
|
PLOT_TEST(the_minor_grid_is_thinner_dashed_and_dimmer_than_the_major) {
|
||||||
|
plottest::HeadlessContext ctx(kW, kH);
|
||||||
|
plot::Status st;
|
||||||
|
PLOT_CHECK(ctx.create(&st));
|
||||||
|
PLOT_CHECK(plot::gl::load(nullptr));
|
||||||
|
plot::Renderer r;
|
||||||
|
PLOT_CHECK(r.init(&st));
|
||||||
|
PLOT_CHECK(r.style().grid_minor_visible);
|
||||||
|
PLOT_CHECK(r.style().grid_minor_dash_off > 0.0f); // the default is a dash, not a solid line
|
||||||
|
|
||||||
|
plot::Plot p;
|
||||||
|
p.set_viewport({0, 0, static_cast<plot::f32>(kW), static_cast<plot::f32>(kH)});
|
||||||
|
p.add_x_axis({"seconds", {0.0, 10.0}, false, plot::AxisPlace::Bottom, false});
|
||||||
|
p.add_y_axis({"volts", {-1.0, 1.0}, false, plot::AxisPlace::Left, false});
|
||||||
|
|
||||||
|
r.begin_frame(kW, kH, {0, 0, static_cast<plot::f32>(kW), static_cast<plot::f32>(kH)});
|
||||||
|
r.draw(p);
|
||||||
|
r.end_frame();
|
||||||
|
PLOT_CHECK(!r.last_frame_had_gl_error());
|
||||||
|
|
||||||
|
const plot::Rect& a = p.layout().axes;
|
||||||
|
const plot::Color bg = r.style().background;
|
||||||
|
const plot::Color major = r.style().grid_major;
|
||||||
|
// Distance from the background, per channel, so "dimmer" means "closer to the background"
|
||||||
|
// whatever the two colours are.
|
||||||
|
const auto bg_distance = [&](const plot::u8 px[4]) {
|
||||||
|
const auto d = [](plot::u8 v, plot::f32 want) {
|
||||||
|
return std::abs(static_cast<int>(v) - static_cast<int>(want * 255.0f + 0.5f));
|
||||||
|
};
|
||||||
|
return d(px[0], bg.r) + d(px[1], bg.g) + d(px[2], bg.b);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The row: the first one that holds all three kinds of pixel, so it is neither a horizontal
|
||||||
|
// grid line (everything major ink) nor a band the layout reserved for something else.
|
||||||
|
const plot::u32 first_row = static_cast<plot::u32>(a.y) + 3u;
|
||||||
|
const plot::u32 last_row = static_cast<plot::u32>(a.y + a.h) - 4u;
|
||||||
|
std::vector<plot::u32> major_cols;
|
||||||
|
std::vector<plot::u32> minor_cols;
|
||||||
|
plot::u32 scan_row = 0;
|
||||||
|
for (plot::u32 row = first_row; row < last_row; ++row) {
|
||||||
|
major_cols.clear();
|
||||||
|
minor_cols.clear();
|
||||||
|
plot::u32 background = 0;
|
||||||
|
for (plot::u32 cx = static_cast<plot::u32>(a.x) + 3u;
|
||||||
|
cx + 3u < static_cast<plot::u32>(a.x + a.w); ++cx) {
|
||||||
|
plot::u8 px[4] = {};
|
||||||
|
PLOT_CHECK(ctx.read_pixel(cx, ctx.height - 1u - row, px));
|
||||||
|
if (pixel_is(px, bg)) {
|
||||||
|
++background;
|
||||||
|
} else if (pixel_is(px, major)) {
|
||||||
|
major_cols.push_back(cx);
|
||||||
|
} else {
|
||||||
|
minor_cols.push_back(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (background > 0u && !major_cols.empty() && !minor_cols.empty()) {
|
||||||
|
scan_row = row;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PLOT_CHECK(scan_row != 0u); // a row carrying both grid classes and the background
|
||||||
|
PLOT_CHECK(major_cols.size() >= 2u);
|
||||||
|
PLOT_CHECK(minor_cols.size() >= 2u);
|
||||||
|
|
||||||
|
// Solid against dashed, down the two columns: a major line is ink at every row, a minor one
|
||||||
|
// alternates -- which is the whole of "dashed" a pixel test can see. The duty cycle is
|
||||||
|
// checked as a range rather than as the exact 3/3 the style asks for, because the dash is a
|
||||||
|
// fragment discard and its ends land where they land.
|
||||||
|
const auto column_ink = [&](plot::u32 cx, plot::u32& ink, plot::u32& gaps) {
|
||||||
|
ink = 0;
|
||||||
|
gaps = 0;
|
||||||
|
for (plot::u32 row = first_row; row < last_row; ++row) {
|
||||||
|
plot::u8 px[4] = {};
|
||||||
|
PLOT_CHECK(ctx.read_pixel(cx, ctx.height - 1u - row, px));
|
||||||
|
if (pixel_is(px, bg)) {
|
||||||
|
++gaps;
|
||||||
|
} else {
|
||||||
|
++ink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plot::u32 ink = 0;
|
||||||
|
plot::u32 gaps = 0;
|
||||||
|
column_ink(major_cols.front(), ink, gaps);
|
||||||
|
PLOT_CHECK(gaps == 0u); // the labelled grid is continuous
|
||||||
|
const plot::u32 major_ink = ink;
|
||||||
|
|
||||||
|
column_ink(minor_cols.front(), ink, gaps);
|
||||||
|
PLOT_CHECK(ink > 0u && gaps > 0u); // dashed, not solid
|
||||||
|
PLOT_CHECK(ink * 5u > major_ink && gaps * 5u > major_ink); // roughly half on, half off
|
||||||
|
|
||||||
|
// Dimmer: the minor's ink sits closer to the background than the major's. This is also the
|
||||||
|
// "thinner" half of the contract at 1x -- see the note above the test.
|
||||||
|
const auto ink_distance = [&](plot::u32 cx) {
|
||||||
|
int best = 0;
|
||||||
|
for (plot::u32 row = first_row; row < last_row; ++row) {
|
||||||
|
plot::u8 px[4] = {};
|
||||||
|
PLOT_CHECK(ctx.read_pixel(cx, ctx.height - 1u - row, px));
|
||||||
|
if (pixel_is(px, bg)) continue;
|
||||||
|
best = std::max(best, bg_distance(px));
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
};
|
||||||
|
const int major_bright = ink_distance(major_cols.front());
|
||||||
|
const int minor_bright = ink_distance(minor_cols.front());
|
||||||
|
PLOT_CHECK(minor_bright > 0);
|
||||||
|
PLOT_CHECK(minor_bright < major_bright);
|
||||||
|
ctx.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
PLOT_TEST(grid_hairlines_land_on_whole_pixels) {
|
PLOT_TEST(grid_hairlines_land_on_whole_pixels) {
|
||||||
plottest::HeadlessContext ctx(kW, kH);
|
plottest::HeadlessContext ctx(kW, kH);
|
||||||
plot::Status st;
|
plot::Status st;
|
||||||
@@ -3296,6 +3419,20 @@ plot::f32 window_ink(const GridFrame& f, const plot::Rect& window, plot::Color b
|
|||||||
return ink;
|
return ink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The ink one minor line is expected to leave in a `kWindowRows`-tall window, **from the
|
||||||
|
/// style**: its width in device pixels, its colour's alpha (the line shader multiplies it in)
|
||||||
|
/// and the dash's duty cycle. Written out rather than as a literal, because the minor class'
|
||||||
|
/// defaults are deliberately a fraction of a solid opaque line -- a threshold saying "most of
|
||||||
|
/// eight rows" stopped describing the class the moment it gained a dash, while it is the style
|
||||||
|
/// that says how much ink a class is *meant* to leave.
|
||||||
|
plot::f32 minor_line_ink(const plot::render::Style& style) {
|
||||||
|
const plot::f32 duty =
|
||||||
|
style.grid_minor_dash_off > 0.0f
|
||||||
|
? style.grid_minor_dash_on / (style.grid_minor_dash_on + style.grid_minor_dash_off)
|
||||||
|
: 1.0f;
|
||||||
|
return kWindowRows * style.device(style.grid_minor_width) * style.grid_minor.a * duty;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/// Spec §11's per-class switch, on the minor class: a class the style switches off is
|
/// Spec §11's per-class switch, on the minor class: a class the style switches off is
|
||||||
@@ -3325,10 +3462,12 @@ PLOT_TEST(disabling_the_minor_grid_removes_its_colour) {
|
|||||||
const GridWindows win = grid_windows(both);
|
const GridWindows win = grid_windows(both);
|
||||||
const plot::f32 major_before = window_ink(both, win.major, bg, major_ink);
|
const plot::f32 major_before = window_ink(both, win.major, bg, major_ink);
|
||||||
const plot::f32 minor_before = window_ink(both, win.minor, bg, minor_ink);
|
const plot::f32 minor_before = window_ink(both, win.minor, bg, minor_ink);
|
||||||
// A line, not one stray fringe pixel: an 8-row window over a 1 px stroke holds about
|
// A line, not one stray fringe pixel: an 8-row window over a stroke holds most of the ink
|
||||||
// 8 px of ink per class, and this asks for most of it.
|
// that stroke is meant to leave. For the major class that is the window's own height; for the
|
||||||
|
// minor class it is what its width, alpha and dash ask for, so the threshold follows the
|
||||||
|
// style instead of a literal the class is no longer drawn to.
|
||||||
PLOT_CHECK(major_before > 0.75f * kWindowRows);
|
PLOT_CHECK(major_before > 0.75f * kWindowRows);
|
||||||
PLOT_CHECK(minor_before > 0.75f * kWindowRows);
|
PLOT_CHECK(minor_before > 0.75f * minor_line_ink(r.style()));
|
||||||
|
|
||||||
r.style().grid_minor_visible = false;
|
r.style().grid_minor_visible = false;
|
||||||
const GridFrame without = draw_grid_scene(ctx, r, 1.0f);
|
const GridFrame without = draw_grid_scene(ctx, r, 1.0f);
|
||||||
@@ -3375,7 +3514,7 @@ PLOT_TEST(disabling_the_major_grid_leaves_the_minor_grid) {
|
|||||||
const plot::f32 major_before = window_ink(both, win.major, bg, r.style().grid_major);
|
const plot::f32 major_before = window_ink(both, win.major, bg, r.style().grid_major);
|
||||||
const plot::f32 minor_before = window_ink(both, win.minor, bg, r.style().grid_minor);
|
const plot::f32 minor_before = window_ink(both, win.minor, bg, r.style().grid_minor);
|
||||||
PLOT_CHECK(major_before > 0.75f * kWindowRows);
|
PLOT_CHECK(major_before > 0.75f * kWindowRows);
|
||||||
PLOT_CHECK(minor_before > 0.75f * kWindowRows);
|
PLOT_CHECK(minor_before > 0.75f * minor_line_ink(r.style()));
|
||||||
|
|
||||||
r.style().grid_major_visible = false;
|
r.style().grid_major_visible = false;
|
||||||
const GridFrame without = draw_grid_scene(ctx, r, 1.0f);
|
const GridFrame without = draw_grid_scene(ctx, r, 1.0f);
|
||||||
@@ -3464,6 +3603,12 @@ PLOT_TEST(grid_widths_are_per_class_and_scale_with_dpi) {
|
|||||||
r.style().grid_major_width = 2.0f;
|
r.style().grid_major_width = 2.0f;
|
||||||
r.style().grid_minor_width = 1.0f;
|
r.style().grid_minor_width = 1.0f;
|
||||||
|
|
||||||
|
// Widths are this test's subject, so the minor class' dash and alpha are stated away first:
|
||||||
|
// they would multiply every count and the ratio below, and their own defaults are the subject
|
||||||
|
// of `the_minor_grid_is_thinner_dashed_and_dimmer_than_the_major`.
|
||||||
|
r.style().grid_minor_dash_off = 0.0f;
|
||||||
|
r.style().grid_minor = plot::Color::hex(0x1C2126);
|
||||||
|
|
||||||
const GridFrame one = draw_grid_scene(ctx, r, 1.0f);
|
const GridFrame one = draw_grid_scene(ctx, r, 1.0f);
|
||||||
const GridWindows win = grid_windows(one);
|
const GridWindows win = grid_windows(one);
|
||||||
const plot::f32 major_1x = window_ink(one, win.major, bg, r.style().grid_major);
|
const plot::f32 major_1x = window_ink(one, win.major, bg, r.style().grid_major);
|
||||||
|
|||||||
Reference in new issue
Block a user