Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-09-19 16:31:48 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-09-19 16:33:28 +0300
commitcdf56b2fade83eb8518dedcbdf137bc2d937407d (patch)
tree829557917c79a0776f642ed162a8444f668614a7 /io_curve_svg
parent7f97ceb05061fd45e49ae53e71ba9b7656cc8aab (diff)
Fix T70050: Unable to import SVG
The issue was caused by parser being confused about ex unit which was attempted to be parsed as an exponent.
Diffstat (limited to 'io_curve_svg')
-rw-r--r--io_curve_svg/svg_util.py82
-rwxr-xr-xio_curve_svg/svg_util_test.py5
2 files changed, 28 insertions, 59 deletions
diff --git a/io_curve_svg/svg_util.py b/io_curve_svg/svg_util.py
index 42e900b4..bd744df5 100644
--- a/io_curve_svg/svg_util.py
+++ b/io_curve_svg/svg_util.py
@@ -46,10 +46,13 @@ def check_points_equal(point_a, point_b):
abs(point_a[1] - point_b[1]) < 1e-6)
match_number = r"-?\d+(\.\d+)?([eE][-+]?\d+)?"
+match_number_optional_fractional = r"-?\d+(\.\d*)?([eE][-+]?\d+)?"
match_first_comma = r"^\s*(?=,)"
match_comma_pair = r",\s*(?=,)"
match_last_comma = r",\s*$"
+re_match_number_optional_fractional = re.compile(match_number_optional_fractional)
+
array_of_floats_pattern = f"({match_number})|{match_first_comma}|{match_comma_pair}|{match_last_comma}"
re_array_of_floats_pattern = re.compile(array_of_floats_pattern)
@@ -62,69 +65,32 @@ def parse_array_of_floats(text):
return [value_to_float(v[0]) for v in elements]
-def read_float(s: str, i: int = 0):
+def read_float(text: str, start_index: int = 0):
"""
Reads floating point value from a string. Parsing starts at the given index.
Returns the value itself (as a string) and index of first character after the value.
"""
- start = i
- n = len(s)
- token = ''
-
- # Skip leading whitespace characters
- while i < n and (s[i].isspace() or s[i] == ','):
- i += 1
-
- if i == n:
- return "0", i
-
- # Read sign
- if s[i] == '-':
- token += '-'
- i += 1
- elif s[i] == '+':
- i += 1
-
- # Read integer part
- if s[i].isdigit():
- while i < n and s[i].isdigit():
- token += s[i]
- i += 1
-
- # Fractional part
- if i < n and s[i] == '.':
- token += '.'
- i += 1
-
- if i < n and s[i].isdigit():
- while i < n and s[i].isdigit():
- token += s[i]
- i += 1
- elif i == n or s[i].isspace() or s[i] == ',':
- # Inkscape sometimes uses weird float format with missed
- # fractional part after dot. Suppose zero fractional part
- # for this case
- pass
- else:
- raise Exception('Invalid float value near ' + s[start:start + 10])
-
- # Degree
- if i < n and (s[i] == 'e' or s[i] == 'E'):
- token += s[i]
- i += 1
- if s[i] == '+' or s[i] == '-':
- token += s[i]
- i += 1
-
- if s[i].isdigit():
- while i < n and s[i].isdigit():
- token += s[i]
- i += 1
- else:
- raise Exception('Invalid float value near ' + s[start:start + 10])
-
- return token, i
+
+ n = len(text)
+
+ # Skip leading whitespace characters and characters which we consider ignorable for float
+ # (like values separator).
+ while start_index < n and (text[start_index].isspace() or text[start_index] == ','):
+ start_index += 1
+ if start_index == n:
+ return "0", start_index
+
+ text_part = text[start_index:]
+ match = re_match_number_optional_fractional.match(text_part)
+
+ if match is None:
+ raise Exception('Invalid float value near ' + text[start_index:start_index + 10])
+
+ token = match.group(0)
+ endptr = start_index + match.end(0)
+
+ return token, endptr
def parse_coord(coord, size):
diff --git a/io_curve_svg/svg_util_test.py b/io_curve_svg/svg_util_test.py
index 6f54d5f3..de1d9823 100755
--- a/io_curve_svg/svg_util_test.py
+++ b/io_curve_svg/svg_util_test.py
@@ -118,7 +118,7 @@ class ReadFloatTest(unittest.TestCase):
def test_not_a_number(self):
# TODO(sergey): Make this more concrete.
with self.assertRaises(Exception):
- value, endptr = read_float("1.2eV", 3)
+ read_float("1.2eV", 3)
def test_missing_fractional(self):
value, endptr = read_float("1.", 0)
@@ -143,6 +143,9 @@ class ParseCoordTest(unittest.TestCase):
def test_unit_cm(self):
self.assertAlmostEqual(parse_coord("1.2cm", 200), 42.51968503937008)
+ def test_unit_ex(self):
+ self.assertAlmostEqual(parse_coord("1.2ex", 200), 1.2)
+
def test_unit_percentage(self):
self.assertEqual(parse_coord("1.2%", 200), 2.4)