-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Expand file tree
/
Copy path_backend_pdf_ps.py
More file actions
128 lines (107 loc) · 4.05 KB
/
_backend_pdf_ps.py
File metadata and controls
128 lines (107 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""
Common functionality between the PDF and PS backends.
"""
import functools
import matplotlib as mpl
from matplotlib import _api
from .. import font_manager, ft2font
from ..afm import AFM
from ..backend_bases import RendererBase
@functools.lru_cache(50)
def _cached_get_afm_from_fname(fname):
with open(fname, "rb") as fh:
return AFM(fh)
class CharacterTracker:
"""
Helper for font subsetting by the pdf and ps backends.
Maintains a mapping of font paths to the set of character codepoints that
are being used from that font.
"""
def __init__(self):
self.used = {}
@_api.deprecated("3.3")
@property
def used_characters(self):
d = {}
for fname, chars in self.used.items():
realpath, stat_key = mpl.cbook.get_realpath_and_stat(fname)
d[stat_key] = (realpath, chars)
return d
def track(self, font, s):
"""Record that string *s* is being typeset using font *font*."""
if isinstance(font, str):
# Unused, can be removed after removal of track_characters.
fname = font
else:
fname = font.fname
self.used.setdefault(fname, set()).update(map(ord, s))
# Not public, can be removed when pdf/ps merge_used_characters is removed.
def merge(self, other):
"""Update self with a font path to character codepoints."""
for fname, charset in other.items():
self.used.setdefault(fname, set()).update(charset)
class RendererPDFPSBase(RendererBase):
# The following attributes must be defined by the subclasses:
# - _afm_font_dir
# - _use_afm_rc_name
def __init__(self, width, height):
super().__init__()
self.width = width
self.height = height
def flipy(self):
# docstring inherited
return False # y increases from bottom to top.
def option_scale_image(self):
# docstring inherited
return True # PDF and PS support arbitrary image scaling.
def option_image_nocomposite(self):
# docstring inherited
# Decide whether to composite image based on rcParam value.
return not mpl.rcParams["image.composite_image"]
def get_canvas_width_height(self):
# docstring inherited
return self.width * 72.0, self.height * 72.0
def get_text_width_height_descent(self, s, prop, ismath):
# docstring inherited
if ismath == "TeX":
texmanager = self.get_texmanager()
fontsize = prop.get_size_in_points()
w, h, d = texmanager.get_text_width_height_descent(
s, fontsize, renderer=self)
return w, h, d
elif ismath:
# Circular import.
from matplotlib.backends.backend_ps import RendererPS
parse = self._text2path.mathtext_parser.parse(
s, 72, prop,
_force_standard_ps_fonts=(isinstance(self, RendererPS)
and mpl.rcParams["ps.useafm"]))
return parse.width, parse.height, parse.depth
elif mpl.rcParams[self._use_afm_rc_name]:
font = self._get_font_afm(prop)
l, b, w, h, d = font.get_str_bbox_and_descent(s)
scale = prop.get_size_in_points() / 1000
w *= scale
h *= scale
d *= scale
return w, h, d
else:
font = self._get_font_ttf(prop)
font.set_text(s, 0.0, flags=ft2font.LOAD_NO_HINTING)
w, h = font.get_width_height()
d = font.get_descent()
scale = 1 / 64
w *= scale
h *= scale
d *= scale
return w, h, d
def _get_font_afm(self, prop):
fname = font_manager.findfont(
prop, fontext="afm", directory=self._afm_font_dir)
return _cached_get_afm_from_fname(fname)
def _get_font_ttf(self, prop):
fname = font_manager.findfont(prop)
font = font_manager.get_font(fname)
font.clear()
font.set_size(prop.get_size_in_points(), 72)
return font