Laravel: niklasravnsborg/laravel-pdf with mPDF 套用客製化的字型
前情提要 這次在工作上遇到中文字體無法解碼問題, 實際上的情況是:使用電腦可以讀取中文字體,但是在手機上卻不行的問題。 當時先思考到的是手機由於缺乏特定字型的支援,所以無法解讀, 因此,解決的辦法就是換掉字體。 不過,因為是承接別人寫的 code,在換之前,想先找出實際上被載入的字體是哪一個, 因此...
前情提要
這次在工作上遇到中文字體無法解碼問題, 實際上的情況是:使用電腦可以讀取中文字體,但是在手機上卻不行的問題。
當時先思考到的是手機由於缺乏特定字型的支援,所以無法解讀, 因此,解決的辦法就是換掉字體。
不過,因為是承接別人寫的 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 佈局功能, 實現更複雜的呈現和樣式設定。
<?php
return [
// 新增以下兩種參數:
'font_path' => resource_path('fonts/'),
'font_data' => [
'notosanstc' => [
'R' => 'NotoSansTC-Regular.ttf',
'B' => 'NotoSansTC-Bold.ttf',
'useOTL' => 255,
],
]
];
最後,整理要設定的餐數:
- 下載自己要的字體,我選用 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!