diff --git a/svgpathtools/parser.py b/svgpathtools/parser.py index 955c671..3a49416 100644 --- a/svgpathtools/parser.py +++ b/svgpathtools/parser.py @@ -30,11 +30,23 @@ def _check_num_parsed_values(values, allowed): def _parse_transform_substr(transform_substr): + transform = np.identity(3) + + # A well-formed transform substring is `type(v1 v2 ...)`. Malformed input + # (no/extra parenthesis, or non-numeric values) previously raised a bare + # ValueError; degrade to the identity matrix with a warning, like the + # unknown-type and wrong-argument-count cases below. + if transform_substr.count('(') != 1: + warnings.warn('Invalid SVG transform substring: {0}'.format(transform_substr)) + return transform + type_str, value_str = transform_substr.split('(') value_str = value_str.replace(',', ' ') - values = list(map(float, filter(None, value_str.split(' ')))) - - transform = np.identity(3) + try: + values = list(map(float, filter(None, value_str.split(' ')))) + except ValueError: + warnings.warn('Invalid SVG transform substring: {0}'.format(transform_substr)) + return transform if 'matrix' in type_str: if not _check_num_parsed_values(values, [6]): return transform diff --git a/test/test_parsing.py b/test/test_parsing.py index cf33b1f..e531abf 100644 --- a/test/test_parsing.py +++ b/test/test_parsing.py @@ -249,6 +249,19 @@ def test_transform(self): scale(10 0.5)""") )) + def test_transform_malformed(self): + # Malformed transform substrings (non-numeric values, missing or extra + # parentheses) used to raise a bare ValueError; they should degrade to + # the identity matrix like the unknown-type case. + import warnings + identity = np.identity(3) + for bad in ('matrix(1 x 3 4 5 6)', 'translate(a)', 'scale()', + 'rotate(1 2 z)', 'foo(1', 'matrix'): + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + tf = svgpathtools.parser.parse_transform(bad) + self.assertTrue(np.array_equal(identity, tf)) + def test_pathd_init(self): path0 = Path('') path1 = parse_path("M 100 100 L 300 100 L 200 300 z")