前情提要
這次在工作上遇到中文字體無法解碼問題,
實際上的情況是:使用電腦可以讀取中文字體,但是在手機上卻不行的問題。
當時先思考到的是手機由於缺乏特定字型的支援,所以無法解讀,
因此,解決的辦法就是換掉字體。
不過,因為是承接別人寫的 code,在換之前,想先找出實際上被載入的字體是哪一個,
因此花了不少時間在看 mpdf 文件、別人的解法與建議。
稍微 memo 一下當時的脈絡:
由於缺乏特定字型的支援 -> 必須換字體 -> 移除實際上無法解析的字體 ->
透過 Stack Overflow, Perplexity, mpdf docs 等等綜合意見找出最適合這次的解法
關於 niklasravnsborg/laravel-pdf
niklasravnsborg/laravel-pdf 這個 open source 的底層是使用 mPDF,
是一個用於從 HTML 生成 PDF 文件的 PHP library。
mPDF 支持 Unicode、UTF-8 和 CJK(Chinese, Japanese, Korean),
可以在 Laravel 中使用 niklasravnsborg/laravel-pdf 輕鬆生成 PDF。
但,niklasravnsborg/laravel-pdf 已於 2023年8月22日 被標記為不再維護。
因為已經沒有在維護,加上我先以不更換套件的前提下,
試著找出可以使手機用戶也能讀取中文字的解法。
當時在查找時,透過這篇講述漢字 Unicode 範圍 (Han unification)
整理 Unicode 經常會使用到的內碼區域並透過 Regex 自動比對文字
就想到,可以到 mPDF 去找有沒有以 Unicode 對應的字!
因此,對應到 mPDF 本身有一段講到通用的 fonts 有哪些:
Unicode coverage of Free Fonts
就找到 CJK UNIFIED IDEOGRAPHS (U+4E00-U+9FFF) 相對應的字體了!
客製化字體
所以要如何新增想要的字體?
在專案本身的 config 資料夾裡有一個叫做 pdf.php 的檔案,
這檔案就是當要生成 pdf 時,所需要的設定檔。
在查看這套件是如何抓取 pdf.php 的參數時,發現還有 font_path
, font_data
可以額外設定!
font_path
: 要給定絕對路徑,讓套件能抓取裡面的字體檔案font_data
: 會根據提供的字體作為讀取備註:依照以下的設定,我把下載好的 NotoSansTC-Regular.ttf 與 NotoSansTC-Bold.ttf,
事先放入 resource/fonts 裡。(fonts 是我自己新增的資料夾)
仔細看會發現有一個
useOTL
參數:那是什麼??
- 在 mPDF 中,
useOTL
代表 OpenType Layout 功能,
用於進行高級的排版控制,如連字、音標和其他特定字型設置。
將useOTL
設置為 255 or 0xFF 可以啟用特定字型的 OpenType 佈局功能,
實現更複雜的呈現和樣式設定。
1 |
|
最後,整理要設定的餐數:
- 下載自己要的字體,我選用 Google - Noto Sans TC fonts
font_path
有事先在 resource 資料夾裡新增 fonts 資料夾,並把下載好的(.ttf)檔案放到裡面font_data
把下載好的(.ttf)檔案名稱寫進去useOTL
設定為 255 or 0xFF
小記
最終以 custom fonts 解決,
其實也可以直接使用 CJK UNIFIED IDEOGRAPHS 也就是 Unicode 對應的 U+4E00 - U+9FFF。
mPDF 文件上提供的字體有:
bitstreamcyberbit
,hannoma
,sun-exta
,用這三種不需額外加字體。
不過,有鑑於整體網站使用的字體(考量到 UX),
最後還是選用 Google - Noto Sans TC fonts 來作為要更換的字體。
P.S.
之前也有使用 TCPDF
作為生成 pdf 的套件,
有興趣可以參考:Viiisit [PHP] - TCPDF Library in Laravel!
參考資料:
➫ mpdf
➫ Laravel PDF 导出