Как получить визуальную длину текстовой строки в python

Подобно этому вопросу , я не спрашиваю, как найти количество символов в строке. Я хотел бы определить визуальную длину строки как визуализированную или сравнить ее с другой строкой.

Например, как «iiii», так и «WWWW» имеют четыре символа. Однако «iiii» короче визуально. Я знаю, что это определяется шрифтом, и я не работаю с моноширинными шрифтами. Итак, для этой проблемы я буду использовать Arial 10pt.

Существуют ли встроенные модули, которые будут предоставлять визуальные размеры строки с учетом шрифта?

Если вы используете Windows, можно использовать следующий подход.

Он использует текущий экран в качестве контекста вывода и вычисляет размеры, необходимые для отображения данного шрифта при заданном размере точки. Он возвращает кортеж, содержащий ширину текста и высоту текста:

import ctypes def GetTextDimensions(text, points, font): class SIZE(ctypes.Structure): _fields_ = [("cx", ctypes.c_long), ("cy", ctypes.c_long)] hdc = ctypes.windll.user32.GetDC(0) hfont = ctypes.windll.gdi32.CreateFontA(-points, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, font) hfont_old = ctypes.windll.gdi32.SelectObject(hdc, hfont) size = SIZE(0, 0) ctypes.windll.gdi32.GetTextExtentPoint32A(hdc, text, len(text), ctypes.byref(size)) ctypes.windll.gdi32.SelectObject(hdc, hfont_old) ctypes.windll.gdi32.DeleteObject(hfont) return (size.cx, size.cy) print GetTextDimensions("....", 12, "Arial") print GetTextDimensions("WWWW", 12, "Arial") print GetTextDimensions("....", 12, "Courier New") print GetTextDimensions("WWWW", 12, "Courier New") 

Это отобразит следующий результат:

 (12, 15) (44, 15) (28, 15) (28, 15) 

Arial являющийся пропорциональным шрифтом, показывает разные размеры для .... и WWWW но Courier New , фиксированная ширина, дает те же результаты.

Вместо рендеринга в буфер изображения и подсчета пикселей вы можете рассчитать ширину напрямую, используя метрики шрифта. Кажется, что API-интерфейс шрифтов не распространяется с основным питоном, но в различных пакетах есть много сторонних. Вот довольно полное решение для метрик Adobe font, используя matplotlib :

 >>> from matplotlib import rcParams >>> import os.path >>> afm_filename = os.path.join(rcParams['datapath'], 'fonts', 'afm', 'ptmr8a.afm') >>> >>> from matplotlib.afm import AFM >>> afm = AFM(open(afm_filename)) >>> afm.string_width_height('What the heck?') (6220.0, 694) 

Другая возможность – это модуль tkinter . Эта страница документирует функцию tkFont.Font.measure("some string") , но, похоже, вам нужно окно Tk, прежде чем вы сможете его использовать; поэтому я не знаю, насколько это практично:

 # Python 3 names -- see Note below import tkinter from tkinter import font as tkFont tkinter.Frame().destroy() # Enough to initialize resources arial36b = tkFont.Font(family='Arial', size=36, weight='bold') width = arial36b.measure("How wide is this?") print(width) # Prints: 404 

Примечание. В python 2 (и на странице, упомянутой выше) tkinter известен как Tkinter , а tkinter.font – модуль верхнего уровня, tkFont :

 import Tkinter import tkFont 

Используйте графическую / библиотеку шрифтов, например ImageFont . Нарисуйте строку, а затем используйте getize для получения ширины.

Обратите внимание, что некоторый текст, такой как «AWAY», может быть уже, чем сумма отдельных букв из-за кернинга . Поэтому было бы трудно искать ширины каждой буквы и добавлять их.