M7: keep embedded CMap ranges compact instead of truncating expansion (#837)

* M7: keep embedded CMap ranges compact instead of truncating expansion

A ToUnicode CMap's sequential bfrange used to expand into one HashMap
entry per code, and the parser stopped at 2^20 expanded codes. A valid
CMap with more codes than that lost every mapping past the cap.

Each sequential range is now one record. Codes below 65 536 find their
covering record in a table, higher codes by binary search over a cover
index; the later declaration wins where ranges and explicit entries
overlap. Explicit entries keep their strings. The budget counts an
explicit entry as one and a range as two, since a range covers at least
two codes, so every CMap with at most 2^20 codes is kept whole. encode
finds the lowest code per character from the same records.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

* ToUnicode: size the low-code tables to the codes a font covers

---------

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
cyfung1031
2026-10-10 17:14:24 -04:00
committed by GitHub
co-authored by Claude Haiku 5.5 Brandon Thomas
parent 8196d6f45a
commit 910b70bb5f
2 changed files with 562 additions and 48 deletions
+1 -1
View File
@@ -405,7 +405,7 @@ fn interpret(
Object::String(s) => {
for (code, len) in m.codes(&s.bytes) {
match m.text_of(code) {
Some(t) => text.push_str(t),
Some(t) => text.push_str(&t),
None => decodable = false,
}
let w = m.width(code) * ts.size + ts.char_spacing + if m.is_space(code, len) { ts.word_spacing } else { 0.0 };