Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f9343ba

Browse files
committed
DOC: Make ftface_props example generate a font metrics figure
The example only printed to stdout with no visual output, so Sphinx Gallery could not auto-generate a thumbnail. Added a matplotlib figure that visualises the font metrics (ascender, descender, bbox, underline position/thickness) normalised to units_per_EM using the same font loaded in the example. Closes #17479
1 parent 315010b commit f9343ba

1 file changed

Lines changed: 53 additions & 17 deletions

File tree

galleries/examples/misc/ftface_props.py

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,40 +11,31 @@
1111
import os
1212

1313
import matplotlib
14+
import matplotlib.pyplot as plt
1415
import matplotlib.ft2font as ft
1516

1617
font = ft.FT2Font(
1718
# Use a font shipped with Matplotlib.
1819
os.path.join(matplotlib.get_data_path(),
1920
'fonts/ttf/DejaVuSans-Oblique.ttf'))
2021

21-
print('Num instances: ', font.num_named_instances) # number of named instances in file
22-
print('Num faces: ', font.num_faces) # number of faces in file
23-
print('Num glyphs: ', font.num_glyphs) # number of glyphs in the face
24-
print('Family name: ', font.family_name) # face family name
25-
print('Style name: ', font.style_name) # face style name
26-
print('PS name: ', font.postscript_name) # the postscript name
27-
print('Num fixed: ', font.num_fixed_sizes) # number of embedded bitmaps
22+
print('Num instances: ', font.num_named_instances)
23+
print('Num faces: ', font.num_faces)
24+
print('Num glyphs: ', font.num_glyphs)
25+
print('Family name: ', font.family_name)
26+
print('Style name: ', font.style_name)
27+
print('PS name: ', font.postscript_name)
28+
print('Num fixed: ', font.num_fixed_sizes)
2829

29-
# the following are only available if face.scalable
3030
if font.scalable:
31-
# the face global bounding box (xmin, ymin, xmax, ymax)
3231
print('Bbox: ', font.bbox)
33-
# number of font units covered by the EM
3432
print('EM: ', font.units_per_EM)
35-
# the ascender in 26.6 units
3633
print('Ascender: ', font.ascender)
37-
# the descender in 26.6 units
3834
print('Descender: ', font.descender)
39-
# the height in 26.6 units
4035
print('Height: ', font.height)
41-
# maximum horizontal cursor advance
4236
print('Max adv width: ', font.max_advance_width)
43-
# same for vertical layout
4437
print('Max adv height: ', font.max_advance_height)
45-
# vertical position of the underline bar
4638
print('Underline pos: ', font.underline_position)
47-
# vertical thickness of the underline
4839
print('Underline thickness:', font.underline_thickness)
4940

5041
for flag in ft.StyleFlags:
@@ -54,3 +45,48 @@
5445
for flag in ft.FaceFlags:
5546
name = flag.name.replace('_', ' ').title() + ':'
5647
print(f"{name:17}", flag in font.face_flags)
48+
49+
# ── Visualise font metrics ──────────────────────────────────────────────────
50+
if font.scalable:
51+
u = font.units_per_EM # normalise every value: divide by EM = 1.0
52+
53+
ascender = font.ascender / u
54+
descender = font.descender / u
55+
bbox_ymax = font.bbox[3] / u
56+
bbox_ymin = font.bbox[1] / u
57+
ul_pos = font.underline_position / u
58+
ul_thick = font.underline_thickness / u
59+
60+
fig, ax = plt.subplots(figsize=(5, 4))
61+
62+
ax.text(0.15, 0, "Ag", fontsize=74, va='baseline',
63+
fontfamily='DejaVu Sans', color='black', zorder=3)
64+
65+
metrics = [
66+
("ascender", ascender, "tab:blue"),
67+
("baseline (y=0)", 0, "black"),
68+
("descender", descender, "tab:red"),
69+
("bbox top (ymax)", bbox_ymax, "tab:green"),
70+
("bbox bottom (ymin)", bbox_ymin, "tab:purple"),
71+
("underline_position", ul_pos, "tab:orange"),
72+
]
73+
74+
for label, y, color in metrics:
75+
ax.axhline(y, color=color, linewidth=1, linestyle='--', alpha=0.8)
76+
ax.text(0.82, y, label, color=color, va='center',
77+
fontsize=7.5, clip_on=True)
78+
79+
ax.axhspan(ul_pos - ul_thick, ul_pos,
80+
color='tab:orange', alpha=0.25,
81+
label=f'underline_thickness = {font.underline_thickness}')
82+
83+
ax.set_xlim(0, 1.55)
84+
ax.set_ylim(bbox_ymin - 0.05, bbox_ymax + 0.05)
85+
ax.set_title(
86+
f"Font metrics — {font.family_name} {font.style_name}\n"
87+
f"(values normalised to units_per_EM = {font.units_per_EM})"
88+
)
89+
ax.legend(fontsize=7, loc='lower right')
90+
ax.axis('off')
91+
plt.tight_layout()
92+
plt.show()

0 commit comments

Comments
 (0)