From d47f2f47fe18bf12e204e1cdaf3e5453fd26b299 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 10 Oct 2026 06:43:43 -0400 Subject: [PATCH] Tests: the PDF text extractor counts a synthetic-bold glyph once Synthetic bold fills and then strokes each glyph, and the test helper appended text on both draws, so bold text read "bboolldd". Whether a run gets synthetic bold depended on font resolution under parallel tests, which made exports_pages_text_and_structure flaky (3/40 runs once #133's tests were added). Regression test: synthetic_bold_text_is_extracted_once. Co-Authored-By: Claude Opus 5.5 --- crates/pdf/src/tests.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/pdf/src/tests.rs b/crates/pdf/src/tests.rs index 75698a9..560d22e 100644 --- a/crates/pdf/src/tests.rs +++ b/crates/pdf/src/tests.rs @@ -84,7 +84,11 @@ fn extract_text(bytes: &[u8]) -> Vec { fn draw_path(&mut self, _: &kurbo::BezPath, _: kurbo::Affine, _: &Paint<'_>, _: &PathDrawMode) {} fn push_clip_path(&mut self, _: &ClipPath) {} fn push_transparency_group(&mut self, _: f32, _: Option>, _: BlendMode) {} - fn draw_glyph(&mut self, g: &Glyph<'_>, _: kurbo::Affine, _: kurbo::Affine, _: &Paint<'_>, _: &GlyphDrawMode) { + fn draw_glyph(&mut self, g: &Glyph<'_>, _: kurbo::Affine, _: kurbo::Affine, _: &Paint<'_>, mode: &GlyphDrawMode) { + // Synthetic bold fills and then strokes each glyph: one character, two draws. + if matches!(mode, GlyphDrawMode::Stroke(_)) { + return; + } match g.as_unicode() { Some(hayro_cmap::BfString::Char(c)) => self.0.push(c), Some(hayro_cmap::BfString::String(s)) => self.0.push_str(&s), @@ -332,3 +336,14 @@ fn unsubsettable_font_is_drawn_as_outlines() { assert_eq!(glyphs, 0, "no text in the font krilla can't subset"); assert!(paths > 0, "its glyphs are drawn as outlines"); } + +#[test] +fn synthetic_bold_text_is_extracted_once() { + // JetBrains Mono ships without a bold face, so its bold is filled and stroked: the text + // layer still holds each character once. + let mut d = Document::new(); + let bold = CharProps { font: Some("JetBrains Mono".into()), bold: Some(true), ..Default::default() }; + d.body = vec![para_block(Paragraph::with_text("Mono bold", bold))]; + let text = squash(&extract_text(&export(&d, &PdfOptions::default()).unwrap()).concat()); + assert!(text.contains("Mono bold"), "{text:?}"); +}