~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to share/extensions/pathmodifier.py

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
'''
3
 
Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
4
 
 
5
 
This program is free software; you can redistribute it and/or modify
6
 
it under the terms of the GNU General Public License as published by
7
 
the Free Software Foundation; either version 2 of the License, or
8
 
(at your option) any later version.
9
 
 
10
 
This program is distributed in the hope that it will be useful,
11
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
GNU General Public License for more details.
14
 
 
15
 
You should have received a copy of the GNU General Public License
16
 
along with this program; if not, write to the Free Software
17
 
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
barraud@math.univ-lille1.fr
19
 
 
20
 
This code defines a basic class (PathModifier) of effects whose purpose is
21
 
to somehow deform given objects: one common tasks for all such effect is to
22
 
convert shapes, groups, clones to paths. The class has several functions to
23
 
make this (more or less!) easy.
24
 
As an exemple, a second class (Diffeo) is derived from it,
25
 
to implement deformations of the form X=f(x,y), Y=g(x,y)...
26
 
 
27
 
TODO: Several handy functions are defined, that might in fact be of general
28
 
interest and that should be shipped out in separate files...
29
 
'''
30
 
import inkex, cubicsuperpath, bezmisc, simplestyle
31
 
from simpletransform import *
32
 
import copy, math, re, random
33
 
 
34
 
####################################################################
35
 
##-- zOrder computation...
36
 
##-- this should be shipped out in a separate file. inkex.py?
37
 
 
38
 
def zSort(inNode,idList):
39
 
    sortedList=[]
40
 
    theid = inNode.get("id")
41
 
    if theid in idList:
42
 
        sortedList.append(theid)
43
 
    for child in inNode:
44
 
        if len(sortedList)==len(idList):
45
 
            break
46
 
        sortedList+=zSort(child,idList)
47
 
    return sortedList
48
 
 
49
 
 
50
 
class PathModifier(inkex.Effect):
51
 
    def __init__(self):
52
 
        inkex.Effect.__init__(self)
53
 
 
54
 
##################################
55
 
#-- Selectionlists manipulation --
56
 
##################################
57
 
 
58
 
    def duplicateNodes(self, aList):
59
 
        clones={}
60
 
        for id,node in aList.iteritems():
61
 
            clone=copy.deepcopy(node)
62
 
            #!!!--> should it be given an id?
63
 
            #seems to work without this!?!
64
 
            myid = node.tag.split('}')[-1]
65
 
            clone.set("id", self.uniqueId(myid))
66
 
            node.getparent().append(clone)
67
 
            clones[clone.get("id")]=clone
68
 
        return(clones)
69
 
 
70
 
    def uniqueId(self, prefix):
71
 
        id="%s%04i"%(prefix,random.randint(0,9999))
72
 
        while len(self.document.getroot().xpath('//*[@id="%s"]' % id,namespaces=inkex.NSS)):
73
 
            id="%s%04i"%(prefix,random.randint(0,9999))
74
 
        return(id)
75
 
 
76
 
    def expandGroups(self,aList,transferTransform=True):
77
 
        for id, node in aList.items():      
78
 
            if node.tag == inkex.addNS('g','svg') or node.tag=='g':
79
 
                mat=parseTransform(node.get("transform"))
80
 
                for child in node:
81
 
                    if transferTransform:
82
 
                        applyTransformToNode(mat,child)
83
 
                    aList.update(self.expandGroups({child.get('id'):child}))
84
 
                if transferTransform and node.get("transform"):
85
 
                    del node.attrib["transform"]
86
 
                del aList[id]
87
 
        return(aList)
88
 
 
89
 
    def expandGroupsUnlinkClones(self,aList,transferTransform=True,doReplace=True):
90
 
        for id in aList.keys()[:]:     
91
 
            node=aList[id]
92
 
            if node.tag == inkex.addNS('g','svg') or node.tag=='g':
93
 
                self.expandGroups(aList,transferTransform)
94
 
                self.expandGroupsUnlinkClones(aList,transferTransform,doReplace)
95
 
                #Hum... not very efficient if there are many clones of groups...
96
 
 
97
 
            elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
98
 
                refnode=self.refNode(node)
99
 
                newnode=self.unlinkClone(node,doReplace)
100
 
                del aList[id]
101
 
 
102
 
                style = simplestyle.parseStyle(node.get('style') or "")
103
 
                refstyle=simplestyle.parseStyle(refnode.get('style') or "")
104
 
                style.update(refstyle)
105
 
                newnode.set('style',simplestyle.formatStyle(style))
106
 
 
107
 
                newid=newnode.get('id')
108
 
                aList.update(self.expandGroupsUnlinkClones({newid:newnode},transferTransform,doReplace))
109
 
        return aList
110
 
    
111
 
    def recursNewIds(self,node):
112
 
        if node.get('id'):
113
 
            node.set('id',self.uniqueId(node.tag))
114
 
        for child in node:
115
 
            self.recursNewIds(child)
116
 
            
117
 
    def refNode(self,node):
118
 
        if node.get(inkex.addNS('href','xlink')):
119
 
            refid=node.get(inkex.addNS('href','xlink'))
120
 
            path = '//*[@id="%s"]' % refid[1:]
121
 
            newNode = self.document.getroot().xpath(path, namespaces=inkex.NSS)[0]
122
 
            return newNode
123
 
        else:
124
 
            raise AssertionError, "Trying to follow empty xlink.href attribute."
125
 
 
126
 
    def unlinkClone(self,node,doReplace):
127
 
        if node.tag == inkex.addNS('use','svg') or node.tag=='use':
128
 
            newNode = copy.deepcopy(self.refNode(node))
129
 
            self.recursNewIds(newNode)
130
 
            applyTransformToNode(parseTransform(node.get('transform')),newNode)
131
 
 
132
 
            if doReplace:
133
 
                parent=node.getparent()
134
 
                parent.insert(parent.index(node),newNode)
135
 
                parent.remove(node)
136
 
 
137
 
            return newNode
138
 
        else:
139
 
            raise AssertionError, "Only clones can be unlinked..."
140
 
 
141
 
 
142
 
 
143
 
################################
144
 
#-- Object conversion ----------
145
 
################################
146
 
 
147
 
    def rectToPath(self,node,doReplace=True):
148
 
        if node.tag == inkex.addNS('rect','svg'):
149
 
            x =float(node.get('x'))
150
 
            y =float(node.get('y'))
151
 
            #FIXME: no exception anymore and sometimes just one
152
 
            try:
153
 
                rx=float(node.get('rx'))
154
 
                ry=float(node.get('ry'))
155
 
            except:
156
 
                rx=0
157
 
                ry=0
158
 
            w =float(node.get('width' ))
159
 
            h =float(node.get('height'))
160
 
            d ='M %f,%f '%(x+rx,y)
161
 
            d+='L %f,%f '%(x+w-rx,y)
162
 
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w,y+ry)
163
 
            d+='L %f,%f '%(x+w,y+h-ry)
164
 
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w-rx,y+h)
165
 
            d+='L %f,%f '%(x+rx,y+h)
166
 
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x,y+h-ry)
167
 
            d+='L %f,%f '%(x,y+ry)
168
 
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+rx,y)
169
 
 
170
 
            newnode=inkex.etree.Element('path')
171
 
            newnode.set('d',d)
172
 
            newnode.set('id', self.uniqueId('path'))
173
 
            newnode.set('style',node.get('style'))
174
 
            nnt = node.get('transform')
175
 
            if nnt:
176
 
                newnode.set('transform',nnt)
177
 
                fuseTransform(newnode)
178
 
            if doReplace:
179
 
                parent=node.getparent()
180
 
                parent.insert(parent.index(node),newnode)
181
 
                parent.remove(node)
182
 
            return newnode
183
 
 
184
 
    def groupToPath(self,node,doReplace=True):
185
 
        if node.tag == inkex.addNS('g','svg'):
186
 
            newNode = inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg'))    
187
 
 
188
 
            newstyle = simplestyle.parseStyle(node.get('style') or "")
189
 
            newp = []
190
 
            for child in node:
191
 
                childstyle = simplestyle.parseStyle(child.get('style') or "")
192
 
                childstyle.update(newstyle)
193
 
                newstyle.update(childstyle)
194
 
                childAsPath = self.objectToPath(child,False)
195
 
                newp += cubicsuperpath.parsePath(childAsPath.get('d'))
196
 
            newNode.set('d',cubicsuperpath.formatPath(newp))
197
 
            newNode.set('style',simplestyle.formatStyle(newstyle))
198
 
 
199
 
            self.current_layer.remove(newNode)
200
 
            if doReplace:
201
 
                parent=node.getparent()
202
 
                parent.insert(parent.index(node),newNode)
203
 
                parent.remove(node)
204
 
 
205
 
            return newNode
206
 
        else:
207
 
            raise AssertionError
208
 
        
209
 
    def objectToPath(self,node,doReplace=True):
210
 
        #--TODO: support other object types!!!!
211
 
        #--TODO: make sure cubicsuperpath supports A and Q commands... 
212
 
        if node.tag == inkex.addNS('rect','svg'):
213
 
            return(self.rectToPath(node,doReplace))
214
 
        if node.tag == inkex.addNS('g','svg'):
215
 
            return(self.groupToPath(node,doReplace))
216
 
        elif node.tag == inkex.addNS('path','svg') or node.tag == 'path':
217
 
            #remove inkscape attributes, otherwise any modif of 'd' will be discarded!
218
 
            for attName in node.attrib.keys():
219
 
                if ("sodipodi" in attName) or ("inkscape" in attName):
220
 
                    del node.attrib[attName]
221
 
            fuseTransform(node)
222
 
            return node
223
 
        elif node.tag == inkex.addNS('use','svg') or node.tag == 'use':
224
 
            newNode = self.unlinkClone(node,doReplace)
225
 
            return self.objectToPath(newNode,doReplace)
226
 
        else:
227
 
            inkex.debug("Please first convert objects to paths!...(got '%s')"%node.tag)
228
 
            return None
229
 
 
230
 
    def objectsToPaths(self,aList,doReplace=True):
231
 
        newSelection={}
232
 
        for id,node in aList.items():
233
 
            newnode=self.objectToPath(node,doReplace)
234
 
            del aList[id]
235
 
            aList[newnode.get('id')]=newnode
236
 
 
237
 
 
238
 
################################
239
 
#-- Action ----------
240
 
################################
241
 
        
242
 
    #-- overwrite this method in subclasses...
243
 
    def effect(self):
244
 
        #self.duplicateNodes(self.selected)
245
 
        #self.expandGroupsUnlinkClones(self.selected, True)
246
 
        self.objectsToPaths(self.selected, True)
247
 
        self.bbox=computeBBox(self.selected.values())
248
 
        for id, node in self.selected.iteritems():
249
 
            if node.tag == inkex.addNS('path','svg'):
250
 
                d = node.get('d')
251
 
                p = cubicsuperpath.parsePath(d)
252
 
 
253
 
                #do what ever you want with p!
254
 
 
255
 
                node.set('d',cubicsuperpath.formatPath(p))
256
 
 
257
 
 
258
 
class Diffeo(PathModifier):
259
 
    def __init__(self):
260
 
        inkex.Effect.__init__(self)
261
 
 
262
 
    def applyDiffeo(self,bpt,vects=()):
263
 
        '''
264
 
        bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. 
265
 
        Defaults to identity!
266
 
        '''
267
 
        for v in vects:
268
 
            v[0]-=bpt[0]
269
 
            v[1]-=bpt[1]
270
 
 
271
 
        #-- your transformations go here:
272
 
        #x,y=bpt
273
 
        #bpt[0]=f(x,y)
274
 
        #bpt[1]=g(x,y)
275
 
        #for v in vects:
276
 
        #    vx,vy=v
277
 
        #    v[0]=df/dx(x,y)*vx+df/dy(x,y)*vy
278
 
        #    v[1]=dg/dx(x,y)*vx+dg/dy(x,y)*vy
279
 
        #
280
 
        #-- !caution! y-axis is pointing downward!
281
 
 
282
 
        for v in vects:
283
 
            v[0]+=bpt[0]
284
 
            v[1]+=bpt[1]
285
 
 
286
 
 
287
 
    def effect(self):
288
 
        #self.duplicateNodes(self.selected)
289
 
        self.expandGroupsUnlinkClones(self.selected, True)
290
 
        self.expandGroups(self.selected, True)
291
 
        self.objectsToPaths(self.selected, True)
292
 
        self.bbox=computeBBox(self.selected.values())
293
 
        for id, node in self.selected.iteritems():
294
 
            if node.tag == inkex.addNS('path','svg') or node.tag=='path':
295
 
                d = node.get('d')
296
 
                p = cubicsuperpath.parsePath(d)
297
 
 
298
 
                for sub in p:
299
 
                    for ctlpt in sub:
300
 
                        self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2]))
301
 
 
302
 
                node.set('d',cubicsuperpath.formatPath(p))
303
 
 
304
 
#e = Diffeo()
305
 
#e.affect()
306
 
 
307
 
    
 
1
#!/usr/bin/env python
 
2
'''
 
3
Copyright (C) 2006 Jean-Francois Barraud, barraud@math.univ-lille1.fr
 
4
 
 
5
This program is free software; you can redistribute it and/or modify
 
6
it under the terms of the GNU General Public License as published by
 
7
the Free Software Foundation; either version 2 of the License, or
 
8
(at your option) any later version.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
barraud@math.univ-lille1.fr
 
19
 
 
20
This code defines a basic class (PathModifier) of effects whose purpose is
 
21
to somehow deform given objects: one common tasks for all such effect is to
 
22
convert shapes, groups, clones to paths. The class has several functions to
 
23
make this (more or less!) easy.
 
24
As an exemple, a second class (Diffeo) is derived from it,
 
25
to implement deformations of the form X=f(x,y), Y=g(x,y)...
 
26
 
 
27
TODO: Several handy functions are defined, that might in fact be of general
 
28
interest and that should be shipped out in separate files...
 
29
'''
 
30
import inkex, cubicsuperpath, bezmisc, simplestyle
 
31
from simpletransform import *
 
32
import copy, math, re, random
 
33
import gettext
 
34
_ = gettext.gettext
 
35
 
 
36
####################################################################
 
37
##-- zOrder computation...
 
38
##-- this should be shipped out in a separate file. inkex.py?
 
39
 
 
40
def zSort(inNode,idList):
 
41
    sortedList=[]
 
42
    theid = inNode.get("id")
 
43
    if theid in idList:
 
44
        sortedList.append(theid)
 
45
    for child in inNode:
 
46
        if len(sortedList)==len(idList):
 
47
            break
 
48
        sortedList+=zSort(child,idList)
 
49
    return sortedList
 
50
 
 
51
 
 
52
class PathModifier(inkex.Effect):
 
53
    def __init__(self):
 
54
        inkex.Effect.__init__(self)
 
55
 
 
56
##################################
 
57
#-- Selectionlists manipulation --
 
58
##################################
 
59
 
 
60
    def duplicateNodes(self, aList):
 
61
        clones={}
 
62
        for id,node in aList.iteritems():
 
63
            clone=copy.deepcopy(node)
 
64
            #!!!--> should it be given an id?
 
65
            #seems to work without this!?!
 
66
            myid = node.tag.split('}')[-1]
 
67
            clone.set("id", self.uniqueId(myid))
 
68
            node.getparent().append(clone)
 
69
            clones[clone.get("id")]=clone
 
70
        return(clones)
 
71
 
 
72
    def uniqueId(self, prefix):
 
73
        id="%s%04i"%(prefix,random.randint(0,9999))
 
74
        while len(self.document.getroot().xpath('//*[@id="%s"]' % id,namespaces=inkex.NSS)):
 
75
            id="%s%04i"%(prefix,random.randint(0,9999))
 
76
        return(id)
 
77
 
 
78
    def expandGroups(self,aList,transferTransform=True):
 
79
        for id, node in aList.items():      
 
80
            if node.tag == inkex.addNS('g','svg') or node.tag=='g':
 
81
                mat=parseTransform(node.get("transform"))
 
82
                for child in node:
 
83
                    if transferTransform:
 
84
                        applyTransformToNode(mat,child)
 
85
                    aList.update(self.expandGroups({child.get('id'):child}))
 
86
                if transferTransform and node.get("transform"):
 
87
                    del node.attrib["transform"]
 
88
                del aList[id]
 
89
        return(aList)
 
90
 
 
91
    def expandGroupsUnlinkClones(self,aList,transferTransform=True,doReplace=True):
 
92
        for id in aList.keys()[:]:     
 
93
            node=aList[id]
 
94
            if node.tag == inkex.addNS('g','svg') or node.tag=='g':
 
95
                self.expandGroups(aList,transferTransform)
 
96
                self.expandGroupsUnlinkClones(aList,transferTransform,doReplace)
 
97
                #Hum... not very efficient if there are many clones of groups...
 
98
 
 
99
            elif node.tag == inkex.addNS('use','svg') or node.tag=='use':
 
100
                refnode=self.refNode(node)
 
101
                newnode=self.unlinkClone(node,doReplace)
 
102
                del aList[id]
 
103
 
 
104
                style = simplestyle.parseStyle(node.get('style') or "")
 
105
                refstyle=simplestyle.parseStyle(refnode.get('style') or "")
 
106
                style.update(refstyle)
 
107
                newnode.set('style',simplestyle.formatStyle(style))
 
108
 
 
109
                newid=newnode.get('id')
 
110
                aList.update(self.expandGroupsUnlinkClones({newid:newnode},transferTransform,doReplace))
 
111
        return aList
 
112
    
 
113
    def recursNewIds(self,node):
 
114
        if node.get('id'):
 
115
            node.set('id',self.uniqueId(node.tag))
 
116
        for child in node:
 
117
            self.recursNewIds(child)
 
118
            
 
119
    def refNode(self,node):
 
120
        if node.get(inkex.addNS('href','xlink')):
 
121
            refid=node.get(inkex.addNS('href','xlink'))
 
122
            path = '//*[@id="%s"]' % refid[1:]
 
123
            newNode = self.document.getroot().xpath(path, namespaces=inkex.NSS)[0]
 
124
            return newNode
 
125
        else:
 
126
            raise AssertionError, "Trying to follow empty xlink.href attribute."
 
127
 
 
128
    def unlinkClone(self,node,doReplace):
 
129
        if node.tag == inkex.addNS('use','svg') or node.tag=='use':
 
130
            newNode = copy.deepcopy(self.refNode(node))
 
131
            self.recursNewIds(newNode)
 
132
            applyTransformToNode(parseTransform(node.get('transform')),newNode)
 
133
 
 
134
            if doReplace:
 
135
                parent=node.getparent()
 
136
                parent.insert(parent.index(node),newNode)
 
137
                parent.remove(node)
 
138
 
 
139
            return newNode
 
140
        else:
 
141
            raise AssertionError, "Only clones can be unlinked..."
 
142
 
 
143
 
 
144
 
 
145
################################
 
146
#-- Object conversion ----------
 
147
################################
 
148
 
 
149
    def rectToPath(self,node,doReplace=True):
 
150
        if node.tag == inkex.addNS('rect','svg'):
 
151
            x =float(node.get('x'))
 
152
            y =float(node.get('y'))
 
153
            #FIXME: no exception anymore and sometimes just one
 
154
            try:
 
155
                rx=float(node.get('rx'))
 
156
                ry=float(node.get('ry'))
 
157
            except:
 
158
                rx=0
 
159
                ry=0
 
160
            w =float(node.get('width' ))
 
161
            h =float(node.get('height'))
 
162
            d ='M %f,%f '%(x+rx,y)
 
163
            d+='L %f,%f '%(x+w-rx,y)
 
164
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w,y+ry)
 
165
            d+='L %f,%f '%(x+w,y+h-ry)
 
166
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+w-rx,y+h)
 
167
            d+='L %f,%f '%(x+rx,y+h)
 
168
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x,y+h-ry)
 
169
            d+='L %f,%f '%(x,y+ry)
 
170
            d+='A %f,%f,%i,%i,%i,%f,%f '%(rx,ry,0,0,1,x+rx,y)
 
171
 
 
172
            newnode=inkex.etree.Element('path')
 
173
            newnode.set('d',d)
 
174
            newnode.set('id', self.uniqueId('path'))
 
175
            newnode.set('style',node.get('style'))
 
176
            nnt = node.get('transform')
 
177
            if nnt:
 
178
                newnode.set('transform',nnt)
 
179
                fuseTransform(newnode)
 
180
            if doReplace:
 
181
                parent=node.getparent()
 
182
                parent.insert(parent.index(node),newnode)
 
183
                parent.remove(node)
 
184
            return newnode
 
185
 
 
186
    def groupToPath(self,node,doReplace=True):
 
187
        if node.tag == inkex.addNS('g','svg'):
 
188
            newNode = inkex.etree.SubElement(self.current_layer,inkex.addNS('path','svg'))    
 
189
 
 
190
            newstyle = simplestyle.parseStyle(node.get('style') or "")
 
191
            newp = []
 
192
            for child in node:
 
193
                childstyle = simplestyle.parseStyle(child.get('style') or "")
 
194
                childstyle.update(newstyle)
 
195
                newstyle.update(childstyle)
 
196
                childAsPath = self.objectToPath(child,False)
 
197
                newp += cubicsuperpath.parsePath(childAsPath.get('d'))
 
198
            newNode.set('d',cubicsuperpath.formatPath(newp))
 
199
            newNode.set('style',simplestyle.formatStyle(newstyle))
 
200
 
 
201
            self.current_layer.remove(newNode)
 
202
            if doReplace:
 
203
                parent=node.getparent()
 
204
                parent.insert(parent.index(node),newNode)
 
205
                parent.remove(node)
 
206
 
 
207
            return newNode
 
208
        else:
 
209
            raise AssertionError
 
210
        
 
211
    def objectToPath(self,node,doReplace=True):
 
212
        #--TODO: support other object types!!!!
 
213
        #--TODO: make sure cubicsuperpath supports A and Q commands... 
 
214
        if node.tag == inkex.addNS('rect','svg'):
 
215
            return(self.rectToPath(node,doReplace))
 
216
        if node.tag == inkex.addNS('g','svg'):
 
217
            return(self.groupToPath(node,doReplace))
 
218
        elif node.tag == inkex.addNS('path','svg') or node.tag == 'path':
 
219
            #remove inkscape attributes, otherwise any modif of 'd' will be discarded!
 
220
            for attName in node.attrib.keys():
 
221
                if ("sodipodi" in attName) or ("inkscape" in attName):
 
222
                    del node.attrib[attName]
 
223
            fuseTransform(node)
 
224
            return node
 
225
        elif node.tag == inkex.addNS('use','svg') or node.tag == 'use':
 
226
            newNode = self.unlinkClone(node,doReplace)
 
227
            return self.objectToPath(newNode,doReplace)
 
228
        else:
 
229
            inkex.errormsg(_("Please first convert objects to paths!  (Got [%s].)") % node.tag)
 
230
            return None
 
231
 
 
232
    def objectsToPaths(self,aList,doReplace=True):
 
233
        newSelection={}
 
234
        for id,node in aList.items():
 
235
            newnode=self.objectToPath(node,doReplace)
 
236
            del aList[id]
 
237
            aList[newnode.get('id')]=newnode
 
238
 
 
239
 
 
240
################################
 
241
#-- Action ----------
 
242
################################
 
243
        
 
244
    #-- overwrite this method in subclasses...
 
245
    def effect(self):
 
246
        #self.duplicateNodes(self.selected)
 
247
        #self.expandGroupsUnlinkClones(self.selected, True)
 
248
        self.objectsToPaths(self.selected, True)
 
249
        self.bbox=computeBBox(self.selected.values())
 
250
        for id, node in self.selected.iteritems():
 
251
            if node.tag == inkex.addNS('path','svg'):
 
252
                d = node.get('d')
 
253
                p = cubicsuperpath.parsePath(d)
 
254
 
 
255
                #do what ever you want with p!
 
256
 
 
257
                node.set('d',cubicsuperpath.formatPath(p))
 
258
 
 
259
 
 
260
class Diffeo(PathModifier):
 
261
    def __init__(self):
 
262
        inkex.Effect.__init__(self)
 
263
 
 
264
    def applyDiffeo(self,bpt,vects=()):
 
265
        '''
 
266
        bpt is a base point and for v in vectors, v'=v-p is a tangent vector at bpt. 
 
267
        Defaults to identity!
 
268
        '''
 
269
        for v in vects:
 
270
            v[0]-=bpt[0]
 
271
            v[1]-=bpt[1]
 
272
 
 
273
        #-- your transformations go here:
 
274
        #x,y=bpt
 
275
        #bpt[0]=f(x,y)
 
276
        #bpt[1]=g(x,y)
 
277
        #for v in vects:
 
278
        #    vx,vy=v
 
279
        #    v[0]=df/dx(x,y)*vx+df/dy(x,y)*vy
 
280
        #    v[1]=dg/dx(x,y)*vx+dg/dy(x,y)*vy
 
281
        #
 
282
        #-- !caution! y-axis is pointing downward!
 
283
 
 
284
        for v in vects:
 
285
            v[0]+=bpt[0]
 
286
            v[1]+=bpt[1]
 
287
 
 
288
 
 
289
    def effect(self):
 
290
        #self.duplicateNodes(self.selected)
 
291
        self.expandGroupsUnlinkClones(self.selected, True)
 
292
        self.expandGroups(self.selected, True)
 
293
        self.objectsToPaths(self.selected, True)
 
294
        self.bbox=computeBBox(self.selected.values())
 
295
        for id, node in self.selected.iteritems():
 
296
            if node.tag == inkex.addNS('path','svg') or node.tag=='path':
 
297
                d = node.get('d')
 
298
                p = cubicsuperpath.parsePath(d)
 
299
 
 
300
                for sub in p:
 
301
                    for ctlpt in sub:
 
302
                        self.applyDiffeo(ctlpt[1],(ctlpt[0],ctlpt[2]))
 
303
 
 
304
                node.set('d',cubicsuperpath.formatPath(p))
 
305
 
 
306
#e = Diffeo()
 
307
#e.affect()
 
308
 
 
309
    
 
310
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99