changeset 1141:8f0ee167c5b2

Fix the issue of the new DOM implementation
author wycc
date Thu, 23 Dec 2010 00:00:46 +0800
parents d4dbcb93aee0 (diff) a2b068594412 (current diff)
children dd6c60c6f41e e14ec6d1a661
files pyink/MBScene.py pyink/tween.py
diffstat 3 files changed, 336 insertions(+), 293 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Wed Dec 22 13:27:37 2010 +0800
+++ b/pyink/MBScene.py	Thu Dec 23 00:00:46 2010 +0800
@@ -11,6 +11,7 @@
 import time
 import pybInkscape
 import math
+from tween import TweenObject
 
 # Please refer to
 # http://www.assembla.com/wiki/show/MadButterfly/Inkscape_extention
@@ -132,33 +133,15 @@
 	pybInkscape.inkscape.connect('change_selection', self.show_selection)
 	self.last_select = None
 	self.lockui=False
+	self.tween=None
+	self.document = None
+	self.dom = None
 	pass
 
-    def startPolling(self):
-	objs =  self.desktop.selection.list()
-	if len(objs) != 1: 
-	    glib.timeout_add(500,self.startPolling)
-	    try:
-		self.nameEditor.set_text('')
-	    except:
-		traceback.print_exc()
-		pass
-	    return
-	o = objs[0]
-	if o == self.last_select: 
-            glib.timeout_add(500,self.startPolling)
-	    return
-	self.last_select = o
-	try:
-	    self.nameEditor.set_text(o.getAttribute("inkscape:label"))
-	except:
-	    self.nameEditor.set_text('')
-	    pass
-        glib.timeout_add(500,self.startPolling)
     def show_selection(self,w,obj):
 	objs =  self.desktop.selection.list()
 	try:
-	    o = objs[0].repr
+	    o = objs[0]
 	    print o.getCenter()
 	    if o == self.last_select: 
 	        return
@@ -241,13 +224,14 @@
 	    pass
 	pass
 	if self.scenemap==None:
-	    self.document.root().setAttribute("xmlns:ns0","http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd")
+	    #self.desktop.doc().root().repr.setAttribute("xmlns:ns0","http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd")
+	    self.dom.setAttribute("xmlns:ns0","http://madbutterfly.sourceforge.net/DTD/madbutterfly.dtd")
 	    scenes = self.document.createElement("ns0:scenes")
 	    node.appendChild(scenes)
     def update(self):
-        root = self.document.root()
+        doc = self.dom
 	rdoc = self.document
-	for node in root.childList():
+	for node in doc.childList():
 	    if node.name() == 'svg:metadata':
 	        for t in node.childList():
 		    if t.name() == "ns0:scenes":
@@ -267,22 +251,22 @@
 	"""
 	self.layers = []
 	self.scenemap = None
-	root = self.document.root()
+	doc = self.dom
 
         #obs = pybInkscape.PYNodeObserver()
         #obs = LayerAddRemoveWatcher(self)
-        #root.addObserver(obs)
-	addEventListener(root,'DOMNodeInserted',self.updateUI,None)
-	addEventListener(root,'DOMNodeRemoved',self.updateUI,None)
-	root.childList()
+        #doc.addObserver(obs)
+	addEventListener(doc,'DOMNodeInserted',self.updateUI,None)
+	addEventListener(doc,'DOMNodeRemoved',self.updateUI,None)
+	doc.childList()
 	try:
-	    self.width = float(root.getAttribute("width"))
-	    self.height= float(root.getAttribute("height"))
+	    self.width = float(doc.getAttribute("width"))
+	    self.height= float(doc.getAttribute("height"))
 	except:
 	    self.width = 640
 	    self.height=480
 	    
-	for node in root.childList():
+	for node in doc.childList():
 	    print node.name()
 	    if node.name() == 'svg:metadata':
 		self.parseMetadata(node)
@@ -330,7 +314,7 @@
 
     def collectID(self):
 	self.ID = {}
-	root = self.document.root()
+	root = self.dom
 	for n in root.childList():
 	    self.collectID_recursive(n)
 	    pass
@@ -339,7 +323,7 @@
     def collectID_recursive(self,node):
 	try:
 	    self.ID[node.getAttribute('id')] = 1
-	except KeyError:
+	except:
 	    pass
 	for n in node.childList():
 	    self.collectID_recursive(n)
@@ -388,12 +372,7 @@
 	txt.setAttribute("height","100")
 	txt.setAttribute("style","fill:#ff00")
 	ns.appendChild(txt)
-	try:
-	    gid = self.last_line.node.getAttribute('inkscape:label') + \
-		self.newID()
-	except KeyError:
-	    gid = self.newID()
-	    pass
+	gid = self.last_line.node.label()+self.newID()
 	self.ID[gid]=1
 	ns.setAttribute("id",gid)
 	ns.setAttribute("inkscape:groupmode","layer")
@@ -509,6 +488,8 @@
 	    pass
 	pass
 
+
+    
     def setCurrentScene(self,nth):
 	"""
 	    Update the scene group according to the curretn scene data. There are a couple of cases.
@@ -524,6 +505,7 @@
 	    available.
 	"""
 	self.current = nth
+	self.tween.updateMapping()
 	for layer in self._framelines:
 	    i=0
 
@@ -559,255 +541,41 @@
 			    layer.duplicateGroup.setAttribute("sodipodi:insensitive","1")
 			    s.ref.setAttribute("style","display:none")
 			    s.ref.parent().appendChild(layer.duplicateGroup)
-			    self.updateTweenContent(layer.duplicateGroup, layer.get_tween_type(s.idx),s, layer._keys[i+2], nth)
+			    self.tween.updateTweenContent(layer.duplicateGroup, layer.get_tween_type(s.idx),s, layer._keys[i+2], nth)
+			else:
+			    layer.duplicateGroup = s.ref.duplicate(self.document)
+			    layer.duplicateGroup.setAttribute("style","")
+			    layer.duplicateGroup.setAttribute("inkscape:label","dup")
+			    layer.duplicateGroup.setAttribute("sodipodi:insensitive","1")
+			    s.ref.setAttribute("style","display:none")
+			    s.ref.parent().appendChild(layer.duplicateGroup)
 		    else:
 		        s.ref.setAttribute("style","display:none")
 		i = i + 2
 		pass
 	    pass
 	pass
-    def updateTweenContent(self,obj, typ, source,dest,cur):
-	"""
-	    Update the content of the duplicate scene group. We will use the (start,end) and cur to calculate the percentage of
-	    the tween motion effect and then use it to update the transform matrix of the duplicated scene group.
+
+    def DOMtoItem(self,obj):
 	"""
-	start = source.idx
-	end = dest.idx
-	print cur,start,end
-	percent = (cur-start)*1.0/(end-start)
-	i = 0
-	s = source.ref.firstChild()
-	d = dest.ref.firstChild()
-	sources={}
-	dests={}
-	
-	# Collect all objects
-	while d:
-	    try:
-		label = d.getAttribute("inkscape:label")
-	    except KeyError:
-		d = d.next()
-		continue
-	    dests[label] = d
-	    d = d.next()
-	# Check if the object in the source exists in the destination
-	s = source.ref.firstChild()
-	d = dest.ref.firstChild()
-	while s:
-	    print s,d
-	    try:
-		label = s.getAttribute("inkscape:label")
-		# Use i8nkscape:label to identidy the equipvalent objects
-		if label:
-		    if dests.hasattr(label.value()):
-			self.updateTweenObject(obj,typ,s,dests[label.value()],percent)
-			s = s.next()
-			continue
-	    except:
-		pass
-	    # Search obejcts in the destination
-	    while d:
-		try:
-		    d.getAttribute("inkscape:label")
-		    d = d.next()
-		    continue
-		except:
-		    pass
-		if s.name() == d.name():
-		    self.updateTweenObject(obj,typ,s,d,percent)
-		    d = d.next()
-		    break
-		d = d.next()
-	    s = s.next()
-    def parseTransform(self,obj):
-	"""
-	    Return the transform matrix of an object
-	"""
-	try:
-	    t = obj.getAttribute("transform")
-	    print t
-	    if t[0:9] == 'translate':
-		print "translate"
-		fields = t[10:].split(',')
-		x = float(fields[0])
-		fields = fields[1].split(')')
-		y = float(fields[0])
-		return [1,0,0,1,x,y]
-	    elif t[0:6] == 'matrix':
-		print "matrix"
-		fields=t[7:].split(')')
-		fields = fields[0].split(',')
-		return [float(fields[0]),float(fields[1]),float(fields[2]),float(fields[3]),float(fields[4]),float(fields[5])]
-	except:
-	    #traceback.print_exc()
-	    return [1,0,0,1,0,0]
-
-    def invA(self,m):
-        d = m[0]*m[3]-m[2]*m[1]
-	return [m[3]/d, -m[1]/d, -m[2]/d, m[0]/d, (m[1]*m[5]-m[4]*m[3])/d, (m[4]*m[2]-m[0]*m[5])/d]
-    def mulA(self,a,b):
-        return [a[0]*b[0]+a[1]*b[2],
-	        a[0]*b[1]+a[1]*b[3],
-		a[2]*b[0]+a[3]*b[2],
-		a[2]*b[1]+a[3]*b[3],
-		a[0]*b[4]+a[1]*b[5]+a[4],
-		a[2]*b[4]+a[3]*b[5]+a[5]]
-    def parseMatrix(self,m):
-        d = (1-m[0])*(1-m[3])-m[1]*m[2]
-	if d == 0:
-	    return [1,0,0,1,m[4],m[5]]
-	else:
-            return [m[0],m[1],m[2],m[3],(m[4]-m[3]*m[4]+m[1]*m[5])/d,(m[5]-m[0]*m[5]+m[2]*m[4])/d]
-
-    def decomposition(self,m):
-	"""
-	Decompose the affine matrix into production of translation,rotation,shear and scale.
-	The algorithm is documented at http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
+	Find the corresponding PYSPObject object for a DOM object.
 	"""
-        if m[0]*m[3] == m[1]*m[2]:
-	    print "The affine matrix is singular"
-	    return [1,0,0,1,0,0]
-	A=m[0]
-	B=m[2]
-	C=m[1]
-	D=m[3]
-	E=m[4]
-	F=m[5]
-	sx = math.sqrt(A*A+B*B)
-	A = A/sx
-	B = B/sx
-	shear = m[0]*m[1]+m[2]*m[3]
-	C = C - A*shear
-	D = D - B*shear
-	sy = math.sqrt(C*C+D*D)
-	C = C/sy
-	D = D/sy
-	r = A*D-B*C
-	if r == -1:
-	    shear = -shear
-	    sy = -sy
-	R = math.atan2(B,A)
-	return [sx,sy, R, E,F]
+	return self.DOMtoItem_recursive(self.desktop.doc().root(),obj)
 
-	    
-    def updateTweenObject(self,obj,typ,s,d,p):
-	"""
-	    Generate tweened object in the @obj by using s and d in the @p percent
-	    http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
-	"""
-	print 'compare',s,d
-	if typ == 'relocate':
-	    print "percent",p
-	    newobj = s.duplicate(self.document)
-	    newobj.setAttribute("ref", s.getAttribute('id'))
-	    top = self.document.createElement("svg:g")
-	    top.appendChild(newobj)
-	    obj.appendChild(top)
-	    print s.name()
-	    if s.name() == 'svg:g':
-		# Parse the translate or matrix
-		sm = self.parseTransform(s)
-		dm = self.parseTransform(d)
-		top.setAttribute("transform","translate(%g,%g)" % ((dm[2]-sm[2])*p,(dm[5]-sm[5])*p))
-	    else:
-		try:
-		    sx = float(s.getAttribute("x"))
-		    sy = float(s.getAttribute("y"))
-		    dx = float(d.getAttribute("x"))
-		    dy = float(d.getAttribute("y"))
-		    tx = (dx-sx)*p
-		    ty = (dy-sy)*p
-		    print tx,ty
-		    top.setAttribute("transform","translate(%g,%g)" % (tx,ty))
-		except:
-		    #traceback.print_exc()
-		    pass
-	    pass
-	elif typ == 'scale':
-	    newobj = s.duplicate(self.document)
-	    top = self.document.createElement("svg:g")
-	    top.appendChild(newobj)
-	    obj.appendChild(top)
-	        
-	    print s,d
-	    if s.name() == 'svg:g':
-		# Parse the translate or matrix
-		# 
-		# D  = B inv(A)
-		item = s.spitem
-		(ox,oy) = item.getCenter()
-		item = d.spitem
-		(dx,dy) = item.getCenter()
-		    
-		sm = self.parseTransform(s)
-		ss = self.decomposition(sm)
-		dm = self.parseTransform(d)
-		dd = self.decomposition(dm)
-		sx = (ss[0]*(1-p)+dd[0]*p)/ss[0]
-		sy = (ss[1]*(1-p)+dd[1]*p)/ss[0]
-		a  = ss[2]*(1-p)+dd[2]*p-ss[2]
-		tx = ox*(1-p)+dx*p-ox
-		ty = oy*(1-p)+dy*p-oy
-		m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0]
-		m = self.mulA([sx,0,0,sy,0,0],m)
-		m = self.mulA(m,[1,0,0,1,-ox,oy-self.height])
-		m = self.mulA([1,0,0,1,tx,self.height-ty],m)
+    def DOMtoItem_recursive(self,tree,obj):
+	nodes = tree.childList()
+	for s in nodes:
+	    if s.getId() == obj.getAttribute('id'):
+	        return s
+	    d = self.DOMtoItem_recursive(s,obj)
+	    if d != None: return d
+	     
 
-		top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5]))
-	    else:
-		try:
-		    sw = float(s.getAttribute("width"))
-		    sh = float(s.getAttribute("height"))
-		    dw = float(d.getAttribute("width"))
-		    dh = float(d.getAttribute("height"))
-	            try:
-	                item = self.nodeToItem[s.attribute("id")]
-		        (ox,oy) = item.getCenter()
-	            except:
-		        ox = 0
-		        oy = 0
-	            try:
-	                item = self.nodeToItem[d.attribute("id")]
-		        (dx,dy) = item.getCenter()
-	            except:
-		        dx = 0
-		        dy = 0
-		    try:
-		        sm = self.parseTransform(s)
-		        ss = self.decomposition(sm)
-		    except:
-		        ss = [1,1,0,0,0]
-		        pass
-		    try:
-		        dm = self.parseTransform(d)
-		        dd = self.decomposition(dm)
-		    except:
-		        dd = [1,1,0,0,0]
-		        pass
-		    dd[0] = ss[0]*dw/sw
-		    dd[1] = ss[1]*dh/sh
-		    sx = (ss[0]*(1-p)+dd[0]*p)/ss[0]
-		    sy = (ss[1]*(1-p)+dd[1]*p)/ss[1]
-		    a  = ss[2]*(1-p)+dd[2]*p-ss[2]
-		    tx = ox*(1-p)+dx*p
-		    ty = oy*(1-p)+dy*p
-		    m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0]
-		    m = self.mulA([sx,0,0,sy,0,0],m)
-		    m = self.mulA(m,[1,0,0,1,-ox,oy-self.height])
-		    m = self.mulA([1,0,0,1,tx,self.height-ty],m)
-
-		    top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5]))
-		except:
-		    traceback.print_exc()
-		    pass
-	    pass
-	    
-	pass
     def enterGroup(self,obj):
         for l in self.layers:
 	    for s in l.node.childList():
 	        if s.getAttribute('id') == obj.getAttribute("id"):
-		    self.desktop.setCurrentLayer(s.spitem)
+		    self.desktop.setCurrentLayer(self.DOMtoItem(s))
         
     def selectSceneObject(self,frameline, nth):
         i = 0
@@ -898,7 +666,7 @@
 	for i in range(len(self.layers)-1,-1,-1):
 	    line = frameline.frameline(nframes)
 	    hbox = gtk.HBox()
-	    label = gtk.Label(self.layers[i].node.getAttribute('inkscape:label'))
+	    label = gtk.Label(self.layers[i].node.getAttribute("inkscape:label"))
 	    label.set_size_request(100,0)
 	    hbox.pack_start(label,expand=False,fill=True)
 	    hbox.pack_start(line)
@@ -919,11 +687,10 @@
     def _update_framelines(self):
 	for frameline in self._framelines:
 	    layer = frameline.layer
-	    try:
-	        frameline.label.set_text(frameline.node.getAttribute('inkscape:label'))
-	    except KeyError:
-		frameline.label.set_text('???')
-		pass
+	    if frameline.node.getAttribute("inkscape:label")==None:
+	        frameline.label.set_text('???')
+	    else:
+	        frameline.label.set_text(frameline.node.getAttribute("inkscape:label"))
 	    for scene in layer.scenes:
 		frameline.add_keyframe(scene.start-1,scene.node)
 		if scene.start != scene.end:
@@ -964,10 +731,10 @@
 	    i = i + 1
     def duplicateSceneGroup(self,gid):
 	# Search for the duplicated group
-        root = self.document.root()
+        doc = self.dom
 	rdoc = self.document
 	orig = None
-	for node in root.childList():
+	for node in doc.childList():
 	    if node.name() == 'svg:g':
 	        for t in node.childList():
 		    if t.name() == "svg:g":
@@ -977,12 +744,7 @@
 	if orig == None:
 	    return None
 	ns = orig.duplicate(rdoc)
-	try:
-	    gid = self.last_line.node.getAttribute('inkscape:label') + \
-		self.newID()
-	except KeyError:
-	    gid = self.newID()
-	    pass
+	gid = self.last_line.node.label()+self.newID()
 	self.ID[gid]=1
 	ns.setAttribute("id",gid)
 	ns.setAttribute("inkscape:groupmode","layer")
@@ -1113,7 +875,9 @@
         self.last_update = glib.timeout_add(300,self.show)
     def show(self):
 	self.OK = True
+	self.dom = self.desktop.doc().root().repr
 	self.document = self.desktop.doc().rdoc
+	self.tween = TweenObject(self.document,self.dom)
 	self.parseScene()
 	self._create_framelines()
 	self._update_framelines()
--- a/pyink/primitive_test.svg	Wed Dec 22 13:27:37 2010 +0800
+++ b/pyink/primitive_test.svg	Thu Dec 23 00:00:46 2010 +0800
@@ -15,7 +15,7 @@
    id="svg2"
    version="1.1"
    inkscape:version="0.48+devel r9774 custom"
-   sodipodi:docname="aa.svg">
+   sodipodi:docname="primitive_test.svg">
   <defs
      id="defs4" />
   <sodipodi:namedview
@@ -56,6 +56,7 @@
       <ns0:scene
          start="21"
          ref="Layer 1s8009"
+         end="24"
          type="normal" />
     </ns0:scenes>
   </metadata>
@@ -84,8 +85,8 @@
          id="rect3431"
          height="432.13434"
          width="64.699173"
-         y="213.35323"
-         x="9.338623" />
+         y="220.30684"
+         x="3.5009925" />
     </g>
   </g>
 </svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyink/tween.py	Thu Dec 23 00:00:46 2010 +0800
@@ -0,0 +1,278 @@
+# -*- indent-tabs-mode: t; tab-width: 8; python-indent: 4; -*-
+# vim: sw=4:ts=8:sts=4
+import traceback
+import math
+class TweenObject:
+    def __init__(self,doc,dom):
+        self.document = doc
+	self.dom = dom
+	try:
+	    self.width = float(dom.getAttribute("width"))
+	    self.height = float(dom.getAttribute("height"))
+	except:
+	    self.width = 640
+	    self.height = 480
+
+    def updateMapping(self):
+	self.nodeToItem={}
+	root = self.dom
+	self.updateMappingNode(root)
+    def updateMappingNode(self,node):
+	for c in node.childList():
+	    self.updateMappingNode(c)
+	    try:
+	        self.nodeToItem[c.getAttribute("id")] = c
+	    except:
+	        pass
+    def updateTweenContent(self,obj, typ, source,dest,cur):
+	"""
+	    Update the content of the duplicate scene group. We will use the (start,end) and cur to calculate the percentage of
+	    the tween motion effect and then use it to update the transform matrix of the duplicated scene group.
+	"""
+
+	start = source.idx
+	end = dest.idx
+	print cur,start,end
+	percent = (cur-start)*1.0/(end-start)
+	i = 0
+	s = source.ref.firstChild()
+	d = dest.ref.firstChild()
+	sources={}
+	dests={}
+	
+	# Collect all objects
+	while d:
+	    try:
+		label = d.getAttribute("inkscape:label")
+	    except:
+		d = d.next()
+		continue
+	    dests[label] = d
+	    d = d.next()
+	# Check if the object in the source exists in the destination
+	s = source.ref.firstChild()
+	d = dest.ref.firstChild()
+	while s:
+	    print s,d
+	    try:
+		label = s.getAttribute("inkscape:label")
+		# Use i8nkscape:label to identidy the equipvalent objects
+		if label:
+		    if dests.hasattr(label.value()):
+			self.updateTweenObject(obj,typ,s,dests[label.value()],percent)
+			s = s.next()
+			continue
+	    except:
+		pass
+	    # Search obejcts in the destination
+	    while d:
+		try:
+		    d.getAttribute("inkscape:label")
+		    d = d.next()
+		    continue
+		except:
+		    pass
+		if s.name() == d.name():
+		    self.updateTweenObject(obj,typ,s,d,percent)
+		    d = d.next()
+		    break
+		d = d.next()
+	    s = s.next()
+
+    def parseTransform(self,obj):
+	"""
+	    Return the transform matrix of an object
+	"""
+	try:
+	    t = obj.getAttribute("transform")
+	    print t
+	    if t[0:9] == 'translate':
+		print "translate"
+		fields = t[10:].split(',')
+		x = float(fields[0])
+		fields = fields[1].split(')')
+		y = float(fields[0])
+		return [1,0,0,1,x,y]
+	    elif t[0:6] == 'matrix':
+		print "matrix"
+		fields=t[7:].split(')')
+		fields = fields[0].split(',')
+		return [float(fields[0]),float(fields[1]),float(fields[2]),float(fields[3]),float(fields[4]),float(fields[5])]
+	except:
+	    #traceback.print_exc()
+	    return [1,0,0,1,0,0]
+
+    def invA(self,m):
+        d = m[0]*m[3]-m[2]*m[1]
+	return [m[3]/d, -m[1]/d, -m[2]/d, m[0]/d, (m[1]*m[5]-m[4]*m[3])/d, (m[4]*m[2]-m[0]*m[5])/d]
+	
+    def mulA(self,a,b):
+        return [a[0]*b[0]+a[1]*b[2],
+	        a[0]*b[1]+a[1]*b[3],
+		a[2]*b[0]+a[3]*b[2],
+		a[2]*b[1]+a[3]*b[3],
+		a[0]*b[4]+a[1]*b[5]+a[4],
+		a[2]*b[4]+a[3]*b[5]+a[5]]
+
+    def decomposition(self,m):
+	"""
+	Decompose the affine matrix into production of translation,rotation,shear and scale.
+	The algorithm is documented at http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
+	"""
+        if m[0]*m[3] == m[1]*m[2]:
+	    print "The affine matrix is singular"
+	    return [1,0,0,1,0,0]
+	A=m[0]
+	B=m[2]
+	C=m[1]
+	D=m[3]
+	E=m[4]
+	F=m[5]
+	sx = math.sqrt(A*A+B*B)
+	A = A/sx
+	B = B/sx
+	shear = m[0]*m[1]+m[2]*m[3]
+	C = C - A*shear
+	D = D - B*shear
+	sy = math.sqrt(C*C+D*D)
+	C = C/sy
+	D = D/sy
+	r = A*D-B*C
+	if r == -1:
+	    shear = -shear
+	    sy = -sy
+	R = math.atan2(B,A)
+	return [sx,sy, R, E,F]
+
+	    
+    def updateTweenObject(self,obj,typ,s,d,p):
+	"""
+	    Generate tweened object in the @obj by using s and d in the @p percent
+	    http://lists.w3.org/Archives/Public/www-style/2010Jun/0602.html
+	"""
+	if typ == 'relocate':
+	    newobj = s.duplicate(self.document)
+	    newobj.setAttribute("ref", s.getAttribute("id"))
+	    top = self.document.createElement("svg:g")
+	    top.appendChild(newobj)
+	    obj.appendChild(top)
+	    if s.name() == 'svg:g':
+		# Parse the translate or matrix
+		sm = self.parseTransform(s)
+		dm = self.parseTransform(d)
+		top.setAttribute("transform","translate(%g,%g)" % ((dm[2]-sm[2])*p,(dm[5]-sm[5])*p))
+	    else:
+		try:
+		    sx = float(s.getAttribute("x"))
+		    sy = float(s.getAttribute("y"))
+		    dx = float(d.getAttribute("x"))
+		    dy = float(d.getAttribute("y"))
+		    tx = (dx-sx)*p
+		    ty = (dy-sy)*p
+		    print tx,ty
+		    top.setAttribute("transform","translate(%g,%g)" % (tx,ty))
+		except:
+		    traceback.print_exc()
+		    pass
+	    pass
+	elif typ == 'scale':
+	    self.updateTweenObjectScale(obj,s,d,p)
+	    pass
+	elif typ == 'normal':
+	    newobj = s.duplicate(self.document)
+	    newobj.setAttribute("ref", s.getAttribute("id"))
+	    top = self.document.createElement("svg:g")
+	    top.appendChild(newobj)
+	    obj.appendChild(top)
+	pass
+
+    def updateTweenObjectScale(self,obj,s,d,p):
+        """
+	    Generate a new group which contains the original group and then 
+	    add the transform matrix to generate a tween frame between the 
+	    origin and destination scene group. 
+
+	    We will parse the transform matrix of the @s and @d and then 
+	    generate the matrix which is (1-p) of @s and p percent of @d.
+	"""
+        newobj = s.duplicate(self.document)
+        top = self.document.createElement("svg:g")
+	top.appendChild(newobj)
+	obj.appendChild(top)
+	        
+	if s.name() == 'svg:g':
+	    # Parse the translate or matrix
+	    # 
+	    # D  = B inv(A)
+	    try:
+	        item = self.nodeToItem[s.getAttribute("id")]
+	        (ox,oy) = item.getCenter()
+	    except:
+	        ox = 0
+   	        oy = 0
+	    try:
+	        item = self.nodeToItem[d.getAttribute("id")]
+	        (dx,dy) = item.getCenter()
+	    except:
+	        dx = 0
+	        dy = 0
+		    
+	    sm = self.parseTransform(s)
+	    ss = self.decomposition(sm)
+	    dm = self.parseTransform(d)
+	    dd = self.decomposition(dm)
+	    sx = (ss[0]*(1-p)+dd[0]*p)/ss[0]
+	    sy = (ss[1]*(1-p)+dd[1]*p)/ss[0]
+	    a  = ss[2]*(1-p)+dd[2]*p-ss[2]
+	    tx = ox*(1-p)+dx*p-ox
+	    ty = oy*(1-p)+dy*p-oy
+	    m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0]
+	    m = self.mulA([sx,0,0,sy,0,0],m)
+	    m = self.mulA(m,[1,0,0,1,-ox,oy-self.height])
+	    m = self.mulA([1,0,0,1,tx,self.height-ty],m)
+
+	    top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5]))
+        else:
+	    try:
+	        sw = float(s.getAttribute("width"))
+  	        sh = float(s.getAttribute("height"))
+		dw = float(d.getAttribute("width"))
+		dh = float(d.getAttribute("height"))
+	        try:
+	            item = self.nodeToItem[s.getAttribute("id")]
+		    (ox,oy) = item.getCenter()
+	        except:
+		    ox = 0
+		    oy = 0
+	        try:
+	            item = self.nodeToItem[d.getAttribute("id")]
+		    (dx,dy) = item.getCenter()
+	        except:
+		    dx = 0
+		    dy = 0
+		try:
+		    sm = self.parseTransform(s)
+		    ss = self.decomposition(sm)
+		except:
+		    ss = [1,1,0,0,0]
+		    pass
+		try:
+		    dm = self.parseTransform(d)
+		    dd = self.decomposition(dm)
+		except:
+		    dd = [1,1,0,0,0]
+		dd[0] = ss[0]*dw/sw
+		dd[1] = ss[1]*dh/sh
+		sx = (ss[0]*(1-p)+dd[0]*p)/ss[0]
+		sy = (ss[1]*(1-p)+dd[1]*p)/ss[1]
+		a  = ss[2]*(1-p)+dd[2]*p-ss[2]
+		tx = ox*(1-p)+dx*p
+		ty = oy*(1-p)+dy*p
+		m = [math.cos(a),math.sin(a),-math.sin(a),math.cos(a),0,0]
+		m = self.mulA([sx,0,0,sy,0,0],m)
+		m = self.mulA(m,[1,0,0,1,-ox,oy-self.height])
+		m = self.mulA([1,0,0,1,tx,self.height-ty],m)
+
+		top.setAttribute("transform","matrix(%g,%g,%g,%g,%g,%g)" % (m[0],m[2],m[1],m[3],m[4],m[5]))
+	    except:
+	        traceback.print_exc()