Logo Search packages:      
Sourcecode: vertex version File versions

print.c

/*
                              Print Outputting
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sched.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "../include/strexp.h"
#include "../include/string.h"
#include "../include/disk.h"
#include "../include/prochandle.h"

#include "print.h"


int PrintWritePSImage(
      FILE *fp,
      print_parms_struct *parms,
        int format,     /* PrintFormatRGBA, PrintFormatRGB, or
                         * PrintFormatGamma.
                         */
        int width,      /* In pixels. */
        int height,
        const void *buf
);
static pid_t PrintDoExec(const char *command);
print_job_struct *PrintJobNew(    
        const char *command,
        const char *file,               /* Path to postscript file. */
        int coppies,
      int remove_file_when_done
);
int PrintJobManage(print_job_struct *pj);
void PrintJobDelete(print_job_struct *pj);


/*
 *    Writes a postscript file to the stream pointed to by fp.
 *
 *    The print parameters are specified in the parms structure, they
 *    will be passed directly to the written postscript file and not
 *    checked for validility.
 *
 *    Orientation is assumed to have already been performed prior to
 *    calling this function, no orientation will be done within this
 *    function.
 *
 *    The image data is specified by buf, which size is calculated
 *    by the given format, width, and height.
 *
 *    Bytes per pixel is determined by format, as follows:
 *
 *    PrintFormatRGBA         4 bytes per pixel
 *    PrintFormatRGB          3 bytes per pixel
 *    PrintFormatGamma  1 bytes per pixel
 *
 *    Returns 0 on success, or non-zero on error.
 */
int PrintWritePSImage(
        FILE *fp,
        print_parms_struct *parms,
        int format,     /* PrintFormatRGBA, PrintFormatRGB, or
                         * PrintFormatGamma.
                         */
        int width,      /* Size of buffer in pixels. */
        int height,
        const void *buf
)
{
      int bytes_per_pixel = 1;      /* Bytes per pixel of given buf. */
      int bytes_per_pixel_out = 1;  /* Bytes per pixel of output data. */


      if((fp == NULL) || (buf == NULL) || (parms == NULL))
          return(-1);

      /* Determine bytes per pixel. */
        switch(format)
      {
        case PrintFormatRGBA:
          bytes_per_pixel = 4;
          bytes_per_pixel_out = 3;
          break;

        case PrintFormatRGB:
          bytes_per_pixel = 3;
          bytes_per_pixel_out = 3;
          break;

        case PrintFormatGamma:
          bytes_per_pixel = 1;
          bytes_per_pixel_out = 1;
            break;
      }


      /* Begin writing postscript data to the stream fp. */

      /* Header. */

      /* Format identifier. */
        fprintf(
          fp,
"%%!PS-Adobe-3.0\n"
      );
        /* Creator. */
        fprintf(
            fp,
"%%%%Creator: %s\n",
            "Generic PostScript Generator"
        );
      /* Title. */
        fprintf(
            fp,
"%%%%Title: %s\n",
          "Untitled"
        );
      /* Date. */
/*
        fprintf(
            fp,
"%%%%CreationDate: ???\n",
            ???
        );
 */
      /* Document data type. */
        fprintf(
            fp,
"%%%%DocumentData: Clean7Bit\n"
        );

      /* Pages. */
        fprintf(
            fp,
"%%%%Pages: %i\n",
            1
        );

      /* Bounding box (in units of pixels). */
        fprintf(
            fp,
"%%%%BoundingBox: %i %i %i %i\n",
            0, 0,
            parms->paper_width - 1, parms->paper_height - 1
        );     

      /* End comments. */
        fprintf(
            fp,   
"%%%%EndComments\n"
      );


      /* Begin prolong. */
      fprintf(
            fp,
"%%%%BeginProlog\n\n"
      );

        fprintf(
            fp,
"%% Use own dictionary to avoid conflicts\n"
        );
        fprintf(
            fp,
"5 dict begin\n"
        );

        /* End prolong. */
        fprintf(
            fp,
"%%%%EndProlog\n\n"
        );



      /* Page set. */
      fprintf(
            fp,
"%%%%Page: %i %i\n\n",
          1, 1
        );

      /* Translate for offset. */
        fprintf(
            fp,
"%% Translate for offset (target at lower-left corner)\n"
        );     
        fprintf(
            fp,
"%i %i translate\n",
            parms->x,
            parms->paper_height - parms->y - height
        );

      /* Scale. */
      fprintf(
            fp,
"%% Scale of image from unit size\n"
        );
        fprintf( 
            fp,
"%.5f %.5f scale\n\n",
            (double)width, (double)height
        );

      /* Scan line buffer. */
        fprintf(
            fp,
"%% Buffer to store one scan line (width * bytes_per_pixel)\n"
        );
        fprintf(
            fp,
"/scanline %i %i mul string def\n",
          width, bytes_per_pixel_out
        );

      /* Image geometry. */
        fprintf(
            fp,
"%% Image geometry\n"
        );
        fprintf(
            fp,
"%i %i %i\n",
            width, height, 8
        );

        /* Transformatino matrix. */
        fprintf(
            fp,
"%% Transformation matrix\n"
        );
        fprintf(
            fp,
"[ %i %i %i %i %i %i ]\n",
            width,
          0,
          0,
          height * -1,
          0,
          height
        );


      switch(parms->visual)
      {
        case PrintColor:
          fprintf(
            fp,
"{ currentfile scanline readhexstring pop } false 3\n"
          );
          fprintf(
            fp,
"colorimage\n"
          );
          break;

        case PrintGreyScale:
            fprintf(
                fp,
"{ currentfile scanline readhexstring pop }\n"
          );
            fprintf(
                fp,
"image\n"
          );
          break;

        case PrintBlackAndWhite:
            fprintf(
                fp,
"{ currentfile scanline readhexstring pop }\n"
            );
            fprintf(
                fp,
"image\n"
            );
            break;
      }

      /* Begin writing image data. */
      if(1)
      {
          int w, h, col = 0;
          int line_max = 70;
            u_int8_t *ptr8 = (u_int8_t *)buf;
          u_int8_t *ptr8_cur;

            for(h = 0; h < height; h++)
            {
                for(w = 0; w < width; w++)
                {
                    /* Write image pixel.
                     * aaaa aaaa rrrr rrrr gggg gggg bbbb bbbb
                     */
                    switch(format)
                {
                  case PrintFormatRGBA:
                  ptr8_cur = &ptr8[
                      (h * width * 4) + (w * 4)
                  ];
                  /* Red. */
                        fprintf(fp, "%.2x",
                            *ptr8_cur++
                  );
                  /* Green. */
                        fprintf(fp, "%.2x",
                      *ptr8_cur++
                  );
                  /* Blue. */
                        fprintf(fp, "%.2x",
                            *ptr8_cur++
                        );
                  /* Skip alpha. */

                        col += 6;
                  break;

                      case PrintFormatRGB:
                        ptr8_cur = &ptr8[
                            (h * width * 3) + (w * 3)
                        ];
                        /* Red. */
                        fprintf(fp, "%.2x",
                            *ptr8_cur++
                        );
                        /* Green. */
                        fprintf(fp, "%.2x",  
                            *ptr8_cur++
                        );
                        /* Blue. */
                        fprintf(fp, "%.2x",
                            *ptr8_cur++
                        );

                        col += 6; 
                        break;

                      case PrintFormatGamma:
                        ptr8_cur = &ptr8[  
                            (h * width * 1) + (w * 1)
                        ];
                        /* Gamma. */
                        fprintf(fp, "%.2x",
                            *ptr8_cur++
                        );

                        col += 2;
                        break;
                }

                /* Columns exceeded? */
                    if(col >= line_max)
                    {
                        col = 0;
                        fputc('\n', fp);
                    }
                }

                col = 0;
                fputc('\n', fp);
            }
        }

        fputc('\n', fp);


        /* Footer. */
      fprintf(
          fp,
"showpage\n\
%%%%Trailer\n\
end\n\
%%%%EOF\n"
      );

      return(0);
}


/*
 *    Runs the given print command non-blocking, returns the pid
 *    of the child process or 0 on error.
 */
static pid_t PrintDoExec(const char *command)
{
      if(command == NULL)
          return(0);

        return(Exec(command));
}

/*
 *    Procedure to run the print command to print the specified post
 *    script file.
 *
 *    Returns a newly allocated job structure or NULL on error.
 */
print_job_struct *PrintJobNew(
        const char *command,
        const char *file,               /* Path to postscript file. */
        int coppies,
      int remove_file_when_done
)
{
      const char *token_string = "%f";
      int subs_needed;
      const char *cstrptr;
      char *new_command;
      int len;

      pid_t pid;

      print_job_struct *pj;


      if(file == NULL)
          return(NULL);

      /* Use default print command? */
      if(command == NULL)
          command = PrintDefaultPrintCommand;

      if((*command) == '\0')
          return(NULL);


      /* Calculate number of substitutions needed in command
       * string.
       */
      subs_needed = 0;
      cstrptr = strstr(command, token_string);
      while(cstrptr != NULL)
      {
          subs_needed++;
          cstrptr = strstr(cstrptr + 1, token_string);
      }

      /* Calculate new command string length needed. */
      len = (strlen(command) +
          (strlen(file) * subs_needed) + (10 * subs_needed)
      );
      new_command = (char *)malloc((len + 1) * sizeof(char));
      if(new_command == NULL)
          return(NULL);
      strcpy(new_command, command);

      /* Substitute. */
      substr(new_command, token_string, file);

      /* Execute new command. */
      pid = PrintDoExec(new_command);
      if(pid <= 0)
      {
          /* Could not run command. */
          free(new_command);
          return(NULL);
      }

      /* Successfully ran print job process, now allocate a new
       * print job structure.
       */
      pj = (print_job_struct *)calloc(
          1, sizeof(print_job_struct)
      );
      if(pj != NULL)
      {
          pj->pid = pid;
          pj->command = strdup(new_command);
          pj->file = strdup(file);
          pj->coppies = coppies;
          pj->coppies_printed = 0;
          pj->remove_file_when_done = remove_file_when_done;
      }

      /* Free new allocated command string. */
      free(new_command);

      return(pj);
}

/*
 *    Manages the given print job.
 *
 *    Returns true if the job should be kept (managed again) or
 *    false if the job should be deleted.
 */
int PrintJobManage(print_job_struct *pj)
{
      pid_t pid;
        struct sched_param sp;
      int pid_not_there;


      if(pj == NULL)
          return(0);

      /* Get process id. */
      pid = pj->pid;
      /* Invalid process id? */
      if(pid <= 0)
          return(0);
      /* Process no longer exists? */
      pid_not_there = 0;
        if(sched_getparam(pid, &sp))
      {
          switch(errno)
          {
            case ESRCH: /* No such pid. */
            pid_not_there = 1;
            break;

            case EPERM: /* Insufficient permission. */
            pid_not_there = 1;
            break;

            default:
            perror("sched_getparam");
            pid_not_there = 1;
            break;
          }
      }
      if(pid_not_there)
      {
          /* Print job pid not exist, this implies print job has
           * finished.
           */
          pj->pid = pid = 0;

          /* Increment the number of documents printed (or attempted
           * to be printed).
           */
          if(pj->coppies_printed < 0)
            pj->coppies_printed = 0;
          pj->coppies_printed++;

          /* Check if we need to make another print. */
          if(pj->coppies_printed < pj->coppies)
          {
            /* Print another one. */
            pj->pid = PrintDoExec(pj->command);
            if(pj->pid <= 0)
            {
                /* Could not print copy, return false. */
                return(0);
            }
            else
            {
                /* Print of copy successful, return true. */
                return(1);
            }
          }
          else
          {
            /* No more coppies to print, and print job finished.
             * Return false.
             */
            return(0);
          }
      }



      /* Return true. */
      return(1);
}

/*
 *    Deletes the given print job, deallocating all its
 *    resources and killing the print job process if it exists.
 *
 *    If the member remove_file_when_done was true, then the file
 *    referanced will be removed.
 */
void PrintJobDelete(print_job_struct *pj)
{
      if(pj == NULL)
          return;

      if(pj->pid > 0)
      {
          kill(pj->pid, SIGTERM);
          pj->pid = -1;
      }

      if((pj->remove_file_when_done) && (pj->file != NULL))
      {
          unlink(pj->file);

          free(pj->file);
          pj->file = NULL;
      }

      free(pj->command);
      free(pj->file);
      free(pj->title);
      free(pj->creator);

      free(pj);
}

Generated by  Doxygen 1.6.0   Back to index