fix specific decoding issues
This commit is contained in:
+16
-8
@@ -674,21 +674,29 @@ pub(crate) fn extract_text_from_operand(
|
||||
// This prevents partial CMap results from blocking the Differences path.
|
||||
if entry.primary.code_byte_length == 1 {
|
||||
let encoding_map = font_encodings.get(current_font);
|
||||
let lookups = entry.primary.lookup_bytes(bytes);
|
||||
let decoded: String = lookups
|
||||
let decoded: String = bytes
|
||||
.iter()
|
||||
.filter_map(|&(b, ref cmap_result)| {
|
||||
// 1. CMap mapped it? Use CMap result
|
||||
if let Some(s) = cmap_result {
|
||||
return Some(s.clone());
|
||||
.filter_map(|&b| {
|
||||
let code = b as u16;
|
||||
// 1. Primary CMap
|
||||
if let Some(s) = entry.primary.lookup(code) {
|
||||
if !s.contains('\u{FFFD}') {
|
||||
return Some(s);
|
||||
}
|
||||
}
|
||||
// 2. Differences mapped it? Use Differences result
|
||||
// 2. Fallback CMap (embedded font cmap)
|
||||
if let Some(fb) = entry.fallback.as_ref().and_then(|c| c.lookup(code)) {
|
||||
if !fb.contains('\u{FFFD}') {
|
||||
return Some(fb);
|
||||
}
|
||||
}
|
||||
// 3. Differences mapped it? Use Differences result
|
||||
if let Some(map) = encoding_map {
|
||||
if let Some(&ch) = map.get(&b) {
|
||||
return Some(ch.to_string());
|
||||
}
|
||||
}
|
||||
// 3. Printable ASCII/Latin-1 fallback
|
||||
// 4. Printable ASCII/Latin-1 fallback
|
||||
if b >= 0x20 {
|
||||
return Some((b as char).to_string());
|
||||
}
|
||||
|
||||
+4
-1
@@ -1725,7 +1725,7 @@ pub fn build_glyph_to_unicode_map() -> HashMap<&'static str, char> {
|
||||
m.insert("controlRS", '\x1E');
|
||||
m.insert("controlSI", '');
|
||||
m.insert("controlSO", '');
|
||||
m.insert("controlSOT", '');
|
||||
m.insert("controlSOT", '˜');
|
||||
m.insert("controlSTX", '');
|
||||
m.insert("controlSUB", '');
|
||||
m.insert("controlSYN", '');
|
||||
@@ -4544,6 +4544,9 @@ static GLYPH_TO_UNICODE: LazyLock<HashMap<&'static str, char>> = LazyLock::new(|
|
||||
// Local overrides for non-standard glyph names seen in PDFs.
|
||||
m.insert("C21", '≥');
|
||||
m.insert("C25", '≈');
|
||||
// Some Type1 fonts use custom glyph names for ASCII tilde.
|
||||
m.insert("C19", '~');
|
||||
m.insert("C24", '~');
|
||||
m
|
||||
});
|
||||
|
||||
|
||||
@@ -758,6 +758,22 @@ fn build_simple_cmap_from_truetype(font_data: &[u8]) -> Option<ToUnicodeCMap> {
|
||||
cmap.char_map.insert(gid, ch.to_string());
|
||||
}
|
||||
}
|
||||
// Fill missing single-byte codes from glyph names (helps with ligatures like "t_i").
|
||||
for gid in 0..face.number_of_glyphs() {
|
||||
let gid = ttf_parser::GlyphId(gid);
|
||||
let gid_val = gid.0;
|
||||
if gid_val > 0xFF || cmap.char_map.contains_key(&gid_val) {
|
||||
continue;
|
||||
}
|
||||
if let Some(name) = face.glyph_name(gid) {
|
||||
if gid_val == 0x1B {
|
||||
debug!("simple cmap glyph gid=0x1B name={:?}", name);
|
||||
}
|
||||
if let Some(s) = glyph_name_to_string(name) {
|
||||
cmap.char_map.insert(gid_val, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
if cmap.char_map.is_empty() {
|
||||
return None;
|
||||
}
|
||||
@@ -769,6 +785,35 @@ fn build_simple_cmap_from_truetype(font_data: &[u8]) -> Option<ToUnicodeCMap> {
|
||||
Some(cmap)
|
||||
}
|
||||
|
||||
fn glyph_name_to_string(name: &str) -> Option<String> {
|
||||
let base = name.split('.').next().unwrap_or(name);
|
||||
if let Some(ch) = glyph_to_char(base) {
|
||||
return Some(ch.to_string());
|
||||
}
|
||||
if base.contains('_') {
|
||||
let mut out = String::new();
|
||||
for part in base.split('_') {
|
||||
if part.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if let Some(ch) = glyph_to_char(part) {
|
||||
out.push(ch);
|
||||
} else if part.len() == 1 {
|
||||
out.push(part.chars().next().unwrap());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
if !out.is_empty() {
|
||||
return Some(out);
|
||||
}
|
||||
}
|
||||
if matches!(base, "ti" | "tt" | "tz") {
|
||||
return Some(base.to_string());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Build a ToUnicodeCMap from a font's glyph names (post table).
|
||||
/// Uses Adobe Glyph List to map glyph names to Unicode.
|
||||
fn build_cmap_from_glyph_names(face: &ttf_parser::Face<'_>) -> Option<ToUnicodeCMap> {
|
||||
|
||||
Reference in New Issue
Block a user