Ширина необработанного текста обычно рассчитывается в точках типографа , но, поскольку точка для определения шрифта определена как 1/72 дюйма, вы можете легко преобразовать ее в любую другую единицу.
Чтобы получить дизайн ширины символа (выраженный в em единицах), вам необходим доступ к низкоуровневым данным шрифта. Самый простой способ - pip install fonttools
, в котором есть все для работы на минимально возможном уровне определений шрифтов.
С установленным fontTools вы можете:
- загрузить данные шрифта - для этого требуется путь к фактическому файлу шрифта;
ширина символов сохраняется как glyph width, что означает, что вы должны получить отображение «символ-глиф»; это в cmap
таблице шрифтов:
а. загрузите cmap
для вашего шрифта. Наиболее полезной является карта Unicode - шрифт может содержать другие.
б. загрузите набор глифов для вашего шрифта. Это список имен для глифов этого шрифта.
Затем для каждого символа Unicode сначала найдите его имя, а затем используйте имя для получения его ширины в единицах проектирования.
- Не забывайте, что «единицы дизайна» основаны на общей «ширине дизайна» шрифта. Это может быть стандартное значение
1000
(типично для шрифтов типа 1), 2048
(типично для шрифтов TrueType) или любое другое значение.
Что приводит к этой функции:
from fontTools.ttLib import TTFont
from fontTools.ttLib.tables._c_m_a_p import CmapSubtable
font = TTFont('/Library/Fonts/Arial.ttf')
cmap = font['cmap']
t = cmap.getcmap(3,1).cmap
s = font.getGlyphSet()
units_per_em = font['head'].unitsPerEm
def getTextWidth(text,pointSize):
total = 0
for c in text:
if ord(c) in t and t[ord(c)] in s:
total += s[t[ord(c)]].width
else:
total += s['.notdef'].width
total = total*float(pointSize)/units_per_em;
return total
text = 'This is a test'
width = getTextWidth(text,12)
print ('Text: "%s"' % text)
print ('Width in points: %f' % width)
print ('Width in inches: %f' % (width/72))
print ('Width in cm: %f' % (width*2.54/72))
print ('Width in WP Units: %f' % (width*1200/72))
Результат:
Text: "This is a test"
Width in points: 67.353516
Width in inches: 0.935465
Width in cm: 2.376082
Width in WP Units: 1122.558594
и является правильным при сравнении с отчетами Adobe InDesign. (Обратите внимание, что символьный кернинг здесь не применяется! Для этого потребуется намного больше кода.)
Символы, которые не определены в шрифте, игнорируются, и, как обычно это делается, используется ширина для символа .notdef
. Если вы хотите, чтобы это сообщалось как об ошибке, удалите тест if
в функции.
Приведение к float
в функции getTextWidth
таково, что это работает как в Python 2.7, так и в 3.5, но учтите, что если вы используете символы Unicode Python 2.7 и более (не простые ASCII), вам нужно переписать функция для правильного использования символов UTF8.