#!/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 = ();
$poly = "";
# Generate a file name based on the input file
$filename = ($ARGV[0] . ".pdf") || "eps2rb-$$.pdf";
$filename =~ s/\.eps\.pdf/.pdf/;

sub dump_poly {
        if ($poly ne "") {
                print "\tpdf.polygon([$poly])";
                print ".$_[0]" if (defined($_[0]));
                print "\n";
                $poly = "";
        }
        elsif (defined($_[0])) {
                print "\tpdf.$_[0]\n";
        }
}

sub append {
        # Usage: x, y, [type, [dontmove]]
        # type is the line/curve type; if "dontmove" eq ".", don't update x, y
        my $app = "[$_[0], $_[1]";
        my $ai = 2;
        if (defined($_[2]) && $_[2] ne ".") {
                $app .= ", :$_[2]";
                $ai++;
        }
        $app .= "]";
        # Update x, y (maybe)
        ($x, $y) = @_[0, 1] unless defined($_[$ai]) && $_[$ai] eq ".";
        # Add drawing point
        if ($poly eq "") {
                $poly = $app;
        } else {
                $poly = "$poly, $app";
        }
}

sub append_rel {
        @params = (@_);
        $params[0] += $x;
        $params[1] += $y;
        append(@params);    
}

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);
        ## Style settings
        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";
        }
        ## Drawing operators
        elsif ($cmd eq "m") { # moveto
                dump_poly();
                append($line[0], $line[1]);
        }
        elsif ($cmd eq "P") { # relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        dump_poly;
                        append(shift @line, shift @line);
                }
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
        }
        elsif ($cmd eq "p") { # relative polygon (moveto, rlineto, …)
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
        }
        elsif ($cmd eq "f") { # filled relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        dump_poly;
                        append(shift @line, shift @line);
                }
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
                dump_poly("fill");
        }
        elsif ($cmd eq "H") { # closed filled relative polygon (moveto, rlineto, …)
                if ($#line >= 0) {
                        dump_poly;
                        append(shift @line, shift @line);
                }
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
                dump_poly("close");
        }
        elsif ($cmd eq "S") { # stroked (optional: relative polygon (moveto, rlineto, …))
                if ($#line >= 0) {
                        dump_poly;
                        append(shift @line, shift @line);
                }
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
                dump_poly("stroke");
        }
        elsif ($cmd eq "h") { # closed relative polygon (rlineto, …)
                while ($#line >= 0) {
                        append_rel(shift @line, shift @line);
                }
                dump_poly("close");
        }
        elsif ($cmd eq "re") { # rectangle
                dump_poly();
                print "\tpdf.rectangle(" . join(", ", @line) . ")\n";
        }
        elsif ($cmd eq "c") { # rcurveto
                append_rel($line[0], $line[1], "curve", ".");
                append_rel($line[2], $line[3], ".");
                append_rel($line[4], $line[5]);
        }
        elsif ($cmd eq "y") { # rcurveto (special)
                append_rel($line[0], $line[1], "curve", ".");
                append_rel($line[2], $line[3], ".");
                append_rel($line[2], $line[3]);
        }
        elsif ($cmd eq "v") { # rcurveto (special)
                append_rel(0,        0,        "curve", ".");
                append_rel($line[0], $line[1], ".");
                append_rel($line[2], $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";
