matplotlib:我能用一个辅助字体来处理丢失的字形吗?

2024-05-29 01:58:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用的字体没有我需要的所有符号。如果缺少符号,matplotlib是否可以使用其他字体?在

下面是一个最小的例子:

import matplotlib.pyplot as plt

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'})

plt.show()

以及输出:

And the output.

Noto Sans缺少心脏符号,而Noto Sans Symbols2缺少字母。我试图得到一些像DejaVu Sans的例子,但是有来自Noto Sans的字母和来自Noto Sans Symbols2的心脏。在


Tags: textrightmatplotlib字母字体符号pltfamily
1条回答
网友
1楼 · 发布于 2024-05-29 01:58:24

我的想法是:

创建一个函数,采用x-起始x位置,y-位置{}位置,text-要绘制的文本,fallbackList-字体列表,其顺序类似于CSS中的font-family。在

  1. 呈现文本时,使用fontTools.ttLib.TTFont来检查某个字符是否包含在主字体(fallbackList[0])中,方法是解析字体表,循环使用它,并检查给定字符是否在映射中(请参见this问题)。在
  2. 如果第1步的结果是False(也就是说它不包含在字体包中),重复步骤1,直到找到一个包含它的字体。如果你发现一个字符没有包含它的字体,只需使用第一个字体。我们将这个字体称为foundFont。在
  3. textpath.TextPath((xPosNow, y) ...stuff... prop=foundFont).getextents()(matplotlib>;1.0.0)绘制该字符。这将绘制该字符,但也会获取文本的边界框,从中可以提取宽度(请参见this问题)。Do xPosNow += textWidth,其中textWidth是从^{中提取的。在

这将基本上保持与原点的总距离的计数(通过将添加的每一位文本的宽度相加),然后当您需要以不同字体添加另一位文本时,只需将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

我们称之为:

^{pr2}$

输出是:

image

相关问题 更多 >

    热门问题