diff --git a/scour/scour.py b/scour/scour.py index a6dede0..7d2e320 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -2623,6 +2623,16 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of if not isinstance(length, Decimal): 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 # plus() corresponds to the unary prefix plus operator and applies context precision and rounding length = scouringContext.plus(length) @@ -2634,15 +2644,14 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of else: length = length.normalize() - # gather the non-scientific notation version of the coordinate. - # this may actually be in scientific notation if the value is - # sufficiently large or small, so this is a misnomer. - nonsci = six.text_type(length).lower().replace("e+", "e") + # Gather the non-scientific notation version of the coordinate. + nonsci = '{0:f}'.format(length) if not needsRendererWorkaround: if len(nonsci) > 2 and nonsci[:2] == '0.': nonsci = nonsci[1:] # remove the 0, leave the dot elif len(nonsci) > 3 and nonsci[:3] == '-0.': nonsci = '-' + nonsci[2:] # remove the 0, leave the minus and dot + return_value = nonsci # 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). @@ -2655,11 +2664,13 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of sci = six.text_type(length) + 'e' + six.text_type(exponent) if len(sci) < len(nonsci): - return sci - else: - return nonsci + return_value = sci + + # 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: - return nonsci + return initial_value def reducePrecision(element): diff --git a/testscour.py b/testscour.py index 560f79b..879b7e8 100755 --- a/testscour.py +++ b/testscour.py @@ -956,6 +956,40 @@ class LimitPrecisionInPathData(unittest.TestCase): '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): def runTest(self): diff --git a/unittests/path-precision.svg b/unittests/path-precision.svg index 8e1e267..1d644e4 100644 --- a/unittests/path-precision.svg +++ b/unittests/path-precision.svg @@ -1,4 +1,9 @@ - - - + + + + + + + +