Merge pull request #19 from storytold/pr/never-crash-render

Never crash: render has no expect/unreachable
This commit is contained in:
Brandon Thomas authored and GitHub committed 2026-10-04 14:47:45 -04:00
commit 66d127bb73
3 files changed
+10 -15

No files matched your search

+1 -8
View File
@@ -392,14 +392,7 @@ impl<'a> Inspector<'a> {
match self.resolve(dest) {
Object::Array(a) => a.first().and_then(|p| self.page_of(p)),
Object::Dictionary(d) => d.get(b"D").ok().and_then(|d| self.dest_page(d, depth + 1)),
named @ (Object::String(..) | Object::Name(_)) => {
let key = match named {
Object::String(s, _) => s.clone(),
Object::Name(n) => n.clone(),
_ => unreachable!(),
};
self.named_dest(&key).and_then(|d| self.dest_page(d, depth + 1))
}
Object::String(key, _) | Object::Name(key) => self.named_dest(key).and_then(|d| self.dest_page(d, depth + 1)),
_ => None,
}
}
+2
View File
@@ -6,6 +6,8 @@
//! DisplayList device design in M1–M2. The public API here is what the engine and UI rely on, so
//! the swap stays internal to this crate.
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
mod inspect;
mod raster;
pub mod text;
+7 -7
View File
@@ -360,13 +360,12 @@ pub fn layout(glyphs: Vec<TextGlyph>) -> PageText {
for i in 0..n {
let g = glyphs[i].rect;
let cont = segs.last().is_some_and(|s| {
let p = *s.idx.last().expect("non-empty");
let Some(&p) = s.idx.last() else { return false };
let ph = height(p).min(height(i));
let gap = g[0] - glyphs[p].rect[2];
(cy(i) - cy(p)).abs() < ph * 0.5 && gap < ph * 3.0 && g[0] > glyphs[p].rect[0] - ph * 2.0
});
if cont {
let s = segs.last_mut().expect("non-empty");
if cont && let Some(s) = segs.last_mut() {
s.idx.push(i);
union(&mut s.bbox, &g);
s.h = s.h.max(height(i));
@@ -410,7 +409,8 @@ pub fn layout(glyphs: Vec<TextGlyph>) -> PageText {
for si in by_top {
let s = &segs[si];
let target = blocks.iter().position(|(members, bb)| {
let last = &segs[*members.last().expect("non-empty")];
let Some(&m) = members.last() else { return false };
let last = &segs[m];
let vgap = s.bbox[1] - last.bbox[3];
let overlap = s.bbox[2].min(bb[2]) - s.bbox[0].max(bb[0]);
let minw = (s.bbox[2] - s.bbox[0]).min(bb[2] - bb[0]).max(1.0);
@@ -429,8 +429,7 @@ pub fn layout(glyphs: Vec<TextGlyph>) -> PageText {
// 3. Block order.
let mut remaining: Vec<usize> = (0..blocks.len()).collect();
let mut block_order = Vec::with_capacity(blocks.len());
while !remaining.is_empty() {
let top = *remaining.iter().min_by(|a, b| blocks[**a].1[1].total_cmp(&blocks[**b].1[1])).expect("non-empty");
while let Some(&top) = remaining.iter().min_by(|a, b| blocks[**a].1[1].total_cmp(&blocks[**b].1[1])) {
let tb = blocks[top].1;
let pick = remaining
.iter()
@@ -500,7 +499,8 @@ pub fn layout(glyphs: Vec<TextGlyph>) -> PageText {
}
}
let mut slots: Vec<Option<TextGlyph>> = glyphs.into_iter().map(Some).collect();
let glyphs = order.iter().map(|i| slots[*i].take().expect("each glyph emitted once")).collect();
// Each glyph is emitted exactly once.
let glyphs = order.iter().filter_map(|i| slots.get_mut(*i).and_then(Option::take)).collect();
PageText { glyphs, line_of, space_before }
}