Skip to content

Commit 72a7c33

Browse files
committed
Merge branch 'ttc-loading' into libraqm-full
2 parents 6c6ec62 + d86660b commit 72a7c33

22 files changed

+3363
-92
lines changed

lib/matplotlib/backends/_backend_pdf_ps.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def get_glyphs_subset(fontfile, glyphs):
2828
2929
Parameters
3030
----------
31-
fontfile : str
31+
fontfile : FontPath
3232
Path to the font file
3333
glyphs : set[int]
3434
Set of glyph IDs to include in subset.
@@ -66,8 +66,7 @@ def get_glyphs_subset(fontfile, glyphs):
6666
'xref', # The cross-reference table (some Apple font tooling information).
6767
]
6868
# if fontfile is a ttc, specify font number
69-
if fontfile.endswith(".ttc"):
70-
options.font_number = 0
69+
options.font_number = fontfile.face_index
7170

7271
font = subset.load_font(fontfile, options)
7372
subsetter = subset.Subsetter(options=options)
@@ -110,12 +109,14 @@ def track(self, font, s):
110109
"""Record that string *s* is being typeset using font *font*."""
111110
char_to_font = font._get_fontmap(s)
112111
for _c, _f in char_to_font.items():
112+
font_path = font_manager.FontPath(_f.fname, _f.face_index)
113113
glyph_index = _f.get_char_index(ord(_c))
114-
self.used.setdefault(_f.fname, set()).add(glyph_index)
114+
self.used.setdefault(font_path, set()).add(glyph_index)
115115

116116
def track_glyph(self, font, glyph):
117117
"""Record that glyph index *glyph* is being typeset using font *font*."""
118-
self.used.setdefault(font.fname, set()).add(glyph)
118+
font_path = font_manager.FontPath(font.fname, font.face_index)
119+
self.used.setdefault(font_path, set()).add(glyph)
119120

120121

121122
class RendererPDFPSBase(RendererBase):

lib/matplotlib/backends/backend_pdf.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
RendererBase)
3434
from matplotlib.backends.backend_mixed import MixedModeRenderer
3535
from matplotlib.figure import Figure
36-
from matplotlib.font_manager import get_font, fontManager as _fontManager
36+
from matplotlib.font_manager import FontPath, get_font, fontManager as _fontManager
3737
from matplotlib._afm import AFM
3838
from matplotlib.ft2font import FT2Font, FaceFlags, LoadFlags, StyleFlags
3939
from matplotlib.transforms import Affine2D, BboxBase
@@ -910,8 +910,10 @@ def fontName(self, fontprop):
910910
as the filename of the font.
911911
"""
912912

913-
if isinstance(fontprop, str):
913+
if isinstance(fontprop, FontPath):
914914
filenames = [fontprop]
915+
elif isinstance(fontprop, str):
916+
filenames = [FontPath(fontprop, 0)]
915917
elif mpl.rcParams['pdf.use14corefonts']:
916918
filenames = _fontManager._find_fonts_by_props(
917919
fontprop, fontext='afm', directory=RendererPdf._afm_font_dir
@@ -950,9 +952,8 @@ def writeFonts(self):
950952
for pdfname, dvifont in sorted(self._dviFontInfo.items()):
951953
_log.debug('Embedding Type-1 font %s from dvi.', dvifont.texname)
952954
fonts[pdfname] = self._embedTeXFont(dvifont)
953-
for filename in sorted(self._fontNames):
954-
Fx = self._fontNames[filename]
955-
_log.debug('Embedding font %s.', filename)
955+
for filename, Fx in sorted(self._fontNames.items()):
956+
_log.debug('Embedding font %r.', filename)
956957
if filename.endswith('.afm'):
957958
# from pdf.use14corefonts
958959
_log.debug('Writing AFM font.')
@@ -1004,7 +1005,8 @@ def _embedTeXFont(self, dvifont):
10041005

10051006
# Reduce the font to only the glyphs used in the document, get the encoding
10061007
# for that subset, and compute various properties based on the encoding.
1007-
chars = frozenset(self._character_tracker.used[dvifont.fname])
1008+
font_path = FontPath(dvifont.fname, dvifont.face_index)
1009+
chars = frozenset(self._character_tracker.used[font_path])
10081010
t1font = t1font.subset(chars, self._get_subset_prefix(chars))
10091011
fontdict['BaseFont'] = Name(t1font.prop['FontName'])
10101012
# createType1Descriptor writes the font data as a side effect
@@ -1113,6 +1115,7 @@ def _get_xobject_glyph_name(self, filename, glyph_name):
11131115
return "-".join([
11141116
Fx.name.decode(),
11151117
os.path.splitext(os.path.basename(filename))[0],
1118+
str(filename.face_index),
11161119
glyph_name])
11171120

11181121
_identityToUnicodeCMap = b"""/CIDInit /ProcSet findresource begin
@@ -1270,7 +1273,7 @@ def embedTTFType42(font, glyphs, descriptor):
12701273
with _backend_pdf_ps.get_glyphs_subset(filename, glyphs) as subset:
12711274
fontdata = _backend_pdf_ps.font_as_file(subset)
12721275
_log.debug(
1273-
"SUBSET %s %d -> %d", filename,
1276+
"SUBSET %r %d -> %d", filename,
12741277
os.stat(filename).st_size, fontdata.getbuffer().nbytes
12751278
)
12761279

@@ -2214,22 +2217,22 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
22142217
self.file.output(Op.begin_text)
22152218
for font, fontsize, glyph_index, ox, oy in glyphs:
22162219
self.file._character_tracker.track_glyph(font, glyph_index)
2217-
fontname = font.fname
2218-
if font not in font_charmaps:
2219-
font_charmaps[font] = {gind: ccode
2220-
for ccode, gind in font.get_charmap().items()}
2221-
ccode = font_charmaps[font].get(glyph_index)
2220+
font_path = FontPath(font.fname, font.face_index)
2221+
if font_path not in font_charmaps:
2222+
font_charmaps[font_path] = {
2223+
gind: ccode for ccode, gind in font.get_charmap().items()}
2224+
ccode = font_charmaps[font_path].get(glyph_index)
22222225
if ccode is None or not _font_supports_glyph(fonttype, ccode):
22232226
# Unsupported chars (i.e. multibyte in Type 3 or beyond BMP in
22242227
# Type 42) must be emitted separately (below).
22252228
unsupported_chars.append((font, fontsize, ox, oy, glyph_index))
22262229
else:
22272230
self._setup_textpos(ox, oy, 0, oldx, oldy)
22282231
oldx, oldy = ox, oy
2229-
if (fontname, fontsize) != prev_font:
2230-
self.file.output(self.file.fontName(fontname), fontsize,
2232+
if (font_path, fontsize) != prev_font:
2233+
self.file.output(self.file.fontName(font_path), fontsize,
22312234
Op.selectfont)
2232-
prev_font = fontname, fontsize
2235+
prev_font = font_path, fontsize
22332236
self.file.output(self.encode_string(chr(ccode), fonttype),
22342237
Op.show)
22352238
self.file.output(Op.end_text)
@@ -2419,7 +2422,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
24192422
self.file.output(Op.begin_text)
24202423
prev_start_x = 0
24212424
for ft_object, start_x, kerns_or_chars in singlebyte_chunks:
2422-
ft_name = self.file.fontName(ft_object.fname)
2425+
font_path = FontPath(ft_object.fname, ft_object.face_index)
2426+
ft_name = self.file.fontName(font_path)
24232427
self.file.output(ft_name, fontsize, Op.selectfont)
24242428
self._setup_textpos(start_x, 0, 0, prev_start_x, 0, 0)
24252429
self.file.output(
@@ -2441,7 +2445,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
24412445
def _draw_xobject_glyph(self, font, fontsize, glyph_index, x, y):
24422446
"""Draw a multibyte character from a Type 3 font as an XObject."""
24432447
glyph_name = font.get_glyph_name(glyph_index)
2444-
name = self.file._get_xobject_glyph_name(font.fname, glyph_name)
2448+
name = self.file._get_xobject_glyph_name(FontPath(font.fname, font.face_index),
2449+
glyph_name)
24452450
self.file.output(
24462451
Op.gsave,
24472452
0.001 * fontsize, 0, 0, 0.001 * fontsize, x, y, Op.concat_matrix,

lib/matplotlib/backends/backend_pgf.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,17 @@
3838

3939
def _get_preamble():
4040
"""Prepare a LaTeX preamble based on the rcParams configuration."""
41-
font_size_pt = FontProperties(
42-
size=mpl.rcParams["font.size"]
43-
).get_size_in_points()
41+
def _to_fontspec():
42+
for command, family in [("setmainfont", "serif"),
43+
("setsansfont", "sans\\-serif"),
44+
("setmonofont", "monospace")]:
45+
font_path = fm.findfont(family)
46+
path = pathlib.Path(font_path)
47+
yield r" \%s{%s}[Path=\detokenize{%s/}%s]" % (
48+
command, path.name, path.parent.as_posix(),
49+
f',FontIndex={font_path.face_index:d}' if path.suffix == '.ttc' else '')
50+
51+
font_size_pt = FontProperties(size=mpl.rcParams["font.size"]).get_size_in_points()
4452
return "\n".join([
4553
# Remove Matplotlib's custom command \mathdefault. (Not using
4654
# \mathnormal instead since this looks odd with Computer Modern.)
@@ -63,15 +71,8 @@ def _get_preamble():
6371
*([
6472
r"\ifdefined\pdftexversion\else % non-pdftex case.",
6573
r" \usepackage{fontspec}",
66-
] + [
67-
r" \%s{%s}[Path=\detokenize{%s/}]"
68-
% (command, path.name, path.parent.as_posix())
69-
for command, path in zip(
70-
["setmainfont", "setsansfont", "setmonofont"],
71-
[pathlib.Path(fm.findfont(family))
72-
for family in ["serif", "sans\\-serif", "monospace"]]
73-
)
74-
] + [r"\fi"] if mpl.rcParams["pgf.rcfonts"] else []),
74+
*_to_fontspec(),
75+
r"\fi"] if mpl.rcParams["pgf.rcfonts"] else []),
7576
# Documented as "must come last".
7677
mpl.texmanager._usepackage_if_not_loaded("underscore", option="strings"),
7778
])

lib/matplotlib/backends/backend_ps.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def _font_to_ps_type3(font_path, glyph_indices):
9494
9595
Parameters
9696
----------
97-
font_path : path-like
97+
font_path : FontPath
9898
Path to the font to be subsetted.
9999
glyph_indices : set[int]
100100
The glyphs to include in the subsetted font.
@@ -174,7 +174,7 @@ def _font_to_ps_type42(font_path, glyph_indices, fh):
174174
175175
Parameters
176176
----------
177-
font_path : path-like
177+
font_path : FontPath
178178
Path to the font to be subsetted.
179179
glyph_indices : set[int]
180180
The glyphs to include in the subsetted font.
@@ -183,12 +183,8 @@ def _font_to_ps_type42(font_path, glyph_indices, fh):
183183
"""
184184
_log.debug("SUBSET %s characters: %s", font_path, glyph_indices)
185185
try:
186-
kw = {}
187-
# fix this once we support loading more fonts from a collection
188-
# https://github.com/matplotlib/matplotlib/issues/3135#issuecomment-571085541
189-
if font_path.endswith('.ttc'):
190-
kw['fontNumber'] = 0
191-
with (fontTools.ttLib.TTFont(font_path, **kw) as font,
186+
with (fontTools.ttLib.TTFont(font_path.path,
187+
fontNumber=font_path.face_index) as font,
192188
_backend_pdf_ps.get_glyphs_subset(font_path, glyph_indices) as subset):
193189
fontdata = _backend_pdf_ps.font_as_file(subset).getvalue()
194190
_log.debug(

lib/matplotlib/dviread.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,10 @@ def fname(self):
610610
"""A fake filename"""
611611
return self.texname.decode('latin-1')
612612

613+
@property
614+
def face_index(self): # For compatibility with FT2Font.
615+
return 0
616+
613617
def _get_fontmap(self, string):
614618
"""Get the mapping from characters to the font that includes them.
615619

lib/matplotlib/dviread.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class DviFont:
7171
def widths(self) -> list[int]: ...
7272
@property
7373
def fname(self) -> str: ...
74+
@property
75+
def face_index(self) -> int: ...
7476

7577
class Vf(Dvi):
7678
def __init__(self, filename: str | os.PathLike) -> None: ...

0 commit comments

Comments
 (0)