|
11 | 11 | import os |
12 | 12 |
|
13 | 13 | import matplotlib |
| 14 | +import matplotlib.pyplot as plt |
14 | 15 | import matplotlib.ft2font as ft |
15 | 16 |
|
16 | 17 | font = ft.FT2Font( |
17 | 18 | # Use a font shipped with Matplotlib. |
18 | 19 | os.path.join(matplotlib.get_data_path(), |
19 | 20 | 'fonts/ttf/DejaVuSans-Oblique.ttf')) |
20 | 21 |
|
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) |
28 | 29 |
|
29 | | -# the following are only available if face.scalable |
30 | 30 | if font.scalable: |
31 | | - # the face global bounding box (xmin, ymin, xmax, ymax) |
32 | 31 | print('Bbox: ', font.bbox) |
33 | | - # number of font units covered by the EM |
34 | 32 | print('EM: ', font.units_per_EM) |
35 | | - # the ascender in 26.6 units |
36 | 33 | print('Ascender: ', font.ascender) |
37 | | - # the descender in 26.6 units |
38 | 34 | print('Descender: ', font.descender) |
39 | | - # the height in 26.6 units |
40 | 35 | print('Height: ', font.height) |
41 | | - # maximum horizontal cursor advance |
42 | 36 | print('Max adv width: ', font.max_advance_width) |
43 | | - # same for vertical layout |
44 | 37 | print('Max adv height: ', font.max_advance_height) |
45 | | - # vertical position of the underline bar |
46 | 38 | print('Underline pos: ', font.underline_position) |
47 | | - # vertical thickness of the underline |
48 | 39 | print('Underline thickness:', font.underline_thickness) |
49 | 40 |
|
50 | 41 | for flag in ft.StyleFlags: |
|
54 | 45 | for flag in ft.FaceFlags: |
55 | 46 | name = flag.name.replace('_', ' ').title() + ':' |
56 | 47 | 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