Code

Merge from fe-moved
[inkscape.git] / share / extensions / simplepath.py
index 06ed73672db59f2d7c80a487e0da7f851fa19e88..8d50429a6d9f49e44426901a55b7f60fe258c282 100755 (executable)
@@ -23,179 +23,182 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 import re, math
 
 def lexPath(d):
-       """
-       returns and iterator that breaks path data 
-       identifies command and parameter tokens
-       """
-       offset = 0
-       length = len(d)
-       delim = re.compile(r'[ \t\r\n,]+')
-       command = re.compile(r'[MLHVCSQTAZmlhvcsqtaz]')
-       parameter = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
-       while 1:
-               m = delim.match(d, offset)
-               if m:
-                       offset = m.end()
-               if offset >= length:
-                       break
-               m = command.match(d, offset)
-               if m:
-                       yield [d[offset:m.end()], True]
-                       offset = m.end()
-                       continue
-               m = parameter.match(d, offset)
-               if m:
-                       yield [d[offset:m.end()], False]
-                       offset = m.end()
-                       continue
-               #TODO: create new exception
-               raise Exception, 'Invalid path data!'
+    """
+    returns and iterator that breaks path data 
+    identifies command and parameter tokens
+    """
+    offset = 0
+    length = len(d)
+    delim = re.compile(r'[ \t\r\n,]+')
+    command = re.compile(r'[MLHVCSQTAZmlhvcsqtaz]')
+    parameter = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
+    while 1:
+        m = delim.match(d, offset)
+        if m:
+            offset = m.end()
+        if offset >= length:
+            break
+        m = command.match(d, offset)
+        if m:
+            yield [d[offset:m.end()], True]
+            offset = m.end()
+            continue
+        m = parameter.match(d, offset)
+        if m:
+            yield [d[offset:m.end()], False]
+            offset = m.end()
+            continue
+        #TODO: create new exception
+        raise Exception, 'Invalid path data!'
 '''
 pathdefs = {commandfamily:
-       [
-       implicitnext,
-       #params,
-       [casts,cast,cast],
-       [coord type,x,y,0]
-       ]}
+    [
+    implicitnext,
+    #params,
+    [casts,cast,cast],
+    [coord type,x,y,0]
+    ]}
 '''
 pathdefs = {
-       'M':['L', 2, [float, float], ['x','y']], 
-       'L':['L', 2, [float, float], ['x','y']], 
-       'H':['H', 1, [float], ['x']], 
-       'V':['V', 1, [float], ['y']], 
-       'C':['C', 6, [float, float, float, float, float, float], ['x','y','x','y','x','y']], 
-       'S':['S', 4, [float, float, float, float], ['x','y','x','y']], 
-       'Q':['Q', 4, [float, float, float, float], ['x','y','x','y']], 
-       'T':['T', 2, [float, float], ['x','y']], 
-       'A':['A', 7, [float, float, float, int, int, float, float], [0,0,0,0,0,'x','y']], 
-       'Z':['L', 0, [], []]
-       }
+    'M':['L', 2, [float, float], ['x','y']], 
+    'L':['L', 2, [float, float], ['x','y']], 
+    'H':['H', 1, [float], ['x']], 
+    'V':['V', 1, [float], ['y']], 
+    'C':['C', 6, [float, float, float, float, float, float], ['x','y','x','y','x','y']], 
+    'S':['S', 4, [float, float, float, float], ['x','y','x','y']], 
+    'Q':['Q', 4, [float, float, float, float], ['x','y','x','y']], 
+    'T':['T', 2, [float, float], ['x','y']], 
+    'A':['A', 7, [float, float, float, int, int, float, float], [0,0,0,0,0,'x','y']], 
+    'Z':['L', 0, [], []]
+    }
 def parsePath(d):
-       """
-       Parse SVG path and return an array of segments.
-       Removes all shorthand notation.
-       Converts coordinates to absolute.
-       """
-       retval = []
-       lexer = lexPath(d)
-
-       pen = (0.0,0.0)
-       subPathStart = pen
-       lastControl = pen
-       lastCommand = ''
-       
-       while 1:
-               try:
-                       token, isCommand = lexer.next()
-               except StopIteration:
-                       break
-               params = []
-               needParam = True
-               if isCommand:
-                       if not lastCommand and token.upper() != 'M':
-                               raise Exception, 'Invalid path, must begin with moveto.'        
-                       else:                           
-                               command = token
-               else:
-                       #command was omited
-                       #use last command's implicit next command
-                       needParam = False
-                       if lastCommand:
-                               if token.isupper():
-                                       command = pathdefs[lastCommand.upper()][0]
-                               else:
-                                       command = pathdefs[lastCommand.upper()][0].lower()
-                       else:
-                               raise Exception, 'Invalid path, no initial command.'    
-               numParams = pathdefs[command.upper()][1]
-               while numParams > 0:
-                       if needParam:
-                               try: 
-                                       token, isCommand = lexer.next()
-                                       if isCommand:
-                                               raise Exception, 'Invalid number of parameters'
-                               except StopIteration:
-                                       raise Exception, 'Unexpected end of path'
-                       cast = pathdefs[command.upper()][2][-numParams]
-                       param = cast(token)
-                       if command.islower():
-                               if pathdefs[command.upper()][3][-numParams]=='x':
-                                       param += pen[0]
-                               elif pathdefs[command.upper()][3][-numParams]=='y':
-                                       param += pen[1]
-                       params.append(param)
-                       needParam = True
-                       numParams -= 1
-               #segment is now absolute so
-               outputCommand = command.upper()
-       
-               #Flesh out shortcut notation    
-               if outputCommand in ('H','V'):
-                       if outputCommand == 'H':
-                               params.append(pen[1])
-                       if outputCommand == 'V':
-                               params.insert(0,pen[0])
-                       outputCommand = 'L'
-               if outputCommand in ('S','T'):
-                       params.insert(0,pen[1]+(pen[1]-lastControl[1]))
-                       params.insert(0,pen[0]+(pen[0]-lastControl[0]))
-                       if outputCommand == 'S':
-                               outputCommand = 'C'
-                       if outputCommand == 'T':
-                               outputCommand = 'Q'
-
-               #current values become "last" values
-               if outputCommand == 'M':
-                       subPathStart = tuple(params[0:2])
-               if outputCommand == 'Z':
-                       pen = subPathStart
-               else:
-                       pen = tuple(params[-2:])
-
-               if outputCommand in ('Q','C'):
-                       lastControl = tuple(params[-4:-2])
-               else:
-                       lastControl = pen
-               lastCommand = command
-
-               retval.append([outputCommand,params])
-       return retval
+    """
+    Parse SVG path and return an array of segments.
+    Removes all shorthand notation.
+    Converts coordinates to absolute.
+    """
+    retval = []
+    lexer = lexPath(d)
+
+    pen = (0.0,0.0)
+    subPathStart = pen
+    lastControl = pen
+    lastCommand = ''
+    
+    while 1:
+        try:
+            token, isCommand = lexer.next()
+        except StopIteration:
+            break
+        params = []
+        needParam = True
+        if isCommand:
+            if not lastCommand and token.upper() != 'M':
+                raise Exception, 'Invalid path, must begin with moveto.'    
+            else:                
+                command = token
+        else:
+            #command was omited
+            #use last command's implicit next command
+            needParam = False
+            if lastCommand:
+                if lastCommand.isupper():
+                    command = pathdefs[lastCommand][0]
+                else:
+                    command = pathdefs[lastCommand.upper()][0].lower()
+            else:
+                raise Exception, 'Invalid path, no initial command.'    
+        numParams = pathdefs[command.upper()][1]
+        while numParams > 0:
+            if needParam:
+                try: 
+                    token, isCommand = lexer.next()
+                    if isCommand:
+                        raise Exception, 'Invalid number of parameters'
+                except StopIteration:
+                    raise Exception, 'Unexpected end of path'
+            cast = pathdefs[command.upper()][2][-numParams]
+            param = cast(token)
+            if command.islower():
+                if pathdefs[command.upper()][3][-numParams]=='x':
+                    param += pen[0]
+                elif pathdefs[command.upper()][3][-numParams]=='y':
+                    param += pen[1]
+            params.append(param)
+            needParam = True
+            numParams -= 1
+        #segment is now absolute so
+        outputCommand = command.upper()
+    
+        #Flesh out shortcut notation    
+        if outputCommand in ('H','V'):
+            if outputCommand == 'H':
+                params.append(pen[1])
+            if outputCommand == 'V':
+                params.insert(0,pen[0])
+            outputCommand = 'L'
+        if outputCommand in ('S','T'):
+            params.insert(0,pen[1]+(pen[1]-lastControl[1]))
+            params.insert(0,pen[0]+(pen[0]-lastControl[0]))
+            if outputCommand == 'S':
+                outputCommand = 'C'
+            if outputCommand == 'T':
+                outputCommand = 'Q'
+
+        #current values become "last" values
+        if outputCommand == 'M':
+            subPathStart = tuple(params[0:2])
+            pen = subPathStart
+        if outputCommand == 'Z':
+            pen = subPathStart
+        else:
+            pen = tuple(params[-2:])
+
+        if outputCommand in ('Q','C'):
+            lastControl = tuple(params[-4:-2])
+        else:
+            lastControl = pen
+        lastCommand = command
+
+        retval.append([outputCommand,params])
+    return retval
 
 def formatPath(a):
-       """Format SVG path data from an array"""
-       return "".join([cmd + " ".join([str(p) for p in params]) for cmd, params in a])
+    """Format SVG path data from an array"""
+    return "".join([cmd + " ".join([str(p) for p in params]) for cmd, params in a])
 
 def translatePath(p, x, y):
-       for cmd,params in p:
-               defs = pathdefs[cmd]
-               for i in range(defs[1]):
-                       if defs[3][i] == 'x':
-                               params[i] += x
-                       elif defs[3][i] == 'y':
-                               params[i] += y
+    for cmd,params in p:
+        defs = pathdefs[cmd]
+        for i in range(defs[1]):
+            if defs[3][i] == 'x':
+                params[i] += x
+            elif defs[3][i] == 'y':
+                params[i] += y
 
 def scalePath(p, x, y):
-       for cmd,params in p:
-               defs = pathdefs[cmd]
-               for i in range(defs[1]):
-                       if defs[3][i] == 'x':
-                               params[i] *= x
-                       elif defs[3][i] == 'y':
-                               params[i] *= y
+    for cmd,params in p:
+        defs = pathdefs[cmd]
+        for i in range(defs[1]):
+            if defs[3][i] == 'x':
+                params[i] *= x
+            elif defs[3][i] == 'y':
+                params[i] *= y
 
 def rotatePath(p, a, cx = 0, cy = 0):
-       if a == 0:
-               return p
-       for cmd,params in p:
-               defs = pathdefs[cmd]
-               for i in range(defs[1]):
-                       if defs[3][i] == 'x':
-                               x = params[i] - cx
-                               y = params[i + 1] - cy
-                               r = math.sqrt((x**2) + (y**2))
-                               if r != 0:
-                                       theta = math.atan2(y, x) + a
-                                       params[i] = (r * math.cos(theta)) + cx
-                                       params[i + 1] = (r * math.sin(theta)) + cy
+    if a == 0:
+        return p
+    for cmd,params in p:
+        defs = pathdefs[cmd]
+        for i in range(defs[1]):
+            if defs[3][i] == 'x':
+                x = params[i] - cx
+                y = params[i + 1] - cy
+                r = math.sqrt((x**2) + (y**2))
+                if r != 0:
+                    theta = math.atan2(y, x) + a
+                    params[i] = (r * math.cos(theta)) + cx
+                    params[i + 1] = (r * math.sin(theta)) + cy
+
 
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99