Share Notes

chundev

View the Project on GitHub latteouka/share-notes

macOS LibreOffice Headless 模式中文字型不渲染的解法

日期:2026-03-25 環境:macOS + LibreOffice (Homebrew) + soffice –headless


TL;DR

soffice --headless --convert-to pdf 把含中文字型(如標楷體)的 .docx 轉成 PDF 時,macOS 上字型會 fallback 成預設字體。原因是 macOS 版 LibreOffice 用 CoreText 而非 fontconfig,CoreText 只認英文字型名稱(如 DFKai-SB),但 .docx 裡指定的是中文名稱(如 標楷體)。解法是在 registrymodifications.xcu 設定字型替換規則。


背景

在自動化文件生成流程中,常需要用 LibreOffice headless 模式將 .docx 轉成 .pdf,作為 CI/CD 產出或自動驗證迴路的一環。當文件使用中文字型時,Linux 上通常只要安裝字型檔 + fc-cache -fv 就能解決,但 macOS 上同樣的做法無效。


問題

轉出的 PDF 中文字型不正確,明顯不是指定的標楷體,而是 fallback 到了宋體或其他預設字型。

確認字型已安裝且 fontconfig 看得到:

fc-list | grep "標楷"
# /Users/xxx/Library/Fonts/Kaiu.ttf: DFKai\-SB,標楷體:style=Regular

但 LibreOffice 轉出來的 PDF 就是不用這個字型。


除錯過程

嘗試 做法 結果 原因
❌ 1 Symlink 字型到 LibreOffice fonts 目錄 無效 macOS LibreOffice 不從該目錄讀取字型
❌ 2 複製到 ~/.local/share/fonts/ + fc-cache -fv fontconfig 看到了,但 PDF 沒變 macOS LibreOffice 不走 fontconfig
❌ 3 清除 LibreOffice cache 無效 問題不在快取
✅ 4 registrymodifications.xcu 設定字型替換 成功 正確的解法

根本原因:macOS vs Linux 的字型處理架構不同

Linux

LibreOffice 使用 fontconfig 處理字型解析和 fallback。fontconfig 能理解中文字型名稱別名(標楷體DFKai-SB),所以只要字型安裝到系統 + fc-cache -fv,就能正常運作。

macOS

LibreOffice 使用 CoreText(macOS 原生字型 API),透過 vcl/quartz/ 後端。CoreText 的字型名稱解析邏輯不同於 fontconfig:

這就是為什麼 fc-list 能看到字型,但 LibreOffice 就是不用。fontconfig 和 CoreText 是兩套完全獨立的系統。


解法:registrymodifications.xcu 字型替換

設定檔位置

~/Library/Application Support/LibreOffice/4/user/registrymodifications.xcu

需要加入的 XML

</oor:items> 結尾標籤前加入兩段:

1. 啟用字型替換功能(預設關閉):

<item oor:path="/org.openoffice.Office.Common/Font/Substitution">
  <prop oor:name="Replacement" oor:op="fuse"><value>true</value></prop>
</item>

2. 定義替換規則:

<item oor:path="/org.openoffice.Office.Common/Font/Substitution/FontPairs">
  <node oor:name="標楷體" oor:op="replace">
    <prop oor:name="Always" oor:op="fuse"><value>true</value></prop>
    <prop oor:name="OnScreenOnly" oor:op="fuse"><value>false</value></prop>
    <prop oor:name="ReplaceFont" oor:op="fuse"><value>標楷體</value></prop>
    <prop oor:name="SubstituteFont" oor:op="fuse"><value>DFKai-SB</value></prop>
  </node>
</item>

也可透過 GUI 設定

  1. 打開 LibreOffice → ToolsOptionsLibreOfficeFonts
  2. 勾選 Apply replacement table
  3. Font 欄填 標楷體,Replace with 欄填 DFKai-SB
  4. 勾選 Always,確認 Screen only 沒有勾選(否則 PDF 輸出不會替換)
  5. 按綠色勾勾新增 → OK

重新轉換

# 確保 LibreOffice 完全關閉
killall soffice.bin 2>/dev/null
sleep 1

# 重新轉換
soffice --headless --convert-to pdf --outdir /tmp document.docx

其他常見中文字型的替換對照

如果文件用了其他中文字型也有同樣問題,可以加入更多替換規則:

中文名稱(docx 內) 英文名稱(macOS CoreText)
標楷體 DFKai-SB
新細明體 PMingLiU
細明體 MingLiU
微軟正黑體 Microsoft JhengHei
微軟雅黑 Microsoft YaHei

前提是對應的 .ttf / .ttc 字型檔已安裝在系統中。


⚠️ Caveat:LibreOffice PDF ≠ Word 渲染

即使字型問題解決了,LibreOffice 轉出的 PDF 和 Word 開啟的 .docx 仍然會有佈局差異

LibreOffice headless 轉 PDF 適合作為快速預覽和自動化驗證迴路(確認大方向的排版沒問題),但最終交付仍應以 Word 開啟的 .docx 為準


學到的事


參考資料