Script do Inkscape: como mostrar / ocultar uma camada e exportar?

8

Eu tenho um desenho animado com várias camadas; Entre essas camadas, tenho uma camada alemã e uma inglesa. Eles têm o texto em seus respectivos idiomas. A idéia é ocultar a camada em alemão e mostrar a camada em inglês e exportar como um desenho em inglês ou ocultar a camada em inglês e mostrar a camada em alemão para uma versão em alemão do desenho. Eu gostaria de criar um script para exportar.

Aqui está uma parte do meu arquivo 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>
         <!-- ... -->

e

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

Eu vi /programming/9652573/inkscape-command-line-programming e tentei este comando (e diversas variações para ele):

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

Mas continuo recebendo o texto em inglês, provavelmente porque quando salvei o arquivo, a camada em inglês estava visível e a camada em alemão não.

Eu também tentei selecionar as camadas por seus IDs (no código acima layer3 e layer4, respectivamente) e selecionar os <text>elementos reais ; Eu tentei várias combinações de verbos do Inkscape. Mas sem sorte também.

Como posso criar um script para essa exportação, ocultando ou mostrando a camada de idioma conforme necessário? Posso fazer isso com os verbos do Inkscape ou devo trabalhar com o XML e tentar definir o atributo de estilo para display: inline ou display: none?

Robert
fonte

Respostas:

3

Ok, eu brinquei com vários módulos de análise XML e acabei com o seguinte 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);

Isso resolve meu problema. Espero que seja útil para outra pessoa também.

Robert
fonte
1
@StephenEglen Na verdade, isso é um buggy ... você não pode simplesmente definir o estilo para display:...que isso ocorra se você já tiver outros atributos de estilo, como opacidade. Eu atualizei a resposta.
Robert
Obrigado. Você quer dizer que, às vezes, o item "estilo" da camada pode conter vários atributos? nesse caso, devemos procurar / substituir display: inline <--> display: inline de acordo?
Stephen Eglen
1
@StephenEglen Sim, exatamente. Notei isso com opacidade, mas provavelmente também pode haver outros. Portanto, o regex substitui apenas a exibição: ... e deixa todo o resto como está.
Robert
2

Eu sei que é um pouco tarde, mas eu encontrei este projeto Github hide-latyer-svg que usa um script python para criar novos arquivos com certas camadas mostradas e ocultas com base em um nó xml que você cria na alavanca da camada.

Best, Christoph

Christoph
fonte
2

Quanto ao motivo pelo qual o teste da linha de comando não estava funcionando, acredito que a resposta é que você primeiro precisa selecionar um item na camada (e não a própria camada) para estar "dentro" da camada. Depois disso, o verbo correto seria LayerToggleHide. (Não tenho certeza se esse verbo estava disponível quando essa pergunta foi feita.) E, sim, os objetos só podem ser selecionados por ID e não por nome.

Além disso, como não existem verbos LayerHide e LayerShow (por quê?), Para criar um script confiável, primeiro você precisará usar LayerHideAllou LayerShowAlldefinir todas as camadas de uma maneira ou de outra antes de usar LayerToggleHidepara obter o resultado final.

Não testei essa rota de linha de comando, portanto não posso mostrar uma solução definitiva de trabalho. Em vez disso, depois de pensar bastante na rota da linha de comando e perceber a quantidade de scripts necessários para fazê-lo funcionar para minhas necessidades, decidi fazer o all-in e escrever uma extensão do Inskape que lida com necessidades como essa. Eu chamo isso de SLiCk Layer Combinator e pode ser encontrado aqui: https://github.com/juanitogan/slick

juanitogan
fonte