Inkscape scripting: ¿como mostrar / ocultar una capa y exportar?

8

Tengo una caricatura con múltiples capas; entre esas capas tengo una capa alemana y otra inglesa. Tienen el texto en sus respectivos idiomas. La idea es ocultar la capa alemana y mostrar la capa inglesa y exportar como una caricatura inglesa u ocultar la capa inglesa y mostrar la capa alemana para una versión alemana de la caricatura. Me gustaría escribir esa exportación.

Aquí hay una parte de mi archivo SVG:

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

y

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

He visto /programming/9652573/inkscape-command-line-programming y probé este comando (y muchas variaciones):

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

Pero sigo recibiendo el texto en inglés, probablemente porque cuando guardé el archivo, la capa en inglés era visible y la capa en alemán no.

También he intentado seleccionar las capas por sus ID (en el código anterior capa3 y capa4, respectivamente), y seleccionando los <text>elementos reales ; He probado varias combinaciones de verbos de Inkscape. Pero tampoco suerte.

¿Cómo puedo escribir esta exportación, ocultar o mostrar la capa de idioma según sea necesario? ¿Puedo hacer esto con los verbos de Inkscape o debería trabajar con el XML e intentar configurar el atributo de estilo para mostrar: en línea o mostrar: ninguno?

Robert
fuente

Respuestas:

3

Ok, me metí con varios módulos de análisis XML y terminé con el siguiente código.

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

Esto resuelve mi problema. Esperemos que también sea útil para alguien más.

Robert
fuente
1
@StephenEglen En realidad, esto tiene errores ... no puedes simplemente configurar el estilo para display:...que se rompa si ya tienes otros atributos de estilo como la opacidad. He actualizado la respuesta.
Robert
Gracias. ¿Quiere decir que a veces el elemento "estilo" para la capa puede contener múltiples atributos? en cuyo caso debemos buscar / reemplazar display: inline <--> display: inline en consecuencia?
Stephen Eglen
1
@StephenEglen Sí, exactamente. Lo noté con opacidad, pero probablemente también pueda haber otros. De ahí la expresión regular para reemplazar solo la pantalla: ... y dejar todo lo demás como está.
Robert
2

Sé que es un poco tarde, pero encontré este proyecto Github hide-latyer-svg que usa un script de Python para crear nuevos archivos con ciertas capas mostradas y ocultas basadas en un nodo xml que creas en la palanca de capa.

Mejor Christoph

Christoph
fuente
2

En cuanto a por qué la prueba de la línea de comandos no estaba funcionando, creo que la respuesta es que primero debe seleccionar un elemento en la capa (y no la capa en sí) para estar "en" la capa. Después de eso, el verbo correcto sería LayerToggleHide. (No estoy seguro de si este verbo estaba disponible cuando se hizo esta pregunta). Y sí, los objetos solo pueden seleccionarse por ID y no por nombre.

Además, debido a que no hay verbos LayerHide y LayerShow (¿por qué?), Para escribir esto de manera confiable, primero deberá usar LayerHideAllo LayerShowAllconfigurar todas las capas de una forma u otra antes de usarlas LayerToggleHidepara lograr el resultado final.

No he probado esta ruta de línea de comandos, así que no puedo mostrar una solución de trabajo definitiva. En cambio, después de pensar mucho en la ruta de la línea de comandos y darme cuenta de la cantidad de secuencias de comandos que se necesitarían para que funcione para mis necesidades, decidí ir todo adentro y escribir una extensión de Inskape que maneje necesidades como esta. Lo llamo SLiCk Layer Combinator y se puede encontrar aquí: https://github.com/juanitogan/slick

juanitogan
fuente