diff --git a/crates/doc/src/props.rs b/crates/doc/src/props.rs index 33120404..4f6491c1 100644 --- a/crates/doc/src/props.rs +++ b/crates/doc/src/props.rs @@ -1189,10 +1189,7 @@ pub enum GridAlign { #[serde(default)] pub struct LayoutGrid { pub kind: GridKind, - /// Grid: cell size. Fixed (not stretched) columns/rows: their width/height. 0 (or Auto) draws - /// a one-pixel hairline at each band's start, like the square grid, and the bands step by - /// `gutter` alone (there is no width to add); a positive value draws a band that many document - /// units wide. A stretched grid works its bands out from the frame and ignores `size`. + /// Grid: cell size. Fixed (not stretched) columns/rows: their width/height. pub size: f64, /// Columns/rows: how many (0: Auto, as many fixed-size ones as fit; a stretched grid has 1). pub count: u32, diff --git a/crates/layout/src/lib.rs b/crates/layout/src/lib.rs index a8376363..02e7bdaf 100644 --- a/crates/layout/src/lib.rs +++ b/crates/layout/src/lib.rs @@ -1047,17 +1047,12 @@ pub fn grid_lines(g: &LayoutGrid, w: f64, h: f64) -> Vec { let total = if cols { w } else { h }; let gutter = if g.gutter.is_finite() { g.gutter.max(0.0) } else { 0.0 }; let offset = if g.offset.is_finite() { g.offset.max(0.0) } else { 0.0 }; - // Auto width (size 0, a non-stretched grid) draws a one-pixel hairline at the band's - // start, like the square grid; otherwise a filled band of `size`. Auto has no width of - // its own, so the gutter alone is the step between the lines. - let auto = g.size <= 0.0 && g.align != GridAlign::Stretch; - let fixed = if g.size.is_finite() && g.size > 0.0 { g.size } else { 0.0 }; let count = match g.count { // Auto: as many fixed-size columns (rows) as fit in the room the type leaves them. 0 if g.align != GridAlign::Stretch => { + let size = if g.size.is_finite() && g.size > 0.0 { g.size } else { 60.0 }; let room = if g.align == GridAlign::Center { total } else { total - offset }; - let step = fixed + gutter; - if step > 0.0 { ((room + gutter) / step).floor().clamp(1.0, 500.0) as usize } else { 1 } + ((room + gutter) / (size + gutter)).floor().clamp(1.0, 500.0) as usize } n => n.clamp(1, 500) as usize, }; @@ -1067,7 +1062,7 @@ pub fn grid_lines(g: &LayoutGrid, w: f64, h: f64) -> Vec { (offset, size) } _ => { - let size = fixed; + let size = if g.size.is_finite() && g.size > 0.0 { g.size } else { 60.0 }; let span = size * count as f64 + gutter * (count - 1) as f64; let start = match g.align { GridAlign::Min => offset, @@ -1079,12 +1074,7 @@ pub fn grid_lines(g: &LayoutGrid, w: f64, h: f64) -> Vec { }; for i in 0..count { let a = start + i as f64 * (size + gutter); - if auto { - // A one-pixel hairline where the band would start (the square grid's lines). - out.push(if cols { Rect::new(a, 0.0, a, h) } else { Rect::new(0.0, a, w, a) }); - } else { - out.push(if cols { Rect::new(a, 0.0, a + size, h) } else { Rect::new(0.0, a, w, a + size) }); - } + out.push(if cols { Rect::new(a, 0.0, a + size, h) } else { Rect::new(0.0, a, w, a + size) }); } } } @@ -1114,16 +1104,11 @@ pub fn grid_snap_lines_in(doc: &Document, frame: NodeId, xf: Affine) -> (Vec { xs.push(a.x); - // An Auto-width band is one line, not an edge pair. - if (b.x - a.x).abs() > 1e-9 { - xs.push(b.x); - } + xs.push(b.x); } GridKind::Rows => { ys.push(a.y); - if (b.y - a.y).abs() > 1e-9 { - ys.push(b.y); - } + ys.push(b.y); } GridKind::Grid => { if (r.x0 - r.x1).abs() < 1e-9 { diff --git a/crates/layout/src/tests.rs b/crates/layout/src/tests.rs index cf8e944a..0af9861b 100644 --- a/crates/layout/src/tests.rs +++ b/crates/layout/src/tests.rs @@ -447,41 +447,3 @@ fn grid_hostile_values() { assert!(x.is_finite() && y.is_finite() && w.is_finite() && h.is_finite()); } } - -#[test] -fn grid_lines_auto_width_columns_rows_hairline() { - // Columns with Auto width (size 0, non-stretched) draw one-pixel hairlines at each band's - // start, like the square grid; a set width draws filled bands. - let g = LayoutGrid { kind: GridKind::Columns, align: GridAlign::Min, count: 3, size: 0.0, gutter: 10.0, offset: 0.0, ..LayoutGrid::default() }; - let lines = grid_lines(&g, 300.0, 50.0); - assert_eq!(lines.len(), 3, "three hairlines"); - for r in &lines { - assert!((r.x0 - r.x1).abs() < 1e-9 && (r.y0 - r.y1).abs() > 1.0, "a vertical hairline: {r:?}"); - } - // Auto has no width of its own, so the gutter alone is the step between the lines (no band - // width hidden in it). - let xs: Vec = lines.iter().map(|r| r.x0).collect(); - assert_eq!(xs, [0.0, 10.0, 20.0], "Auto steps by the gutter: {xs:?}"); - // Auto count: as many hairlines as the gutter fits. - let g = LayoutGrid { kind: GridKind::Columns, align: GridAlign::Min, count: 0, size: 0.0, gutter: 10.0, offset: 0.0, ..LayoutGrid::default() }; - let lines = grid_lines(&g, 300.0, 50.0); - assert_eq!(lines.len(), 31, "300 wide, 10 apart: 31 lines"); - // A positive width draws filled bands again. - let g = LayoutGrid { kind: GridKind::Columns, align: GridAlign::Min, count: 3, size: 8.0, gutter: 10.0, offset: 0.0, ..LayoutGrid::default() }; - let lines = grid_lines(&g, 300.0, 50.0); - assert!(lines.iter().all(|r| (r.x1 - r.x0).abs() > 1e-9), "a set width draws bands"); - - // Rows Auto width: horizontal hairlines. - let g = LayoutGrid { kind: GridKind::Rows, align: GridAlign::Min, count: 2, size: 0.0, gutter: 10.0, offset: 0.0, ..LayoutGrid::default() }; - let lines = grid_lines(&g, 50.0, 200.0); - assert_eq!(lines.len(), 2, "two hairlines"); - for r in &lines { - assert!((r.y0 - r.y1).abs() < 1e-9 && (r.x0 - r.x1).abs() > 1.0, "a horizontal hairline: {r:?}"); - } - // A stretched grid works its bands out from the frame whatever its width says. - let g = - LayoutGrid { kind: GridKind::Columns, align: GridAlign::Stretch, count: 4, size: 0.0, gutter: 10.0, offset: 0.0, ..LayoutGrid::default() }; - let lines = grid_lines(&g, 400.0, 50.0); - assert!(lines.iter().all(|r| (r.x1 - r.x0) > 1.0), "stretch draws bands, not hairlines: {lines:?}"); - assert!((lines[0].x0 - 0.0).abs() < 1e-9 && (lines[3].x1 - 400.0).abs() < 1e-9, "the bands fill the frame"); -} diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index b400e56d..96bd20bf 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -923,12 +923,7 @@ fn overlays(app: &FigApp, painter: &egui::Painter, t: &Tokens) -> Vec<(NodeId, [ let a = w * Point::new(r.x0, r.y0); let b = w * Point::new(r.x1, r.y1); let (sa, sb) = (app.to_screen(a.x, a.y), app.to_screen(b.x, b.y)); - // The square grid and an Auto-width line draw one-pixel hairlines; a filled - // band (a column/row with a set width) is painted as a rectangle. - if g.kind == figcraft_doc::GridKind::Grid - || (r.x0 - r.x1).abs() < 1e-9 - || (r.y0 - r.y1).abs() < 1e-9 - { + if g.kind == figcraft_doc::GridKind::Grid { painter.line_segment([sa, sb], stroke(col, 1.0)); } else { painter.rect_filled(Rect::from_two_pos(sa, sb), CornerRadius::ZERO, col);