2013年4月12日

動態提供網頁字型開發筆記 - fonten

我在做SharePoster的時候遇到一個問題,我想讓使用者可以使用不同的字型在canvas上面寫字,但是中文字型檔太大,直接載入瀏覽器會太久,所以如何動態提供字型給canvas作圖使用呢?

問題可以分成幾個部分:

1. 動態切割字型檔
   
     一個完整中文字型檔大概要5~20mb,假如我們只使用幾個中文字就要下載全部檔案很不划算,所以如果可以讓server提供一個根據需要的文字來提供瘦身過的字型檔,這個字型檔可能只有幾kb,是原來千分之一的大小,專門用來顯示特定的文字所需要的字型。

     實際上已經有一些open source project提供這樣的切割能力,像是FontForge (Python), Sfntly (Java)。



2. 根據所需要的文字要求字型檔
 
     一般比較正常的作法是這樣,第一次送post給server告訴server準備哪些字,換取一個hash token,如果這裡是使用jQuery cross-domain post,發post之前會先發一個options詢問server是否允許哪些method的cross-domain request,確認許可之後才會發post,client根據這個token組成一個url交給css的font-face,server端必須藉由Access-Control-Allow-Origin和Access-Control-Allow-Method兩個header來回應cross-domain的請求。

     這裡需要一些改進,我原本以為字型可以像圖片一樣使用javascript拿到字型的object,或許html5要可以,事實上是無法的,規則的制定者看來沒有這樣的需求,我們只能夠組成url交給css去處理,其實這樣造成了request的浪費,比較好的狀態應該一次request就能夠拿到字型,所以在實作上我加了另一種方法,當需求文字少的時候,在client端組成font url就直接較給css處理,這樣就少了options和post這兩個request,只剩下css會發出的get request,但是換來的限制是url長度大概要在2000以下比較安全(不管舊版IE的話至少也要在4000以下)也就是encode 之前大概200個中文字比較保險。

     然後我們用一個jQuery plugin把這些方法包起來。



3. 使用字型

     還有一個問題,什麼時候可以使用字型了?

     字型載入需要時間,而且我們沒有任何獲得css font request的callback或類似onload事件的方法,如果在字型載入之前使用該字型,我們只會得到瀏覽器備用的字型(fallback font),不過或許我們可以利用這個機制來測試字型是否載入了,無法拿到event就polling吧,當字型載入的時候文字寬度和fallback字型的寬度會不同,就用這樣來測試字型是否載入了。

     這個方法也把它包在jQuery plugin裡面。


綜合以上這是一個我目前正在開發的開源項目fonten,他同時包含一個可上傳字型的server和一組API以及一個比較方便的jQuery plugin。

fonten on Github