Exporting multiple layers in Inkscape – streamlining the headset design

6 min read

Until now I had a very heavyweight process for specifying the headset for eyeskills, using OpenScad and lots of geometry. Now that I’m gradually working my way back into the project with new ideas and some fresh motivation, I want to streamline this dramatically so I don’t get bogged down in tool chain hell again.

I think the solution is to just work in straight .svg files using Inkscape. The issue that arises however, is that (for the laser cutter at least) there are several different types of passes that one wants to achieve per headset.

Some passes must be strong enough and slow enough to slice right through the card. Other passes must be weak enough and fast enough (to save time) to simply mark the card with instructions for the assembler/user. Yet other passes must score the card deeply enough to help it fold, but not so deeply that the pass becomes a cut.

The only open source software I can find that works reliably with the laser cutter I have is LaserWeb. In laser web one can superimpose multiple .svg files and assign them different pass properties (speed/strength etc.). Unfortunately, the workflow to create these multiple .svgs with all the image parts perfectly aligned is a pain. From a single .svg it’s a process of manually cutting/pasting parts each time and using save as…. there must be a better way.

The obvious solution would be to use multiple layers in an .svg and export each layer to an individual .svg. That should be built in functionality right? Obviously. Obviously it isn’t. Thankfully there is a fork of an export plugin which might just do the job!

Let’s take a look at what it can do.

If you’re using Inkscape 1.0 on Ubuntu 20.04LTS as I am, you’re probably using a snap package. You’ll want to put the extension files in ~/.config/inkscape/extensions/ with

git clone https://github.com/dmitry-t/inkscape-export-layers.git

Now restart Inkscape.

Naturally, the plugin doesn’t work – as I report here. Here we go again.

I stumbled across these notes on upgrading extensions for Inkscape 1.0 (which seems to break most of them). https://wiki.inkscape.org/wiki/index.php/Updating_your_Extension_for_1.0

After editing the export_layers.inx file appropriately it now looks like this :


<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
    <_name>Export layers</_name>

    <id>com.over9000.export-layers-2</id>

    <dependency type="executable" location="inx">export_layers.py</dependency>

    <param name="output-dir" type="string" _gui-text="Directory to export to">~/</param>

    <param name="fit-contents" type="optiongroup" appearance="minimal" _gui-text="Area to export">
        <option value="false" selected="selected">Use document boundaries</option>
        <option value="true">Fit to document contents</option>
    </param>

    <param name="file-type" type="optiongroup" appearance="minimal" _gui-text="Output file type">
        <option value="png" selected="selected">PNG</option>
        <option value="svg">SVG</option>
        <option value="jpeg">JPEG (requires ImageMagick)</option>
    </param>

    <param name="dpi" type="int" min="1" max="1024" appearance="minimal" _gui-text="Export DPI">96</param>

    <param name="enumerate" type="boolean" _gui-text="Add number prefixes to exported filenames (001_, 002_ etc)">true
    </param>

    <param name="help" type="description">Every layer marked with the prefix "[export]" is exported into a separate
        file. All layers marked with the prefix "[fixed]" are additionally exported into every such file.
    </param>

    <effect needs-live-preview="false">
        <object-type>all</object-type>
        <effects-menu>
            <submenu _name="Export"/>
        </effects-menu>
    </effect>

    <script>
        <command location="inx" interpreter="python">export_layers.py</command>
    </script>
</inkscape-extension>

The important changes are around the export_layers.py elements.

The plugin now at least displays, and does it work?

No of course it doesn’t. It vomits a heap of warnings back :


export_layers.py:28: DeprecationWarning: Effect.OptionParser or `optparse` has been deprecated and replaced with `argparser`.You must change `self.OptionParser.add_option` to `self.arg_parser.add_argument`; the arguments are similar.
  self.OptionParser.add_option('-o', '--output-dir',
export_layers.py:34: DeprecationWarning: Effect.OptionParser or `optparse` has been deprecated and replaced with `argparser`.You must change `self.OptionParser.add_option` to `self.arg_parser.add_argument`; the arguments are similar.
  self.OptionParser.add_option('-f', '--file-type',
export_layers.py:41: DeprecationWarning: Effect.OptionParser or `optparse` has been deprecated and replaced with `argparser`.You must change `self.OptionParser.add_option` to `self.arg_parser.add_argument`; the arguments are similar.
  self.OptionParser.add_option('--fit-contents',
export_layers.py:47: DeprecationWarning: Effect.OptionParser or `optparse` has been deprecated and replaced with `argparser`.You must change `self.OptionParser.add_option` to `self.arg_parser.add_argument`; the arguments are similar.
  self.OptionParser.add_option('--dpi',
export_layers.py:53: DeprecationWarning: Effect.OptionParser or `optparse` has been deprecated and replaced with `argparser`.You must change `self.OptionParser.add_option` to `self.arg_parser.add_argument`; the arguments are similar.
  self.OptionParser.add_option('--enumerate',
export_layers.py:239: DeprecationWarning: Effect.affect is now `Effect.run()`. The `output` argument has changed.
  LayerExport().affect(output=False)
export_layers.py:75: ResourceWarning: unclosed file <_io.BufferedReader name=4>
  if not self.convert_svg_to_svg(svg_file, output_dir):
export_layers.py:75: ResourceWarning: unclosed file <_io.BufferedReader name=6>
  if not self.convert_svg_to_svg(svg_file, output_dir):
export_layers.py:75: ResourceWarning: unclosed file <_io.BufferedReader name=4>
  if not self.convert_svg_to_svg(svg_file, output_dir):
export_layers.py:75: ResourceWarning: unclosed file <_io.BufferedReader name=6>
  if not self.convert_svg_to_svg(svg_file, output_dir):

Python is one of the few languages I never made the effort to learn. I couldn’t stand the idea of semantically important indents… but is it time? 🙁

Perhaps it’s going to be worth trying https://gitlab.com/su-v/inx-exportobjects next. Despite it being old as the sands of time, relative to the rate code seems to rot these days.

UPDATE: I found a bit more time and the other plugin also can’t do what’s necessary. Along the way I discovered that inscape has built in capabilities to query layers and export them individually from the command line – well, it would if that functionality wasn’t also broken. It’s getting a bit silly isn’t it.

The GOOD news, is that I found the Filter By Stroke Color in LaserWeb – which allows you to specify passes based on the colour value of paths in the .svg. Problem solved. I export a single svg with different paths (e.g. for Cut, Mark, or Score) coloured uniquely.

You can find more here: https://laserweb.yurl.ch/documentation/cam-operations/63-creating-operations/4-laser-cutting-an-svg-file

Would you like to beta test EyeSkills* or just follow what we are doing?


Leave a Reply

Your email address will not be published. Required fields are marked *