diff --git a/crates/edit/src/rules.rs b/crates/edit/src/rules.rs index a5a77903a0..52600ab4dd 100644 --- a/crates/edit/src/rules.rs +++ b/crates/edit/src/rules.rs @@ -1,7 +1,7 @@ //! A page's ruled lines: the horizontal and vertical strokes (and thin filled bars) its content //! draws, so exports can tell a ruled table from text that merely lines up (#5149). -use pdfcraft_content::{Matrix, Pieces}; +use pdfcraft_content::Matrix; use pdfcraft_cos::Document; use crate::EditError; @@ -26,7 +26,7 @@ pub fn page_rules(doc: &Document, page: usize) -> Result, EditErro let pages = pdfcraft_model::pages(doc); let p = pages.get(page).ok_or(EditError::NoSuchPage(page))?; let streams = crate::text::content_streams(doc, &p.dict)?; - let pieces = Pieces::join(&streams.iter().map(|(_, d)| d.as_slice()).collect::>()); + let pieces = crate::text::joined(&streams); let ops = pieces.parse().ops; let mut out: Vec<[f64; 4]> = Vec::new(); diff --git a/crates/edit/src/tests.rs b/crates/edit/src/tests.rs index 7c8f65dbab..a5962366ed 100644 --- a/crates/edit/src/tests.rs +++ b/crates/edit/src/tests.rs @@ -9501,6 +9501,20 @@ fn page_with(build: impl FnOnce(&mut Document) -> (Object, Dict)) -> Document { doc } +#[test] +fn page_rules_join_decoded_streams_before_parsing_operators() { + let doc = page_with(|doc| { + let first = doc.add(Stream::flate(Dict::new(), b"q 2 0 0 2 0 0 cm 10 20 m 30")); + let second = doc.add(Stream::flate(Dict::new(), b"20 l S Q 40 50 1 30 re f")); + (Object::Array(vec![Object::Ref(first), Object::Null, Object::Ref(second)]), Dict::new()) + }); + assert_eq!(page_rules(&doc, 0).unwrap(), vec![[20.0, 40.0, 60.0, 40.0], [40.0, 50.0, 41.0, 80.0]]); + assert_eq!(page_rules(&doc, 1), Err(EditError::NoSuchPage(1))); + + let empty = page_with(|_| (Object::Array(Vec::new()), Dict::new())); + assert!(page_rules(&empty, 0).unwrap().is_empty()); +} + #[test] fn repeated_content_references_share_one_decode_budget() { // One 1 MiB stream (a kilobyte on disk) named 300 times by the page's /Contents.