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 92e57c8

Browse filesBrowse files
efiringmdboom
authored andcommitted
Merge pull request #5651 from mdboom/shorter-svg-files
Shorter svg files
1 parent 5f1127c commit 92e57c8
Copy full SHA for 92e57c8

File tree

Expand file treeCollapse file tree

3 files changed

+13076
-19306
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+13076
-19306
lines changed

‎lib/matplotlib/backends/backend_svg.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/backend_svg.py
+58-39Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ def escape_attrib(s):
8787
s = s.replace(">", ">")
8888
return s
8989

90+
def short_float_fmt(x):
91+
"""
92+
Create a short string representation of a float, which is %f
93+
formatting with trailing zeros and the decimal point removed.
94+
"""
95+
return '{0:f}'.format(x).rstrip('0').rstrip('.')
96+
9097
##
9198
# XML writer class.
9299
#
@@ -231,7 +238,8 @@ def generate_transform(transform_list=[]):
231238
if type == 'matrix' and isinstance(value, Affine2DBase):
232239
value = value.to_values()
233240

234-
output.write('%s(%s)' % (type, ' '.join(str(x) for x in value)))
241+
output.write('%s(%s)' % (
242+
type, ' '.join(short_float_fmt(x) for x in value)))
235243
return output.getvalue()
236244
return ''
237245

@@ -403,32 +411,32 @@ def _get_style_dict(self, gc, rgbFace):
403411
if gc.get_hatch() is not None:
404412
attrib['fill'] = "url(#%s)" % self._get_hatch(gc, rgbFace)
405413
if rgbFace is not None and len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
406-
attrib['fill-opacity'] = str(rgbFace[3])
414+
attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
407415
else:
408416
if rgbFace is None:
409417
attrib['fill'] = 'none'
410418
else:
411419
if tuple(rgbFace[:3]) != (0, 0, 0):
412420
attrib['fill'] = rgb2hex(rgbFace)
413421
if len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
414-
attrib['fill-opacity'] = str(rgbFace[3])
422+
attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
415423

416424
if forced_alpha and gc.get_alpha() != 1.0:
417-
attrib['opacity'] = str(gc.get_alpha())
425+
attrib['opacity'] = short_float_fmt(gc.get_alpha())
418426

419427
offset, seq = gc.get_dashes()
420428
if seq is not None:
421-
attrib['stroke-dasharray'] = ','.join(['%f' % val for val in seq])
422-
attrib['stroke-dashoffset'] = six.text_type(float(offset))
429+
attrib['stroke-dasharray'] = ','.join([short_float_fmt(val) for val in seq])
430+
attrib['stroke-dashoffset'] = short_float_fmt(float(offset))
423431

424432
linewidth = gc.get_linewidth()
425433
if linewidth:
426434
rgb = gc.get_rgb()
427435
attrib['stroke'] = rgb2hex(rgb)
428436
if not forced_alpha and rgb[3] != 1.0:
429-
attrib['stroke-opacity'] = str(rgb[3])
437+
attrib['stroke-opacity'] = short_float_fmt(rgb[3])
430438
if linewidth != 1.0:
431-
attrib['stroke-width'] = str(linewidth)
439+
attrib['stroke-width'] = short_float_fmt(linewidth)
432440
if gc.get_joinstyle() != 'round':
433441
attrib['stroke-linejoin'] = gc.get_joinstyle()
434442
if gc.get_capstyle() != 'butt':
@@ -476,8 +484,12 @@ def _write_clips(self):
476484
writer.element('path', d=path_data)
477485
else:
478486
x, y, w, h = clip
479-
writer.element('rect', x=six.text_type(x), y=six.text_type(y),
480-
width=six.text_type(w), height=six.text_type(h))
487+
writer.element(
488+
'rect',
489+
x=short_float_fmt(x),
490+
y=short_float_fmt(y),
491+
width=short_float_fmt(w),
492+
height=short_float_fmt(h))
481493
writer.end('clipPath')
482494
writer.end('defs')
483495

@@ -498,7 +510,8 @@ def _write_svgfonts(self):
498510
'font-family': font.family_name,
499511
'font-style': font.style_name.lower(),
500512
'units-per-em': '72',
501-
'bbox': ' '.join(six.text_type(x / 64.0) for x in font.bbox)})
513+
'bbox': ' '.join(
514+
short_float_fmt(x / 64.0) for x in font.bbox)})
502515
for char in chars:
503516
glyph = font.load_char(char, flags=LOAD_NO_HINTING)
504517
verts, codes = font.get_path()
@@ -511,7 +524,8 @@ def _write_svgfonts(self):
511524
attrib={
512525
# 'glyph-name': name,
513526
'unicode': unichr(char),
514-
'horiz-adv-x': six.text_type(glyph.linearHoriAdvance / 65536.0)})
527+
'horiz-adv-x':
528+
short_float_fmt(glyph.linearHoriAdvance / 65536.0)})
515529
writer.end('font')
516530
writer.end('defs')
517531

@@ -607,8 +621,8 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None)
607621
trans_and_flip, clip=clip, simplify=False):
608622
if len(vertices):
609623
x, y = vertices[-2:]
610-
attrib['x'] = six.text_type(x)
611-
attrib['y'] = six.text_type(y)
624+
attrib['x'] = short_float_fmt(x)
625+
attrib['y'] = short_float_fmt(y)
612626
attrib['style'] = self._get_style(gc, rgbFace)
613627
writer.element('use', attrib=attrib)
614628
writer.end('g')
@@ -659,8 +673,8 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms,
659673
writer.start('g', attrib={'clip-path': 'url(#%s)' % clipid})
660674
attrib = {
661675
'xlink:href': '#%s' % path_id,
662-
'x': six.text_type(xo),
663-
'y': six.text_type(self.height - yo),
676+
'x': short_float_fmt(xo),
677+
'y': short_float_fmt(self.height - yo),
664678
'style': self._get_style(gc0, rgbFace)
665679
}
666680
writer.element('use', attrib=attrib)
@@ -729,13 +743,13 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
729743
writer.start(
730744
'linearGradient',
731745
id="GR%x_%d" % (self._n_gradients, i),
732-
x1=six.text_type(x1), y1=six.text_type(y1),
733-
x2=six.text_type(xb), y2=six.text_type(yb))
746+
x1=short_float_fmt(x1), y1=short_float_fmt(y1),
747+
x2=short_float_fmt(xb), y2=short_float_fmt(yb))
734748
writer.element(
735749
'stop',
736750
offset='0',
737751
style=generate_css({'stop-color': rgb2hex(c),
738-
'stop-opacity': six.text_type(c[-1])}))
752+
'stop-opacity': short_float_fmt(c[-1])}))
739753
writer.element(
740754
'stop',
741755
offset='1',
@@ -746,7 +760,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
746760
writer.element(
747761
'polygon',
748762
id='GT%x' % self._n_gradients,
749-
points=" ".join([six.text_type(x)
763+
points=" ".join([short_float_fmt(x)
750764
for x in (x1, y1, x2, y2, x3, y3)]))
751765
writer.end('defs')
752766

@@ -756,7 +770,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
756770
'use',
757771
attrib={'xlink:href': href,
758772
'fill': rgb2hex(avg_color),
759-
'fill-opacity': str(avg_color[-1])})
773+
'fill-opacity': short_float_fmt(avg_color[-1])})
760774
for i in range(3):
761775
writer.element(
762776
'use',
@@ -842,16 +856,16 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
842856

843857
alpha = gc.get_alpha()
844858
if alpha != 1.0:
845-
attrib['opacity'] = str(alpha)
859+
attrib['opacity'] = short_float_fmt(alpha)
846860

847861
attrib['id'] = oid
848862

849863
if transform is None:
850864
self.writer.element(
851865
'image',
852-
x=six.text_type(x/trans[0]),
853-
y=six.text_type((self.height-y)/trans[3]-h),
854-
width=six.text_type(w), height=six.text_type(h),
866+
x=short_float_fmt(x/trans[0]),
867+
y=short_float_fmt((self.height-y)/trans[3]-h),
868+
width=short_float_fmt(w), height=short_float_fmt(h),
855869
attrib=attrib)
856870
else:
857871
flipped = self._make_flip_transform(transform)
@@ -864,8 +878,8 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
864878
[('matrix', flipped)])
865879
self.writer.element(
866880
'image',
867-
x=six.text_type(x), y=six.text_type(y),
868-
width=six.text_type(dx), height=six.text_type(abs(dy)),
881+
x=short_float_fmt(x), y=short_float_fmt(y),
882+
width=short_float_fmt(dx), height=short_float_fmt(abs(dy)),
869883
attrib=attrib)
870884

871885
if url is not None:
@@ -906,7 +920,7 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
906920
if color != '#000000':
907921
style['fill'] = color
908922
if gc.get_alpha() != 1.0:
909-
style['opacity'] = six.text_type(gc.get_alpha())
923+
style['opacity'] = short_float_fmt(gc.get_alpha())
910924

911925
if not ismath:
912926
font = text2path._get_font(prop)
@@ -936,9 +950,9 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
936950
for glyph_id, xposition, yposition, scale in glyph_info:
937951
attrib={'xlink:href': '#%s' % glyph_id}
938952
if xposition != 0.0:
939-
attrib['x'] = six.text_type(xposition)
953+
attrib['x'] = short_float_fmt(xposition)
940954
if yposition != 0.0:
941-
attrib['y'] = six.text_type(yposition)
955+
attrib['y'] = short_float_fmt(yposition)
942956
writer.element(
943957
'use',
944958
attrib=attrib)
@@ -1007,7 +1021,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10071021
if color != '#000000':
10081022
style['fill'] = color
10091023
if gc.get_alpha() != 1.0:
1010-
style['opacity'] = six.text_type(gc.get_alpha())
1024+
style['opacity'] = short_float_fmt(gc.get_alpha())
10111025

10121026
if not ismath:
10131027
font = self._get_font(prop)
@@ -1020,7 +1034,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10201034

10211035
attrib = {}
10221036
# Must add "px" to workaround a Firefox bug
1023-
style['font-size'] = six.text_type(fontsize) + 'px'
1037+
style['font-size'] = short_float_fmt(fontsize) + 'px'
10241038
style['font-family'] = six.text_type(fontfamily)
10251039
style['font-style'] = prop.get_style().lower()
10261040
style['font-weight'] = six.text_type(prop.get_weight()).lower()
@@ -1048,10 +1062,13 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10481062
'center': 'middle'}
10491063
style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()]
10501064

1051-
attrib['x'] = str(ax)
1052-
attrib['y'] = str(ay)
1065+
attrib['x'] = short_float_fmt(ax)
1066+
attrib['y'] = short_float_fmt(ay)
10531067
attrib['style'] = generate_css(style)
1054-
attrib['transform'] = "rotate(%f, %f, %f)" % (-angle, ax, ay)
1068+
attrib['transform'] = "rotate(%s, %s, %s)" % (
1069+
short_float_fmt(-angle),
1070+
short_float_fmt(ax),
1071+
short_float_fmt(ay))
10551072
writer.element('text', s, attrib=attrib)
10561073
else:
10571074
attrib['transform'] = generate_transform([
@@ -1090,7 +1107,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10901107
spans = {}
10911108
for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs:
10921109
style = generate_css({
1093-
'font-size': six.text_type(fontsize) + 'px',
1110+
'font-size': short_float_fmt(fontsize) + 'px',
10941111
'font-family': font.family_name,
10951112
'font-style': font.style_name.lower(),
10961113
'font-weight': font.style_name.lower()})
@@ -1120,7 +1137,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11201137

11211138
attrib = {
11221139
'style': style,
1123-
'x': ' '.join(six.text_type(c[0]) for c in chars),
1140+
'x': ' '.join(short_float_fmt(c[0]) for c in chars),
11241141
'y': ys
11251142
}
11261143

@@ -1135,8 +1152,10 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11351152
for x, y, width, height in svg_rects:
11361153
writer.element(
11371154
'rect',
1138-
x=six.text_type(x), y=six.text_type(-y + height),
1139-
width=six.text_type(width), height=six.text_type(height)
1155+
x=short_float_fmt(x),
1156+
y=short_float_fmt(-y + height),
1157+
width=short_float_fmt(width),
1158+
height=short_float_fmt(height)
11401159
)
11411160

11421161
writer.end('g')

0 commit comments

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