这是我的想法:
创建一个函数,采用x - 起始x 位置,y - y 位置,text - 要绘制的文本,fallbackList - 字体列表,按@ 排序CSS 中的 987654331@。
- 渲染文本时,使用
fontTools.ttLib.TTFont检查某个字符是否包含在主要字体(fallbackList[0])中,通过解析字体表,循环遍历它,并检查给定字符是否在地图内(请参阅this 问题)。
- 如果第 1 步的结果是
False(即它不包含在字体包中),请遍历 fallbackList,重复第 1 步,直到找到确实包含它的字体.如果您发现一个没有包含它的字体的字符,只需使用第一种字体。我们将把我们刚刚找到的这个字体命名为foundFont。
- 使用
textpath.TextPath((xPosNow, y) ...stuff... prop=foundFont).getextents() (matplotlib > 1.0.0) 绘制该字符。这会绘制该字符,但也会获取文本的边界框,您可以从中提取宽度(请参阅this 问题)。做xPosNow += textWidth,其中textWidth是从getextents()中提取出来的。
这基本上会记录到原点的总距离(通过将您添加的每一位文本的宽度加在一起),然后当您需要添加另一位不同字体的文本时,只需设置x 值是这个计数 + 一点点用于字距调整,这样,您就可以计算出您希望每个字符去哪里(但要分别处理每个字符)。
这是一个代码示例:
import matplotlib.pyplot as plt
from matplotlib.textpath import TextPath
from fontTools.ttLib import TTFont
fig = plt.figure()
plt.axis([0, 8, 0, 6])
t = u'abcde♥'
plt.text(4.5, 4, 'DejaVu Sans:', horizontalalignment='right')
plt.text(5, 4, t, {'family':'DejaVu Sans'})
plt.text(4.5, 3, 'Noto Sans:', horizontalalignment='right')
plt.text(5, 3, t, {'family':'Noto Sans'})
plt.text(4.5, 2, 'Noto Sans Symbols2:', horizontalalignment='right')
plt.text(5, 2, t, {'family':'Noto Sans Symbols2'})
def doesContain(fontPath, unicode_char): # Helper function, the only issue being it takes font paths instead of names
font = TTFont(fontPath) # Use helper library to go through all characters
for cmap in font['cmap'].tables:
if cmap.isUnicode():
if ord(unicode_char) in cmap.cmap: # If the character table contains our character return True
return True
# Otherwise, return False.
return False
def renderText(x, y, text, fontSize, fallback_list, spacingSize):
xPosNow = x
for char in text: # For each character...
fontId = 0
while not doesContain(fallback_list[fontId]['path'], char): # find a font that works
if fontId < len(fallback_list) - 1:
fontId += 1
else: # Or just go with the first font, if nothing seems to match
fontId = 0
break
print(fontId)
t = plt.text(xPosNow, y, char, {'family':fallback_list[fontId]['name']})
r = fig.canvas.get_renderer()
xPosNow += t.get_window_extent(renderer=r).width/100 + spacingSize
我们称之为:
renderText(3, 5, t, 9, [
{
'path': 'C:\\Users\\User\\Downloads\\NotoSans-hinted\\NotoSans-Regular.ttf', # Font path
'name': 'Noto Sans' # Font name
},
{
'path': 'C:\\Users\\User\\Downloads\\NotoSansSymbols2-unhinted\\NotoSansSymbols2-Regular.ttf',
'name': 'Noto Sans Symbols2'
}
]
, 0.08) # The distance between the letters
plt.show()
输出是: