From 95b45d154e7f84a701bd908aa6362dbfe713decb Mon Sep 17 00:00:00 2001 From: Abimael Martell Date: Fri, 20 Mar 2026 19:42:11 -0700 Subject: [PATCH] fix(fonts): fall back to raw stream for uncompressed ToUnicode CMaps lopdf's decompressed_content() fails with DictKey("Filter") when a ToUnicode stream has no /Filter entry (uncompressed raw text). Now falls back to the raw stream.content when decompression fails. Fixes Identity-H fonts with valid uncompressed ToUnicode CMaps producing empty text (e.g. neoenergia tabela PDF). --- src/extractor/content_stream.rs | 13 +++++++------ src/extractor/xobjects.rs | 13 +++++++------ src/tounicode.rs | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/extractor/content_stream.rs b/src/extractor/content_stream.rs index ef7fe61..c1952b7 100644 --- a/src/extractor/content_stream.rs +++ b/src/extractor/content_stream.rs @@ -75,12 +75,13 @@ pub(crate) fn extract_page_text_items( if let Ok(obj_ref) = tounicode.as_reference() { font_tounicode_refs.insert(resource_name, obj_ref.0); } else if let Object::Stream(s) = tounicode { - if let Ok(data) = s.decompressed_content() { - if let Some(entry) = - crate::tounicode::build_cmap_entry_from_stream(&data, font_dict, doc, 0) - { - inline_cmaps.insert(resource_name, entry); - } + let data = s + .decompressed_content() + .unwrap_or_else(|_| s.content.clone()); + if let Some(entry) = + crate::tounicode::build_cmap_entry_from_stream(&data, font_dict, doc, 0) + { + inline_cmaps.insert(resource_name, entry); } } } diff --git a/src/extractor/xobjects.rs b/src/extractor/xobjects.rs index 5491bb8..f780783 100644 --- a/src/extractor/xobjects.rs +++ b/src/extractor/xobjects.rs @@ -179,12 +179,13 @@ fn extract_form_xobject_text_inner( if let Ok(obj_ref) = tounicode.as_reference() { font_tounicode_refs.insert(resource_name, obj_ref.0); } else if let Object::Stream(s) = tounicode { - if let Ok(data) = s.decompressed_content() { - if let Some(entry) = - crate::tounicode::build_cmap_entry_from_stream(&data, font_dict, doc, 0) - { - inline_cmaps.insert(resource_name, entry); - } + let data = s + .decompressed_content() + .unwrap_or_else(|_| s.content.clone()); + if let Some(entry) = + crate::tounicode::build_cmap_entry_from_stream(&data, font_dict, doc, 0) + { + inline_cmaps.insert(resource_name, entry); } } } diff --git a/src/tounicode.rs b/src/tounicode.rs index 2c25668..2a757ab 100644 --- a/src/tounicode.rs +++ b/src/tounicode.rs @@ -1734,7 +1734,7 @@ impl FontCMaps { }; let data = match stream.decompressed_content() { Ok(d) => d, - Err(_) => continue, + Err(_) => stream.content.clone(), }; if let Some(cmap) = ToUnicodeCMap::parse(&data) { debug!(