mf2ff mf2ff是使用Fontforge的Python API從Metafont代碼創建向量字體的工具。
它基於一個概念,即metafont如何與矢量字體生成器一起工作,而無需繞點圖跟踪,如下所示,在MF2VEC概念部分中所述。 mf2ff是迄今為止此概念的唯一實現,也是第一個,也是第一個。
在下面,您將在如何設置以及如何使用它方面找到一些幫助。
該工具尚未經過徹底的測試,但是支持大多數常見的metafont命令。除了填充和繪畫外,還支持Kerning和一些結紮命令。請查看下面列出的限制。
mf2ffmf2ff的當前局限性您需要安裝fontforge和metafont以使用mf2ff 。
您可能會遇到運行mf2ff腳本的問題。一個問題可能是您需要使用Fontforge模塊運行Python 3。以下是有關如何使其工作的一些技巧。我不能保證這對您的系統有效,但是您應該嘗試一下。
在不同的操作系統或系統配置上,下面的提示不起作用,請檢查您是否使用Python和Fontforge的Python模塊:
ffpython , python3 , python )。檢查版本信息是否指出您正在運行Python 3 。import fontforge應無誤。fontforge.font()不應引起錯誤。如果僅在某些目錄中起作用,則應檢查PATH或PYTHONPATH變量。對於臨時訪問Fontforge的Python版本ffpython ,Fontforge帶有批處理文件:
C:Program Files (x86)FontForgeBuilds ),並執行fontforge-console.bat ,因為Windows的set命令命令僅在當前命令提示中更改PATH變量,因此,Ffpython僅在patch文件中執行命令提示中的每個位置可用ffpython。對於永久訪問,您需要永久編輯路徑變量:
environment variables並打開Edit the system environment variables 。單擊Environment variables ,並編輯用戶帳戶的PATH變量,或者如果您需要在多個用戶帳戶上訪問ffpython則該系統。現在,將fontforge的路徑(例如C:Program Files (x86)FontForgeBuildsbin ,請注意bin !)。ffpython ,您應該能夠使用ffpython path/to/mf2ff.py ...要輕鬆訪問到處的mf2ff腳本,請執行以下操作:
mf2ff的路徑添加到PYTHONPATH變量。如果還沒有PYTHONPATH變量,請將其添加到列表中。ffpython -m mf2ff ...在新命令提示會話中運行mf2ff 。在此示例中使用了Ubuntu。
一些存儲庫將Fontforge的舊版本帶有Python 2支持。您可能需要從來源構建Fontforge:
sudo apt install libjpeg-dev libtiff5-dev libpng-dev libfreetype6-dev libgif-dev libgtk-3-dev libxml2-dev libpango1.0-dev libcairo2-dev libspiro-dev libuninameslist-dev python3-dev ninja-build cmake build-essentialsudo apt install gitgit clone https://github.com/fontforge/fontforge 。這將創建一個fontforge/目錄。fontforge/ Directory內部的單獨目錄:cd fontforge; mkdir build; cd buildcmake -GNinja ..ninjasudo ninja install注意:如果您對此過程有問題,請檢查Fontfore的文檔。
要輕鬆訪問Fontforge的Python模塊,請將其添加到您的PythonPath中:
~/.profile文件的末尾: export PYTHONPATH=$PYTHONPATH:/path/to/fontforge/ ,其中/path/to/fontforge/ Directory是通過將fontforge與git cloning fontforge創建的,例如$HOME/fontforge 。python3 path/to/mf2ff.py ...注意:根據系統的配置,您需要鍵入python而不是python3運行Python 3。
要輕鬆地訪問到處的mf2ff腳本,請將其位置添加到PythonPath變量:
~/.profile文件的末尾: export PYTHONPATH=$PYTHONPATH:/path/to/mf2ff/ ,其中/path/to/mf2ff/ Directory是您放置mf2ff.py文件的一個,例如$HOME/mf2ff/mf2ff 。python3 -m mf2ff ...輕鬆運行mf2ff 。注意:取決於您使用的雜物,重新啟動而不是重新啟動可能就足夠了。
下面的解決方案使用自製。這樣,python也可以訪問fontforge:
brew install fontforge 。python3 path/to/mf2ff.py ...注意:根據系統的配置,您需要鍵入python而不是python3運行Python 3。
要輕鬆地訪問到處的mf2ff腳本,請將其位置添加到PYTHONPATH變量:
PYTHONPATH=$PYTHONPATH:/path/to/mf2ff/ 。zsh 。在您的主目錄中,創建或修改文件.zshenv 。bash 。在您的主目錄中,創建或修改文件.bash_profile 。tcsh 。在您的主目錄中,創建或修改tcsh Shell的相應文件。python3 -m mf2ff ...在新的Shell Sessions中運行mf2ff 。 默認情況下, mf2ff將生成一個樣條字體數據庫(.sfd)文件。您可以使用選項-ttf / mf2ff.options['ttf'] = True或-otf / mf2ff.options['otf'] = True直接生成字體。
默認情況下, mf2ff不會進行太多清理,因為您可能想手動刷新字形。您可以使用選項-cull-at-shipout / mf2ff.options['cull-at-shipout'] = True或-remove-artifacts / mf2ff.options['remove-artifacts'] = True以執行一些自動清理。請注意,作為字形定義一部分的cull命令可能會導致cull-at-shipout選項不會對某些字形進行任何進一步的更改。
請查看下面列出的限制。
MF2VEC概念的主要思想是使Metafont將字形的幾何形狀重定向到另一個程序(如果是mf2ff則此程序是Fontforge),而不是使用它們來生成位圖字體。這是可能的,因為Metafont內部使用了相同的幾何描述,該描述隨後在vector Font Files(Bézier曲線)中需要。
一些替代方案將Bézier曲線轉換為柵格圖形,然後回到Bézier曲線。通過直接使用幾何形狀,不會丟失信息。
由於使用metafont而不是其他工具(例如Metapost)來讀取.mf文件,因此可以使用未修改的metafont代碼文件,不僅可以使用幾何形狀,而且還可以使用字符編碼,盒子大小,kerning和結紮信息等。沒有手動rework將其運送到矢量字體。
信息的攔截是通過重新定義metafont命令來完成的。由於Metafont在運行時無法與其他程序進行交互,因此需要將.mf文件的解釋和字體的生成需要及時分開。因此,Metafont將用於生成位圖圖形的信息保存在Metafont的日誌文件中。重新定義了Metafont的命令,以便Metafont在其日誌文件中寫入幾何和字體屬性。一旦Metafont處理了Metafont文件的所有命令,就會從日誌文件中讀取信息,並處理以創建字體然後從日誌文件中刪除以保持清晰。
這種方法的想法在2018年10月提出。要檢查實用性在Python中立即實現了實施,並逐漸擴大了支持命令的範圍。當初始測試表明該想法有效時,決定將mf2ff提供給其他感興趣的用戶。這是自2019年3月以來發生的。經過一些改進和錯誤修復,開發暫停了幾年。由於社區的反饋, mf2ff開發於2023年7月繼續進行。
基本思想
該概念基於重新定義基本的metafont命令。它們的定義方式使信息metafont通常用於創建位圖字體的信息寫入日誌文件中。隨後,將讀取此日誌文件,並將指令傳遞給從其生成向量字體的程序。例如, mf2ff將Fontforge用於此目的。之後,從日誌文件中刪除了修改後的Metafont命令添加的信息,以使其清晰。
下圖用mf2ff作為示例說明了該概念。
┌──────────┐
│ font.mf │
└──────────┘
v
┌──────────┐ ┌───────────┐
│ │ > │ METAFONT │
│ │ └───────────┘
│ │ v
│ │ ┌───────────┐
│ mf2ff │ < │ font.log │
│ │ └───────────┘
│ │
│ │ ┌───────────┐
│ │ > │ FontForge │
└──────────┘ └───────────┘
v v
┌──────────┐ ┌─────────────────────┐
│ font.log │ │ font.ttf / font.otf │
└──────────┘ └─────────────────────┘
簡單示例
將以下代碼添加到metafont文件中會導致metafont不fill輪廓c ,而是將操作寫入日誌文件:
def fill expr c =
message "fill"; show c;
enddef;
METAFONT完成處理該文件後,腳本分析了日誌文件,並知道有一個fill命令,並且知道要填充的輪廓。可以將此信息傳遞到字體處理程序中,以將其添加到字形中。
實際上,這個過程要復雜得多。為了能夠處理不基於普通Metafont的Metafont文件,需要重新定義諸如addto而不是fill之類的命令。但是那些addto命令更為複雜。它們還構成了其他普通的元法命令(如unfill ,( un ) draw ,( un ) drawdot和erase的基礎。這些命令擴展到幾個關鍵字,將執行這些不同操作所需的不同信息的不同部分( addto , also , contour , doublepath ,with pen, withpen , withweight )分開。
另一個挑戰是結腸在條件和循環中。這些結構也可以出現在任何其他命令中,即使在使用結腸作為分離器( ligtable和fontdimen )的命令中也可以出現,因此:必須像其他關鍵字一樣重新定義以將信息輸出到日誌文件。在這些命令中,需要在結腸的不同重新定義之間進行複雜的切換。
除此之外,即使Metafont文件中有消息命令與Metafont Primitives的重新定義無關,也需要實現一個過程,以使其易於找到日誌文件中的所有命令。這些不應被解釋為字體生成的信息。因此,日誌文件中寫入的所有信息都需要包含在特殊關鍵字中,這些關鍵字不太可能在Metafont文件的消息命令中使用。
Metafont自1977年以來由De Knuth開發,是一個程序,該程序從用Metafont語言編寫的文件中生成位圖字體。位圖字體的缺點是它們在放大倍率下變得模糊。 Metafont的開發是為了使打印機的特定分辨率生成單獨的字體。如今,矢量字體是標準的,在放大方面沒有此問題。因此,它們更適合在顯示器上使用。此外,它們可以與每台打印機一起使用,而無需任何限制。
除了此處介紹的mf2ff的MF2VEC方法外,還有以下用於將metafont文件轉換為矢量字體的腳本:
| 姓名 | 方法 |
|---|---|
| metatype1 | Metapost |
| MF2PT1 | Metapost |
| mftrace | 位圖跟踪 |
| Textrace | 位圖跟踪 |
在這種情況下,Metapost意味著程序Metapost用於將Metafont文件的每個字符轉換為向量圖形。之後,將向量圖形組合在一起以獲取向量字體。該方法的缺點是,Metapost只能處理Metafont語言的一部分。
位圖跟踪意味著Metafont首先生成位圖字體。在一個單獨的程序中,每個字形的位圖都被追踪,然後將其放在一起以獲取矢量字體。
每種方法都有特定的缺點。請查看以下比較以獲取更多詳細信息。
在下表中,顯示了可用腳本的比較,以將metafont文件轉換為向量字體。
| 特徵 | metafont | mf2ff | metatype1 | MF2PT1 | mftrace | Textrace |
|---|---|---|---|---|---|---|
| 腳本寫在 | - | Python 3 | 珀爾 | 珀爾 | Python 2 | 珀爾 |
| Metafont文件處理 | metafont | metafont | Metapost | Metapost | metafont | metafont |
| 隨後的處理 | - | fontforge | 尷尬 / t1asm | T1asm | Autotrace或Potrace / T1ASM | Autotrace |
| 輸出格式 | GF / TFM | ✅TTF,OTF,SFD | ? PFB | ? PFB | ✅afm / pfa / pfb / ttf / svg | ? PFB |
| 產出質量 | 點陣圖 | ✅矢量圖 | ✅矢量圖 | ✅矢量圖 | ?跟踪位圖 | ?跟踪位圖 |
| 重新定義非原始劑 /需要非原始劑 | ✅不 | ✅不 | 是的 | 是的 | ✅不 | ✅不 |
| Unicode支持 | 不 | ✅是的 | ❔ | 不 | 不 | 不 |
| 支持筆命令 | ✅是的 | ?有限的 | 不 | ?有限的 | ✅是的 | ✅是的 |
| 支持結紮和kerning命令 | ✅是的 | ?有限的 | ❔ | ❔ | ❔ | 不 |
| 支持可變字體 | 不 | 不,可能將來 | 不 | 不 | ❔ | 不 |
以下是使用mf2ff創建的一些示例。在Fontforge顯示時,顯示出大綱和填充字符。請注意,結果還不是完美的。
計算機現代字體的某些字形尚未正確處理,即Capital S的中間部分和sloped_serif中的小寫字母。

![]() | ![]() | ![]() |
左側的圖像是通過停用cull命令而創建的。
在MetafontBook的第124-126頁上介紹的有程式化的海岸紅木埃爾·帕洛阿爾托(El Palo Alto)。在左版本中,將激活選項cull-at-shipout 。由於後備箱和最高分支共享一個曲線點,因此當前的實現在那裡導致錯誤的結果。
![]() | ![]() | ![]() | ![]() |
該徽標,該徽標在第138頁的MetafontBook。在左版本中,將激活選項cull-at-shipout 。在兩種情況下,填充徽標都是相同的。
![]() | ![]() | ![]() |
mf2ff的當前局限性由於mf2ff仍在開發且未經徹底的測試中,因此有一些局限性。他們可能會在以後的更新中得到解決。
如果特定的限制阻止您的項目退縮,請打開問題,以便將來的更新可以集中在用戶的需求上。
penrazor (請參見danker_bend_symbol示例),fontforge:“中風寬度不能為零”penspeck的使用會引起警告,但在某些情況下,輸出似乎還可以。cull命令的支持是有限的。: ,, :: , kern , skipto以及結紮運算符=: |=: , =:|和|=:|得到支持。操作員中的可ligtable命令忽略> 。此外,操作員||:不支持。charlist和extensible命令。picture關鍵字,以將圖片變量初始化為Fontforge矢量層。由於Metafont使用布爾表達式中的變量聲明和類型測試的類型關鍵字,因此picture關鍵字不能用於測試變量是否為類型picture 。makepen和makepath類的命令無效。筆和路徑不能使用布爾表達中的pen或path區分。有一個選項is_type引入is_pen或is_path ,這可能有助於您解決此問題。ligtable和fontdimenmf2ff需要重新定義結腸( : 。 if ...( elseif )...( end )... fi和 /或for / forsuffixes / forever ... endfor在使用自己的語法中使用結腸的命令內部,即ligtable fontdimen這可能會引起多個嵌套的問題。charlist且extensible有幾件事可能會有所幫助。請記住,我100%不了解它們:
/usr/local/lib/python3/dist-packages到您的$PYTHONPATHexport PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3/dist-packages到您的~/.profile )/usr/local/lib/python3.4/site-packages到Python的路徑