Difference between revisions of "PythonEffectTutorial"
m (Just creating a page.) |
(Initial page content.) |
||
Line 1: | Line 1: | ||
Here will be | Effect extensions in Inkscape means a simple programs or scripts that reads input SVG file transforms it somehow and prints it to the standart output. | ||
We will write simple effect extension script in Python that will put "Hello World!" or "Hello <value of option>!" string in the center of document and inside a new layer. | |||
== Effect Extension Script == | |||
First of all create file ''hello_world.py'' and make them executable with Python interpreter with well-known directive: | |||
<pre> | |||
#!/usr/bin/env python | |||
</pre> | |||
Import ''inkex.py'' file with ''Effect'' base class that will do most of work for us and ''simplestyle.py'' module with support functions for working with CSS styles. We will use just ''formatStyle'' function from this module: | |||
<pre> | |||
import inkex | |||
from simplestyle import * | |||
</pre> | |||
Declare ''HelloWordEffect'' class and write a constructor where base class is initialized and script option for opition parser is defined: | |||
<pre> | |||
class HelloWorldEffect(inkex.Effect): | |||
def __init__(self): | |||
inkex.Effect.__init__(self) | |||
self.OptionParser.add_option('-w', '--what', action = 'store', | |||
type = 'string', dest = 'what', default = 'World', | |||
help = 'What would you like to greet?') | |||
</pre> | |||
Complete documentation for ''OptionParser'' class can be found at http://docs.python.org/lib/module-optparse.html. Here we just use ''add_option'' method which has as first argument short option name, as second argument long option name and then a few other arguments with this meaning: | |||
* ''action'' - An action which should be done with option value. In this case we use action ''store'' which will store option value in ''self.options.<destination>'' attribute. | |||
* ''type'' - Type of option value. We use string here. | |||
* ''dest'' - Destination of option action specified by ''action'' argument. Using ''what'' value we say that we want to store option value to self.options.what attribute. | |||
* ''default'' - Defalut value for this option if it is not specified. | |||
* ''help'' - A help string that will be displayed if script will be given no arguments or some option or argument will have wrong syntax. | |||
Inkscape will create a GUI form with widgets for all specified options and prefill them with specified default values using ''.inx''. file for this extenstion which we will write later. | |||
We need to override only one ''Effect'' class method to provide effect functionality: | |||
<pre> | |||
def effect(self): | |||
what = self.options.what | |||
</pre> | |||
As you can mention we just stored ''--what'' option value to ''what'' variable. | |||
Now we will finally start to do something. We will work with XML representation of SVG document via ''self.document'' attribute. It is of ''Document'' class type from ''xml.dom'' module. Complete documentation for this module can be found at http://docs.python.org/lib/module-xml.dom.html. | |||
First get SVG document ''svg'' element and its dimensions: | |||
<pre> | |||
svg = self.document.getElementsByTagName('svg')[0] | |||
width = parseLength(svg.getAttribute('width'))[0] | |||
height = parseLength(svg.getAttribute('height'))[0] | |||
</pre> | |||
Function ''getElementsByTagName'' returns list of all found elements of this name so we just use first of them. | |||
We used ''parseLength'' function which returns tuple with float value and string with unit from its parameter containg CSS lenght type value (for example: 10px, 10pt, 10, 10cm, ...). Function will be defined later. | |||
Create SVG group element and "convert" it to layer using Inkscape SVG extenstions: | |||
<pre> | |||
layer = self.document.createElement('g') | |||
layer.setAttribute('inkscape:label', 'Hello %s Layer' % (what)) | |||
layer.setAttribute('inkscape:groupmode', 'layer') | |||
</pre> | |||
Create SVG text element and its value containing "Hello World"" string: | |||
<pre> | |||
text = self.document.createElement('text') | |||
value = self.document.createTextNode('Hello %s!' % (what)) | |||
</pre> | |||
Set position of text to center of SVG document: | |||
<pre> | |||
text.setAttribute('x', str(width / 2)) | |||
text.setAttribute('y', str(height / 2)) | |||
</pre> | |||
If we want center text on its position we will define CSS style of SVG ''text'' element. Actually use ''text-anchor'' SVG extension to CSS styles to do that work: | |||
<pre> | |||
style = {'text-align' : 'center', 'text-anchor' : 'middle'} | |||
text.setAttribute('style', formatStyle(style)) | |||
</pre> | |||
Finally connect all created elements together and put them in SVG document: | |||
<pre> | |||
text.appendChild(value) | |||
layer.appendChild(text) | |||
svg.appendChild(layer) | |||
</pre> | |||
We just defined a class of our effect extension so we have to create an instance of it and execute it in main control flow: | |||
<pre> | |||
effect = HelloWorldEffect() | |||
effect.affect() | |||
</pre> | |||
As mentioned before we need to define ''parseLength'' function. Probably this kind of function and other similar should be a part of a new support module for extensions creating: | |||
<pre> | |||
def parseLength(length): | |||
if len(length) >= 1: | |||
if length[-1:] == '%': | |||
return (float(length[:-1]), length[-1:]) | |||
if len(length) >= 2: | |||
if length[-2:] in ('px', 'pt', 'em', 'cm', 'mm'): | |||
return (float(length[:-2]), length[-2:]) | |||
return (float(length), '') | |||
</pre> | |||
== Extension Description File == | |||
To include script in Inkscape's main menu create ''hello_world.inx'' file describing script evokation. | |||
<pre> | |||
<inkscape-extension> | |||
<_name>Hello World!</_name> | |||
<id>org.ekips.filter.hello_world</id> | |||
<dependency type="executable" location="extensions">hello_world.py</dependency> | |||
<dependency type="executable" location="extensions">inkex.py</dependency> | |||
<param name="what" type="string" _gui-text="What would you like to greet?">World</param> | |||
<effect> | |||
<object-type>all</object-type> | |||
<effects-menu> | |||
<submenu _name="Examples"/> | |||
</effects-menu> | |||
</effect> | |||
<script> | |||
<command reldir="extensions" interpreter="python">hello_world.py</command> | |||
</script> | |||
</inkscape-extension> | |||
</pre> | |||
Create ''<param>'' element for every option of a script and ''<dependency>'' for every included module which is not from Python standard library. Inkscape will search for this modules in directory with script. ''<effect>'' element and its descendants defines name of menu item evoking our new "Hello World!" extension. | |||
== Installation == | |||
To install a new extenstion just put ''hello_world.py'' and ''hello_world.inx'' files with all dependency modules to ''<path_to_inkscape>/extensions'' or ''~/.inkscape/extensions'' directory and start Inkscape. A new menu item ''Hello World!'' in ''Effects->Examples'' menu should appear. | |||
[[User:Blackhex|Blackhex]] 11:59, 26 April 2007 (UTC) |
Revision as of 11:59, 26 April 2007
Effect extensions in Inkscape means a simple programs or scripts that reads input SVG file transforms it somehow and prints it to the standart output.
We will write simple effect extension script in Python that will put "Hello World!" or "Hello <value of option>!" string in the center of document and inside a new layer.
Effect Extension Script
First of all create file hello_world.py and make them executable with Python interpreter with well-known directive:
#!/usr/bin/env python
Import inkex.py file with Effect base class that will do most of work for us and simplestyle.py module with support functions for working with CSS styles. We will use just formatStyle function from this module:
import inkex from simplestyle import *
Declare HelloWordEffect class and write a constructor where base class is initialized and script option for opition parser is defined:
class HelloWorldEffect(inkex.Effect): def __init__(self): inkex.Effect.__init__(self) self.OptionParser.add_option('-w', '--what', action = 'store', type = 'string', dest = 'what', default = 'World', help = 'What would you like to greet?')
Complete documentation for OptionParser class can be found at http://docs.python.org/lib/module-optparse.html. Here we just use add_option method which has as first argument short option name, as second argument long option name and then a few other arguments with this meaning:
- action - An action which should be done with option value. In this case we use action store which will store option value in self.options.<destination> attribute.
- type - Type of option value. We use string here.
- dest - Destination of option action specified by action argument. Using what value we say that we want to store option value to self.options.what attribute.
- default - Defalut value for this option if it is not specified.
- help - A help string that will be displayed if script will be given no arguments or some option or argument will have wrong syntax.
Inkscape will create a GUI form with widgets for all specified options and prefill them with specified default values using .inx. file for this extenstion which we will write later.
We need to override only one Effect class method to provide effect functionality:
def effect(self): what = self.options.what
As you can mention we just stored --what option value to what variable.
Now we will finally start to do something. We will work with XML representation of SVG document via self.document attribute. It is of Document class type from xml.dom module. Complete documentation for this module can be found at http://docs.python.org/lib/module-xml.dom.html.
First get SVG document svg element and its dimensions:
svg = self.document.getElementsByTagName('svg')[0] width = parseLength(svg.getAttribute('width'))[0] height = parseLength(svg.getAttribute('height'))[0]
Function getElementsByTagName returns list of all found elements of this name so we just use first of them.
We used parseLength function which returns tuple with float value and string with unit from its parameter containg CSS lenght type value (for example: 10px, 10pt, 10, 10cm, ...). Function will be defined later.
Create SVG group element and "convert" it to layer using Inkscape SVG extenstions:
layer = self.document.createElement('g') layer.setAttribute('inkscape:label', 'Hello %s Layer' % (what)) layer.setAttribute('inkscape:groupmode', 'layer')
Create SVG text element and its value containing "Hello World"" string:
text = self.document.createElement('text') value = self.document.createTextNode('Hello %s!' % (what))
Set position of text to center of SVG document:
text.setAttribute('x', str(width / 2)) text.setAttribute('y', str(height / 2))
If we want center text on its position we will define CSS style of SVG text element. Actually use text-anchor SVG extension to CSS styles to do that work:
style = {'text-align' : 'center', 'text-anchor' : 'middle'} text.setAttribute('style', formatStyle(style))
Finally connect all created elements together and put them in SVG document:
text.appendChild(value) layer.appendChild(text) svg.appendChild(layer)
We just defined a class of our effect extension so we have to create an instance of it and execute it in main control flow:
effect = HelloWorldEffect() effect.affect()
As mentioned before we need to define parseLength function. Probably this kind of function and other similar should be a part of a new support module for extensions creating:
def parseLength(length): if len(length) >= 1: if length[-1:] == '%': return (float(length[:-1]), length[-1:]) if len(length) >= 2: if length[-2:] in ('px', 'pt', 'em', 'cm', 'mm'): return (float(length[:-2]), length[-2:]) return (float(length), '')
Extension Description File
To include script in Inkscape's main menu create hello_world.inx file describing script evokation.
<inkscape-extension> <_name>Hello World!</_name> <id>org.ekips.filter.hello_world</id> <dependency type="executable" location="extensions">hello_world.py</dependency> <dependency type="executable" location="extensions">inkex.py</dependency> <param name="what" type="string" _gui-text="What would you like to greet?">World</param> <effect> <object-type>all</object-type> <effects-menu> <submenu _name="Examples"/> </effects-menu> </effect> <script> <command reldir="extensions" interpreter="python">hello_world.py</command> </script> </inkscape-extension>
Create <param> element for every option of a script and <dependency> for every included module which is not from Python standard library. Inkscape will search for this modules in directory with script. <effect> element and its descendants defines name of menu item evoking our new "Hello World!" extension.
Installation
To install a new extenstion just put hello_world.py and hello_world.inx files with all dependency modules to <path_to_inkscape>/extensions or ~/.inkscape/extensions directory and start Inkscape. A new menu item Hello World! in Effects->Examples menu should appear.
Blackhex 11:59, 26 April 2007 (UTC)