Skip to content

fix: keep composite glyph CIDs aligned with subset GIDs / 修复复合字形子集中的 CID/GID 错位 - #74

Open
activeliang wants to merge 1 commit into
lmn1919:mainfrom
activeliang:liang
Open

fix: keep composite glyph CIDs aligned with subset GIDs / 修复复合字形子集中的 CID/GID 错位#74
activeliang wants to merge 1 commit into
lmn1919:mainfrom
activeliang:liang

Conversation

@activeliang

Copy link
Copy Markdown

Summary / 概要

  • Build subset CID maps from the exact transitive glyph closure used by the TTF subsetter.
  • 使用 TTF 子集器生成的完整复合字形传递闭包构建 CID 映射。
  • Keep /CIDToGIDMap /Identity content CIDs aligned with the final embedded font GIDs.
  • 确保内容流 CID 与最终嵌入字体的 GID 完全一致。
  • Regenerate the embedded WASM bundle and add Rust and end-to-end regression tests.
  • 重新生成内嵌 WASM,并增加 Rust 单元测试和端到端回归测试。

Problem / 问题

When a rendered glyph is composite, the TTF subsetter also inserts its component
glyphs into the embedded font. However, prepare_subset_maps() previously built
the old-to-new GID map from directly shaped glyphs only.

当渲染的字形是复合字形时,TTF 子集器还会将其组件字形插入嵌入字体。
但此前 prepare_subset_maps() 只根据直接参与排版的字形构建新旧 GID 映射。

Because the generated PDF uses /CIDToGIDMap /Identity, the inserted component
glyphs shifted the final subset GIDs while the content stream continued using
the old mapping. The PDF therefore displayed incorrect glyph outlines even
though its ToUnicode mapping and copied text were correct.

由于生成的 PDF 使用 /CIDToGIDMap /Identity,组件字形的插入会改变后续字形
在最终子集中的 GID,但内容流仍使用旧映射。因此 PDF 显示了错误的字形轮廓,
而 ToUnicode 映射和复制出来的文本仍然正确。

One downstream reproduction extracted ˈsɪtɪŋ correctly but visually rendered
it as ʌsɛtɛð.

一个实际案例中,复制或提取出的文本是正确的 ˈsɪtɪŋ,但 PDF 中显示成了
错误的 ʌsɛtɛð

Solution / 解决方案

Expose the subsetter's transitive composite-glyph closure and use that exact
ordered glyph list when preparing the PDF CID map. The CID map and final subset
font now assign identical GIDs, including all component-glyph slots.

复用子集器计算出的复合字形传递闭包,并使用完全相同的有序字形列表生成 PDF
CID 映射。现在 CID 映射与最终字体子集会为所有字形分配相同的 GID,其中也
包括复合字形所依赖的组件字形。

Testing / 测试

  • cargo test - 5 tests passed / 5 个测试全部通过
  • node scripts/verify.mjs - all verification groups passed / 全部验证通过
  • Rollup package build / Rollup 包构建
  • TypeScript declaration build / TypeScript 声明构建
  • npm pack --dry-run
  • Confirmed the regression test fails with the previous WASM / 确认旧 WASM 无法通过新增回归测试
  • Confirmed CommonJS and ESM bundles contain the rebuilt WASM / 确认两种构建均包含新 WASM

Notes / 说明

  • No public API changes. / 不涉及公共 API 变更。
  • Text remains vector-based, selectable, searchable, and copyable. / 文字仍为矢量,可选择、搜索和复制。
  • No bitmap fallback or font replacement is required. / 不需要使用位图回退或替换字体。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant