Inkscape-Scripting: Wie kann man eine Ebene ein- / ausblenden und exportieren?

8

Ich habe einen Cartoon mit mehreren Schichten; Unter diesen Schichten habe ich eine deutsche und eine englische Schicht. Sie haben den Text in ihrer jeweiligen Sprache. Die Idee ist, die deutsche Ebene auszublenden und die englische Ebene anzuzeigen und als englischen Cartoon zu exportieren oder die englische Ebene auszublenden und die deutsche Ebene für eine deutsche Version des Cartoons anzuzeigen. Ich möchte diesen Export per Skript ausführen.

Hier ist ein Teil meiner SVG-Datei:

  <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>
         <!-- ... -->

und

 <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> 
           <!-- ... -->

Ich habe /programming/9652573/inkscape-command-line-programming gesehen und diesen Befehl (und viele Variationen davon) ausprobiert:

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

Aber ich bekomme immer wieder den englischen Text, wahrscheinlich weil beim Speichern der Datei die englische Ebene sichtbar war und die deutsche Ebene nicht.

Ich habe auch versucht, die Ebenen anhand ihrer IDs auszuwählen (im Code über Ebene 3 bzw. Ebene 4) und die tatsächlichen <text>Elemente auszuwählen . Ich habe verschiedene Kombinationen von Inkscape-Verben ausprobiert. Aber auch kein Glück.

Wie kann ich diesen Export per Skript ausführen, die Sprachebene nach Bedarf ausblenden oder anzeigen? Kann ich dies mit Inkscape-Verben tun oder sollte ich mit XML arbeiten und versuchen, das Stilattribut auf display: inline oder display: none festzulegen?

Robert
quelle

Antworten:

3

Ok, ich habe mit verschiedenen XML-Parsing-Modulen herumgespielt und am Ende den folgenden Code erhalten.

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

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);

Dies löst mein Problem. Hoffentlich ist es auch für andere nützlich.

Robert
quelle
1
@StephenEglen Eigentlich ist das fehlerhaft ... Sie können den Stil nicht einfach so einstellen, display:...dass dies nicht funktioniert, wenn Sie bereits andere Stilattribute wie die Deckkraft haben. Ich habe die Antwort aktualisiert.
Robert
Vielen Dank. Meinen Sie damit, dass das "Stil" -Element für die Ebene manchmal mehrere Attribute enthalten kann? In welchem ​​Fall sollten wir display: inline <--> display: inline entsprechend suchen / ersetzen?
Stephen Eglen
1
@ StephenEglen Ja genau. Ich habe es mit Deckkraft bemerkt, aber es kann wahrscheinlich auch andere geben. Daher die Regex, um nur die Anzeige zu ersetzen: ... und alles andere so zu lassen, wie es ist.
Robert
2

Ich weiß, dass es etwas spät ist, aber ich habe dieses Hithub-Projekt hide-latyer-svg gefunden , das ein Python-Skript verwendet, um neue Dateien mit bestimmten Ebenen zu erstellen, die basierend auf einem XML-Knoten angezeigt und ausgeblendet werden, den Sie auf dem Ebenenhebel erstellen.

Am besten, Christoph

Christoph
quelle
2

Ich glaube, die Antwort lautet, dass Sie zuerst ein Element in der Ebene (und nicht die Ebene selbst) auswählen müssen, um "in" der Ebene zu sein. Danach wäre das richtige Verb LayerToggleHide. (Ich bin mir nicht sicher, ob dieses Verb verfügbar war, als diese Frage gestellt wurde.) Und ja, Objekte können nur anhand der ID und nicht anhand des Namens ausgewählt werden.

Da es keine LayerHide- und LayerShow-Verben gibt (warum?), Müssen Sie zum zuverlässigen Skript zunächst alle Ebenen auf die eine oder andere Weise verwenden LayerHideAlloder LayerShowAllfestlegen, bevor Sie sie verwenden LayerToggleHide, um das Endergebnis zu erzielen.

Ich habe diese Befehlszeilenroute nicht getestet, daher kann ich keine endgültige funktionierende Lösung anzeigen. Nachdem ich die Befehlszeilenroute gründlich durchdacht und festgestellt hatte, wie viel Skripting erforderlich ist, damit sie für meine Anforderungen funktioniert, entschied ich mich stattdessen, einfach All-in zu gehen und eine Inskape-Erweiterung zu schreiben, die solche Anforderungen erfüllt. Ich nenne es den SLiCk Layer Combinator und er ist hier zu finden: https://github.com/juanitogan/slick

Juanitogan
quelle