Skip to content
sgmanohar edited this page Feb 18, 2016 · 5 revisions

#Python quick-scripting extension for Inkscape

I thought I should share my Inkscape plugin.

It's designed for users who are also programmers. It's useful for minor automation. It allows running very short Python script fragments on the fly. It works by calling "exec()" on your line of code, with a variable "n" set to the current node.


It has two components:
  1. an XPATH query, which iterates over a set of objects (or iterate over the current selection)
  2. a short fragment of Python, which you enter, and is executed for each object.

Instructions

Unzip the files into your Inkscape "share/extensions" folder. On windows this is something like "C:\Program Files\Inkscape\share\extensions". On Linux, it is something like "/usr/share/inkscape/share/extensions". When you start Inkscape, Go to "Extensions/Sanjay/Custom Iterator".

Example

 for i in p:
   if len(i)>1: 
     i[1][1]+=x*sin(i[1][0]/10.)

To use this, delete the "XPath" field in the dialog, and select an object. This makes the variable n refer to the selected object. Check the box "Process paths" (which creates the p variable, parsing the nodes of the selected path into a python array). Enter each line in a separate code field, with indents as spaces at the start of the field. The for loop iterates over the control points in each path, and for points which have coordinates, it disturbs the y-coordinate by a sine wave dependent upon the x-coordinate.

 c=n
 for i in range(18):
   c=copy.deepcopy(c)
   applyTransformToNode(parseTransform('rotate(20)'),c)
   self.current_layer.append(c)

This starts off with the selected item, makes a duplicate, and rotates it 20 degrees around the origin. It does this 18 times.

using XPath

I've given a few examples of how to use XPath to do 'and', 'not', 'intersection' searches. It is quite powerful but not intuitive. If you're not familiar with XPath, you can do all of those things from within the python commands. The XPath requires namespaces on every tag, so you can use the original "svg:" namespace or the abbreviation "s:".

What sort of code can I write?

The 5 lines of python are concatenated into a short script. You can actually have more lines if you use "\n" in your scripts and turn on "process escapes in python command". You can toggle each line on and off, to switch individual commands.

  • If "Skip over errors" is selected, then it will execute your code on each node, committing only those nodes which didn't give an error. If it is not selected, then the script stops, displays the error, and does not commit any changes.
  • If "Process escapes in python" is on, then each line can store multi-line commands, if you use "\n" and/or "\t".
  • Parse path coordinates will examine the "d" attribute of any path, and call "parsePath". The result is stored in "p", and is an array of path nodes. Each node is ['c', (x,y)], representing the command letter, and absolute coordinates. You can edit "p".
  • You have access to all functions in
    • "math" (sin, cos, tan, atan, rand, floor etc.)
    • "inkex" (etree, addNS, unittouu, uniqueId, createGuide, getNamedView etc)
    • "simplepath" (translatePath, scalePath, rotatePath),
    • "simpletransform" (computeBBox)
    • "simplestyle" (svgcolors dictionary, parseColor, formatColoria, formatColor3i, formatColorfa, formatColor3f, isColor),
    • "pturtle", and "bezmisc".
    • Additionally, 'self' is defined (with properties such as 'selected', 'current_layer', 'view_center', 'document', 'original_document').
    • You can also use "print" commands for debugging, since stdout is mapped to the error dialog that pops up after the script completes.
    Some further examples of these commands are given under "Commands".

    So, it's basically quite a lot more powerful than the built-in find/replace tool. And quicker than writing your own extension. There is brief documentation in the dialog box.

    Sanjay Manohar 2014

    ##Known issues:

    1. Inkscape 48.3 seems to break in Ubuntu, but works well on Windows; 48.4 should be fine.
    2. If "parse path" is on, changes made by calls to "n.set('d',something)" are discarded. Path changes should be made only to "p", in this case.
    3. Currently, if changes are made to the style using 's', then any changes to the style made by calls to "n.set('style',something)" are discarded. It is therefore best to make style changes to "s".
    4. Attribute deletions from "a" are not processed at present.
    5. Pure style deletions from "s" are not processed at present.