diff --git a/.travis.yml b/.travis.yml index 48a15d5..5200f17 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,27 @@ +sudo: false + language: python +python: + - pypy + - 2.7 + - 3.3 + - 3.4 + - 3.5 + - 3.6 install: - - pip install tox codecov - -env: - - TOX_ENV=pypy - - TOX_ENV=py27 - - TOX_ENV=py33 - - TOX_ENV=py34 -# - TOX_ENV=py35 -# - TOX_ENV=flake8 + - pip install tox-travis codecov script: - - tox -e $TOX_ENV + - tox matrix: fast_finish: true include: - # https://github.com/travis-ci/travis-ci/issues/4794#issuecomment-143758799 - python: 3.5 env: - - TOX_ENV=py35 - - - python: 3.5 - env: - - TOX_ENV=flake8 + - TOXENV=flake8 after_success: - coverage combine && codecov \ No newline at end of file diff --git a/scour/scour.py b/scour/scour.py index c97564d..10261c4 100644 --- a/scour/scour.py +++ b/scour/scour.py @@ -2625,6 +2625,7 @@ def scourUnitlessLength(length, needsRendererWorkaround=False, isControlPoint=Fa """ if not isinstance(length, Decimal): length = getcontext().create_decimal(str(length)) + initial_length = length # reduce numeric precision # plus() corresponds to the unary prefix plus operator and applies context precision and rounding @@ -2655,15 +2656,17 @@ def scourUnitlessLength(length, needsRendererWorkaround=False, isControlPoint=Fa 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. + # Re-quantize from the initial value to prevent unnecessary loss of precision + # (e.g. 123.4 should become 123, not 120 or even 100) + nonsci = '{0:f}'.format(length) + nonsci = '{0:f}'.format(initial_length.quantize(Decimal(nonsci))) 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). @@ -2676,11 +2679,9 @@ def scourUnitlessLength(length, needsRendererWorkaround=False, isControlPoint=Fa sci = six.text_type(length) + 'e' + six.text_type(exponent) if len(sci) < len(nonsci): - return sci - else: - return nonsci - else: - return nonsci + return_value = sci + + return return_value def reducePrecision(element): @@ -3057,7 +3058,7 @@ def properlySizeDoc(docElement, options): # else we have a statically sized image and we should try to remedy that # parse viewBox attribute - vbSep = re.split("\\s*\\,?\\s*", docElement.getAttribute('viewBox'), 3) + vbSep = re.split('[, ]+', docElement.getAttribute('viewBox')) # if we have a valid viewBox we need to check it vbWidth, vbHeight = 0, 0 if len(vbSep) == 4: @@ -3516,6 +3517,11 @@ def scourString(in_string, options=None): 'x1', 'y1', 'x2', 'y2', 'fx', 'fy', 'offset']: if elem.getAttribute(attr) != '': elem.setAttribute(attr, scourLength(elem.getAttribute(attr))) + viewBox = doc.documentElement.getAttribute('viewBox') + if viewBox: + lengths = re.split('[, ]+', viewBox) + lengths = [scourUnitlessLength(lenght) for lenght in lengths] + doc.documentElement.setAttribute('viewBox', ' '.join(lengths)) # more length scouring in this function _num_bytes_saved_in_lengths = reducePrecision(doc.documentElement) diff --git a/testscour.py b/testscour.py index 560f79b..6daec27 100755 --- a/testscour.py +++ b/testscour.py @@ -956,6 +956,62 @@ 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')) + self.assertEqual(paths[5].getAttribute('d'), "m123 101-123-101", + 'Precision not correctly reduced with "--set-precision=1" ' + 'for path with ID ' + paths[5].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')) + self.assertEqual(paths[5].getAttribute('d'), "m123 101-123-101", + 'Precision not correctly reduced with "--set-precision=2" ' + 'for path with ID ' + paths[5].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')) + self.assertEqual(paths[5].getAttribute('d'), "m123 101-123-101", + 'Precision not correctly reduced with "--set-precision=3" ' + 'for path with ID ' + paths[5].getAttribute('id')) + + doc = scourXmlFile('unittests/path-precision.svg', parse_args(['--set-precision=4'])) + 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=4" ' + '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=4" ' + 'for path with ID ' + paths[4].getAttribute('id')) + self.assertEqual(paths[5].getAttribute('d'), "m123.5 101-123.5-101", + 'Precision not correctly reduced with "--set-precision=4" ' + 'for path with ID ' + paths[5].getAttribute('id')) + + class RemoveEmptyLineSegmentsFromPath(unittest.TestCase): def runTest(self): @@ -2449,7 +2505,21 @@ class EmbedRasters(unittest.TestCase): "Raster image from remote path '" + href + "' not embedded.") -# TODO: write tests for --enable-viewboxing +class ViewBox(unittest.TestCase): + + def test_viewbox_create(self): + doc = scourXmlFile('unittests/viewbox-create.svg', parse_args(['--enable-viewboxing'])) + viewBox = doc.documentElement.getAttribute('viewBox') + self.assertEqual(viewBox, '0 0 123.46 654.32', "viewBox not properly created with '--enable-viewboxing'.") + + def test_viewbox_remove_width_and_height(self): + doc = scourXmlFile('unittests/viewbox-remove.svg', parse_args(['--enable-viewboxing'])) + width = doc.documentElement.getAttribute('width') + height = doc.documentElement.getAttribute('height') + self.assertEqual(width, '', "width not removed with '--enable-viewboxing'.") + self.assertEqual(height, '', "height not removed with '--enable-viewboxing'.") + + # TODO: write tests for --keep-editor-data if __name__ == '__main__': diff --git a/tox.ini b/tox.ini index 30dacf8..df04c05 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,7 @@ envlist = py33 py34 py35 + py36 flake8 diff --git a/unittests/path-precision.svg b/unittests/path-precision.svg index 8e1e267..9f2bc38 100644 --- a/unittests/path-precision.svg +++ b/unittests/path-precision.svg @@ -1,4 +1,11 @@ - - - + + + + + + + + + + diff --git a/unittests/viewbox-create.svg b/unittests/viewbox-create.svg new file mode 100644 index 0000000..0d250db --- /dev/null +++ b/unittests/viewbox-create.svg @@ -0,0 +1,3 @@ + + + diff --git a/unittests/viewbox-remove.svg b/unittests/viewbox-remove.svg new file mode 100644 index 0000000..8fa8307 --- /dev/null +++ b/unittests/viewbox-remove.svg @@ -0,0 +1,3 @@ + + +