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

SVG importer:

- Remove unneeded "global" specificaitons
- Fixed parsing for paths which contains floating-point numbers
  in format like 10e-2
- Fixes aspect ration when viewBox is specified
parent c75b0a4f
No related branches found
No related tags found
No related merge requests found
...@@ -44,6 +44,70 @@ SVGEmptyStyles = {'useFill': None, ...@@ -44,6 +44,70 @@ SVGEmptyStyles = {'useFill': None,
'fill': None} 'fill': None}
def SVGParseFloat(s, i=0):
"""
Parse first float value from string
Returns value as string
"""
start = i
n = len(s)
token = ''
# Ski[ leading whitespace characters
while i < n and (s[i].isspace() or s[i] == ','):
i += 1
if i == n:
return None
# 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 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])
# 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])
else:
raise Exception('Invalid float value near ' + s[start:start + 10])
return token
def SVGCreateCurve(): def SVGCreateCurve():
""" """
Create new curve object to hold splines in Create new curve object to hold splines in
...@@ -82,15 +146,13 @@ def SVGParseCoord(coord, size): ...@@ -82,15 +146,13 @@ def SVGParseCoord(coord, size):
Needed to handle coordinates set in cm, mm, iches.. Needed to handle coordinates set in cm, mm, iches..
""" """
r = re.compile('([0-9\\-\\+\\.])([A-z%]*)') token = SVGParseFloat(coord)
val = float(r.sub('\\1', coord)) val = float(token)
unit = r.sub('\\2', coord).lower() unit = coord[len(token):]
if unit == '%': if unit == '%':
return float(size) / 100.0 * val return float(size) / 100.0 * val
else: else:
global SVGUnits
return val * SVGUnits[unit] return val * SVGUnits[unit]
return val return val
...@@ -143,9 +205,17 @@ def SVGMatrixFromNode(node, context): ...@@ -143,9 +205,17 @@ def SVGMatrixFromNode(node, context):
vw = SVGParseCoord(viewBox[2], w) vw = SVGParseCoord(viewBox[2], w)
vh = SVGParseCoord(viewBox[3], h) vh = SVGParseCoord(viewBox[3], h)
sx = w / vw
sy = h / vh
scale = min(sx, sy)
tx = (w - vw * scale) / 2
ty = (h - vh * scale) / 2
m = m * m.Translation(Vector((tx, ty, 0.0)))
m = m * m.Translation(Vector((-vx, -vy, 0.0))) m = m * m.Translation(Vector((-vx, -vy, 0.0)))
m = m * m.Scale(w / vw, 4, Vector((1.0, 0.0, 0.0))) m = m * m.Scale(scale, 4, Vector((1.0, 0.0, 0.0)))
m = m * m.Scale(h / vh, 4, Vector((0.0, 1.0, 0.0))) m = m * m.Scale(scale, 4, Vector((0.0, 1.0, 0.0)))
return m return m
...@@ -310,7 +380,6 @@ def SVGParseStyles(node, context): ...@@ -310,7 +380,6 @@ def SVGParseStyles(node, context):
style = node.getAttribute('style') style = node.getAttribute('style')
if style: if style:
elems = style.split(';') elems = style.split(';')
print(elems)
for elem in elems: for elem in elems:
s = elem.split(':') s = elem.split(':')
...@@ -358,13 +427,30 @@ class SVGPathData: ...@@ -358,13 +427,30 @@ class SVGPathData:
d - the definition of the outline of a shape d - the definition of the outline of a shape
""" """
# Convert to easy-to-parse format spaces = ' ,\t'
d = d.replace(',', ' ').replace('-', ' -') commands = ['m', 'l', 'h', 'v', 'c', 's', 'q', '', 't', 'a', 'z']
d = re.sub('([A-z])', ' \\1 ', d) tokens = []
i = 0
n = len(d)
while i < n:
c = d[i]
if c in spaces:
pass
elif c.lower() in commands:
tokens.append(c)
elif c in ['-', '.'] or c.isdigit():
token = SVGParseFloat(d, i)
tokens.append(token)
self._data = d.split() i += len(token) - 1
i += 1
self._data = tokens
self._index = 0 self._index = 0
self._len = len(self._data) self._len = len(tokens)
def eof(self): def eof(self):
""" """
...@@ -976,8 +1062,6 @@ class SVGGeometryPATH(SVGGeometry): ...@@ -976,8 +1062,6 @@ class SVGGeometryPATH(SVGGeometry):
Initialize SVG path Initialize SVG path
""" """
global SVGEmptyStyles
super().__init__(node, context) super().__init__(node, context)
self._splines = [] self._splines = []
...@@ -1117,8 +1201,6 @@ class SVGGeometryRECT(SVGGeometry): ...@@ -1117,8 +1201,6 @@ class SVGGeometryRECT(SVGGeometry):
Initialize new rectangle Initialize new rectangle
""" """
global SVGEmptyStyles
super().__init__(node, context) super().__init__(node, context)
self._rect = ('0', '0', '0', '0') self._rect = ('0', '0', '0', '0')
...@@ -1279,8 +1361,6 @@ class SVGGeometryELLIPSE(SVGGeometry): ...@@ -1279,8 +1361,6 @@ class SVGGeometryELLIPSE(SVGGeometry):
Initialize new ellipse Initialize new ellipse
""" """
global SVGEmptyStyles
super().__init__(node, context) super().__init__(node, context)
self._cx = '0.0' self._cx = '0.0'
...@@ -1402,8 +1482,6 @@ class SVGGeometryLINE(SVGGeometry): ...@@ -1402,8 +1482,6 @@ class SVGGeometryLINE(SVGGeometry):
Initialize new line Initialize new line
""" """
global SVGEmptyStyles
super().__init__(node, context) super().__init__(node, context)
self._x1 = '0.0' self._x1 = '0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment