mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-30 05:17:25 -06:00
Layout: a drop cap in a font over 1000 pt no longer panics (#389)
The drop-cap letter's size was `clamp(rc.size, 1000.0)`, and `f32::clamp` panics when the minimum is above the maximum, which happens as soon as the paragraph's text is larger than 1000 pt (Word allows up to 1638). Layout, PDF export and saving run outside `Session::run`'s panic guard, so the desktop app panicked on every frame, and `wordcraft-cli convert` failed. Use `.min(1000.0).max(rc.size)`, which never panics and keeps the letter at least as large as the text. Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
4615cef878
commit
da07540f31
@@ -694,7 +694,8 @@ pub fn layout_para(p: &Paragraph, env: &ParaEnv) -> ParaLayout {
|
||||
let lines = rp.drop_cap as f32;
|
||||
// Capital height is ~0.7 em: the letter's cap spans from line 1's caps to line N's baseline.
|
||||
let mut big = (*rc).clone();
|
||||
big.size = (((lines - 1.0) * line_h + rc.size * 0.7) / 0.7).clamp(rc.size, 1000.0);
|
||||
// `clamp` would panic here when the text itself is larger than 1000 pt.
|
||||
big.size = (((lines - 1.0) * line_h + rc.size * 0.7) / 0.7).min(1000.0).max(rc.size);
|
||||
let before = b.clusters.len();
|
||||
b.shape(first, 0, &Arc::new(big), None);
|
||||
let w: f32 = b.clusters.get(before..).map(|c| c.iter().map(|c| c.adv).sum()).unwrap_or(0.0);
|
||||
|
||||
@@ -1282,6 +1282,24 @@ fn repeated_header_is_followed_by_the_next_row_even_when_it_overflows() {
|
||||
assert!(pages.iter().all(|p| p.first() == Some(&0)), "{pages:?}");
|
||||
}
|
||||
|
||||
/// A drop-cap paragraph in a font larger than 1000 pt used to panic in layout (`clamp` with min > max).
|
||||
#[test]
|
||||
fn drop_cap_with_a_huge_font_lays_out() {
|
||||
for size in [999.0, 1000.0, 1001.0, 1638.0] {
|
||||
let cp = wordcraft_doc::CharProps { size: Some(size), ..Default::default() };
|
||||
let mut p = wordcraft_doc::Paragraph::with_text("Hello drop cap world", cp);
|
||||
p.props.drop_cap = Some(3);
|
||||
let mut d = Document::from_text("x");
|
||||
d.body = vec![wordcraft_doc::para_block(p)];
|
||||
let l = lay(&d);
|
||||
let Some(pl) = l.pages[0].items.iter().find_map(|i| if let Placed::Lines { para, .. } = i { Some(para.clone()) } else { None }) else {
|
||||
panic!("no lines at size {size}")
|
||||
};
|
||||
let (nc, lines, _) = pl.drop_cap.unwrap_or((0, 0, 0.0));
|
||||
assert_eq!((nc, lines), (1, 3), "size {size}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drop_cap_indents_its_lines() {
|
||||
let mut p =
|
||||
|
||||
Reference in New Issue
Block a user