/*******************************************************************************
+
+  LEDA 3.5
+
+  ps_file.h
+
+  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.
+ 
*******************************************************************************/
#ifndef LEDA_PS_FILE_H
#define LEDA_PS_FILE_H

/*{\Manpage {ps_file} {} {Postscript Files}}*/


#include <iostream.h>
#include <stdlib.h>
#include <math.h>

#include <LEDA/basic.h>
#include <LEDA/list.h>
#include <LEDA/string.h>
#include <LEDA/stream.h>
#include <LEDA/point.h>
#include <LEDA/segment.h>
#include <LEDA/line.h>
#include <LEDA/circle.h>
#include <LEDA/polygon.h>
#include <LEDA/color.h>
#include <LEDA/window.h>

enum output_mode {gray_mode,colored_mode};

static const double PIXEL    =2.54/72.0;
static const double HEIGHT   =23.5;
static const double WIDTH    =16.0;

class ps_file_pair {
  friend class ps_file;
  color c;
  double grayvalue;
public:
  ps_file_pair(): c(black),grayvalue(0) {}
  ps_file_pair(color col,double d): c(col),grayvalue(d) {}
  friend istream& operator>>(istream& in,ps_file_pair&) { return in; }
};



class ps_file {

/*{\Mdefinition
The date type |\Mname| is a graphical input/output interface for the
familiar LEDA drawing operations of two-dimensional geometry. Unlike
the data type |window|, the output produced by a |\Mname| object is
\emph{permanent}, i.e., it is not lost after exiting the C++-program as
it is saved in an output file. 

An instance of type |\Mname| is (as far as the user takes notice of it)
an ordinary ASCII file that contains the source code of the graphics
output in the PostScript description language. After running the
C++-program, the file is created in the user's current working
directory and can later be handled like any other PostScript file, i.e., it
may be viewed, printed etc.

Of course, features like a panel section (as in |window| type
instances) don't make sense for a representation that is not supposed
to be displayed on the screen and interactively worked with by the
user. Therefore, only drawing operations are applicable to a |\Mname|.
instance.

|\Mname| was implemented by 
\begin{center}
Thomas Wahl\\ 
Lehrstuhl für Informatik I\\
Universit\"at W\"urzburg\\
\end{center}
The complete user manual can be found in LEDAROOT/Manual/contrib.
}*/


private:
  static const string VERSION;
  static const short  X_SHIFT;
  static const short  Y_SHIFT;
#ifndef PI
  static const double PI;
#endif
  static const double SIZE;
  static const string DEFAULT_FONT;
  static const double DEFAULT_FACTOR;

  string       filename;
  file_ostream file;
  double       width, height;
  double       X0,X1,Y0,Y1;
  double       scaling;
  bool         must_scale;
  double       bbx,bby;
  bool         draw_bb;
  short        page;
  output_mode  outputmode;
  list<ps_file_pair>   grayvalue_list;
  color        fg_col;
  double       linewidth;
  double       unitlinewidth;
  line_style   linestyle;
  double       nodewidth;
  double       crosswidth;
  double       arrowlength;
  double       arrowangle;
  string       textfont;
  double       fontsize;
  text_mode    textmode;

  void initialize();
  void scale_xcoord(double&);
  void scale_xcoord(double&,double&);
  void scale_ycoord(double&);
  void scale_ycoord(double&,double&);
  void scale_radius(double&);
  list_item grayvalue_item(color);
  void set_defaults();
  void set_old_values();
  void change_color(color);
  void change_rgb(color);
  void change_line_style(line_style);
  void new_font();

  static inline int round(double d);
  static inline bool exor(bool,bool);
  static inline double dist(double,double,double,double);
  static inline double dist(point,point);


public:
  // Constructors, destructors, initializers
  ps_file(double w, double h=HEIGHT, string name="unnamed.ps");
  ps_file(string name="unnamed.ps");
  void init(double, double, double);
  void newpage();
  void clear() { newpage(); }
  void finish_old_page();
  void newfile(double w, double h=HEIGHT, string name="unnamed.ps");
  void newfile(string name="unnamed.ps");
  void close();
  ~ps_file();

  // Setting parameters
  bool        set_draw_bb(bool);
  output_mode set_output_mode(output_mode);
  double      set_gray_value(color,double);
  color       set_color(color);
  double      set_line_width(double);
  double      set_unit_line_width(double);
  line_style  set_line_style(line_style);
  double      set_node_width(double);
  double      set_cross_width(double);
  double      set_arrow_length(double);
  double      set_arrow_angle(double);
  string      set_text_font(string);
  double      set_font_size(double);
  text_mode   set_text_mode(text_mode);

  // Reading parameters
  bool        get_draw_bb();
  output_mode get_output_mode();
  double      get_gray_value(color);
  color       get_color();
  double      get_line_width();
  double      get_unit_line_width();
  line_style  get_line_style();
  double      get_node_width();
  double      get_cross_width();
  double      get_arrow_length();
  double      get_arrow_angle();
  string      get_text_font();
  double      get_font_size();
  text_mode   get_text_mode();

  // Drawing operations. I use the DEF_COLOR constant from the
  // x_window.h header file, as the ps_file::fg_col parameter is not a
  // static member (it may be different for several ps_file instances).

  // Drawing points
  void draw_point(double, double, color c=DEF_COLOR);
  void draw_point(point, color c=DEF_COLOR);
  void draw_pixel(double, double, color c=DEF_COLOR);
  void draw_pixel(point, color c=DEF_COLOR);

  // Drawing line segments
  void draw_segment(double, double, double, double, color c=DEF_COLOR);
  void draw_segment(point, point, color c=DEF_COLOR);
  void draw_segment(segment, color c=DEF_COLOR);

  // Drawing lines
  void draw_line(double, double, double, double, color c=DEF_COLOR);
  void draw_line(point, point, color c=DEF_COLOR);
  void draw_line(segment, color c=DEF_COLOR);
  void draw_line(line, color c=DEF_COLOR);
  void draw_hline(double, color c=DEF_COLOR);
  void draw_vline(double, color c=DEF_COLOR);
  void draw_arc(double, double, double, double, double, color c=DEF_COLOR);
  void draw_arc(point, point, double, color c=DEF_COLOR);
  void draw_arc(segment, double, color c=DEF_COLOR);

  // Drawing arrows
  void draw_arrow_head(point, double, color c=DEF_COLOR);
  void draw_arrow(double, double, double, double, color c=DEF_COLOR);
  void draw_arrow(point, point, color c=DEF_COLOR);
  void draw_arrow(segment, color c=DEF_COLOR);
  void draw_arc_arrow(double, double, double, double, double, color c=DEF_COLOR);
  void draw_arc_arrow(point, point, double, color c=DEF_COLOR);
  void draw_arc_arrow(segment, double, color c=DEF_COLOR);

  // Drawing circles
  void draw_circle(double, double, double, color c=DEF_COLOR);
  void draw_circle(point, double, color c=DEF_COLOR);
  void draw_circle(circle, color c=DEF_COLOR);
  void draw_ellipse(double, double, double, double, color c=DEF_COLOR);
  void draw_ellipse(point, double, double, color c=DEF_COLOR);

  // Drawing discs
  void draw_disc(double, double, double, color c=DEF_COLOR);
  void draw_disc(point, double, color c=DEF_COLOR);
  void draw_disc(circle, color c=DEF_COLOR);
  void draw_filled_ellipse(double, double, double, double, color c=DEF_COLOR);
  void draw_filled_ellipse(point, double, double, color c=DEF_COLOR);

  // Drawing polygons
  void draw_polygon(const list<point>&, color c=DEF_COLOR);
  void draw_polygon(polygon, color c=DEF_COLOR);
  void draw_filled_polygon(const list<point>&, color c=DEF_COLOR);
  void draw_filled_polygon(polygon, color c=DEF_COLOR);
  void draw_rectangle(double, double, double, double, color c=DEF_COLOR);
  void draw_rectangle(point, point, color c=DEF_COLOR);
  void draw_box(double, double, double, double, color c=DEF_COLOR);
  void draw_box(point, point, color c=DEF_COLOR);
  void draw_triangle(point, point, point, color c=DEF_COLOR);
  void draw_filled_triangle(point, point, point, color c=DEF_COLOR);

  // Drawing functions
  void plot_xy(double, double, win_draw_func, color c=DEF_COLOR);
  void plot_yx(double, double, win_draw_func, color c=DEF_COLOR);

  // Drawing text
  void draw_text(double, double, string, color c=DEF_COLOR);
  void draw_text(point, string, color c=DEF_COLOR);
  void draw_ctext(double, double, string, color c=DEF_COLOR);
  void draw_ctext(point, string, color c=DEF_COLOR);

  // Drawing nodes
  void draw_node(double, double, color c=DEF_COLOR);
  void draw_node(point, color c=DEF_COLOR);
  void draw_filled_node(double, double, color c=DEF_COLOR);
  void draw_filled_node(point, color c=DEF_COLOR);
  void draw_text_node(double, double, string, color c=DEF_COLOR);
  void draw_text_node(point, string, color c=DEF_COLOR);
  void draw_int_node(double, double, int, color c=DEF_COLOR);
  void draw_int_node(point, int, color c=DEF_COLOR);

  // Drawing edges
  void draw_edge(double, double, double, double, color c=DEF_COLOR);
  void draw_edge(point, point, color c=DEF_COLOR);
  void draw_edge(segment, color c=DEF_COLOR);
  void draw_edge_arrow(double, double, double, double, color c=DEF_COLOR);
  void draw_edge_arrow(point, point, color c=DEF_COLOR);
  void draw_edge_arrow(segment, color c=DEF_COLOR);
  void draw_arc_edge(double, double, double, double, double, color c=DEF_COLOR);
  void draw_arc_edge(point, point, double, color c=DEF_COLOR);
  void draw_arc_edge(segment, double, color c=DEF_COLOR);
  void draw_arc_edge_arrow(double, double, double, double, double, color c=DEF_COLOR);
  void draw_arc_edge_arrow(point, point, double, color c=DEF_COLOR);
  void draw_arc_edge_arrow(segment, double, color c=DEF_COLOR);

  // overloaded output stream operators
  ps_file& operator << (point p)   {draw_point(p);   return *this; }
  ps_file& operator << (segment s) {draw_segment(s); return *this; }
  ps_file& operator << (line l)    {draw_line(l);    return *this; }
  ps_file& operator << (circle C)  {draw_circle(C);  return *this; }
  ps_file& operator << (polygon P) {draw_polygon(P); return *this; }

};  // End class ps_file

#endif  // #ifndef LEDA_PS_FILE_H
