M2: the two Identity-H ToUnicode rules point at each other

Review follow-up on #3497: the editing map in crates/fonts and the vendored
renderer each read an identity /ToUnicode name as code = Unicode without
controls or lone surrogates; each now names the other, so a change to one
is made to both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LymhVaGZCWwB9HNEbLzeMM
This commit is contained in:
Claude
2026-10-19 18:07:05 +00:00
parent 7f9d86c915
commit b88c8d79ab
2 changed files with 5 additions and 2 deletions
+3 -1
View File
@@ -1216,7 +1216,9 @@ fn unicode_map(doc: &Document, font: &Dict, composite: bool) -> Unicode {
// `/ToUnicode /Identity-H` is not a stream, as ISO 32000-2 §9.10.3 requires, but CAD
// exporters (WSCAD among them) write it for composite fonts whose two-byte codes are the
// UTF-16 code units. Acrobat shows them as code = Unicode, and so does the renderer's
// text layer; without it the text could be seen but not edited or found.
// text layer; without it the text could be seen but not edited or found. The same rule
// (code = Unicode, no controls or lone surrogates) is in the vendored renderer,
// `Type0Font::char_code_to_unicode` in vendor/hayro-interpret/src/font/cid.rs: keep both alike.
Some(Object::Name(n)) if composite && matches!(n.as_slice(), b"Identity-H" | b"Identity-V") => {
parse_to_unicode(&identity_to_unicode(), &mut out);
}
+2 -1
View File
@@ -445,7 +445,8 @@ impl Type0Font {
/// identity `/ToUnicode` name, when the code is a control or a lone surrogate).
pub(crate) fn char_code_to_unicode(&self, code: u32) -> Option<BfString> {
if self.identity_to_unicode {
// Controls and lone surrogates are not text.
// Controls and lone surrogates are not text. The same rule builds the editing
// map, `identity_to_unicode` in crates/fonts/src/pdf.rs: keep both alike.
return char::from_u32(code)
.filter(|c| !c.is_control())
.map(BfString::Char);