authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-24 10:50:33-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-25 20:26:21-07:00
logf5d0249a43558a42eb7286211d167646f9eed475
treef259b508829f5966172ffdb5823e8b4ba203211d
parentc3f7869026fe3c368c667c6d6d40cfe6c7fef277
signature Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU

feat: align paragraphs left, center or right as stored

Paragraph alignment was read from the file but every paragraph laid out left-aligned. Lines now offset within the wrap width for center (1) and right (2), the values OneNote stores. Assisted-by: claude-opus-5.5

1 files changed, 39 insertions(+), 1 deletions(-)

crates/canvas/src/layout.rs+39-1
...@@ -176,7 +176,12 @@ impl TextEngine {...@@ -176,7 +176,12 @@ impl TextEngine {
176 }176 }
177 let mut shaped = builder.build(text);177 let mut shaped = builder.build(text);
178 shaped.break_all_lines(Some(width));178 shaped.break_all_lines(Some(width));
179 shaped.align(Alignment::Start, AlignmentOptions::default());179 let alignment = match paragraph.spans()[0].format.alignment {
180 Some(1) => Alignment::Center,
181 Some(2) => Alignment::End,
182 _ => Alignment::Start,
183 };
184 shaped.align(alignment, AlignmentOptions::default());
180 Ok(shaped)185 Ok(shaped)
181 }186 }
182187
...@@ -549,6 +554,39 @@ mod tests {...@@ -549,6 +554,39 @@ mod tests {
549 assert_eq!(fonts.len(), 1);554 assert_eq!(fonts.len(), 1);
550 }555 }
551556
557 #[test]
558 fn paragraph_alignment_offsets_lines_within_the_wrap_width() {
559 let mut engine = TextEngine::default();
560 let mut offset = |alignment| {
561 let layout = engine
562 .layout(
563 &Paragraph::new(
564 "Short".into(),
565 Format {
566 alignment,
567 ..Format::default()
568 },
569 ),
570 200.0,
571 )
572 .unwrap();
573 let (line, _) = layout.lines().next().unwrap();
574 let advance = line.metrics().advance;
575 let x = line
576 .items()
577 .find_map(|item| match item {
578 PositionedLayoutItem::GlyphRun(run) => Some(run.offset()),
579 _ => None,
580 })
581 .unwrap();
582 (x, advance)
583 };
584 let (left, advance) = offset(None);
585 assert_eq!(left, 0.0);
586 assert!(((offset(Some(1)).0) - (200.0 - advance) / 2.0).abs() < 0.01);
587 assert!(((offset(Some(2)).0) - (200.0 - advance)).abs() < 0.01);
588 }
589
552 #[test]590 #[test]
553 fn highlights_share_line_geometry_without_changing_wraps() {591 fn highlights_share_line_geometry_without_changing_wraps() {
554 let paragraph = Paragraph::from_runs([592 let paragraph = Paragraph::from_runs([