Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 45cd371

Browse filesBrowse files
committed
backend_svg: separate font attributes && use translate(x y) in RendedSVG._draw_text_as_path
fixed linting (flake8 test failing) Fixed checks in testing for svg.fonttype = none fixed flake8 && failing tests linting modified tspans && fix to svg tests Updated baseline images for svg tests Update lib/matplotlib/testing/compare.py nicer regex to check if font syling in svg is specified Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Apply suggestions from code review More concise font testing in test_backend_svg.py Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Update lib/matplotlib/tests/test_mathtext.py Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Update backend_svg.py inlining `style` restored test images update to baseline images Fix to regex for testing/compare.py::compare forgot one baseline image
1 parent ed17e00 commit 45cd371
Copy full SHA for 45cd371
Expand file treeCollapse file tree

30 files changed

+14072
-13299
lines changed
Open diff view settings
Collapse file

‎lib/matplotlib/backends/backend_svg.py‎

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_svg.py
+43-52Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,12 +1066,13 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10661066
self._update_glyph_map_defs(glyph_map_new)
10671067

10681068
for glyph_id, xposition, yposition, scale in glyph_info:
1069-
attrib = {'xlink:href': f'#{glyph_id}'}
1070-
if xposition != 0.0:
1071-
attrib['x'] = _short_float_fmt(xposition)
1072-
if yposition != 0.0:
1073-
attrib['y'] = _short_float_fmt(yposition)
1074-
writer.element('use', attrib=attrib)
1069+
writer.element(
1070+
'use',
1071+
transform=_generate_transform([
1072+
('translate', (xposition, yposition)),
1073+
('scale', (scale,)),
1074+
]),
1075+
attrib={'xlink:href': f'#{glyph_id}'})
10751076

10761077
else:
10771078
if ismath == "TeX":
@@ -1109,25 +1110,26 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11091110
writer = self.writer
11101111

11111112
color = rgb2hex(gc.get_rgb())
1112-
style = {}
1113+
font_style = {}
1114+
color_style = {}
11131115
if color != '#000000':
1114-
style['fill'] = color
1116+
color_style['fill'] = color
11151117

11161118
alpha = gc.get_alpha() if gc.get_forced_alpha() else gc.get_rgb()[3]
11171119
if alpha != 1:
1118-
style['opacity'] = _short_float_fmt(alpha)
1120+
color_style['opacity'] = _short_float_fmt(alpha)
11191121

11201122
if not ismath:
11211123
attrib = {}
11221124

1123-
font_parts = []
1125+
# Separate font style in their separate attributes
11241126
if prop.get_style() != 'normal':
1125-
font_parts.append(prop.get_style())
1127+
font_style['font-style'] = prop.get_style()
11261128
if prop.get_variant() != 'normal':
1127-
font_parts.append(prop.get_variant())
1129+
font_style['font-variant'] = prop.get_variant()
11281130
weight = fm.weight_dict[prop.get_weight()]
11291131
if weight != 400:
1130-
font_parts.append(f'{weight}')
1132+
font_style['font-weight'] = f'{weight}'
11311133

11321134
def _normalize_sans(name):
11331135
return 'sans-serif' if name in ['sans', 'sans serif'] else name
@@ -1150,15 +1152,15 @@ def _get_all_quoted_names(prop):
11501152
for entry in prop.get_family()
11511153
for name in _expand_family_entry(entry)]
11521154

1153-
font_parts.extend([
1154-
f'{_short_float_fmt(prop.get_size())}px',
1155-
# ensure expansion, quoting, and dedupe of font names
1156-
", ".join(dict.fromkeys(_get_all_quoted_names(prop)))
1157-
])
1158-
style['font'] = ' '.join(font_parts)
1155+
font_style['font-size'] = f'{_short_float_fmt(prop.get_size())}px'
1156+
# ensure expansion, quoting, and dedupe of font names
1157+
font_style['font-family'] = ", ".join(
1158+
dict.fromkeys(_get_all_quoted_names(prop))
1159+
)
1160+
11591161
if prop.get_stretch() != 'normal':
1160-
style['font-stretch'] = prop.get_stretch()
1161-
attrib['style'] = _generate_css(style)
1162+
font_style['font-stretch'] = prop.get_stretch()
1163+
attrib['style'] = _generate_css({**font_style, **color_style})
11621164

11631165
if mtext and (angle == 0 or mtext.get_rotation_mode() == "anchor"):
11641166
# If text anchoring can be supported, get the original
@@ -1180,11 +1182,11 @@ def _get_all_quoted_names(prop):
11801182

11811183
ha_mpl_to_svg = {'left': 'start', 'right': 'end',
11821184
'center': 'middle'}
1183-
style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()]
1185+
font_style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()]
11841186

11851187
attrib['x'] = _short_float_fmt(ax)
11861188
attrib['y'] = _short_float_fmt(ay)
1187-
attrib['style'] = _generate_css(style)
1189+
attrib['style'] = _generate_css({**font_style, **color_style})
11881190
attrib['transform'] = _generate_transform([
11891191
("rotate", (-angle, ax, ay))])
11901192

@@ -1204,7 +1206,7 @@ def _get_all_quoted_names(prop):
12041206
# Apply attributes to 'g', not 'text', because we likely have some
12051207
# rectangles as well with the same style and transformation.
12061208
writer.start('g',
1207-
style=_generate_css(style),
1209+
style=_generate_css({**font_style, **color_style}),
12081210
transform=_generate_transform([
12091211
('translate', (x, y)),
12101212
('rotate', (-angle,))]),
@@ -1216,43 +1218,32 @@ def _get_all_quoted_names(prop):
12161218
spans = {}
12171219
for font, fontsize, thetext, new_x, new_y in glyphs:
12181220
entry = fm.ttfFontProperty(font)
1219-
font_parts = []
1221+
font_style = {}
1222+
# Separate font style in its separate attributes
12201223
if entry.style != 'normal':
1221-
font_parts.append(entry.style)
1224+
font_style['font-style'] = entry.style
12221225
if entry.variant != 'normal':
1223-
font_parts.append(entry.variant)
1226+
font_style['font-variant'] = entry.variant
12241227
if entry.weight != 400:
1225-
font_parts.append(f'{entry.weight}')
1226-
font_parts.extend([
1227-
f'{_short_float_fmt(fontsize)}px',
1228-
f'{entry.name!r}', # ensure quoting
1229-
])
1230-
style = {'font': ' '.join(font_parts)}
1228+
font_style['font-weight'] = f'{entry.weight}'
1229+
font_style['font-size'] = f'{_short_float_fmt(fontsize)}px'
1230+
font_style['font-family'] = f'{entry.name!r}' # ensure quoting
12311231
if entry.stretch != 'normal':
1232-
style['font-stretch'] = entry.stretch
1233-
style = _generate_css(style)
1232+
font_style['font-stretch'] = entry.stretch
1233+
style = _generate_css({**font_style, **color_style})
12341234
if thetext == 32:
12351235
thetext = 0xa0 # non-breaking space
12361236
spans.setdefault(style, []).append((new_x, -new_y, thetext))
12371237

12381238
for style, chars in spans.items():
1239-
chars.sort()
1240-
1241-
if len({y for x, y, t in chars}) == 1: # Are all y's the same?
1242-
ys = str(chars[0][1])
1243-
else:
1244-
ys = ' '.join(str(c[1]) for c in chars)
1245-
1246-
attrib = {
1247-
'style': style,
1248-
'x': ' '.join(_short_float_fmt(c[0]) for c in chars),
1249-
'y': ys
1250-
}
1251-
1252-
writer.element(
1253-
'tspan',
1254-
''.join(chr(c[2]) for c in chars),
1255-
attrib=attrib)
1239+
chars.sort() # Sort by increasing x position
1240+
for x, y, t in chars: # Output one tspan for each character
1241+
writer.element(
1242+
'tspan',
1243+
chr(t),
1244+
x=_short_float_fmt(x),
1245+
y=_short_float_fmt(y),
1246+
style=style)
12561247

12571248
writer.end('text')
12581249

Collapse file

‎lib/matplotlib/testing/compare.py‎

Copy file name to clipboardExpand all lines: lib/matplotlib/testing/compare.py
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import sys
1414
from tempfile import TemporaryDirectory, TemporaryFile
1515
import weakref
16+
import re
1617

1718
import numpy as np
1819
from PIL import Image
@@ -305,7 +306,15 @@ def convert(filename, cache):
305306
# re-generate any SVG test files using this mode, or else such tests will
306307
# fail to use the converter for the expected images (but will for the
307308
# results), and the tests will fail strangely.
308-
if 'style="font:' in contents:
309+
if re.search(
310+
# searches for attributes :
311+
# style=[font|font-size|font-weight|
312+
# font-family|font-variant|font-style]
313+
# taking care of the possibility of multiple style attributes
314+
# before the font styling (i.e. opacity)
315+
r'style="[^"]*font(|-size|-weight|-family|-variant|-style):',
316+
contents # raw contents of the svg file
317+
):
309318
# for svg.fonttype = none, we explicitly patch the font search
310319
# path so that fonts shipped by Matplotlib are found.
311320
convert = _svg_with_matplotlib_fonts_converter

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.