From 140681429f15331045673162df0f09c048bb294d Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Sat, 24 Oct 2026 08:52:37 +0000 Subject: [PATCH] refactor: split complex functions in epub table and pdf frame text (Sonar S3776) Co-Authored-By: Claude Sonnet 5.5 --- crates/epub/src/lib.rs | 25 ++++++++++++-------- crates/pdf/src/text.rs | 53 +++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/crates/epub/src/lib.rs b/crates/epub/src/lib.rs index 1df759608..0ecc4e1a8 100644 --- a/crates/epub/src/lib.rs +++ b/crates/epub/src/lib.rs @@ -967,6 +967,20 @@ impl<'a, 'f> StoryWriter<'a, 'f> { out } + /// One table cell with its row and column spans, as `th` or `td`. + fn table_cell(&mut self, text: &Story, cell_tag: &str, (rs, cs): (usize, usize), depth: usize, out: &mut String) { + let _ = write!(out, "<{cell_tag}"); + if rs > 1 { + let _ = write!(out, " rowspan=\"{rs}\""); + } + if cs > 1 { + let _ = write!(out, " colspan=\"{cs}\""); + } + out.push('>'); + self.paragraphs(text, depth, "", out); + let _ = writeln!(out, ""); + } + /// A table: header rows as `thead`, footer rows as `tfoot`, merged cells as row and column /// spans (kept within their row group). fn table(&mut self, t: &Table, depth: usize, out: &mut String) { @@ -1000,16 +1014,7 @@ impl<'a, 'f> StoryWriter<'a, 'f> { } } } - let _ = write!(out, "<{cell_tag}"); - if rs > 1 { - let _ = write!(out, " rowspan=\"{rs}\""); - } - if cs > 1 { - let _ = write!(out, " colspan=\"{cs}\""); - } - out.push('>'); - self.paragraphs(&cell.text, depth, "", out); - let _ = writeln!(out, ""); + self.table_cell(&cell.text, cell_tag, (rs, cs), depth, out); } out.push_str("\n"); } diff --git a/crates/pdf/src/text.rs b/crates/pdf/src/text.rs index 1aaf435d9..b68a70571 100644 --- a/crates/pdf/src/text.rs +++ b/crates/pdf/src/text.rs @@ -233,6 +233,34 @@ impl Exporter<'_> { } } + /// One line's glyphs as tagged runs; a glyph that is turned or slanted gets a transform of its own. + fn line_glyphs(&mut self, s: &mut Surface, cs: &ComposedStory, ft: &FrameText, l: &designcraft_compose::Line, story: &str) { + let gs = &l.glyphs; + let mut i = 0; + while i < gs.len() { + let g = &gs[i]; + if !g.visible || g.sx <= 0.0 || g.sy <= 0.0 { + i += 1; + continue; + } + // Vertical type: an upright glyph turns back a quarter about its em box centre. + // Shatai slants each glyph about its own em box centre first. + let turn = if ft.vertical { g.vertical_xf(l.baseline) } else { None }; + let shatai = cs.styles.get(g.style as usize).and_then(|st| st.shatai_xf(g, l.baseline)); + if turn.is_some() || shatai.is_some() { + let m = turn.unwrap_or(Affine::IDENTITY) * shatai.unwrap_or(Affine::IDENTITY); + s.push_transform(&crate::export::tf(m)); + self.tagged_run(s, cs, &gs[i..i + 1], l.baseline, story); + s.pop(); + i += 1; + continue; + } + let j = run_end(ft, gs, i); + self.tagged_run(s, cs, &gs[i..j], l.baseline, story); + i = j; + } + } + pub(crate) fn frame_text(&mut self, s: &mut Surface, cs: &ComposedStory, ft: &FrameText, story: &str) { // Paragraph shading and rules under the text. self.as_artifact(s, |me, s| { @@ -260,30 +288,7 @@ impl Exporter<'_> { }); } for l in &ft.lines { - let gs = &l.glyphs; - let mut i = 0; - while i < gs.len() { - let g = &gs[i]; - if !g.visible || g.sx <= 0.0 || g.sy <= 0.0 { - i += 1; - continue; - } - // Vertical type: an upright glyph turns back a quarter about its em box centre. - // Shatai slants each glyph about its own em box centre first. - let turn = if ft.vertical { g.vertical_xf(l.baseline) } else { None }; - let shatai = cs.styles.get(g.style as usize).and_then(|st| st.shatai_xf(g, l.baseline)); - if turn.is_some() || shatai.is_some() { - let m = turn.unwrap_or(Affine::IDENTITY) * shatai.unwrap_or(Affine::IDENTITY); - s.push_transform(&crate::export::tf(m)); - self.tagged_run(s, cs, &gs[i..i + 1], l.baseline, story); - s.pop(); - i += 1; - continue; - } - let j = run_end(ft, gs, i); - self.tagged_run(s, cs, &gs[i..j], l.baseline, story); - i = j; - } + self.line_glyphs(s, cs, ft, l, story); } self.as_artifact(s, |me, s| { for (rule, r) in text_rules(cs, ft, false) {