Como aplicar caminhos de arquivo relativos

4

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

  • Não consigo mover o diretório com meus gráficos sem interromper o SVG.
  • Não consigo armazenar o diretório com meus gráficos em uma memória portátil para trabalhar em vários computadores, pois o dispositivo portátil recebe 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 gráficos PNG em diferentes pontos de montagem.
  • Não consigo fornecer o diretório com meus gráficos aos colegas em um compartilhamento de rede de onde eles podem copiá-lo, porque os caminhos não coincidem.
  • Os arquivos não podem ser confirmados diretamente 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 confirmar o arquivo alterado, as linhas que contêm caminhos completos serão registradas sem sentido como alterações pelo VCS.
  • Com os arquivos freqüentemente armazenados no diretório inicial do usuário, isso também apresenta um risco à privacidade, fornecendo o nome de usuário do criador (nas configurações de trabalho, geralmente o nome real) ou outras informações sobre o sistema de arquivos do criador.

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 existem (em particular, a preocupação com a privacidade é inalterada, e o problema com o VCS).

Observe que não desejo incorporar os dados PNG nos documentos do Inkscape por vários motivos, dois dos quais são:

  • Os gráficos podem mudar mais tarde, e é mais flexível ter a imagem PNG como um arquivo PNG separado, onde eu possa editá-la (e, assim, será atualizada automaticamente ao abrir o Inkscape novamente), em vez de incorporar os dados PNG no SVG , ainda o salve como um arquivo extra (para que eu possa editar a imagem PNG posteriormente) e toda vez que eu alterar o PNG; incorporando a nova versão novamente no Inkscape, adaptando manualmente sua posição e tamanho para corresponder à da versão anterior e removendo a versão anterior.
  • Várias imagens PNG (pense em logotipos ou outros gráficos relacionados à identidade corporativa) são usadas em vários documentos SVG; portanto, seria um desperdício de espaço incorporar uma dessas imagens em cada documento SVG, em vez de armazená-las 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 a cada documento SVG em que eu uso um determinado gráfico de varredura modificado.)

Como solução alternativa, pensei em escrever um script que precise ser executado nos arquivos SVG após salvar, seja com XSLT ou com alguma linguagem convencional que possa carregar SVGs. Possivelmente, isso também pode ser configurado como um gancho de confirmação prévia para os sistemas de controle de versão acima mencionados. No entanto, fazer isso parece bastante entediante para mim, então eu só quero ir tão longe se realmente não houver outra maneira.

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

OR Mapper
fonte

Respostas:

1

Essa é uma ótima pergunta, e eu gostaria de ter uma solução muito 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;
}
Ben Crowell
fonte