Logo Search packages:      
Sourcecode: felt version File versions  Download package

pslib.c

/* 
 * this code taken basically verbatim (changes and deletions only where
 * necessary) from the xmgr package by Paul J. Turner.  It looks like he
 * got if from somewhere else too, so credit to those folks as well.
 */

/* 
 *
 * driver for postscript printer
 *
 * courtesy of:
 *
 * Jim Hudgens
 * hudgens@ray.met.fsu.edu
 *
 * Further modifications by,
 * Ole Holm Nielsen
 * ohnielse@ltf.dth.dk
 *
 */

#include <stdio.h>
#include <ctype.h>
#include "version.h"

#define MAX_BUF_LEN 128

static void putps();
static int isoneof();
static void stripspecial ();

/* postscript page at scale = 0.25 */

/*
 * the following defines are tuned for our HP LaserJet IV
 * and may need adjustment for other printers
 */

#define PSXMIN 100
#define PSXMAX 2350
#define PSYMIN 100
#define PSYMAX 3045
#define DXPS 2250
#define DYPS 2945
#define CHARS 1.8

#define MINCOLOR 0
#define PSMAXPAT 30
#define MAXLINEWIDTH 9


static int psxmin = PSXMIN;
static int psxmax = PSXMAX;
static int psymin = PSYMIN;
static int psymax = PSYMAX;
static int psdx = DXPS;
static int psdy = DYPS;
static int pscolor = -1;
static int pslinewidth = -1;
static int psdmode;
static int pspattern = 0;
static int psfont = 0;
static double pscharsize = 1.7;
static int pslinestyle;
static char *fname;

/* reduced from 1000 to 800 PJT */

#define MAXPATHLEN 800        /* MAXPATHLEN points in a path between
                         * strokes */
static int   pathlength = 0;
static FILE *psout;

static int   prevx = 99999, 
             prevy = 99999, 
           prevmode;

static void stroke()
{
    if (pathlength) {
       fprintf(psout, "stroke\n");
      prevx = 99999;
      prevy = 99999;
      pathlength = 0;
    }
}

int pssetmode(mode, ps_fp)
    int    mode;
    FILE   *ps_fp;
{
    if (mode % 2) {
       psout = ps_fp;
       if (psout == NULL) 
           return 0;
    }

    switch (mode) {

    case 3:             /* EPS   portrait */
      pscharsize = CHARS;
        psxmin = PSXMIN;
      psxmax = PSXMAX;
      psymin = PSYMIN;
      psymax = PSYMAX;
      psdx = DXPS;
      psdy = DYPS;
      
      break;

    case 1:             /* EPS landscape */
      pscharsize = CHARS;
      psxmin = PSYMIN;
      psxmax = PSYMAX;
      psymin = PSXMIN;
      psymax = PSXMAX;
      psdx = DYPS;
      psdy = DXPS;
      
      break;

    case 2:
    case 4:
        stroke();
        fprintf(psout, "showpage\n");
        fprintf(psout, "%%%%Trailer\n");
        fclose(psout);
 
        break;
    }

    return mode;
}

void drawps(x2, y2, mode)
    int x2, y2, mode;
{
    int xtmp, ytmp;

    if (x2 < 0 || y2 < 0) {   /* Eliminate garbage on output */
      return;
    } 
    xtmp = x2;
    ytmp = y2;

    if (mode) {
      if (prevmode && xtmp == prevx && ytmp == prevy) {
          return;       /* previous mode was draw and points are the
                         * same */
      }
      fprintf(psout, "%d %d l\n", xtmp, ytmp);  /* lineto */
    } else {
      /* Avoid excessive moveto */
      if (xtmp == prevx && ytmp == prevy) {
          return;
      }
      fprintf(psout, "%d %d m\n", xtmp, ytmp);  /* moveto */
    }
    pathlength++;
    prevx = xtmp;
    prevy = ytmp;

    /*
     * Printers have some maximum number of points in a path. See PostScript
     * Language Reference Manual (Red book), p. 261. Hence the fix that
     * follows 
     */

    prevmode = mode;
    if (pathlength > MAXPATHLEN) {
      stroke();
      prevmode = 0;
      fprintf(psout, "%d %d m\n", xtmp, ytmp);  /* moveto */
    }
}

int xconvps(x)
    double x;
{
    return ((int) (psxmin + x));
}

int yconvps(y)
    double y;
{
    return ((int) (psymin + y));
}

int pssetcolor(c)
    int c;
{
    static int             first_time = 1;
    static unsigned char   red[16], 
                     green[16], 
                     blue[16];

    if (first_time) {
       first_time = 0;

    /* white  */ red[0] = 255;  green[0] = 255; blue[0] = 255; 
    /* black  */ red[1] = 0;    green[1] = 0;   blue[1] = 0;
    /* red    */ red[2] = 255;  green[2] = 0;   blue[2] = 0;
    /* green  */ red[3] = 0;    green[3] = 255; blue[3] = 0;
    /* blue   */ red[4] = 0;    green[4] = 0;   blue[4] = 255;
    /* yellow */ red[5] = 255;  green[5] = 255; blue[5] = 0;
    /* brown  */ red[6] = 188;  green[6] = 143; blue[6] = 143;
    /* gray   */ red[7] = 220;  green[7] = 220; blue[7] = 220;
    /* violet */ red[8] = 148;  green[8] = 0;   blue[8] = 211;
    /* cyan   */ red[9] = 0;    green[9] = 255; blue[9] = 255;
    /* magenta*/ red[10] = 255; green[10] = 0;  blue[10] = 211;
    /* orange */ red[11] = 255; green[11] = 138; blue[11] = 0;
    /* b violet*/ red[12] = 114; green[12] = 33; blue[12] = 188;
    /* maroon */ red[13] = 103; green[13] = 7;   blue[13] = 72;
    /* turq   */ red[14] = 72;  green[14] = 209; blue[14] = 204;
    /* f green*/ red[15] = 85;  green[15] = 192; blue[15] = 52;

    }
    
    stroke();
    if (c != pscolor) {
      if (c >= 0) {
          fprintf(psout, "%f %f %f setrgbcolor\n", red[c] / 255.0, 
                                                     green[c] / 255.0, 
                                           blue[c] / 255.0);
          pscolor = 1;
      }
    }
    pscolor = c;
    return c;
}

int pssetlinewidth(c)
    int c;
{
    stroke();
    if (c != pslinewidth) {
      c = c % (MAXLINEWIDTH + 1);
      if (c == 1)
          fprintf(psout, "1 setlinewidth\n");
      else
          fprintf(psout, "%d setlinewidth\n", (int) (3.5 * c + 0.51));
    }
    pslinewidth = c;
    return c;
}

int pssetlinestyle(style)
    int style;
{
    stroke();
    if (style == pslinestyle) {
      return (pslinestyle);
    }
    switch (style) {
    case 1:             /* solid */
      fprintf(psout, "[] 0 setdash\n");
      break;
    case 2:             /* dotted */
      fprintf(psout, "[4 8] 0 setdash\n");
      break;
    case 3:             /* long dash */
      fprintf(psout, "[20 20] 0 setdash\n");
      break;
    case 4:             /* short dash */
      fprintf(psout, "[40 20] 0 setdash\n");
      break;
    case 5:             /* dot-dashed */
      fprintf(psout, "[40 20 12 20] 0 setdash\n");
      break;
    }
    return (pslinestyle = style);
}

char pscurfont[MAX_BUF_LEN] = "/Times-Roman findfont \n60 scalefont\n setfont";
int psfontsize = 60;

void pssetfont(n)
    int n;
{
    if (psfont == n) {
      return;
    }
    switch (n) {
    case 0:
      sprintf(pscurfont, "/Times-Roman findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 1:
      sprintf(pscurfont, "/Times-Bold findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 2:
      sprintf(pscurfont, "/Times-Italic findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 3:
      sprintf(pscurfont, "/Times-BoldItalic findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 4:
      sprintf(pscurfont, "/Helvetica findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 5:
      sprintf(pscurfont, "/Helvetica-Bold findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 6:
      sprintf(pscurfont, "/Helvetica-Oblique findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 7:
      sprintf(pscurfont, "/Helvetica-BoldOblique findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 8:
      sprintf(pscurfont, "/Courier findfont \n%d scalefont\n setfont", psfontsize);
        break; 
    case 9:
      sprintf(pscurfont, "/Courier-Bold findfont \n%d scalefont\n setfont", psfontsize);
        break; 
    case 10:
      sprintf(pscurfont, "/Courier-Oblique findfont \n%d scalefont\n setfont", psfontsize);
        break; 
    case 11:
      sprintf(pscurfont, "/Courier-BoldOblique findfont \n%d scalefont\n setfont", psfontsize);
        break; 
    case 12:
      sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 13:
      sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
      break;
    case 14:
      sprintf(pscurfont, "/Symbol findfont \n%d scalefont\n setfont", psfontsize);
      break;
    }

    fprintf(psout, "%s\n", pscurfont);
    psfont = n;
}

void pssetfontsize(size)
    double size;
{
    static double prev_size;
    int sf = psfont;

    if (size == prev_size)
       return;


    psfontsize = (int) (size * 4);  /* to account for the 0.25 scaling */
    psfont = -1;
    pssetfont(sf);
}

static void escape_paren(s)
    char *s;
{
    char t[256];
    int i, cnt = 0;
    for (i = 0; i < strlen(s); i++) {
      if (s[i] == '(' || s[i] == ')') {
          t[cnt++] = '\\';
      }
      t[cnt++] = s[i];
    }
    t[cnt] = 0;
    strcpy(s, t);
}

void dispstrps(x, y, rot, s, just, fudge)
    int x, y, rot, just, fudge;
    char *s;
{
    char tmpstr[256];

    stroke();
    if (psfontsize == 0 || s == NULL || strlen(s) == 0) {
      return;
    }
    fprintf(psout, "%d %d m\n", x, y);
    fprintf(psout, "gsave\n");
    fprintf(psout, "%d %d translate\n", x, y);
    fprintf(psout, "%d rotate\n", rot);
    if (fudge) {
      fprintf(psout, "%d 0  m\n", psfontsize / 4);
    } else {
      fprintf(psout, "0 0  m\n");
    }
    switch (just) {
    case 0:
      break;
    case 1:
      stripspecial(s, tmpstr);
      escape_paren(tmpstr);
      fprintf(psout, "(%s) RJ\n", tmpstr);
      break;
    case 2:
      stripspecial(s, tmpstr);
      escape_paren(tmpstr);
      fprintf(psout, "(%s) CS\n", tmpstr);
      break;
    }
    putps(s);
    fprintf(psout, "grestore\n");
    fprintf(psout, "newpath\n");
}

static void putps(s)
    char *s;
{
    int i, slen = strlen(s), curcnt = 0;
    int underline = 0, offset = 0;
    double saves = psfontsize / 60.0, scale = psfontsize / 60.0;
    char curstr[256];
    int upperset = 0;
    int symfont = 0;

    if (psfont == 9) {
      symfont = 1;
      upperset = 0x80;
    } else {
      symfont = 0;
      upperset = 0;
    }
    for (i = 0; i < slen; i++) {
      if (s[i] == '-' && isdigit(s[i + 1])) {
          /* s[i] = 0261; */
      } else if (s[i] == '\\' && isdigit(s[i + 1])) {
          curstr[curcnt] = 0;
          if (curcnt >= 1) {
            fprintf(psout, "(%s) show\n", curstr);
          }
          curcnt = 0;
          if (symfont) {
            symfont = 0;
            upperset = 0;
          }
          pssetfont(s[i + 1] - '0');
          if (psfont == 9) {
            symfont = 1;
            upperset = 0x80;
          }
          i++;
          continue;
      } else if (s[i] == '(' || s[i] == ')') {
          curstr[curcnt++] = '\\';
      } else if (s[i] == '\\' && isoneof(s[i + 1], "cCbxsSNuU+-")) {
          switch (s[i + 1]) {
          case 'x':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            if (symfont == 0) {
                symfont = 1;
                upperset = 0x80;
            }
            pssetfont(10);
            i++;
            break;
          case 's':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            pssetfontsize(scale = 0.6 * saves);
            offset -= psfontsize / 2;
            fprintf(psout, "0 %d rmoveto\n", -(psfontsize / 2));
            i++;
            break;
          case 'S':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            pssetfontsize(scale = 0.6 * saves);
            offset += psfontsize;
            fprintf(psout, "0 %d rmoveto\n", psfontsize);
            i++;
            break;
          case 'N':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            scale = saves;
            pssetfontsize(scale);
            fprintf(psout, "0 %d rmoveto\n", -offset);
            offset = 0;
/*
            fprintf(psout, "0 %d rmoveto\n", psfontsize);
*/
            i++;
            break;
          case 'b':
            i++;
            break;
          case 'c':
            upperset = 0x80;
            i++;
            break;
          case 'C':
            upperset = 0;
            i++;
            break;
          case 'u':
            underline = 1;
            i++;
            break;
          case 'U':
            underline = 0;
            i++;
            break;
          case '-':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            scale -= 0.2;
            if (scale < 0.2) {
                scale = 0.2;
            }
            pssetfontsize(scale);
            i++;
            break;
          case '+':
            curstr[curcnt] = 0;
            if (curcnt >= 1) {
                fprintf(psout, "(%s) show\n", curstr);
            }
            curcnt = 0;
            scale += 0.2;
            pssetfontsize(scale);
            i++;
            break;
          }
          continue;
      } else if (s[i] == '\\' && s[i + 1] == '\\') {
          curstr[curcnt++] = '\\';
          curstr[curcnt++] = s[i];
          i++;
          continue;
      }
      curstr[curcnt++] = s[i] + upperset;
    }
    curstr[curcnt] = 0;
    fprintf(psout, "(%s) show\n", curstr);
}

int pssetpat(k)
    int k;
{
    stroke();
    if (k > PSMAXPAT) {
      k = PSMAXPAT;
    } else if (k < 0) {
      k = 0;
      fprintf(psout, "0.0 setgray\n");
    }
    return (pspattern = k);
}

void psfill(n, px, py)
    int n;
    int px[], py[];

{
    int i;

    stroke();
    drawps(px[0], py[0], 0);
    for (i = 1; i < n; i++) {
      drawps(px[i], py[i], 1);
    }
    fprintf(psout, "closepath\n");
    fprintf(psout, "%f setgray\n", 1.0 - pspattern / (double) PSMAXPAT);
    fprintf(psout, "gsave eofill grestore\n");
    stroke();
    fprintf(psout, "0 setgray\n");
}

void psfillcolor(n, px, py)
    int n;
    int px[], py[];

{
    int i;

    stroke();
    drawps(px[0], py[0], 0);
    for (i = 1; i < n; i++) {
      drawps(px[i], py[i], 1);
    }
    fprintf(psout, "closepath\n");
    fprintf(psout, "gsave eofill grestore\n");
    stroke();
}

void psdrawarc(x, y, r, start, end) 
    int x, y, r, start, end;
{
    stroke();
    fprintf(psout, "%d %d %d %d %d arc\n", x, y, r, start, end);
    fprintf(psout, "stroke\n");
}

void psfillarc(x, y, r, start, end)
    int x, y, r, start, end;
{
    stroke();
    fprintf(psout, "%d %d %d %d %d arc\n", x, y, r, start, end);
    fprintf(psout, "gsave fill grestore\n");
    fprintf(psout, "stroke\n");
}

void psdrawellipse(x, y, xm, ym, start, end)
    int x, y, xm, ym, start, end;
{
    double scalex = (double) xm / (double) ym, scaley = 1.0;

    stroke();
    fprintf(psout, "gsave\n");
    fprintf(psout, "%f %f scale\n", scalex, scaley);
    fprintf(psout, "%d %d %d %d %d arc\n", (int) (x * 1.0 / scalex), 
                                           y, ym, start, end);
    fprintf(psout, "stroke\n");
    fprintf(psout, "grestore\n");
}

void psfillellipse(x, y, xm, ym, start, end)
    int x, y, xm, ym, start, end;
{
    double scalex = (double) xm / (double) ym, scaley = 1.0;

    stroke();
    fprintf(psout, "gsave\n");
    fprintf(psout, "%f %f scale\n", scalex, scaley);
/*
    fprintf(psout, "%d %d %d %d %d arc\n", x, y, ym, start, end);
*/
    fprintf(psout, "%d %d %d %d %d arc\n", (int) (x * 1.0 / scalex), 
                                            y, ym, start, end);
    fprintf(psout, "gsave fill grestore\n");
    fprintf(psout, "stroke\n");
    fprintf(psout, "grestore\n");
}

int psgetextents (x, y)
    int           *x, *y;
{
    *x = psdx;
    *y = psdy;

    return 0;
}

void psleavegraphics(fp)
     FILE *fp;
{
     pssetmode(psdmode + 1, fp);
}

/*           postscript initialization routine  */


int psinitgraphics(dmode, ps_fp)
    int   dmode;
    FILE  *ps_fp;
{
    psdmode = dmode;
    if (!pssetmode(psdmode, ps_fp)) {
      return -1;
    }

    fprintf(psout, "%%!PostScript\n");

    fprintf(psout, "%%%%Creator: Velvet %s\n", VERSION);
    fprintf(psout, "%%%%Title: %s\n", fname);

    fprintf(psout, "%%%%EndComments\n");
    fprintf(psout, "/m {moveto} bind def\n");
    fprintf(psout, "/l {lineto} bind def\n");
    fprintf(psout, "/RJ {\n");
    fprintf(psout, " stringwidth neg exch neg exch\n");
    fprintf(psout, " rmoveto\n");
    fprintf(psout, "} bind def\n");

    fprintf(psout, "/CS {\n");
    fprintf(psout, " stringwidth\n");
    fprintf(psout, " 2 div neg exch 2 div neg exch\n");
    fprintf(psout, " rmoveto\n");
    fprintf(psout, "} bind def\n");

    fprintf(psout, "0.25 0.25 scale\n");
    fprintf(psout, "1 setlinecap\n");

/*
 * rotate if in landscape mode
 */

    if (dmode == 1) {
      fprintf(psout, "%d 0 translate\n", 2 * psymin + psdy);
      fprintf(psout, "90 rotate\n");
    }

    pssetcolor(1);
    pssetlinewidth(1);
    pssetlinestyle(0);
    psfont = -1;
    pssetfont(2);
    return 0;
}

static int isoneof(c, s)
    int c;
    char *s;
{
    while (*s) {
      if (c == *s) {
          return 1;
      } else {
          s++;
      }
    }
    return 0;
}

static void stripspecial(s, cs)
    char *s, *cs;
{
    int i, slen = strlen(s), curcnt = 0;

    for (i = 0; i < slen; i++) {
      if (s[i] == '\\' && isdigit(s[i + 1])) {
          i++;
      } else if (s[i] == '\\' && isoneof(s[i + 1], "cCbxsSNuU+-")) {
          i++;
      } else if (s[i] == '\\' && s[i + 1] == '\\') {
          i++;
      } else {
          cs[curcnt++] = s[i];
      }
    }
    cs[curcnt] = 0;
}

Generated by  Doxygen 1.6.0   Back to index