如何确定字体是符号字体还是文本字体



我正在构建一个 kivy 应用程序,需要包含一个字体选择器。由于我找不到一个kivy,所以我正在建造自己的。但是我找不到一种方法来判断字体是否适合我(即,我可以用它来制作句子而不是一串符号)。我正在使用枕头图像字体。有没有办法区分 python 中的符号和文本字体?

一直在努力,我现在对我的工作更满意了。仍然不完美,但以下代码只给了我一个支持 Ubuntu 框文本的字体的误报:

def isValidFont(f, fontNum=0, debug=False):
"""
Determine if a font is a valid font for displaying text
This code makes a best guess as to whether the font supports text.
It does this by writing a 'W' using the font, and inspecting the result.
:param f: full path to the font file
:param fontNum: index into the font file (for a file containing a collection of fonts)
:param debug: If True, files will be written for each font with information useful for debugging
:return: True if font appears to support text, False otherwise
"""
# size of test image
width = 40
height = 40
font = ImageFont.truetype(f, index=fontNum, size=height-6)
fontName = font.getname()
tmpImg = Image.new('1', (width,height)) #default fill is 0 (black)
# draw a single 'W' into the test image (sized and positioned to fit inside test image)
# this codes depends on the character drawn being a 'W'
dr = ImageDraw.Draw(tmpImg)
dr.text((3, 3), 'W', font=font, fill=(1))
if debug:
# save test image for this font
fname = str(fontName) + '.bmp'
tmpImg.save(fname)
# get the data from the image as a list of 1's and 0's (one value per pixel)
img_data = list(tmpImg.getdata())
if debug:
# write the image data to a file
fname = str(fontName) + '.txt'
fd = open(fname, mode='w')
for row in range(height):
fd.write(str(img_data[row*width : (row+1)*width]) + 'n')
fd.close()
# if the image is all black (0's), this is not a valid text font
if sum(img_data) == 0:
return False
# build a simplified version of the image data
compressedList = []
for i in range(height):
prev_elem = None
thisRow = []
for j in range(width):
index = i*width + j
elem = img_data[index] # this is the element at (i,j)
if prev_elem is None:
# first element in this row, just append to "thisRow"
thisRow.append(elem)
prev_elem = elem
elif elem == prev_elem:
# if this element is same as previous (and it's a one), just increment the value in "thisRow"
if elem == 1:
thisRow[len(thisRow)-1] += 1
else:
# just append the element to "thisRow"
thisRow.append(elem)
prev_elem = elem
# finished row #i, append it to "compressedList"
compressedList.append(thisRow)
# a bit more compressing
for row in compressedList:
# eliminate leading zeros from each row
while len(row) > 0 and row[0] == 0:
del row[0]
# eliminate trailing zeros from each row
while len(row) > 0:
index = len(row)-1
if row[index] == 0:
del row[index]
else:
break
# eliminate leading empty rows
while len(compressedList[0]) == 0:
del compressedList[0]
# eliminate trailing empty rows
index = len(compressedList)-1
while len(compressedList[index]) == 0:
del compressedList[index]
index = len(compressedList)-1
if debug:
# save the compressed format
fname = str(fontName) + '_c.txt'
fd = open(fname, mode='w')
for row in compressedList:
fd.write(str(row) + 'n')
fd.close()
# this is where the decision is actually made
for row in compressedList:
if len(row) > 3: # characteristic of a 'W', a simple box will have maximum rowLen of 3
return True
return False

我不是这方面的专家,但这是我如何看待事物的。

当你尝试用字体写一些字母时,渲染器将使用这个字母的代码点从字体文件中获取绘制指令。 3种可能的情况:

  1. 代码点指令存在,但包含错误的图像。为 示例,对于代码点0x0041而不是包含指令 绘制拉丁大写字母"A"字体包含绘制说明 一些表情符号。
  2. 代码点指令存在并包含正确的图像。
  3. 代码点的指令不存在。

在第一种情况下,您别无选择:只有人类(或非常高级的脚本)可以说"这堆像素包含表情符号而不是字母"。但这种情况应该很少见:这不是(正常)人们创建符号字体的方式。

第二种情况很简单:这个字体没问题,你可以使用它。

第三种情况更有趣一些。有时,人们会填充 unicode 图像的代码点,但删除字母的说明以减小字体文件大小。ImageFont似乎没有通过代码点提取信息的特定方法,但它允许我们获取文本掩码。可按字体绘制的文本的蒙版将具有(0, 0)大小:

from PIL import ImageFont

font = ImageFont.truetype("font_to_test.ttf")
mask = font.getmask('abcdefg')  # use some letters from lang you need
if mask.size == (0, 0):
print('This is image font.')
else:
print('This is text font.')

不理想,但适用于我测试的几种字体。

最新更新