fix(fonts): revert TrueType cmap override for fonts with explicit encoding

The third-pass change to extract embedded cmaps for TrueType fonts with
WinAnsiEncoding caused apostrophes and other characters to be dropped
in subsetted fonts where the cmap doesn't cover all glyphs. The declared
encoding is authoritative for these fonts. The OCR text extraction fix
(invisible Tr=3 text) doesn't need this cmap override.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Abimael Martell
2026-03-18 12:07:21 -07:00
co-authored by Claude Opus 4.6
parent 258210a821
commit 80f9bb7ab2
+7 -12
View File
@@ -1920,6 +1920,13 @@ impl FontCMaps {
if font_dict.get(b"ToUnicode").is_ok() {
continue;
}
// Skip fonts with explicit encoding — they can be decoded by the
// standard encoding path (lopdf) and don't need a fallback CMap.
if let Ok(enc) = font_dict.get(b"Encoding") {
if enc.as_name().is_ok() || enc.as_dict().is_ok() || enc.as_reference().is_ok() {
continue;
}
}
let subtype = match font_dict
.get(b"Subtype")
.ok()
@@ -1931,18 +1938,6 @@ impl FontCMaps {
if subtype == b"Type0" {
continue;
}
// Skip non-TrueType fonts with explicit encoding — they can be
// decoded by the standard encoding path and don't need a fallback.
// TrueType fonts are NOT skipped: OCR-generated PDFs often declare
// WinAnsiEncoding but the embedded font's cmap has the real mapping.
if subtype != b"TrueType" {
if let Ok(enc) = font_dict.get(b"Encoding") {
if enc.as_name().is_ok() || enc.as_dict().is_ok() || enc.as_reference().is_ok()
{
continue;
}
}
}
let font_descriptor = font_dict.get(b"FontDescriptor").ok().and_then(|o| match o {
Object::Reference(r) => doc.get_dictionary(*r).ok(),