From 29fdd5ba660cfc5c97b5566b516ef2c1cf4e5a27 Mon Sep 17 00:00:00 2001 From: JSCHILL1 Date: Mon, 27 Apr 2009 11:19:34 -0500 Subject: [PATCH] Use decimals for path data and limit to 6 digits of precision --- scour.py | 41 ++++++++++++++++++++--------------- testscour.py | 18 ++++++++++++++- unittests/path-abs-to-rel.svg | 2 +- unittests/path-precision.svg | 3 +++ 4 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 unittests/path-precision.svg diff --git a/scour.py b/scour.py index ac17048..95ea13c 100755 --- a/scour.py +++ b/scour.py @@ -37,7 +37,6 @@ # * Eliminate empty path segments # * Eliminate last segment in a polygon # * Collapse straight curves. -# * Convert absolute path segments to relative ones. # * Process Transformations # * Process quadratic Bezier curves # * Collapse all group based transformations @@ -50,6 +49,7 @@ # + Sanitize path data (remove unnecessary whitespace # + Move from absolute to relative path data # + Remove trailing zeroes from path data +# + Limit to no more than 6 digits of precision # - Remove unnecessary units of precision on attributes (use decimal: http://docs.python.org/library/decimal.html) # - Remove unnecessary units of precision on path coordinates # - Convert all colors to #RRGGBB format @@ -69,6 +69,10 @@ import base64 import os.path import urllib from svg_regex import svg_parser +from decimal import * + +# set precision to 6 decimal places +getcontext().prec = 6 APP = 'scour' VER = '0.10' @@ -619,15 +623,16 @@ def cleanPath(element) : # one or more tuples, each containing two numbers nums = [] for t in dataset: - nums.append(t[0]) - nums.append(t[1]) + # convert to a Decimal and ensure precision + nums.append(Decimal(str(t[0])) * Decimal(1)) + nums.append(Decimal(str(t[1])) * Decimal(1)) path.append( (cmd, nums) ) elif cmd in ['V','v','H','h']: # one or more numbers nums = [] for n in dataset: - nums.append(n) + nums.append(Decimal(str(n))) path.append( (cmd, nums) ) elif cmd in ['C','c']: @@ -635,8 +640,8 @@ def cleanPath(element) : nums = [] for t in dataset: for pair in t: - nums.append(pair[0]) - nums.append(pair[1]) + nums.append(Decimal(str(pair[0])) * Decimal(1)) + nums.append(Decimal(str(pair[1])) * Decimal(1)) path.append( (cmd, nums) ) elif cmd in ['S','s','Q','q']: @@ -644,8 +649,8 @@ def cleanPath(element) : nums = [] for t in dataset: for pair in t: - nums.append(pair[0]) - nums.append(pair[1]) + nums.append(Decimal(str(pair[0])) * Decimal(1)) + nums.append(Decimal(str(pair[1])) * Decimal(1)) path.append( (cmd, nums) ) elif cmd in ['A','a']: @@ -653,18 +658,18 @@ def cleanPath(element) : # another boolean, and a tuple of two numbers nums = [] for t in dataset: - nums.append( t[0][0] ) - nums.append( t[0][1] ) - nums.append( t[1] ) + nums.append( Decimal(str(t[0][0])) * Decimal(1) ) + nums.append( Decimal(str(t[0][1])) * Decimal(1) ) + nums.append( Decimal(str(t[1])) * Decimal(1)) - if t[2]: nums.append( 1 ) - else: nums.append( 0 ) + if t[2]: nums.append( Decimal(1) ) + else: nums.append( Decimal(0) ) - if t[3]: nums.append( 1 ) - else: nums.append( 0 ) + if t[3]: nums.append( Decimal(1) ) + else: nums.append( Decimal(0) ) - nums.append( t[4][0] ) - nums.append( t[4][1] ) + nums.append( Decimal(str(t[4][0])) * Decimal(1) ) + nums.append( Decimal(str(t[4][1])) * Decimal(1) ) path.append( (cmd, nums) ) elif cmd in ['Z','z']: @@ -741,7 +746,7 @@ def cleanPath(element) : # - reserialize the path data with some cleanups: # - removes scientific notation (exponents) -# - removes trailing zeros after the decimal +# - removes all trailing zeros after the decimal # - removes extraneous whitespace # - adds commas between all values in a subcommand def serializePath(pathObj): diff --git a/testscour.py b/testscour.py index b3e8463..cf2667d 100755 --- a/testscour.py +++ b/testscour.py @@ -443,6 +443,22 @@ class ConvertAbsoluteToRelativePathCommands(unittest.TestCase): 'Absolute V command not converted to relative v command') self.assertEquals(path[1][1][0], -20.0, 'Absolute V value not converted to relative v value') - + +class RoundPathData(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/path-precision.svg') + path = svg_parser.parse(doc.getElementsByTagNameNS(SVGNS, 'path')[0].getAttribute('d')) + self.assertEquals(path[0][1][0][0], 100.0, + 'Not rounding down' ) + self.assertEquals(path[0][1][0][1], 100.0, + 'Not rounding up' ) + +class LimitPrecisionInPathData(unittest.TestCase): + def runTest(self): + doc = scour.scourXmlFile('unittests/path-precision.svg') + path = svg_parser.parse(doc.getElementsByTagNameNS(SVGNS, 'path')[0].getAttribute('d')) + self.assertEquals(path[1][1][0], 100.001, + 'Not correctly limiting precision on path data' ) + if __name__ == '__main__': unittest.main() diff --git a/unittests/path-abs-to-rel.svg b/unittests/path-abs-to-rel.svg index 2647269..473cb52 100644 --- a/unittests/path-abs-to-rel.svg +++ b/unittests/path-abs-to-rel.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/unittests/path-precision.svg b/unittests/path-precision.svg new file mode 100644 index 0000000..333fc16 --- /dev/null +++ b/unittests/path-precision.svg @@ -0,0 +1,3 @@ + + +