/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * ps.c - interface with the PostScript languaje.
 * 
 * Author:          J. G. Antuna Roces
 *                  EECS Department
 *                  University of Oviedo
 * Date:            Fri Jan 22 1993
 * Copyright (c) 1993, J. G. Antuna Roces
 *
 *
 * LUG's Author:    Raul Rivero
 *                  Mathematics Dept.
 *                  University of Oviedo
 * Date:            Wed Feb 17 1993
 *
 */

#include <lug.h>
#include <lugfnts.h>

extern int LUGverbose;

write_ps_file( name, image )
char *name;
bitmap_hdr *image;
{
  write_ps_file_dimensions( name, image, 19.0, 0.0 );
}

write_ps_file_dimensions( name, image, width, length )
char *name;
bitmap_hdr *image;
double width, length;
{
  ImagenGrisesPs( image->xsize, image->ysize, image->r, 19.0, 27.0, name);
}

ImagenGrisesPs( AnchoPix, AltoPix, Datos, Anchura, Altura, Fichero ) 
int AnchoPix, AltoPix;
unsigned char Datos[];
double Anchura, Altura;
char *Fichero;
/***************************   DOCUMENTACION   *********************************

   > Implementado el 15 de Enero de 1993 por J. G. Antuna Roces
   > Modificado el 22 de Enero de 1993 por J. G. Antuna Roces
        Si no se proporciona la dimension vertical que la imagen final ha de
        tener, esta se calcula a partir de la dimension horizontal y de la
        relacion entre el ancho y el alto en pixels de la misma.

   Parametros de entrada .......................................................

      AnchoPix : Dimension horizontal en pixels de la imagen a representar
      AltoPix  : Dimension vertical en pixels de la imagen a representar
      Datos [] : Tonalidad de gris de cada pixel por filas de arriba a abajo
      Anchura  : Tamano horizontal de la imagen final en centimetros
      Altura   : Tamano vertical en centimetros (si es cero, se calcula)
      Fichero  : Denominacion del fichero PostScript de salida

   Retorno de la funcion .......................................................

       1 : Indica exito de la funcion.
      -1 : Error al intentar abrir el fichero de salida;
      -2 : Ancho de imagen en centimetros invalida (negativa,nula o muy pequena)
      -3 : Alto de imagen en centimetros invalida (negativa,nula o muy pequena)
      -4 : Anchura de imagen en pixels no valida (negativa o nula)
      -5 : Altura de imagen en pixels no valida (negativa o nula)

   Descripcion .................................................................

      Permite obtener un fichero PostScript que generara una imagen a partir
      de los datos proporcionados mediante los parametros de entrada. Esta
      imagen se presentara centrada en una pagina DIN A4, en posicion normal
      o apaisada, en funcion de cual de sus dimensiones sea la mayor (la
      vertical o la horizontal, respectivamente).

      La informacion necesaria para generar la imagen, ademas de los tamanos
      horizontal y vertical que esta ha de tener al ser representada en la
      pagina, consiste en una secuencia de valores que indican la tonalidad
      de gris correspondiente a cada uno de los puntos de la misma (un valor
      entre 0 y 255), descritos de izquierda a derecha y de arriba a abajo,
      comenzando por la esquina superior izquierda.

      Es necesario indicar, ademas, la dimension horizontal y vertical en
      puntos de la imagen a representar y, por supuesto, el numero de valores
      debera coincidir con el producto de esas dos cantidades.

      Si como altura final de la imagen a mostrar en la pagina se da un valor
      nulo, esta se calcula a partir del ancho indicado para la misma, de forma
      que se mantenga entre ambos valores la relacion existente entre el ancho
      y el alto de dicha imagen, cuando estos valores se miden en pixels.

   Implementacion ..............................................................

      El codigo de la funcion puede considerarse dividido en tres partes. Una
      primera en la que se verifica  la validez y consistencia de los datos
      proporcionados mediante los parametros de entrada y se procede al calculo
      de aquellos valores necesarios para la ejecucion. Una segunda en la que
      se obtiene el nucleo del codigo fuente PostScript, necesario para la
      generacion de la imagen y, por ultimo, una tercera parte que proporciona
      los datos necesarios para la obtencion de la imagen, representados en el
      formato hexadecimal que requiere el procedimiento PostScript.

      El codigo fuente PostScript, compactado en lo posible, define una serie
      de valores que parametrizan la imagen a representar (anchura, altura,
      posicion,...) junto con la funcion cuya llamada generara dicha imagen a
      partir de los datos de la misma incluidos en el fichero PostScript.

*******************************************************************************/

{ int NoErr               = 1;  /* Codigos de retorno de la funcion */
  int ErrFicheroSalida    = -1;
  int ErrAnchoInvalido    = -2;
  int ErrAltoInvalido     = -3;
  int ErrAnchoPixInvalido = -4;
  int ErrAltoPixInvalido  = -5;

  int LimiteEscritura = 40;  /* Cuantos valores hexadecimales por linea */
  int MaxPuntosXPs    = 558; /* Dimensiones de un DIN A4 en PostScript */
  int MaxPuntosYPs    = 789;

  int      CoordX;        /* Para situar la imagen en la pagina */
  int      CoordY;
  int      SizeX;         /* Para calcular tamano en puntos PostScript */
  int      SizeY;
  int      Rotacion;      /* Para girar o no la imagen en la pagina */
  int      ContEscritura; /* Cuenta datos hexadecimales de cada linea */
  long int ContLectura;   /* Cuenta el numero de puntos leidos */
  long int LimiteLectura; /* Maximo de datos hexadecimales por linea */
  FILE     *Salida;       /* Denominacion del fichero de salida */

  /* Verifica la validez de los datos obtenidos como parametros de entrada */

  if ( AnchoPix <= 0 ) return (ErrAnchoPixInvalido);
  if ( AltoPix <= 0 ) return (ErrAltoPixInvalido);
  if ( Anchura <= 0.0 ) return (ErrAnchoInvalido);
  if ( Altura <= 0.0 ) SizeY = (int) (Altura/Anchura*SizeX);

  /* Calcula las dimensiones de la imagen medidas en puntos PostScript */

  SizeX = (int) ((Anchura / 2.71) * 72.0);
  SizeY = (int) ((Altura  / 2.71) * 72.0);

  if ( SizeX <= 0 ) return (ErrAnchoInvalido);
  if ( SizeY <= 0 ) return (ErrAltoInvalido);

  /* Obtiene las coordenadas de la esquina inferior izquierda de la imagen
     para situar esta en la pagina y verifica si es necesario rotar la misma */

  if ( SizeX > SizeY )
    { Rotacion = 90;
      CoordX = (MaxPuntosXPs - SizeY) / 2 + SizeY;
      CoordY = (MaxPuntosYPs - SizeX) / 2;
    }
  else 
    { Rotacion = 0;
      CoordX = (MaxPuntosXPs - SizeX) / 2;
      CoordY = (MaxPuntosYPs - SizeY) / 2;
    }

  /* Numero de puntos que forman la imagen */

  LimiteLectura = (long int)AnchoPix*(long int)AltoPix;

  /* Abre el fichero de salida PostScript y verifica dicha apertura */

  Salida = fopen (Fichero,"wb");
  if ( Salida == NULL ) return (ErrFicheroSalida);

  /* Codigo fuente en PostScript para la generacion de la imagen */

  fprintf (Salida,"%%!PS-Adobe-2.0\n");
  fprintf (Salida,"%%Creator: LUG Library\n");
  fprintf (Salida,"%%PS converter by J.G.Antuna Roces. @1993\n");
  fprintf (Salida,"%%EndComments\n\n");
  fprintf (Salida,"/Px %d def /Py %d def /S Px string def\n",AnchoPix,AltoPix);
  fprintf (Salida,"/Dib { gsave Px Py 8 [Px 0 0 Py neg 0 Py]\n");
  fprintf (Salida,"         { currentfile S readhexstring pop } ");
  fprintf (Salida,"image grestore} def\n");
  fprintf (Salida,"%d %d translate %d rotate ",CoordX,CoordY,Rotacion);
  fprintf (Salida,"%d %d scale\n",SizeX,SizeY);
  fprintf (Salida,"Dib\n");

  /* Volcado de valores de cada uno de los pixels de la imagen.Se escriben en
     formato hexadecimal, incluyendo por cada linea <LimiteEscritura> datos   */

  ContEscritura = 0;

  for (ContLectura = 0; ContLectura < LimiteLectura; ContLectura++)
    if ( ++ContEscritura == LimiteEscritura )
      { ContEscritura = 0;
        fprintf(Salida,"%02x\n",Datos [ContLectura]);
      }
    else fprintf (Salida,"%02x",Datos [ContLectura]);

  /* Anade el comando <showpage> (sin el no se ve la imagen) y cierra fichero */

  fprintf (Salida,"\nshowpage\n");
  fclose (Salida);
  return (NoErr);
};
