Странное поведение, вычисляющее ограничивающую рамку текста с символом градусов

Я использую интерфейс Adobe Font Metrics от matplotlib, чтобы вычислять ограничивающую рамку для различных строк. Расчет ограничивающих рамок для "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 - это Юникод для °)

Результаты

(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)

РЕДАКТИРОВАТЬ:

Проверяя класс AFM в matplotlib.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

0 ответов

Другие вопросы по тегам