From 9a7c2d8052f792056e412c05ee7eeba9708dd861 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 25 Jul 2025 01:20:05 -0400 Subject: [PATCH 1/6] Add os.PathLike support to FT2Font constructor, and FontManager Since we pass the filename to `io.open`, we can accept everything it can. Also, fix the return value of `FT2Font.fname`, which could be `bytes` if that was initially provided. --- lib/matplotlib/font_manager.py | 6 ++--- lib/matplotlib/font_manager.pyi | 14 +++++----- lib/matplotlib/ft2font.pyi | 5 ++-- lib/matplotlib/tests/test_font_manager.py | 33 ++++++++++++++++++----- lib/matplotlib/tests/test_ft2font.py | 22 +++++++++++++++ src/ft2font_wrapper.cpp | 13 +++++---- 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 79e088b85998..47339d4491dd 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -1611,10 +1611,10 @@ def get_font(font_filepaths, hinting_factor=None): Parameters ---------- - font_filepaths : Iterable[str, Path, bytes], str, Path, bytes + font_filepaths : Iterable[str, bytes, os.PathLike], str, bytes, os.PathLike Relative or absolute paths to the font files to be used. - If a single string, bytes, or `pathlib.Path`, then it will be treated + If a single string, bytes, or `os.PathLike`, then it will be treated as a list with that entry only. If more than one filepath is passed, then the returned FT2Font object @@ -1626,7 +1626,7 @@ def get_font(font_filepaths, hinting_factor=None): `.ft2font.FT2Font` """ - if isinstance(font_filepaths, (str, Path, bytes)): + if isinstance(font_filepaths, (str, bytes, os.PathLike)): paths = (_cached_realpath(font_filepaths),) else: paths = tuple(_cached_realpath(fname) for fname in font_filepaths) diff --git a/lib/matplotlib/font_manager.pyi b/lib/matplotlib/font_manager.pyi index e865f67384cd..f5e3910e5f63 100644 --- a/lib/matplotlib/font_manager.pyi +++ b/lib/matplotlib/font_manager.pyi @@ -24,7 +24,7 @@ def list_fonts(directory: str, extensions: Iterable[str]) -> list[str]: ... def win32FontDirectory() -> str: ... def _get_fontconfig_fonts() -> list[Path]: ... def findSystemFonts( - fontpaths: Iterable[str | os.PathLike | Path] | None = ..., fontext: str = ... + fontpaths: Iterable[str | os.PathLike] | None = ..., fontext: str = ... ) -> list[str]: ... @dataclass class FontEntry: @@ -50,7 +50,7 @@ class FontProperties: weight: int | str | None = ..., stretch: int | str | None = ..., size: float | str | None = ..., - fname: str | os.PathLike | Path | None = ..., + fname: str | os.PathLike | None = ..., math_fontfamily: str | None = ..., ) -> None: ... def __hash__(self) -> int: ... @@ -72,7 +72,7 @@ class FontProperties: def set_weight(self, weight: int | str | None) -> None: ... def set_stretch(self, stretch: int | str | None) -> None: ... def set_size(self, size: float | str | None) -> None: ... - def set_file(self, file: str | os.PathLike | Path | None) -> None: ... + def set_file(self, file: str | os.PathLike | None) -> None: ... def set_fontconfig_pattern(self, pattern: str) -> None: ... def get_math_fontfamily(self) -> str: ... def set_math_fontfamily(self, fontfamily: str | None) -> None: ... @@ -83,8 +83,8 @@ class FontProperties: set_slant = set_style get_size_in_points = get_size -def json_dump(data: FontManager, filename: str | Path | os.PathLike) -> None: ... -def json_load(filename: str | Path | os.PathLike) -> FontManager: ... +def json_dump(data: FontManager, filename: str | os.PathLike) -> None: ... +def json_load(filename: str | os.PathLike) -> FontManager: ... class FontManager: __version__: str @@ -93,7 +93,7 @@ class FontManager: afmlist: list[FontEntry] ttflist: list[FontEntry] def __init__(self, size: float | None = ..., weight: str = ...) -> None: ... - def addfont(self, path: str | Path | os.PathLike) -> None: ... + def addfont(self, path: str | os.PathLike) -> None: ... @property def defaultFont(self) -> dict[str, str]: ... def get_default_weight(self) -> str: ... @@ -120,7 +120,7 @@ class FontManager: def is_opentype_cff_font(filename: str) -> bool: ... def get_font( - font_filepaths: Iterable[str | Path | bytes] | str | Path | bytes, + font_filepaths: Iterable[str | bytes | os.PathLike] | str | bytes | os.PathLike, hinting_factor: int | None = ..., ) -> ft2font.FT2Font: ... diff --git a/lib/matplotlib/ft2font.pyi b/lib/matplotlib/ft2font.pyi index 5257893b380a..997d041c619a 100644 --- a/lib/matplotlib/ft2font.pyi +++ b/lib/matplotlib/ft2font.pyi @@ -1,4 +1,5 @@ from enum import Enum, Flag +from os import PathLike import sys from typing import BinaryIO, Literal, TypedDict, final, overload, cast from typing_extensions import Buffer # < Py 3.12 @@ -187,7 +188,7 @@ class _SfntPcltDict(TypedDict): class FT2Font(Buffer): def __init__( self, - filename: str | BinaryIO, + filename: str | bytes | PathLike | BinaryIO, hinting_factor: int = ..., *, _fallback_list: list[FT2Font] | None = ..., @@ -249,7 +250,7 @@ class FT2Font(Buffer): @property def family_name(self) -> str: ... @property - def fname(self) -> str: ... + def fname(self) -> str | bytes: ... @property def height(self) -> int: ... @property diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index b15647644e04..d51eb8d9837f 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -1,4 +1,4 @@ -from io import BytesIO, StringIO +from io import BytesIO import gc import multiprocessing import os @@ -137,6 +137,32 @@ def test_find_noto(): fig.savefig(BytesIO(), format=fmt) +def test_find_valid(): + class PathLikeClass: + def __init__(self, filename): + self.filename = filename + + def __fspath__(self): + return self.filename + + file_str = findfont('DejaVu Sans') + file_bytes = os.fsencode(file_str) + + font = get_font(file_str) + assert font.fname == file_str + font = get_font(file_bytes) + assert font.fname == file_bytes + font = get_font(PathLikeClass(file_str)) + assert font.fname == file_str + font = get_font(PathLikeClass(file_bytes)) + assert font.fname == file_bytes + + # Note, fallbacks are not currently accessible. + font = get_font([file_str, file_bytes, + PathLikeClass(file_str), PathLikeClass(file_bytes)]) + assert font.fname == file_str + + def test_find_invalid(tmp_path): with pytest.raises(FileNotFoundError): @@ -148,11 +174,6 @@ def test_find_invalid(tmp_path): with pytest.raises(FileNotFoundError): get_font(bytes(tmp_path / 'non-existent-font-name.ttf')) - # Not really public, but get_font doesn't expose non-filename constructor. - from matplotlib.ft2font import FT2Font - with pytest.raises(TypeError, match='font file or a binary-mode file'): - FT2Font(StringIO()) # type: ignore[arg-type] - @pytest.mark.skipif(sys.platform != 'linux' or not has_fclist, reason='only Linux with fontconfig installed') diff --git a/lib/matplotlib/tests/test_ft2font.py b/lib/matplotlib/tests/test_ft2font.py index 5dd96ce9cafe..80630d35e07b 100644 --- a/lib/matplotlib/tests/test_ft2font.py +++ b/lib/matplotlib/tests/test_ft2font.py @@ -1,5 +1,6 @@ import itertools import io +import os from pathlib import Path import numpy as np @@ -133,6 +134,27 @@ def test_ft2font_stix_bold_attrs(): assert font.bbox == (4, -355, 1185, 2095) +def test_ft2font_valid_args(): + class PathLikeClass: + def __init__(self, filename): + self.filename = filename + + def __fspath__(self): + return self.filename + + file_str = fm.findfont('DejaVu Sans') + file_bytes = os.fsencode(file_str) + + font = ft2font.FT2Font(file_str) + assert font.fname == file_str + font = ft2font.FT2Font(file_bytes) + assert font.fname == file_bytes + font = ft2font.FT2Font(PathLikeClass(file_str)) + assert font.fname == file_str + font = ft2font.FT2Font(PathLikeClass(file_bytes)) + assert font.fname == file_bytes + + def test_ft2font_invalid_args(tmp_path): # filename argument. with pytest.raises(TypeError, match='to a font file or a binary-mode file object'): diff --git a/src/ft2font_wrapper.cpp b/src/ft2font_wrapper.cpp index 5ba4bec36874..8df990752234 100644 --- a/src/ft2font_wrapper.cpp +++ b/src/ft2font_wrapper.cpp @@ -420,7 +420,7 @@ ft_glyph_warn(FT_ULong charcode, std::set family_names) const char *PyFT2Font_init__doc__ = R"""( Parameters ---------- - filename : str or file-like + filename : str, bytes, os.PathLike, or io.BinaryIO The source of the font data in a format (ttf or ttc) that FreeType can read. hinting_factor : int, optional @@ -481,7 +481,10 @@ PyFT2Font_init(py::object filename, long hinting_factor = 8, } } - if (py::isinstance(filename) || py::isinstance(filename)) { + auto PathLike = py::module_::import("os").attr("PathLike"); + if (py::isinstance(filename) || py::isinstance(filename) || + py::isinstance(filename, PathLike)) + { self->py_file = py::module_::import("io").attr("open")(filename, "rb"); self->stream.close = &close_file_callback; } else { @@ -507,13 +510,13 @@ PyFT2Font_init(py::object filename, long hinting_factor = 8, return self; } -static py::str +static py::object PyFT2Font_fname(PyFT2Font *self) { - if (self->stream.close) { // Called passed a filename to the constructor. + if (self->stream.close) { // User passed a filename to the constructor. return self->py_file.attr("name"); } else { - return py::cast(self->py_file); + return self->py_file; } } From c352088b98cf28d14be7edfe019e4661757f3f5b Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 18 Jul 2025 03:50:41 -0400 Subject: [PATCH 2/6] Expose face index when loading fonts This enables loading a non-initial font from collections (`.ttc` files). Currently exposed for `FT2Font`, only. --- lib/matplotlib/ft2font.pyi | 3 +++ lib/matplotlib/tests/test_ft2font.py | 18 ++++++++++++++++++ src/ft2font.cpp | 5 ++--- src/ft2font.h | 2 +- src/ft2font_wrapper.cpp | 21 ++++++++++++++++----- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/lib/matplotlib/ft2font.pyi b/lib/matplotlib/ft2font.pyi index 997d041c619a..eea180e4c7b5 100644 --- a/lib/matplotlib/ft2font.pyi +++ b/lib/matplotlib/ft2font.pyi @@ -191,6 +191,7 @@ class FT2Font(Buffer): filename: str | bytes | PathLike | BinaryIO, hinting_factor: int = ..., *, + face_index: int = ..., _fallback_list: list[FT2Font] | None = ..., _kerning_factor: int | None = ... ) -> None: ... @@ -248,6 +249,8 @@ class FT2Font(Buffer): @property def face_flags(self) -> FaceFlags: ... @property + def face_index(self) -> int: ... + @property def family_name(self) -> str: ... @property def fname(self) -> str | bytes: ... diff --git a/lib/matplotlib/tests/test_ft2font.py b/lib/matplotlib/tests/test_ft2font.py index 80630d35e07b..7ffc83f75e75 100644 --- a/lib/matplotlib/tests/test_ft2font.py +++ b/lib/matplotlib/tests/test_ft2font.py @@ -198,6 +198,24 @@ def test_ft2font_invalid_args(tmp_path): ft2font.FT2Font(file, _kerning_factor=123) +@pytest.mark.parametrize('name, size, skippable', + [('DejaVu Sans', 1, False), ('WenQuanYi Zen Hei', 3, True)]) +def test_ft2font_face_index(name, size, skippable): + try: + file = fm.findfont(name, fallback_to_default=False) + except ValueError: + if skippable: + pytest.skip(r'Font {name} may be missing') + raise + for index in range(size): + font = ft2font.FT2Font(file, face_index=index) + assert font.num_faces >= size + with pytest.raises(ValueError, match='must be between'): # out of bounds for spec + ft2font.FT2Font(file, face_index=0x1ffff) + with pytest.raises(RuntimeError, match='invalid argument'): # invalid for this font + ft2font.FT2Font(file, face_index=0xff) + + def test_ft2font_clear(): file = fm.findfont('DejaVu Sans') font = ft2font.FT2Font(file) diff --git a/src/ft2font.cpp b/src/ft2font.cpp index 1d03ecf10b56..24d965331228 100644 --- a/src/ft2font.cpp +++ b/src/ft2font.cpp @@ -207,8 +207,7 @@ FT2Font::get_path(std::vector &vertices, std::vector &cod codes.push_back(CLOSEPOLY); } -FT2Font::FT2Font(FT_Open_Args &open_args, - long hinting_factor_, +FT2Font::FT2Font(FT_Long face_index, FT_Open_Args &open_args, long hinting_factor_, std::vector &fallback_list, FT2Font::WarnFunc warn, bool warn_if_used) : ft_glyph_warn(warn), warn_if_used(warn_if_used), image({1, 1}), face(nullptr), @@ -217,7 +216,7 @@ FT2Font::FT2Font(FT_Open_Args &open_args, kerning_factor(0) { clear(); - FT_CHECK(FT_Open_Face, _ft2Library, &open_args, 0, &face); + FT_CHECK(FT_Open_Face, _ft2Library, &open_args, face_index, &face); if (open_args.stream != nullptr) { face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; } diff --git a/src/ft2font.h b/src/ft2font.h index 0881693e7557..161dc8b8938c 100644 --- a/src/ft2font.h +++ b/src/ft2font.h @@ -99,7 +99,7 @@ class FT2Font typedef void (*WarnFunc)(FT_ULong charcode, std::set family_names); public: - FT2Font(FT_Open_Args &open_args, long hinting_factor, + FT2Font(FT_Long face_index, FT_Open_Args &open_args, long hinting_factor, std::vector &fallback_list, WarnFunc warn, bool warn_if_used); virtual ~FT2Font(); diff --git a/src/ft2font_wrapper.cpp b/src/ft2font_wrapper.cpp index 8df990752234..d8c965c5d31b 100644 --- a/src/ft2font_wrapper.cpp +++ b/src/ft2font_wrapper.cpp @@ -426,6 +426,9 @@ const char *PyFT2Font_init__doc__ = R"""( hinting_factor : int, optional Must be positive. Used to scale the hinting in the x-direction. + face_index : int, optional + The index of the face in the font file to load. + _fallback_list : list of FT2Font, optional A list of FT2Font objects used to find missing glyphs. @@ -440,7 +443,7 @@ const char *PyFT2Font_init__doc__ = R"""( )"""; static PyFT2Font * -PyFT2Font_init(py::object filename, long hinting_factor = 8, +PyFT2Font_init(py::object filename, long hinting_factor = 8, FT_Long face_index = 0, std::optional> fallback_list = std::nullopt, std::optional kerning_factor = std::nullopt, bool warn_if_used = false) @@ -456,6 +459,10 @@ PyFT2Font_init(py::object filename, long hinting_factor = 8, kerning_factor = 0; } + if (face_index < 0 || face_index >= 1<<16) { + throw std::range_error("face_index must be between 0 and 65535, inclusive"); + } + PyFT2Font *self = new PyFT2Font(); self->x = nullptr; memset(&self->stream, 0, sizeof(FT_StreamRec)); @@ -502,8 +509,8 @@ PyFT2Font_init(py::object filename, long hinting_factor = 8, self->stream.close = nullptr; } - self->x = new FT2Font(open_args, hinting_factor, fallback_fonts, ft_glyph_warn, - warn_if_used); + self->x = new FT2Font(face_index, open_args, hinting_factor, fallback_fonts, + ft_glyph_warn, warn_if_used); self->x->set_kerning_factor(*kerning_factor); @@ -1609,7 +1616,7 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used()) auto cls = py::class_(m, "FT2Font", py::is_final(), py::buffer_protocol(), PyFT2Font__doc__) .def(py::init(&PyFT2Font_init), - "filename"_a, "hinting_factor"_a=8, py::kw_only(), + "filename"_a, "hinting_factor"_a=8, py::kw_only(), "face_index"_a=0, "_fallback_list"_a=py::none(), "_kerning_factor"_a=py::none(), "_warn_if_used"_a=false, PyFT2Font_init__doc__) @@ -1682,8 +1689,12 @@ PYBIND11_MODULE(ft2font, m, py::mod_gil_not_used()) }, "PostScript name of the font.") .def_property_readonly( "num_faces", [](PyFT2Font *self) { - return self->x->get_face()->num_faces; + return self->x->get_face()->num_faces & 0xffff; }, "Number of faces in file.") + .def_property_readonly( + "face_index", [](PyFT2Font *self) { + return self->x->get_face()->face_index; + }, "The index of the font in the file.") .def_property_readonly( "family_name", [](PyFT2Font *self) { if (const char *name = self->x->get_face()->family_name) { From 24c1576c6944cc6d0e9cde6a1565a197afd4d139 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 18 Jul 2025 04:51:05 -0400 Subject: [PATCH 3/6] Parse data from all fonts within a collection This should allow listing the metadata from the whole collection, which will also pick the right one if specified, though it will not load the specific index yet. --- lib/matplotlib/font_manager.py | 12 +++++++++--- lib/matplotlib/font_manager.pyi | 1 + lib/matplotlib/tests/test_font_manager.py | 11 ++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index 47339d4491dd..e9aac793ce4c 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -319,6 +319,7 @@ class FontEntry: """ fname: str = '' + index: int = 0 name: str = '' style: str = 'normal' variant: str = 'normal' @@ -465,7 +466,8 @@ def get_weight(): # From fontconfig's FcFreeTypeQueryFaceInternal. raise NotImplementedError("Non-scalable fonts are not supported") size = 'scalable' - return FontEntry(font.fname, name, style, variant, weight, stretch, size) + return FontEntry(font.fname, font.face_index, name, + style, variant, weight, stretch, size) def afmFontProperty(fontpath, font): @@ -535,7 +537,7 @@ def afmFontProperty(fontpath, font): size = 'scalable' - return FontEntry(fontpath, name, style, variant, weight, stretch, size) + return FontEntry(fontpath, 0, name, style, variant, weight, stretch, size) def _cleanup_fontproperties_init(init_method): @@ -1069,7 +1071,7 @@ class FontManager: # Increment this version number whenever the font cache data # format or behavior has changed and requires an existing font # cache files to be rebuilt. - __version__ = '3.11.0a1' + __version__ = '3.11.0a2' def __init__(self, size=None, weight='normal'): self._version = self.__version__ @@ -1134,6 +1136,10 @@ def addfont(self, path): font = ft2font.FT2Font(path) prop = ttfFontProperty(font) self.ttflist.append(prop) + for face_index in range(1, font.num_faces): + subfont = ft2font.FT2Font(path, face_index=face_index) + prop = ttfFontProperty(subfont) + self.ttflist.append(prop) self._findfont_cached.cache_clear() @property diff --git a/lib/matplotlib/font_manager.pyi b/lib/matplotlib/font_manager.pyi index f5e3910e5f63..6b072f707f66 100644 --- a/lib/matplotlib/font_manager.pyi +++ b/lib/matplotlib/font_manager.pyi @@ -29,6 +29,7 @@ def findSystemFonts( @dataclass class FontEntry: fname: str = ... + index: int = ... name: str = ... style: str = ... variant: str = ... diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index d51eb8d9837f..6301163b4527 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -117,8 +117,13 @@ def test_utf16m_sfnt(): def test_find_ttc(): fp = FontProperties(family=["WenQuanYi Zen Hei"]) - if Path(findfont(fp)).name != "wqy-zenhei.ttc": + fontpath = findfont(fp) + if Path(fontpath).name != "wqy-zenhei.ttc": pytest.skip("Font wqy-zenhei.ttc may be missing") + # All fonts from this collection should have loaded as well. + for name in ["WenQuanYi Zen Hei Mono", "WenQuanYi Zen Hei Sharp"]: + assert findfont(FontProperties(family=[name]), + fallback_to_default=False) == fontpath fig, ax = plt.subplots() ax.text(.5, .5, "\N{KANGXI RADICAL DRAGON}", fontproperties=fp) for fmt in ["raw", "svg", "pdf", "ps"]: @@ -363,6 +368,10 @@ def test_get_font_names(): font = ft2font.FT2Font(path) prop = ttfFontProperty(font) ttf_fonts.append(prop.name) + for face_index in range(1, font.num_faces): + font = ft2font.FT2Font(path, face_index=face_index) + prop = ttfFontProperty(font) + ttf_fonts.append(prop.name) except Exception: pass available_fonts = sorted(list(set(ttf_fonts))) From 1f2b3309a9981dbb02e770757f985b83424a65db Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 25 Jul 2025 03:33:54 -0400 Subject: [PATCH 4/6] Implement loading of any font in a collection For backwards-compatibility, the path+index is passed around in a lightweight subclass of `str`. --- lib/matplotlib/font_manager.py | 89 +++++++++++++++++++---- lib/matplotlib/font_manager.pyi | 19 ++++- lib/matplotlib/tests/test_font_manager.py | 44 ++++++++++- 3 files changed, 133 insertions(+), 19 deletions(-) diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py index e9aac793ce4c..6810fa8a8930 100644 --- a/lib/matplotlib/font_manager.py +++ b/lib/matplotlib/font_manager.py @@ -310,6 +310,61 @@ def findSystemFonts(fontpaths=None, fontext='ttf'): return [fname for fname in fontfiles if os.path.exists(fname)] +class FontPath(str): + """ + A class to describe a path to a font with a face index. + + Parameters + ---------- + path : str + The path to a font. + face_index : int + The face index in the font. + """ + + __match_args__ = ('path', 'face_index') + + def __new__(cls, path, face_index): + ret = super().__new__(cls, path) + ret._face_index = face_index + return ret + + @property + def path(self): + """The path to a font.""" + return str(self) + + @property + def face_index(self): + """The face index in a font.""" + return self._face_index + + def _as_tuple(self): + return (self.path, self.face_index) + + def __eq__(self, other): + if isinstance(other, FontPath): + return self._as_tuple() == other._as_tuple() + return super().__eq__(other) + + def __ne__(self, other): + return not (self == other) + + def __lt__(self, other): + if isinstance(other, FontPath): + return self._as_tuple() < other._as_tuple() + return super().__lt__(other) + + def __gt__(self, other): + return not (self == other or self < other) + + def __hash__(self): + return hash(self._as_tuple()) + + def __repr__(self): + return f'FontPath{self._as_tuple()}' + + @dataclasses.dataclass(frozen=True) class FontEntry: """ @@ -1326,7 +1381,7 @@ def findfont(self, prop, fontext='ttf', directory=None, Returns ------- - str + FontPath The filename of the best matching font. Notes @@ -1396,7 +1451,7 @@ def _find_fonts_by_props(self, prop, fontext='ttf', directory=None, Returns ------- - list[str] + list[FontPath] The paths of the fonts found. Notes @@ -1542,7 +1597,7 @@ def _findfont_cached(self, prop, fontext, directory, fallback_to_default, # actually raised. return cbook._ExceptionInfo(ValueError, "No valid font could be found") - return _cached_realpath(result) + return FontPath(_cached_realpath(result), best_font.index) @_api.deprecated("3.11") @@ -1562,15 +1617,16 @@ def is_opentype_cff_font(filename): @lru_cache(64) def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id, enable_last_resort): - first_fontpath, *rest = font_filepaths + (first_fontpath, first_fontindex), *rest = font_filepaths fallback_list = [ - ft2font.FT2Font(fpath, hinting_factor, _kerning_factor=_kerning_factor) - for fpath in rest + ft2font.FT2Font(fpath, hinting_factor, face_index=index, + _kerning_factor=_kerning_factor) + for fpath, index in rest ] last_resort_path = _cached_realpath( cbook._get_data_path('fonts', 'ttf', 'LastResortHE-Regular.ttf')) try: - last_resort_index = font_filepaths.index(last_resort_path) + last_resort_index = font_filepaths.index((last_resort_path, 0)) except ValueError: last_resort_index = -1 # Add Last Resort font so we always have glyphs regardless of font, unless we're @@ -1582,7 +1638,7 @@ def _get_font(font_filepaths, hinting_factor, *, _kerning_factor, thread_id, _warn_if_used=True)) last_resort_index = len(fallback_list) font = ft2font.FT2Font( - first_fontpath, hinting_factor, + first_fontpath, hinting_factor, face_index=first_fontindex, _fallback_list=fallback_list, _kerning_factor=_kerning_factor ) @@ -1617,7 +1673,8 @@ def get_font(font_filepaths, hinting_factor=None): Parameters ---------- - font_filepaths : Iterable[str, bytes, os.PathLike], str, bytes, os.PathLike + font_filepaths : Iterable[str, bytes, os.PathLike, FontPath], \ +str, bytes, os.PathLike, FontPath Relative or absolute paths to the font files to be used. If a single string, bytes, or `os.PathLike`, then it will be treated @@ -1632,10 +1689,16 @@ def get_font(font_filepaths, hinting_factor=None): `.ft2font.FT2Font` """ - if isinstance(font_filepaths, (str, bytes, os.PathLike)): - paths = (_cached_realpath(font_filepaths),) - else: - paths = tuple(_cached_realpath(fname) for fname in font_filepaths) + match font_filepaths: + case FontPath(path, index): + paths = ((_cached_realpath(path), index), ) + case str() | bytes() | os.PathLike() as path: + paths = ((_cached_realpath(path), 0), ) + case _: + paths = tuple( + (_cached_realpath(fname.path), fname.face_index) + if isinstance(fname, FontPath) else (_cached_realpath(fname), 0) + for fname in font_filepaths) hinting_factor = mpl._val_or_rc(hinting_factor, 'text.hinting_factor') diff --git a/lib/matplotlib/font_manager.pyi b/lib/matplotlib/font_manager.pyi index 6b072f707f66..47ee194c671a 100644 --- a/lib/matplotlib/font_manager.pyi +++ b/lib/matplotlib/font_manager.pyi @@ -3,7 +3,7 @@ from dataclasses import dataclass from numbers import Integral import os from pathlib import Path -from typing import Any, Literal +from typing import Any, Final, Literal from matplotlib._afm import AFM from matplotlib import ft2font @@ -26,6 +26,19 @@ def _get_fontconfig_fonts() -> list[Path]: ... def findSystemFonts( fontpaths: Iterable[str | os.PathLike] | None = ..., fontext: str = ... ) -> list[str]: ... + +class FontPath(str): + __match_args__: Final[tuple[str, ...]] + def __new__(cls: type[str], path: str, face_index: int) -> FontPath: ... + @property + def path(self) -> str: ... + @property + def face_index(self) -> int: ... + def _as_tuple(self) -> tuple[str, int]: ... + def __eq__(self, other: Any) -> bool: ... + def __hash__(self) -> int: ... + def __repr__(self) -> str: ... + @dataclass class FontEntry: fname: str = ... @@ -116,12 +129,12 @@ class FontManager: directory: str | None = ..., fallback_to_default: bool = ..., rebuild_if_missing: bool = ..., - ) -> str: ... + ) -> FontPath: ... def get_font_names(self) -> list[str]: ... def is_opentype_cff_font(filename: str) -> bool: ... def get_font( - font_filepaths: Iterable[str | bytes | os.PathLike] | str | bytes | os.PathLike, + font_filepaths: Iterable[str | bytes | os.PathLike | FontPath] | str | bytes | os.PathLike | FontPath, hinting_factor: int | None = ..., ) -> ft2font.FT2Font: ... diff --git a/lib/matplotlib/tests/test_font_manager.py b/lib/matplotlib/tests/test_font_manager.py index 6301163b4527..cc8ae03a9f97 100644 --- a/lib/matplotlib/tests/test_font_manager.py +++ b/lib/matplotlib/tests/test_font_manager.py @@ -13,7 +13,7 @@ import matplotlib as mpl from matplotlib.font_manager import ( - findfont, findSystemFonts, FontEntry, FontProperties, fontManager, + findfont, findSystemFonts, FontEntry, FontPath, FontProperties, fontManager, json_dump, json_load, get_font, is_opentype_cff_font, MSUserFontDirectories, ttfFontProperty, _get_fontconfig_fonts, _normalize_weight) @@ -24,6 +24,38 @@ has_fclist = shutil.which('fc-list') is not None +def test_font_path(): + fp = FontPath('foo', 123) + fp2 = FontPath('foo', 321) + assert str(fp) == 'foo' + assert repr(fp) == "FontPath('foo', 123)" + assert fp.path == 'foo' + assert fp.face_index == 123 + # Should be immutable. + with pytest.raises(AttributeError, match='has no setter'): + fp.path = 'bar' + with pytest.raises(AttributeError, match='has no setter'): + fp.face_index = 321 + # Should be comparable with str and itself. + assert fp == 'foo' + assert fp == FontPath('foo', 123) + assert fp <= fp + assert fp >= fp + assert fp != fp2 + assert fp < fp2 + assert fp <= fp2 + assert fp2 > fp + assert fp2 >= fp + # Should be hashable, but not the same as str. + d = {fp: 1, 'bar': 2} + assert fp in d + assert d[fp] == 1 + assert d[FontPath('foo', 123)] == 1 + assert fp2 not in d + assert 'foo' not in d + assert FontPath('bar', 0) not in d + + def test_font_priority(): with rc_context(rc={ 'font.sans-serif': @@ -122,8 +154,12 @@ def test_find_ttc(): pytest.skip("Font wqy-zenhei.ttc may be missing") # All fonts from this collection should have loaded as well. for name in ["WenQuanYi Zen Hei Mono", "WenQuanYi Zen Hei Sharp"]: - assert findfont(FontProperties(family=[name]), - fallback_to_default=False) == fontpath + subfontpath = findfont(FontProperties(family=[name]), fallback_to_default=False) + assert subfontpath.path == fontpath.path + assert subfontpath.face_index != fontpath.face_index + subfont = get_font(subfontpath) + assert subfont.fname == subfontpath.path + assert subfont.face_index == subfontpath.face_index fig, ax = plt.subplots() ax.text(.5, .5, "\N{KANGXI RADICAL DRAGON}", fontproperties=fp) for fmt in ["raw", "svg", "pdf", "ps"]: @@ -161,6 +197,8 @@ def __fspath__(self): assert font.fname == file_str font = get_font(PathLikeClass(file_bytes)) assert font.fname == file_bytes + font = get_font(FontPath(file_str, 0)) + assert font.fname == file_str # Note, fallbacks are not currently accessible. font = get_font([file_str, file_bytes, From 1bc92f0df6ad9cced8bf62b8aefc90ee2e8719f4 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 25 Jul 2025 06:13:59 -0400 Subject: [PATCH 5/6] pdf/ps: Support any font in a collection --- lib/matplotlib/backends/_backend_pdf_ps.py | 11 +- lib/matplotlib/backends/backend_pdf.py | 33 +- lib/matplotlib/backends/backend_ps.py | 14 +- lib/matplotlib/dviread.py | 4 + lib/matplotlib/dviread.pyi | 2 + .../test_backend_pdf/ttc_type3.pdf | Bin 0 -> 21114 bytes .../test_backend_pdf/ttc_type42.pdf | Bin 0 -> 9696 bytes .../test_backend_ps/ttc_type3.eps | 1483 +++++++++++++++++ .../test_backend_ps/ttc_type42.eps | 1483 +++++++++++++++++ lib/matplotlib/tests/test_backend_pdf.py | 35 +- lib/matplotlib/tests/test_backend_ps.py | 36 +- 11 files changed, 3071 insertions(+), 30 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type3.pdf create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type42.pdf create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type3.eps create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type42.eps diff --git a/lib/matplotlib/backends/_backend_pdf_ps.py b/lib/matplotlib/backends/_backend_pdf_ps.py index a2a878d54156..6e0a348c3d88 100644 --- a/lib/matplotlib/backends/_backend_pdf_ps.py +++ b/lib/matplotlib/backends/_backend_pdf_ps.py @@ -28,7 +28,7 @@ def get_glyphs_subset(fontfile, characters): Parameters ---------- - fontfile : str + fontfile : FontPath Path to the font file characters : str Continuous set of characters to include in subset @@ -66,8 +66,7 @@ def get_glyphs_subset(fontfile, characters): 'xref', # The cross-reference table (some Apple font tooling information). ] # if fontfile is a ttc, specify font number - if fontfile.endswith(".ttc"): - options.font_number = 0 + options.font_number = fontfile.face_index font = subset.load_font(fontfile, options) subsetter = subset.Subsetter(options=options) @@ -110,11 +109,13 @@ def track(self, font, s): """Record that string *s* is being typeset using font *font*.""" char_to_font = font._get_fontmap(s) for _c, _f in char_to_font.items(): - self.used.setdefault(_f.fname, set()).add(ord(_c)) + font_path = font_manager.FontPath(_f.fname, _f.face_index) + self.used.setdefault(font_path, set()).add(ord(_c)) def track_glyph(self, font, glyph): """Record that codepoint *glyph* is being typeset using font *font*.""" - self.used.setdefault(font.fname, set()).add(glyph) + font_path = font_manager.FontPath(font.fname, font.face_index) + self.used.setdefault(font_path, set()).add(glyph) class RendererPDFPSBase(RendererBase): diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index ff351e301176..2e1054e887f2 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -33,7 +33,7 @@ RendererBase) from matplotlib.backends.backend_mixed import MixedModeRenderer from matplotlib.figure import Figure -from matplotlib.font_manager import get_font, fontManager as _fontManager +from matplotlib.font_manager import FontPath, get_font, fontManager as _fontManager from matplotlib._afm import AFM from matplotlib.ft2font import FT2Font, FaceFlags, Kerning, LoadFlags, StyleFlags from matplotlib.transforms import Affine2D, BboxBase @@ -910,8 +910,10 @@ def fontName(self, fontprop): as the filename of the font. """ - if isinstance(fontprop, str): + if isinstance(fontprop, FontPath): filenames = [fontprop] + elif isinstance(fontprop, str): + filenames = [FontPath(fontprop, 0)] elif mpl.rcParams['pdf.use14corefonts']: filenames = _fontManager._find_fonts_by_props( fontprop, fontext='afm', directory=RendererPdf._afm_font_dir @@ -950,9 +952,8 @@ def writeFonts(self): for pdfname, dvifont in sorted(self._dviFontInfo.items()): _log.debug('Embedding Type-1 font %s from dvi.', dvifont.texname) fonts[pdfname] = self._embedTeXFont(dvifont) - for filename in sorted(self._fontNames): - Fx = self._fontNames[filename] - _log.debug('Embedding font %s.', filename) + for filename, Fx in sorted(self._fontNames.items()): + _log.debug('Embedding font %r.', filename) if filename.endswith('.afm'): # from pdf.use14corefonts _log.debug('Writing AFM font.') @@ -1004,7 +1005,8 @@ def _embedTeXFont(self, dvifont): # Reduce the font to only the glyphs used in the document, get the encoding # for that subset, and compute various properties based on the encoding. - chars = frozenset(self._character_tracker.used[dvifont.fname]) + font_path = FontPath(dvifont.fname, dvifont.face_index) + chars = frozenset(self._character_tracker.used[font_path]) t1font = t1font.subset(chars, self._get_subset_prefix(chars)) fontdict['BaseFont'] = Name(t1font.prop['FontName']) # createType1Descriptor writes the font data as a side effect @@ -1113,6 +1115,7 @@ def _get_xobject_glyph_name(self, filename, glyph_name): return "-".join([ Fx.name.decode(), os.path.splitext(os.path.basename(filename))[0], + str(filename.face_index), glyph_name]) _identityToUnicodeCMap = b"""/CIDInit /ProcSet findresource begin @@ -1270,11 +1273,11 @@ def embedTTFType42(font, characters, descriptor): toUnicodeMapObject = self.reserveObject('ToUnicode map') subset_str = "".join(chr(c) for c in characters) - _log.debug("SUBSET %s characters: %s", filename, subset_str) + _log.debug("SUBSET %r characters: %s", filename, subset_str) with _backend_pdf_ps.get_glyphs_subset(filename, subset_str) as subset: fontdata = _backend_pdf_ps.font_as_file(subset) _log.debug( - "SUBSET %s %d -> %d", filename, + "SUBSET %r %d -> %d", filename, os.stat(filename).st_size, fontdata.getbuffer().nbytes ) @@ -2218,7 +2221,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle): self.file.output(Op.begin_text) for font, fontsize, num, ox, oy in glyphs: self.file._character_tracker.track_glyph(font, num) - fontname = font.fname + font_path = FontPath(font.fname, font.face_index) if not _font_supports_glyph(fonttype, num): # Unsupported chars (i.e. multibyte in Type 3 or beyond BMP in # Type 42) must be emitted separately (below). @@ -2226,10 +2229,10 @@ def draw_mathtext(self, gc, x, y, s, prop, angle): else: self._setup_textpos(ox, oy, 0, oldx, oldy) oldx, oldy = ox, oy - if (fontname, fontsize) != prev_font: - self.file.output(self.file.fontName(fontname), fontsize, + if (font_path, fontsize) != prev_font: + self.file.output(self.file.fontName(font_path), fontsize, Op.selectfont) - prev_font = fontname, fontsize + prev_font = font_path, fontsize self.file.output(self.encode_string(chr(num), fonttype), Op.show) self.file.output(Op.end_text) @@ -2413,7 +2416,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): self.file.output(Op.begin_text) prev_start_x = 0 for ft_object, start_x, kerns_or_chars in singlebyte_chunks: - ft_name = self.file.fontName(ft_object.fname) + font_path = FontPath(ft_object.fname, ft_object.face_index) + ft_name = self.file.fontName(font_path) self.file.output(ft_name, fontsize, Op.selectfont) self._setup_textpos(start_x, 0, 0, prev_start_x, 0, 0) self.file.output( @@ -2435,7 +2439,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): def _draw_xobject_glyph(self, font, fontsize, glyph_idx, x, y): """Draw a multibyte character from a Type 3 font as an XObject.""" glyph_name = font.get_glyph_name(glyph_idx) - name = self.file._get_xobject_glyph_name(font.fname, glyph_name) + name = self.file._get_xobject_glyph_name(FontPath(font.fname, font.face_index), + glyph_name) self.file.output( Op.gsave, 0.001 * fontsize, 0, 0, 0.001 * fontsize, x, y, Op.concat_matrix, diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py index 368564a1518d..06c1deb8e5da 100644 --- a/lib/matplotlib/backends/backend_ps.py +++ b/lib/matplotlib/backends/backend_ps.py @@ -94,7 +94,7 @@ def _font_to_ps_type3(font_path, chars): Parameters ---------- - font_path : path-like + font_path : FontPath Path to the font to be subsetted. chars : str The characters to include in the subsetted font. @@ -175,7 +175,7 @@ def _font_to_ps_type42(font_path, chars, fh): Parameters ---------- - font_path : path-like + font_path : FontPath Path to the font to be subsetted. chars : str The characters to include in the subsetted font. @@ -183,14 +183,10 @@ def _font_to_ps_type42(font_path, chars, fh): Where to write the font. """ subset_str = ''.join(chr(c) for c in chars) - _log.debug("SUBSET %s characters: %s", font_path, subset_str) + _log.debug("SUBSET %r characters: %s", font_path, subset_str) try: - kw = {} - # fix this once we support loading more fonts from a collection - # https://github.com/matplotlib/matplotlib/issues/3135#issuecomment-571085541 - if font_path.endswith('.ttc'): - kw['fontNumber'] = 0 - with (fontTools.ttLib.TTFont(font_path, **kw) as font, + with (fontTools.ttLib.TTFont(font_path.path, + fontNumber=font_path.face_index) as font, _backend_pdf_ps.get_glyphs_subset(font_path, subset_str) as subset): fontdata = _backend_pdf_ps.font_as_file(subset).getvalue() _log.debug( diff --git a/lib/matplotlib/dviread.py b/lib/matplotlib/dviread.py index 9e8b6a5facf5..245c19db62fb 100644 --- a/lib/matplotlib/dviread.py +++ b/lib/matplotlib/dviread.py @@ -610,6 +610,10 @@ def fname(self): """A fake filename""" return self.texname.decode('latin-1') + @property + def face_index(self): # For compatibility with FT2Font. + return 0 + def _get_fontmap(self, string): """Get the mapping from characters to the font that includes them. diff --git a/lib/matplotlib/dviread.pyi b/lib/matplotlib/dviread.pyi index 82c0238d39d1..fdacbe751314 100644 --- a/lib/matplotlib/dviread.pyi +++ b/lib/matplotlib/dviread.pyi @@ -68,6 +68,8 @@ class DviFont: def widths(self) -> list[int]: ... @property def fname(self) -> str: ... + @property + def face_index(self) -> int: ... class Vf(Dvi): def __init__(self, filename: str | os.PathLike) -> None: ... diff --git a/lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type3.pdf b/lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a3fad017236451b768f01358368b601991bf5cf8 GIT binary patch literal 21114 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 Ch|0hK literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type42.pdf b/lib/matplotlib/tests/baseline_images/test_backend_pdf/ttc_type42.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d43f233ef4e6bba524f535b400d38f7fe5a45bac GIT binary patch literal 9696 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 LJG-2QJn?@4aq!mr literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type3.eps b/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type3.eps new file mode 100644 index 000000000000..e066abad29f5 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type3.eps @@ -0,0 +1,1483 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%LanguageLevel: 3 +%%Title: ttc_type3.eps +%%Creator: Matplotlib v3.11.0.dev1121+gba80e42970.d20250725, https://matplotlib.org/ +%%CreationDate: Fri Jul 25 06:03:10 2025 +%%Orientation: portrait +%%BoundingBox: 0 0 504 72 +%%HiResBoundingBox: 0.000000 0.000000 504.000000 72.000000 +%%EndComments +%%BeginProlog +/mpldict 10 dict def +mpldict begin +/_d { bind def } bind def +/m { moveto } _d +/l { lineto } _d +/r { rlineto } _d +/c { curveto } _d +/cl { closepath } _d +/ce { closepath eofill } _d +/sc { setcachedevice } _d +%!PS-Adobe-3.0 Resource-Font +%%Creator: Converted from TrueType to Type 3 by Matplotlib. +10 dict begin +/FontName /WenQuanYiZenHei def +/PaintType 0 def +/FontMatrix [0.0009765625 0 0 0.0009765625 0 0] def +/FontBBox [-129 -304 1076 986] def +/FontType 3 def +/Encoding [/space /colon /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /a /e /i /n /u] def +/CharStrings 34 dict dup begin +/.notdef 0 def +/space{307 0 0 0 0 0 sc +ce} _d +/colon{307 0 101 0 215 520 sc +215 404 m +101 404 l +101 520 l +215 520 l +215 404 l + +215 0 m +101 0 l +101 116 l +215 116 l +215 0 l + +ce} _d +/A{573 0 11 0 568 702 sc +568 0 m +478 0 l +408 205 l +147 205 l +85 0 l +11 0 l +239 702 l +340 702 l +568 0 l + +388 271 m +281 608 l +172 271 l +388 271 l + +ce} _d +/B{634 0 83 0 588 702 sc +588 194 m +588 130 565 80 520 45 c +484 16 434 1 370 0 c +347 0 l +83 0 l +83 702 l +348 702 l +405 702 448 694 477 679 c +482 676 487 673 493 670 c +541 637 565 591 566 531 c +566 470 542 424 494 394 c +462 380 l +456 377 449 375 442 374 c +442 372 l +501 359 543 327 568 276 c +581 251 588 224 588 194 c + +479 520 m +479 585 443 621 370 630 c +361 631 351 631 341 631 c +171 631 l +171 401 l +317 401 l +425 401 479 441 479 520 c + +500 198 m +500 241 485 276 454 303 c +453 304 451 306 449 307 c +426 325 389 334 338 334 c +171 334 l +171 75 l +343 75 l +432 75 483 105 497 166 c +499 175 500 186 500 198 c + +ce} _d +/C{634 0 43 -10 589 713 sc +589 219 m +558 90 490 16 386 -5 c +367 -8 348 -10 329 -10 c +224 -10 146 38 94 135 c +60 199 43 273 43 358 c +43 471 72 560 131 626 c +183 684 251 713 336 713 c +435 713 508 669 555 582 c +570 554 582 523 589 488 c +506 473 l +479 573 430 628 359 637 c +350 638 342 639 333 639 c +248 639 190 590 159 492 c +146 449 139 402 139 351 c +139 261 158 189 197 134 c +230 87 274 63 329 63 c +418 63 477 117 506 225 c +507 229 508 233 509 237 c +589 219 l + +ce} _d +/D{675 0 87 0 636 702 sc +636 353 m +636 247 607 160 550 93 c +496 31 425 0 338 0 c +87 0 l +87 702 l +309 702 l +394 702 462 682 512 642 c +525 631 538 618 551 603 c +608 537 636 454 636 353 c + +547 353 m +547 436 525 504 482 557 c +449 599 403 623 344 628 c +304 629 l +175 629 l +175 75 l +304 75 l +382 75 440 97 478 140 c +484 147 490 155 496 164 c +530 216 547 279 547 353 c + +ce} _d +/E{573 0 87 0 542 702 sc +542 0 m +87 0 l +87 702 l +531 702 l +531 627 l +175 627 l +175 403 l +458 403 l +458 333 l +175 333 l +175 76 l +542 76 l +542 0 l + +ce} _d +/F{491 0 84 0 514 702 sc +514 627 m +172 627 l +172 403 l +456 403 l +456 333 l +172 333 l +172 0 l +84 0 l +84 702 l +514 702 l +514 627 l + +ce} _d +/G{675 0 49 -10 614 713 sc +614 -5 m +560 -5 l +537 82 l +497 24 436 -7 355 -10 c +350 -10 346 -10 342 -10 c +237 -10 157 35 104 125 c +67 187 49 260 49 344 c +49 452 77 541 133 610 c +188 679 262 713 353 713 c +457 713 532 670 579 585 c +591 563 600 538 607 511 c +524 490 l +512 553 480 597 428 622 c +403 633 376 639 347 639 c +256 639 195 589 164 488 c +151 447 144 400 144 348 c +144 251 167 176 212 123 c +247 82 292 61 348 61 c +418 61 469 88 500 141 c +516 170 524 203 524 242 c +524 281 l +349 281 l +349 354 l +614 354 l +614 -5 l + +ce} _d +/H{675 0 83 0 585 702 sc +585 0 m +497 0 l +497 334 l +171 334 l +171 0 l +83 0 l +83 702 l +171 702 l +171 411 l +497 411 l +497 702 l +585 702 l +585 0 l + +ce} _d +/I{266 0 88 0 176 702 sc +176 0 m +88 0 l +88 702 l +176 702 l +176 0 l + +ce} _d +/J{409 0 17 -10 331 702 sc +331 229 m +331 104 290 29 207 2 c +182 -6 153 -10 120 -10 c +86 -10 52 -5 17 4 c +17 76 l +50 69 81 66 108 66 c +171 66 211 83 227 118 c +238 139 243 176 243 229 c +243 702 l +331 702 l +331 229 l + +ce} _d +/K{634 0 88 0 643 702 sc +643 0 m +546 0 l +337 387 l +176 187 l +176 0 l +88 0 l +88 702 l +176 702 l +176 295 l +493 702 l +588 702 l +398 457 l +643 0 l + +ce} _d +/L{512 0 86 0 501 702 sc +501 0 m +86 0 l +86 702 l +174 702 l +174 78 l +501 78 l +501 0 l + +ce} _d +/M{839 0 82 0 761 702 sc +761 0 m +673 0 l +673 613 l +669 613 l +446 0 l +387 0 l +160 613 l +156 613 l +156 0 l +82 0 l +82 702 l +213 702 l +425 140 l +632 702 l +761 702 l +761 0 l + +ce} _d +/N{675 0 84 0 601 702 sc +601 0 m +515 0 l +158 612 l +158 0 l +84 0 l +84 702 l +195 702 l +527 130 l +527 702 l +601 702 l +601 0 l + +ce} _d +/O{675 0 45 -10 623 713 sc +623 359 m +623 258 598 173 548 102 c +495 27 424 -10 335 -10 c +230 -10 151 36 98 128 c +63 189 45 262 45 346 c +45 453 71 540 124 609 c +176 678 246 713 334 713 c +435 713 513 669 566 580 c +604 517 623 443 623 359 c + +530 354 m +530 449 509 522 468 575 c +435 618 392 640 337 640 c +250 640 191 591 159 492 c +144 448 137 399 137 345 c +137 258 157 187 197 133 c +232 85 278 61 335 61 c +417 61 474 108 507 203 c +522 248 530 299 530 354 c + +ce} _d +/P{573 0 66 0 542 702 sc +542 492 m +542 436 523 388 485 348 c +480 343 l +441 305 385 286 311 286 c +154 286 l +154 0 l +66 0 l +66 702 l +301 702 l +376 702 433 686 470 655 c +510 622 534 575 541 515 c +542 507 542 499 542 492 c + +453 492 m +453 557 425 600 370 620 c +351 626 331 629 308 629 c +154 629 l +154 358 l +302 358 l +375 358 422 384 442 435 c +449 452 453 471 453 492 c + +ce} _d +/Q{675 0 42 -167 626 713 sc +626 351 m +626 244 599 158 546 91 c +509 46 462 16 407 1 c +407 -14 l +407 -55 425 -80 461 -88 c +468 -90 476 -91 485 -91 c +500 -91 532 -89 580 -84 c +580 -154 l +553 -163 528 -167 504 -167 c +412 -167 357 -130 340 -55 c +337 -41 335 -26 335 -10 c +224 -7 142 41 91 135 c +58 195 42 265 42 346 c +42 456 69 545 124 613 c +177 680 247 713 334 713 c +441 713 520 666 572 572 c +608 509 626 436 626 351 c + +530 349 m +530 482 496 569 428 610 c +401 627 370 635 333 635 c +234 635 172 576 147 459 c +140 424 136 386 136 344 c +136 239 160 161 207 112 c +238 79 278 62 327 62 c +425 62 488 116 516 225 c +525 263 530 304 530 349 c + +ce} _d +/R{634 0 83 0 588 702 sc +588 0 m +496 0 l +366 304 l +171 304 l +171 0 l +83 0 l +83 702 l +346 702 l +436 702 502 676 544 624 c +563 599 575 568 580 532 c +581 524 581 515 581 506 c +581 445 559 396 515 359 c +496 344 474 333 450 326 c +588 0 l + +493 507 m +493 577 454 616 377 625 c +367 626 357 627 346 627 c +171 627 l +171 376 l +336 376 l +422 376 472 406 487 467 c +491 479 493 492 493 507 c + +ce} _d +/S{634 0 43 -10 590 713 sc +590 201 m +590 114 550 53 469 17 c +428 -1 381 -10 328 -10 c +184 -10 89 56 43 189 c +122 207 l +143 134 191 89 266 72 c +286 67 307 65 330 65 c +398 65 447 83 476 120 c +491 139 499 162 499 189 c +499 237 469 273 408 296 c +343 314 l +264 334 221 345 214 348 c +179 359 153 373 135 389 c +97 423 78 466 78 519 c +78 599 115 655 189 688 c +227 705 269 713 316 713 c +413 713 485 678 534 608 c +554 571 l +559 562 563 552 566 541 c +486 519 l +477 565 448 600 398 624 c +371 637 343 643 314 643 c +265 643 226 629 195 601 c +174 582 164 558 164 531 c +164 485 193 451 250 430 c +264 425 308 414 383 397 c +450 382 497 363 524 340 c +568 305 590 258 590 201 c + +ce} _d +/T{512 0 11 0 499 702 sc +499 626 m +299 626 l +299 0 l +211 0 l +211 626 l +11 626 l +11 702 l +499 702 l +499 626 l + +ce} _d +/U{655 0 83 -10 567 702 sc +567 258 m +567 184 556 128 534 91 c +528 83 522 75 516 68 c +473 16 410 -10 327 -10 c +210 -10 135 32 103 117 c +90 154 83 201 83 258 c +83 702 l +171 702 l +171 258 l +171 179 187 126 218 99 c +243 78 282 68 334 68 c +417 68 468 103 485 174 c +491 197 494 225 494 258 c +494 702 l +567 702 l +567 258 l + +ce} _d +/V{573 0 10 0 569 702 sc +569 702 m +332 0 l +248 0 l +10 702 l +102 702 l +298 123 l +493 702 l +569 702 l + +ce} _d +/W{839 0 11 0 831 702 sc +831 702 m +663 0 l +574 0 l +422 545 l +279 0 l +189 0 l +11 702 l +101 702 l +242 133 l +244 133 l +392 702 l +463 702 l +623 133 l +625 133 l +755 702 l +831 702 l + +ce} _d +/X{552 0 9 0 552 702 sc +552 0 m +453 0 l +275 299 l +91 0 l +9 0 l +234 364 l +34 702 l +132 702 l +287 442 l +443 702 l +524 702 l +328 381 l +552 0 l + +ce} _d +/Y{573 0 11 0 568 702 sc +568 702 m +334 296 l +334 0 l +246 0 l +246 296 l +11 702 l +114 702 l +300 379 l +488 702 l +568 702 l + +ce} _d +/Z{552 0 17 0 513 702 sc +513 0 m +17 0 l +17 76 l +399 630 l +35 630 l +35 702 l +502 702 l +502 644 l +116 76 l +513 76 l +513 0 l + +ce} _d +/a{552 0 56 -10 509 534 sc +509 0 m +429 0 l +420 97 l +385 26 324 -10 238 -10 c +171 -10 120 11 87 53 c +66 79 56 110 56 147 c +56 198 78 240 122 273 c +131 281 142 287 153 292 c +198 313 272 324 375 323 c +420 323 l +420 345 l +420 409 397 448 352 463 c +316 470 l +307 471 298 471 288 471 c +205 471 158 440 145 379 c +71 391 l +80 458 124 502 205 522 c +233 530 263 534 295 534 c +384 534 442 510 469 463 c +488 431 498 380 498 311 c +498 110 l +498 63 502 26 509 0 c + +420 228 m +420 262 l +353 262 l +212 262 142 222 142 143 c +142 100 165 71 211 58 c +224 54 239 52 255 52 c +312 52 356 76 388 123 c +409 154 420 189 420 228 c + +ce} _d +/e{552 0 38 -10 506 534 sc +506 254 m +128 254 l +127 187 143 136 174 101 c +200 72 236 57 283 57 c +341 57 384 82 411 133 c +415 140 419 149 422 158 c +498 142 l +479 82 439 38 378 11 c +346 -3 312 -10 276 -10 c +187 -10 121 27 78 100 c +51 145 38 199 38 260 c +38 346 64 415 116 468 c +159 512 213 534 279 534 c +369 534 434 495 473 417 c +495 374 506 323 506 266 c +506 254 l + +418 313 m +419 370 401 413 366 442 c +342 462 313 472 279 472 c +226 472 186 448 158 400 c +142 374 133 345 132 313 c +418 313 l + +ce} _d +/i{245 0 79 0 167 702 sc +167 612 m +79 612 l +79 702 l +167 702 l +167 612 l + +163 0 m +83 0 l +83 520 l +163 520 l +163 0 l + +ce} _d +/n{552 0 71 0 482 534 sc +482 0 m +402 0 l +402 322 l +402 366 398 396 391 412 c +390 414 389 416 388 418 c +373 444 348 459 313 464 c +308 465 304 465 299 465 c +234 465 190 432 166 366 c +156 337 151 306 151 272 c +151 0 l +71 0 l +71 520 l +146 520 l +146 424 l +148 424 l +173 477 211 511 263 526 c +278 531 294 534 310 534 c +375 534 423 508 455 457 c +458 453 l +474 425 482 377 482 309 c +482 0 l + +ce} _d +/u{552 0 71 -10 479 520 sc +479 0 m +407 0 l +407 103 l +404 103 l +386 58 355 25 310 4 c +289 -5 268 -10 245 -10 c +144 -10 87 45 74 156 c +72 171 71 187 71 204 c +71 520 l +151 520 l +151 204 l +151 113 181 65 242 59 c +242 59 245 59 252 59 c +311 59 354 89 380 148 c +393 177 399 209 399 244 c +399 520 l +479 520 l +479 0 l + +ce} _d +end readonly def + +/BuildGlyph { + exch begin + CharStrings exch + 2 copy known not {pop /.notdef} if + true 3 1 roll get exec + end +} _d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +} _d + +FontName currentdict end definefont pop +%!PS-Adobe-3.0 Resource-Font +%%Creator: Converted from TrueType to Type 3 by Matplotlib. +10 dict begin +/FontName /WenQuanYiZenHeiMono def +/PaintType 0 def +/FontMatrix [0.0009765625 0 0 0.0009765625 0 0] def +/FontBBox [-129 -304 1076 986] def +/FontType 3 def +/Encoding [/space /colon /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /a /e /i /n /o /u] def +/CharStrings 35 dict dup begin +/.notdef 0 def +/space{512 0 0 0 0 0 sc +ce} _d +/colon{512 0 195 18 317 571 sc +195 418 m +195 571 l +317 571 l +317 418 l +195 418 l + +195 18 m +195 172 l +317 172 l +317 18 l +195 18 l + +ce} _d +/A{512 0 20 18 492 766 sc +255 694 m +253 694 l +168 305 l +340 305 l +255 694 l + +356 233 m +152 233 l +104 18 l +20 18 l +205 766 l +307 766 l +492 18 l +403 18 l +356 233 l + +ce} _d +/B{512 0 77 8 466 776 sc +161 459 m +207 459 l +262 459 301 469 326 489 c +351 509 364 540 364 582 c +364 621 352 651 327 672 c +302 694 267 705 222 705 c +197 705 177 702 161 696 c +161 459 l + +161 387 m +161 88 l +186 83 217 80 253 80 c +339 80 382 135 382 244 c +382 339 327 387 217 387 c +161 387 l + +466 233 m +466 83 389 8 236 8 c +181 8 128 13 77 24 c +77 761 l +128 771 181 776 236 776 c +375 776 445 715 445 592 c +445 550 435 515 414 486 c +393 457 365 438 328 429 c +328 427 l +367 420 400 398 426 361 c +453 325 466 282 466 233 c + +ce} _d +/C{512 0 56 8 435 776 sc +56 392 m +56 527 77 624 118 685 c +159 746 221 776 302 776 c +347 776 390 766 430 745 c +430 669 l +389 691 348 702 307 702 c +194 702 138 599 138 392 c +138 280 152 200 181 153 c +210 106 252 82 307 82 c +350 82 392 95 435 121 c +435 39 l +395 18 351 8 302 8 c +219 8 157 37 116 96 c +76 155 56 253 56 392 c + +ce} _d +/D{512 0 67 8 476 776 sc +392 392 m +392 507 377 587 347 633 c +318 679 271 702 207 702 c +184 702 166 699 151 694 c +151 90 l +166 85 184 82 207 82 c +251 82 286 90 311 107 c +337 124 357 155 371 200 c +385 246 392 310 392 392 c + +476 392 m +476 251 454 151 411 94 c +368 37 300 8 207 8 c +159 8 112 13 67 24 c +67 761 l +112 771 159 776 207 776 c +300 776 368 747 411 688 c +454 630 476 531 476 392 c + +ce} _d +/E{512 0 82 18 430 766 sc +166 692 m +166 459 l +420 459 l +420 387 l +166 387 l +166 92 l +430 92 l +430 18 l +82 18 l +82 766 l +430 766 l +430 692 l +166 692 l + +ce} _d +/F{512 0 92 18 430 766 sc +176 387 m +176 18 l +92 18 l +92 766 l +430 766 l +430 692 l +176 692 l +176 459 l +420 459 l +420 387 l +176 387 l + +ce} _d +/G{512 0 41 8 461 776 sc +379 105 m +379 387 l +220 387 l +220 459 l +461 459 l +461 49 l +406 22 348 8 287 8 c +206 8 145 38 103 99 c +62 160 41 257 41 392 c +41 526 63 623 106 684 c +149 745 215 776 302 776 c +342 776 386 768 435 751 c +435 672 l +390 692 346 702 302 702 c +243 702 198 677 167 628 c +136 579 121 501 121 392 c +121 185 178 82 292 82 c +323 82 352 90 379 105 c + +ce} _d +/H{512 0 61 18 451 766 sc +143 766 m +143 461 l +365 461 l +365 766 l +451 766 l +451 18 l +365 18 l +365 387 l +143 387 l +143 18 l +61 18 l +61 766 l +143 766 l + +ce} _d +/I{512 0 92 18 420 766 sc +420 18 m +92 18 l +92 90 l +213 90 l +213 694 l +92 694 l +92 766 l +420 766 l +420 694 l +299 694 l +299 90 l +420 90 l +420 18 l + +ce} _d +/J{512 0 61 8 410 766 sc +410 766 m +410 213 l +410 138 395 85 365 54 c +336 23 286 8 215 8 c +159 8 108 18 61 39 c +61 128 l +81 117 107 106 138 96 c +170 87 196 82 215 82 c +251 82 278 92 296 113 c +314 134 323 168 323 215 c +323 694 l +154 694 l +154 766 l +410 766 l + +ce} _d +/K{512 0 77 18 476 766 sc +161 428 m +163 428 l +374 766 l +471 766 l +241 408 l +476 18 l +379 18 l +163 387 l +161 387 l +161 18 l +77 18 l +77 766 l +161 766 l +161 428 l + +ce} _d +/L{512 0 102 18 430 766 sc +186 766 m +186 92 l +430 92 l +430 18 l +102 18 l +102 766 l +186 766 l + +ce} _d +/M{512 0 41 18 471 766 sc +387 571 m +385 571 l +295 223 l +213 223 l +123 571 l +121 571 l +121 18 l +41 18 l +41 766 l +135 766 l +257 305 l +259 305 l +381 766 l +471 766 l +471 18 l +387 18 l +387 571 l + +ce} _d +/N{512 0 67 18 445 766 sc +155 582 m +153 582 l +153 18 l +67 18 l +67 766 l +153 766 l +361 203 l +364 203 l +364 766 l +445 766 l +445 18 l +364 18 l +155 582 l + +ce} _d +/O{512 0 41 8 471 776 sc +93 689 m +128 747 183 776 256 776 c +329 776 383 747 418 689 c +453 632 471 533 471 392 c +471 251 453 152 418 94 c +383 37 329 8 256 8 c +183 8 128 37 93 94 c +58 152 41 251 41 392 c +41 533 58 632 93 689 c + +183 108 m +202 91 226 82 256 82 c +286 82 310 91 328 108 c +347 125 361 157 372 203 c +383 250 389 313 389 392 c +389 471 383 534 372 580 c +361 627 347 659 328 676 c +310 693 286 702 256 702 c +226 702 202 693 183 676 c +165 659 150 627 139 580 c +128 534 123 471 123 392 c +123 313 128 250 139 203 c +150 157 165 125 183 108 c + +ce} _d +/P{512 0 77 18 466 776 sc +384 551 m +384 605 372 644 347 668 c +322 693 284 705 232 705 c +204 705 180 702 161 696 c +161 397 l +181 394 205 392 232 392 c +285 392 323 404 347 428 c +372 453 384 494 384 551 c + +466 551 m +466 469 448 410 412 374 c +376 339 320 321 243 321 c +219 321 192 323 161 326 c +161 18 l +77 18 l +77 761 l +130 771 185 776 241 776 c +318 776 375 758 411 722 c +448 687 466 630 466 551 c + +ce} _d +/Q{512 0 41 -135 492 776 sc +93 689 m +128 747 183 776 256 776 c +329 776 383 747 418 689 c +453 632 471 533 471 392 c +471 206 437 89 369 40 c +369 38 l +397 23 422 1 443 -30 c +465 -61 481 -96 492 -135 c +401 -135 l +387 -82 369 -44 346 -23 c +323 -2 293 8 256 8 c +183 8 128 37 93 94 c +58 152 41 251 41 392 c +41 533 58 632 93 689 c + +183 108 m +202 91 226 82 256 82 c +286 82 310 91 328 108 c +347 125 361 157 372 203 c +383 250 389 313 389 392 c +389 471 383 534 372 580 c +361 627 347 659 328 676 c +310 693 286 702 256 702 c +226 702 202 693 183 676 c +165 659 150 627 139 580 c +128 534 123 471 123 392 c +123 313 128 250 139 203 c +150 157 165 125 183 108 c + +ce} _d +/R{512 0 72 18 481 776 sc +379 571 m +379 660 328 705 227 705 c +199 705 175 702 156 696 c +156 418 l +217 418 l +276 418 318 429 342 452 c +367 475 379 514 379 571 c + +156 346 m +156 18 l +72 18 l +72 761 l +125 771 180 776 236 776 c +312 776 368 759 405 725 c +442 692 461 640 461 571 c +461 474 424 408 349 374 c +349 372 l +370 361 393 317 417 238 c +481 18 l +393 18 l +333 240 l +321 283 307 312 290 325 c +274 339 246 346 207 346 c +156 346 l + +ce} _d +/S{512 0 72 8 451 776 sc +266 702 m +234 702 208 692 187 671 c +166 650 156 624 156 592 c +156 558 163 530 178 507 c +193 485 217 466 251 451 c +327 417 379 382 408 345 c +437 309 451 262 451 203 c +451 138 433 90 398 57 c +363 24 312 8 246 8 c +184 8 128 27 77 65 c +77 162 l +132 109 190 82 251 82 c +328 82 367 122 367 203 c +367 240 358 271 340 296 c +322 321 292 342 251 361 c +187 390 141 422 113 459 c +86 496 72 540 72 592 c +72 647 89 691 124 725 c +159 759 204 776 261 776 c +297 776 327 773 350 768 c +373 763 400 752 430 735 c +430 643 l +377 682 323 702 266 702 c + +ce} _d +/T{512 0 56 18 456 766 sc +214 18 m +214 694 l +56 694 l +56 766 l +456 766 l +456 694 l +298 694 l +298 18 l +214 18 l + +ce} _d +/U{512 0 61 8 451 766 sc +402 58 m +369 25 321 8 256 8 c +191 8 143 25 110 58 c +77 91 61 143 61 213 c +61 766 l +147 766 l +147 233 l +147 178 156 139 174 116 c +193 93 221 82 258 82 c +295 82 323 93 341 116 c +360 139 369 178 369 233 c +369 766 l +451 766 l +451 213 l +451 143 435 91 402 58 c + +ce} _d +/V{512 0 31 18 481 766 sc +259 90 m +397 766 l +481 766 l +307 18 l +205 18 l +31 766 l +119 766 l +257 90 l +259 90 l + +ce} _d +/W{512 0 26 18 486 766 sc +157 141 m +159 141 l +214 664 l +306 664 l +361 141 l +364 141 l +410 766 l +486 766 l +425 18 l +313 18 l +257 551 l +255 551 l +199 18 l +87 18 l +26 766 l +111 766 l +157 141 l + +ce} _d +/X{512 0 51 18 461 766 sc +257 469 m +259 469 l +374 766 l +459 766 l +307 402 l +461 18 l +369 18 l +255 331 l +253 331 l +138 18 l +51 18 l +205 402 l +53 766 l +143 766 l +257 469 l + +ce} _d +/Y{512 0 31 18 481 766 sc +257 402 m +259 402 l +394 766 l +481 766 l +298 315 l +298 18 l +214 18 l +214 315 l +31 766 l +123 766 l +257 402 l + +ce} _d +/Z{512 0 77 18 435 766 sc +343 692 m +343 694 l +77 694 l +77 766 l +435 766 l +435 694 l +169 92 l +169 90 l +435 90 l +435 18 l +77 18 l +77 90 l +343 692 l + +ce} _d +/a{512 0 61 8 440 561 sc +261 561 m +330 561 377 547 402 520 c +427 493 440 442 440 367 c +440 18 l +367 18 l +365 95 l +362 95 l +330 37 279 8 210 8 c +165 8 129 22 102 50 c +75 79 61 118 61 167 c +61 229 82 277 124 310 c +166 344 229 361 312 361 c +361 361 l +361 387 l +361 426 353 453 338 469 c +323 485 298 493 261 493 c +238 493 210 489 175 480 c +140 472 111 463 87 452 c +87 525 l +111 536 140 544 174 551 c +208 558 237 561 261 561 c + +361 300 m +312 300 l +196 300 138 257 138 172 c +138 141 146 118 161 101 c +177 85 198 77 225 77 c +266 77 298 93 323 126 c +348 159 361 205 361 264 c +361 300 l + +ce} _d +/e{512 0 56 8 445 561 sc +141 258 m +144 195 157 149 180 121 c +203 93 237 79 282 79 c +323 79 369 91 420 116 c +420 34 l +369 17 321 8 276 8 c +129 8 56 100 56 285 c +56 381 73 451 107 495 c +142 539 193 561 261 561 c +323 561 369 540 399 497 c +430 455 445 386 445 290 c +445 283 444 272 443 258 c +141 258 l + +141 326 m +365 326 l +364 435 330 490 261 490 c +222 490 193 478 174 453 c +155 429 144 387 141 326 c + +ce} _d +/i{512 0 97 18 435 797 sc +324 551 m +324 88 l +435 88 l +435 18 l +97 18 l +97 88 l +240 88 l +240 481 l +128 481 l +128 551 l +324 551 l + +219 674 m +219 797 l +324 797 l +324 674 l +219 674 l + +ce} _d +/n{512 0 72 18 451 561 sc +451 356 m +451 18 l +372 18 l +372 338 l +372 398 365 438 351 458 c +338 478 313 488 276 488 c +242 488 213 469 189 431 c +165 393 153 341 153 276 c +153 18 l +72 18 l +72 551 l +147 551 l +150 474 l +152 474 l +165 500 184 521 211 537 c +238 553 266 561 297 561 c +351 561 390 545 414 514 c +439 483 451 431 451 356 c + +ce} _d +/o{512 0 51 8 461 561 sc +51 284 m +51 469 119 561 256 561 c +393 561 461 469 461 284 c +461 100 393 8 256 8 c +119 8 51 100 51 284 c + +164 125 m +184 94 215 79 256 79 c +297 79 328 94 347 125 c +367 156 377 209 377 284 c +377 359 367 412 347 443 c +328 474 297 490 256 490 c +215 490 184 474 164 443 c +145 412 135 359 135 284 c +135 209 145 156 164 125 c + +ce} _d +/u{512 0 67 8 435 551 sc +67 203 m +67 551 l +145 551 l +145 221 l +145 164 151 127 164 108 c +177 90 201 81 236 81 c +269 81 297 100 320 137 c +343 175 354 227 354 293 c +354 551 l +435 551 l +435 18 l +359 18 l +357 95 l +355 95 l +342 68 323 46 298 31 c +273 16 245 8 215 8 c +162 8 124 23 101 52 c +78 81 67 132 67 203 c + +ce} _d +end readonly def + +/BuildGlyph { + exch begin + CharStrings exch + 2 copy known not {pop /.notdef} if + true 3 1 roll get exec + end +} _d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +} _d + +FontName currentdict end definefont pop +end +%%EndProlog +mpldict begin +0 0 translate +0 0 504 72 rectclip +gsave +0 0 m +504 0 l +504 72 l +0 72 l +cl +1 setgray +fill +grestore +gsave +0 36 m +504 36 l +504 72 l +0 72 l +0 36 l +cl +grestore +0 setgray +/WenQuanYiZenHei 16.000 selectfont +gsave + +55.4375 49.7812 translate +0 rotate +0 0 m /W glyphshow +13.1094 0 m /e glyphshow +21.7344 0 m /n glyphshow +30.3594 0 m /Q glyphshow +40.9062 0 m /u glyphshow +49.5312 0 m /a glyphshow +58.1562 0 m /n glyphshow +66.7812 0 m /Y glyphshow +75.7344 0 m /i glyphshow +79.5625 0 m /space glyphshow +84.3594 0 m /Z glyphshow +92.9844 0 m /e glyphshow +101.609 0 m /n glyphshow +110.234 0 m /space glyphshow +115.031 0 m /H glyphshow +125.578 0 m /e glyphshow +134.203 0 m /i glyphshow +138.031 0 m /colon glyphshow +142.828 0 m /space glyphshow +147.625 0 m /A glyphshow +156.578 0 m /B glyphshow +166.484 0 m /C glyphshow +176.391 0 m /D glyphshow +186.938 0 m /E glyphshow +195.891 0 m /F glyphshow +203.562 0 m /G glyphshow +214.109 0 m /H glyphshow +224.656 0 m /I glyphshow +228.812 0 m /J glyphshow +235.203 0 m /K glyphshow +245.109 0 m /L glyphshow +253.109 0 m /M glyphshow +266.219 0 m /N glyphshow +276.766 0 m /O glyphshow +287.312 0 m /P glyphshow +296.266 0 m /Q glyphshow +306.812 0 m /R glyphshow +316.719 0 m /S glyphshow +326.625 0 m /T glyphshow +334.625 0 m /U glyphshow +344.859 0 m /V glyphshow +353.812 0 m /W glyphshow +366.922 0 m /X glyphshow +375.547 0 m /Y glyphshow +384.5 0 m /Z glyphshow +grestore +gsave +0 0 m +504 0 l +504 36 l +0 36 l +0 0 l +cl +grestore +/WenQuanYiZenHeiMono 16.000 selectfont +gsave + +52 13.6328 translate +0 rotate +0 0 m /W glyphshow +8 0 m /e glyphshow +16 0 m /n glyphshow +24 0 m /Q glyphshow +32 0 m /u glyphshow +40 0 m /a glyphshow +48 0 m /n glyphshow +56 0 m /Y glyphshow +64 0 m /i glyphshow +72 0 m /space glyphshow +80 0 m /Z glyphshow +88 0 m /e glyphshow +96 0 m /n glyphshow +104 0 m /space glyphshow +112 0 m /H glyphshow +120 0 m /e glyphshow +128 0 m /i glyphshow +136 0 m /space glyphshow +144 0 m /M glyphshow +152 0 m /o glyphshow +160 0 m /n glyphshow +168 0 m /o glyphshow +176 0 m /colon glyphshow +184 0 m /space glyphshow +192 0 m /A glyphshow +200 0 m /B glyphshow +208 0 m /C glyphshow +216 0 m /D glyphshow +224 0 m /E glyphshow +232 0 m /F glyphshow +240 0 m /G glyphshow +248 0 m /H glyphshow +256 0 m /I glyphshow +264 0 m /J glyphshow +272 0 m /K glyphshow +280 0 m /L glyphshow +288 0 m /M glyphshow +296 0 m /N glyphshow +304 0 m /O glyphshow +312 0 m /P glyphshow +320 0 m /Q glyphshow +328 0 m /R glyphshow +336 0 m /S glyphshow +344 0 m /T glyphshow +352 0 m /U glyphshow +360 0 m /V glyphshow +368 0 m /W glyphshow +376 0 m /X glyphshow +384 0 m /Y glyphshow +392 0 m /Z glyphshow +grestore + +end +showpage diff --git a/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type42.eps b/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type42.eps new file mode 100644 index 000000000000..3df370bd885e --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_backend_ps/ttc_type42.eps @@ -0,0 +1,1483 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%LanguageLevel: 3 +%%Title: ttc_type42.eps +%%Creator: Matplotlib v3.11.0.dev1121+gba80e42970.d20250725, https://matplotlib.org/ +%%CreationDate: Fri Jul 25 06:03:10 2025 +%%Orientation: portrait +%%BoundingBox: 0 0 504 72 +%%HiResBoundingBox: 0.000000 0.000000 504.000000 72.000000 +%%EndComments +%%BeginProlog +/mpldict 10 dict def +mpldict begin +/_d { bind def } bind def +/m { moveto } _d +/l { lineto } _d +/r { rlineto } _d +/c { curveto } _d +/cl { closepath } _d +/ce { closepath eofill } _d +/sc { setcachedevice } _d +%!PS-Adobe-3.0 Resource-Font +%%Creator: Converted from TrueType to Type 3 by Matplotlib. +10 dict begin +/FontName /WenQuanYiZenHei def +/PaintType 0 def +/FontMatrix [0.0009765625 0 0 0.0009765625 0 0] def +/FontBBox [-129 -304 1076 986] def +/FontType 3 def +/Encoding [/space /colon /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /a /e /i /n /u] def +/CharStrings 34 dict dup begin +/.notdef 0 def +/space{307 0 0 0 0 0 sc +ce} _d +/colon{307 0 101 0 215 520 sc +215 404 m +101 404 l +101 520 l +215 520 l +215 404 l + +215 0 m +101 0 l +101 116 l +215 116 l +215 0 l + +ce} _d +/A{573 0 11 0 568 702 sc +568 0 m +478 0 l +408 205 l +147 205 l +85 0 l +11 0 l +239 702 l +340 702 l +568 0 l + +388 271 m +281 608 l +172 271 l +388 271 l + +ce} _d +/B{634 0 83 0 588 702 sc +588 194 m +588 130 565 80 520 45 c +484 16 434 1 370 0 c +347 0 l +83 0 l +83 702 l +348 702 l +405 702 448 694 477 679 c +482 676 487 673 493 670 c +541 637 565 591 566 531 c +566 470 542 424 494 394 c +462 380 l +456 377 449 375 442 374 c +442 372 l +501 359 543 327 568 276 c +581 251 588 224 588 194 c + +479 520 m +479 585 443 621 370 630 c +361 631 351 631 341 631 c +171 631 l +171 401 l +317 401 l +425 401 479 441 479 520 c + +500 198 m +500 241 485 276 454 303 c +453 304 451 306 449 307 c +426 325 389 334 338 334 c +171 334 l +171 75 l +343 75 l +432 75 483 105 497 166 c +499 175 500 186 500 198 c + +ce} _d +/C{634 0 43 -10 589 713 sc +589 219 m +558 90 490 16 386 -5 c +367 -8 348 -10 329 -10 c +224 -10 146 38 94 135 c +60 199 43 273 43 358 c +43 471 72 560 131 626 c +183 684 251 713 336 713 c +435 713 508 669 555 582 c +570 554 582 523 589 488 c +506 473 l +479 573 430 628 359 637 c +350 638 342 639 333 639 c +248 639 190 590 159 492 c +146 449 139 402 139 351 c +139 261 158 189 197 134 c +230 87 274 63 329 63 c +418 63 477 117 506 225 c +507 229 508 233 509 237 c +589 219 l + +ce} _d +/D{675 0 87 0 636 702 sc +636 353 m +636 247 607 160 550 93 c +496 31 425 0 338 0 c +87 0 l +87 702 l +309 702 l +394 702 462 682 512 642 c +525 631 538 618 551 603 c +608 537 636 454 636 353 c + +547 353 m +547 436 525 504 482 557 c +449 599 403 623 344 628 c +304 629 l +175 629 l +175 75 l +304 75 l +382 75 440 97 478 140 c +484 147 490 155 496 164 c +530 216 547 279 547 353 c + +ce} _d +/E{573 0 87 0 542 702 sc +542 0 m +87 0 l +87 702 l +531 702 l +531 627 l +175 627 l +175 403 l +458 403 l +458 333 l +175 333 l +175 76 l +542 76 l +542 0 l + +ce} _d +/F{491 0 84 0 514 702 sc +514 627 m +172 627 l +172 403 l +456 403 l +456 333 l +172 333 l +172 0 l +84 0 l +84 702 l +514 702 l +514 627 l + +ce} _d +/G{675 0 49 -10 614 713 sc +614 -5 m +560 -5 l +537 82 l +497 24 436 -7 355 -10 c +350 -10 346 -10 342 -10 c +237 -10 157 35 104 125 c +67 187 49 260 49 344 c +49 452 77 541 133 610 c +188 679 262 713 353 713 c +457 713 532 670 579 585 c +591 563 600 538 607 511 c +524 490 l +512 553 480 597 428 622 c +403 633 376 639 347 639 c +256 639 195 589 164 488 c +151 447 144 400 144 348 c +144 251 167 176 212 123 c +247 82 292 61 348 61 c +418 61 469 88 500 141 c +516 170 524 203 524 242 c +524 281 l +349 281 l +349 354 l +614 354 l +614 -5 l + +ce} _d +/H{675 0 83 0 585 702 sc +585 0 m +497 0 l +497 334 l +171 334 l +171 0 l +83 0 l +83 702 l +171 702 l +171 411 l +497 411 l +497 702 l +585 702 l +585 0 l + +ce} _d +/I{266 0 88 0 176 702 sc +176 0 m +88 0 l +88 702 l +176 702 l +176 0 l + +ce} _d +/J{409 0 17 -10 331 702 sc +331 229 m +331 104 290 29 207 2 c +182 -6 153 -10 120 -10 c +86 -10 52 -5 17 4 c +17 76 l +50 69 81 66 108 66 c +171 66 211 83 227 118 c +238 139 243 176 243 229 c +243 702 l +331 702 l +331 229 l + +ce} _d +/K{634 0 88 0 643 702 sc +643 0 m +546 0 l +337 387 l +176 187 l +176 0 l +88 0 l +88 702 l +176 702 l +176 295 l +493 702 l +588 702 l +398 457 l +643 0 l + +ce} _d +/L{512 0 86 0 501 702 sc +501 0 m +86 0 l +86 702 l +174 702 l +174 78 l +501 78 l +501 0 l + +ce} _d +/M{839 0 82 0 761 702 sc +761 0 m +673 0 l +673 613 l +669 613 l +446 0 l +387 0 l +160 613 l +156 613 l +156 0 l +82 0 l +82 702 l +213 702 l +425 140 l +632 702 l +761 702 l +761 0 l + +ce} _d +/N{675 0 84 0 601 702 sc +601 0 m +515 0 l +158 612 l +158 0 l +84 0 l +84 702 l +195 702 l +527 130 l +527 702 l +601 702 l +601 0 l + +ce} _d +/O{675 0 45 -10 623 713 sc +623 359 m +623 258 598 173 548 102 c +495 27 424 -10 335 -10 c +230 -10 151 36 98 128 c +63 189 45 262 45 346 c +45 453 71 540 124 609 c +176 678 246 713 334 713 c +435 713 513 669 566 580 c +604 517 623 443 623 359 c + +530 354 m +530 449 509 522 468 575 c +435 618 392 640 337 640 c +250 640 191 591 159 492 c +144 448 137 399 137 345 c +137 258 157 187 197 133 c +232 85 278 61 335 61 c +417 61 474 108 507 203 c +522 248 530 299 530 354 c + +ce} _d +/P{573 0 66 0 542 702 sc +542 492 m +542 436 523 388 485 348 c +480 343 l +441 305 385 286 311 286 c +154 286 l +154 0 l +66 0 l +66 702 l +301 702 l +376 702 433 686 470 655 c +510 622 534 575 541 515 c +542 507 542 499 542 492 c + +453 492 m +453 557 425 600 370 620 c +351 626 331 629 308 629 c +154 629 l +154 358 l +302 358 l +375 358 422 384 442 435 c +449 452 453 471 453 492 c + +ce} _d +/Q{675 0 42 -167 626 713 sc +626 351 m +626 244 599 158 546 91 c +509 46 462 16 407 1 c +407 -14 l +407 -55 425 -80 461 -88 c +468 -90 476 -91 485 -91 c +500 -91 532 -89 580 -84 c +580 -154 l +553 -163 528 -167 504 -167 c +412 -167 357 -130 340 -55 c +337 -41 335 -26 335 -10 c +224 -7 142 41 91 135 c +58 195 42 265 42 346 c +42 456 69 545 124 613 c +177 680 247 713 334 713 c +441 713 520 666 572 572 c +608 509 626 436 626 351 c + +530 349 m +530 482 496 569 428 610 c +401 627 370 635 333 635 c +234 635 172 576 147 459 c +140 424 136 386 136 344 c +136 239 160 161 207 112 c +238 79 278 62 327 62 c +425 62 488 116 516 225 c +525 263 530 304 530 349 c + +ce} _d +/R{634 0 83 0 588 702 sc +588 0 m +496 0 l +366 304 l +171 304 l +171 0 l +83 0 l +83 702 l +346 702 l +436 702 502 676 544 624 c +563 599 575 568 580 532 c +581 524 581 515 581 506 c +581 445 559 396 515 359 c +496 344 474 333 450 326 c +588 0 l + +493 507 m +493 577 454 616 377 625 c +367 626 357 627 346 627 c +171 627 l +171 376 l +336 376 l +422 376 472 406 487 467 c +491 479 493 492 493 507 c + +ce} _d +/S{634 0 43 -10 590 713 sc +590 201 m +590 114 550 53 469 17 c +428 -1 381 -10 328 -10 c +184 -10 89 56 43 189 c +122 207 l +143 134 191 89 266 72 c +286 67 307 65 330 65 c +398 65 447 83 476 120 c +491 139 499 162 499 189 c +499 237 469 273 408 296 c +343 314 l +264 334 221 345 214 348 c +179 359 153 373 135 389 c +97 423 78 466 78 519 c +78 599 115 655 189 688 c +227 705 269 713 316 713 c +413 713 485 678 534 608 c +554 571 l +559 562 563 552 566 541 c +486 519 l +477 565 448 600 398 624 c +371 637 343 643 314 643 c +265 643 226 629 195 601 c +174 582 164 558 164 531 c +164 485 193 451 250 430 c +264 425 308 414 383 397 c +450 382 497 363 524 340 c +568 305 590 258 590 201 c + +ce} _d +/T{512 0 11 0 499 702 sc +499 626 m +299 626 l +299 0 l +211 0 l +211 626 l +11 626 l +11 702 l +499 702 l +499 626 l + +ce} _d +/U{655 0 83 -10 567 702 sc +567 258 m +567 184 556 128 534 91 c +528 83 522 75 516 68 c +473 16 410 -10 327 -10 c +210 -10 135 32 103 117 c +90 154 83 201 83 258 c +83 702 l +171 702 l +171 258 l +171 179 187 126 218 99 c +243 78 282 68 334 68 c +417 68 468 103 485 174 c +491 197 494 225 494 258 c +494 702 l +567 702 l +567 258 l + +ce} _d +/V{573 0 10 0 569 702 sc +569 702 m +332 0 l +248 0 l +10 702 l +102 702 l +298 123 l +493 702 l +569 702 l + +ce} _d +/W{839 0 11 0 831 702 sc +831 702 m +663 0 l +574 0 l +422 545 l +279 0 l +189 0 l +11 702 l +101 702 l +242 133 l +244 133 l +392 702 l +463 702 l +623 133 l +625 133 l +755 702 l +831 702 l + +ce} _d +/X{552 0 9 0 552 702 sc +552 0 m +453 0 l +275 299 l +91 0 l +9 0 l +234 364 l +34 702 l +132 702 l +287 442 l +443 702 l +524 702 l +328 381 l +552 0 l + +ce} _d +/Y{573 0 11 0 568 702 sc +568 702 m +334 296 l +334 0 l +246 0 l +246 296 l +11 702 l +114 702 l +300 379 l +488 702 l +568 702 l + +ce} _d +/Z{552 0 17 0 513 702 sc +513 0 m +17 0 l +17 76 l +399 630 l +35 630 l +35 702 l +502 702 l +502 644 l +116 76 l +513 76 l +513 0 l + +ce} _d +/a{552 0 56 -10 509 534 sc +509 0 m +429 0 l +420 97 l +385 26 324 -10 238 -10 c +171 -10 120 11 87 53 c +66 79 56 110 56 147 c +56 198 78 240 122 273 c +131 281 142 287 153 292 c +198 313 272 324 375 323 c +420 323 l +420 345 l +420 409 397 448 352 463 c +316 470 l +307 471 298 471 288 471 c +205 471 158 440 145 379 c +71 391 l +80 458 124 502 205 522 c +233 530 263 534 295 534 c +384 534 442 510 469 463 c +488 431 498 380 498 311 c +498 110 l +498 63 502 26 509 0 c + +420 228 m +420 262 l +353 262 l +212 262 142 222 142 143 c +142 100 165 71 211 58 c +224 54 239 52 255 52 c +312 52 356 76 388 123 c +409 154 420 189 420 228 c + +ce} _d +/e{552 0 38 -10 506 534 sc +506 254 m +128 254 l +127 187 143 136 174 101 c +200 72 236 57 283 57 c +341 57 384 82 411 133 c +415 140 419 149 422 158 c +498 142 l +479 82 439 38 378 11 c +346 -3 312 -10 276 -10 c +187 -10 121 27 78 100 c +51 145 38 199 38 260 c +38 346 64 415 116 468 c +159 512 213 534 279 534 c +369 534 434 495 473 417 c +495 374 506 323 506 266 c +506 254 l + +418 313 m +419 370 401 413 366 442 c +342 462 313 472 279 472 c +226 472 186 448 158 400 c +142 374 133 345 132 313 c +418 313 l + +ce} _d +/i{245 0 79 0 167 702 sc +167 612 m +79 612 l +79 702 l +167 702 l +167 612 l + +163 0 m +83 0 l +83 520 l +163 520 l +163 0 l + +ce} _d +/n{552 0 71 0 482 534 sc +482 0 m +402 0 l +402 322 l +402 366 398 396 391 412 c +390 414 389 416 388 418 c +373 444 348 459 313 464 c +308 465 304 465 299 465 c +234 465 190 432 166 366 c +156 337 151 306 151 272 c +151 0 l +71 0 l +71 520 l +146 520 l +146 424 l +148 424 l +173 477 211 511 263 526 c +278 531 294 534 310 534 c +375 534 423 508 455 457 c +458 453 l +474 425 482 377 482 309 c +482 0 l + +ce} _d +/u{552 0 71 -10 479 520 sc +479 0 m +407 0 l +407 103 l +404 103 l +386 58 355 25 310 4 c +289 -5 268 -10 245 -10 c +144 -10 87 45 74 156 c +72 171 71 187 71 204 c +71 520 l +151 520 l +151 204 l +151 113 181 65 242 59 c +242 59 245 59 252 59 c +311 59 354 89 380 148 c +393 177 399 209 399 244 c +399 520 l +479 520 l +479 0 l + +ce} _d +end readonly def + +/BuildGlyph { + exch begin + CharStrings exch + 2 copy known not {pop /.notdef} if + true 3 1 roll get exec + end +} _d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +} _d + +FontName currentdict end definefont pop +%!PS-Adobe-3.0 Resource-Font +%%Creator: Converted from TrueType to Type 3 by Matplotlib. +10 dict begin +/FontName /WenQuanYiZenHeiMono def +/PaintType 0 def +/FontMatrix [0.0009765625 0 0 0.0009765625 0 0] def +/FontBBox [-129 -304 1076 986] def +/FontType 3 def +/Encoding [/space /colon /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /a /e /i /n /o /u] def +/CharStrings 35 dict dup begin +/.notdef 0 def +/space{512 0 0 0 0 0 sc +ce} _d +/colon{512 0 195 18 317 571 sc +195 418 m +195 571 l +317 571 l +317 418 l +195 418 l + +195 18 m +195 172 l +317 172 l +317 18 l +195 18 l + +ce} _d +/A{512 0 20 18 492 766 sc +255 694 m +253 694 l +168 305 l +340 305 l +255 694 l + +356 233 m +152 233 l +104 18 l +20 18 l +205 766 l +307 766 l +492 18 l +403 18 l +356 233 l + +ce} _d +/B{512 0 77 8 466 776 sc +161 459 m +207 459 l +262 459 301 469 326 489 c +351 509 364 540 364 582 c +364 621 352 651 327 672 c +302 694 267 705 222 705 c +197 705 177 702 161 696 c +161 459 l + +161 387 m +161 88 l +186 83 217 80 253 80 c +339 80 382 135 382 244 c +382 339 327 387 217 387 c +161 387 l + +466 233 m +466 83 389 8 236 8 c +181 8 128 13 77 24 c +77 761 l +128 771 181 776 236 776 c +375 776 445 715 445 592 c +445 550 435 515 414 486 c +393 457 365 438 328 429 c +328 427 l +367 420 400 398 426 361 c +453 325 466 282 466 233 c + +ce} _d +/C{512 0 56 8 435 776 sc +56 392 m +56 527 77 624 118 685 c +159 746 221 776 302 776 c +347 776 390 766 430 745 c +430 669 l +389 691 348 702 307 702 c +194 702 138 599 138 392 c +138 280 152 200 181 153 c +210 106 252 82 307 82 c +350 82 392 95 435 121 c +435 39 l +395 18 351 8 302 8 c +219 8 157 37 116 96 c +76 155 56 253 56 392 c + +ce} _d +/D{512 0 67 8 476 776 sc +392 392 m +392 507 377 587 347 633 c +318 679 271 702 207 702 c +184 702 166 699 151 694 c +151 90 l +166 85 184 82 207 82 c +251 82 286 90 311 107 c +337 124 357 155 371 200 c +385 246 392 310 392 392 c + +476 392 m +476 251 454 151 411 94 c +368 37 300 8 207 8 c +159 8 112 13 67 24 c +67 761 l +112 771 159 776 207 776 c +300 776 368 747 411 688 c +454 630 476 531 476 392 c + +ce} _d +/E{512 0 82 18 430 766 sc +166 692 m +166 459 l +420 459 l +420 387 l +166 387 l +166 92 l +430 92 l +430 18 l +82 18 l +82 766 l +430 766 l +430 692 l +166 692 l + +ce} _d +/F{512 0 92 18 430 766 sc +176 387 m +176 18 l +92 18 l +92 766 l +430 766 l +430 692 l +176 692 l +176 459 l +420 459 l +420 387 l +176 387 l + +ce} _d +/G{512 0 41 8 461 776 sc +379 105 m +379 387 l +220 387 l +220 459 l +461 459 l +461 49 l +406 22 348 8 287 8 c +206 8 145 38 103 99 c +62 160 41 257 41 392 c +41 526 63 623 106 684 c +149 745 215 776 302 776 c +342 776 386 768 435 751 c +435 672 l +390 692 346 702 302 702 c +243 702 198 677 167 628 c +136 579 121 501 121 392 c +121 185 178 82 292 82 c +323 82 352 90 379 105 c + +ce} _d +/H{512 0 61 18 451 766 sc +143 766 m +143 461 l +365 461 l +365 766 l +451 766 l +451 18 l +365 18 l +365 387 l +143 387 l +143 18 l +61 18 l +61 766 l +143 766 l + +ce} _d +/I{512 0 92 18 420 766 sc +420 18 m +92 18 l +92 90 l +213 90 l +213 694 l +92 694 l +92 766 l +420 766 l +420 694 l +299 694 l +299 90 l +420 90 l +420 18 l + +ce} _d +/J{512 0 61 8 410 766 sc +410 766 m +410 213 l +410 138 395 85 365 54 c +336 23 286 8 215 8 c +159 8 108 18 61 39 c +61 128 l +81 117 107 106 138 96 c +170 87 196 82 215 82 c +251 82 278 92 296 113 c +314 134 323 168 323 215 c +323 694 l +154 694 l +154 766 l +410 766 l + +ce} _d +/K{512 0 77 18 476 766 sc +161 428 m +163 428 l +374 766 l +471 766 l +241 408 l +476 18 l +379 18 l +163 387 l +161 387 l +161 18 l +77 18 l +77 766 l +161 766 l +161 428 l + +ce} _d +/L{512 0 102 18 430 766 sc +186 766 m +186 92 l +430 92 l +430 18 l +102 18 l +102 766 l +186 766 l + +ce} _d +/M{512 0 41 18 471 766 sc +387 571 m +385 571 l +295 223 l +213 223 l +123 571 l +121 571 l +121 18 l +41 18 l +41 766 l +135 766 l +257 305 l +259 305 l +381 766 l +471 766 l +471 18 l +387 18 l +387 571 l + +ce} _d +/N{512 0 67 18 445 766 sc +155 582 m +153 582 l +153 18 l +67 18 l +67 766 l +153 766 l +361 203 l +364 203 l +364 766 l +445 766 l +445 18 l +364 18 l +155 582 l + +ce} _d +/O{512 0 41 8 471 776 sc +93 689 m +128 747 183 776 256 776 c +329 776 383 747 418 689 c +453 632 471 533 471 392 c +471 251 453 152 418 94 c +383 37 329 8 256 8 c +183 8 128 37 93 94 c +58 152 41 251 41 392 c +41 533 58 632 93 689 c + +183 108 m +202 91 226 82 256 82 c +286 82 310 91 328 108 c +347 125 361 157 372 203 c +383 250 389 313 389 392 c +389 471 383 534 372 580 c +361 627 347 659 328 676 c +310 693 286 702 256 702 c +226 702 202 693 183 676 c +165 659 150 627 139 580 c +128 534 123 471 123 392 c +123 313 128 250 139 203 c +150 157 165 125 183 108 c + +ce} _d +/P{512 0 77 18 466 776 sc +384 551 m +384 605 372 644 347 668 c +322 693 284 705 232 705 c +204 705 180 702 161 696 c +161 397 l +181 394 205 392 232 392 c +285 392 323 404 347 428 c +372 453 384 494 384 551 c + +466 551 m +466 469 448 410 412 374 c +376 339 320 321 243 321 c +219 321 192 323 161 326 c +161 18 l +77 18 l +77 761 l +130 771 185 776 241 776 c +318 776 375 758 411 722 c +448 687 466 630 466 551 c + +ce} _d +/Q{512 0 41 -135 492 776 sc +93 689 m +128 747 183 776 256 776 c +329 776 383 747 418 689 c +453 632 471 533 471 392 c +471 206 437 89 369 40 c +369 38 l +397 23 422 1 443 -30 c +465 -61 481 -96 492 -135 c +401 -135 l +387 -82 369 -44 346 -23 c +323 -2 293 8 256 8 c +183 8 128 37 93 94 c +58 152 41 251 41 392 c +41 533 58 632 93 689 c + +183 108 m +202 91 226 82 256 82 c +286 82 310 91 328 108 c +347 125 361 157 372 203 c +383 250 389 313 389 392 c +389 471 383 534 372 580 c +361 627 347 659 328 676 c +310 693 286 702 256 702 c +226 702 202 693 183 676 c +165 659 150 627 139 580 c +128 534 123 471 123 392 c +123 313 128 250 139 203 c +150 157 165 125 183 108 c + +ce} _d +/R{512 0 72 18 481 776 sc +379 571 m +379 660 328 705 227 705 c +199 705 175 702 156 696 c +156 418 l +217 418 l +276 418 318 429 342 452 c +367 475 379 514 379 571 c + +156 346 m +156 18 l +72 18 l +72 761 l +125 771 180 776 236 776 c +312 776 368 759 405 725 c +442 692 461 640 461 571 c +461 474 424 408 349 374 c +349 372 l +370 361 393 317 417 238 c +481 18 l +393 18 l +333 240 l +321 283 307 312 290 325 c +274 339 246 346 207 346 c +156 346 l + +ce} _d +/S{512 0 72 8 451 776 sc +266 702 m +234 702 208 692 187 671 c +166 650 156 624 156 592 c +156 558 163 530 178 507 c +193 485 217 466 251 451 c +327 417 379 382 408 345 c +437 309 451 262 451 203 c +451 138 433 90 398 57 c +363 24 312 8 246 8 c +184 8 128 27 77 65 c +77 162 l +132 109 190 82 251 82 c +328 82 367 122 367 203 c +367 240 358 271 340 296 c +322 321 292 342 251 361 c +187 390 141 422 113 459 c +86 496 72 540 72 592 c +72 647 89 691 124 725 c +159 759 204 776 261 776 c +297 776 327 773 350 768 c +373 763 400 752 430 735 c +430 643 l +377 682 323 702 266 702 c + +ce} _d +/T{512 0 56 18 456 766 sc +214 18 m +214 694 l +56 694 l +56 766 l +456 766 l +456 694 l +298 694 l +298 18 l +214 18 l + +ce} _d +/U{512 0 61 8 451 766 sc +402 58 m +369 25 321 8 256 8 c +191 8 143 25 110 58 c +77 91 61 143 61 213 c +61 766 l +147 766 l +147 233 l +147 178 156 139 174 116 c +193 93 221 82 258 82 c +295 82 323 93 341 116 c +360 139 369 178 369 233 c +369 766 l +451 766 l +451 213 l +451 143 435 91 402 58 c + +ce} _d +/V{512 0 31 18 481 766 sc +259 90 m +397 766 l +481 766 l +307 18 l +205 18 l +31 766 l +119 766 l +257 90 l +259 90 l + +ce} _d +/W{512 0 26 18 486 766 sc +157 141 m +159 141 l +214 664 l +306 664 l +361 141 l +364 141 l +410 766 l +486 766 l +425 18 l +313 18 l +257 551 l +255 551 l +199 18 l +87 18 l +26 766 l +111 766 l +157 141 l + +ce} _d +/X{512 0 51 18 461 766 sc +257 469 m +259 469 l +374 766 l +459 766 l +307 402 l +461 18 l +369 18 l +255 331 l +253 331 l +138 18 l +51 18 l +205 402 l +53 766 l +143 766 l +257 469 l + +ce} _d +/Y{512 0 31 18 481 766 sc +257 402 m +259 402 l +394 766 l +481 766 l +298 315 l +298 18 l +214 18 l +214 315 l +31 766 l +123 766 l +257 402 l + +ce} _d +/Z{512 0 77 18 435 766 sc +343 692 m +343 694 l +77 694 l +77 766 l +435 766 l +435 694 l +169 92 l +169 90 l +435 90 l +435 18 l +77 18 l +77 90 l +343 692 l + +ce} _d +/a{512 0 61 8 440 561 sc +261 561 m +330 561 377 547 402 520 c +427 493 440 442 440 367 c +440 18 l +367 18 l +365 95 l +362 95 l +330 37 279 8 210 8 c +165 8 129 22 102 50 c +75 79 61 118 61 167 c +61 229 82 277 124 310 c +166 344 229 361 312 361 c +361 361 l +361 387 l +361 426 353 453 338 469 c +323 485 298 493 261 493 c +238 493 210 489 175 480 c +140 472 111 463 87 452 c +87 525 l +111 536 140 544 174 551 c +208 558 237 561 261 561 c + +361 300 m +312 300 l +196 300 138 257 138 172 c +138 141 146 118 161 101 c +177 85 198 77 225 77 c +266 77 298 93 323 126 c +348 159 361 205 361 264 c +361 300 l + +ce} _d +/e{512 0 56 8 445 561 sc +141 258 m +144 195 157 149 180 121 c +203 93 237 79 282 79 c +323 79 369 91 420 116 c +420 34 l +369 17 321 8 276 8 c +129 8 56 100 56 285 c +56 381 73 451 107 495 c +142 539 193 561 261 561 c +323 561 369 540 399 497 c +430 455 445 386 445 290 c +445 283 444 272 443 258 c +141 258 l + +141 326 m +365 326 l +364 435 330 490 261 490 c +222 490 193 478 174 453 c +155 429 144 387 141 326 c + +ce} _d +/i{512 0 97 18 435 797 sc +324 551 m +324 88 l +435 88 l +435 18 l +97 18 l +97 88 l +240 88 l +240 481 l +128 481 l +128 551 l +324 551 l + +219 674 m +219 797 l +324 797 l +324 674 l +219 674 l + +ce} _d +/n{512 0 72 18 451 561 sc +451 356 m +451 18 l +372 18 l +372 338 l +372 398 365 438 351 458 c +338 478 313 488 276 488 c +242 488 213 469 189 431 c +165 393 153 341 153 276 c +153 18 l +72 18 l +72 551 l +147 551 l +150 474 l +152 474 l +165 500 184 521 211 537 c +238 553 266 561 297 561 c +351 561 390 545 414 514 c +439 483 451 431 451 356 c + +ce} _d +/o{512 0 51 8 461 561 sc +51 284 m +51 469 119 561 256 561 c +393 561 461 469 461 284 c +461 100 393 8 256 8 c +119 8 51 100 51 284 c + +164 125 m +184 94 215 79 256 79 c +297 79 328 94 347 125 c +367 156 377 209 377 284 c +377 359 367 412 347 443 c +328 474 297 490 256 490 c +215 490 184 474 164 443 c +145 412 135 359 135 284 c +135 209 145 156 164 125 c + +ce} _d +/u{512 0 67 8 435 551 sc +67 203 m +67 551 l +145 551 l +145 221 l +145 164 151 127 164 108 c +177 90 201 81 236 81 c +269 81 297 100 320 137 c +343 175 354 227 354 293 c +354 551 l +435 551 l +435 18 l +359 18 l +357 95 l +355 95 l +342 68 323 46 298 31 c +273 16 245 8 215 8 c +162 8 124 23 101 52 c +78 81 67 132 67 203 c + +ce} _d +end readonly def + +/BuildGlyph { + exch begin + CharStrings exch + 2 copy known not {pop /.notdef} if + true 3 1 roll get exec + end +} _d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +} _d + +FontName currentdict end definefont pop +end +%%EndProlog +mpldict begin +0 0 translate +0 0 504 72 rectclip +gsave +0 0 m +504 0 l +504 72 l +0 72 l +cl +1 setgray +fill +grestore +gsave +0 36 m +504 36 l +504 72 l +0 72 l +0 36 l +cl +grestore +0 setgray +/WenQuanYiZenHei 16.000 selectfont +gsave + +55.4375 49.7812 translate +0 rotate +0 0 m /W glyphshow +13.1094 0 m /e glyphshow +21.7344 0 m /n glyphshow +30.3594 0 m /Q glyphshow +40.9062 0 m /u glyphshow +49.5312 0 m /a glyphshow +58.1562 0 m /n glyphshow +66.7812 0 m /Y glyphshow +75.7344 0 m /i glyphshow +79.5625 0 m /space glyphshow +84.3594 0 m /Z glyphshow +92.9844 0 m /e glyphshow +101.609 0 m /n glyphshow +110.234 0 m /space glyphshow +115.031 0 m /H glyphshow +125.578 0 m /e glyphshow +134.203 0 m /i glyphshow +138.031 0 m /colon glyphshow +142.828 0 m /space glyphshow +147.625 0 m /A glyphshow +156.578 0 m /B glyphshow +166.484 0 m /C glyphshow +176.391 0 m /D glyphshow +186.938 0 m /E glyphshow +195.891 0 m /F glyphshow +203.562 0 m /G glyphshow +214.109 0 m /H glyphshow +224.656 0 m /I glyphshow +228.812 0 m /J glyphshow +235.203 0 m /K glyphshow +245.109 0 m /L glyphshow +253.109 0 m /M glyphshow +266.219 0 m /N glyphshow +276.766 0 m /O glyphshow +287.312 0 m /P glyphshow +296.266 0 m /Q glyphshow +306.812 0 m /R glyphshow +316.719 0 m /S glyphshow +326.625 0 m /T glyphshow +334.625 0 m /U glyphshow +344.859 0 m /V glyphshow +353.812 0 m /W glyphshow +366.922 0 m /X glyphshow +375.547 0 m /Y glyphshow +384.5 0 m /Z glyphshow +grestore +gsave +0 0 m +504 0 l +504 36 l +0 36 l +0 0 l +cl +grestore +/WenQuanYiZenHeiMono 16.000 selectfont +gsave + +52 13.6328 translate +0 rotate +0 0 m /W glyphshow +8 0 m /e glyphshow +16 0 m /n glyphshow +24 0 m /Q glyphshow +32 0 m /u glyphshow +40 0 m /a glyphshow +48 0 m /n glyphshow +56 0 m /Y glyphshow +64 0 m /i glyphshow +72 0 m /space glyphshow +80 0 m /Z glyphshow +88 0 m /e glyphshow +96 0 m /n glyphshow +104 0 m /space glyphshow +112 0 m /H glyphshow +120 0 m /e glyphshow +128 0 m /i glyphshow +136 0 m /space glyphshow +144 0 m /M glyphshow +152 0 m /o glyphshow +160 0 m /n glyphshow +168 0 m /o glyphshow +176 0 m /colon glyphshow +184 0 m /space glyphshow +192 0 m /A glyphshow +200 0 m /B glyphshow +208 0 m /C glyphshow +216 0 m /D glyphshow +224 0 m /E glyphshow +232 0 m /F glyphshow +240 0 m /G glyphshow +248 0 m /H glyphshow +256 0 m /I glyphshow +264 0 m /J glyphshow +272 0 m /K glyphshow +280 0 m /L glyphshow +288 0 m /M glyphshow +296 0 m /N glyphshow +304 0 m /O glyphshow +312 0 m /P glyphshow +320 0 m /Q glyphshow +328 0 m /R glyphshow +336 0 m /S glyphshow +344 0 m /T glyphshow +352 0 m /U glyphshow +360 0 m /V glyphshow +368 0 m /W glyphshow +376 0 m /X glyphshow +384 0 m /Y glyphshow +392 0 m /Z glyphshow +grestore + +end +showpage diff --git a/lib/matplotlib/tests/test_backend_pdf.py b/lib/matplotlib/tests/test_backend_pdf.py index f126fb543e78..c2b8d780ab8f 100644 --- a/lib/matplotlib/tests/test_backend_pdf.py +++ b/lib/matplotlib/tests/test_backend_pdf.py @@ -3,6 +3,7 @@ import io import os from pathlib import Path +import string import numpy as np import pytest @@ -363,7 +364,7 @@ def test_glyphs_subset(): nosubfont.set_text(chars) # subsetted FT2Font - with get_glyphs_subset(fpath, chars) as subset: + with get_glyphs_subset(fm.FontPath(fpath, 0), chars) as subset: subfont = FT2Font(font_as_file(subset)) subfont.set_text(chars) @@ -402,6 +403,38 @@ def test_multi_font_type42(): horizontalalignment='center', verticalalignment='center') +@image_comparison(['ttc_type3.pdf'], style='mpl20') +def test_ttc_type3(): + fp = fm.FontProperties(family=['WenQuanYi Zen Hei']) + if Path(fm.findfont(fp)).name != 'wqy-zenhei.ttc': + pytest.skip('Font wqy-zenhei.ttc may be missing') + + fonts = ['WenQuanYi Zen Hei', 'WenQuanYi Zen Hei Mono'] + plt.rc('font', size=16) + plt.rc('pdf', fonttype=3) + + figs = plt.figure(figsize=(7, len(fonts) / 2)).subfigures(len(fonts)) + for font, fig in zip(fonts, figs): + fig.text(0.5, 0.5, f'{font}: {string.ascii_uppercase}', font=font, + horizontalalignment='center', verticalalignment='center') + + +@image_comparison(['ttc_type42.pdf'], style='mpl20') +def test_ttc_type42(): + fp = fm.FontProperties(family=['WenQuanYi Zen Hei']) + if Path(fm.findfont(fp)).name != 'wqy-zenhei.ttc': + pytest.skip('Font wqy-zenhei.ttc may be missing') + + fonts = ['WenQuanYi Zen Hei', 'WenQuanYi Zen Hei Mono'] + plt.rc('font', size=16) + plt.rc('pdf', fonttype=42) + + figs = plt.figure(figsize=(7, len(fonts) / 2)).subfigures(len(fonts)) + for font, fig in zip(fonts, figs): + fig.text(0.5, 0.5, f'{font}: {string.ascii_uppercase}', font=font, + horizontalalignment='center', verticalalignment='center') + + @pytest.mark.parametrize('family_name, file_name', [("Noto Sans", "NotoSans-Regular.otf"), ("FreeMono", "FreeMono.otf")]) diff --git a/lib/matplotlib/tests/test_backend_ps.py b/lib/matplotlib/tests/test_backend_ps.py index f5ec85005079..5fc97c14188b 100644 --- a/lib/matplotlib/tests/test_backend_ps.py +++ b/lib/matplotlib/tests/test_backend_ps.py @@ -1,12 +1,14 @@ from collections import Counter import io +from pathlib import Path import re +import string import tempfile import numpy as np import pytest -from matplotlib import cbook, path, patheffects +from matplotlib import cbook, font_manager, path, patheffects from matplotlib.figure import Figure from matplotlib.patches import Ellipse from matplotlib.testing import _gen_multi_font_text @@ -340,6 +342,38 @@ def test_multi_font_type42(): horizontalalignment='center', verticalalignment='center') +@image_comparison(['ttc_type3.eps'], style='mpl20') +def test_ttc_type3(): + fp = font_manager.FontProperties(family=['WenQuanYi Zen Hei']) + if Path(font_manager.findfont(fp)).name != 'wqy-zenhei.ttc': + pytest.skip('Font wqy-zenhei.ttc may be missing') + + fonts = ['WenQuanYi Zen Hei', 'WenQuanYi Zen Hei Mono'] + plt.rc('font', size=16) + plt.rc('pdf', fonttype=3) + + figs = plt.figure(figsize=(7, len(fonts) / 2)).subfigures(len(fonts)) + for font, fig in zip(fonts, figs): + fig.text(0.5, 0.5, f'{font}: {string.ascii_uppercase}', font=font, + horizontalalignment='center', verticalalignment='center') + + +@image_comparison(['ttc_type42.eps'], style='mpl20') +def test_ttc_type42(): + fp = font_manager.FontProperties(family=['WenQuanYi Zen Hei']) + if Path(font_manager.findfont(fp)).name != 'wqy-zenhei.ttc': + pytest.skip('Font wqy-zenhei.ttc may be missing') + + fonts = ['WenQuanYi Zen Hei', 'WenQuanYi Zen Hei Mono'] + plt.rc('font', size=16) + plt.rc('pdf', fonttype=42) + + figs = plt.figure(figsize=(7, len(fonts) / 2)).subfigures(len(fonts)) + for font, fig in zip(fonts, figs): + fig.text(0.5, 0.5, f'{font}: {string.ascii_uppercase}', font=font, + horizontalalignment='center', verticalalignment='center') + + @image_comparison(["scatter.eps"]) def test_path_collection(): rng = np.random.default_rng(19680801) From d86660b4ab1c44af543b42e1dbd5da3e594b053c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Fri, 25 Jul 2025 19:53:21 -0400 Subject: [PATCH 6/6] pgf: Support any font in a collection Note, this only has an effect if set as the global font. Otherwise, just the font name is recorded, and the TeX engine's normal lookup is performed. --- lib/matplotlib/backends/backend_pgf.py | 25 +++++++++--------- .../test_backend_pgf/ttc_pgf.pdf | Bin 0 -> 15526 bytes lib/matplotlib/tests/test_backend_pgf.py | 20 ++++++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_backend_pgf/ttc_pgf.pdf diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py index 48b6e8ac152c..ab9782b369a3 100644 --- a/lib/matplotlib/backends/backend_pgf.py +++ b/lib/matplotlib/backends/backend_pgf.py @@ -38,9 +38,17 @@ def _get_preamble(): """Prepare a LaTeX preamble based on the rcParams configuration.""" - font_size_pt = FontProperties( - size=mpl.rcParams["font.size"] - ).get_size_in_points() + def _to_fontspec(): + for command, family in [("setmainfont", "serif"), + ("setsansfont", "sans\\-serif"), + ("setmonofont", "monospace")]: + font_path = fm.findfont(family) + path = pathlib.Path(font_path) + yield r" \%s{%s}[Path=\detokenize{%s/}%s]" % ( + command, path.name, path.parent.as_posix(), + f',FontIndex={font_path.face_index:d}' if path.suffix == '.ttc' else '') + + font_size_pt = FontProperties(size=mpl.rcParams["font.size"]).get_size_in_points() return "\n".join([ # Remove Matplotlib's custom command \mathdefault. (Not using # \mathnormal instead since this looks odd with Computer Modern.) @@ -63,15 +71,8 @@ def _get_preamble(): *([ r"\ifdefined\pdftexversion\else % non-pdftex case.", r" \usepackage{fontspec}", - ] + [ - r" \%s{%s}[Path=\detokenize{%s/}]" - % (command, path.name, path.parent.as_posix()) - for command, path in zip( - ["setmainfont", "setsansfont", "setmonofont"], - [pathlib.Path(fm.findfont(family)) - for family in ["serif", "sans\\-serif", "monospace"]] - ) - ] + [r"\fi"] if mpl.rcParams["pgf.rcfonts"] else []), + *_to_fontspec(), + r"\fi"] if mpl.rcParams["pgf.rcfonts"] else []), # Documented as "must come last". mpl.texmanager._usepackage_if_not_loaded("underscore", option="strings"), ]) diff --git a/lib/matplotlib/tests/baseline_images/test_backend_pgf/ttc_pgf.pdf b/lib/matplotlib/tests/baseline_images/test_backend_pgf/ttc_pgf.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5d695e734577100ab881040016fbbdb0d76a016a GIT binary patch literal 15526 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 K pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy