Использование оболочки Inkscape из perl

#perl #svg #automation #command-line-interface #inkscape

#perl #svg #автоматизация #интерфейс командной строки #inkscape

Вопрос:

Inkscape имеет режим оболочки, вызываемый следующим образом

 inkscape --shell
  

где вы можете выполнять такие команды, как:

 some_svg_file.svg -e some_png_output.png -y 1.0 -b #ffffff -D -d 150 
  

который сгенерирует файл PNG или что-то вроде этого:

 /home/simone/some_text.svg -S
  

который дает вам ограничивающую рамку для всех элементов в файле в возвращаемом сообщении следующим образом

  svg2,0.72,-12.834,122.67281,12.942
 layer1,0.72,-12.834,122.67281,12.942
 text2985,0.72,-12.834,122.67281,12.942
 tspan2987,0.72,-12.834,122.67281,12.942
  

Преимущество этого заключается в том, что вы можете выполнять операции с файлами SVG без необходимости перезапускать Inkscape каждый раз.

Я хотел бы сделать что-то вроде этого:

 sub do_inkscape {
     my ($file, $commands) = @_;
     # capture output
     return $output
}
  

Все работает нормально, если я использую open2 и разветвляюсь следующим образом:

 use IPC::Open2;

$pid = open2(*CHLD_OUT, *CHLD_IN, 'inkscape --shell');
$ = "n"; $/ = ">";

my $out; open my $fh, '>', $out;

if (!defined($kidpid = fork())) {
    die "cannot fork: $!";
} elsif ($kidpid == 0) {
    while (<>) { print CHLD_IN $_; }
} else { 
    while (<CHLD_OUT>) { chop; s/s*$//gmi; print ""$_"";  }
    waitpid($kidpid, 0); 
}
  

но я не могу понять, как вводить только одну строку и записывать только этот вывод без необходимости перезапускать Inkscape каждый раз.

Спасибо

Симона

Ответ №1:

Вам не нужно раскошеливаться, open2 обрабатывает это само по себе. Что вам нужно сделать, так это найти способ определения того, когда inkscape ожидается ввод.

Вот очень простой пример того, как вы могли бы этого добиться:

 #! /usr/bin/perl
use strict;
use warnings;

use IPC::Open2;

sub read_until_prompt($) {
    my ($fh) = (@_);
    my $done = 0;
    while (!$done) {
        my $in;
        read($fh, $in, 1);
        if ($in eq '>') {
            $done = 1;
        } else {
            print $in;
        }
    }
}

my ($is_in, $is_out);
my $pid = open2($is_out, $is_in, 'inkscape --shell');

read_until_prompt($is_out);
print "readyn";

print $is_in "test.svg -Sn";
read_until_prompt($is_out);

print $is_in "quitn";
waitpid $pid, 0;

print "done!n";
  

read_until_prompt Считывает данные из inkscape выходных данных s до тех пор, пока не найдет > символ, и предполагает, что, когда он его увидит, inkscape он готов.

Примечание: это слишком просто, вам, вероятно, потребуется больше логики, чтобы заставить его работать более надежно, если a > может появиться вне приглашения в ожидаемом вами выводе. Кроме того, в приведенном выше скрипте вообще нет проверки ошибок, что плохо.