If you are using Windows, then the following approach could be used.
It uses the current screen as the output context and calculates the dimensions needed to display the given font at the given point size. It returns a tuple holding the text width and text height:
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)
for text, font in [
('....', 'Arial'),
('WWWW', 'Arial'),
('WWWW', 'Arial Narrow'),
('....', 'Courier New'),
('WWWW', 'Courier New'),
("Test", "Unknown font"),
('Test', 'Calibri')]:
print '{:8} {:20} {}'.format(text, font, GetTextDimensions(text, 12, font))
This would display the following output:
.... Arial (12, 15)
WWWW Arial (44, 15)
WWWW Arial Narrow (36, 16)
.... Courier New (28, 15)
WWWW Courier New (28, 15)
Test Unknown font (24, 15)
Test Calibri (23, 14)
Arial
being a proportional font shows different dimensions for ....
and WWWW
but Courier New
being fixed width gives the same results. Arial Narrow
gives 36
compared to 44
for Arial
.
In the case of Unknown font
, the Windows font mapper has automatically picked a default font.
Tested on Python 2.x.
Note for Python 3.x
As this is calling GetTextExtentPoint32A()
in Windows, this expects ANSI text to be passed to it, as such the call could be changed as follows to fix this:
ctypes.windll.gdi32.GetTextExtentPoint32A(hdc, text.encode('cp1252'), len(text), ctypes.byref(size))
Alternatively, switch the code to use the wide versions, replace with these two:
hfont = ctypes.windll.gdi32.CreateFontW(-points, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, font)
ctypes.windll.gdi32.GetTextExtentPoint32W(hdc, text, len(text), ctypes.byref(size))