mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
Never crash: text layout and font resolution without expect()
Text layout and font resolution without expect(): an empty line list keeps the default bounds, the line breaker stops instead of expect()ing a checked option, and font resolution falls back to the first bundled face. The one remaining expect (the bundled-font database is never empty) carries the documented narrow allow. Denies the panic lints in the crate. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
10644a83aa
commit
0873393e43
4 files changed
+19
-12
No files matched your search
@@ -0,0 +1,4 @@
|
||||
allow-unwrap-in-tests = true
|
||||
allow-expect-in-tests = true
|
||||
allow-panic-in-tests = true
|
||||
allow-indexing-slicing-in-tests = true
|
||||
@@ -309,6 +309,9 @@ pub fn system_scanned() -> bool {
|
||||
/// A face by id (panics never: unknown ids give the default face).
|
||||
pub fn face(id: FaceId) -> Arc<Face> {
|
||||
let d = db().read().unwrap_or_else(|e| e.into_inner());
|
||||
// The bundled fonts are compiled in and always parse (`tests::bundled_families_and_resolution` checks them), so
|
||||
// the database is never empty.
|
||||
#[allow(clippy::expect_used)]
|
||||
d.faces.get(id).or_else(|| d.faces.first()).cloned().expect("bundled fonts present")
|
||||
}
|
||||
|
||||
@@ -388,7 +391,8 @@ pub fn resolve(family: &str, style: &str) -> Resolved {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
let mut r = resolve_in(DEFAULT_FAMILY, style).expect("Inter is bundled");
|
||||
// Inter is bundled; face 0 (the first bundled face) is the last resort.
|
||||
let mut r = resolve_in(DEFAULT_FAMILY, style).unwrap_or(Resolved { face: 0, synth_bold: false, synth_italic: false, missing: true });
|
||||
r.missing = !family.is_empty() && !family.eq_ignore_ascii_case(DEFAULT_FAMILY);
|
||||
r
|
||||
}
|
||||
@@ -403,13 +407,10 @@ fn resolve_in(family: &str, style: &str) -> Option<Resolved> {
|
||||
return Some(Resolved { face: f.id, synth_bold: false, synth_italic: false, missing: false });
|
||||
}
|
||||
let (w, it) = style_wants(style);
|
||||
let best = fam
|
||||
.iter()
|
||||
.min_by_key(|f| {
|
||||
let italic_pen = if f.info.italic == it { 0 } else { 1000 };
|
||||
italic_pen + (f.info.weight as i32 - w as i32).unsigned_abs()
|
||||
})
|
||||
.expect("non-empty");
|
||||
let best = fam.iter().min_by_key(|f| {
|
||||
let italic_pen = if f.info.italic == it { 0 } else { 1000 };
|
||||
italic_pen + (f.info.weight as i32 - w as i32).unsigned_abs()
|
||||
})?;
|
||||
Some(Resolved { face: best.id, synth_bold: w >= 600 && best.info.weight <= 500, synth_italic: it && !best.info.italic, missing: false })
|
||||
}
|
||||
|
||||
|
||||
@@ -776,7 +776,7 @@ fn paragraph(text: &str, base: usize, runs: &[(Range<usize>, TextStyle)], primar
|
||||
last_ok = Some(p);
|
||||
break;
|
||||
}
|
||||
let b = last_ok.take().expect("checked");
|
||||
let Some(b) = last_ok.take() else { break };
|
||||
ranges.push(start..b);
|
||||
start = b;
|
||||
}
|
||||
@@ -1015,9 +1015,9 @@ pub fn layout_rich_uncached(text: &str, runs: &[(Range<usize>, TextStyle)], para
|
||||
x0 = x0.min(0.0);
|
||||
x1 = x1.max(w);
|
||||
}
|
||||
let first = &lay.lines[0];
|
||||
let last = lay.lines.last().expect("at least one line");
|
||||
lay.bounds = [x0, first.baseline - first.ascent, x1.max(x0), last.baseline + last.descent];
|
||||
if let (Some(first), Some(last)) = (lay.lines.first(), lay.lines.last()) {
|
||||
lay.bounds = [x0, first.baseline - first.ascent, x1.max(x0), last.baseline + last.descent];
|
||||
}
|
||||
lay
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
//! - This module turns a layer's [`TextDoc`] into per-character glyph outlines (Bezier paths) with
|
||||
//! character / word / line indices, which is what text animators and selectors work on.
|
||||
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
|
||||
pub mod fonts;
|
||||
pub mod layout;
|
||||
pub mod path_text;
|
||||
|
||||
Reference in new issue
Block a user