9

I have a cartoon with multiple layers; among those layers I have a German and an English layer. They have the text in their respective languages. The idea is to hide the German layer and show the English layer and export as an English cartoon or to hide the English layer and show the German layer for a German version of the cartoon. I'd like to script that export.

Here is a part of my SVG file:

  <g
     inkscape:groupmode="layer"
     id="layer3"
     inkscape:label="English"
     style="display:inline">
     <text
         xml:space="preserve"  
         <!-- .... --> 
         id="text3255">
         <tspan id="tspan3257">I don't think</tspan>
         <!-- ... -->

and

 <g
     inkscape:groupmode="layer"
     id="layer4"
     inkscape:label="German"
     style="display:none"> 
     <text
           xml:space="preserve"
           <!-- ... -->
           id="text3284">   
           <tspan id="tspan3286">Ich glaube nicht,</tspan> 
           <!-- ... -->

I've seen https://stackoverflow.com/questions/9652573/inkscape-command-line-programming and tried this command (and plenty of variations to it):

inkscape -z --file=cartoon.svg --select=English --verb=LayerHideAll --select=German --verb=LayerShowAll --export-png=cartoon-de.png --export-area-drawing

But I keep getting the English text, probably because when I saved the file, the English layer was visible and the German layer wasn't.

I've also tried selecting the layers by their IDs (in the code above layer3 and layer4, respectively), and selecting the actual <text> elements; I've tried various combinations of Inkscape verbs. But no luck either.

How can I script this export, hiding or showing the language layer as needed? Can I do this with Inkscape verbs or should I work with the XML and try setting the style attribute to display:inline or display:none?

4 Answers 4

4

As to why the command-line testing wasn't working, I believe the answer is that you first need to select an item in the layer (and not the layer itself) to be "in" the layer. After that, the correct verb would be LayerToggleHide. (Not sure if this verb was available when this question was asked.) And, yes, objects can only be selected by ID, and not name.

Furthermore, because there are no LayerHide and LayerShow verbs (why?), to reliably script this you would first need to use LayerHideAll or LayerShowAll to set all layers one way or the other before then using LayerToggleHide to achieve the final result.

I haven't tested this command-line route so I can't show a definitive working solution. Instead, after thinking through the command-line route a great deal and realizing how much scripting it would take to make it work for my needs, I decided to just go all-in and write an Inskape extension that handles needs like this. I call it the SLiCk Layer Combinator and it can be found here: https://github.com/juanitogan/slick

1
  • According to inkscape wiki verbs are now deprecated in favor of actions.
    – sampi
    Feb 26, 2022 at 12:22
4

Ok, I messed around with various XML parsing modules and ended up with the following Perl code.

use XML::LibXML;
use XML::LibXML::XPathContext;

my $file = "file/to/open.svg";

my $xml = XML::LibXML->load_xml(location => $file);
my $xpath = XML::LibXML::XPathContext->new($xml);  
$xpath->registerNs("defNs", 'http://www.w3.org/2000/svg');
foreach my $layer ($xpath->findnodes('/defNs:svg/defNs:g[@inkscape:groupmode="layer"]')) {
    my $label = $layer->{'inkscape:label'};
    foreach my $otherLang (@languages) {
        if ($label =~ m/$other_lang$/) {
            $layer->{'style'} =~ s{\bdisplay:inline\b}{display:none};
        }
    }
    if ($layerLang eq $lang) {
        $layer->{'style'} =~ s{\bdisplay:none\b}{display:inline};
    }
}
$xml->toFile($tempFileName);

This solves my problem. Hopefully it is useful to someone else as well.

4
  • 1
    @StephenEglen Actually, this is buggy... you can't just set the style to display:... cause this will break if you already have other style attributes like opacity. I've updated the answer.
    – Robert
    Aug 4, 2016 at 21:55
  • Thanks. Do you mean that sometimes the "style" item for the layer can contain multiple attributes? in which case we should search/replace display:inline <--> display:inline accordingly? Aug 6, 2016 at 8:32
  • 1
    @StephenEglen Yes, exactly. I noticed it with opacity, but there can probably be others as well. Hence the regex to replace only the display:... and leave everything else as is.
    – Robert
    Aug 6, 2016 at 17:56
  • Thanx @Robert and @Stephen Eglin for your Perl code snippet. This was the missing piece that enabled me to create the ink2pdf tool. See github.com/spook/ink2pdf - It creates a multi-page PDF from an Inkscape drawing, and can use conditional tags too.
    – US Haunted
    Oct 28, 2020 at 15:36
3

I know it is a little bit late but I found this hide-latyer-svg Github Project which uses a python script to create new files with certain layers shown and hidden based on a xml node that you create on layer lever.

Best, Christoph

1

Given a file with multiple layers, where the interesting ones have ids: layer0 and layer1. It is possible to export the layers separately or together using inkscape actions as follows:

# Export layer0 alone into first.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer0; object-set-attribute:style, display:inline' \
    --export-filename='first.png' --export-type='png'

# Export layer1 alone into second.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer1; object-set-attribute:style, display:inline' \
    --export-filename='second.png' --export-type='png'

# Export layer0 and layer1 into both.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer0,layer1; object-set-attribute:style, display:inline' \
    --export-filename='both.png' --export-type='png'

Reading this inkscape forum post was key to figuring out how to use this sparsely documented feature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.