PDF: track the first text run with a flag

text_rotated counted the Tf operators written so far on every run, which is
quadratic for text that alternates between WinAnsi and CID characters.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
vangel76
2026-11-07 17:19:10 +01:00
co-authored by Claude Sonnet 5.5
parent b396e6c0bd
commit cca09cc8f4
2 changed files with 14 additions and 1 deletions
+2 -1
View File
@@ -743,8 +743,9 @@ impl Page {
if let Some(f) = self.fonts.get_mut(slot) {
*f = true;
}
let first_run = runs.is_empty();
let _ = writeln!(runs, "/F{} {} Tf", slot + 1, size);
if runs.matches("Tf\n").count() == 1 {
if first_run {
runs.push_str(&tm);
}
let _ = writeln!(runs, "{string} Tj");
+12
View File
@@ -873,6 +873,18 @@ fn cjk_text_is_not_replaced_by_question_marks() -> Result<(), Box<dyn Error>> {
Ok(())
}
#[test]
fn many_alternating_runs_share_one_text_matrix() {
let mut doc = PdfDoc::new();
let p = doc.add_page(612.0, 792.0);
p.text(10.0, 20.0, 10.0, Font::Helvetica, [0, 0, 0], &"a\u{4e2d}".repeat(2000));
let pdf = doc.finish();
let count = |needle: &[u8]| pdf.windows(needle.len()).filter(|w| *w == needle).count();
assert_eq!(count(b" Tm\n"), 1, "the position is set once, before the first run");
assert_eq!(count(b" Tf\n"), 4000, "every run selects its font");
assert_eq!(count(b" Tj\n"), 4000);
}
#[test]
fn symbol_font_draws_maths_in_its_own_encoding() {
let mut doc = PdfDoc::new();