Merge pull request #133 from Ede123/precision

Some fixes for `scourUnitlessLength()`
This commit is contained in:
Eduard Braun 2017-02-18 19:45:51 +01:00 committed by GitHub
commit 7c2e035644
3 changed files with 61 additions and 11 deletions

View file

@ -2623,6 +2623,16 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of
if not isinstance(length, Decimal): if not isinstance(length, Decimal):
length = getcontext().create_decimal(str(length)) length = getcontext().create_decimal(str(length))
# remove trailing zeroes as we do not care for significance
intLength = length.to_integral_value()
if length == intLength:
length = Decimal(intLength)
else:
length = length.normalize()
# Gather the initial non-scientific notation version of the coordinate (we want to compare with it later)
initial_value = '{0:f}'.format(length)
# reduce numeric precision # reduce numeric precision
# plus() corresponds to the unary prefix plus operator and applies context precision and rounding # plus() corresponds to the unary prefix plus operator and applies context precision and rounding
length = scouringContext.plus(length) length = scouringContext.plus(length)
@ -2634,15 +2644,14 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of
else: else:
length = length.normalize() length = length.normalize()
# gather the non-scientific notation version of the coordinate. # Gather the non-scientific notation version of the coordinate.
# this may actually be in scientific notation if the value is nonsci = '{0:f}'.format(length)
# sufficiently large or small, so this is a misnomer.
nonsci = six.text_type(length).lower().replace("e+", "e")
if not needsRendererWorkaround: if not needsRendererWorkaround:
if len(nonsci) > 2 and nonsci[:2] == '0.': if len(nonsci) > 2 and nonsci[:2] == '0.':
nonsci = nonsci[1:] # remove the 0, leave the dot nonsci = nonsci[1:] # remove the 0, leave the dot
elif len(nonsci) > 3 and nonsci[:3] == '-0.': elif len(nonsci) > 3 and nonsci[:3] == '-0.':
nonsci = '-' + nonsci[2:] # remove the 0, leave the minus and dot nonsci = '-' + nonsci[2:] # remove the 0, leave the minus and dot
return_value = nonsci
# Gather the scientific notation version of the coordinate which # Gather the scientific notation version of the coordinate which
# can only be shorter if the length of the number is at least 4 characters (e.g. 1000 = 1e3). # can only be shorter if the length of the number is at least 4 characters (e.g. 1000 = 1e3).
@ -2655,11 +2664,13 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of
sci = six.text_type(length) + 'e' + six.text_type(exponent) sci = six.text_type(length) + 'e' + six.text_type(exponent)
if len(sci) < len(nonsci): if len(sci) < len(nonsci):
return sci return_value = sci
else:
return nonsci # Return the shortest representation (if they are equal prefer the original as it still has the full precision)
if len(return_value) < len(initial_value):
return return_value
else: else:
return nonsci return initial_value
def reducePrecision(element): def reducePrecision(element):

View file

@ -956,6 +956,40 @@ class LimitPrecisionInPathData(unittest.TestCase):
'Not correctly limiting precision on path data') 'Not correctly limiting precision on path data')
class KeepPrecisionInPathDataIfSameLength(unittest.TestCase):
def runTest(self):
doc = scourXmlFile('unittests/path-precision.svg', parse_args(['--set-precision=1']))
paths = doc.getElementsByTagNameNS(SVGNS, 'path')
for path in paths[1:3]:
self.assertEqual(path.getAttribute('d'), "m1 12 123 1e3 1e4 1e5",
'Precision not correctly reduced with "--set-precision=1" '
'for path with ID ' + path.getAttribute('id'))
self.assertEqual(paths[4].getAttribute('d'), "m-1-12-123-1e3 -1e4 -1e5",
'Precision not correctly reduced with "--set-precision=1" '
'for path with ID ' + paths[4].getAttribute('id'))
doc = scourXmlFile('unittests/path-precision.svg', parse_args(['--set-precision=2']))
paths = doc.getElementsByTagNameNS(SVGNS, 'path')
for path in paths[1:3]:
self.assertEqual(path.getAttribute('d'), "m1 12 123 1234 12345 1.2e5",
'Precision not correctly reduced with "--set-precision=2" '
'for path with ID ' + path.getAttribute('id'))
self.assertEqual(paths[4].getAttribute('d'), "m-1-12-123-1234-12345-1.2e5",
'Precision not correctly reduced with "--set-precision=2" '
'for path with ID ' + paths[4].getAttribute('id'))
doc = scourXmlFile('unittests/path-precision.svg', parse_args(['--set-precision=3']))
paths = doc.getElementsByTagNameNS(SVGNS, 'path')
for path in paths[1:3]:
self.assertEqual(path.getAttribute('d'), "m1 12 123 1234 12345 123456",
'Precision not correctly reduced with "--set-precision=3" '
'for path with ID ' + path.getAttribute('id'))
self.assertEqual(paths[4].getAttribute('d'), "m-1-12-123-1234-12345-123456",
'Precision not correctly reduced with "--set-precision=3" '
'for path with ID ' + paths[4].getAttribute('id'))
class RemoveEmptyLineSegmentsFromPath(unittest.TestCase): class RemoveEmptyLineSegmentsFromPath(unittest.TestCase):
def runTest(self): def runTest(self):

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg" version="1.1"> <svg vxmlns="http://www.w3.org/2000/svg">
<path d="M 100.0000001 99.9999999 h100.01 v123456789.123456789 h-100 z" fill="red" /> <path id="p0" d="M 100.0000001 99.9999999 h100.01 v123456789.123456789 h-100 z" />
<path id="p1" d="m 1 12 123 1234 12345 123456 " />
<path id="p2" d="m 1.0 12.0 123.0 1234.0 12345.0 123456.0" />
<path id="p3" d="m 01 012 0123 01234 012345 0123456 " />
<path id="p4" d="m -1 -12 -123 -1234 -12345 -123456 " />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 456 B

Before After
Before After