开发者

Using the Inkscape shell from perl

Inkscape has a shell mode invoked like this

inkscape --shell

where you can execute commands like this:

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

which will generate a PNG file, or like this:

/home/simone/some_text.svg -S

which gives you the bounding box of all elements in the file in the return message like this

 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

The benefit of this is that you can perform operations on SVG files without having to restart Inkscape every time.

I would like to 开发者_JAVA百科do something like this:

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

Things work OK if I use open2 and forking like this:

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); 
}

but I can't find out how to input only one line, and capture only that output without having to restart Inkscape every time.

Thanks

Simone


You don't need to fork, open2 handles that by itself. What you need to do is find a way of detecting when inkscape is waiting for input.

Here's a very basic example of how you could achieve that:

#! /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";

The read_until_prompt reads from inkscapes output until it finds a > character, and assumes that when it sees one, inkscape is ready.

Note: This is too simple, you will probably need more logic in there to make it work more reliably if a > can appear outside the prompt in the output you're expecting. There is also no error checking at all in the above script, which is bad.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜