feat(lapaloma-cartesian): ejes con ticks y labels decimadas

- axis.rs: ticks_nice (Wilkinson sobre lapaloma_core::scale::nice_step),
  decimate_labels con min_spacing_px, format_tick con decimales según
  step, AxisStyle config. 8 tests.
- gpui_backend::draw_text: shape_line via window.text_system() + iterate
  glyphs con paint_glyph. Sin dep en App context (sólo &mut Window).
- LapalomaChartElement.paint_axes: línea base + tick marks + labels
  centrados (X) / right-aligned (Y) con decimación. Margins por defecto
  reservan 32px izq + 24px abajo.

45 tests verdes en lapaloma-{core,cartesian,render}.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-13 02:43:01 +00:00
parent 97c09bc96a
commit fd25369715
4 changed files with 397 additions and 37 deletions
@@ -16,7 +16,10 @@
//! `WindowTextSystem` en una fase próxima).
use crate::{Canvas, Color, Point, Rect, StrokeStyle};
use gpui::{fill, hsla, point as gpui_point, px, size as gpui_size, Bounds, Hsla, PathBuilder, Window};
use gpui::{
fill, font, hsla, point as gpui_point, px, size as gpui_size, Bounds, Hsla, PathBuilder,
SharedString, TextRun, Window,
};
/// Adapter que pinta sobre un `&mut Window` de GPUI.
///
@@ -120,8 +123,42 @@ impl<'a> Canvas for WindowCanvas<'a> {
// vertex buffer wgpu.
}
fn draw_text(&mut self, _p: Point, _text: &str, _color: Color, _size_px: f32) {
// TODO: integrar con WindowTextSystem para axis labels.
fn draw_text(&mut self, p: Point, text: &str, color: Color, size_px: f32) {
if text.is_empty() {
return;
}
let hsla = color_to_hsla(color);
let font_size = px(size_px);
let text_str: SharedString = text.to_string().into();
let runs = [TextRun {
len: text.len(),
font: font("Monospace"),
color: hsla,
background_color: None,
underline: None,
strikethrough: None,
}];
let shaped = self
.window
.text_system()
.shape_line(text_str, font_size, &runs, None);
// Iteramos glyphs vía `paint_glyph` para evitar la
// dependencia con `&mut App` que pide `ShapedLine::paint`.
// Eso encaja con el contrato actual del Canvas trait que
// sólo expone `&mut Window`.
let origin_x = px(p.x);
let origin_y = px(p.y);
for run in shaped.runs.iter() {
for glyph in run.glyphs.iter() {
let gx = origin_x + glyph.position.x;
let gy = origin_y + glyph.position.y;
let _ = self
.window
.paint_glyph(gpui_point(gx, gy), run.font_id, glyph.id, font_size, hsla);
}
}
}
}