|
21 | 21 | from matplotlib.backends.backend_mixed import MixedModeRenderer |
22 | 22 | from matplotlib.colors import rgb2hex |
23 | 23 | from matplotlib.dates import UTC |
24 | | -from matplotlib.font_manager import findfont, get_font |
| 24 | +from matplotlib.font_manager import findfont, get_font, ttfFontProperty |
25 | 25 | from matplotlib.ft2font import LOAD_NO_HINTING |
26 | 26 | from matplotlib.mathtext import MathTextParser |
27 | 27 | from matplotlib.path import Path |
@@ -94,6 +94,12 @@ def escape_attrib(s): |
94 | 94 | return s |
95 | 95 |
|
96 | 96 |
|
| 97 | +def _quote_escape_attrib(s): |
| 98 | + return ('"' + escape_cdata(s) + '"' if '"' not in s else |
| 99 | + "'" + escape_cdata(s) + "'" if "'" not in s else |
| 100 | + '"' + escape_attrib(s) + '"') |
| 101 | + |
| 102 | + |
97 | 103 | def short_float_fmt(x): |
98 | 104 | """ |
99 | 105 | Create a short string representation of a float, which is %f |
@@ -159,8 +165,8 @@ def start(self, tag, attrib={}, **extra): |
159 | 165 | for k, v in sorted({**attrib, **extra}.items()): |
160 | 166 | if v: |
161 | 167 | k = escape_cdata(k) |
162 | | - v = escape_attrib(v) |
163 | | - self.__write(' %s="%s"' % (k, v)) |
| 168 | + v = _quote_escape_attrib(v) |
| 169 | + self.__write(' %s=%s' % (k, v)) |
164 | 170 | self.__open = 1 |
165 | 171 | return len(self.__tags) - 1 |
166 | 172 |
|
@@ -1197,11 +1203,21 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
1197 | 1203 | # Sort the characters by font, and output one tspan for each. |
1198 | 1204 | spans = OrderedDict() |
1199 | 1205 | for font, fontsize, thetext, new_x, new_y in glyphs: |
1200 | | - style = generate_css({ |
1201 | | - 'font-size': short_float_fmt(fontsize) + 'px', |
1202 | | - 'font-family': font.family_name, |
1203 | | - 'font-style': font.style_name.lower(), |
1204 | | - 'font-weight': font.style_name.lower()}) |
| 1206 | + entry = ttfFontProperty(font) |
| 1207 | + font_parts = ['font:'] |
| 1208 | + if entry.style != 'normal': |
| 1209 | + font_parts.append(entry.style) |
| 1210 | + if entry.variant != 'normal': |
| 1211 | + font_parts.append(entry.variant) |
| 1212 | + if entry.weight != 400: |
| 1213 | + font_parts.append(f'{entry.weight}') |
| 1214 | + font_parts.extend([ |
| 1215 | + f'{short_float_fmt(fontsize)}px', |
| 1216 | + f'{entry.name!r}', # ensure quoting |
| 1217 | + ]) |
| 1218 | + if entry.stretch != 'normal': |
| 1219 | + font_parts.extend(['; font-stretch:', entry.stretch]) |
| 1220 | + style = ' '.join(font_parts) |
1205 | 1221 | if thetext == 32: |
1206 | 1222 | thetext = 0xa0 # non-breaking space |
1207 | 1223 | spans.setdefault(style, []).append((new_x, -new_y, thetext)) |
|
0 commit comments