fix(render): drop x title rows the chrome clamp cut short
This commit is contained in:
1 parent
e211701d05
commit
9dc3b1e5e6
2 files changed
+168
-20
No files matched your search
+25
-19
@@ -586,22 +586,38 @@ void Renderer::draw_titles(const Plot& plot, const PlotLayout& layout) {
|
||||
// than the strip -- which the layout caps, because a title may shrink the plot
|
||||
// but never erase it -- stops at the strip's padding instead of spilling over the
|
||||
// labels or the data.
|
||||
//
|
||||
// A line is staged only if the cell it occupies *fits* the strip, and that is a
|
||||
// check this function owns: a run's clip cuts along the run (`walk_text_clipped()`),
|
||||
// the layout clamps the strip against the viewport's chrome allowance without
|
||||
// knowing what a line is (`Plot::layout()`), and the cell's other dimension -- a
|
||||
// row's height, a column's width -- is one text line. Rows are staged top down and
|
||||
// columns left to right, so the lines a clamped strip cut short are the trailing
|
||||
// ones: keep the leading lines that fit and stage no more. A dropped title is
|
||||
// chrome that had no room, which is the same bargain the label strips already make
|
||||
// -- never drawn outside its strip, and never inside `axes`.
|
||||
const f32 pad = style_.grid_label_pad;
|
||||
const f32 line_h = font_backend_.height();
|
||||
|
||||
// X titles: the strip's rows top down, one per titled axis, each read left to
|
||||
// right on the row it owns.
|
||||
// right on the row it owns. A row must fit the strip's *height* -- with this basis
|
||||
// the cell is [pen.y, pen.y + line_h] -- and the x strip is the bottom-most, so a
|
||||
// row that does not fit leaves the target entirely (nothing is over it) and is
|
||||
// clipped rather than overprinted. It is dropped all the same: a title is drawn in
|
||||
// the strip the layout reserved, or not at all, and this is the dimension the
|
||||
// layout's clamp is applied to.
|
||||
for (u32 i = 0, row = 0; i < plot.x_axis_count(); ++i) {
|
||||
const Axis& axis = plot.x_axis(i);
|
||||
if (axis.label.empty()) continue;
|
||||
const Rect& strip = layout.x_title_area;
|
||||
const f32 y = strip.y + pad + static_cast<f32>(row) * line_h;
|
||||
if (y + line_h > strip.bottom()) break;
|
||||
const f32 budget = strip.w - 2.0f * pad;
|
||||
const f32 width = clipped_text_width(axis.label.c_str(), budget, kTextRight);
|
||||
// Centred on the strip: the tick labels have their own rows above it, so the
|
||||
// title needs no alignment of its own.
|
||||
stage_text_clipped({strip.x + 0.5f * (strip.w - width),
|
||||
strip.y + pad + static_cast<f32>(row) * line_h},
|
||||
axis.label.c_str(), budget, kTextRight);
|
||||
stage_text_clipped({strip.x + 0.5f * (strip.w - width), y}, axis.label.c_str(), budget,
|
||||
kTextRight);
|
||||
++row;
|
||||
}
|
||||
|
||||
@@ -622,21 +638,11 @@ void Renderer::draw_titles(const Plot& plot, const PlotLayout& layout) {
|
||||
const Axis& axis = plot.y_axis(i);
|
||||
if (axis.label.empty()) continue;
|
||||
const Rect& strip = layout.y_title_area;
|
||||
// A column must *fit* before it is staged, and its own cell is what has to fit:
|
||||
// with this basis the cell occupies [pen.x, pen.x + line_h], so the strip's
|
||||
// width -- the one dimension the run never advances along -- is the whole of a
|
||||
// column's cross extent, and nothing else in this path can see it. `walk_text_clipped()`
|
||||
// cuts along the run and would happily stage a column that is wider than the
|
||||
// strip it belongs to, drawing its cells over whatever is beside them.
|
||||
//
|
||||
// The layout clamps the strip against the viewport's chrome allowance (see
|
||||
// `Plot::layout()`), so a viewport narrow enough to spend that allowance on the
|
||||
// tick labels leaves room for fewer columns than there are titled axes, or for
|
||||
// none at all. Columns are laid out left to right, so the ones the clamp cut
|
||||
// short are the trailing ones: keep the leading columns that fit and stage no
|
||||
// more. A dropped title is chrome that had no room, which is the same bargain
|
||||
// the label strip already makes -- never drawn outside its strip, and never
|
||||
// inside `axes`.
|
||||
// A column must fit the strip's *width* -- with this basis the cell is
|
||||
// [pen.x, pen.x + line_h] -- and a column that does not fit is unlike an x row,
|
||||
// which would leave the target and be clipped: this one is drawn beside the
|
||||
// columns that do fit, over the tick labels the next strip holds, and past `axes`
|
||||
// once the columns reach it (a 64 px viewport does both). See the rule above.
|
||||
const f32 x = strip.x + pad + static_cast<f32>(column) * line_h;
|
||||
if (x + line_h > strip.right()) break;
|
||||
const f32 budget = strip.h - 2.0f * pad;
|
||||
|
||||
Reference in new issue
Block a user