#!/usr/bin/perl -w
# Convert a .eps file generated by Ghostscript eps2eps
# into a Ruby PDF::Writer setup
$skip = 1;
$x = $y = 0; # Pen coordinates
$prev = undef;
%colors = ();
# Generate a file name based on the input file
$filename = ($ARGV[0] . ".pdf") || "eps2rb-$$.pdf";
$filename =~ s/\.eps\.pdf/.pdf/;
while (<>) {
        chomp;

        # Skip the beginning of the file
        if (m/^%%EndPageSetup/) {
                $skip = 0;
                chmod(0755, *STDOUT);
                print "#!/usr/bin/ruby -rubygems\n";
                print 'require "pdf/writer"' . "\n";
                print 'require "color/rgb"' . "\n";
                print 'require "color/grayscale"' . "\n";
                print "def draw(pdf)\n";
                print "\tss = PDF::Writer::StrokeStyle.new\n";
                #print "\tpdf.translate_axis(-315, -265)\n";
                print "\tpdf.scale_axis(0.1, 0.1)\n";
                # Read three more lines, up to the setclip rectangle
                $dump = <>;
                $dump = <>;
                $dump = <>;
                next;
        }
        next if $skip;

        # Join wrapped lines ...
        if (defined $prev) {
                $_ = "$prev $_";
                $prev = undef;
        }
        # ... until there is something besides numbers and "back" operators in there
        if (m/^[-0-9. ^]*$/) {
                $prev = $_;
                next;
        }

        # Implement the "back" operator
        @line = split;
        for (my $i = 0; $i < $#line; $i++) {
                if ($line[$i] eq "^") {
                        @line = (@line[0 .. $i-1], -$line[$i-3], -$line[$i-2], @line[$i+1 .. $#line]);
                }
        }

        # Extract command
        $cmd = pop(@line);
        if ($cmd eq "K") { # setgray
                $g = "g0";
                print "\t$g = Color::GrayScale.new(0)\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        }
        elsif ($cmd eq "G") { # setgray
                $g = "g$line[0]";
                print "\t$g = Color::GrayScale.new($line[0]/2.55)\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        }
        elsif ($cmd eq "rG") { # setrgbcolor
                $g = "r$line[0]g$line[1]b$line[2]";
                print "\t$g = Color::RGB.new($line[0], $line[1], $line[2])\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        } 
        elsif ($cmd eq "r3") { # setrgbcolor special
                $g = "r$line[0]g$line[1]b$line[1]";
                print "\t$g = Color::RGB.new($line[0], $line[1], $line[1])\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        } 
        elsif ($cmd eq "r5") { # setrgbcolor special
                $g = "r$line[1]g$line[0]b$line[1]";
                print "\t$g = Color::RGB.new($line[1], $line[0], $line[1])\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        } 
        elsif ($cmd eq "r6") { # setrgbcolor special
                $g = "r$line[1]g$line[1]b$line[0]";
                print "\t$g = Color::RGB.new($line[1], $line[1], $line[0])\n" unless (exists($colors{$g}));
                print "\tpdf.stroke_color($g); pdf.fill_color($g)\n";
                $colors{$g} = 1;
        } 
        elsif ($cmd eq "J") { # setlinejoin
                print "\tss.join = PDF::Writer::StrokeStyle::LINE_JOINS.index($line[0]); pdf.stroke_style!(ss)\n";
        } 
        elsif ($cmd eq "j") { # setlinecap
                print "\tss.cap = PDF::Writer::StrokeStyle::LINE_CAPS.index($line[0]); pdf.stroke_style!(ss)\n";
        } 
        elsif ($cmd eq "M") { # setmiterlimit
                print "\tss.miter_limit = $line[0]; pdf.stroke_style!(ss)\n";
        }
        elsif ($cmd eq "w") { # setlinewidth
                print "\tss.width = $line[0]; pdf.stroke_style!(ss)\n";
        }
        elsif ($cmd eq "m") { # moveto
                print "\tpdf.move_to($line[0], $line[1])\n";
                ($x, $y) = @line;
        }
        elsif ($cmd eq "P") { # relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        $x = shift @line;
                        $y = shift @line;
                        print "\tpdf.move_to($x, $y)\n";                        
                }
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
        }
        elsif ($cmd eq "p") { # relative polygon (moveto, rlineto, …)
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
        }
        elsif ($cmd eq "f") { # filled relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        $x = shift @line;
                        $y = shift @line;
                        print "\tpdf.move_to($x, $y)\n";                        
                }
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
                print "\tpdf.fill\n";
        }
        elsif ($cmd eq "H") { # closed filled relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        $x = shift @line;
                        $y = shift @line;
                        print "\tpdf.move_to($x, $y)\n";                        
                }
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
                print "\tpdf.close\n";
        }
        elsif ($cmd eq "S") { # stroked (optional: relative polygon (moveto, rlineto, …))
                if ($#line >= 0) {
                        $x = shift @line;
                        $y = shift @line;
                        print "\tpdf.move_to($x, $y)\n";                        
                }
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
                print "\tpdf.stroke\n";
        }
        elsif ($cmd eq "h") { # closed relative polygon (rlineto, …)
                while ($#line >= 0) {
                        $x += shift @line;
                        $y += shift @line;
                        print "\tpdf.line_to($x, $y)\n";
                }
                print "\tpdf.close\n";
        }
        elsif ($cmd eq "re") { # rectangle
                print "\tpdf.rectangle(" . join(", ", @line) . ")\n";
        }
        elsif ($cmd eq "c") { # rcurveto
                print "\tpdf.curve_to(" .
                ($x + $line[0]) . ", " . ($y + $line[1]) . ", " .
                ($x + $line[2]) . ", " . ($y + $line[3]) . ", " .
                ($x + $line[4]) . ", " . ($y + $line[5]) . 
                ")\n";
                $x += $line[4];
                $y += $line[5];
        }
        elsif ($cmd eq "y") { # rcurveto (special)
                print "\tpdf.curve_to(" .
                ($x + $line[0]) . ", " . ($y + $line[1]) . ", " .
                ($x + $line[2]) . ", " . ($y + $line[3]) . ", " .
                ($x + $line[2]) . ", " . ($y + $line[3]) . 
                ")\n";
                $x += $line[2];
                $y += $line[3];
        }
        elsif ($cmd eq "v") { # rcurveto (special)
                print "\tpdf.curve_to(" .
                $x . ", " . $y . ", " .
                ($x + $line[0]) . ", " . ($y + $line[1]) . ", " .
                ($x + $line[2]) . ", " . ($y + $line[3]) . 
                ")\n";
                $x += $line[2];
                $y += $line[3];
        }
        else {
                print "#\t" . join(" ", @line, $cmd) . "\n";
        }
}
print "end\n";
print 'pdf = PDF::Writer.new(:paper => "A4")' . "\n" .
"draw(pdf)\n" . 
'pdf.save_as("' . $filename .'")' . "\n";
