Code

fix bug with implicit paths
[inkscape.git] / share / extensions / interp.py
index 5edbf026ddc34366f4b706d83c199194dfd72ae5..ba8d8d7f40f6ec8b2e1494c5f4cc871b2704bc09 100755 (executable)
@@ -20,313 +20,313 @@ import inkex, cubicsuperpath, simplestyle, copy, math, re, bezmisc
 
 uuconv = {'in':90.0, 'pt':1.25, 'px':1, 'mm':3.5433070866, 'cm':35.433070866, 'pc':15.0}
 def numsegs(csp):
-       return sum([len(p)-1 for p in csp])
+    return sum([len(p)-1 for p in csp])
 def interpcoord(v1,v2,p):
-       return v1+((v2-v1)*p)
+    return v1+((v2-v1)*p)
 def interppoints(p1,p2,p):
-       return [interpcoord(p1[0],p2[0],p),interpcoord(p1[1],p2[1],p)]
+    return [interpcoord(p1[0],p2[0],p),interpcoord(p1[1],p2[1],p)]
 def pointdistance((x1,y1),(x2,y2)):
-       return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
+    return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
 def bezlenapprx(sp1, sp2):
-       return pointdistance(sp1[1], sp1[2]) + pointdistance(sp1[2], sp2[0]) + pointdistance(sp2[0], sp2[1])
+    return pointdistance(sp1[1], sp1[2]) + pointdistance(sp1[2], sp2[0]) + pointdistance(sp2[0], sp2[1])
 def tpoint((x1,y1), (x2,y2), t = 0.5):
-       return [x1+t*(x2-x1),y1+t*(y2-y1)]
+    return [x1+t*(x2-x1),y1+t*(y2-y1)]
 def cspbezsplit(sp1, sp2, t = 0.5):
-       m1=tpoint(sp1[1],sp1[2],t)
-       m2=tpoint(sp1[2],sp2[0],t)
-       m3=tpoint(sp2[0],sp2[1],t)
-       m4=tpoint(m1,m2,t)
-       m5=tpoint(m2,m3,t)
-       m=tpoint(m4,m5,t)
-       return [[sp1[0][:],sp1[1][:],m1], [m4,m,m5], [m3,sp2[1][:],sp2[2][:]]]
+    m1=tpoint(sp1[1],sp1[2],t)
+    m2=tpoint(sp1[2],sp2[0],t)
+    m3=tpoint(sp2[0],sp2[1],t)
+    m4=tpoint(m1,m2,t)
+    m5=tpoint(m2,m3,t)
+    m=tpoint(m4,m5,t)
+    return [[sp1[0][:],sp1[1][:],m1], [m4,m,m5], [m3,sp2[1][:],sp2[2][:]]]
 def cspbezsplitatlength(sp1, sp2, l = 0.5, tolerance = 0.001):
-       bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
-       t = bezmisc.beziertatlength(bez, l, tolerance)
-       return cspbezsplit(sp1, sp2, t)
+    bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
+    t = bezmisc.beziertatlength(bez, l, tolerance)
+    return cspbezsplit(sp1, sp2, t)
 def cspseglength(sp1,sp2, tolerance = 0.001):
-       bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
-       return bezmisc.bezierlength(bez, tolerance)     
+    bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
+    return bezmisc.bezierlength(bez, tolerance)    
 def csplength(csp):
-       total = 0
-       lengths = []
-       for sp in csp:
-               lengths.append([])
-               for i in xrange(1,len(sp)):
-                       l = cspseglength(sp[i-1],sp[i])
-                       lengths[-1].append(l)
-                       total += l                      
-       return lengths, total
+    total = 0
+    lengths = []
+    for sp in csp:
+        lengths.append([])
+        for i in xrange(1,len(sp)):
+            l = cspseglength(sp[i-1],sp[i])
+            lengths[-1].append(l)
+            total += l            
+    return lengths, total
 def styleunittouu(string):
-       unit = re.compile('(%s)$' % '|'.join(uuconv.keys()))
-       param = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
+    unit = re.compile('(%s)$' % '|'.join(uuconv.keys()))
+    param = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
 
-       p = param.match(string)
-       u = unit.search(string) 
-       if p:
-               retval = float(p.string[p.start():p.end()])
-       else:
-               retval = 0.0
-       if u:
-               try:
-                       return retval * uuconv[u.string[u.start():u.end()]]
-               except KeyError:
-                       pass
-       return retval
-       
+    p = param.match(string)
+    u = unit.search(string)    
+    if p:
+        retval = float(p.string[p.start():p.end()])
+    else:
+        retval = 0.0
+    if u:
+        try:
+            return retval * uuconv[u.string[u.start():u.end()]]
+        except KeyError:
+            pass
+    return retval
+    
 def tweenstylefloat(property, start, end, time):
-       sp = float(start[property])
-       ep = float(end[property])
-       return str(sp + (time * (ep - sp)))
+    sp = float(start[property])
+    ep = float(end[property])
+    return str(sp + (time * (ep - sp)))
 def tweenstyleunit(property, start, end, time):
-       sp = styleunittouu(start[property])
-       ep = styleunittouu(end[property])
-       return str(sp + (time * (ep - sp)))
+    sp = styleunittouu(start[property])
+    ep = styleunittouu(end[property])
+    return str(sp + (time * (ep - sp)))
 def tweenstylecolor(property, start, end, time):
-       sr,sg,sb = parsecolor(start[property])
-       er,eg,eb = parsecolor(end[property])
-       return '#%s%s%s' % (tweenhex(time,sr,er),tweenhex(time,sg,eg),tweenhex(time,sb,eb))
+    sr,sg,sb = parsecolor(start[property])
+    er,eg,eb = parsecolor(end[property])
+    return '#%s%s%s' % (tweenhex(time,sr,er),tweenhex(time,sg,eg),tweenhex(time,sb,eb))
 def tweenhex(time,s,e):
-       s = float(int(s,16))
-       e = float(int(e,16))
-       retval = hex(int(math.floor(s + (time * (e - s)))))[2:]
-       if len(retval)==1:
-               retval = '0%s' % retval
-       return retval
+    s = float(int(s,16))
+    e = float(int(e,16))
+    retval = hex(int(math.floor(s + (time * (e - s)))))[2:]
+    if len(retval)==1:
+        retval = '0%s' % retval
+    return retval
 def parsecolor(c):
-       r,g,b = '0','0','0'
-       if c[:1]=='#':
-               if len(c)==4:
-                       r,g,b = c[1:2],c[2:3],c[3:4]
-               elif len(c)==7:
-                       r,g,b = c[1:3],c[3:5],c[5:7]
-       return r,g,b
+    r,g,b = '0','0','0'
+    if c[:1]=='#':
+        if len(c)==4:
+            r,g,b = c[1:2],c[2:3],c[3:4]
+        elif len(c)==7:
+            r,g,b = c[1:3],c[3:5],c[5:7]
+    return r,g,b
 
 class Interp(inkex.Effect):
-       def __init__(self):
-               inkex.Effect.__init__(self)
-               self.OptionParser.add_option("-e", "--exponent",
-                                               action="store", type="float", 
-                                               dest="exponent", default=0.0,
-                                               help="values other than zero give non linear interpolation")
-               self.OptionParser.add_option("-s", "--steps",
-                                               action="store", type="int", 
-                                               dest="steps", default=5,
-                                               help="number of interpolation steps")
-               self.OptionParser.add_option("-m", "--method",
-                                               action="store", type="int", 
-                                               dest="method", default=2,
-                                               help="method of interpolation")
-               self.OptionParser.add_option("-d", "--dup",
-                                               action="store", type="inkbool", 
-                                               dest="dup", default=True,
-                                               help="duplicate endpaths")      
-               self.OptionParser.add_option("--style",
-                                               action="store", type="inkbool", 
-                                               dest="style", default=True,
-                                               help="try interpolation of some style properties")      
-       def effect(self):
-               exponent = self.options.exponent
-               if exponent>= 0:
-                       exponent = 1.0 + exponent
-               else:
-                       exponent = 1.0/(1.0 - exponent)
-               steps = [1.0/(self.options.steps + 1.0)]
-               for i in range(self.options.steps - 1):
-                       steps.append(steps[0] + steps[-1])
-               steps = [step**exponent for step in steps]
-                       
-               paths = {}                      
-               styles = {}
-               for id in self.options.ids:
-                       node = self.selected[id]
-                       if node.tagName =='path':
-                               paths[id] = cubicsuperpath.parsePath(node.attributes.getNamedItem('d').value)
-                               styles[id] = simplestyle.parseStyle(node.attributes.getNamedItem('style').value)
-                       else:
-                               self.options.ids.remove(id)
+    def __init__(self):
+        inkex.Effect.__init__(self)
+        self.OptionParser.add_option("-e", "--exponent",
+                        action="store", type="float", 
+                        dest="exponent", default=0.0,
+                        help="values other than zero give non linear interpolation")
+        self.OptionParser.add_option("-s", "--steps",
+                        action="store", type="int", 
+                        dest="steps", default=5,
+                        help="number of interpolation steps")
+        self.OptionParser.add_option("-m", "--method",
+                        action="store", type="int", 
+                        dest="method", default=2,
+                        help="method of interpolation")
+        self.OptionParser.add_option("-d", "--dup",
+                        action="store", type="inkbool", 
+                        dest="dup", default=True,
+                        help="duplicate endpaths")    
+        self.OptionParser.add_option("--style",
+                        action="store", type="inkbool", 
+                        dest="style", default=True,
+                        help="try interpolation of some style properties")    
+    def effect(self):
+        exponent = self.options.exponent
+        if exponent>= 0:
+            exponent = 1.0 + exponent
+        else:
+            exponent = 1.0/(1.0 - exponent)
+        steps = [1.0/(self.options.steps + 1.0)]
+        for i in range(self.options.steps - 1):
+            steps.append(steps[0] + steps[-1])
+        steps = [step**exponent for step in steps]
+            
+        paths = {}            
+        styles = {}
+        for id in self.options.ids:
+            node = self.selected[id]
+            if node.tagName =='path':
+                paths[id] = cubicsuperpath.parsePath(node.attributes.getNamedItem('d').value)
+                styles[id] = simplestyle.parseStyle(node.attributes.getNamedItem('style').value)
+            else:
+                self.options.ids.remove(id)
 
-               for i in range(1,len(self.options.ids)):
-                       start = copy.deepcopy(paths[self.options.ids[i-1]])
-                       end = copy.deepcopy(paths[self.options.ids[i]])
-                       sst = copy.deepcopy(styles[self.options.ids[i-1]])
-                       est = copy.deepcopy(styles[self.options.ids[i]])
-                       basestyle = copy.deepcopy(sst)
+        for i in range(1,len(self.options.ids)):
+            start = copy.deepcopy(paths[self.options.ids[i-1]])
+            end = copy.deepcopy(paths[self.options.ids[i]])
+            sst = copy.deepcopy(styles[self.options.ids[i-1]])
+            est = copy.deepcopy(styles[self.options.ids[i]])
+            basestyle = copy.deepcopy(sst)
 
-                       #prepare for experimental style tweening
-                       if self.options.style:
-                               dostroke = True
-                               dofill = True
-                               styledefaults = {'opacity':'1.0', 'stroke-opacity':'1.0', 'fill-opacity':'1.0',
-                                               'stroke-width':'1.0', 'stroke':'none', 'fill':'none'}
-                               for key in styledefaults.keys():
-                                       sst.setdefault(key,styledefaults[key])
-                                       est.setdefault(key,styledefaults[key])
-                               isnotplain = lambda x: not (x=='none' or x[:1]=='#')
-                               if isnotplain(sst['stroke']) or isnotplain(est['stroke']) or (sst['stroke']=='none' and est['stroke']=='none'):
-                                       dostroke = False
-                               if isnotplain(sst['fill']) or isnotplain(est['fill']) or (sst['fill']=='none' and est['fill']=='none'):
-                                       dofill = False
-                               if dostroke:
-                                       if sst['stroke']=='none':
-                                               sst['stroke-width'] = '0.0'
-                                               sst['stroke-opacity'] = '0.0'
-                                               sst['stroke'] = est['stroke'] 
-                                       elif est['stroke']=='none':
-                                               est['stroke-width'] = '0.0'
-                                               est['stroke-opacity'] = '0.0'
-                                               est['stroke'] = sst['stroke'] 
-                               if dofill:
-                                       if sst['fill']=='none':
-                                               sst['fill-opacity'] = '0.0'
-                                               sst['fill'] = est['fill'] 
-                                       elif est['fill']=='none':
-                                               est['fill-opacity'] = '0.0'
-                                               est['fill'] = sst['fill'] 
+            #prepare for experimental style tweening
+            if self.options.style:
+                dostroke = True
+                dofill = True
+                styledefaults = {'opacity':'1.0', 'stroke-opacity':'1.0', 'fill-opacity':'1.0',
+                        'stroke-width':'1.0', 'stroke':'none', 'fill':'none'}
+                for key in styledefaults.keys():
+                    sst.setdefault(key,styledefaults[key])
+                    est.setdefault(key,styledefaults[key])
+                isnotplain = lambda x: not (x=='none' or x[:1]=='#')
+                if isnotplain(sst['stroke']) or isnotplain(est['stroke']) or (sst['stroke']=='none' and est['stroke']=='none'):
+                    dostroke = False
+                if isnotplain(sst['fill']) or isnotplain(est['fill']) or (sst['fill']=='none' and est['fill']=='none'):
+                    dofill = False
+                if dostroke:
+                    if sst['stroke']=='none':
+                        sst['stroke-width'] = '0.0'
+                        sst['stroke-opacity'] = '0.0'
+                        sst['stroke'] = est['stroke'] 
+                    elif est['stroke']=='none':
+                        est['stroke-width'] = '0.0'
+                        est['stroke-opacity'] = '0.0'
+                        est['stroke'] = sst['stroke'] 
+                if dofill:
+                    if sst['fill']=='none':
+                        sst['fill-opacity'] = '0.0'
+                        sst['fill'] = est['fill'] 
+                    elif est['fill']=='none':
+                        est['fill-opacity'] = '0.0'
+                        est['fill'] = sst['fill'] 
 
-                                       
+                    
 
-                       if self.options.method == 2:
-                               #subdivide both paths into segments of relatively equal lengths
-                               slengths, stotal = csplength(start)
-                               elengths, etotal = csplength(end)
-                               lengths = {}
-                               t = 0
-                               for sp in slengths:
-                                       for l in sp:
-                                               t += l / stotal
-                                               lengths.setdefault(t,0)
-                                               lengths[t] += 1
-                               t = 0
-                               for sp in elengths:
-                                       for l in sp:
-                                               t += l / etotal
-                                               lengths.setdefault(t,0)
-                                               lengths[t] += -1
-                               sadd = [k for (k,v) in lengths.iteritems() if v < 0]
-                               sadd.sort()
-                               eadd = [k for (k,v) in lengths.iteritems() if v > 0]
-                               eadd.sort()
+            if self.options.method == 2:
+                #subdivide both paths into segments of relatively equal lengths
+                slengths, stotal = csplength(start)
+                elengths, etotal = csplength(end)
+                lengths = {}
+                t = 0
+                for sp in slengths:
+                    for l in sp:
+                        t += l / stotal
+                        lengths.setdefault(t,0)
+                        lengths[t] += 1
+                t = 0
+                for sp in elengths:
+                    for l in sp:
+                        t += l / etotal
+                        lengths.setdefault(t,0)
+                        lengths[t] += -1
+                sadd = [k for (k,v) in lengths.iteritems() if v < 0]
+                sadd.sort()
+                eadd = [k for (k,v) in lengths.iteritems() if v > 0]
+                eadd.sort()
 
-                               t = 0
-                               s = [[]]
-                               for sp in slengths:
-                                       if not start[0]:
-                                               s.append(start.pop(0))
-                                       s[-1].append(start[0].pop(0))
-                                       for l in sp:
-                                               pt = t
-                                               t += l / stotal
-                                               if sadd and t > sadd[0]:
-                                                       while sadd and sadd[0] < t:
-                                                               nt = (sadd[0] - pt) / (t - pt)
-                                                               bezes = cspbezsplitatlength(s[-1][-1][:],start[0][0][:], nt)
-                                                               s[-1][-1:] = bezes[:2]
-                                                               start[0][0] = bezes[2]
-                                                               pt = sadd.pop(0)
-                                               s[-1].append(start[0].pop(0))
-                               t = 0
-                               e = [[]]
-                               for sp in elengths:
-                                       if not end[0]:
-                                               e.append(end.pop(0))
-                                       e[-1].append(end[0].pop(0))
-                                       for l in sp:
-                                               pt = t
-                                               t += l / etotal
-                                               if eadd and t > eadd[0]:
-                                                       while eadd and eadd[0] < t:
-                                                               nt = (eadd[0] - pt) / (t - pt)
-                                                               bezes = cspbezsplitatlength(e[-1][-1][:],end[0][0][:], nt)
-                                                               e[-1][-1:] = bezes[:2]
-                                                               end[0][0] = bezes[2]
-                                                               pt = eadd.pop(0)
-                                               e[-1].append(end[0].pop(0))
-                               start = s[:]
-                               end = e[:]
-                       else:
-                               #which path has fewer segments?
-                               lengthdiff = numsegs(start) - numsegs(end)
-                               #swap shortest first
-                               if lengthdiff > 0:
-                                       start, end = end, start
-                               #subdivide the shorter path
-                               for x in range(abs(lengthdiff)):
-                                       maxlen = 0
-                                       subpath = 0
-                                       segment = 0
-                                       for y in range(len(start)):
-                                               for z in range(1, len(start[y])):
-                                                       leng = bezlenapprx(start[y][z-1], start[y][z])
-                                                       if leng > maxlen:
-                                                               maxlen = leng
-                                                               subpath = y
-                                                               segment = z
-                                       sp1, sp2 = start[subpath][segment - 1:segment + 1]
-                                       start[subpath][segment - 1:segment + 1] = cspbezsplit(sp1, sp2)
-                               #if swapped, swap them back
-                               if lengthdiff > 0:
-                                       start, end = end, start
-                       
-                       #break paths so that corresponding subpaths have an equal number of segments
-                       s = [[]]
-                       e = [[]]
-                       while start and end:
-                               if start[0] and end[0]:
-                                       s[-1].append(start[0].pop(0))
-                                       e[-1].append(end[0].pop(0))
-                               elif end[0]:
-                                       s.append(start.pop(0))
-                                       e[-1].append(end[0][0])
-                                       e.append([end[0].pop(0)])
-                               elif start[0]:
-                                       e.append(end.pop(0))
-                                       s[-1].append(start[0][0])
-                                       s.append([start[0].pop(0)])
-                               else:
-                                       s.append(start.pop(0))
-                                       e.append(end.pop(0))
-       
-                       if self.options.dup:
-                               steps = [0] + steps + [1]       
-                       #create an interpolated path for each interval
-                       group = self.document.createElement('svg:g')    
-                       self.document.documentElement.appendChild(group)
-                       for time in steps:
-                               interp = []
-                               #process subpaths
-                               for ssp,esp in zip(s, e):
-                                       if not (ssp or esp):
-                                               break
-                                       interp.append([])
-                                       #process superpoints
-                                       for sp,ep in zip(ssp, esp):
-                                               if not (sp or ep):
-                                                       break
-                                               interp[-1].append([])
-                                               #process points
-                                               for p1,p2 in zip(sp, ep):
-                                                       if not (sp or ep):
-                                                               break
-                                                       interp[-1][-1].append(interppoints(p1, p2, time))
+                t = 0
+                s = [[]]
+                for sp in slengths:
+                    if not start[0]:
+                        s.append(start.pop(0))
+                    s[-1].append(start[0].pop(0))
+                    for l in sp:
+                        pt = t
+                        t += l / stotal
+                        if sadd and t > sadd[0]:
+                            while sadd and sadd[0] < t:
+                                nt = (sadd[0] - pt) / (t - pt)
+                                bezes = cspbezsplitatlength(s[-1][-1][:],start[0][0][:], nt)
+                                s[-1][-1:] = bezes[:2]
+                                start[0][0] = bezes[2]
+                                pt = sadd.pop(0)
+                        s[-1].append(start[0].pop(0))
+                t = 0
+                e = [[]]
+                for sp in elengths:
+                    if not end[0]:
+                        e.append(end.pop(0))
+                    e[-1].append(end[0].pop(0))
+                    for l in sp:
+                        pt = t
+                        t += l / etotal
+                        if eadd and t > eadd[0]:
+                            while eadd and eadd[0] < t:
+                                nt = (eadd[0] - pt) / (t - pt)
+                                bezes = cspbezsplitatlength(e[-1][-1][:],end[0][0][:], nt)
+                                e[-1][-1:] = bezes[:2]
+                                end[0][0] = bezes[2]
+                                pt = eadd.pop(0)
+                        e[-1].append(end[0].pop(0))
+                start = s[:]
+                end = e[:]
+            else:
+                #which path has fewer segments?
+                lengthdiff = numsegs(start) - numsegs(end)
+                #swap shortest first
+                if lengthdiff > 0:
+                    start, end = end, start
+                #subdivide the shorter path
+                for x in range(abs(lengthdiff)):
+                    maxlen = 0
+                    subpath = 0
+                    segment = 0
+                    for y in range(len(start)):
+                        for z in range(1, len(start[y])):
+                            leng = bezlenapprx(start[y][z-1], start[y][z])
+                            if leng > maxlen:
+                                maxlen = leng
+                                subpath = y
+                                segment = z
+                    sp1, sp2 = start[subpath][segment - 1:segment + 1]
+                    start[subpath][segment - 1:segment + 1] = cspbezsplit(sp1, sp2)
+                #if swapped, swap them back
+                if lengthdiff > 0:
+                    start, end = end, start
+            
+            #break paths so that corresponding subpaths have an equal number of segments
+            s = [[]]
+            e = [[]]
+            while start and end:
+                if start[0] and end[0]:
+                    s[-1].append(start[0].pop(0))
+                    e[-1].append(end[0].pop(0))
+                elif end[0]:
+                    s.append(start.pop(0))
+                    e[-1].append(end[0][0])
+                    e.append([end[0].pop(0)])
+                elif start[0]:
+                    e.append(end.pop(0))
+                    s[-1].append(start[0][0])
+                    s.append([start[0].pop(0)])
+                else:
+                    s.append(start.pop(0))
+                    e.append(end.pop(0))
+    
+            if self.options.dup:
+                steps = [0] + steps + [1]    
+            #create an interpolated path for each interval
+            group = self.document.createElement('svg:g')    
+            self.current_layer.appendChild(group)
+            for time in steps:
+                interp = []
+                #process subpaths
+                for ssp,esp in zip(s, e):
+                    if not (ssp or esp):
+                        break
+                    interp.append([])
+                    #process superpoints
+                    for sp,ep in zip(ssp, esp):
+                        if not (sp or ep):
+                            break
+                        interp[-1].append([])
+                        #process points
+                        for p1,p2 in zip(sp, ep):
+                            if not (sp or ep):
+                                break
+                            interp[-1][-1].append(interppoints(p1, p2, time))
 
-                               #remove final subpath if empty.
-                               if not interp[-1]:
-                                       del interp[-1]
-                               new = self.document.createElement('svg:path')
+                #remove final subpath if empty.
+                if not interp[-1]:
+                    del interp[-1]
+                new = self.document.createElement('svg:path')
 
-                               #basic style tweening
-                               if self.options.style:
-                                       basestyle['opacity'] = tweenstylefloat('opacity',sst,est,time)
-                                       if dostroke:
-                                               basestyle['stroke-opacity'] = tweenstylefloat('stroke-opacity',sst,est,time)
-                                               basestyle['stroke-width'] = tweenstyleunit('stroke-width',sst,est,time)
-                                               basestyle['stroke'] = tweenstylecolor('stroke',sst,est,time)
-                                       if dofill:
-                                               basestyle['fill-opacity'] = tweenstylefloat('fill-opacity',sst,est,time)
-                                               basestyle['fill'] = tweenstylecolor('fill',sst,est,time)
-                               new.setAttribute('style', simplestyle.formatStyle(basestyle))
-                               new.setAttribute('d', cubicsuperpath.formatPath(interp))
-                               group.appendChild(new)
+                #basic style tweening
+                if self.options.style:
+                    basestyle['opacity'] = tweenstylefloat('opacity',sst,est,time)
+                    if dostroke:
+                        basestyle['stroke-opacity'] = tweenstylefloat('stroke-opacity',sst,est,time)
+                        basestyle['stroke-width'] = tweenstyleunit('stroke-width',sst,est,time)
+                        basestyle['stroke'] = tweenstylecolor('stroke',sst,est,time)
+                    if dofill:
+                        basestyle['fill-opacity'] = tweenstylefloat('fill-opacity',sst,est,time)
+                        basestyle['fill'] = tweenstylecolor('fill',sst,est,time)
+                new.setAttribute('style', simplestyle.formatStyle(basestyle))
+                new.setAttribute('d', cubicsuperpath.formatPath(interp))
+                group.appendChild(new)
 
 e = Interp()
 e.affect()