Como impor caminhos de arquivos relativos

3

Ao vincular a gráficos de varredura PNG do Inkscape SVG documentos, parece que o Inkscape sempre insiste em escrever o caminho absoluto para o gráfico PNG para o arquivo. Isso tem muitas desvantagens (que, obviamente, podem ser mitigadas editando manualmente o arquivo SVG em um editor de texto após cada salvamento, mas essa não pode ser a ideia por trás de um editor gráfico como o Inkscape):

  • Não consigo mover o diretório com meus gráficos sem quebrar o SVG.
  • Não consigo armazenar o diretório com meus gráficos em uma memória portátil para trabalhar nele a partir de vários computadores, pois o dispositivo portátil será atribuído a diferentes letras de unidade.
  • Não consigo editar meus gráficos de diferentes sistemas operacionais, pois eles podem montar a partição que armazena os arquivos SVG e os elementos gráficos PNG em diferentes pontos de montagem.
  • Eu não posso fornecer o diretório com meus gráficos para os colegas em um compartilhamento de rede de onde eles podem copiá-lo, porque os caminhos não serão compatíveis.
  • Os arquivos não podem ser diretamente confirmados e compartilhados por meio de sistemas de controle de versão, como SVN ou Git pelo mesmo motivo. No mínimo, toda vez que alguém fizer o commit do arquivo modificado, as linhas que contiverem caminhos completos serão registradas como mudanças pelo VCS.
  • Com arquivos armazenados frequentemente no diretório pessoal do usuário, isso também introduz um risco de privacidade, fornecendo o nome de usuário do criador (em configurações de trabalho, geralmente o nome real) ou outras informações sobre o sistema de arquivos do criador. li>

Mesmo agora, que o Inkscape parece usar caminhos relativos e apenas adicionar o caminho completo em um atributo extra ( sodipodi:absref ), vários dos problemas acima ainda estão ao redor (em particular, a privacidade preocupação é inalterada, e assim é a questão VCS).

Note que eu não quero incorporar os dados PNG nos documentos do Inkscape por várias razões, duas das quais são:

  • Os gráficos podem mudar mais tarde e é mais flexível ter a imagem PNG como um arquivo PNG separado, onde posso editá-la (e, portanto, ela será atualizada automaticamente ao abrir o Inkscape novamente), em vez de incorporar os dados PNG no SVG, ainda salvando-o como um arquivo extra (para que eu possa editar a imagem PNG mais tarde) e toda vez que eu alterar o PNG; Incorporando a nova versão novamente no Inkscape, adaptando manualmente sua posição e tamanho para coincidir com a versão anterior e, em seguida, removendo a versão anterior.
  • Diversas imagens PNG (como logotipos ou outros gráficos relacionados à identidade corporativa) são usadas em vários documentos SVG, por isso seria simplesmente um desperdício de espaço incorporar uma dessas imagens em cada documento SVG, de armazená-lo apenas uma vez e referindo-se ao gráfico PNG original de cada documento SVG. (E, claro, o esforço do item anterior se multiplica com cada documento SVG em que eu uso um dado gráfico raster modificado.)

Como solução alternativa, pensei em escrever um script que tenha que ser executado em arquivos SVG depois de salvar, com XSLT , ou com alguma linguagem convencional que pode carregar SVGs. Possivelmente, isso também poderia ser configurado como um gancho de pré-consolidação para os sistemas de controle de versão mencionados anteriormente. No entanto, isso parece suficientemente tedioso para mim, então eu só quero ir até esses limites se realmente não houver outro jeito.

Existe uma maneira de forçar o Inkscape a escrever apenas os caminhos relativos a imagens vinculadas no arquivo SVG? (Também para o caminho de exportação de bitmap usado mais recentemente, se possível.)

    
por O. R. Mapper 16.04.2014 / 11:14

1 resposta

1

Esta é uma ótima pergunta, e gostaria de ter uma solução realmente boa. Tudo o que consegui criar é o seguinte script hackish:

#!/usr/bin/perl

use strict;

# usage:
#   relativise_svg.pl foo.svg
# Looks for absolute links in svg file and makes them relative.
# Also checks whether files linked to exist.

use File::Spec; 
use File::Basename;
use Cwd 'abs_path';
my $svg = $ARGV[0];

-e $svg or err("file $svg doesn't exist");
-w $svg or err("file $svg not writeable");

local $/; # slurp whole file

open(F,"<$svg");
my $xml = <F>;
close F;

# Absolute links look like this:
#   xlink:href="file:///home/bcrowell/Documents/writing/books/physics/share/..."
# After we relativise them, they look like this:
#   xlink:href="foo/bar.jpg"

my $cwd = Cwd::getcwd();
my $svg_dir = File::Basename::dirname(abs_path($svg));
my $original_xml = $xml;

my @changes = ();
while ($xml=~m@(file://(/[^'"]*))@g) {
  my $whole = $1;
  my $path = $2;
  my $rel = relativise($path,$svg_dir,$cwd);
  print "changing absolute path in $svg to $rel\n";
  push @changes,[$whole,$rel];
}
foreach my $change(@changes) {
  my $from = quotemeta($change->[0]);
  my $to = $change->[1];
  $xml =~ s/$from/$to/g;
}

while ($xml=~m@xlink:href\s*=\s*"([^'"]*)@g) {
  my $rel = $1;
  if ($rel=~/\.(png|jpg)$/ && !($rel=~/\A#/ || $rel=~/\Adata:;/)) {
    my $abs = File::Spec->rel2abs($rel,$svg_dir);
    -e $abs or err("file $rel doesn't exist, resolved to absolute path $abs");
  }
}

if ($xml ne $original_xml) {
  open(F,">$svg");
  print F $xml;
  close F;
}

sub err {
  my $message = shift;
  print "relativise_svg.pl, working on $svg, ",$message,"\n";
  exit(-1);
}

sub relativise {
  my ($abs,$rel_to,$within) = @_;
  my $rel = File::Spec->abs2rel($abs,$rel_to);
  if (File::Spec->abs2rel($rel,$within)=~/\.\./) {
    err("result, $rel, would have been outside $within");
  }
  return $rel;
}
    
por 16.07.2014 / 00:03