|
|
@@ -88,6 +88,13 @@ def escape_attrib(s): |
|
|
s = s.replace(">", ">")
|
|
|
return s
|
|
|
|
|
|
+def short_float_fmt(x):
|
|
|
+ """
|
|
|
+ Create a short string representation of a float, which is %f
|
|
|
+ formatting with trailing zeros and the decimal point removed.
|
|
|
+ """
|
|
|
+ return '{0:f}'.format(x).rstrip('0').rstrip('.')
|
|
|
+
|
|
|
##
|
|
|
# XML writer class.
|
|
|
#
|
|
|
@@ -232,7 +239,8 @@ def generate_transform(transform_list=[]): |
|
|
if type == 'matrix' and isinstance(value, Affine2DBase):
|
|
|
value = value.to_values()
|
|
|
|
|
|
- output.write('%s(%s)' % (type, ' '.join('%f' % x for x in value)))
|
|
|
+ output.write('%s(%s)' % (
|
|
|
+ type, ' '.join(short_float_fmt(x) for x in value)))
|
|
|
return output.getvalue()
|
|
|
return ''
|
|
|
|
|
|
@@ -401,32 +409,32 @@ def _get_style_dict(self, gc, rgbFace): |
|
|
if gc.get_hatch() is not None:
|
|
|
attrib['fill'] = "url(#%s)" % self._get_hatch(gc, rgbFace)
|
|
|
if rgbFace is not None and len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
|
|
|
- attrib['fill-opacity'] = "%f" % rgbFace[3]
|
|
|
+ attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
|
|
|
else:
|
|
|
if rgbFace is None:
|
|
|
attrib['fill'] = 'none'
|
|
|
else:
|
|
|
if tuple(rgbFace[:3]) != (0, 0, 0):
|
|
|
attrib['fill'] = rgb2hex(rgbFace)
|
|
|
if len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha:
|
|
|
- attrib['fill-opacity'] = "%f" % rgbFace[3]
|
|
|
+ attrib['fill-opacity'] = short_float_fmt(rgbFace[3])
|
|
|
|
|
|
if forced_alpha and gc.get_alpha() != 1.0:
|
|
|
- attrib['opacity'] = "%f" % gc.get_alpha()
|
|
|
+ attrib['opacity'] = short_float_fmt(gc.get_alpha())
|
|
|
|
|
|
offset, seq = gc.get_dashes()
|
|
|
if seq is not None:
|
|
|
- attrib['stroke-dasharray'] = ','.join(['%f' % val for val in seq])
|
|
|
- attrib['stroke-dashoffset'] = six.text_type(float(offset))
|
|
|
+ attrib['stroke-dasharray'] = ','.join([short_float_fmt(val) for val in seq])
|
|
|
+ attrib['stroke-dashoffset'] = short_float_fmt(float(offset))
|
|
|
|
|
|
linewidth = gc.get_linewidth()
|
|
|
if linewidth:
|
|
|
rgb = gc.get_rgb()
|
|
|
attrib['stroke'] = rgb2hex(rgb)
|
|
|
if not forced_alpha and rgb[3] != 1.0:
|
|
|
- attrib['stroke-opacity'] = "%f" % rgb[3]
|
|
|
+ attrib['stroke-opacity'] = short_float_fmt(rgb[3])
|
|
|
if linewidth != 1.0:
|
|
|
- attrib['stroke-width'] = "%f" % linewidth
|
|
|
+ attrib['stroke-width'] = short_float_fmt(linewidth)
|
|
|
if gc.get_joinstyle() != 'round':
|
|
|
attrib['stroke-linejoin'] = gc.get_joinstyle()
|
|
|
if gc.get_capstyle() != 'butt':
|
|
|
@@ -474,8 +482,12 @@ def _write_clips(self): |
|
|
writer.element('path', d=path_data)
|
|
|
else:
|
|
|
x, y, w, h = clip
|
|
|
- writer.element('rect', x=six.text_type(x), y=six.text_type(y),
|
|
|
- width=six.text_type(w), height=six.text_type(h))
|
|
|
+ writer.element(
|
|
|
+ 'rect',
|
|
|
+ x=short_float_fmt(x),
|
|
|
+ y=short_float_fmt(y),
|
|
|
+ width=short_float_fmt(w),
|
|
|
+ height=short_float_fmt(h))
|
|
|
writer.end('clipPath')
|
|
|
writer.end('defs')
|
|
|
|
|
|
@@ -496,7 +508,8 @@ def _write_svgfonts(self): |
|
|
'font-family': font.family_name,
|
|
|
'font-style': font.style_name.lower(),
|
|
|
'units-per-em': '72',
|
|
|
- 'bbox': ' '.join(six.text_type(x / 64.0) for x in font.bbox)})
|
|
|
+ 'bbox': ' '.join(
|
|
|
+ short_float_fmt(x / 64.0) for x in font.bbox)})
|
|
|
for char in chars:
|
|
|
glyph = font.load_char(char, flags=LOAD_NO_HINTING)
|
|
|
verts, codes = font.get_path()
|
|
|
@@ -509,7 +522,8 @@ def _write_svgfonts(self): |
|
|
attrib={
|
|
|
# 'glyph-name': name,
|
|
|
'unicode': unichr(char),
|
|
|
- 'horiz-adv-x': six.text_type(glyph.linearHoriAdvance / 65536.0)})
|
|
|
+ 'horiz-adv-x':
|
|
|
+ short_float_fmt(glyph.linearHoriAdvance / 65536.0)})
|
|
|
writer.end('font')
|
|
|
writer.end('defs')
|
|
|
|
|
|
@@ -605,8 +619,8 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None) |
|
|
trans_and_flip, clip=clip, simplify=False):
|
|
|
if len(vertices):
|
|
|
x, y = vertices[-2:]
|
|
|
- attrib['x'] = six.text_type(x)
|
|
|
- attrib['y'] = six.text_type(y)
|
|
|
+ attrib['x'] = short_float_fmt(x)
|
|
|
+ attrib['y'] = short_float_fmt(y)
|
|
|
attrib['style'] = self._get_style(gc, rgbFace)
|
|
|
writer.element('use', attrib=attrib)
|
|
|
writer.end('g')
|
|
|
@@ -657,8 +671,8 @@ def draw_path_collection(self, gc, master_transform, paths, all_transforms, |
|
|
writer.start('g', attrib={'clip-path': 'url(#%s)' % clipid})
|
|
|
attrib = {
|
|
|
'xlink:href': '#%s' % path_id,
|
|
|
- 'x': six.text_type(xo),
|
|
|
- 'y': six.text_type(self.height - yo),
|
|
|
+ 'x': short_float_fmt(xo),
|
|
|
+ 'y': short_float_fmt(self.height - yo),
|
|
|
'style': self._get_style(gc0, rgbFace)
|
|
|
}
|
|
|
writer.element('use', attrib=attrib)
|
|
|
@@ -727,13 +741,13 @@ def draw_gouraud_triangle(self, gc, points, colors, trans): |
|
|
writer.start(
|
|
|
'linearGradient',
|
|
|
id="GR%x_%d" % (self._n_gradients, i),
|
|
|
- x1=six.text_type(x1), y1=six.text_type(y1),
|
|
|
- x2=six.text_type(xb), y2=six.text_type(yb))
|
|
|
+ x1=short_float_fmt(x1), y1=short_float_fmt(y1),
|
|
|
+ x2=short_float_fmt(xb), y2=short_float_fmt(yb))
|
|
|
writer.element(
|
|
|
'stop',
|
|
|
offset='0',
|
|
|
style=generate_css({'stop-color': rgb2hex(c),
|
|
|
- 'stop-opacity': six.text_type(c[-1])}))
|
|
|
+ 'stop-opacity': short_float_fmt(c[-1])}))
|
|
|
writer.element(
|
|
|
'stop',
|
|
|
offset='1',
|
|
|
@@ -744,7 +758,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans): |
|
|
writer.element(
|
|
|
'polygon',
|
|
|
id='GT%x' % self._n_gradients,
|
|
|
- points=" ".join([six.text_type(x)
|
|
|
+ points=" ".join([short_float_fmt(x)
|
|
|
for x in (x1, y1, x2, y2, x3, y3)]))
|
|
|
writer.end('defs')
|
|
|
|
|
|
@@ -754,7 +768,7 @@ def draw_gouraud_triangle(self, gc, points, colors, trans): |
|
|
'use',
|
|
|
attrib={'xlink:href': href,
|
|
|
'fill': rgb2hex(avg_color),
|
|
|
- 'fill-opacity': "%f" % avg_color[-1]})
|
|
|
+ 'fill-opacity': short_float_fmt(avg_color[-1])})
|
|
|
for i in range(3):
|
|
|
writer.element(
|
|
|
'use',
|
|
|
@@ -840,16 +854,16 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None): |
|
|
|
|
|
alpha = gc.get_alpha()
|
|
|
if alpha != 1.0:
|
|
|
- attrib['opacity'] = "%f" % alpha
|
|
|
+ attrib['opacity'] = short_float_fmt(alpha)
|
|
|
|
|
|
attrib['id'] = oid
|
|
|
|
|
|
if transform is None:
|
|
|
self.writer.element(
|
|
|
'image',
|
|
|
- x=six.text_type(x/trans[0]),
|
|
|
- y=six.text_type((self.height-y)/trans[3]-h),
|
|
|
- width=six.text_type(w), height=six.text_type(h),
|
|
|
+ x=short_float_fmt(x/trans[0]),
|
|
|
+ y=short_float_fmt((self.height-y)/trans[3]-h),
|
|
|
+ width=short_float_fmt(w), height=short_float_fmt(h),
|
|
|
attrib=attrib)
|
|
|
else:
|
|
|
flipped = self._make_flip_transform(transform)
|
|
|
@@ -862,8 +876,8 @@ def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None): |
|
|
[('matrix', flipped)])
|
|
|
self.writer.element(
|
|
|
'image',
|
|
|
- x=six.text_type(x), y=six.text_type(y),
|
|
|
- width=six.text_type(dx), height=six.text_type(abs(dy)),
|
|
|
+ x=short_float_fmt(x), y=short_float_fmt(y),
|
|
|
+ width=short_float_fmt(dx), height=short_float_fmt(abs(dy)),
|
|
|
attrib=attrib)
|
|
|
|
|
|
if url is not None:
|
|
|
@@ -904,7 +918,7 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
if color != '#000000':
|
|
|
style['fill'] = color
|
|
|
if gc.get_alpha() != 1.0:
|
|
|
- style['opacity'] = six.text_type(gc.get_alpha())
|
|
|
+ style['opacity'] = short_float_fmt(gc.get_alpha())
|
|
|
|
|
|
if not ismath:
|
|
|
font = text2path._get_font(prop)
|
|
|
@@ -934,9 +948,9 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
for glyph_id, xposition, yposition, scale in glyph_info:
|
|
|
attrib={'xlink:href': '#%s' % glyph_id}
|
|
|
if xposition != 0.0:
|
|
|
- attrib['x'] = six.text_type(xposition)
|
|
|
+ attrib['x'] = short_float_fmt(xposition)
|
|
|
if yposition != 0.0:
|
|
|
- attrib['y'] = six.text_type(yposition)
|
|
|
+ attrib['y'] = short_float_fmt(yposition)
|
|
|
writer.element(
|
|
|
'use',
|
|
|
attrib=attrib)
|
|
|
@@ -1005,7 +1019,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
if color != '#000000':
|
|
|
style['fill'] = color
|
|
|
if gc.get_alpha() != 1.0:
|
|
|
- style['opacity'] = six.text_type(gc.get_alpha())
|
|
|
+ style['opacity'] = short_float_fmt(gc.get_alpha())
|
|
|
|
|
|
if not ismath:
|
|
|
font = self._get_font(prop)
|
|
|
@@ -1018,7 +1032,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
|
|
|
attrib = {}
|
|
|
# Must add "px" to workaround a Firefox bug
|
|
|
- style['font-size'] = six.text_type(fontsize) + 'px'
|
|
|
+ style['font-size'] = short_float_fmt(fontsize) + 'px'
|
|
|
style['font-family'] = six.text_type(fontfamily)
|
|
|
style['font-style'] = prop.get_style().lower()
|
|
|
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): |
|
|
'center': 'middle'}
|
|
|
style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()]
|
|
|
|
|
|
- attrib['x'] = "%f" % ax
|
|
|
- attrib['y'] = "%f" % ay
|
|
|
+ attrib['x'] = short_float_fmt(ax)
|
|
|
+ attrib['y'] = short_float_fmt(ay)
|
|
|
attrib['style'] = generate_css(style)
|
|
|
- attrib['transform'] = "rotate(%f, %f, %f)" % (-angle, ax, ay)
|
|
|
+ attrib['transform'] = "rotate(%s, %s, %s)" % (
|
|
|
+ short_float_fmt(-angle),
|
|
|
+ short_float_fmt(ax),
|
|
|
+ short_float_fmt(ay))
|
|
|
writer.element('text', s, attrib=attrib)
|
|
|
else:
|
|
|
attrib['transform'] = generate_transform([
|
|
|
@@ -1088,7 +1105,7 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
spans = OrderedDict()
|
|
|
for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs:
|
|
|
style = generate_css({
|
|
|
- 'font-size': six.text_type(fontsize) + 'px',
|
|
|
+ 'font-size': short_float_fmt(fontsize) + 'px',
|
|
|
'font-family': font.family_name,
|
|
|
'font-style': font.style_name.lower(),
|
|
|
'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): |
|
|
|
|
|
attrib = {
|
|
|
'style': style,
|
|
|
- 'x': ' '.join(six.text_type(c[0]) for c in chars),
|
|
|
+ 'x': ' '.join(short_float_fmt(c[0]) for c in chars),
|
|
|
'y': ys
|
|
|
}
|
|
|
|
|
|
@@ -1133,8 +1150,10 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): |
|
|
for x, y, width, height in svg_rects:
|
|
|
writer.element(
|
|
|
'rect',
|
|
|
- x=six.text_type(x), y=six.text_type(-y + height),
|
|
|
- width=six.text_type(width), height=six.text_type(height)
|
|
|
+ x=short_float_fmt(x),
|
|
|
+ y=short_float_fmt(-y + height),
|
|
|
+ width=short_float_fmt(width),
|
|
|
+ height=short_float_fmt(height)
|
|
|
)
|
|
|
|
|
|
writer.end('g')
|
|
|
|