Skip to content

Commit bc2b853

Browse files
QuLogictacaswell
authored andcommitted
ft2font: Convert flag properties to enums
1 parent 0bed02d commit bc2b853

File tree

7 files changed

+186
-66
lines changed

7 files changed

+186
-66
lines changed

doc/api/next_api_changes/deprecations/28842-ES.rst

+19
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,22 @@ prefix):
3434
- ``LOAD_TARGET_MONO``
3535
- ``LOAD_TARGET_LCD``
3636
- ``LOAD_TARGET_LCD_V``
37+
38+
The following constants are now part of `.ft2font.FaceFlags`:
39+
40+
- ``EXTERNAL_STREAM``
41+
- ``FAST_GLYPHS``
42+
- ``FIXED_SIZES``
43+
- ``FIXED_WIDTH``
44+
- ``GLYPH_NAMES``
45+
- ``HORIZONTAL``
46+
- ``KERNING``
47+
- ``MULTIPLE_MASTERS``
48+
- ``SCALABLE``
49+
- ``SFNT``
50+
- ``VERTICAL``
51+
52+
The following constants are now part of `.ft2font.StyleFlags`:
53+
54+
- ``ITALIC``
55+
- ``BOLD``

galleries/examples/misc/ftface_props.py

+7-15
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,10 @@
4646
# vertical thickness of the underline
4747
print('Underline thickness:', font.underline_thickness)
4848

49-
for style in ('Italic',
50-
'Bold',
51-
'Scalable',
52-
'Fixed sizes',
53-
'Fixed width',
54-
'SFNT',
55-
'Horizontal',
56-
'Vertical',
57-
'Kerning',
58-
'Fast glyphs',
59-
'Multiple masters',
60-
'Glyph names',
61-
'External stream'):
62-
bitpos = getattr(ft, style.replace(' ', '_').upper()) - 1
63-
print(f"{style+':':17}", bool(font.style_flags & (1 << bitpos)))
49+
for flag in ft.StyleFlags:
50+
name = flag.name.replace('_', ' ').title() + ':'
51+
print(f"{name:17}", flag in font.style_flags)
52+
53+
for flag in ft.FaceFlags:
54+
name = flag.name.replace('_', ' ').title() + ':'
55+
print(f"{name:17}", flag in font.face_flags)

lib/matplotlib/backends/backend_pdf.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from matplotlib.figure import Figure
3636
from matplotlib.font_manager import get_font, fontManager as _fontManager
3737
from matplotlib._afm import AFM
38-
from matplotlib.ft2font import FIXED_WIDTH, ITALIC, FT2Font, Kerning, LoadFlags
38+
from matplotlib.ft2font import FT2Font, FaceFlags, Kerning, LoadFlags, StyleFlags
3939
from matplotlib.transforms import Affine2D, BboxBase
4040
from matplotlib.path import Path
4141
from matplotlib.dates import UTC
@@ -1417,15 +1417,15 @@ def embedTTFType42(font, characters, descriptor):
14171417

14181418
flags = 0
14191419
symbolic = False # ps_name.name in ('Cmsy10', 'Cmmi10', 'Cmex10')
1420-
if ff & FIXED_WIDTH:
1420+
if FaceFlags.FIXED_WIDTH in ff:
14211421
flags |= 1 << 0
14221422
if 0: # TODO: serif
14231423
flags |= 1 << 1
14241424
if symbolic:
14251425
flags |= 1 << 2
14261426
else:
14271427
flags |= 1 << 5
1428-
if sf & ITALIC:
1428+
if StyleFlags.ITALIC in sf:
14291429
flags |= 1 << 6
14301430
if 0: # TODO: all caps
14311431
flags |= 1 << 16

lib/matplotlib/font_manager.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def ttfFontProperty(font):
379379
style = 'italic'
380380
elif sfnt2.find('regular') >= 0:
381381
style = 'normal'
382-
elif font.style_flags & ft2font.ITALIC:
382+
elif ft2font.StyleFlags.ITALIC in font.style_flags:
383383
style = 'italic'
384384
else:
385385
style = 'normal'
@@ -428,7 +428,7 @@ def get_weight(): # From fontconfig's FcFreeTypeQueryFaceInternal.
428428
for regex, weight in _weight_regexes:
429429
if re.search(regex, style, re.I):
430430
return weight
431-
if font.style_flags & ft2font.BOLD:
431+
if ft2font.StyleFlags.BOLD in font.style_flags:
432432
return 700 # "bold"
433433
return 500 # "medium", not "regular"!
434434

lib/matplotlib/ft2font.pyi

+28-15
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,27 @@ from numpy.typing import NDArray
88

99
__freetype_build_type__: str
1010
__freetype_version__: str
11-
BOLD: int
12-
EXTERNAL_STREAM: int
13-
FAST_GLYPHS: int
14-
FIXED_SIZES: int
15-
FIXED_WIDTH: int
16-
GLYPH_NAMES: int
17-
HORIZONTAL: int
18-
ITALIC: int
19-
KERNING: int
20-
MULTIPLE_MASTERS: int
21-
SCALABLE: int
22-
SFNT: int
23-
VERTICAL: int
11+
12+
class FaceFlags(Flag):
13+
SCALABLE: int
14+
FIXED_SIZES: int
15+
FIXED_WIDTH: int
16+
SFNT: int
17+
HORIZONTAL: int
18+
VERTICAL: int
19+
KERNING: int
20+
FAST_GLYPHS: int
21+
MULTIPLE_MASTERS: int
22+
GLYPH_NAMES: int
23+
EXTERNAL_STREAM: int
24+
HINTER: int
25+
CID_KEYED: int
26+
TRICKY: int
27+
COLOR: int
28+
# VARIATION: int # FT 2.9
29+
# SVG: int # FT 2.12
30+
# SBIX: int # FT 2.12
31+
# SBIX_OVERLAY: int # FT 2.12
2432

2533
class Kerning(Enum):
2634
DEFAULT: int
@@ -54,6 +62,11 @@ class LoadFlags(Flag):
5462
TARGET_LCD: int
5563
TARGET_LCD_V: int
5664

65+
class StyleFlags(Flag):
66+
NORMAL: int
67+
ITALIC: int
68+
BOLD: int
69+
5770
class _SfntHeadDict(TypedDict):
5871
version: tuple[int, int]
5972
fontRevision: tuple[int, int]
@@ -232,7 +245,7 @@ class FT2Font(Buffer):
232245
@property
233246
def descender(self) -> int: ...
234247
@property
235-
def face_flags(self) -> int: ...
248+
def face_flags(self) -> FaceFlags: ...
236249
@property
237250
def family_name(self) -> str: ...
238251
@property
@@ -256,7 +269,7 @@ class FT2Font(Buffer):
256269
@property
257270
def scalable(self) -> bool: ...
258271
@property
259-
def style_flags(self) -> int: ...
272+
def style_flags(self) -> StyleFlags: ...
260273
@property
261274
def style_name(self) -> str: ...
262275
@property

lib/matplotlib/tests/test_ft2font.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ def test_ft2font_dejavu_attrs():
4444
assert font.num_fixed_sizes == 0 # All glyphs are scalable.
4545
assert font.num_charmaps == 5
4646
# Other internal flags are set, so only check the ones we're allowed to test.
47-
expected_flags = (ft2font.SCALABLE | ft2font.SFNT | ft2font.HORIZONTAL |
48-
ft2font.KERNING | ft2font.GLYPH_NAMES)
49-
assert (font.face_flags & expected_flags) == expected_flags
50-
assert font.style_flags == 0 # Not italic or bold.
47+
expected_flags = (ft2font.FaceFlags.SCALABLE | ft2font.FaceFlags.SFNT |
48+
ft2font.FaceFlags.HORIZONTAL | ft2font.FaceFlags.KERNING |
49+
ft2font.FaceFlags.GLYPH_NAMES)
50+
assert expected_flags in font.face_flags
51+
assert font.style_flags == ft2font.StyleFlags.NORMAL
5152
assert font.scalable
5253
# From FontForge: Font Information → General tab → entry name below.
5354
assert font.units_per_EM == 2048 # Em Size.
@@ -76,10 +77,10 @@ def test_ft2font_cm_attrs():
7677
assert font.num_fixed_sizes == 0 # All glyphs are scalable.
7778
assert font.num_charmaps == 2
7879
# Other internal flags are set, so only check the ones we're allowed to test.
79-
expected_flags = (ft2font.SCALABLE | ft2font.SFNT | ft2font.HORIZONTAL |
80-
ft2font.GLYPH_NAMES)
81-
assert (font.face_flags & expected_flags) == expected_flags, font.face_flags
82-
assert font.style_flags == 0 # Not italic or bold.
80+
expected_flags = (ft2font.FaceFlags.SCALABLE | ft2font.FaceFlags.SFNT |
81+
ft2font.FaceFlags.HORIZONTAL | ft2font.FaceFlags.GLYPH_NAMES)
82+
assert expected_flags in font.face_flags
83+
assert font.style_flags == ft2font.StyleFlags.NORMAL
8384
assert font.scalable
8485
# From FontForge: Font Information → General tab → entry name below.
8586
assert font.units_per_EM == 2048 # Em Size.
@@ -108,10 +109,10 @@ def test_ft2font_stix_bold_attrs():
108109
assert font.num_fixed_sizes == 0 # All glyphs are scalable.
109110
assert font.num_charmaps == 3
110111
# Other internal flags are set, so only check the ones we're allowed to test.
111-
expected_flags = (ft2font.SCALABLE | ft2font.SFNT | ft2font.HORIZONTAL |
112-
ft2font.GLYPH_NAMES)
113-
assert (font.face_flags & expected_flags) == expected_flags, font.face_flags
114-
assert font.style_flags == ft2font.BOLD
112+
expected_flags = (ft2font.FaceFlags.SCALABLE | ft2font.FaceFlags.SFNT |
113+
ft2font.FaceFlags.HORIZONTAL | ft2font.FaceFlags.GLYPH_NAMES)
114+
assert expected_flags in font.face_flags
115+
assert font.style_flags == ft2font.StyleFlags.BOLD
115116
assert font.scalable
116117
# From FontForge: Font Information → General tab → entry name below.
117118
assert font.units_per_EM == 1000 # Em Size.

src/ft2font_wrapper.cpp

+114-19
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,74 @@ P11X_DECLARE_ENUM(
3333
{"UNSCALED", FT_KERNING_UNSCALED},
3434
);
3535

36+
const char *FaceFlags__doc__ = R"""(
37+
Flags returned by `FT2Font.face_flags`.
38+
39+
For more information, see `the FreeType documentation
40+
<https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_face_flag_xxx>`_.
41+
42+
.. versionadded:: 3.10
43+
)""";
44+
45+
enum class FaceFlags : FT_Long {
46+
#define DECLARE_FLAG(name) name = FT_FACE_FLAG_##name
47+
DECLARE_FLAG(SCALABLE),
48+
DECLARE_FLAG(FIXED_SIZES),
49+
DECLARE_FLAG(FIXED_WIDTH),
50+
DECLARE_FLAG(SFNT),
51+
DECLARE_FLAG(HORIZONTAL),
52+
DECLARE_FLAG(VERTICAL),
53+
DECLARE_FLAG(KERNING),
54+
DECLARE_FLAG(FAST_GLYPHS),
55+
DECLARE_FLAG(MULTIPLE_MASTERS),
56+
DECLARE_FLAG(GLYPH_NAMES),
57+
DECLARE_FLAG(EXTERNAL_STREAM),
58+
DECLARE_FLAG(HINTER),
59+
DECLARE_FLAG(CID_KEYED),
60+
DECLARE_FLAG(TRICKY),
61+
DECLARE_FLAG(COLOR),
62+
#ifdef FT_FACE_FLAG_VARIATION // backcompat: ft 2.9.0.
63+
DECLARE_FLAG(VARIATION),
64+
#endif
65+
#ifdef FT_FACE_FLAG_SVG // backcompat: ft 2.12.0.
66+
DECLARE_FLAG(SVG),
67+
#endif
68+
#ifdef FT_FACE_FLAG_SBIX // backcompat: ft 2.12.0.
69+
DECLARE_FLAG(SBIX),
70+
#endif
71+
#ifdef FT_FACE_FLAG_SBIX_OVERLAY // backcompat: ft 2.12.0.
72+
DECLARE_FLAG(SBIX_OVERLAY),
73+
#endif
74+
#undef DECLARE_FLAG
75+
};
76+
77+
P11X_DECLARE_ENUM(
78+
"FaceFlags", "Flag",
79+
{"SCALABLE", FaceFlags::SCALABLE},
80+
{"FIXED_SIZES", FaceFlags::FIXED_SIZES},
81+
{"FIXED_WIDTH", FaceFlags::FIXED_WIDTH},
82+
{"SFNT", FaceFlags::SFNT},
83+
{"HORIZONTAL", FaceFlags::HORIZONTAL},
84+
{"VERTICAL", FaceFlags::VERTICAL},
85+
{"KERNING", FaceFlags::KERNING},
86+
{"FAST_GLYPHS", FaceFlags::FAST_GLYPHS},
87+
{"MULTIPLE_MASTERS", FaceFlags::MULTIPLE_MASTERS},
88+
{"GLYPH_NAMES", FaceFlags::GLYPH_NAMES},
89+
{"EXTERNAL_STREAM", FaceFlags::EXTERNAL_STREAM},
90+
{"HINTER", FaceFlags::HINTER},
91+
{"CID_KEYED", FaceFlags::CID_KEYED},
92+
{"TRICKY", FaceFlags::TRICKY},
93+
{"COLOR", FaceFlags::COLOR},
94+
// backcompat: ft 2.9.0.
95+
// {"VARIATION", FaceFlags::VARIATION},
96+
// backcompat: ft 2.12.0.
97+
// {"SVG", FaceFlags::SVG},
98+
// backcompat: ft 2.12.0.
99+
// {"SBIX", FaceFlags::SBIX},
100+
// backcompat: ft 2.12.0.
101+
// {"SBIX_OVERLAY", FaceFlags::SBIX_OVERLAY},
102+
);
103+
36104
const char *LoadFlags__doc__ = R"""(
37105
Flags for `FT2Font.load_char`, `FT2Font.load_glyph`, and `FT2Font.set_text`.
38106
@@ -110,6 +178,30 @@ P11X_DECLARE_ENUM(
110178
{"TARGET_LCD_V", LoadFlags::TARGET_LCD_V},
111179
);
112180

181+
const char *StyleFlags__doc__ = R"""(
182+
Flags returned by `FT2Font.style_flags`.
183+
184+
For more information, see `the FreeType documentation
185+
<https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_style_flag_xxx>`_.
186+
187+
.. versionadded:: 3.10
188+
)""";
189+
190+
enum class StyleFlags : FT_Long {
191+
#define DECLARE_FLAG(name) name = FT_STYLE_FLAG_##name
192+
NORMAL = 0,
193+
DECLARE_FLAG(ITALIC),
194+
DECLARE_FLAG(BOLD),
195+
#undef DECLARE_FLAG
196+
};
197+
198+
P11X_DECLARE_ENUM(
199+
"StyleFlags", "Flag",
200+
{"NORMAL", StyleFlags::NORMAL},
201+
{"ITALIC", StyleFlags::ITALIC},
202+
{"BOLD", StyleFlags::BOLD},
203+
);
204+
113205
/**********************************************************************
114206
* FT2Image
115207
* */
@@ -1339,16 +1431,16 @@ PyFT2Font_style_name(PyFT2Font *self)
13391431
return name;
13401432
}
13411433

1342-
static FT_Long
1434+
static FaceFlags
13431435
PyFT2Font_face_flags(PyFT2Font *self)
13441436
{
1345-
return self->x->get_face()->face_flags;
1437+
return static_cast<FaceFlags>(self->x->get_face()->face_flags);
13461438
}
13471439

1348-
static FT_Long
1440+
static StyleFlags
13491441
PyFT2Font_style_flags(PyFT2Font *self)
13501442
{
1351-
return self->x->get_face()->style_flags;
1443+
return static_cast<StyleFlags>(self->x->get_face()->style_flags);
13521444
}
13531445

13541446
static FT_Long
@@ -1496,6 +1588,20 @@ ft2font__getattr__(std::string name) {
14961588
DEPRECATE_ATTR_FROM_FLAG(LOAD_TARGET_LCD, LoadFlags, TARGET_LCD);
14971589
DEPRECATE_ATTR_FROM_FLAG(LOAD_TARGET_LCD_V, LoadFlags, TARGET_LCD_V);
14981590

1591+
DEPRECATE_ATTR_FROM_FLAG(SCALABLE, FaceFlags, SCALABLE);
1592+
DEPRECATE_ATTR_FROM_FLAG(FIXED_SIZES, FaceFlags, FIXED_SIZES);
1593+
DEPRECATE_ATTR_FROM_FLAG(FIXED_WIDTH, FaceFlags, FIXED_WIDTH);
1594+
DEPRECATE_ATTR_FROM_FLAG(SFNT, FaceFlags, SFNT);
1595+
DEPRECATE_ATTR_FROM_FLAG(HORIZONTAL, FaceFlags, HORIZONTAL);
1596+
DEPRECATE_ATTR_FROM_FLAG(VERTICAL, FaceFlags, VERTICAL);
1597+
DEPRECATE_ATTR_FROM_FLAG(KERNING, FaceFlags, KERNING);
1598+
DEPRECATE_ATTR_FROM_FLAG(FAST_GLYPHS, FaceFlags, FAST_GLYPHS);
1599+
DEPRECATE_ATTR_FROM_FLAG(MULTIPLE_MASTERS, FaceFlags, MULTIPLE_MASTERS);
1600+
DEPRECATE_ATTR_FROM_FLAG(GLYPH_NAMES, FaceFlags, GLYPH_NAMES);
1601+
DEPRECATE_ATTR_FROM_FLAG(EXTERNAL_STREAM, FaceFlags, EXTERNAL_STREAM);
1602+
1603+
DEPRECATE_ATTR_FROM_FLAG(ITALIC, StyleFlags, ITALIC);
1604+
DEPRECATE_ATTR_FROM_FLAG(BOLD, StyleFlags, BOLD);
14991605
#undef DEPRECATE_ATTR_FROM_FLAG
15001606

15011607
throw py::attribute_error(
@@ -1515,6 +1621,8 @@ PYBIND11_MODULE(ft2font, m)
15151621
p11x::bind_enums(m);
15161622
p11x::enums["Kerning"].attr("__doc__") = Kerning__doc__;
15171623
p11x::enums["LoadFlags"].attr("__doc__") = LoadFlags__doc__;
1624+
p11x::enums["FaceFlags"].attr("__doc__") = FaceFlags__doc__;
1625+
p11x::enums["StyleFlags"].attr("__doc__") = StyleFlags__doc__;
15181626

15191627
py::class_<FT2Image>(m, "FT2Image", py::is_final(), py::buffer_protocol(),
15201628
PyFT2Image__doc__)
@@ -1614,9 +1722,9 @@ PYBIND11_MODULE(ft2font, m)
16141722
.def_property_readonly("style_name", &PyFT2Font_style_name,
16151723
"Style name.")
16161724
.def_property_readonly("face_flags", &PyFT2Font_face_flags,
1617-
"Face flags; see the ft2font constants.")
1725+
"Face flags; see `.FaceFlags`.")
16181726
.def_property_readonly("style_flags", &PyFT2Font_style_flags,
1619-
"Style flags; see the ft2font constants.")
1727+
"Style flags; see `.StyleFlags`.")
16201728
.def_property_readonly("num_glyphs", &PyFT2Font_num_glyphs,
16211729
"Number of glyphs in the face.")
16221730
.def_property_readonly("num_fixed_sizes", &PyFT2Font_num_fixed_sizes,
@@ -1658,17 +1766,4 @@ PYBIND11_MODULE(ft2font, m)
16581766
m.attr("__freetype_version__") = version_string;
16591767
m.attr("__freetype_build_type__") = FREETYPE_BUILD_TYPE;
16601768
m.def("__getattr__", ft2font__getattr__);
1661-
m.attr("SCALABLE") = FT_FACE_FLAG_SCALABLE;
1662-
m.attr("FIXED_SIZES") = FT_FACE_FLAG_FIXED_SIZES;
1663-
m.attr("FIXED_WIDTH") = FT_FACE_FLAG_FIXED_WIDTH;
1664-
m.attr("SFNT") = FT_FACE_FLAG_SFNT;
1665-
m.attr("HORIZONTAL") = FT_FACE_FLAG_HORIZONTAL;
1666-
m.attr("VERTICAL") = FT_FACE_FLAG_VERTICAL;
1667-
m.attr("KERNING") = FT_FACE_FLAG_KERNING;
1668-
m.attr("FAST_GLYPHS") = FT_FACE_FLAG_FAST_GLYPHS;
1669-
m.attr("MULTIPLE_MASTERS") = FT_FACE_FLAG_MULTIPLE_MASTERS;
1670-
m.attr("GLYPH_NAMES") = FT_FACE_FLAG_GLYPH_NAMES;
1671-
m.attr("EXTERNAL_STREAM") = FT_FACE_FLAG_EXTERNAL_STREAM;
1672-
m.attr("ITALIC") = FT_STYLE_FLAG_ITALIC;
1673-
m.attr("BOLD") = FT_STYLE_FLAG_BOLD;
16741769
}

0 commit comments

Comments
 (0)