Skip to content
Snippets Groups Projects
Commit cdf56b2f authored by Sergey Sharybin's avatar Sergey Sharybin
Browse files

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.
parent 7f97ceb0
Branches
Tags
No related merge requests found
...@@ -46,10 +46,13 @@ def check_points_equal(point_a, point_b): ...@@ -46,10 +46,13 @@ def check_points_equal(point_a, point_b):
abs(point_a[1] - point_b[1]) < 1e-6) abs(point_a[1] - point_b[1]) < 1e-6)
match_number = r"-?\d+(\.\d+)?([eE][-+]?\d+)?" match_number = r"-?\d+(\.\d+)?([eE][-+]?\d+)?"
match_number_optional_fractional = r"-?\d+(\.\d*)?([eE][-+]?\d+)?"
match_first_comma = r"^\s*(?=,)" match_first_comma = r"^\s*(?=,)"
match_comma_pair = r",\s*(?=,)" match_comma_pair = r",\s*(?=,)"
match_last_comma = 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}" 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) re_array_of_floats_pattern = re.compile(array_of_floats_pattern)
...@@ -62,69 +65,32 @@ def parse_array_of_floats(text): ...@@ -62,69 +65,32 @@ def parse_array_of_floats(text):
return [value_to_float(v[0]) for v in elements] 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. 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. Returns the value itself (as a string) and index of first character after the value.
""" """
start = i
n = len(s) n = len(text)
token = ''
# Skip leading whitespace characters and characters which we consider ignorable for float
# Skip leading whitespace characters # (like values separator).
while i < n and (s[i].isspace() or s[i] == ','): while start_index < n and (text[start_index].isspace() or text[start_index] == ','):
i += 1 start_index += 1
if start_index == n:
if i == n: return "0", start_index
return "0", i
text_part = text[start_index:]
# Read sign match = re_match_number_optional_fractional.match(text_part)
if s[i] == '-':
token += '-' if match is None:
i += 1 raise Exception('Invalid float value near ' + text[start_index:start_index + 10])
elif s[i] == '+':
i += 1 token = match.group(0)
endptr = start_index + match.end(0)
# Read integer part
if s[i].isdigit(): return token, endptr
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
def parse_coord(coord, size): def parse_coord(coord, size):
......
...@@ -118,7 +118,7 @@ class ReadFloatTest(unittest.TestCase): ...@@ -118,7 +118,7 @@ class ReadFloatTest(unittest.TestCase):
def test_not_a_number(self): def test_not_a_number(self):
# TODO(sergey): Make this more concrete. # TODO(sergey): Make this more concrete.
with self.assertRaises(Exception): with self.assertRaises(Exception):
value, endptr = read_float("1.2eV", 3) read_float("1.2eV", 3)
def test_missing_fractional(self): def test_missing_fractional(self):
value, endptr = read_float("1.", 0) value, endptr = read_float("1.", 0)
...@@ -143,6 +143,9 @@ class ParseCoordTest(unittest.TestCase): ...@@ -143,6 +143,9 @@ class ParseCoordTest(unittest.TestCase):
def test_unit_cm(self): def test_unit_cm(self):
self.assertAlmostEqual(parse_coord("1.2cm", 200), 42.51968503937008) 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): def test_unit_percentage(self):
self.assertEqual(parse_coord("1.2%", 200), 2.4) self.assertEqual(parse_coord("1.2%", 200), 2.4)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment