mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-09 22:24:06 +00:00
fix(print,engine): read the page tree once when finding which pages' text reads up
This commit is contained in:
@@ -171,7 +171,13 @@ impl Session {
|
||||
Err(_) => return Vec::new(),
|
||||
},
|
||||
};
|
||||
(0..doc.info.pages.len()).map(|i| pages.contains(&i) && pdfcraft_print::text_reads_up(&cos, i)).collect()
|
||||
// The page tree is read once, and each page is looked up, not searched for, in `pages`.
|
||||
let mut out = vec![false; doc.info.pages.len()];
|
||||
let wanted: Vec<usize> = pages.iter().copied().filter(|&p| p < out.len()).collect::<std::collections::BTreeSet<_>>().into_iter().collect();
|
||||
for (p, up) in wanted.iter().zip(pdfcraft_print::texts_read_up(&cos, &wanted)) {
|
||||
out[*p] = up;
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Combine whole files, in order, into new PDF bytes (one bookmark per file).
|
||||
|
||||
@@ -42,4 +42,4 @@ pub use settings::{
|
||||
};
|
||||
#[cfg(test)]
|
||||
use sheets::text_direction;
|
||||
pub use sheets::{LABEL_MARGIN, MARGIN, Placement, Sheet, layout, matching_paper, text_reads_up};
|
||||
pub use sheets::{LABEL_MARGIN, MARGIN, Placement, Sheet, layout, matching_paper, text_reads_up, texts_read_up};
|
||||
|
||||
@@ -7,7 +7,17 @@ use super::{DecodeBudget, Dict, Document, Matrix, Object};
|
||||
/// sideways on a letter or A4 sheet), counting each text-showing operator once; form XObjects
|
||||
/// are followed a few levels deep.
|
||||
pub fn text_reads_up(doc: &Document, index: usize) -> bool {
|
||||
let Some(page) = pdfcraft_model::pages(doc).into_iter().nth(index) else { return false };
|
||||
texts_read_up(doc, &[index]).first().copied().unwrap_or(false)
|
||||
}
|
||||
|
||||
/// [`text_reads_up`] for each of `indices`, reading the page tree once: once per page, the
|
||||
/// whole tree would be walked for every page asked about.
|
||||
pub fn texts_read_up(doc: &Document, indices: &[usize]) -> Vec<bool> {
|
||||
let pages = pdfcraft_model::pages(doc);
|
||||
indices.iter().map(|&i| pages.get(i).is_some_and(|page| page_reads_up(doc, page))).collect()
|
||||
}
|
||||
|
||||
fn page_reads_up(doc: &Document, page: &pdfcraft_model::Page) -> bool {
|
||||
let to_display = Matrix(page.view_matrix(doc)).invert().unwrap_or_default();
|
||||
let res = page.dict.get(b"Resources").and_then(|r| doc.resolve(r).as_dict().cloned()).unwrap_or_default();
|
||||
let mut score = 0i64;
|
||||
|
||||
@@ -1245,3 +1245,17 @@ fn contents_pieces_join_with_a_space_across_a_trailing_comment() {
|
||||
let printed_ctrl = impose(&with_newline, &settings(vec![0], Layout::Size(SizeMode::Actual))).unwrap();
|
||||
assert_eq!(form_strings(printed_ctrl), [b"HIDDEN".to_vec(), b"SHOWN".to_vec()]);
|
||||
}
|
||||
|
||||
/// Many pages asked about at once are answered from one walk of the page tree, each as
|
||||
/// [`text_reads_up`] answers it alone; a page past the end is `false`.
|
||||
#[test]
|
||||
fn texts_read_up_answers_many_pages_from_one_walk() {
|
||||
let doc = fixture(3_000);
|
||||
let all: Vec<usize> = (0..3_001).collect();
|
||||
let started = std::time::Instant::now();
|
||||
let up = texts_read_up(&doc, &all);
|
||||
assert!(started.elapsed() < std::time::Duration::from_secs(20), "{:?}", started.elapsed());
|
||||
assert_eq!(up.len(), all.len());
|
||||
assert!(up.iter().all(|u| !u), "upright text, and no page 3000");
|
||||
assert_eq!(up[1], text_reads_up(&doc, 1));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user