Comment installer et programmer des scripts Python dans Inkscape ? VVPix v0.10 (décembre 2008) Table des matières 1 Introduction 1 2 Installations 2 2.1 Installation d’Inkscape avec Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.2 Installation de nouveaux scripts Python dans Inkscape . . . . . . . . . . . . . . . . . . . . 2 2.3 Localisation des nouveaux scripts dans Inkscape . . . . . . . . . . . . . . . . . . . . . . . 2 3 Programmation Python 1 3 3.1 Saisie de valeurs grâce à une interface utilisateur . . . . . . . . . . . . . . . . . . . . . . . 3 3.2 Dessin des formes de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.3 Accès à la documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Introduction Inkscape est un logiciel de dessin vectoriel, gratuit et multiplateformes (Linux, Mac, Windows). Ce document indique succintement comment écrire des scripts Python pour ce logiciel. J’ai écrit ce document en faisant des tests sur la version 0.46 d’Inkscape, sous Windows 2000 SP4. www.VVPix.com 2 2.1 Installations Installation d’Inkscape avec Windows La dernière version d’Inkscape est disponible ici : http://www.inkscape.org/. L’installation ne pose aucun problème particulier. Python est installé avec Inkscape et il ne faut faire aucune installation complémentaire pour pouvoir bénéficier des scripts Python avec Inkscape. 2.2 Installation de nouveaux scripts Python dans Inkscape Un script Python pour Inkscape est constitué d’au moins deux fichiers : – Un fichier .inx : – Un fichier .py Ces scripts sont localisés dans le dossier share/extensions d’Inkscape. Par exemple, le chemin par défaut dans Windows est : C:\Program Files\Inkscape\share\extensions Avec Gimp et Blender, on peut choisir où placer ses greffons pour éviter de les mélanger avec ceux livrés avec le logiciel, mais apparemment ce n’est pas encore le cas avec Inkscape v0.46. 2.3 Localisation des nouveaux scripts dans Inkscape La localisation d’un script s’effectue grâce au fichier .inx. Un fichier “inx” est un fichier XML dont on trouve un schéma DTD sur le site officiel d’Inkscape. Voici par exemple le fichier hello.inx, dérivé de l’exemple “Hello world” posté sur le wiki de www. inkscape.org. Listing 1 – Exemple de fichier “.inx” : le fichier “Hello.inx” 1 3 5 7 9 11 13 15 <inkscape−e x t e n s i o n> < name>H e l l o< / name> <i d>org . e k i p s . f i l t e r . h e l l o< / i d> <dependency t y p e = ” e x e c u t a b l e ” l o c a t i o n = ” e x t e n s i o n s ”>h e l l o . py< / dependency> <dependency t y p e = ” e x e c u t a b l e ” l o c a t i o n = ” e x t e n s i o n s ”>i n k e x . py< / dependency> <param name= ” s t r T e x t e ” t y p e = ” s t r i n g ” g u i −t e x t = ” S a i s i s s e z l e t e x t e a e c r i r e : ”> H e l l o< / param> < e f f e c t> <o b j e c t −t y p e> a l l< / o b j e c t −t y p e> <e f f e c t s −menu> <submenu name= ” Exemples ” /> < / e f f e c t s −menu> < / e f f e c t> < s c r i p t> <command r e l d i r = ” e x t e n s i o n s ” i n t e r p r e t e r = ” python ”>h e l l o . py< / command> < / s c r i p t> < / inkscape−e x t e n s i o n> La ligne 2 du listing 1 donne le nom d’appel du script dans le menu d’Inkscape (“Hello”). Les lignes 9 et 10 indiquent que le script sera inséré dans le menu “Effect - Exemples” d’Inkscape (voir figure 1 ci-après). La ligne 4 indique quel fichier Python est relié au fichier .py (hello.py). page 2 / 8 www.VVPix.com F IG . 1 – Script “Hello” dans le menu “Effect” d’Inkscape ATTENTION : Un moyen très simple d’écrire un fichier “.inx” qui ne fonctionne pas est d’ajouter un accent dans n’importe laquelle de ses lignes. Le fichier “.inx” que j’ai utilisé est écrit avec le jeu de caractère CP1252 (≈ ISO 8859-15). 3 Programmation Python Dans les fichiers Python, comme dans les fichiers “.inx”, il ne faut utiliser aucun accent si on utilise le jeu de caractère CP1252 (≈ ISO 8859-15). 3.1 Saisie de valeurs grâce à une interface utilisateur Le fichier “Hello.inx”, listing 1, permet aussi de créer l’interface graphique figure 2, juste avec la ligne 6. On voit la récupération de cette variable “strTexte” dans le listing 2, ligne 55 et 56. F IG . 2 – Interface utilisateur générée par le fichier “Hello.inx” Listing 2 – Fichier “hello.py” (partiel) # ! / u s r / b i n / env python 2 4 6 8 10 # Les deux l i g n e s s u i v a n t s o n t n e c e s s a i r e s seulement s i l e s c r i p t n ’ e s t pas # d i r e c t e m e n t dans l e d o s s i e r d ’ i n s t a l l a t i o n i m p o r t sys #sys . path . append ( ’ / u s r / share / inkscape / e x t e n s i o n s ’ ) # U t i l i s a t i o n du module i n k e x avec des e f f e t s p r e d e f i n i s import inkex # Le module s i m p l e s t y l e f o u r n i t des f o n c t i o n s pour l e p a r s i n g des s t y l e s page 3 / 8 www.VVPix.com from s i m p l e s t y l e i m p o r t ∗ 12 14 16 18 20 22 24 26 28 30 c l a s s CHello ( i n k e x . E f f e c t ) : ””” Exemple Inkscape Cree un nouveau calque e t dessine des elements de base ””” def init ( self ) : ””” Constructeur D e f i n i t l ’ o p t i o n ”−− s t r T e x t e ” du s c r i p t ””” # Appel du c o n s t r u c t e u r . inkex . E f f e c t . init ( self ) # D e f i n i t l a chaine d ’ o p t i o n ”−− s t r T e x t e ” avec l e r a c c o u r c i ”−w” e t # l a v a l e u r par d e f a u t ” H e l l o ” . s e l f . O p t i o n P a r s e r . a d d o p t i o n ( ’−w ’ , ’−−s t r T e x t e ’ , a c t i o n = ’ s t o r e ’ , type = ’ s t r i n g ’ , dest = ’ strTexte ’ , d e f a u l t = ’ Hello ’ , h e l p = ’ Message a e c r i r e ? ’ ) 32 34 36 38 40 42 44 46 48 def e f f e c t ( s e l f ) : ””” Fonction p r i n c i p a l e Surchage l a f o n c t i o n de l a c l a s s e de base Dessine quelques elements s u r l e docuement SVG ””” # Recupere l e document SVG p r i n c i p a l svg = s e l f . document . g e t r o o t ( ) # Recuperation de l a h a u t e u r e t de l a l a r g e u r de l a f e u i l l e w i d t h = i n k e x . u n i t t o u u ( svg . g e t ( ’ w i d t h ’ ) ) h e i g h t = i n k e x . u n i t t o u u ( svg . a t t r i b [ ’ h e i g h t ’ ] ) # C r e a t i o n d ’ un nouveau calque l a y e r = i n k e x . e t r e e . SubElement ( svg , ’ g ’ ) l a y e r . s e t ( i n k e x . addNS ( ’ l a b e l ’ , ’ inkscape ’ ) , ’ Layer t e x t e ’ ) l a y e r . s e t ( i n k e x . addNS ( ’ groupmode ’ , ’ inkscape ’ ) , ’ l a y e r ’ ) 50 52 54 56 # C r e a t i o n d ’ un element t e x t e t e x t e = i n k e x . e t r e e . Element ( i n k e x . addNS ( ’ t e x t ’ , ’ svg ’ ) ) # − Recuperation de l a v a l e u r de l a v a r i a b l e ” s t r T e x t e ” s a i s i e dans l a # b o i t e de d i a l o g u e strVal = s e l f . options . strTexte texte . text = strVal [...] 58 60 # Execute l a f o n c t i o n ” e f f e c t ” de l a c l a s s e ” CHello ” h e l l o = CHello ( ) hello . affect () page 4 / 8 www.VVPix.com 3.2 Dessin des formes de base Le script listing 3 (page 5), associé au fichier inx, listing 1, produit l’image figure 3. F IG . 3 – Résultat du script “Hello.py”, listing 3 Listing 3 – Fichier “hello.py” 1 # ! / u s r / b i n / env python 3 # Les deux l i g n e s s u i v a n t s o n t n e c e s s a i r e s seulement s i l e s c r i p t n ’ e s t pas # d i r e c t e m e n t dans l e d o s s i e r d ’ i n s t a l l a t i o n i m p o r t sys #sys . path . append ( ’ / u s r / share / inkscape / e x t e n s i o n s ’ ) 5 page 5 / 8 www.VVPix.com 7 9 11 13 15 17 19 21 23 # U t i l i s a t i o n du module i n k e x avec des e f f e t s p r e d e f i n i s import inkex # Le module s i m p l e s t y l e f o u r n i t des f o n c t i o n s pour l e p a r s i n g des s t y l e s from s i m p l e s t y l e i m p o r t ∗ c l a s s CHello ( i n k e x . E f f e c t ) : ””” Exemple Inkscape Cree un nouveau calque e t dessine des elements de base ””” def init ( self ) : ””” Constructeur D e f i n i t l ’ o p t i o n ”−− s t r T e x t e ” du s c r i p t ””” # Appel du c o n s t r u c t e u r . inkex . E f f e c t . init ( self ) 25 27 29 31 33 35 37 39 # D e f i n i t l a chaine d ’ o p t i o n ”−− s t r T e x t e ” avec l e r a c c o u r c i ”−w” e t # l a v a l e u r par d e f a u t ” H e l l o ” . s e l f . O p t i o n P a r s e r . a d d o p t i o n ( ’−w ’ , ’−−s t r T e x t e ’ , a c t i o n = ’ s t o r e ’ , type = ’ s t r i n g ’ , dest = ’ strTexte ’ , d e f a u l t = ’ Hello ’ , h e l p = ’ Message a e c r i r e ? ’ ) def e f f e c t ( s e l f ) : ””” Fonction p r i n c i p a l e Surchage l a f o n c t i o n de l a c l a s s e de base Dessine quelques elements s u r l e docuement SVG ””” # Recupere l e document SVG p r i n c i p a l svg = s e l f . document . g e t r o o t ( ) 41 43 # Recuperation de l a h a u t e u r e t de l a l a r g e u r de l a f e u i l l e w i d t h = i n k e x . u n i t t o u u ( svg . g e t ( ’ w i d t h ’ ) ) h e i g h t = i n k e x . u n i t t o u u ( svg . a t t r i b [ ’ h e i g h t ’ ] ) 45 47 49 51 53 55 # C r e a t i o n d ’ un nouveau calque l a y e r = i n k e x . e t r e e . SubElement ( svg , ’ g ’ ) l a y e r . s e t ( i n k e x . addNS ( ’ l a b e l ’ , ’ inkscape ’ ) , ’ Layer t e x t e ’ ) l a y e r . s e t ( i n k e x . addNS ( ’ groupmode ’ , ’ inkscape ’ ) , ’ l a y e r ’ ) # C r e a t i o n d ’ un element t e x t e t e x t e = i n k e x . e t r e e . Element ( i n k e x . addNS ( ’ t e x t ’ , ’ svg ’ ) ) # − Recuperation de l a v a l e u r de l a v a r i a b l e ” s t r T e x t e ” s a i s i e dans l a # b o i t e de d i a l o g u e strVal = s e l f . options . strTexte texte . text = strVal 57 59 61 63 # Reglages i n i t i a u x x o r g = h e i g h t / 10 y o r g = w i d t h / 10 pas x = w i d t h / 6 pas y = w i d t h / 10 nLargeurTrait = 5 67 # Set t e x t p o s i t i o n t o c e n t e r o f document . texte . set ( ’ x ’ , s t r ( x org ) ) texte . set ( ’ y ’ , s t r ( y org ) ) 69 # Center t e x t h o r i z o n t a l l y w i t h CSS s t y l e . 65 page 6 / 8 www.VVPix.com 71 73 s t y l e = { ’ t e x t −a l i g n ’ : ’ l e f t ’ , \ ’ t e x t −anchor ’ : ’ t o p ’ , \ ’ f o n t −s i z e ’ : ’ 48 p t ’ , \ ’ f i l l ’ : ’ rgb ( 2 5 5 , 0 , 0 ) ’ } texte . set ( ’ s t y l e ’ , formatStyle ( s t y l e ) ) 75 77 79 81 83 85 87 # A j o u t e l e t e x t e au calque l a y e r . append ( t e x t e ) # C r e a t i o n d ’ un r e c t a n g l e y o r g += pas y r e c t a n g l e = i n k e x . e t r e e . Element ( i n k e x . addNS ( ’ r e c t ’ , ’ svg ’ ) ) rectangle . set ( ’ x ’ , s t r ( x org ) ) rectangle . set ( ’ y ’ , s t r ( y org ) ) r e c t a n g l e . s e t ( ’ w i d t h ’ , s t r ( pas x − pas x / 1 0 . 0 ) ) r e c t a n g l e . s e t ( ’ h e i g h t ’ , s t r ( pas y − pas y / 1 0 . 0 ) ) r e c t a n g l e . s e t ( ’ f i l l ’ , ’ rgb ( 0 , 255 , 0 ) ’ ) ; # c o u l e u r de r e m p l i s s a g e r e c t a n g l e . s e t ( ’ s t r o k e ’ , ’ b l u e ’ ) ; # c o u l e u r du c o n t o u r r e c t a n g l e . s e t ( ’ s t r o k e −w i d t h ’ , s t r ( n L a r g e u r T r a i t ) ) ; # l a r g e u r du c o n t o u r 89 91 93 95 97 99 101 103 105 # A j o u t du r e c t a n g l e s u r l e calque l a y e r . append ( r e c t a n g l e ) # C r e a t i o n d ’ un c e r c l e y o r g += pas y c e r c l e = i n k e x . e t r e e . Element ( i n k e x . addNS ( ’ c i r c l e ’ , ’ svg ’ ) ) nRayon = ( pas y − pas y / 1 0 . 0 ) / 2 . 0 y o r g += 2 ∗ nRayon c e r c l e . s e t ( ’ cx ’ , s t r ( x o r g ) ) c e r c l e . s e t ( ’ cy ’ , s t r ( y o r g ) ) c e r c l e . s e t ( ’ r ’ , s t r ( nRayon ) ) c e r c l e . s e t ( ’ f i l l ’ , ’ #0000FF ’ ) ; c e r c l e . s e t ( ’ s t r o k e ’ , ’ red ’ ) ; c e r c l e . s e t ( ’ s t r o k e −w i d t h ’ , s t r ( n L a r g e u r T r a i t ) ) ; # A j o u t du c e r c l e s u r l e calque l a y e r . append ( c e r c l e ) 107 109 111 113 115 117 # C r e a t i o n d ’ une l i g n e y o r g += pas y l i g n e = i n k e x . e t r e e . Element ( i n k e x . addNS ( ’ l i n e ’ , ’ svg ’ ) ) nRayon = ( pas y − pas y / 1 0 . 0 ) / 2 . 0 y o r g += nRayon l i g n e . s e t ( ’ x1 ’ , s t r ( x o r g ) ) l i g n e . s e t ( ’ y1 ’ , s t r ( y o r g ) ) l i g n e . s e t ( ’ x2 ’ , s t r ( x o r g + pas x ) ) l i g n e . s e t ( ’ y2 ’ , s t r ( y o r g + pas y ) ) ; l i g n e . s e t ( ’ s t r o k e ’ , ’ rgb ( 1 0 , 1 0 , 1 0 ) ’ ) ; l i g n e . s e t ( ’ s t r o k e −w i d t h ’ , s t r ( n L a r g e u r T r a i t ) ) ; 119 121 # A j o u t de l a l i g n e s u r l e calque l a y e r . append ( l i g n e ) 123 125 # Execute l a f o n c t i o n ” e f f e c t ” de l a c l a s s e ” CHello ” h e l l o = CHello ( ) hello . affect () page 7 / 8 www.VVPix.com 3.3 Accès à la documentation Avec Inkscape, le problème est, pour l’instant, que je n’ai pas trouvé de documentation de l’API InkscapePython. On trouve seulement quelques listings éparpillés sur internet sans explications. J’ai passé beaucoup de temps juste pour dessiner un rectangle et en changer les couleurs, alors que c’est une opération très simple. Inkscape repose sur le format SVG et le meilleur moyen que j’ai trouvé pour récupérer la documentation des attributs des formes de base, par exemple, a été de me référer au site du W3C sur le format SVG. Ici par exemple : – http://www.w3.org/TR/SVG/shapes.html – http://www.w3.org/Graphics/SVG/IG/resources/StateOfArt-Dailey.html F IG . 4 – Détail des attributs des figures de base SVG sur le site W3C page 8 / 8