move y-axis labels to the right

This commit is contained in:
Emil Lerch 2026-06-25 15:29:19 -07:00
parent 6170dc1ac1
commit 889cfc215a
Signed by: lobo
GPG key ID: A7B62D657EF764F8
4 changed files with 20 additions and 17 deletions

View file

@ -63,15 +63,17 @@ pub fn fmtDollar(buf: []u8, value: f64) []const u8 {
return std.fmt.bufPrint(buf, "{s}${s}", .{ sign, commas }) catch "$?";
}
/// Draw `n + 1` right-aligned dollar labels evenly spaced from
/// `value_max` (at `top`) down to `value_min` (at `bottom`), with each
/// label's right edge a small pad left of `right_x` (typically the
/// plot's left edge) and vertically centered on its level.
/// Draw `n + 1` left-aligned dollar labels evenly spaced from
/// `value_max` (at `top`) down to `value_min` (at `bottom`), placed in
/// the right margin a small pad to the right of `plot_right` (the plot's
/// right edge) and vertically centered on each level. Right-side y-axis
/// is the financial convention: the latest (rightmost) values sit next
/// to the scale as the series grows.
pub fn drawYDollarTicks(
sfc: *Surface,
scale: i32,
color: [3]u8,
right_x: f64,
plot_right: f64,
top: f64,
bottom: f64,
value_min: f64,
@ -82,6 +84,7 @@ pub fn drawYDollarTicks(
const span = bottom - top;
const half_h = @divFloor(text.glyph_h * scale, 2);
const pad: f64 = labelGap(scale);
const lx: i32 = @intFromFloat(plot_right + pad);
var i: usize = 0;
while (i <= n) : (i += 1) {
const frac = @as(f64, @floatFromInt(i)) / @as(f64, @floatFromInt(n));
@ -89,8 +92,6 @@ pub fn drawYDollarTicks(
const y = top + frac * span;
var buf: [24]u8 = undefined;
const label = fmtDollar(&buf, val);
const lw = text.measureWidth(label, scale);
const lx = @as(i32, @intFromFloat(right_x - pad)) - lw;
const ly = @as(i32, @intFromFloat(y)) - half_h;
text.drawText(sfc, lx, ly, scale, color, label);
}
@ -142,7 +143,9 @@ test "drawYDollarTicks stamps labels in the requested color" {
const color = [3]u8{ 0xCC, 0xCC, 0xCC };
try testing.expectEqual(@as(usize, 0), draw.countColor(&sfc, color));
drawYDollarTicks(&sfc, 2, color, 280, 10, 190, 1_000_000, 5_000_000, 5);
// plot_right=180 leaves room for the labels in the right margin of a
// 300px-wide surface.
drawYDollarTicks(&sfc, 2, color, 180, 10, 190, 1_000_000, 5_000_000, 5);
try testing.expect(draw.countColor(&sfc, color) > 0);
}

View file

@ -287,8 +287,8 @@ pub fn renderToSurface(
// scaled to the surface so labels stay legible on large exports.
const label_scale: i32 = axis.labelScale(h);
const label_char_h: f64 = axis.charHeight(label_scale);
const m_left: f64 = if (axis_labels) axis.yAxisMargin(label_scale) else margin_left;
const m_right: f64 = if (axis_labels) label_char_h else margin_right;
const m_left: f64 = if (axis_labels) label_char_h else margin_left;
const m_right: f64 = if (axis_labels) axis.yAxisMargin(label_scale) else margin_right;
const m_top: f64 = if (axis_labels) (label_char_h / 2 + 4) else margin_top;
const m_bottom: f64 = if (axis_labels) axis.bottomMargin(label_scale) else margin_bottom;
@ -502,7 +502,7 @@ pub fn renderToSurface(
// Axis labels (export only)
if (axis_labels) {
// Dollar ticks against the price panel; start/end dates below.
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_left, price_top, price_bottom, price_min, price_max, 4);
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_right, price_top, price_bottom, price_min, price_max, 4);
var fbuf: [12]u8 = undefined;
var lbuf: [12]u8 = undefined;
const first_s = std.fmt.bufPrint(&fbuf, "{f}", .{data[0].date}) catch "";

View file

@ -149,8 +149,8 @@ pub fn renderToSurface(
// with the surface so labels stay legible on large exports.
const label_scale: i32 = axis.labelScale(h);
const label_char_h: f64 = axis.charHeight(label_scale);
const m_left: f64 = if (opts.axis_labels) axis.yAxisMargin(label_scale) else margin_left;
const m_right: f64 = if (opts.axis_labels) label_char_h else margin_right;
const m_left: f64 = if (opts.axis_labels) label_char_h else margin_left;
const m_right: f64 = if (opts.axis_labels) axis.yAxisMargin(label_scale) else margin_right;
const m_top: f64 = if (opts.axis_labels) (label_char_h / 2 + 4) else margin_top;
const m_bottom: f64 = if (opts.axis_labels) axis.bottomMargin(label_scale) else margin_bottom;
@ -246,7 +246,7 @@ pub fn renderToSurface(
// Axis labels (export only; drawn directly into the buffer)
if (opts.axis_labels) {
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_left, chart_top, chart_bottom, value_min, value_max, 5);
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_right, chart_top, chart_bottom, value_min, value_max, 5);
var fbuf: [12]u8 = undefined;
var lbuf: [12]u8 = undefined;
const first_s = std.fmt.bufPrint(&fbuf, "{f}", .{points[0].date}) catch "";

View file

@ -124,8 +124,8 @@ pub fn renderToSurface(
// ticks) and a bottom margin (year endpoints), scaled to the surface.
const label_scale: i32 = axis.labelScale(h);
const label_char_h: f64 = axis.charHeight(label_scale);
const m_left: f64 = if (axis_labels) axis.yAxisMargin(label_scale) else margin_left;
const m_right: f64 = if (axis_labels) label_char_h else margin_right;
const m_left: f64 = if (axis_labels) label_char_h else margin_left;
const m_right: f64 = if (axis_labels) axis.yAxisMargin(label_scale) else margin_right;
const m_top: f64 = if (axis_labels) (label_char_h / 2 + 4) else margin_top;
const m_bottom: f64 = if (axis_labels) axis.bottomMargin(label_scale) else margin_bottom;
const chart_left = m_left;
@ -311,7 +311,7 @@ pub fn renderToSurface(
// Axis labels (export only)
if (axis_labels) {
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_left, chart_top, chart_bottom, value_min, value_max, 5);
axis.drawYDollarTicks(&sfc, label_scale, th.text_muted, chart_right, chart_top, chart_bottom, value_min, value_max, 5);
var fbuf: [8]u8 = undefined;
var lbuf: [8]u8 = undefined;
const first_s = std.fmt.bufPrint(&fbuf, "{d}", .{bands[0].year}) catch "";