/*******************************************************************************
+
+  LEDA 3.5
+
+  ps.c
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#include <fstream.h>
#include "../../src/graphwin/ps.h"

#include <time.h>

// ---------------------------------------------------------------------------

#define DefPSBufSize	1000

// ---------------------------------------------------------------------------

char ps_buf[DefPSBufSize];

color PostScript::fgcol=black;
color PostScript::bgcol=white;

// ---------------------------------------------------------------------------

void PostScript::add(const char* str) { s << str; }
void PostScript::add(const string& str) { s << str; }

// ---------------------------------------------------------------------------

void PostScript::add(color c) { s << color_name[c]; }

// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, const char* str) {
  ps.add(str);
  return ps;
}

PostScript& operator << (PostScript& ps, const string& str) {
  ps.add(str);
  return ps;
}

// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, color c) {
  ps.add(c);
  ps << " ";
  return ps;
}

// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, double d) {
  ps << string("%f ",d);
  return ps;
}

// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, int i) {
  ps << string("%d ",i);
  return ps;
}

// ---------------------------------------------------------------------------

char* PostScript::str() { 
  s << ends;
  return s.str(); 
}

// ---------------------------------------------------------------------------

bool PostScript::save(string fname) {
  ofstream o(fname,ios::out);
  if (!o) return false;
  o << *this;
  if (o.fail()) return false;
  o.close();
  return true;
}
  
// ---------------------------------------------------------------------------

bool PostScript::save() { 
  return save(f); 
}

// ---------------------------------------------------------------------------

void PostScript::init_color_names() {
  color_name[black]  = "black";
  color_name[white]  = "white";
  color_name[red]    = "red";
  color_name[green]  = "green";
  color_name[blue]   = "blue";
  color_name[yellow] = "yellow";
  color_name[violet] = "violet";
  color_name[orange] = "orange";
  color_name[cyan]   = "cyan";
  color_name[brown]  = "brown";
  color_name[pink]   = "pink";
  color_name[green2] = "green2";
  color_name[blue2]  = "blue2";
  color_name[grey1]  = "grey1";
  color_name[grey2]  = "grey2";
  color_name[grey3]  = "grey3";
}

// ---------------------------------------------------------------------------

void PostScript::header(ostream& o) {
  time_t t;
  time(&t);
  o << "%!PS-Adobe-2.0" << endl;
  o << "%%Creator: LEDA GraphWin 1.0" << endl;
  o << "%%CreationDate: " << ctime(&t);
  o << "%%Pages:  1" << endl;
  o << "%%BoundingBox: " << " " <<      0  << " " <<      0 
                         << " " << x_width << " " << y_width << endl; 
  o << "%%EndComments" << endl;
}

// ---------------------------------------------------------------------------

void PostScript::footer(ostream& o) {
  o << endl << "%%EndProgram" << endl << endl;
  o << "showpage" << endl;
  o << "end %% LEDA_dict" << endl;
  o << "%%EOF" << endl;
}

// ---------------------------------------------------------------------------

void PostScript::define_colors(ostream& out) {
  out << '/' << color_name[black] << "  { 0     0     0     } def" << endl;
  out << '/' << color_name[white] << "  { 1     1     1     } def" << endl;
  out << '/' << color_name[red] << "    { 1     0     0     } def" << endl;
  out << '/' << color_name[green] << "  { 0     1     0     } def" << endl;
  out << '/' << color_name[blue] << "   { 0     0     1     } def" << endl;
  out << '/' << color_name[yellow] << " { 1     1     0     } def" << endl;
  out << '/' << color_name[violet] << " { 0.933 0.510 0.933 } def" << endl;
  out << '/' << color_name[orange] << " { 1     0.647 0     } def" << endl;
  out << '/' << color_name[cyan] << "   { 0     1     1     } def" << endl;
  out << '/' << color_name[brown] << "  { 1     0.251 0.251 } def" << endl;
  out << '/' << color_name[pink] << "   { 1     0.753 0.796 } def" << endl;
  out << '/' << color_name[green2] << " { 0     0.804 0     } def" << endl;
  out << '/' << color_name[blue2] << "  { 0     0     0.804 } def" << endl;
  out << '/' << color_name[grey1] << "  { 0.25  0.25  0.25  } def" << endl;
  out << '/' << color_name[grey2] << "  { 0.5   0.5   0.5   } def" << endl;
  out << '/' << color_name[grey3] << "  { 0.75  0.75  0.75  } def" << endl;
}

// ---------------------------------------------------------------------------

void PostScript::prolog(ostream& o) {
  o << "/LEDA_dict 100 dict def" << endl;
  o << "LEDA_dict begin" << endl;
  o << "%% ------------------------  MISC  ----------------------" << endl;
  o << "/max { 2 copy lt { exch } if pop } def" << endl;
  o << "/min { 2 copy gt { exch } if pop } def" << endl;
  o << "%% --------------------  COLORS  ------------------------" << endl;
  define_colors(o);
  o << "/set_color { setrgbcolor } def" << endl;
  o << "%% ------------------  SCALING  -------------------------" << endl;
  o << "/maxscale { xscale yscale max } def" << endl;
  o << "/set_scale {" << endl;
  o << "  /yscale exch def /xscale exch def" << endl;
  o << "  xscale yscale scale" << endl;
  o << "  currentlinewidth maxscale div setlinewidth" << endl;
  o << "} def" << endl;
  o << "/units { maxscale div } def" << endl;
  o << "/unit { units } def" << endl;
  o << "%% ------------------------------------------------------" << endl;
  o << "/set_line_width { units setlinewidth } def" << endl;
  o << "%% --------------------  FONT  --------------------------" << endl;
  o << "/font_dict 2 dict def" << endl;
  o << "/set_font {" << endl;
  o << "  font_dict" << endl;
  o << "  begin" << endl;
  o << "    /font_size exch def /font_name exch def" << endl;
  o << "    font_name cvn font_size selectfont" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "%% ------------------  SEGMENTS  ------------------------" << endl;
  o << "/segment_dict 4 dict def" << endl;
  o << "/segment {" << endl;
  o << "  segment_dict" << endl;
  o << "  begin" << endl;
  o << "    /y2 exch def /x2 exch def /y1 exch def /x1 exch def" << endl;
  o << "    x1 y1 moveto" << endl;
  o << "    x2 y2 lineto" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/draw_segment { set_color segment stroke } def" << endl;
  o << "%% ------------------  POLYGONS  ------------------------" << endl;
  o << "/polygon_dict 1 dict def" << endl;
  o << "/polygon_unclosed {" << endl;
  o << "  polygon_dict" << endl;
  o << "  begin" << endl;
  o << "    /points exch def" << endl;
  o << "    points 2 mul dup 2 sub roll" << endl;
  o << "    moveto" << endl;
  o << "    points 1 sub" << endl;
  o << "    dup { dup 2 mul 1 add -2 roll lineto 1 sub} repeat" << endl;
  o << "    pop" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/polygon { newpath polygon_unclosed closepath } def" << endl;
  o << "/filled_polygon { polygon fill } def" << endl;
  o << "/draw_polygon { set_color polygon stroke } def" << endl;
  o << "/draw_filled_polygon { set_color filled_polygon stroke } def" << endl;
  o << "%% -------------------  CIRCLES  ------------------------" << endl;
  o << "/circle_dict 3 dict def" << endl;
  o << "/circle {" << endl;
  o << "  circle_dict" << endl;
  o << "  begin" << endl;
  o << "    /rad exch def /ypos exch def /xpos exch def" << endl;
  o << "    xpos ypos rad 0 360 arc" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/disc { circle fill } def" << endl;
  o << "/filled_circle { disc } def" << endl;
  o << "/draw_circle { set_color circle stroke } def" << endl;
  o << "/draw_disc { set_color disc stroke } def" << endl;
  o << "%% -------------------  ELLIPSES  -----------------------" << endl;
  o << "/ellipse_dict 4 dict def" << endl;
  o << "/ellipse {" << endl;
  o << "  ellipse_dict" << endl;
  o << "  begin" << endl;
  o << "    /yrad exch def /xrad exch def /ypos exch def /xpos exch def" << endl;
  o << "    matrix currentmatrix" << endl;
  o << "    xpos ypos translate" << endl;
  o << "    xrad yrad scale" << endl;
  o << "    0 0 1 0 360 arc" << endl;
  o << "    setmatrix" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/filled_ellipse { ellipse fill } def" << endl;
  
  o << "/draw_ellipse { set_color ellipse stroke } def" << endl;
  o << "/draw_filled_ellipse { set_color filled_ellipse stroke } def" << endl;
  o << "%% -----------------  RECTANGLES  -----------------------" << endl;
  o << "/rectangle_dict 4 dict def" << endl;
  o << "/rectangle {" << endl;
  o << "  rectangle_dict" << endl;
  o << "  begin" << endl;
  o << "    /y2 exch def /x2 exch def /y1 exch def /x1 exch def" << endl;
  o << "    x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto closepath" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/filled_rectangle { rectangle fill } def" << endl;
  o << "/draw_rectangle { set_color rectangle stroke } def" << endl;
  o << "/draw_filled_rectangle { set_color filled_rectangle stroke } def" << endl;
  o << "%% -------------------  NODES  --------------------------" << endl;
  o << "/draw_circle_node {" << endl;
  o << "    set_color" << endl;
  o << "    3 dict begin" << endl;
  o << "    /rad exch def /ypos exch def /xpos exch def" << endl;
  o << "    xpos ypos rad disc" << endl;
  o << "    xpos ypos rad black draw_circle" << endl;
  o << "    end" << endl;
  o << "} def" << endl;
  o << "/draw_ellipse_node {" << endl;
  o << "    set_color" << endl;
  o << "    4 dict begin" << endl;
  o << "    /yrad exch def /xrad exch def /ypos exch def /xpos exch def" << endl;
  o << "    xpos ypos xrad yrad filled_ellipse" << endl;
  o << "    xpos ypos xrad yrad black draw_ellipse" << endl;
  o << "    end" << endl;
  o << "} def" << endl;
  o << "/draw_rectangle_node {" << endl;
  o << "    set_color" << endl;
  o << "    4 dict begin" << endl;
  o << "    /y2 exch def /x2 exch def /y1 exch def /x1 exch def" << endl;
  o << "    x1 y1 x2 y2 filled_rectangle" << endl;
  o << "    x1 y1 x2 y2 black draw_rectangle" << endl;
  o << "    end" << endl;
  o << "} def" << endl;
  o << "%% --------------------  TEXT  --------------------------" << endl;
  o << "/text_dict 1 dict def" << endl;
  o << "/text {" << endl;
  o << "  text_dict" << endl;
  o << "  begin" << endl;
  o << "    /label exch def" << endl;
  o << "    matrix currentmatrix" << endl;
  o << "      initmatrix" << endl;
  o << "      label show" << endl;
  o << "    setmatrix" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/ctext_dict 3 dict def" << endl;
  o << "/ctext {" << endl;
  o << "  ctext_dict" << endl;
  o << "  begin" << endl;
  o << "    /label exch def" << endl;
  o << "    matrix currentmatrix" << endl;
  o << "      initmatrix" << endl;
  o << "      label stringwidth pop /width exch def" << endl;
  o << "      gsave" << endl;
  o << "        newpath" << endl;
  o << "        0 0 moveto" << endl;
  o << "        label false charpath pathbbox" << endl;
  o << "        /height exch def pop pop pop" << endl;
  o << "      grestore" << endl;
  o << "      width -2 div height -2 div rmoveto" << endl;
  o << "      label show" << endl;
  o << "    setmatrix" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/draw_text {" << endl;
  o << "  set_color" << endl;
  o << "  3 dict begin" << endl;
  o << "    /label exch def /ypos exch def /xpos exch def" << endl;
  o << "    xpos ypos moveto" << endl;
  o << "    label text" << endl;
  o << "    stroke" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/draw_ctext {" << endl;
  o << "  set_color" << endl;
  o << "  3 dict begin" << endl;
  o << "    /label exch def /ypos exch def /xpos exch def" << endl;
  o << "    xpos ypos moveto" << endl;
  o << "    label ctext" << endl;
  o << "    stroke" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "%% -------------------  ARROWS  -------------------------" << endl;
  o << "/arrow_head_length { currentlinewidth 3 units max } def" << endl;
  o << "/arrow_head_dict 5 dict def" << endl;
  o << "/arrow_head {" << endl;
  o << "  arrow_head_dict" << endl;
  o << "  begin" << endl;
  o << "    /angle exch def /tipy exch def /tipx exch def" << endl;
  o << "    /len arrow_head_length def" << endl;
  o << "    /wid len def" << endl;
  o << "    currentlinejoin" << endl;
  o << "      2 setlinejoin" << endl;
  o << "      matrix currentmatrix" << endl;
  o << "        tipx tipy translate" << endl;
  o << "        angle rotate" << endl;
  o << "        0 0 moveto" << endl;
  o << "        len 2 mul neg wid neg lineto" << endl;
  o << "        len neg 0 lineto" << endl;
  o << "        len 2 mul neg wid lineto" << endl;
  o << "        closepath" << endl;
  o << "        fill" << endl;
  o << "      setmatrix" << endl;
  o << "    setlinejoin" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/arrowto_dict 10 dict def" << endl;
  o << "/arrowto {" << endl;
  o << "  arrowto_dict" << endl;
  o << "  begin" << endl;
  o << "    /tipy exch def /tipx exch def" << endl;
  o << "    currentpoint /taily exch def /tailx exch def" << endl;
  o << "    /dx tipx tailx sub def" << endl;
  o << "    /dy tipy taily sub def" << endl;
  o << "    /arrowlength dx dx mul dy dy mul add sqrt def" << endl;
  o << "    /angle dy dx atan def" << endl;
  o << "    /head arrow_head_length def" << endl;
  o << "    /base arrowlength head sub def" << endl;
  o << "    matrix currentmatrix" << endl;
  o << "      tailx taily translate" << endl;
  o << "      angle rotate" << endl;
  o << "      base 0 lineto" << endl;
  o << "      stroke" << endl;
  o << "    setmatrix" << endl;
  o << "    tipx tipy angle arrow_head" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/arrow_dict 4 dict def" << endl;
  o << "/arrow {" << endl;
  o << "  arrow_dict" << endl;
  o << "  begin" << endl;
  o << "    /tipy exch def /tipx exch def /taily exch def /tailx exch def" << endl;
  o << "    tailx taily moveto" << endl;
  o << "    tipx tipy arrowto" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "/draw_arrow { set_color arrow stroke } def" << endl;
  o << "/draw_arrow_head { set_color arrow_head stroke } def" << endl;
  o << "%% --------------  POLYGON - EDGES  ---------------------" << endl;
  o << "/draw_polygon_edge { set_color polygon_unclosed stroke } def" << endl;
  o << "/draw_polygon_arrow {" << endl;
  o << "  set_color" << endl;
  o << "  3 dict begin" << endl;
  o << "    /points exch def /tipy exch def /tipx exch def" << endl;
  o << "    points 1 sub polygon_unclosed" << endl;
  o << "    tipx tipy arrowto" << endl;
  o << "    stroke" << endl;
  o << "  end" << endl;
  o << "} def" << endl;
  o << "%% ----------------  LINESTYLES  ------------------------" << endl;
  o << "/solid  { [ ] } def" << endl;
  o << "/dashed { [ 6 units ] } def" << endl;
  o << "/dotted { [ 1 unit 6 units ] } def" << endl;
  o << "/set_line_style { 0 setdash } def" << endl;
  o << "%% ------------------  INITIAL  -------------------------" << endl;
  o << "1 1 scale" << endl;
  o << "1 setlinewidth" << endl;
  o << "(Helvetica) 9 set_font" << endl;
  o << "%%EndProlog" << endl;
  o << "%% -------------------------------------------------------" << endl;
  o << "%%BeginProgram" << endl;
}

// ---------------------------------------------------------------------------

void PostScript::init() {
    init_color_names();
    x_width=21 * PSPixelPerCM;
    y_width=29 * PSPixelPerCM;
}

// ---------------------------------------------------------------------------

void PostScript::set_color(color c) { *this << c << " set_color\n"; }

// ---------------------------------------------------------------------------

void PostScript::set_origin(double x, double y) {
  *this << x << y << "translate\n";
}

// ---------------------------------------------------------------------------

void PostScript::scale(double f_x, double f_y) {
  *this << f_x << f_y << "set_scale\n";
}

// ---------------------------------------------------------------------------

void PostScript::set_line_width(int w) { *this << w << "set_line_width\n"; }

// ---------------------------------------------------------------------------

double PostScript::get_x_width() { return x_width; }
double PostScript::set_x_width(double new_x_width) {
  double old_x=x_width;
  x_width=new_x_width;
  return old_x;
}

// ---------------------------------------------------------------------------

double PostScript::get_y_width() { return y_width; }
double PostScript::set_y_width(double new_y_width) {
  double old_y=y_width;
  y_width=new_y_width;
  return old_y;
}

// ---------------------------------------------------------------------------

void PostScript::set_page_size(double new_x_width, double new_y_width) {
  set_x_width(new_x_width);
  set_y_width(new_y_width);
}

// ---------------------------------------------------------------------------

void PostScript::set_variable(string name, int value) {
  *this << "/" << name << " " << value << "def\n";
}

// ---------------------------------------------------------------------------

void PostScript::set_font(const char* name, int size) {
  *this << "(" << name << ") " << size << "set_font\n";
}   

// ---------------------------------------------------------------------------

void PostScript::draw_text(double x, double y, string t, color c) {
  *this << x << y << "(" << t << ") " << c << "draw_text\n";
}

void PostScript::draw_text(point p, string t, color c) {
  draw_text(p.xcoord(),p.ycoord(),t,c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_ctext(double x, double y,string t, color c) {
  *this << x << y << "(" << t << ") " << c << "draw_ctext\n";
}

void PostScript::draw_ctext(point p, string t, color c) {
  draw_ctext(p.xcoord(),p.ycoord(),t,c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_circle(double x, double y, double r, color c) {
  *this << x << y << r << c << "draw_circle\n";
}

void PostScript::draw_circle(point p, double r, color c) {
  draw_circle(p.xcoord(),p.ycoord(),r,c);
}

void PostScript::draw_circle(const circle& c, color clr) {
  draw_circle(c.center(),c.radius(),clr);
}                        

// ---------------------------------------------------------------------------

void PostScript::draw_disc(double x, double y, double r, color c) {
  *this << x << y << r << c << "draw_disc\n";
}

void PostScript::draw_disc(point p, double r, color c) {
  draw_disc(p.xcoord(),p.ycoord(),r,c);
}

void PostScript::draw_disc(const circle& c, color clr) {
  draw_disc(c.center(),c.radius(),clr);
}                        

// ---------------------------------------------------------------------------

void PostScript::draw_arrow(double x1, double y1, double x2, double y2, color c) {
  *this << x1 << y1 << x2 << y2 << c << "draw_arrow\n";
}

void PostScript::draw_arrow(point p, point q, color c) {
  draw_arrow(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c);
}

void PostScript::draw_arrow(const segment& seg, color c) {
  draw_arrow(seg.source(),seg.target(),c);
}    

// ---------------------------------------------------------------------------

void PostScript::draw_segment(double x1, double y1, double x2, double y2, color c) {
  *this << x1 << y1 << x2 << y2 << c << "draw_segment\n";  
}

void PostScript::draw_segment(point p, point q, color c) {
  draw_segment(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c);
}

void PostScript::draw_segment(const segment& seg, color c) {
  draw_segment(seg.source(),seg.target(),c);
}    

// ---------------------------------------------------------------------------

void PostScript::set_line_style(line_style ls) {
  string str("solid");
  if (ls == dotted) str="dotted";
  if (ls == dashed) str="dashed";
  *this << str << " set_line_style\n";
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

void PostScript::draw_rectangle(double x0, double y0, double x1, double y1, color c) {
  *this << x0  << y0 << x1 << y1 << c << "draw_rectangle\n";
}

// ---------------------------------------------------------------------------

void PostScript::draw_filled_rectangle(double x0, double y0, double x1, double y1, color c) {
  *this << x0  << y0 << x1 << y1 << c << "draw_filled_rectangle\n";
}

// ---------------------------------------------------------------------------

void PostScript::draw_ellipse(double x, double y, double r1, double r2, color c) {
  *this << x << y << r1 << r2 << c << "draw_ellipse\n";
}

void PostScript::draw_ellipse(point p, double r1, double r2, color c) {
  draw_ellipse(p.xcoord(),p.ycoord(),r1,r2,c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_filled_ellipse(double x, double y, double r1, double r2, color c) {
  *this << x << y << r1 << r2 << c << "draw_filled_ellipse\n";
}

void PostScript::draw_filled_ellipse(point p, double r1, double r2, color c) {
  draw_ellipse(p.xcoord(),p.ycoord(),r1,r2,c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_circle_node(double x, double y, double r, color c) {
  *this << x << y << r << c << "draw_circle_node\n";
}

void PostScript::draw_circle_node(point p, double r, color c) {
  draw_circle_node(p.xcoord(),p.ycoord(),r,c);
}

void PostScript::draw_circle_node(const circle& c, color clr) {
  draw_circle_node(c.center(),c.radius(),clr);
}                        

// ---------------------------------------------------------------------------

void PostScript::draw_rectangle_node(double x0, double y0, double x1, double y1, color c) {
  *this << x0 << y0 << x1 << y1 << c << "draw_rectangle_node\n";
}

// ---------------------------------------------------------------------------

void PostScript::draw_ellipse_node(double x, double y, double r1, double r2, color c) {
  *this << x << y << r1 << r2 << c << "draw_ellipse_node\n";
}

void PostScript::draw_ellipse_node(point p, double r1, double r2, color c) {
  draw_ellipse_node(p.xcoord(),p.ycoord(),r1,r2,c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_polygon(const list<point>& P, color c) {
  point p;
  forall(p,P) *this << p.xcoord() << p.ycoord(); 
  *this << P.size() << c << "draw_polygon\n";
}

void PostScript::draw_polygon(const polygon& P, color c) {
  draw_polygon(P.vertices(),c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_filled_polygon(const list<point>& P, color c) {
  point p;
  forall(p,P) *this << p.xcoord() << p.ycoord(); 
  *this << P.size() << c << "draw_filled_polygon\n";
}

void PostScript::draw_filled_polygon(const polygon& P, color c) {
  draw_filled_polygon(P.vertices(),c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_polygon_edge(const list<point>& P, color c) {
  point p;
  forall(p,P) *this << p.xcoord() << p.ycoord();
  *this << P.size() << c << "draw_polygon_edge\n";
}

void PostScript::draw_polygon_edge(const polygon& P, color c) {
  draw_polygon_edge(P.vertices(),c);
}

// ---------------------------------------------------------------------------

void PostScript::draw_polygon_arrow(const list<point>& P, color c) {
  point p;
  forall(p,P) *this << p.xcoord() << p.ycoord();
  *this << P.size() << c << "draw_polygon_arrow\n";
}

void PostScript::draw_polygon_arrow(const polygon& P, color c) {
  draw_polygon_arrow(P.vertices(),c);
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// ----------------------------  Operators  ----------------------------------
// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, const circle& c) {
  ps.draw_circle(c);
  return ps;
}

// ---------------------------------------------------------------------------

PostScript& operator << (PostScript& ps, const segment& s) {
  ps.draw_segment(s);
  return ps;
}

// ---------------------------------------------------------------------------

ostream& operator << (ostream& o, PostScript& ps) {
  char *ps_str=ps.str();
  ps.header(o);
  ps.prolog(o);
  o << ps_str;
  ps.footer(o);
  delete(ps_str);
  return o;
} 

// ---------------------------------------------------------------------------

