簡體   English   中英

如何使用 Python 在 1200ths 英寸中獲取 truetype 字體字符的寬度?

[英]How to get width of a truetype font character in 1200ths of an inch with Python?

我可以使用 PIL 以像素為單位獲得字符的高度和寬度(見下文),但是(除非我弄錯了)像素大小取決於屏幕的 DPI,這可能會有所不同。 相反,我想做的是以絕對單位(如英寸或 1200 分之一英寸(“wordperfect 單位”))計算字符的寬度。

>>> # Getting pixels width with PIL
>>> font = ImageFont.truetype('/blah/Fonts/times.ttf' , 12)
>>> font.getsize('a')
(5, 14)

我想要這樣做的原因是創建一個用於編寫二進制 Word Perfect 文檔的自動換行功能。 Word Perfect 要求在整個文本的有效點處插入軟換行符,否則文件將損壞且無法打開。 問題是在哪里為可變寬度字體添加它們。

我意識到我並不完全理解像素與屏幕分辨率和字體大小之間的關系。 我在這一切都錯了嗎?

原始文本的寬度通常在計算排版的點,但由於為字體定義的目的點定義為1/72英寸,您可以輕松地將其轉換成其他任何單位。

要獲得字符的設計寬度(以em單位表示),您需要訪問字體的低級數據。 最簡單的方法是pip install fonttools ,它可以在字體定義的最低級別工作。

安裝 fontTools 后,您可以:

  1. 加載字體數據——這需要實際字體文件的路徑;

  2. 字符寬度存儲為字形寬度,這意味着您必須檢索“字符到字形”映射; 這是在字體的cmap表中:

    一種。 為您的字體加載cmap 最有用的是 Unicode 映射——一種字體可能包含其他字體。 加載為您的字體設置的字形。 這是該字體中字形的名稱列表。

  3. 然后,對於每個 Unicode 字符,首先查找其名稱,然后使用該名稱以設計單位檢索其寬度。

  4. 不要忘記“設計單位”基於字體的整體“設計寬度”。 這可以是標准值1000 (Type 1 字體的典型值)、 2048 (TrueType 字體的典型值)或任何其他值。

這導致了這個功能:

from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable

font = TTFont('/Library/Fonts/Arial.ttf')
cmap = font['cmap']
t = cmap.getcmap(3,1).cmap
s = font.getGlyphSet()
units_per_em = font['head'].unitsPerEm

def getTextWidth(text,pointSize):
    total = 0
    for c in text:
        if ord(c) in t and t[ord(c)] in s:
            total += s[t[ord(c)]].width
        else:
            total += s['.notdef'].width
    total = total*float(pointSize)/units_per_em;
    return total

text = 'This is a test'

width = getTextWidth(text,12)

print ('Text: "%s"' % text)
print ('Width in points: %f' % width)
print ('Width in inches: %f' % (width/72))
print ('Width in cm: %f' % (width*2.54/72))
print ('Width in WP Units: %f' % (width*1200/72))

結果是:

Text: "This is a test"
Width in points: 67.353516
Width in inches: 0.935465
Width in cm: 2.376082
Width in WP Units: 1122.558594

並且與 Adob​​e InDesign 報告的內容進行比較時是正確的。 (請注意,這里不應用每個字符的字距調整!那將需要更多的代碼。)

字體中未定義的字符會被默默忽略,並且通常會使用.notdef字形的寬度。 如果您希望將此報告為錯誤,請刪除函數中的if測試。

函數getTextWidth中的float getTextWidth因此適用於 Python 2.7 和 3.5,但請注意,如果您使用 Python 2.7 和更大值的 Unicode 字符(非純 ASCII),則需要重寫該函數以正確使用 UTF8 字符。

這對我來說效果更好:

def pixel_width(unicode_text): 
    width=len(unicode_text)*50 
    height=100 
    back_ground_color=(0,0,0) 
    font_size=64 
    font_color=(255,255,255) 

    im  =  Image.new ( "RGB", (width,height), back_ground_color ) 
    draw  =  ImageDraw.Draw (im) 
    unicode_font = ImageFont.truetype("./usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", font_size) 
    draw.text ( (0,0), unicode_text, font=unicode_font, fill=font_color ) 
    im.save("/dev/shm/text.png") 
    box = Image.open("/dev/shm/text.png").getbbox() 
    return box[2] - box[0] 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM