我正在使用matplotlib的Adobe Font Metrics接口来计算各种字符串的边界框。计算“12”和“°”的边界框效果很好,但是在计算“12°”的边界框时,框的大小似乎太大了。
我知道边界框的尺寸不一定等于由于字距调整等部分的边界框的总和,但这看起来很荒谬。 (它似乎也没有反映出这种文本在渲染时的大小)。
代码:
import os.path
from matplotlib import rcParams
from matplotlib.afm import AFM
afm_fname = os.path.join(rcParams['datapath'],
'fonts', 'afm', 'ptmr8a.afm')
with open(afm_fname, 'rb') as fh:
afm = AFM(fh)
print(afm.get_str_bbox('12'))
print(afm.get_str_bbox('\u00B0'))
print(afm.get_str_bbox('12\u00B0'))
(\ u00B0是°的unicode)
结果
(0, 0, 1000.0, 676)
(0, 390, 400.0, 676)
(0, 0, 1400.0, 1066)
第三个结果的高度显然太大了。 1066是676 + 390,我不知道这是巧合,但我不明白
问题的
为什么边界框太大/导致这种行为的原因是什么?
有没有办法'修复'这个,以便我得到一个更具代表性的bbox,文本实际上是什么样的?
(有关边界框的更多信息,请点击此处:https://wwwimages2.adobe.com/content/dam/acom/en/devnet/font/pdfs/5004.AFM_Spec.pdf)
修改
在matplotlib.afm中检查AFM类我认为我找到了违规行。 # find the max y
下面是thismax = b + h
。我无法理解为什么b+h
应该在那里使用,而不仅仅是h
????
def get_str_bbox_and_descent(self, s):
"""
Return the string bounding box
"""
if not len(s):
return 0, 0, 0, 0
totalw = 0
namelast = None
miny = 1e9
maxy = 0
left = 0
if not isinstance(s, six.text_type):
s = _to_str(s)
for c in s:
if c == '\n':
continue
name = uni2type1.get(ord(c), 'question')
try:
wx, bbox = self._metrics_by_name[name]
except KeyError:
name = 'question'
wx, bbox = self._metrics_by_name[name]
l, b, w, h = bbox
if l < left:
left = l
# find the width with kerning
try:
kp = self._kern[(namelast, name)]
except KeyError:
kp = 0
totalw += wx + kp
# find the max y
thismax = b + h
if thismax > maxy:
maxy = thismax
# find the min y
thismin = b
if thismin < miny:
miny = thismin
namelast = name
return left, miny, totalw, maxy - miny, -miny