==scripts==
[blender.git] / release / scripts / bpymodules / svg2obj.py
1 # -*- coding: latin-1 -*-
2 """
3 SVG 2 OBJ translater, 0.4.7
4 Copyright (c) jm soler juillet/novembre 2004-janvier 2006, 
5 # ---------------------------------------------------------------
6     released under GNU Licence 
7     for the Blender 2.40 Python Scripts Bundle.
8 Ce programme est libre, vous pouvez le redistribuer et/ou
9 le modifier selon les termes de la Licence Publique Générale GNU
10 publiée par la Free Software Foundation (version 2 ou bien toute
11 autre version ultérieure choisie par vous).
12
13 Ce programme est distribué car potentiellement utile, mais SANS
14 AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties
15 de commercialisation ou d'adaptation dans un but spécifique.
16 Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
17
18 Vous devez avoir reçu une copie de la Licence Publique Générale GNU
19 en même temps que ce programme ; si ce n'est pas le cas, écrivez à la
20 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 MA 02111-1307, États-Unis.
22
23
24 This program is free software; you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation; either version 2 of the License, or
27 (at your option) any later version.
28
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    
37 # ---------------------------------------------------------------
38
39 #---------------------------------------------------------------------------
40 # Page officielle :
41 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg.htm
42 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_svg_en.htm
43 # Communiquer les problemes et erreurs sur:
44 #   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
45 #---------------------------------------------------------------------------
46
47 -- Concept : translate SVG file in GEO .obj file and try to load it. 
48 -- Curiousity : the original matrix must be :
49
50                          0.0 0.0 1.0 0.0
51                          0.0 1.0 0.0 0.0
52                          0.0 0.0 1.0 0.0
53                          0.0 0.0 0.0 1.0 
54
55                   and not:
56                          1.0 0.0 0.0 0.0
57                          0.0 1.0 0.0 0.0
58                          0.0 0.0 1.0 0.0
59                          0.0 0.0 0.0 1.0 
60
61 -- Options :
62     SHARP_IMPORT = 0 
63             choise between "As is", "Devide by height" and "Devide by width"
64     SHARP_IMPORT = 1
65             no choise
66
67 -- Possible bug : sometime, the new curves object's RotY value 
68                   jumps to -90.0 degrees without any reason.
69
70 Yet done: 
71    M : absolute move to 
72    Z : close path
73    L : absolute line to  
74    C : absolute curve to
75    S : absolute curve to with only one handle
76    H : absolute horizontal line to  
77    V : absolute vertical line to  
78    
79    l : relative line to     2004/08/03
80    c : relative curve to    2004/08/03
81    s : relative curve to with only one handle  
82    h : relative horizontal line to 
83    v : relative vertical line to 
84
85    A : courbe_vers_a, 
86    V : ligne_tracee_v,
87    H : ligne_tracee_h, 
88    Z : boucle_z,
89    Q : courbe_vers_q,
90    T : courbe_vers_t,
91    a : courbe_vers_a, 
92    v : ligne_tracee_v,
93    h : ligne_tracee_h, 
94    z : boucle_z,
95    q : courbe_vers_q,
96
97    transfrom for <g> tag 
98    transform for <path> tag
99
100 Changelog:
101       0.1.1 : - control file without extension
102       0.2.0 : - improved reading of several data of the same type 
103                 following the same command (for gimp import)
104       0.2.1 : - better choice for viewboxing ( takes the viewbox if found, 
105                 instead of x,y,width and height              
106       0.2.2 : - read compact path data from Illustrator 10             
107       0.2.3 : - read a few new relative displacements
108       0.2.4 : - better hash for command followed by a lone data 
109                 (h,v) or uncommun number (a) 
110       0.2.5 : - correction for gimp import 
111       0.2.6 : - correction for illustrator 10 SVG
112       0.2.7 : - correction for inskape 0.40 cvs  SVG
113       0.2.8 : - correction for inskape plain SVG
114       0.3   : - reading of the transform properties added : 
115                     translate
116       0.3.1 : - compatibility restored with gimp 
117       0.3.2 : - transform properties added (june, 15-16): 
118                     scale, 
119                     rotate, 
120                     matrix, 
121                     skew               
122               - added a test on __name__ to load the script
123                 outside from the blender menu  
124       0.3.3 : - matrix transform content control  
125       0.3.4 : - paths data reading rewritten (19/06/05) 
126       0.3.5 : - test on empty curve  (22/06/05)
127               - removed overlayed points
128       0.3.6 : - rewriting of the bezier point contruction to correct
129                 a problem in the connection between L type point and
130                 C or S type point         
131       0.3.7 : - code correction for bezier knot in Curveto command when
132                 the command close a path
133       0.3.8 : - code was aded to manage quadratic bezier, 
134                 Q,q command and T,t commands, as a normal  blender's bezier point 
135               - The last modications does not work with gimp 2.0 svg export . 
136                 corrected too .
137       0.3.9 : - Path's A,a  command for ellipse's arc  .
138       0.4.0 : - To speed up the function filtre_DATA was removed and text
139                 variables are changed into numeric variables               
140       0.4.1 : - svg, groups and shapes hierarchy  added
141               - now transform properties are computed  using a stack  with all
142                 parented groups
143               - removed or replaced useless functions :
144               - skewY, skewX transforms
145               - radians in rotate transform 
146       0.4.2 : - Added functon to translate others shapes in path 
147                      rect, line, polyline, polygon
148         
149       0.4.3 : - various corrections 
150                   text font (id property exported by Adobe Illustrator are between coma)
151                   function  to code  s tag has been  rewritten 
152
153       0.4.4 : - various corrections      
154                 to oblige the script to understand a line feed just after 
155                 a tag . Rarely encountered problem, but it exits in a svg file
156                 format exported by a outliner script for mesh .
157
158       0.4.5 : - update for CVS only, at least blender 2.38 and upper
159                 no BezTriple module in older version
160                 added a createCURVES function to avoid to use
161                 the OBJ format export/import .
162
163                 Perhaps problems with cyclic curves . If a closed curve 
164                 does not appear closed in blender, enter edit mode select 
165                 all  knot with Akey,  do a Hkey to set handle type (without 
166                 this the knot are recalculated) , and finally use the Ckey 
167                 to close the curve .
168                 Should work ... not guaranted .
169
170       0.4.6 : - cyclic flag ...
171
172       0.4.7 : - Management of the svgz files . the complete python or the gzip.py 
173                 file is needed .
174                 Little improvement of the curve drawing using the createCURVES 
175                 function 
176 ==================================================================================   
177 =================================================================================="""
178
179 SHARP_IMPORT=0
180 SCALE=1
181 scale_=1
182 DEBUG = 0#print
183 DEVELOPPEMENT=0
184     
185 import sys
186 from math import cos,sin,tan, atan2, pi, ceil
187 PI=pi
188 import Blender
189 from Blender import Mathutils
190 BLversion=Blender.Get('version')
191
192 try:
193     import nt
194     os=nt
195     os.sep='\\'
196
197 except:    
198     import posix
199     os=posix
200     os.sep='/'
201     
202 def isdir(path):
203     try:
204         st = os.stat(path)
205         return 1 
206     except:
207         return 0
208     
209 def split(pathname):
210          if pathname.find(os.sep)!=-1:
211              k0=pathname.split(os.sep)
212          else:
213             if os.sep=='/':
214                 k0=pathname.split('\\')
215             else:
216                 k0=pathname.split('/') 
217
218          directory=pathname.replace(k0[len(k0)-1],'')
219          Name=k0[len(k0)-1]
220          return directory, Name
221         
222 def join(l0,l1):        
223      return  l0+os.sep+l1
224     
225 os.isdir=isdir
226 os.split=split
227 os.join=join
228
229 def filtreFICHIER(nom):
230      """
231      Function  filtreFICHIER
232
233      in  : string  nom , filename
234      out : string  t   , if correct filecontaint 
235
236      Lit le contenu du fichier et en fait une pre-analyse 
237      pour savoir s'il merite d'etre traite .
238      """
239      # ----------
240      # 0.4.7 
241      # ----------
242      if nom.upper().find('.SVGZ')!=-1:
243          try :
244              import gzip 
245              tz=gzip.GzipFile(nom)
246              t=tz.read()
247          except:
248              name = "ERROR: fail to import gzip module or gzip error ... "  
249              result = Blender.Draw.PupMenu(name)
250              return "false"
251      else:    
252         f=open(nom,'rU')
253         t=f.read()
254         f.close()
255      # ----------
256      # 0.4.7  : end 
257      # ----------
258      
259      # -----------------
260      #  pre-format ...
261      # -----------------
262      # --------------------
263      # 0.4.4  '\r','' -->  '\r',' ' 
264      #        '\n','' -->  '\n',' ' 
265      #--------------------
266      t=t.replace('\r',' ')
267      t=t.replace('\n',' ')
268      t=t.replace('svg:','')
269      
270      if t.upper().find('<SVG')==-1 :
271          name = "ERROR: invalid or empty file ... "  # if no %xN int is set, indices start from 1
272          result = Blender.Draw.PupMenu(name)
273          return "false"
274      else:
275           return t
276
277      """
278      elif  t.upper().find('<PATH')==-1 and\
279            t.upper().find('<RECT')==-1 and\
280            t.upper().find('<LINE')==-1 and\
281            t.upper().find('<POLYLINE')==-1      :
282          name = "ERROR: there's no Path in this file ... "  # if no %xN int is set, indices start from 1
283          result = Blender.Draw.PupMenu(name)
284          return "false"
285      """
286
287
288 #===============================
289 # Data
290 #===============================
291
292
293 #===============================
294 # Blender Curve Data
295 #===============================
296 objBEZIER=0
297 objSURFACE=5
298 typBEZIER3D=1  #3D
299 typBEZIER2D=9  #2D
300
301 class Bez:
302       def __init__(self):
303            self.co=[]
304            self.ha=[0,0]
305            self.tag=''
306
307 class ITEM:
308       def __init__(self):
309                self.type        =  typBEZIER3D        
310                self.pntsUV      =  [0,0]              
311                self.resolUV     =  [32,0]            
312                self.orderUV     =  [0,0]             
313                self.flagUV      =  [0,0]              
314                self.Origine     =  [0.0,0.0]
315                self.beziers_knot = []
316                self.fill=0
317                self.closed=0
318                self.color=[0.0,0.0,0.0]
319
320 class COURBE:
321       def __init__(self):
322               self.magic_number='3DG3'              
323               self.type            =  objBEZIER        
324               self.number_of_items =  0              
325               self.ext1_ext2       =  [0,0]             
326               self.matrix          =  """0.0 0.0 1.0 0.0
327 0.0 1.0 0.0 0.0
328 0.0 0.0 1.0 0.0
329 0.0 0.0 0.0 1.0 """ 
330               self.ITEM = {}
331
332
333 courbes=COURBE()
334 PATTERN={}
335 BOUNDINGBOX={'rec':[],'coef':1.0}
336 npat=0
337 #=====================================================================
338 #======== name of the curve in the curves dictionnary ===============
339 #=====================================================================
340 n0=0
341
342 #=====================================================================
343 #====================== current Point ================================
344 #=====================================================================
345 CP=[0.0,0.0] #currentPoint
346
347 #=====================================================================
348 #===== to compare last position to the original move to displacement =
349 #=====  needed for cyclic definition inAI, EPS forma  ================
350 #=====================================================================
351 def test_egalitedespositions(f1,f2):
352     if f1[0]==f2[0] and f1[1]==f2[1]:
353        return Blender.TRUE
354     else:
355        return Blender.FALSE
356
357
358 def Open_GEOfile(dir,nom):
359     global SCALE,BOUNDINGBOX, scale_
360     if BLversion>=233:
361        Blender.Load(dir+nom+'OOO.obj', 1)
362        BO=Blender.Object.Get()
363
364        BO[-1].RotY=3.1416
365        BO[-1].RotZ=3.1416
366        BO[-1].RotX=3.1416/2.0
367        
368        if scale_==1:
369           BO[-1].LocY+=BOUNDINGBOX['rec'][3]
370        else:
371          BO[-1].LocY+=BOUNDINGBOX['rec'][3]/SCALE
372  
373        BO[-1].makeDisplayList() 
374        Blender.Window.RedrawAll()
375     else:
376        print "Not yet implemented"
377
378 def create_GEOtext(courbes):
379     global SCALE, B, BOUNDINGBOX,scale_
380
381     r=BOUNDINGBOX['rec']
382     if scale_==1:
383        SCALE=1.0
384     elif scale_==2:
385        SCALE=r[2]-r[0]
386     elif scale_==3:
387        SCALE=r[3]-r[1]
388  
389     t=[]
390     t.append(courbes.magic_number+'\n')
391     t.append(str(courbes.type)+'\n')
392     t.append(str(courbes.number_of_items)+'\n')
393     t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
394     t.append(courbes.matrix+'\n')
395     
396     for k in courbes.ITEM.keys():
397         t.append("%s\n"%courbes.ITEM[k].type)
398         t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
399         t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
400         t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
401         t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
402
403         flag =0#courbes.ITEM[k].flagUV[0]
404
405         for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
406            #k1 =courbes.ITEM[k].beziers_knot[k2]
407            k1=ajustement(courbes.ITEM[k].beziers_knot[k2], SCALE)
408            
409            t.append("%4f 0.0 %4f \n"%(k1[4],k1[5]))
410            t.append("%4f 0.0 %4f \n"%(k1[0],k1[1]))
411            t.append("%4f 0.0 %4f \n"%(k1[2],k1[3]))
412            t.append(str(courbes.ITEM[k].beziers_knot[k2].ha[0])+' '+str(courbes.ITEM[k].beziers_knot[k2].ha[1])+'\n')
413
414     return t
415
416 def save_GEOfile(dir,nom,t):
417      f=open(dir+nom+'OOO.obj','w')
418      f.writelines(t)
419      f.close()
420
421 #--------------------
422 # 0.4.5 : for blender cvs 2.38 ....
423 #--------------------
424 def createCURVES(courbes):
425     global SCALE, B, BOUNDINGBOX,scale_
426     from Blender import Curve, Object, Scene, BezTriple
427
428     r=BOUNDINGBOX['rec']
429     if scale_==1:
430        SCALE=1.0
431     elif scale_==2:
432        SCALE=r[2]-r[0]
433     elif scale_==3:
434        SCALE=r[3]-r[1]
435
436     [o.select(0) for o in Object.Get()]
437     for I in courbes.ITEM:
438         c = Curve.New()
439         # ----------
440         # 0.4.7 
441         # ----------
442         c.setResolu(24)  
443         scene = Scene.getCurrent()
444         ob = Object.New('Curve')
445         ob.link(c)
446         scene.link(ob)
447         ob.select(1)
448         bzn=0
449         #for b in courbes.ITEM[I].beziers_knot:
450         for k2 in range(0,len(courbes.ITEM[I].beziers_knot)):
451             bz=ajustement(courbes.ITEM[I].beziers_knot[k2], SCALE)
452             #bz=k1
453             if bzn==0:
454               cp1 =  bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0, 
455               beztriple1 = BezTriple.New(cp1)
456               bez = c.appendNurb(beztriple1)
457               
458               bzn = 1
459             else:
460               cp2 =  bz[4],bz[5],0.0 , bz[0],bz[1],0.0, bz[2],bz[3],0.0
461               beztriple2 = BezTriple.New(cp2)
462               bez.append(beztriple2)
463
464         if courbes.ITEM[I].flagUV[0]==1 :
465           #--------------------
466           # 0.4.6 : cyclic flag ...
467           #--------------------
468            bez.flagU += 1
469            
470
471
472 #=====================================================================
473 #=====      SVG format   :  DEBUT             =========================
474 #=====================================================================
475 #--------------------
476 # 0.4.2
477 #--------------------
478 OTHERSSHAPES=['rect','line', 'polyline', 'polygon','circle','ellipse']
479
480 #--------------------
481 # 0.4.2
482 #--------------------
483 def rect(prp):
484   D=[]
485   if 'x' not in prp.keys(): x=0.0
486   else  : x=float(prp['x'])
487   if 'y' not in prp.keys(): y=0.0
488   else  : y=float(prp['y'])
489                 
490   height=float(prp['height'])
491   width=float(prp['width'])
492         
493   """
494    normal rect
495
496    x,y 
497                   h1       
498        *----------*
499        |          |
500        |          | 
501        |          |
502        *----------* v1
503        h2
504   """
505   if 'rx' not in prp.keys() or 'rx' not in prp.keys(): 
506      exec   """D=['M','%s','%s','h','%s','v','%s','h','%s','z']"""%(x,y,width,height,-width)    
507   else :
508      rx=float(prp['rx'])
509      if 'ry' not in prp.keys()  : 
510             ry=float(prp['rx'])
511      else :     ry=float(prp['ry'])
512      if 'rx' in prp.keys() and prp['rx']<0.0: rx*=-1
513      if 'ry' in prp.keys() and prp['ry']<0.0: ry*=-1
514         
515      """
516    rounded corner
517       
518    x,y     M         h1       
519        ---*----------*  
520          /            \  
521         /              \
522     v2 *                * c1
523        |                |
524        |                |   
525        |                |
526     c3 *                * v2
527         \              /
528          \            /   
529           *----------*  
530           h2         c2
531      """
532      exec   """D=['M','%s','%s',
533                   'h','%s',
534                   'c','%s','%s','%s','%s','%s','%s',
535                   'v','%s',
536                   'c','%s','%s','%s','%s','%s','%s',
537                   'h','%s',
538                   'c','%s','%s','%s','%s','%s','%s',
539                   'v','%s',
540                   'c','%s','%s','%s','%s','%s','%s',
541                   'z']"""%(x+rx,y,
542                            width-2*rx,
543                            rx,0.0,rx,ry,rx,ry,
544                             height-ry,
545                            0.0,ry,-rx,ry,-rx,ry,
546                            -width+2*rx,
547                            -rx,0.0,-rx,-ry,-rx,-ry,
548                            -height+ry,
549                            0.0,0.0,0.0,-ry,rx,-ry
550  )      
551                        
552   return D
553
554 #--------------------
555 # 0.4.2
556 #--------------------
557 def circle(prp):
558    if 'cx' not in prp.keys(): cx=0.0    
559    else : cx =float(prp['cx'])
560    if 'cy' not in prp.keys(): cy=0.0
561    else : cy =float(prp['cy'])
562    r = float(prp['r'])
563    exec """D=['M','%s','%s',                  
564               'C','%s','%s','%s','%s','%s','%s',
565               'C','%s','%s','%s','%s','%s','%s',
566               'C','%s','%s','%s','%s','%s','%s',
567               'C','%s','%s','%s','%s','%s','%s',
568               'Z']"""%( 
569                       cx,cy+r, 
570                       cx-r,cy+r*0.552, cx-0.552*r,cy+r, cx,cy+r,
571                       cx+r*0.552,cy+r, cx+r,cy+r*0.552, cx+r,cy,
572                       cx+r,cy-r*0.552,  cx+r*0.552,cy-r,   cx,cy-r,
573                       cx-r*0.552,cy-r, cx-r,cy-r*0.552, cx-r,cy
574                       )
575    return D 
576    
577 #--------------------
578 # 0.4.2
579 #--------------------
580 def ellipse(prp):
581    if 'cx' not in prp.keys(): cx=0.0    
582    else : cx =float(prp['cx'])
583    if 'cy' not in prp.keys(): cy=0.0
584    else : cy =float(prp['cy'])
585    ry = float(prp['rx'])
586    rx = float(prp['ry'])
587
588    exec """D=['M','%s','%s',                  
589               'C','%s','%s','%s','%s','%s','%s',
590               'C','%s','%s','%s','%s','%s','%s',
591               'C','%s','%s','%s','%s','%s','%s',
592               'C','%s','%s','%s','%s','%s','%s',
593               'Z']"""%( 
594                       cx,cy+rx, 
595                       cx-ry,cy+rx*0.552, cx-0.552*ry,cy+rx, cx,cy+rx,
596                       cx+ry*0.552,cy+rx, cx+ry,cy+rx*0.552, cx+ry,cy,
597                       cx+ry,cy-rx*0.552,  cx+ry*0.552,cy-rx,   cx,cy-rx,
598                       cx-ry*0.552,cy-rx, cx-ry,cy-rx*0.552, cx-ry,cy
599                       )
600    return D 
601 #--------------------
602 # 0.4.2
603 #--------------------
604 def line(prp):
605   exec   """D=['M','%s','%s',
606                   'L','%s','%s']"""%(prp['x1'],prp['y1'], prp['x2'],prp['y2'])
607   return D
608 #--------------------
609 # 0.4.2
610 #--------------------    
611 def polyline(prp):
612  if 'points' in  prp.keys():
613     #print prp['points']
614     points=prp['points'].split(' ')
615     #print points
616     np=0
617     for p in points:
618      if p!='':
619         p=p.split(',')
620         if np==0:
621            exec "D=['M','%s','%s']"%(p[0],p[1])
622            np+=1
623         else: 
624            exec """D.append('L');D.append('%s');D.append('%s')"""%(p[0],p[1])
625     #print D
626     return D
627  else:
628     return []
629
630 #--------------------
631 # 0.4.2
632 #--------------------   
633 def polygon(prp):
634     D=polyline(prp)
635     if D!=[]:
636         D.append('Z')
637     return D
638
639     
640 #--------------------
641 # 0.3.9
642 #--------------------
643 def calc_arc (cpx,cpy, rx, ry,  ang, fa , fs , x, y) :
644     rx=abs(rx)
645     ry=abs(ry)
646     px=abs((cos(ang)*(cpx-x)+sin(ang)*(cpy-y))*0.5)**2.0
647     py=abs((cos(ang)*(cpy-y)-sin(ang)*(cpx-x))*0.5)**2.0
648     pl=px/(rx**2.0)+py/(ry**2.0 )
649     if pl>1.0:
650         pl=pl**0.5;rx*=pl;ry*=pl
651     x0=(cos(ang)/rx)*cpx+(sin(ang)/rx)*cpy
652     y0=(-sin(ang)/ry)*cpx+(cos(ang)/ry)*cpy
653     x1=(cos(ang)/rx)*x+(sin(ang)/rx)*y
654     y1=(-sin(ang)/ry)*x+(cos(ang)/ ry)*y    
655     d=(x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)  
656     if abs(d)>0.0 :sq=1.0/d-0.25
657     else: sq=-0.25
658     if sq<0.0 :sq=0.0
659     sf=sq**0.5
660     if fs==fa :sf=-sf
661     xc=0.5*(x0+x1)-sf*(y1-y0)
662     yc=0.5*(y0+y1)+sf*(x1-x0)
663     ang_0=atan2(y0-yc,x0-xc)
664     ang_1=atan2(y1-yc,x1-xc)
665     ang_arc=ang_1-ang_0;
666     if (ang_arc < 0.0 and fs==1) :
667         ang_arc += 2.0 * PI
668     elif (ang_arc>0.0 and fs==0) :
669         ang_arc-=2.0*PI
670     n_segs=int(ceil(abs(ang_arc*2.0/(PI*0.5+0.001))))
671     P=[]
672     for i in range(n_segs):
673         ang0=ang_0+i*ang_arc/n_segs
674         ang1=ang_0+(i+1)*ang_arc/n_segs
675         ang_demi=0.25*(ang1-ang0)
676         t=2.66666*sin(ang_demi)*sin(ang_demi)/sin(ang_demi*2.0)
677         x1=xc+cos(ang0)-t*sin(ang0)
678         y1=yc+sin(ang0)+t*cos(ang0)
679         x2=xc+cos(ang1)
680         y2=yc+sin(ang1)
681         x3=x2+t*sin(ang1)
682         y3=y2-t*cos(ang1)
683         P.append([[(cos(ang)*rx)*x1+(-sin(ang)*ry)*y1,
684                (sin(ang)*rx)*x1+(cos(ang)*ry)*y1],
685               [(cos(ang)*rx)*x3+(-sin(ang)*ry)*y3,
686                (sin(ang)*rx)*x3+(cos(ang)*ry)*y3],
687               [(cos(ang)*rx)*x2+(-sin(ang)*ry)*y2,
688                (sin(ang)*rx)*x2+(cos(ang)*ry)*y2]])
689     return P
690
691
692 #--------------------
693 # 0.3.9
694 #--------------------
695 def courbe_vers_a(c,D,n0,CP):  #A,a
696     global SCALE
697
698     l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
699         int(D[c[1]+4]),int(D[c[1]+5]),float(D[c[1]+6]),float(D[c[1]+7])]
700     if c[0]=='a':
701        l[5]=l[5] + CP[0]
702        l[6]=l[6] + CP[1]
703
704     B=Bez()
705     B.co=[ CP[0], CP[1], CP[0], CP[1], CP[0], CP[1] ]             
706     B.ha=[0,0]
707     B.tag=c[0]
708  
709     POINTS= calc_arc (CP[0],CP[1], 
710                       l[0], l[1], l[2]*(PI / 180.0),
711                       l[3], l[4], 
712                       l[5], l[6] )
713
714     if DEBUG == 1  : print POINTS
715     
716     for p in POINTS :
717         B=Bez()
718         B.co=[ p[2][0],p[2][1], p[0][0],p[0][1], p[1][0],p[1][1]]             
719         B.ha=[0,0]
720         B.tag=c[0]
721         BP=courbes.ITEM[n0].beziers_knot[-1]
722         BP.co[2]=B.co[2]
723         BP.co[3]=B.co[3]
724         courbes.ITEM[n0].beziers_knot.append(B)
725            
726     BP=courbes.ITEM[n0].beziers_knot[-1]
727     BP.co[2]=BP.co[0]
728     BP.co[3]=BP.co[1]
729
730     CP=[l[5], l[6]]
731     return  courbes,n0,CP    
732
733 def mouvement_vers(c, D, n0,CP, proprietes):
734     global DEBUG,TAGcourbe
735
736     #l=filtre_DATA(c,D,2)
737     l=[float(D[c[1]+1]),float(D[c[1]+2])]
738
739     if c[0]=='m':
740        l=[l[0]+CP[0],
741            l[1] + CP[1]]
742
743     if n0 in courbes.ITEM.keys():
744        n0+=1
745
746     CP=[l[0],l[1]] 
747     courbes.ITEM[n0]=ITEM() 
748     courbes.ITEM[n0].Origine=[l[0],l[1]] 
749
750     proprietes['n'].append(n0)
751     #print 'prop et item',proprietes['n'], courbes.ITEM.keys()
752
753     B=Bez()
754     B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
755     B.ha=[0,0]
756     B.tag=c[0]
757     courbes.ITEM[n0].beziers_knot.append(B)
758     
759     if DEBUG==1: print courbes.ITEM[n0], CP    
760
761     return  courbes,n0,CP     
762     
763 def boucle_z(c,D,n0,CP): #Z,z
764     #print c, 'close'
765     #print courbes.ITEM[n0].beziers_knot
766     courbes.ITEM[n0].flagUV[0]=1
767     #print 'len(courbes.ITEM[n0].beziers_knot)',len(courbes.ITEM[n0].beziers_knot)
768     if len(courbes.ITEM[n0].beziers_knot)>1:
769         BP=courbes.ITEM[n0].beziers_knot[-1]
770         BP0=courbes.ITEM[n0].beziers_knot[0]
771         if BP.tag in ['c','C','s','S']: 
772            BP.co[2]=BP0.co[2]  #4-5 point prec
773            BP.co[3]=BP0.co[3]
774            del courbes.ITEM[n0].beziers_knot[0]
775     else:
776      del courbes.ITEM[n0]
777
778      n0-=1 
779     return  courbes,n0,CP    
780
781 def courbe_vers_q(c,D,n0,CP):  #Q,q
782     l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),float(D[c[1]+4])]
783     if c[0]=='q':
784        l=[l[0]+CP[0], l[1]+CP[1], l[2]+CP[0], l[3]+CP[1]]
785     B=Bez()
786     B.co=[l[2],  l[3],  l[2],  l[3], l[0], l[1]] #plus toucher au 2-3
787     B.ha=[0,0]
788     B.tag=c[0]
789     BP=courbes.ITEM[n0].beziers_knot[-1]
790     BP.co[2]=BP.co[0]
791     BP.co[3]=BP.co[1]
792     courbes.ITEM[n0].beziers_knot.append(B)
793     if DEBUG==1: print B.co,BP.co
794
795     CP=[l[2],l[3]]
796     if DEBUG==1:
797        pass 
798     if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
799         c[1]+=4
800         courbe_vers_q(c, D, n0,CP)
801     return  courbes,n0,CP          
802
803 def courbe_vers_t(c,D,n0,CP):  #T,t 
804     l=[float(D[c[1]+1]),float(D[c[1]+2])]
805     if c[0]=='t':
806        l=[l[0]+CP[0], l[1]+CP[1]]
807           
808     B=Bez()
809     B.co=[l[0], l[1], l[0], l[1], l[0], l[1]] #plus toucher au 2-3
810     B.ha=[0,0]
811     B.tag=c[0]
812
813     BP=courbes.ITEM[n0].beziers_knot[-1]
814
815     l0=contruit_SYMETRIC([BP.co[0],BP.co[1],BP.co[4],BP.co[5]])
816
817     if BP.tag in ['q','Q','t','T','m','M']:
818        BP.co[2]=l0[2]
819        BP.co[3]=l0[3]
820
821     courbes.ITEM[n0].beziers_knot.append(B)
822     if DEBUG==1: print B.co,BP.co
823
824     CP=[l[0],l[1]]
825     if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
826         c[1]+=4
827         courbe_vers_t(c, D, n0,CP)    
828     return  courbes,n0,CP     
829
830 #--------------------
831 # 0.4.3 : rewritten
832 #--------------------
833 def contruit_SYMETRIC(l):
834     X=l[2]-(l[0]-l[2])
835     Y=l[3]-(l[1]-l[3])
836     return X,Y
837
838 def courbe_vers_s(c,D,n0,CP):  #S,s
839     l=[float(D[c[1]+1]),
840        float(D[c[1]+2]),
841        float(D[c[1]+3]),
842        float(D[c[1]+4])]
843     if c[0]=='s':
844        l=[l[0]+CP[0], l[1]+CP[1], 
845           l[2]+CP[0], l[3]+CP[1]]
846     B=Bez()
847     B.co=[l[2],l[3],l[2],l[3],l[0],l[1]] #plus toucher au 2-3
848     B.ha=[0,0]
849     B.tag=c[0]
850     BP=courbes.ITEM[n0].beziers_knot[-1]
851     #--------------------
852     # 0.4.3
853     #--------------------
854     BP.co[2],BP.co[3]=contruit_SYMETRIC([BP.co[4],BP.co[5],BP.co[0],BP.co[1]])
855     courbes.ITEM[n0].beziers_knot.append(B)
856     if DEBUG==1: print B.co,BP.co
857     #--------------------
858     # 0.4.3
859     #--------------------       
860     CP=[l[2],l[3]]    
861     if len(D)>c[1]+5 and D[c[1]+5] not in TAGcourbe :
862         c[1]+=4
863         courbe_vers_c(c, D, n0,CP)       
864     return  courbes,n0,CP
865        
866 def courbe_vers_c(c, D, n0,CP): #c,C
867     l=[float(D[c[1]+1]),float(D[c[1]+2]),float(D[c[1]+3]),
868        float(D[c[1]+4]),float(D[c[1]+5]),float(D[c[1]+6])]
869     if c[0]=='c':
870        l=[l[0]+CP[0],
871           l[1]+CP[1],
872           l[2]+CP[0],
873           l[3]+CP[1],
874           l[4]+CP[0],
875           l[5]+CP[1]]
876     B=Bez()
877     B.co=[l[4],
878           l[5],
879           l[4],
880           l[5],
881           l[2],
882           l[3]] #plus toucher au 2-3
883     B.ha=[0,0]
884     B.tag=c[0]
885     BP=courbes.ITEM[n0].beziers_knot[-1]
886     BP.co[2]=l[0]
887     BP.co[3]=l[1]
888     courbes.ITEM[n0].beziers_knot.append(B)
889     if DEBUG==1: print B.co,BP.co
890     CP=[l[4],l[5]]
891     if len(D)>c[1]+7 and D[c[1]+7] not in TAGcourbe :
892         c[1]+=6
893         courbe_vers_c(c, D, n0,CP)
894     return  courbes,n0,CP
895     
896     
897 def ligne_tracee_l(c, D, n0,CP): #L,l
898     l=[float(D[c[1]+1]),float(D[c[1]+2])]
899     if c[0]=='l':
900        l=[l[0]+CP[0],
901           l[1]+CP[1]]
902     B=Bez()
903     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
904     B.ha=[0,0]
905     B.tag=c[0]
906     BP=courbes.ITEM[n0].beziers_knot[-1]
907     if BP.tag in ['c','C','s','S','m','M']:
908        BP.co[2]=B.co[4]
909        BP.co[3]=B.co[5]
910     courbes.ITEM[n0].beziers_knot.append(B)    
911     CP=[B.co[0],B.co[1]]
912     if len(D)>c[1]+3 and D[c[1]+3] not in TAGcourbe :
913         c[1]+=2
914         ligne_tracee_l(c, D, n0,CP) #L
915     return  courbes,n0,CP    
916     
917     
918 def ligne_tracee_h(c,D,n0,CP): #H,h
919     if c[0]=='h':
920        l=[float(D[c[1]+1])+float(CP[0]),CP[1]]
921     else:
922        l=[float(D[c[1]+1]),CP[1]]
923     B=Bez()
924     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
925     B.ha=[0,0]
926     B.tag=c[0]
927     BP=courbes.ITEM[n0].beziers_knot[-1]
928     if BP.tag in ['c','C','s','S','m','M']:
929         BP.co[2]=B.co[4]
930         BP.co[3]=B.co[5]
931     courbes.ITEM[n0].beziers_knot.append(B)    
932     CP=[l[0],l[1]]
933     return  courbes,n0,CP    
934
935 def ligne_tracee_v(c,D,n0,CP): #V, v    
936     if c[0]=='v':
937        l=[CP[0], float(D[c[1]+1])+CP[1]]
938     else:
939        l=[CP[0], float(D[c[1]+1])]               
940     B=Bez()
941     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
942     B.ha=[0,0]
943     B.tag=c[0]
944     BP=courbes.ITEM[n0].beziers_knot[-1]
945     if BP.tag in ['c','C','s','S','m','M']:
946         BP.co[2]=B.co[4]
947         BP.co[3]=B.co[5]
948     courbes.ITEM[n0].beziers_knot.append(B)    
949     CP=[l[0],l[1]]
950     return  courbes,n0,CP    
951      
952 Actions=   {     "C" : courbe_vers_c,
953                  "A" : courbe_vers_a, 
954                  "S" : courbe_vers_s,
955                  "M" : mouvement_vers,
956                  "V" : ligne_tracee_v,
957                  "L" : ligne_tracee_l,
958                  "H" : ligne_tracee_h,                
959                  "Z" : boucle_z,
960                  "Q" : courbe_vers_q,
961                  "T" : courbe_vers_t,
962
963                  "c" : courbe_vers_c,
964                  "a" : courbe_vers_a, 
965                  "s" : courbe_vers_s,
966                  "m" : mouvement_vers,
967                  "v" : ligne_tracee_v,
968                  "l" : ligne_tracee_l,
969                  "h" : ligne_tracee_h,                
970                  "z" : boucle_z,
971                  "q" : courbe_vers_q,
972                  "T" : courbe_vers_t
973 }
974      
975 TAGcourbe=Actions.keys()
976 TAGtransform=['M','L','C','S','H','V','T','Q']
977 tagTRANSFORM=0
978  
979 def wash_DATA(ndata):
980    if ndata!='':
981        while ndata[0]==' ': 
982            ndata=ndata[1:]
983        while ndata[-1]==' ': 
984            ndata=ndata[:-1]
985        if ndata[0]==',':ndata=ndata[1:]
986        if ndata[-1]==',':ndata=ndata[:-1]
987        #--------------------
988        # 0.4.0 : 'e'
989        #--------------------
990        if ndata.find('-')!=-1 and ndata[ndata.find('-')-1] not in [' ', ',', 'e']:
991           ndata=ndata.replace('-',',-')
992        ndata=ndata.replace(',,',',')    
993        ndata=ndata.replace(' ',',')
994        ndata=ndata.split(',')
995        for n in ndata :
996           if n=='' : ndata.remove(n)    
997    return ndata
998
999 #--------------------             
1000 # 0.3.4 : - reading data rewrittten
1001 #--------------------
1002 def list_DATA(DATA):
1003     """
1004     cette fonction doit retourner une liste proposant
1005     une suite correcte de commande avec le nombre de valeurs
1006     attendu pour chacune d'entres-elles .
1007     Par exemple :
1008     d="'M0,14.0 z" devient ['M','0.0','14.0','z'] 
1009     """
1010     tagplace=[]
1011     for d in Actions.keys():
1012         b1=0
1013         b2=len(DATA)
1014         while DATA.find(d,b1,b2)!=-1 :
1015             tagplace.append(DATA.find(d,b1,b2))
1016             b1=DATA.find(d,b1,b2)+1
1017     tagplace.sort()
1018     tpn=range(len(tagplace)-1)
1019     #--------------------
1020     # 0.3.5 :: short data,only one tag
1021     #--------------------
1022     if len(tagplace)-1>0:
1023        DATA2=[]
1024        for t in tpn: 
1025           DATA2.append(DATA[tagplace[t]:tagplace[t]+1])    
1026           ndata=DATA[tagplace[t]+1:tagplace[t+1]]
1027           if DATA2[-1] not in ['z','Z'] :
1028              ndata=wash_DATA(ndata)
1029              for n in ndata : DATA2.append(n)       
1030        DATA2.append(DATA[tagplace[t+1]:tagplace[t+1]+1])   
1031        if DATA2[-1] not in ['z','Z'] and len(DATA)-1>=tagplace[t+1]+1:
1032           ndata=DATA[tagplace[t+1]+1:-1]
1033           ndata=wash_DATA(ndata)
1034           for n in ndata : DATA2.append(n)
1035     else:
1036         #--------------------   
1037         # 0.3.5 : short data,only one tag
1038         #--------------------
1039         DATA2=[]
1040         DATA2.append(DATA[tagplace[0]:tagplace[0]+1])
1041         ndata=DATA[tagplace[0]+1:]
1042         ndata=wash_DATA(ndata)
1043         for n in ndata : DATA2.append(n)
1044     return DATA2    
1045
1046 # 0.3
1047 def translate(tx=None,ty=None):
1048     return [1, 0, tx], [0, 1, ty],[0,0,1]
1049 # 0.3.2
1050 def scale(sx=None,sy=None):
1051     if sy==None: sy=sx
1052     return [sx, 0, 0], [0, sy, 0],[0,0,1]
1053 # 0.4.1 : transslate a in radians
1054 def rotate(a):
1055     return [cos(a*3.1416/90.0), -sin(a*3.1416/90.0), 0], [sin(a*3.1416/90.0), cos(a*3.1416/90.0),0],[0,0,1]
1056 # 0.3.2
1057 def skewX(a):
1058     return [1, tan(a), 0], [0, 1, 0],[0,0,1]
1059 # 0.4.1
1060 def skewY(a):
1061     return [1, 0, 0], [tan(a), 1 , 0],[0,0,1]
1062 # 0.3.2
1063 def matrix(a,b,c,d,e,f):
1064     return [a,c,e],[b,d,f],[0,0,1]
1065
1066 # 0.4.2 : rewritten 
1067 def control_CONTAINT(txt):
1068     """
1069     les descriptions de transformation peuvent être seules ou plusieurs et
1070     les séparateurs peuvent avoir été oubliés
1071     """
1072     t0=0
1073     tlist=[]
1074     while txt.count(')',t0)>0:
1075         t1=txt.find(')',t0)
1076         nt0=txt[t0:t1+1]
1077         t2=nt0[nt0.find('(')+1:-1]
1078         val=nt0[:nt0.find('(')]
1079         while t2.find('  ')!=-1:
1080                  t2=t2.replace('  ',' ')
1081         t2=t2.replace(' ',',')
1082         if t2.find('e'):
1083               t3=t2.split(',')
1084               t2='' 
1085               for t in t3 :
1086                    t=str(float(t)) 
1087               t2=str(t3).replace(']','').replace('[','').replace('\'','')
1088         if val=='rotate' :
1089            t3=t2.split(',')
1090            if len(t3)==3:
1091               tlist.append('translate('+t3[1]+','+t3[2]+')')
1092               tlist.append('rotate('+t3[0]+')')
1093               tlist.append('translate(-'+t3[1]+',-'+t3[2]+')')
1094         else:
1095               tlist.append(val+'('+t2+')')
1096         t0=t1+1
1097     return tlist
1098
1099 # 0.4.1 : apply transform stack
1100 def courbe_TRANSFORM(Courbe,proprietes):
1101     # 1/ deplier le STACK
1102     #   créer une matrice pour chaque transformation    
1103     ST=[]
1104     #print proprietes['stack'] 
1105     for st in proprietes['stack'] :
1106         if st and  type(st)==list:
1107           for t in st:
1108                exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(t)[0]
1109                ST.append(T)
1110         elif st :
1111            exec "a,b,c=%s;T=Mathutils.Matrix(a,b,c)"%control_CONTAINT(st)[0]
1112            ST.append(T)              
1113     if 'transform' in proprietes.keys():
1114         for trans in control_CONTAINT(proprietes['transform']):
1115            exec """a,b,c=%s;T=Mathutils.Matrix(a,b,c)"""%trans
1116            ST.append(T)
1117            #print ST
1118     ST.reverse()
1119     for n in proprietes['n']:
1120      if n in Courbe.keys():
1121         for bez0 in Courbe[n].beziers_knot:
1122           bez=bez0.co
1123           for b in [0,2,4]:
1124               for t in ST:
1125                  v=Mathutils.Vector([bez[b],bez[b+1],1.0])
1126                  #v=Mathutils.MatMultVec(t, v)
1127                  v=t * v
1128                  bez[b]=v[0]
1129                  bez[b+1]=v[1]          
1130
1131 def filtre(d):
1132     for nn in d:
1133        if '0123456789.'.find(nn)==-1:
1134           d=d.replace(nn,"")
1135     return d
1136
1137 def get_BOUNDBOX(BOUNDINGBOX,SVG):
1138     if 'viewbox' not in SVG.keys():
1139         h=float(filtre(SVG['height']))
1140         if DEBUG==1 : print 'h : ',h
1141         w=float(filtre(SVG['width']))
1142         if DEBUG==1 : print 'w :',w
1143         BOUNDINGBOX['rec']=[0.0,0.0,w,h]
1144         r=BOUNDINGBOX['rec']
1145         BOUNDINGBOX['coef']=w/h       
1146     else:
1147         viewbox=SVG['viewbox'].split()
1148         BOUNDINGBOX['rec']=[float(viewbox[0]),float(viewbox[1]),float(viewbox[2]),float(viewbox[3])]
1149         r=BOUNDINGBOX['rec']
1150         BOUNDINGBOX['coef']=(r[2]-r[0])/(r[3]-r[1])       
1151     return BOUNDINGBOX
1152
1153 # 0.4.1 : attributs ex : 'id=', 'transform=', 'd=' ...
1154 def collecte_ATTRIBUTS(data):
1155     data=data.replace('  ',' ')
1156     ELEM={'TYPE':data[1:data.find(' ')]}
1157     t1=len(data)
1158     t2=0
1159     ct=data.count('="')
1160     while ct>0:
1161         t0=data.find('="',t2)
1162         t2=data.find(' ',t2)+1
1163         id=data[t2:t0]
1164         t2=data.find('"',t0+2)
1165         if id!='d':
1166            exec "ELEM[id]=\"\"\"%s\"\"\""%(data[t0+2:t2].replace('\\','/'))
1167         else:
1168               exec "ELEM[id]=[%s,%s]"%(t0+2,t2) 
1169         ct=data.count('="',t2)
1170     return ELEM
1171
1172 # --------------------------------------------
1173 # 0.4.1 : to avoid to use sax and ths xml  
1174 #         tools of the complete python
1175 # --------------------------------------------
1176 def contruit_HIERARCHIE(t):
1177     global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
1178     TRANSFORM=0
1179     t=t.replace('\t',' ')
1180     while t.find('  ')!=-1:
1181           t=t.replace('  ',' ')
1182     n0=0      
1183     t0=t1=0
1184     baliste=[]
1185     balisetype=['?','?','/','/','!','!']
1186     BALISES=['D',  #DECL_TEXTE',
1187              'D',  #DECL_TEXTE',
1188              'F',  #FERMANTE',
1189              'E',  #ELEM_VIDE',
1190              'd',  #DOC',
1191              'R',  #REMARQUES',
1192              'C',  #CONTENU',
1193              'O'   #OUVRANTE'
1194              ]
1195     STACK=[]
1196     while t1<len(t) and t0>-1:
1197       t0=t.find('<',t0)
1198       t1=t.find('>',t0)
1199       ouvrante=0
1200       #--------------------
1201       # 0.4.4 , add 'else:' and 'break' to the 'if' statement
1202       #--------------------
1203       if t0>-1 and t1>-1:
1204           if t[t0+1] in balisetype:
1205              b=balisetype.index(t[t0+1])
1206              if t[t0+2]=='-': 
1207                b=balisetype.index(t[t0+1])+1
1208              balise=BALISES[b]
1209              if b==2:
1210                  parent=STACK.pop(-1)
1211                  if parent!=None and TRANSFORM>0:
1212                      TRANSFORM-=1
1213           elif t[t1-1] in balisetype:
1214             balise=BALISES[balisetype.index(t[t1-1])+1]
1215           else:
1216             t2=t.find(' ',t0)  
1217             if t2>t1: t2=t1
1218             ouvrante=1
1219             NOM=t[t0+1:t2]
1220             if t.find('</'+NOM)>-1:
1221                balise=BALISES[-1]
1222             else:
1223                balise=BALISES[-2]
1224           if balise=='E' or balise=='O':
1225              proprietes=collecte_ATTRIBUTS(t[t0:t1+ouvrante])
1226              if  balise=='O' and 'transform' in proprietes.keys():
1227                  STACK.append(proprietes['transform'])
1228                  TRANSFORM+=1   
1229              elif balise=='O' : 
1230                  STACK.append(None)
1231              proprietes['stack']=STACK[:]
1232              D=[] 
1233              if proprietes['TYPE'] in ['path'] and (proprietes['d'][1]-proprietes['d'][0]>1):
1234                  D=list_DATA(t[proprietes['d'][0]+t0:proprietes['d'][1]+t0])
1235              elif proprietes['TYPE'] in OTHERSSHAPES:
1236                  exec "D=%s(proprietes)"% proprietes['TYPE']
1237              if len(D)>0:
1238                  cursor=0
1239                  proprietes['n']=[]
1240                  for cell in D: 
1241                    if DEBUG==2 : print 'cell : ',cell ,' --'                   
1242                    if len(cell)>=1 and cell[0] in TAGcourbe:
1243                        prop=''
1244                        if cell[0] in ['m','M']: 
1245                                      prop=',proprietes'
1246                        exec """courbes,n0,CP=Actions[cell]([cell,cursor], D, n0,CP%s)"""%prop
1247                    cursor+=1
1248                  if TRANSFORM>0 or 'transform' in proprietes.keys() :
1249                      courbe_TRANSFORM(courbes.ITEM,proprietes)
1250              elif proprietes['TYPE'] in ['svg'] :
1251                    BOUNDINGBOX = get_BOUNDBOX(BOUNDINGBOX,proprietes)          
1252       else:
1253          #--------------------
1254          # 0.4.4 
1255          #--------------------
1256          break
1257       t1+=1
1258       t0=t1             
1259                         
1260 def scan_FILE(nom):
1261   global CP, courbes, SCALE, DEBUG, BOUNDINGBOX, scale_, tagTRANSFORM
1262   dir,name=split(nom)
1263   name=name.split('.')
1264   result=0
1265   t=filtreFICHIER(nom)
1266   if t!='false':
1267      Blender.Window.EditMode(0)
1268      if not SHARP_IMPORT:
1269          warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" 
1270          scale_ = Blender.Draw.PupMenu(warning)
1271      # 0.4.1 : to avoid to use sax and the xml  
1272      #         tools of the complete python
1273      contruit_HIERARCHIE(t)
1274      r=BOUNDINGBOX['rec']
1275      if scale_==1:
1276         SCALE=1.0
1277      elif scale==2:
1278         SCALE=r[2]-r[0]
1279      elif scale_==3:
1280         SCALE=r[3]-r[1]
1281   courbes.number_of_items=len(courbes.ITEM.keys())
1282   for k in courbes.ITEM.keys():
1283      courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
1284
1285   #--------------------
1286   # 0.4.5
1287   #--------------------
1288   CVS=2
1289   if BLversion>=238 : 
1290      warning = "CVS version you can import as : %t| Blender internal, experimental ? %x1 |  Old proofed method, import using Blender OBJ format  %x2" 
1291      CVS=Blender.Draw.PupMenu(warning)
1292
1293   if courbes.number_of_items>0 and CVS==2:
1294      if len(PATTERN.keys() )>0:
1295         if DEBUG == 3 : print len(PATTERN.keys() )
1296      t=create_GEOtext(courbes)
1297      save_GEOfile(dir,name[0],t)
1298      Open_GEOfile(dir,name[0])
1299
1300   elif courbes.number_of_items>0 and CVS==1 :
1301            #--------------------
1302      # 0.4.5
1303      #--------------------
1304            createCURVES(courbes)
1305         
1306   else:
1307      pass      
1308     
1309 def  ajustement(v,s):
1310      
1311      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])
1312      return [a/s,-b/s,c/s,-d/s,e/s,-f/s]
1313
1314 #=====================================================================
1315 #====================== SVG format mouvements ========================
1316 #=====================================================================
1317
1318 #=====================================================================
1319 # une sorte de contournement qui permet d'utiliser la fonction
1320 # et de documenter les variables Window.FileSelector
1321 #=====================================================================
1322 def fonctionSELECT(nom):
1323     scan_FILE(nom)
1324
1325 if __name__=='__main__':
1326    Blender.Window.FileSelector (fonctionSELECT, 'SELECT a .SVG FILE')