我正在构建一个kivy应用程序,需要包含一个字体选择器。由于我找不到一个kivy,我正在建立自己的。但我找不到一种方法来判断一个字体是否对我有用(也就是说,我可以用它来制作一个句子而不是一串符号)。我正在使用Pillow ImageFont。有没有办法在python中区分符号和文本字体?
答案 0 :(得分:1)
一直在努力,我现在对自己的工作感到高兴。仍然不完美,但以下代码只给我一个误报,支持我的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
答案 1 :(得分:0)
我不是这方面的专家,但在这里我是如何看待事物的。
当您尝试使用字体书写一些字母时,渲染器将使用此字母code point从字体文件中获取绘图说明。可能有3种情况:
0x0041
而不是包含指令
绘制拉丁文大写字母" A" font包含绘制的指令
一些表情符号。在第一种情况下,你没有选择:只有人类(或非常高级的脚本)可以说"这一组像素包含表情符号而不是字母"。但这种情况应该很少见:这不是(正常)人们如何创建符号字体。
第二种情况很简单:这个字体没问题,你可以使用它。
第三种情况更有趣。有时候人们会为unicode图像(for example)留下代码点,但会删除字母说明以减少字体文件的大小。 ImageFont似乎没有特定的方法来通过代码点提取信息,但它allows us来获取文本掩码。可以通过字体绘制的文本掩码将具有(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.')
不太理想,但我测试了几种字体的工作。