8000 Merge pull request #28842 from QuLogic/ft2font-improvements · matplotlib/matplotlib@1f0ddbe · GitHub
[go: up one dir, main page]

Skip to content

Commit 1f0ddbe

Browse files
authored
Merge pull request #28842 from QuLogic/ft2font-improvements
FT2Font extension improvements
2 parents 51e8f7f + 5864017 commit 1f0ddbe

File tree

20 files changed

+1182
-333
lines changed

20 files changed

+1182
-333
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
ft2font module-level constants replaced by enums
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
The `.ft2font`-level constants have been converted to `enum` classes, and all API using
5+
them now take/return the new types.
6+
7+
The following constants are now part of `.ft2font.Kerning` (without the ``KERNING_``
8+
prefix):
9+
10+
- ``KERNING_DEFAULT``
11+
- ``KERNING_UNFITTED``
12+
- ``KERNING_UNSCALED``
13+
14+
The following constants are now part of `.ft2font.LoadFlags` (without the ``LOAD_``
15+
prefix):
16+
17+
- ``LOAD_DEFAULT``
18+
- ``LOAD_NO_SCALE``
19+
- ``LOAD_NO_HINTING``
20+
- ``LOAD_RENDER``
21+
- ``LOAD_NO_BITMAP``
22+
- ``LOAD_VERTICAL_LAYOUT``
23+
- ``LOAD_FORCE_AUTOHINT``
24+
- ``LOAD_CROP_BITMAP``
25+
- ``LOAD_PEDANTIC``
26+
- ``LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH``
27+
- ``LOAD_NO_RECURSE``
28+
- ``LOAD_IGNORE_TRANSFORM``
29+
- ``LOAD_MONOCHROME``
30+
- ``LOAD_LINEAR_DESIGN``
31+
- ``LOAD_NO_AUTOHINT``
32+
- ``LOAD_TARGET_NORMAL``
33+
- ``LOAD_TARGET_LIGHT``
34+
- ``LOAD_TARGET_MONO``
35+
- ``LOAD_TARGET_LCD``
36+
- ``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/font_indexing.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
import os
1010

1111
import matplotlib
12-
from matplotlib.ft2font import (KERNING_DEFAULT, KERNING_UNFITTED,
13-
KERNING_UNSCALED, FT2Font)
12+
from matplotlib.ft2font import FT2Font, Kerning
1413

1514
font = FT2Font(
1615
os.path.join(matplotlib.get_data_path(), 'fonts/ttf/DejaVuSans.ttf'))
@@ -31,7 +30,7 @@
3130
glyph = font.load_char(code)
3231
print(glyph.bbox)
3332
print(glyphd['A'], glyphd['V'], coded['A'], coded['V'])
34-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_DEFAULT))
35-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_UNFITTED))
36-
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], KERNING_UNSCALED))
37-
print('AT', font.get_kerning(glyphd['A'], glyphd['T'], KERNING_UNSCALED))
33+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], Kerning.DEFAULT))
34+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], Kerning.UNFITTED))
35+
print('AV', font.get_kerning(glyphd['A'], glyphd['V'], Kerning.UNSCALED))
36+
print('AT', font.get_kerning(glyphd['A'], glyphd['T'], Kerning.UNSCALED))

galleries/examples/misc/ftface_props.py

Lines changed: 7 additions & 15 deletions
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/_mathtext.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from ._mathtext_data import (
3030
latex_to_bakoma, stix_glyph_fixes, stix_virtual_fonts, tex2uni)
3131
from .font_manager import FontProperties, findfont, get_font
32-
from .ft2font import FT2Font, FT2Image, KERNING_DEFAULT
32+
from .ft2font import FT2Font, FT2Image, Kerning, LoadFlags
3333

3434
from packaging.version import parse as parse_version
3535
from pyparsing import __version__ as pyparsing_version
@@ -227,14 +227,14 @@ class Fonts(abc.ABC):
227227
to do the actual drawing.
228228
"""
229229

230-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
230+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
231231
"""
232232
Parameters
233233
----------
234234
default_font_prop : `~.font_manager.FontProperties`
235235
The default non-math font, or the base font for Unicode (generic)
236236
font rendering.
237-
load_glyph_flags : int
237+
load_glyph_flags : `.ft2font.LoadFlags`
238238
Flags passed to the glyph loader (e.g. ``FT_Load_Glyph`` and
239239
``FT_Load_Char`` for FreeType-based fonts).
240240
"""
@@ -332,7 +332,7 @@ class TruetypeFonts(Fonts, metaclass=abc.ABCMeta):
332332
(through FT2Font).
333333
"""
334334

335-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
335+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
336336
super().__init__(default_font_prop, load_glyph_flags)
337337
# Per-instance cache.
338338
self._get_info = functools.cache(self._get_info) # type: ignore[method-assign]
@@ -426,7 +426,7 @@ def get_kern(self, font1: str, fontclass1: str, sym1: str, fontsize1: float,
426426
info1 = self._get_info(font1, fontclass1, sym1, fontsize1, dpi)
427427
info2 = self._get_info(font2, fontclass2, sym2, fontsize2, dpi)
428428
font = info1.font
429-
return font.get_kerning(info1.num, info2.num, KERNING_DEFAULT) / 64
429+
return font.get_kerning(info1.num, info2.num, Kerning.DEFAULT) / 64
430430
return super().get_kern(font1, fontclass1, sym1, fontsize1,
431431
font2, fontclass2, sym2, fontsize2, dpi)
432432

@@ -448,7 +448,7 @@ class BakomaFonts(TruetypeFonts):
448448
'ex': 'cmex10',
449449
}
450450

451-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
451+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
452452
self._stix_fallback = StixFonts(default_font_prop, load_glyph_flags)
453453

454454
super().__init__(default_font_prop, load_glyph_flags)
@@ -557,7 +557,7 @@ class UnicodeFonts(TruetypeFonts):
557557
0x2212: 0x00A1, # Minus sign.
558558
}
559559

560-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
560+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
561561
# This must come first so the backend's owner is set correctly
562562
fallback_rc = mpl.rcParams['mathtext.fallback']
563563
font_cls: type[TruetypeFonts] | None = {
@@ -672,7 +672,7 @@ def get_sized_alternatives_for_symbol(self, fontname: str,
672672
class DejaVuFonts(UnicodeFonts, metaclass=abc.ABCMeta):
673673
_fontmap: dict[str | int, str] = {}
674674

675-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
675+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
676676
# This must come first so the backend's owner is set correctly
677677
if isinstance(self, DejaVuSerifFonts):
678678
self._fallback_font = StixFonts(default_font_prop, load_glyph_flags)
@@ -776,7 +776,7 @@ class StixFonts(UnicodeFonts):
776776
_fallback_font = None
777777
_sans = False
778778

779-
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: int):
779+
def __init__(self, default_font_prop: FontProperties, load_glyph_flags: LoadFlags):
780780
TruetypeFonts.__init__(self, default_font_prop, load_glyph_flags)
781781
for key, name in self._fontmap.items():
782782
fullpath = findfont(name)

lib/matplotlib/_text_helpers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import dataclasses
88

99
from . import _api
10-
from .ft2font import KERNING_DEFAULT, LOAD_NO_HINTING, FT2Font
10+
from .ft2font import FT2Font, Kerning, LoadFlags
1111

1212

1313
@dataclasses.dataclass(frozen=True)
@@ -43,7 +43,7 @@ def warn_on_missing_glyph(codepoint, fontnames):
4343
f"Matplotlib currently does not support {block} natively.")
4444

4545

46-
def layout(string, font, *, kern_mode=KERNING_DEFAULT):
46+
def layout(string, font, *, kern_mode=Kerning.DEFAULT):
4747
"""
4848
Render *string* with *font*.
4949
@@ -56,7 +56,7 @@ def layout(string, font, *, kern_mode=KERNING_DEFAULT):
5656
The string to be rendered.
5757
font : FT2Font
5858
The font.
59-
kern_mode : int
59+
kern_mode : Kerning
6060
A FreeType kerning mode.
6161
6262
Yields
@@ -76,7 +76,7 @@ def layout(string, font, *, kern_mode=KERNING_DEFAULT):
7676
if prev_glyph_idx is not None else 0.
7777
)
7878
x += kern
79-
glyph = font.load_glyph(glyph_idx, flags=LOAD_NO_HINTING)
79+
glyph = font.load_glyph(glyph_idx, flags=LoadFlags.NO_HINTING)
8080
yield LayoutItem(font, char, glyph_idx, x, kern)
8181
x += glyph.linearHoriAdvance / 65536
8282
prev_glyph_idx = glyph_idx

lib/matplotlib/backends/_backend_pdf_ps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ def get_text_width_height_descent(self, s, prop, ismath):
161161
return w, h, d
162162
else:
163163
font = self._get_font_ttf(prop)
164-
font.set_text(s, 0.0, flags=ft2font.LOAD_NO_HINTING)
164+
font.set_text(s, 0.0, flags=ft2font.LoadFlags.NO_HINTING)
165165
w, h = font.get_width_height()
166166
d = font.get_descent()
167167
scale = 1 / 64

lib/matplotlib/backends/backend_agg.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@
3131
from matplotlib.backend_bases import (
3232
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase)
3333
from matplotlib.font_manager import fontManager as _fontManager, get_font
34-
from matplotlib.ft2font import (LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING,
35-
LOAD_DEFAULT, LOAD_NO_AUTOHINT)
34+
from matplotlib.ft2font import LoadFlags
3635
from matplotlib.mathtext import MathTextParser
3736
from matplotlib.path import Path
3837
from matplotlib.transforms import Bbox, BboxBase
@@ -41,16 +40,16 @@
4140

4241
def get_hinting_flag():
4342
mapping = {
44-
'default': LOAD_DEFAULT,
45-
'no_autohint': LOAD_NO_AUTOHINT,
46-
'force_autohint': LOAD_FORCE_AUTOHINT,
47-
'no_hinting': LOAD_NO_HINTING,
48-
True: LOAD_FORCE_AUTOHINT,
49-
False: LOAD_NO_HINTING,
50-
'either': LOAD_DEFAULT,
51-
'native': LOAD_NO_AUTOHINT,
52-
'auto': LOAD_FORCE_AUTOHINT,
53-
'none': LOAD_NO_HINTING,
43+
'default': LoadFlags.DEFAULT,
44+
'no_autohint': LoadFlags.NO_AUTOHINT,
45+
'force_autohint': LoadFlags.FORCE_AUTOHINT,
46+
'no_hinting': LoadFlags.NO_HINTING,
47+
True: LoadFlags.FORCE_AUTOHINT,
48+
False: LoadFlags.NO_HINTING,
49+
'either': LoadFlags.DEFAULT,
50+
'native': LoadFlags.NO_AUTOHINT,
51+
'auto': LoadFlags.FORCE_AUTOHINT,
52+
'none': LoadFlags.NO_HINTING,
5453
}
5554
return mapping[mpl.rcParams['text.hinting']]
5655

lib/matplotlib/backends/backend_pdf.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +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, LOAD_NO_SCALE,
39-
LOAD_NO_HINTING, KERNING_UNFITTED, FT2Font)
38+
from matplotlib.ft2font import FT2Font, FaceFlags, Kerning, LoadFlags, StyleFlags
4039
from matplotlib.transforms import Affine2D, BboxBase
4140
from matplotlib.path import Path
4241
from matplotlib.dates import UTC
@@ -617,7 +616,7 @@ def _get_pdf_charprocs(font_path, glyph_ids):
617616
conv = 1000 / font.units_per_EM # Conversion to PS units (1/1000's).
618617
procs = {}
619618
for glyph_id in glyph_ids:
620-
g = font.load_glyph(glyph_id, LOAD_NO_SCALE)
619+
g = font.load_glyph(glyph_id, LoadFlags.NO_SCALE)
621620
# NOTE: We should be using round(), but instead use
622621
# "(x+.5).astype(int)" to keep backcompat with the old ttconv code
623622
# (this is different for negative x's).
@@ -1185,7 +1184,7 @@ def embedTTFType3(font, characters, descriptor):
11851184
def get_char_width(charcode):
11861185
s = ord(cp1252.decoding_table[charcode])
11871186
width = font.load_char(
1188-
s, flags=LOAD_NO_SCALE | LOAD_NO_HINTING).horiAdvance
1187+
s, flags=LoadFlags.NO_SCALE | LoadFlags.NO_HINTING).horiAdvance
11891188
return cvt(width)
11901189
with warnings.catch_warnings():
11911190
# Ignore 'Required glyph missing from current font' warning
@@ -1322,7 +1321,7 @@ def embedTTFType42(font, characters, descriptor):
13221321
ccode = c
13231322
gind = font.get_char_index(ccode)
13241323
glyph = font.load_char(ccode,
1325-
flags=LOAD_NO_SCALE | LOAD_NO_HINTING)
1324+
flags=LoadFlags.NO_SCALE | LoadFlags.NO_HINTING)
13261325
widths.append((ccode, cvt(glyph.horiAdvance)))
13271326
if ccode < 65536:
13281327
cid_to_gid_map[ccode] = chr(gind)
@@ -1418,15 +1417,15 @@ def embedTTFType42(font, characters, descriptor):
14181417

14191418
flags = 0
14201419
symbolic = False # ps_name.name in ('Cmsy10', 'Cmmi10', 'Cmex10')
1421-
if ff & FIXED_WIDTH:
1420+
if FaceFlags.FIXED_WIDTH in ff:
14221421
flags |= 1 << 0
14231422
if 0: # TODO: serif
14241423
flags |= 1 << 1
14251424
if symbolic:
14261425
flags |= 1 << 2
14271426
else:
14281427
flags |= 1 << 5
1429-
if sf & ITALIC:
1428+
if StyleFlags.ITALIC in sf:
14301429
flags |= 1 << 6
14311430
if 0: # TODO: all caps
14321431
flags |= 1 << 16
@@ -2379,7 +2378,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
23792378
multibyte_glyphs = []
23802379
prev_was_multibyte = True
23812380
prev_font = font
2382-
for item in _text_helpers.layout(s, font, kern_mode=KERNING_UNFITTED):
2381+
for item in _text_helpers.layout(s, font, kern_mode=Kerning.UNFITTED):
23832382
if _font_supports_glyph(fonttype, ord(item.char)):
23842383
if prev_was_multibyte or item.ft_object != prev_font:
23852384
singlebyte_chunks.append((item.ft_object, item.x, []))

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
_Backend, FigureCanvasBase, FigureManagerBase, RendererBase)
3030
from matplotlib.cbook import is_writable_file_like, file_requires_unicode
3131
from matplotlib.font_manager import get_font
32-
from matplotlib.ft2font import LOAD_NO_SCALE
32+
from matplotlib.ft2font import LoadFlags
3333
from matplotlib._mathtext_data import uni2type1
3434
from matplotlib.path import Path
3535
from matplotlib.texmanager import TexManager
@@ -148,7 +148,7 @@ def _font_to_ps_type3(font_path, chars):
148148

149149
entries = []
150150
for glyph_id in glyph_ids:
151-
g = font.load_glyph(glyph_id, LOAD_NO_SCALE)
151+
g = font.load_glyph(glyph_id, LoadFlags.NO_SCALE)
152152
v, c = font.get_path()
153153
entries.append(
154154
"/%(name)s{%(bbox)s sc\n" % {

lib/matplotlib/font_manager.py

Lines changed: 2 additions & 2 deletions
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

0 commit comments

Comments
 (0)
0