/*----------------------------------------------------------------------------*
 | This file is part of DEU (Doom Editing Utilities), created by the DEU team:|
 | Raphael Quinet, Brendon Wyber, Ted Vessenes and others.  See README.1ST or |
 | the "about" dialog box for full credits.                                   |
 |                                                                            |
 | DEU is an open project: if you think that you can contribute, please join  |
 | the DEU team.  You will be credited for any code (or ideas) included in    |
 | the next version of the program.                                           |
 |                                                                            |
 | If you want to make any modifications and re-distribute them on your own,  |
 | you must follow the conditions of the DEU license.  Read the file LICENSE  |
 | in this directory or README.1ST in the top directory.  If do not have a    |
 | copy of these files, you can request them from any member of the DEU team, |
 | or by mail: Raphael Quinet, Rue des Martyrs 9, B-4550 Nandrin (Belgium).   |
 |                                                                            |
 | This program comes with absolutely no warranty.  Use it at your own risks! |
 *----------------------------------------------------------------------------*

 M_PRINT.C - Map printing routines

*/

#include "deu.h"
#include "d_config.h"
#include "d_main.h"
#include "w_levels.h"
#include "w_things.h"
#include "m_print.h"


/* the following is for PostScript Printing */

static void SendPSHead(FILE *prtout, double scale, char *mapname)
{
  /* PS header */
  fprintf(prtout, "%%!PS\n");
  fprintf(prtout, "%%%%Creator: Doom Editing Utilities %s\n", DEU_VERSION);
  fprintf(prtout, "%%%%Title: DEU Printout - %s\n", mapname);
  /* print misc. info at the bottom */
  fprintf(prtout, "/Times-Roman findfont\n");
  fprintf(prtout, "8 scalefont\n");
  fprintf(prtout, "setfont\n");
  fprintf(prtout, "%d %d moveto\n", 32, 32);
  fprintf(prtout, "(Level: %s) show\n", mapname);
  fprintf(prtout, "%d %d moveto\n", 275, 32);  /*! should be X - strlen(DEU_VERSION) * ... */
  fprintf(prtout, "(Printed using DEU %s) show\n", DEU_VERSION);
  fprintf(prtout, "%d %d moveto\n", 550, 32);
  if (DoomVersion == 0)
    fprintf(prtout,  "(REGISTER DOOM!) show\n");
  if (DoomVersion == 16)
    fprintf(prtout,  "(REGISTER HERETIC!) show\n");

  /* tell the printer what orientation we want */
  if (Config.printPortrait == TRUE)
    fprintf(prtout, "%f %f translate\n", PRINT_BORDER, PRINT_BORDER);
  else
    {
      fprintf(prtout, "%f %f translate\n", PRINT_BORDER, PRINT_LENGTH - PRINT_BORDER);
      fprintf(prtout, "-90 rotate\n");
    }

  /* tell the printer to scale based on our math. */
  fprintf(prtout, "%f %f scale\n", scale, scale );
  /* define a macro for printing Things */
  fprintf(prtout, "/thing\n");
  fprintf(prtout, "{ gsave\n");
  fprintf(prtout, "  setgray\n");
  fprintf(prtout, "  dup\n");
  fprintf(prtout, "  4 1 roll\n");
  fprintf(prtout, "  0 360 arc\n");
  fprintf(prtout, "  dup dup dup\n");
  fprintf(prtout, "  neg 0 rlineto\n");
  fprintf(prtout, "  currentpoint translate\n");
  fprintf(prtout, "  0 exch lineto\n");
  fprintf(prtout, "  0 0 moveto\n");
  fprintf(prtout, "  neg 0 lineto\n");
  fprintf(prtout, "  0 0 moveto\n");
  fprintf(prtout, "  neg 0 exch lineto\n");
  fprintf(prtout, "  stroke\n");
  fprintf(prtout, "  grestore\n");
  fprintf(prtout, "} def\n");
  /* define a macro for drawing lines */
  fprintf(prtout, "/line\n");
  fprintf(prtout, "{ setgray\n");
  fprintf(prtout, "  setlinewidth\n");
  fprintf(prtout, "  newpath\n");
  fprintf(prtout, "  moveto\n");
  fprintf(prtout, "  lineto\n");
  fprintf(prtout, "  stroke\n");
  fprintf(prtout, "} def\n");
  /* done! */
}


static void PSDrawLine(FILE *prtout, Int16 x1, Int16 y1, Int16 x2, Int16 y2, int thickness, float shade)
{
  fprintf(prtout, "%d %d %d %d %d %f line\n", x1, y1, x2, y2, thickness, shade);
}


static void PSDrawThing(FILE *prtout, Int16 x, Int16 y, Int16 radius, float shade)
{
  fprintf(prtout, "%d %d %d %f thing\n", x, y, radius, shade);
}



static void printPS(LevelPtr level, FILE *prtout, double scale)
{
  UInt16 i;
  int    thickness = 0; /*! why 0 ? */
  float  shade;

  /* send the header to the printer */
  SendPSHead(prtout, scale, level->dir->dir.name);

  /* draw the LineDefs */
  fprintf(prtout, "%%%%%%%%LINEDEFS%%%%%%%%\n");
  for (i = 0; i < level->num_linedefs; i++ )
    {
      if ((Config.printGraySecrets) && (level->linedefs[i].flags & 0x20))
        shade = 0.5;
      else
        shade = 0;
      if (Config.printThickImpass)
        {
          if (level->linedefs[i].flags & 0x01)
            thickness = 4;
          else
            thickness = 2;
        }
      PSDrawLine(prtout,
                 level->vertexes[level->linedefs[i].start].x - level->map_minX,
                 level->vertexes[level->linedefs[i].start].y - level->map_minY,
                 level->vertexes[level->linedefs[i].end].x - level->map_minX,
                 level->vertexes[level->linedefs[i].end].y - level->map_minY,
                 thickness, shade);
  }

  /* reset shade and LineWidth */
  shade = 0;
  fprintf(prtout, "2 setlinewidth\n");

  if (Config.printThings) /* If user wants to print things */
    {
      /* draw the Things */
      fprintf(prtout, "%%%%%%%%THINGS%%%%%%%%\n");
      for (i = 0; i < level->num_things; i++)
        PSDrawThing(prtout,
                    level->things[i].xpos - level->map_minX,
                    level->things[i].ypos - level->map_minY,
                    GetThingRadius(level->things[i].type),
                    shade);
    }
  /* tell Printer to print the page */
  fprintf(prtout, "showpage\n");
  /* the end! */
  fprintf(prtout, "%%%%EOF\n");
}



/* the following is for PCL Printing */

static void printPCL(LevelPtr level, FILE *prtout, double scale)
{
  /*! (Not implemented yet) */
}



/*
   Scale the WAD (common for both PS and PCL).
*/

static double ScaleWad(LevelPtr level)
{
  Int16 xsize, ysize;
  double xscale, yscale;

  xsize = level->map_maxX - level->map_minX;
  ysize = level->map_maxY - level->map_minY;

  /* Determine orientation of paper and scale */
  if (Config.printBestFit == TRUE)
    Config.printPortrait = (xsize < ysize);

  if (Config.printPortrait == TRUE)
    {
      xscale = (double) (PRINT_WIDTH - 2 * PRINT_BORDER) / xsize;
      yscale = (double) (PRINT_LENGTH - 2 * PRINT_BORDER) / ysize;
    }
  else
    {
      xscale = (double) (PRINT_LENGTH - 2 * PRINT_BORDER) / xsize;
      yscale = (double) (PRINT_WIDTH - 2 * PRINT_BORDER) / ysize;
    }
  return MIN(xscale, yscale);
}



/*
   Print a map to a file (PostScript or PCL).
*/

Bool PrintWad(LevelPtr level, char *filename)
{
  FILE   *prtout;
  double  scale;

  if ((prtout = fopen(filename, "wt")) == NULL)
    return FALSE;

  scale = ScaleWad(level);         /* scale the Wad to paper size */

  if (TRUE) /*! until the PCL code is done... */
    printPS(level, prtout, scale);  /* print to PostScript */
  else
    printPCL(level, prtout, scale); /* print to PCL        */
  fclose(prtout);
  return TRUE;
}


/* end of file */
