Использование оболочки Inkscape из Perl - PullRequest
2 голосов
/ 08 октября 2011

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 Ответ

2 голосов
/ 08 октября 2011

Вам не нужно разветвляться, 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 "ready\n";

print $is_in "test.svg -S\n";
read_until_prompt($is_out);

print $is_in "quit\n";
waitpid $pid, 0;

print "done!\n";

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

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

...