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 d2d4c80

Browse filesBrowse files
committed
Reduce SVG file size
1 parent 61f0eea commit d2d4c80
Copy full SHA for d2d4c80

File tree

Expand file treeCollapse file tree

1 file changed

+58
-39
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+58
-39
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
@@ -88,6 +88,13 @@ def escape_attrib(s):
8888
s = s.replace(">", ">")
8989
return s
9090

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

235-
output.write('%s(%s)' % (type, ' '.join('%f' % x for x in value)))
242+
output.write('%s(%s)' % (
243+
type, ' '.join(short_float_fmt(x) for x in value)))
236244
return output.getvalue()
237245
return ''
238246

@@ -401,32 +409,32 @@ def _get_style_dict(self, gc, rgbFace):
401409
if gc.get_hatch() is not None:
402410
attrib['fill'] = "url(#%s)" % self._get_hatch(gc, rgbFace)
403411
if rgbFace is not None and len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
404-
attrib['fill-opacity'] = "%f" % rgbFace[3]
412+
attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
405413
else:
406414
if rgbFace is None:
407415
attrib['fill'] = 'none'
408416
else:
409417
if tuple(rgbFace[:3]) != (0, 0, 0):
410418
attrib['fill'] = rgb2hex(rgbFace)
411419
if len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
412-
attrib['fill-opacity'] = "%f" % rgbFace[3]
420+
attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
413421

414422
if forced_alpha and gc.get_alpha() != 1.0:
415-
attrib['opacity'] = "%f" % gc.get_alpha()
423+
attrib['opacity'] = short_float_fmt(gc.get_alpha())
416424

417425
offset, seq = gc.get_dashes()
418426
if seq is not None:
419-
attrib['stroke-dasharray'] = ','.join(['%f' % val for val in seq])
420-
attrib['stroke-dashoffset'] = six.text_type(float(offset))
427+
attrib['stroke-dasharray'] = ','.join([short_float_fmt(val) for val in seq])
428+
attrib['stroke-dashoffset'] = short_float_fmt(float(offset))
421429

422430
linewidth = gc.get_linewidth()
423431
if linewidth:
424432
rgb = gc.get_rgb()
425433
attrib['stroke'] = rgb2hex(rgb)
426434
if not forced_alpha and rgb[3] != 1.0:
427-
attrib['stroke-opacity'] = "%f" % rgb[3]
435+
attrib['stroke-opacity'] = short_float_fmt(rgb[3])
428436
if linewidth != 1.0:
429-
attrib['stroke-width'] = "%f" % linewidth
437+
attrib['stroke-width'] = short_float_fmt(linewidth)
430438
if gc.get_joinstyle() != 'round':
431439
attrib['stroke-linejoin'] = gc.get_joinstyle()
432440
if gc.get_capstyle() != 'butt':
@@ -474,8 +482,12 @@ def _write_clips(self):
474482
writer.element('path', d=path_data)
475483
else:
476484
x, y, w, h = clip
477-
writer.element('rect', x=six.text_type(x), y=six.text_type(y),
478-
width=six.text_type(w), height=six.text_type(h))
485+
writer.element(
486+
'rect',
487+
x=short_float_fmt(x),
488+
y=short_float_fmt(y),
489+
width=short_float_fmt(w),
490+
height=short_float_fmt(h))
479491
writer.end('clipPath')
480492
writer.end('defs')
481493

@@ -496,7 +508,8 @@ def _write_svgfonts(self):
496508
'font-family': font.family_name,
497509
'font-style': font.style_name.lower(),
498510
'units-per-em': '72',
499-
'bbox': ' '.join(six.text_type(x / 64.0) for x in font.bbox)})
511+
'bbox': ' '.join(
512+
short_float_fmt(x / 64.0) for x in font.bbox)})
500513
for char in chars:
501514
glyph = font.load_char(char, flags=LOAD_NO_HINTING)
502515
verts, codes = font.get_path()
@@ -509,7 +522,8 @@ def _write_svgfonts(self):
509522
attrib={
510523
# 'glyph-name': name,
511524
'unicode': unichr(char),
512-
'horiz-adv-x': six.text_type(glyph.linearHoriAdvance / 65536.0)})
525+
'horiz-adv-x':
526+
short_float_fmt(glyph.linearHoriAdvance / 65536.0)})
513527
writer.end('font')
514528
writer.end('defs')
515529

@@ -605,8 +619,8 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None)
605619
trans_and_flip, clip=clip, simplify=False):
606620
if len(vertices):
607621
x, y = vertices[-2:]
608-
attrib['x'] = six.text_type(x)
609-
attrib['y'] = six.text_type(y)
622+
attrib['x'] = short_float_fmt(x)
623+
attrib['y'] = short_float_fmt(y)
610624
attrib['style'] = self._get_style(gc, rgbFace)
611625
writer.element('use', attrib=attrib)
612626
writer.end('g')
@@ -657,8 +671,8 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms,
657671
writer.start('g', attrib={'clip-path': 'url(#%s)' % clipid})
658672
attrib = {
659673
'xlink:href': '#%s' % path_id,
660-
'x': six.text_type(xo),
661-
'y': six.text_type(self.height - yo),
674+
'x': short_float_fmt(xo),
675+
'y': short_float_fmt(self.height - yo),
662676
'style': self._get_style(gc0, rgbFace)
663677
}
664678
writer.element('use', attrib=attrib)
@@ -727,13 +741,13 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
727741
writer.start(
728742
'linearGradient',
729743
id="GR%x_%d" % (self._n_gradients, i),
730-
x1=six.text_type(x1), y1=six.text_type(y1),
731-
x2=six.text_type(xb), y2=six.text_type(yb))
744+
x1=short_float_fmt(x1), y1=short_float_fmt(y1),
745+
x2=short_float_fmt(xb), y2=short_float_fmt(yb))
732746
writer.element(
733747
'stop',
734748
offset='0',
735749
style=generate_css({'stop-color': rgb2hex(c),
736-
'stop-opacity': six.text_type(c[-1])}))
750+
'stop-opacity': short_float_fmt(c[-1])}))
737751
writer.element(
738752
'stop',
739753
offset='1',
@@ -744,7 +758,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
744758
writer.element(
745759
'polygon',
746760
id='GT%x' % self._n_gradients,
747-
points=" ".join([six.text_type(x)
761+
points=" ".join([short_float_fmt(x)
748762
for x in (x1, y1, x2, y2, x3, y3)]))
749763
writer.end('defs')
750764

@@ -754,7 +768,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans):
754768
'use',
755769
attrib={'xlink:href': href,
756770
'fill': rgb2hex(avg_color),
757-
'fill-opacity': "%f" % avg_color[-1]})
771+
'fill-opacity': short_float_fmt(avg_color[-1])})
758772
for i in range(3):
759773
writer.element(
760774
'use',
@@ -840,16 +854,16 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
840854

841855
alpha = gc.get_alpha()
842856
if alpha != 1.0:
843-
attrib['opacity'] = "%f" % alpha
857+
attrib['opacity'] = short_float_fmt(alpha)
844858

845859
attrib['id'] = oid
846860

847861
if transform is None:
848862
self.writer.element(
849863
'image',
850-
x=six.text_type(x/trans[0]),
851-
y=six.text_type((self.height-y)/trans[3]-h),
852-
width=six.text_type(w), height=six.text_type(h),
864+
x=short_float_fmt(x/trans[0]),
865+
y=short_float_fmt((self.height-y)/trans[3]-h),
866+
width=short_float_fmt(w), height=short_float_fmt(h),
853867
attrib=attrib)
854868
else:
855869
flipped = self._make_flip_transform(transform)
@@ -862,8 +876,8 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None):
862876
[('matrix', flipped)])
863877
self.writer.element(
864878
'image',
865-
x=six.text_type(x), y=six.text_type(y),
866-
width=six.text_type(dx), height=six.text_type(abs(dy)),
879+
x=short_float_fmt(x), y=short_float_fmt(y),
880+
width=short_float_fmt(dx), height=short_float_fmt(abs(dy)),
867881
attrib=attrib)
868882

869883
if url is not None:
@@ -904,7 +918,7 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
904918
if color != '#000000':
905919
style['fill'] = color
906920
if gc.get_alpha() != 1.0:
907-
style['opacity'] = six.text_type(gc.get_alpha())
921+
style['opacity'] = short_float_fmt(gc.get_alpha())
908922

909923
if not ismath:
910924
font = text2path._get_font(prop)
@@ -934,9 +948,9 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
934948
for glyph_id, xposition, yposition, scale in glyph_info:
935949
attrib={'xlink:href': '#%s' % glyph_id}
936950
if xposition != 0.0:
937-
attrib['x'] = six.text_type(xposition)
951+
attrib['x'] = short_float_fmt(xposition)
938952
if yposition != 0.0:
939-
attrib['y'] = six.text_type(yposition)
953+
attrib['y'] = short_float_fmt(yposition)
940954
writer.element(
941955
'use',
942956
attrib=attrib)
@@ -1005,7 +1019,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10051019
if color != '#000000':
10061020
style['fill'] = color
10071021
if gc.get_alpha() != 1.0:
1008-
style['opacity'] = six.text_type(gc.get_alpha())
1022+
style['opacity'] = short_float_fmt(gc.get_alpha())
10091023

10101024
if not ismath:
10111025
font = self._get_font(prop)
@@ -1018,7 +1032,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10181032

10191033
attrib = {}
10201034
# Must add "px" to workaround a Firefox bug
1021-
style['font-size'] = six.text_type(fontsize) + 'px'
1035+
style['font-size'] = short_float_fmt(fontsize) + 'px'
10221036
style['font-family'] = six.text_type(fontfamily)
10231037
style['font-style'] = prop.get_style().lower()
10241038
style['font-weight'] = six.text_type(prop.get_weight()).lower()
@@ -1046,10 +1060,13 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10461060
'center': 'middle'}
10471061
style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()]
10481062

1049-
attrib['x'] = "%f" % ax
1050-
attrib['y'] = "%f" % ay
1063+
attrib['x'] = short_float_fmt(ax)
1064+
attrib['y'] = short_float_fmt(ay)
10511065
attrib['style'] = generate_css(style)
1052-
attrib['transform'] = "rotate(%f, %f, %f)" % (-angle, ax, ay)
1066+
attrib['transform'] = "rotate(%s, %s, %s)" % (
1067+
short_float_fmt(-angle),
1068+
short_float_fmt(ax),
1069+
short_float_fmt(ay))
10531070
writer.element('text', s, attrib=attrib)
10541071
else:
10551072
attrib['transform'] = generate_transform([
@@ -1088,7 +1105,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
10881105
spans = OrderedDict()
10891106
for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs:
10901107
style = generate_css({
1091-
'font-size': six.text_type(fontsize) + 'px',
1108+
'font-size': short_float_fmt(fontsize) + 'px',
10921109
'font-family': font.family_name,
10931110
'font-style': font.style_name.lower(),
10941111
'font-weight': font.style_name.lower()})
@@ -1118,7 +1135,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11181135

11191136
attrib = {
11201137
'style': style,
1121-
'x': ' '.join(six.text_type(c[0]) for c in chars),
1138+
'x': ' '.join(short_float_fmt(c[0]) for c in chars),
11221139
'y': ys
11231140
}
11241141

@@ -1133,8 +1150,10 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
11331150
for x, y, width, height in svg_rects:
11341151
writer.element(
11351152
'rect',
1136-
x=six.text_type(x), y=six.text_type(-y + height),
1137-
width=six.text_type(width), height=six.text_type(height)
1153+
x=short_float_fmt(x),
1154+
y=short_float_fmt(-y + height),
1155+
width=short_float_fmt(width),
1156+
height=short_float_fmt(height)
11381157
)
11391158

11401159
writer.end('g')

0 commit comments

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