Skip to content

fix(pdfium): resolve installed CJK fonts referenced by PostScript name - #425

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/snipefrom
GongHeng2017:202610211604-re-snipe
Oct 21, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:release/snipefrom
GongHeng2017:202610211604-re-snipe

Conversation

@GongHeng2017

@GongHeng2017 GongHeng2017 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Register each enumerated font in m_FontList before notifying the mapper so that GetFont() succeeds during enumeration and PostScript names get read.

字体枚举时先注册进 m_FontList 再通知 mapper,保证枚举期间 GetFont() 成功, 使已安装字体的 PostScript 名可被读取索引。

Index the PostScript name of every installed font whose PS name differs from its family name, not only localized names, so /BaseFont entries like "FZXBSJW--GB1-0" can resolve to the installed font family.

为所有 PS 名与族名不同的已安装字体建立 PostScript 名索引(不再仅限本地化名),
使 /BaseFont 条目(如 "FZXBSJW--GB1-0")能解析到已安装字族。

Prefer an exact family-name match in MapFont for CJK charsets over the hardcoded fallback lists, which previously ignored the requested family.

MapFont 对 CJK 字符集优先按请求族名精确匹配,而非直接落入硬编码回退列表。

Log: 修复PDF按PostScript字体名无法匹配已安装中文字体的问题
PMS: BUG-380413
Influence: PDF中引用已安装中文字体的PostScript名(如方正小标宋)时能正确
匹配对应字体,不再被无关替代字体替换,中文显示恢复正确。

Summary by Sourcery

Fix installed-font enumeration and matching so PDF PostScript and family font references resolve correctly for CJK text.

Bug Fixes:

  • Resolve installed CJK fonts referenced by PostScript names so PDF text uses the correct font instead of an unrelated fallback.

Enhancements:

  • Prioritize exact installed family-name matches for CJK font mapping over generic fallback lists.

Register each enumerated font in m_FontList before notifying the mapper so
that GetFont() succeeds during enumeration and PostScript names get read.

字体枚举时先注册进 m_FontList 再通知 mapper,保证枚举期间 GetFont() 成功,
使已安装字体的 PostScript 名可被读取索引。

Index the PostScript name of every installed font whose PS name differs
from its family name, not only localized names, so /BaseFont entries like
"FZXBSJW--GB1-0" can resolve to the installed font family.

为所有 PS 名与族名不同的已安装字体建立 PostScript 名索引(不再仅限本地化名),
使 /BaseFont 条目(如 "FZXBSJW--GB1-0")能解析到已安装字族。

Prefer an exact family-name match in MapFont for CJK charsets over the
hardcoded fallback lists, which previously ignored the requested family.

MapFont 对 CJK 字符集优先按请求族名精确匹配,而非直接落入硬编码回退列表。

Log: 修复PDF按PostScript字体名无法匹配已安装中文字体的问题
PMS: BUG-380413
Influence: PDF中引用已安装中文字体的PostScript名(如方正小标宋)时能正确
匹配对应字体,不再被无关替代字体替换,中文显示恢复正确。
@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes installed CJK font resolution when PDFs reference fonts by PostScript name by making fonts available during enumeration, indexing differing PostScript names for all installed fonts, and honoring exact family-name matches before CJK fallback substitution.

Sequence diagram for installed CJK PostScript font indexing

sequenceDiagram
    participant Enumerator as CFX_FolderFontInfo
    participant Mapper as CFX_FontMapper
    participant FontInfo as FontInfo
    participant FontFile as InstalledFont

    Enumerator->>FontInfo: m_FontList[facename] = FontFaceInfo
    Enumerator->>Mapper: AddInstalledFont(facename, charset)
    Mapper->>FontInfo: GetFont(name.c_str())
    FontInfo-->>Mapper: Font handle
    Mapper->>FontFile: GetPSNameFromTT(hFont)
    FontFile-->>Mapper: ps_name
    Mapper->>Mapper: m_LocalizedTTFonts.push_back(ps_name, name)
    Mapper->>FontInfo: DeleteFont(hFont)
Loading

Flow diagram for CJK font matching by family or PostScript name

flowchart TD
    A[PDF requests a CJK font] --> B{PostScript name indexed?}
    B -->|Yes| C[Resolve to installed family]
    B -->|No| D{Exact family in m_FontList?}
    D -->|Yes| C
    D -->|No| E[Use charset fallback list]
    C --> F[Render with requested installed font]
    E --> G[Render with fallback font]
Loading

File-Level Changes

Change Details Files
Registers font metadata before mapper callbacks so PostScript names can be read during font enumeration.
  • Initializes style flags before registration.
  • Stores each FontFaceInfo in m_FontList before calling AddInstalledFont().
  • Updates charset flags through the registered face object.
3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/cfx_folderfontinfo.cpp
Indexes PostScript names for all installed fonts when they differ from the family name.
  • Attempts direct font lookup for every installed font and uses mapping fallback for localized names.
  • Adds normalized PostScript-name-to-family mappings only when names differ.
  • Continues registering successfully enumerated fonts even when PostScript lookup fails for non-localized names.
3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/cfx_fontmapper.cpp
Prioritizes exact installed-family matches for CJK font mapping over static fallback lists.
  • Checks the requested family first for Simplified Chinese, Traditional Chinese, and Hangul charsets.
  • Retains existing charset-specific fallback lists when no exact family is installed.
3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp" line_range="122-123" />
<code_context>
+      // 该名字往往不在下方任何旧回退列表中;若不先做精确匹配,下方列表
+      // 会无条件替换为列表中第一个找到的字体,完全忽略请求的族名。
+      auto exact_it = m_FontList.find(family);
+      if (exact_it != m_FontList.end())
+          return exact_it->second.get();
       for (const char* name : g_LinuxGbFontList) {
         auto it = m_FontList.find(name);
</code_context>
<issue_to_address>
**CJK text loses glyphs**

When a requested CJK family is installed but its face lacks the requested charset, `MapFont()` returns `exact_it` without checking charset support, bypassing the CJK fallback list and rendering the text with a face that lacks the required glyphs.

Return the exact match only when it supports the requested charset; otherwise continue to the CJK fallback list.

Also at `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135`, `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147`.
</issue_to_address>

### Comment 2
<location path="3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp" line_range="121-122" />
<code_context>
+      // 某个已安装 CJK 字体的族名引用它(例如 "FZXiaoBiaoSong-B05S"),
+      // 该名字往往不在下方任何旧回退列表中;若不先做精确匹配,下方列表
+      // 会无条件替换为列表中第一个找到的字体,完全忽略请求的族名。
+      auto exact_it = m_FontList.find(family);
+      if (exact_it != m_FontList.end())
+          return exact_it->second.get();
       for (const char* name : g_LinuxGbFontList) {
</code_context>
<issue_to_address>
**Installed Japanese font is ignored**

When a PDF requests ShiftJIS text in an installed Japanese family that is absent from the hardcoded Japanese fallback lists, `MapFont()` searches `g_LinuxJpFontList` without checking `m_FontList` for the requested family, so it selects a generic fallback instead of the installed font.

Check `m_FontList` for the requested family before searching the Japanese fallback lists.
</issue_to_address>

### Comment 3
<location path="3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp" line_range="121-123" />
<code_context>
+      // 某个已安装 CJK 字体的族名引用它(例如 "FZXiaoBiaoSong-B05S"),
+      // 该名字往往不在下方任何旧回退列表中;若不先做精确匹配,下方列表
+      // 会无条件替换为列表中第一个找到的字体,完全忽略请求的族名。
+      auto exact_it = m_FontList.find(family);
+      if (exact_it != m_FontList.end())
+          return exact_it->second.get();
       for (const char* name : g_LinuxGbFontList) {
         auto it = m_FontList.find(name);
</code_context>
<issue_to_address>
**Requested font style is ignored**

When the family has an exact regular face and the request calls for a different weight or italic style, the exact-family branch returns the regular face without considering `weight` or `bItalic`, even when the requested styled face is installed.

Apply the requested weight and italic style when selecting an exact-family match.

Also at `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135`, `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147`.
</issue_to_address>

### Comment 4
<location path="3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/cfx_fontmapper.cpp" line_range="334-335" />
<code_context>
+  // 原先仅对本地化(含非 ASCII 字符)的族名做该索引,导致 ASCII 族名字体
+  // 的 PostScript 名请求永远无法匹配已安装字体,总会被无关的替代字体替换。
+  void* hFont = m_pFontInfo->GetFont(name.c_str());
+  if (!hFont && bLocalized) {
       hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str());
-      if (!hFont)
-        return;
</code_context>
<issue_to_address>
**PostScript font name is not indexed**

When an external provider cannot resolve an ASCII family through `GetFont()` but can open it through `MapFont()`, `AddInstalledFont()` calls `MapFont()` only when `bLocalized` is true, so it never reads the font’s differing PostScript name and requests using that name fail to resolve to the installed family.

Try `MapFont()` when `GetFont()` returns null for an ASCII family as well.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +122 to +123
if (exact_it != m_FontList.end())
return exact_it->second.get();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High · CJK text loses glyphs

When a requested CJK family is installed but its face lacks the requested charset, MapFont() returns exact_it without checking charset support, bypassing the CJK fallback list and rendering the text with a face that lacks the required glyphs.

Return the exact match only when it supports the requested charset; otherwise continue to the CJK fallback list.

Also at 3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135, 3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147.

Prompt for AI agents
In `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp` at lines 122-123:

**CJK text loses glyphs**

When a requested CJK family is installed but its face lacks the requested charset, `MapFont()` returns `exact_it` without checking charset support, bypassing the CJK fallback list and rendering the text with a face that lacks the required glyphs.

Return the exact match only when it supports the requested charset; otherwise continue to the CJK fallback list.

Also at `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135`, `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147`.

Comment on lines +121 to +122
auto exact_it = m_FontList.find(family);
if (exact_it != m_FontList.end())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Installed Japanese font is ignored

When a PDF requests ShiftJIS text in an installed Japanese family that is absent from the hardcoded Japanese fallback lists, MapFont() searches g_LinuxJpFontList without checking m_FontList for the requested family, so it selects a generic fallback instead of the installed font.

Check m_FontList for the requested family before searching the Japanese fallback lists.

Prompt for AI agents
In `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp` at lines 121-122:

**Installed Japanese font is ignored**

When a PDF requests ShiftJIS text in an installed Japanese family that is absent from the hardcoded Japanese fallback lists, `MapFont()` searches `g_LinuxJpFontList` without checking `m_FontList` for the requested family, so it selects a generic fallback instead of the installed font.

Check `m_FontList` for the requested family before searching the Japanese fallback lists.

Comment on lines +121 to +123
auto exact_it = m_FontList.find(family);
if (exact_it != m_FontList.end())
return exact_it->second.get();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · Requested font style is ignored

When the family has an exact regular face and the request calls for a different weight or italic style, the exact-family branch returns the regular face without considering weight or bItalic, even when the requested styled face is installed.

Apply the requested weight and italic style when selecting an exact-family match.

Also at 3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135, 3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147.

Prompt for AI agents
In `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp` at lines 121-123:

**Requested font style is ignored**

When the family has an exact regular face and the request calls for a different weight or italic style, the exact-family branch returns the regular face without considering `weight` or `bItalic`, even when the requested styled face is installed.

Apply the requested weight and italic style when selecting an exact-family match.

Also at `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:133-135`, `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/fx_ge_linux.cpp:145-147`.

Comment on lines +334 to 335
if (!hFont && bLocalized) {
hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium · PostScript font name is not indexed

When an external provider cannot resolve an ASCII family through GetFont() but can open it through MapFont(), AddInstalledFont() calls MapFont() only when bLocalized is true, so it never reads the font’s differing PostScript name and requests using that name fail to resolve to the installed family.

Try MapFont() when GetFont() returns null for an ASCII family as well.

Prompt for AI agents
In `3rdparty/deepin-pdfium/src/3rdparty/pdfium/pdfium/core/fxge/cfx_fontmapper.cpp` at lines 334-335:

**PostScript font name is not indexed**

When an external provider cannot resolve an ASCII family through `GetFont()` but can open it through `MapFont()`, `AddInstalledFont()` calls `MapFont()` only when `bLocalized` is true, so it never reads the font’s differing PostScript name and requests using that name fail to resolve to the installed family.

Try `MapFont()` when `GetFont()` returns null for an ASCII family as well.

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 98 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交修复了 pdfium 中 CJK 字体按 PostScript 名无法解析的问题,三处改动逻辑正确、注释详尽,未引入安全漏洞。仅存在轻微代码重复(3 个 switch case 中相同的精确匹配模式),整体质量优秀。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无']


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['可考虑将 fx_ge_linux.cpp 中重复的精确匹配逻辑提取为辅助函数或宏,减少未来维护时的修改遗漏风险']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无']


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: ['无']


💡 改进建议代码示例

// fx_ge_linux.cpp: 可将重复的精确匹配提取为辅助方法,减少重复
// 例如在 CFX_LinuxFontInfo 类中添加:
// void* FindExactFont(const ByteString& family) {
//     auto it = m_FontList.find(family);
//     return it != m_FontList.end() ? it->second.get() : nullptr;
// }
// 然后在各 case 中:
// case FX_CHARSET_ChineseSimplified: {
//     if (void* p = FindExactFont(family))
//         return p;
//     for (const char* name : g_LinuxGbFontList) { ... }
//     break;
// }

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: GongHeng2017, max-lvs

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@GongHeng2017

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit ebdc424 into linuxdeepin:release/snipe Oct 21, 2026
9 checks passed
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.

3 participants