98c6a489b0c6c0b81dc84ed15ccede61a24ef052
[blender.git] / release / scripts / bpymodules / svg2obj.py
1 """
2 SVG 2 OBJ translater, 0.3.3
3 (c) jm soler juillet/novembre 2004-juin 2005, 
4 #   released under Blender Artistic Licence 
5     for the Blender 2.37/36/35/34/33 Python Scripts Bundle.
6 #---------------------------------------------------------------------------
7 # Page officielle :
8 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
9 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg_en.htm
10 # Communiquer les problemes et erreurs sur:
11 #   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
12 #---------------------------------------------------------------------------
13
14 -- Concept : translate SVG file in GEO .obj file and try to load it. 
15 -- Curiousity : the original matrix must be :
16
17                          0.0 0.0 1.0 0.0
18                          0.0 1.0 0.0 0.0
19                          0.0 0.0 1.0 0.0
20                          0.0 0.0 0.0 1.0 
21
22                   and not:
23                          1.0 0.0 0.0 0.0
24                          0.0 1.0 0.0 0.0
25                          0.0 0.0 1.0 0.0
26                          0.0 0.0 0.0 1.0 
27
28 -- Options :
29     SHARP_IMPORT = 0 
30             choise between "As is", "Devide by height" and "Devide by width"
31     SHARP_IMPORT = 1
32             no choise
33
34 -- Possible bug : sometime, the new curves object's RotY value 
35                   jumps to -90.0 degrees without any reason.
36
37 Yet done: 
38    M : absolute move to 
39    Z : close path
40    L : absolute line to  
41    C : absolute curve to
42    S : absolute curve to with only one handle
43    l : relative line to     2004/08/03
44    c : relative curve to    2004/08/03
45    s : relative curve to with only one handle  
46
47
48    A : courbe_vers_a, 
49    V : ligne_tracee_v,
50    H : ligne_tracee_h, 
51    Z : boucle_z,
52    Q : courbe_vers_q,
53    T : courbe_vers_t,
54    a : courbe_vers_a, 
55    v : ligne_tracee_v,
56    h : ligne_tracee_h, 
57    z : boucle_z,
58    q : courbe_vers_q,
59
60    transfrom for <g> tag 
61    transform for <path> tag
62
63 Changelog:
64       0.1.1 : - control file without extension
65       0.2.0 : - improved reading of several data of the same type 
66                 following the same command (for gimp import)
67       0.2.1 : - better choice for viewboxing ( takes the viewbox if found, 
68                 instead of x,y,width and height              
69       0.2.2 : - read compact path data from Illustrator 10             
70       0.2.3 : - read a few new relative displacements
71       0.2.4 : - better hash for command followed by a lone data 
72                 (h,v) or uncommun number (a) 
73       0.2.5 : - correction for gimp import 
74       0.2.6 : - correction for illustrator 10 SVG
75       0.2.7 : - correction for inskape 0.40 cvs  SVG
76       0.2.8 : - correction for inskape plain SVG
77       0.3   : - reading of the transform properties added : 
78                     translate
79       0.3.1 : - compatibility restored with gimp 
80       0.3.2 : - transform properties added (june, 15-16): 
81                     scale, 
82                     rotate, 
83                     matrix, 
84                     skew               
85               - added a test on __name__ to load the script
86                 outside from the blender menu  
87       0.3.3 : - controle du contenu des transformation de type matrix 
88       0.3.4 : - restructuration de la lecture des donnes paths (19/06/05) 
89 ==================================================================================   
90 =================================================================================="""
91
92 SHARP_IMPORT=0
93 SCALE=1
94 scale=1
95 DEBUG =0 #print
96 DEVELOPPEMENT=0
97     
98 import sys
99 from math import cos,sin,tan
100 import Blender
101 from Blender import Mathutils
102 BLversion=Blender.Get('version')
103
104 try:
105     import nt
106     os=nt
107     os.sep='\\'
108
109 except:    
110     import posix
111     os=posix
112     os.sep='/'
113     
114 def isdir(path):
115     try:
116         st = os.stat(path)
117         return 1 
118     except:
119         return 0
120     
121 def split(pathname):
122          if pathname.find(os.sep)!=-1:
123              k0=pathname.split(os.sep)
124          else:
125             if os.sep=='/':
126                 k0=pathname.split('\\')
127             else:
128                 k0=pathname.split('/') 
129
130          directory=pathname.replace(k0[len(k0)-1],'')
131          Name=k0[len(k0)-1]
132          return directory, Name
133         
134 def join(l0,l1):        
135      return  l0+os.sep+l1
136     
137 os.isdir=isdir
138 os.split=split
139 os.join=join
140
141 def filtreFICHIER(nom):
142      f=open(nom,'rU')
143      t=f.read()
144      f.close()
145      
146      t=t.replace('\r','')
147      t=t.replace('\n','')
148      
149      if t.upper().find('<SVG')==-1 :
150          name = "ERROR: invalid or empty file ... "  # if no %xN int is set, indices start from 1
151          result = Blender.Draw.PupMenu(name)
152          return "false"
153      elif  t.upper().find('<PATH')==-1:
154          name = "ERROR: there's no Path in this file ... "  # if no %xN int is set, indices start from 1
155          result = Blender.Draw.PupMenu(name)
156          return "false"
157      else:
158           return t
159
160 #===============================
161 # Data
162 #===============================
163 #===============================
164 # Blender Curve Data
165 #===============================
166 objBEZIER=0
167 objSURFACE=5
168 typBEZIER3D=1  #3D
169 typBEZIER2D=9  #2D
170
171 class Bez:
172       def __init__(self):
173            self.co=[]
174            self.ha=[0,0]
175            
176 class ITEM:
177       def __init__(self):
178                self.type        =  typBEZIER3D,        
179                self.pntsUV      =  [0,0]              
180                self.resolUV     =  [32,0]            
181                self.orderUV     =  [0,0]             
182                self.flagUV      =  [0,0]              
183                self.Origine     =  [0.0,0.0]
184                self.beziers_knot = []
185
186 class COURBE:
187       def __init__(self):
188               self.magic_number='3DG3'              
189               self.type            =  objBEZIER        
190               self.number_of_items =  0              
191               self.ext1_ext2       =  [0,0]             
192               self.matrix          =  """0.0 0.0 1.0 0.0
193 0.0 1.0 0.0 0.0
194 0.0 0.0 1.0 0.0
195 0.0 0.0 0.0 1.0 """ 
196               self.ITEM = {}
197
198
199 courbes=COURBE()
200 PATTERN={}
201 BOUNDINGBOX={'rec':[],'coef':1.0}
202 npat=0
203 #=====================================================================
204 #======== name of the curve in the curves dictionnary ===============
205 #=====================================================================
206 n0=0
207
208 #=====================================================================
209 #====================== current Point ================================
210 #=====================================================================
211 CP=[0.0,0.0] #currentPoint
212
213 #=====================================================================
214 #===== to compare last position to the original move to displacement =
215 #=====  needed for cyclic definition inAI, EPS forma  ================
216 #=====================================================================
217 def test_egalitedespositions(f1,f2):
218     if f1[0]==f2[0] and f1[1]==f2[1]:
219        return Blender.TRUE
220     else:
221        return Blender.FALSE
222
223
224 def Open_GEOfile(dir,nom):
225     global SCALE,BOUNDINGBOX, scale
226     if BLversion>=233:
227        Blender.Load(dir+nom+'OOO.obj', 1)
228        BO=Blender.Object.Get()
229
230        BO[-1].RotY=3.1416
231        BO[-1].RotZ=3.1416
232        BO[-1].RotX=3.1416/2.0
233        
234        if scale==1:
235           BO[-1].LocY+=BOUNDINGBOX['rec'][3]
236        else:
237          BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
238  
239        BO[-1].makeDisplayList() 
240        Blender.Window.RedrawAll()
241     else:
242        print "Not yet implemented"
243
244 def create_GEOtext(courbes):
245     global SCALE, B, BOUNDINGBOX,scale
246     r=BOUNDINGBOX['rec']
247
248     if scale==1:
249        SCALE=1.0
250     elif scale==2:
251        SCALE=r[2]-r[0]
252     elif scale==3:
253        SCALE=r[3]-r[1]
254  
255     t=[]
256     t.append(courbes.magic_number+'\n')
257     t.append(str(courbes.type)+'\n')
258     t.append(str(courbes.number_of_items)+'\n')
259     t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
260     t.append(courbes.matrix+'\n')
261     
262     for k in courbes.ITEM.keys():
263         t.append("%s\n"%courbes.ITEM[k].type)
264         t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
265         t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
266         t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
267         t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
268
269         flag =0#courbes.ITEM[k].flagUV[0]
270
271         for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
272            #k1 =courbes.ITEM[k].beziers_knot[k2]
273            k1=ajustement(courbes.ITEM[k].beziers_knot[k2], SCALE)
274            
275            t.append("%4f 0.0 %4f \n"%(k1[4],k1[5]))
276            t.append("%4f 0.0 %4f \n"%(k1[0],k1[1]))
277            t.append("%4f 0.0 %4f \n"%(k1[2],k1[3]))
278            t.append(str(courbes.ITEM[k].beziers_knot[k2].ha[0])+' '+str(courbes.ITEM[k].beziers_knot[k2].ha[1])+'\n')
279
280     return t
281
282 def save_GEOfile(dir,nom,t):
283      f=open(dir+nom+'OOO.obj','w')
284      f.writelines(t)
285      f.close()
286
287
288 def filtre_DATA(c,D,n):
289     global DEBUG,TAGcourbe
290     #print 'c',c,'D',D,'n',n
291     l=[] 
292     if len(c[0])==1 and D[c[1]+1].find(',')!=-1:
293         for n2 in range(1,n+1): 
294            ld=D[c[1]+n2].split(',')
295            for l_ in ld: 
296                l.append(l_)
297                
298     elif len(c[0])==1 and D[c[1]+2][0] not in  TAGcourbe:
299         for n2 in range(1,n*2+1):
300            l.append(D[c[1]+n2])
301         if DEBUG==1 : print l 
302
303     return l
304
305 #=====================================================================
306 #=====      SVG format   :  DEBUT             =========================
307 #=====================================================================
308
309 def contruit_SYMETRIC(l):
310     L=[float(l[0]), float(l[1]),
311        float(l[2]),float(l[3])]
312     X=L[0]-(L[2]-L[0])
313     Y=L[1]-(L[3]-L[1])
314     l =[l[0],l[1],"%4s"%X,"%4s"%Y,l[2],l[3]]   
315     return l
316
317 def mouvement_vers(c, D, n0,CP):
318     global DEBUG,TAGcourbe
319     #print 'c',c,'D[c[1]+1]',D[c[1]+1]
320
321     l=filtre_DATA(c,D,1)
322     #print 'l',l
323     if n0 in courbes.ITEM.keys():
324        n0+=1
325     #
326     #   CP=[l[0],l[1]]        
327     #else:
328     #   CP=[l[0],l[1]] 
329     CP=[l[0],l[1]] 
330
331     courbes.ITEM[n0]=ITEM() 
332     courbes.ITEM[n0].Origine=[l[0],l[1]] 
333
334     B=Bez()
335     B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
336     B.ha=[0,0]
337     
338     courbes.ITEM[n0].beziers_knot.append(B)
339     if DEBUG==1: print courbes.ITEM[n0], CP
340     
341
342     return  courbes,n0,CP     
343     
344 def boucle_z(c,D,n0,CP): #Z,z
345     #print c, 'close'
346     courbes.ITEM[n0].flagUV[0]=1 
347     return  courbes,n0,CP    
348    
349 def courbe_vers_s(c,D,n0,CP):  #S,s
350     l=filtre_DATA(c,D,2) 
351     if c[0]=='s':
352        l=["%4s"%(float(l[0])+float(CP[0])),
353           "%4s"%(float(l[1])+float(CP[1])),
354           "%4s"%(float(l[2])+float(CP[0])),
355           "%4s"%(float(l[3])+float(CP[1]))]
356     l=contruit_SYMETRIC(l)    
357     B=Bez()
358     B.co=[l[4],l[5],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
359     B.ha=[0,0]
360
361     BP=courbes.ITEM[n0].beziers_knot[-1]
362     BP.co[2]=l[2]  #4-5 point prec
363     BP.co[3]=l[3]
364
365     courbes.ITEM[n0].beziers_knot.append(B)
366     if DEBUG==1: print B.co,BP.co
367     CP=[l[4],l[5]]    
368
369     if len(D)<c[1]+3 and D[c[1]+3] not in TAGcourbe :
370         c[1]+=2
371         courbe_vers_c(c, D, n0,CP)
372     return  courbes,n0,CP
373
374 def courbe_vers_a(c,D,n0,CP):  #A
375     #print c
376     return  courbes,n0,CP     
377
378 def courbe_vers_q(c,D,n0,CP):  #Q
379     #print c
380     return  courbes,n0,CP     
381
382 def courbe_vers_t(c,D,n0,CP):  #T
383     return  courbes,n0,CP     
384        
385 def courbe_vers_c(c, D, n0,CP): #c,C
386
387     l=filtre_DATA(c,D,3) 
388
389     print '\n','l',l, 'c',c,'CP', CP
390
391     if c[0]=='c':
392        l=["%4s"%(float(l[0])+float(CP[0])),
393           "%4s"%(float(l[1])+float(CP[1])),
394           "%4s"%(float(l[2])+float(CP[0])),
395           "%4s"%(float(l[3])+float(CP[1])),
396           "%4s"%(float(l[4])+float(CP[0])),
397           "%4s"%(float(l[5])+float(CP[1]))]
398
399     #print l
400    
401     B=Bez()
402     B.co=[l[4],
403           l[5],
404           l[0],
405           l[1],
406           l[2],
407           l[3]] #plus toucher au 2-3
408
409     B.ha=[0,0]
410
411     BP=courbes.ITEM[n0].beziers_knot[-1]
412
413     BP.co[2]=l[0]
414     BP.co[3]=l[1]
415
416     courbes.ITEM[n0].beziers_knot.append(B)
417     if DEBUG==1: print B.co,BP.co
418
419     CP=[l[4],l[5]]
420     if DEBUG==1:
421        pass #print 'D[c[1]]', D[c[1]], c
422        #print D
423     if len(D)<c[1]+4 and D[c[1]+4] not in TAGcourbe :
424         c[1]+=3
425         courbe_vers_c(c, D, n0,CP)
426
427     return  courbes,n0,CP
428     
429     
430 def ligne_tracee_l(c, D, n0,CP): #L,l
431     #print c
432     
433     l=filtre_DATA(c,D,1)
434     if c[0]=='l':
435        l=["%4s"%(float(l[0])+float(CP[0])),
436           "%4s"%(float(l[1])+float(CP[1]))]
437
438     B=Bez()
439     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
440     B.ha=[0,0]
441     courbes.ITEM[n0].beziers_knot.append(B)    
442
443     CP=[l[0],l[1]]
444
445     if len(D)<c[1]+2 and D[c[1]+2] not in TAGcourbe :
446         c[1]+=1
447         ligne_tracee_l(c, D, n0,CP) #L
448             
449     return  courbes,n0,CP    
450     
451     
452 def ligne_tracee_h(c,D,n0,CP): #H,h
453     #print '|',c[0],'|',len(c[0]),'  --> ',CP[0]
454     #print   'D   :',D,' \n CP  :', CP 
455     if c[0]=='h':
456        l=["%4s"%(float(D[c[1]+1])+float(CP[0])),"%4s"%float(CP[1])]
457     else:
458        l=["%4s"%float(D[c[1]+1]),"%4s"%float(CP[1])]        
459     B=Bez()
460     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
461     B.ha=[0,0]
462     courbes.ITEM[n0].beziers_knot.append(B)    
463
464     CP=[l[0],l[1]]
465     #print 'CP', CP    
466     return  courbes,n0,CP    
467
468 def ligne_tracee_v(c,D,n0,CP): #V, v
469     #l=filtre_DATA(c,D,0)
470     
471     if c[0]=='v':
472        l=["%4s"%float(CP[0]),
473           "%4s"%(float(D[c[1]+1])+float(CP[1]))]
474        #print '|',c[0],'|', len(c[0]) ,'  --> ',CP
475     else:
476        l=["%4s"%float(CP[0]),
477           "%4s"%float(D[c[1]+1])]        
478        #print '|',c[0],'|', len(c[0]) ,'  --> ',CP
479
480     B=Bez()
481     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
482     B.ha=[0,0]
483     courbes.ITEM[n0].beziers_knot.append(B)    
484
485     CP=[l[0],l[1]]
486     #print 'CP', CP
487     return  courbes,n0,CP    
488
489 def boucle_tracee_z(c,D,n0,CP): #Z
490     #print c
491     #CP=[]
492     return  courbes,n0,CP    
493      
494 Actions=   {     "C" : courbe_vers_c,
495                  "A" : courbe_vers_a, 
496                  "S" : courbe_vers_s,
497                  "M" : mouvement_vers,
498                  "V" : ligne_tracee_v,
499                  "L" : ligne_tracee_l,
500                  "H" : ligne_tracee_h,                
501                  "Z" : boucle_z,
502                  "Q" : courbe_vers_q,
503                  "T" : courbe_vers_t,
504
505                  "c" : courbe_vers_c,
506                  "a" : courbe_vers_a, 
507                  "s" : courbe_vers_s,
508                  "m" : mouvement_vers,
509                  "v" : ligne_tracee_v,
510                  "l" : ligne_tracee_l,
511                  "h" : ligne_tracee_h,                
512                  "z" : boucle_z,
513                  "q" : courbe_vers_q,
514                  "T" : courbe_vers_t
515 }
516      
517 TAGcourbe=Actions.keys()
518 TAGtransform=['M','L','C','S','H','V','T','Q']
519 tagTRANSFORM=0
520
521 def get_content(val,t0):
522     t=t0[:] 
523     if t.find(' '+val+'="')!=-1:
524        t=t[t.find(' '+val+'="')+len(' '+val+'="'):]
525        val=t[:t.find('"')]
526        t=t[t.find('"'):]
527        return t0,val
528     else:
529        return t0,0
530
531 def get_tag(val,t):
532     t=t[t.find('<'+val):]
533     val=t[:t.find('>')+1]
534     t=t[t.find('>')+1:]    
535     if DEBUG==3 : print t[:10], val
536     return t,val
537
538 def get_data(val,t):
539     t=t[t.find('<'+val):]
540     val=t[:t.find('</'+val+'>')]
541     t=t[t.find('</'+val+'>')+3+len(val):]
542     if DEBUG==3 : print t[:10], val
543     return t,val
544     
545 def get_val(val,t):
546     d=""
547     #print t
548     for l in t:
549         if l.find(val+'="')!=-1:
550             #print 'l', l
551             # 0.2.7 : - correction for inskape 0.40 cvs  SVG
552             l=l.replace('>','')
553             # 0.2.7 : -- end 
554             d=l[l[:-1].rfind('"')+1:-1]
555             #print 'd', d   
556             for nn in d:
557                 if '0123456789.'.find(nn)==-1:
558                      d=d.replace(nn,"")
559                      #print d
560             d=float(d)
561             break
562         #else:
563         #  print l
564         d=0.0 
565     return d
566
567
568
569 def get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox):
570     if viewbox==0:
571         h=get_val('height',SVG)
572         if DEBUG==1 : print 'h : ',h
573         w=get_val('width',SVG)
574         if DEBUG==1 : print 'w :',w
575         BOUNDINGBOX['rec']=[0.0,0.0,w,h]
576         r=BOUNDINGBOX['rec']
577         BOUNDINGBOX['coef']=w/h       
578     else:
579         viewbox=viewbox.split()
580         BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
581         r=BOUNDINGBOX['rec']
582         BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])       
583
584     return BOUNDINGBOX
585
586 # 0.2.8 : - correction for inskape 0.40 cvs  SVG
587 def repack_DATA2(DATA):   
588     for d in Actions.keys():
589         DATA=DATA.replace(d,d+' ')
590     return DATA    
591
592
593 def wash_DATA(ndata):
594    print 'ndata', ndata, len(ndata)
595    if ndata!='':
596        while ndata[0]==' ': 
597            ndata=ndata[1:]
598        while ndata[-1]==' ': 
599            ndata=ndata[:-1]
600        if ndata[0]==',':ndata=ndata[1:]
601        if ndata[-1]==',':ndata=ndata[:-1]
602        if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ',' ']:
603           ndata=ndata.replace('-',',-')
604        ndata=ndata.replace(',,',',')    
605        ndata=ndata.replace(' ',',')
606        ndata=ndata.split(',')
607        for n in ndata :
608           if n=='' : ndata.remove(n)
609    return ndata
610          
611         
612 # 0.3.4 : - restructuration de la lecture des donnes paths
613 def list_DATA(DATA):
614     """
615     cette fonction doit retourner une liste proposant
616     une suite correcte de commande avec le nombre de valeurs
617     attendu pour chacune d'entres-elles .
618     Par exemple :
619     d="'M0,14.0 z" devient ['M','0.0','14.0','z'] 
620     """
621     while DATA.count('  ')!=0 :
622         DATA=DATA.replace('  ',' ')
623
624     tagplace=[]
625     DATA=DATA.replace('\n','')
626
627     for d in Actions.keys():
628         b1=0
629         b2=len(DATA)
630         while DATA.find(d,b1,b2)!=-1 :
631             #print d, b1 
632             tagplace.append(DATA.find(d,b1,b2))
633             b1=DATA.find(d,b1,b2)+1
634     tagplace.sort()
635     tpn=range(len(tagplace)-1)
636     DATA2=[]
637
638     for t in tpn: 
639              
640        DATA2.append(DATA[tagplace[t]:tagplace[t]+1])    
641        print DATA2[-1]
642
643        ndata=DATA[tagplace[t]+1:tagplace[t+1]]
644        if DATA2[-1] not in ['z','Z'] :
645           ndata=wash_DATA(ndata)
646           for n in ndata : DATA2.append(n)
647        
648     DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])   
649         
650     print DATA2[-1]
651         
652     if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
653        ndata=DATA[tagplace[t+1]+1:-1]
654        ndata=wash_DATA(ndata)
655        for n in ndata : DATA2.append(n)
656
657     return DATA2    
658
659
660 # 0.3
661 def translate(tx,ty):
662     return [1, 0, tx], [0, 1, ty],[0,0,1]
663
664 # 0.3.2
665 def scale(sx,sy):
666     return [sx, 0, 0], [0, sy, 0],[0,0,1]
667 # 0.3.2
668 def rotate(a):
669     return [cos(a), -sin(a), 0], [sin(a), cos(a),0],[0,0,1]
670 # 0.3.2
671 def skewX(a):
672     return [1, tan(a), 0], [0, 1, 0],[0,0,1]
673 # 0.3.2
674 def skewX(a):
675     return [1, 0, 0], [tan(a), 1 , 0],[0,0,1]
676 # 0.3.2
677 def matrix(a,b,c,d,e,f):
678     return [a,b,e],[c,d,f],[0,0,1]
679
680 # 0.3.3
681 def controle_CONTENU(val,t):
682     """
683     une matrice peut s'ecrire : matrix(a,b,c,d,e,f) ou matrix(a b c d e f)
684     """
685     if val.find('matrix') and t.find(val+'(')!=-1 and t.find(val+',')==-1:
686        t0=t[t.find(val+'(')+len(val+'('):]
687        t0=t0[:t0.find(')')]
688        val=t0[:]
689        while val.find('  ')!=-1:
690            val=val.replace('  ',' ')
691        val=val.replace(' ',',')
692        t=t.replace(t0,val)
693        return val
694     else:
695        return -1
696
697 # 0.3    
698 def get_TRANSFORM(STRING):
699     STRING,TRANSFORM=get_content('transform',STRING)
700     #print 'TRANSFORM 1 :', TRANSFORM
701     for t in ['translate','scale','rotate','matrix','skewX','skewY'] :
702        if TRANSFORM.find(t)!=-1 and TRANSFORM.count('(')==1:
703          #print 'TRANSFORM 2 :', TRANSFORM
704          print ' getcontent ', t,' ',controle_CONTENU(t,TRANSFORM)
705          exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%TRANSFORM       
706     return  T
707
708 # 0.3
709 def G_move(l,a,t):
710     if a==0:
711         v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
712         v=Mathutils.MatMultVec(t, v)
713         return str(v[0]),str(v[1])
714     else :
715        #print 'l', l ,'t', t, 'a', a
716        l=l.split(',')
717        v=Mathutils.Vector([float(l[0]),float(l[1]),1.0])
718        v=Mathutils.MatMultVec(t, v)            
719        return str(v[0])+','+str(v[1])
720     
721 # 0.3    
722 def transform_DATA(D1,TRANSFORM):   
723     for cell in range(len(D1)):
724         if D1[cell] in TAGtransform:
725            if D1[cell+1].find(',')==-1:       
726                 if D1[cell] in ['C', 'S','Q', 'M','L','T',]: #2 valeurs
727                     D1[cell+1],D1[cell+2]=G_move([D1[cell+1],D1[cell+2]],0,TRANSFORM)
728                     if D1[cell] in ['C', 'S','Q'] :
729                        D1[cell+3],D1[cell+4]=G_move([D1[cell+3],D1[cell+4]],0,TRANSFORM)
730                        if D1[cell] in ['C']:
731                           D1[cell+5],D1[cell+6]=G_move([D1[cell+5],D1[cell+6]],0,TRANSFORM)
732            else :
733                 if D1[cell] == 'C': #6 valeurs
734                     D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
735                     D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
736                     D1[cell+3]=G_move(D1[cell+3],-1,TRANSFORM)
737                 elif D1[cell] in ['M','L','T']: #2 valeurs
738                     D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
739                 elif D1[cell] == ['S','Q']: #4 valeurs
740                     D1[cell+1]=G_move(D1[cell+1],-1,TRANSFORM)
741                     D1[cell+2]=G_move(D1[cell+2],-1,TRANSFORM)
742            if D1[cell] == 'H': #1 valeurs x
743                 n=0
744                 D1[cell+1]=G_move(D1[cell+1],0,TRANSFORM)
745            elif D1[cell] == 'V': #1 valeurs y
746                 n=0
747                 D1[cell+1]=G_move(D1[cell+1],1,TRANSFORM)
748     return D1            
749                 
750 def format_PATH(t,TRANSFORM):
751     global tagTRANSFORM
752     
753     t,PATH=get_tag('path',t)
754
755     if PATH.find(' transform="')!=-1:
756        TRANSFORM2=get_TRANSFORM(PATH)
757        # 0.3.3
758        TRANSFORM=TRANSFORM*TRANSFORM2
759        #TRANSFORM[1]+=TRANSFORM2[1]
760        tagTRANSFORM+=1
761        
762     if PATH.find(' id="')!=-1:
763        PATH,ID=get_content('id',PATH)
764        #print 'ident = ', ID
765
766     if PATH.find(' STROKE="')!=-1:
767        PATH,ID=get_content('stroke',PATH)
768        #print 'path stroke = ', ID
769
770     if PATH.find(' stroke-width="')!=-1:
771        PATH,ID=get_content('stroke-width',PATH)
772        #print 'path stroke-width = ', ID
773
774     if PATH.find(' d="')!=-1:
775        PATH,D=get_content('d',PATH)
776     D=list_DATA(D)
777
778     if  tagTRANSFORM in [1,2] : D=transform_DATA(D,TRANSFORM)
779     return t,D
780
781
782
783                         
784 def scan_FILE(nom):
785   global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale, tagTRANSFORM
786   dir,name=split(nom)
787   name=name.split('.')
788   n0=0
789   result=0
790   
791   t=filtreFICHIER(nom)
792   
793   if t!='false':
794      if not SHARP_IMPORT:
795          warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" 
796          scale = Blender.Draw.PupMenu(warning)
797      npat=0
798      l=0
799      do=0
800      t,SVG=get_tag('svg',t)
801
802      SVG,viewbox=get_content('viewBox',SVG)
803
804      SVG=SVG.split(' ')
805      if DEBUG==1 : print SVG
806      if viewbox==0:
807           BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,0)
808      else:
809           BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,SVG,viewbox)
810           
811      while t.find('<g')!=-1:
812          t,G=get_data('g',t)
813          TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
814          tagTRANSFORM=0
815          if G.find(' transform="')!=-1:  
816             TRANSFORM=get_TRANSFORM(G)
817             tagTRANSFORM=1
818             
819          while G.find('path')!=-1: 
820             G,D=format_PATH(G,TRANSFORM)
821             #print D
822             cursor=0
823             for cell in D: 
824               if DEBUG==2 : print 'cell : ',cell ,' --'                   
825               if len(cell)>=1 and cell[0] in TAGcourbe:
826                    courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)            
827               cursor+=1
828               
829      # 0.3.1
830      while t.find('path')!=-1:
831             TRANSFORM=Mathutils.Matrix([1.0,0.0,0.0],[0.0,1.0,0.0],[0,0,1])
832             t,D=format_PATH(t,TRANSFORM)
833             cursor=0
834             for cell in D: 
835               if DEBUG==2 : print 'cell : ',cell ,' --'                   
836               if len(cell)>=1 and cell[0] in TAGcourbe:
837                    courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP)            
838               cursor+=1
839
840   courbes.number_of_items=len(courbes.ITEM.keys())
841
842   for k in courbes.ITEM.keys():
843      courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
844
845   if courbes.number_of_items>0:
846      if len(PATTERN.keys() )>0:
847         if DEBUG == 3 : print len(PATTERN.keys() )
848      t=create_GEOtext(courbes)
849      save_GEOfile(dir,name[0],t)
850      Open_GEOfile(dir,name[0])
851   else:
852       pass
853     
854 def  ajustement(v,s):
855      
856      a,b,c,d,e,f=float(v.co[0]),float(v.co[1]),float(v.co[2]),float(v.co[3]),float(v.co[4]),float(v.co[5])
857      return [a/s,-b/s,c/s,-d/s,e/s,-f/s]
858
859 #=====================================================================
860 #====================== SVG format mouvements ========================
861 #=====================================================================
862
863 #=====================================================================
864 # une sorte de contournement qui permet d'utiliser la fonction
865 # et de documenter les variables Window.FileSelector
866 #=====================================================================
867 def fonctionSELECT(nom):
868     scan_FILE(nom)
869
870 if __name__=='__main__':
871    Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')