From b00b374e648cb95a4fb0abd8f593499907444598 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Sat, 18 Feb 2017 18:06:09 +0100 Subject: [PATCH 1/3] Fix generation of non-scientific number representation. Before numbers often were already in scientific notation due to the str() implementation of Decimal leading to strange optimization results. --- scour/scour.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scour/scour.py b/scour/scour.py index a6dede0..24bfaa6 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -2634,10 +2634,8 @@ 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 From 8f87118725a70329801b3f42b8eed2cc8c8e0dc1 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Sat, 18 Feb 2017 19:01:26 +0100 Subject: [PATCH 2/3] Only use number representation with reduced precision if it is shorter than the initial representation. Before it could happen that "123" was replaced with "1e3" if precision was set to 1 which is obviously not desirable. --- scour/scour.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/scour/scour.py b/scour/scour.py index 24bfaa6..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) @@ -2641,6 +2651,7 @@ def scourUnitlessLength(length, needsRendererWorkaround=False): # length is of 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). @@ -2653,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): From a69efb3a558b91603facaf18912403b658ad1451 Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Sat, 18 Feb 2017 19:36:19 +0100 Subject: [PATCH 3/3] Add unittests for b00b374e648cb95a4fb0abd8f593499907444598 and 8f87118725a70329801b3f42b8eed2cc8c8e0dc1 --- testscour.py | 34 ++++++++++++++++++++++++++++++++++ unittests/path-precision.svg | 11 ++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) 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 @@ - - - + + + + + + + +