home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / cat2deskjet / part03 / vf.c < prev   
Encoding:
C/C++ Source or Header  |  1990-08-30  |  11.5 KB  |  530 lines

  1. #ifndef lint
  2. static char ScrId[] = "@(#) vfonts.c:1.3";
  3. #endif
  4.  
  5. /*****************************************************************
  6.  
  7.     Copyright 1985. All Rights Reserved Chris Lewis
  8.  
  9.     Module          : vfonts.c 1.3
  10.     Date submitted  : 86/01/30 09:19:57
  11.     Author          : Chris Lewis
  12.     Origin          : Permission to copy and further distribute is 
  13.               freely given provided this copyright notice remains 
  14.               intact and that this software is not sold for profit.
  15.     Description     : Description of the file
  16.     Modifications:
  17.  
  18.     - modified to work with the HP DeskJet printer, by maintaining
  19.       each line in an internal buffer and then dumping it in one
  20.       go.  The original way of printing each character individually
  21.       didn't work because the DeskJet cannot reverse feed the paper.
  22.  
  23.     - added draft-mode printing at 150 dpi.  Problem is that with
  24.       the bitmap you just can't mix fonts of different resolutions.
  25.       The quick&dirty way out of this is to consider the low-ress
  26.       option as binding (i.e. if you start low-res and you don't
  27.       have the fonts, your job aborts!).
  28.  
  29. ******************************************************************/
  30.  
  31. #include <assert.h>
  32. #include <stdio.h>
  33. #include <fcntl.h>
  34. #ifdef UNIX
  35. #include <ctype.h>
  36. #include <vfont.h>
  37. #else
  38. #include <alloc.h>
  39. #include <mem.h>
  40. #include <vp/vfont.h>
  41. #endif
  42. #define LCAT
  43. #include "lcat.h"
  44.  
  45. extern FILE    *diagFile;
  46. extern FILE    *outFile;
  47. #define    DEBUGPRINTF    if (diagFile) fprintf
  48. #define REGISTER    /**/
  49. static char    *fontFamily;
  50. #define FONTS    "RIBS"
  51. char    fpos[] = FONTS;
  52.  
  53. #define STD_DPI 300
  54. static int    dpi = STD_DPI;
  55. static int    gl_dpi = STD_DPI;
  56.  
  57. #define MAX_FONT    3
  58. #define SPEC_FONT    3
  59. #define IMG_SIZE    (unsigned int)(50000)
  60.  
  61. static long xpos = -1;
  62. static long ypos = -1;
  63.  
  64. static struct header vf_header;
  65. struct fcache {
  66.     int fnum;    /* number of cached font (R=0, I=1, B=2, S=3) */
  67.     int psize;    /* pointsize of font */
  68.     int count;    /* usage counter for LRU caching */
  69.     struct dispatch *dsp;    /* font description table */
  70.     u_char *image;    /* font bitmaps */
  71. } fontcache[MAX_FONT];
  72.  
  73. /*
  74.  * following vars hold data for selected font
  75.  */
  76. int cfnum, cpsize;
  77. struct dispatch *cdsp;
  78. u_char huge* imageTable;
  79. int use_count=1;
  80.  
  81.  
  82. /* raster related definitions */
  83. extern u_char raster[NLINES][RASTWIDTH];
  84. #define TRUE 1
  85. #define FALSE 0
  86. static int new_page = TRUE;
  87. static long y_base;    /* vertical position of baseline for current line */
  88. static long max_up;    /* max height above baseline of glyphs on current line */
  89. static long max_down;    /* max depth below baseline of glyphs on cur line */
  90. static long min_x;    /* left horizontal offset of cur. line */
  91. static long max_x;    /* rightmost position on current line */
  92.  
  93. #ifdef NOALLOC
  94. char* vpalloc(i, k)
  95. int i, k;
  96. {
  97.     int j;
  98.     static char c;
  99.  
  100.     j = i;
  101.     j = k;
  102.     return(&c);
  103. }
  104. #else
  105. #define vpalloc    calloc
  106. #endif
  107.  
  108. vf_init(quality, ff)
  109. int quality;
  110. char* ff;
  111. {
  112.     int i, j;
  113.     u_char huge* vp;
  114.  
  115.     fontFamily = ff;
  116.     new_page = TRUE;
  117.     for (i = 0; i < NLINES; i++)
  118.         for (j = 0, vp = raster[i]; j < RASTWIDTH; j++)
  119.             *vp++ = 0;
  120.     if (quality == 2)
  121.     {
  122.         gl_dpi = dpi = 150;
  123.         fprintf(outFile, "\033*r1Q");
  124.     } else
  125.         fprintf(outFile, "\033*r0Q");
  126.     cfnum = -1;
  127.     for (i=0; i < MAX_FONT; i++)
  128.     {
  129.         fontcache[i].fnum = -1;
  130.         if ((fontcache[i].dsp = (struct dispatch *)
  131.             vpalloc(NUM_DISPATCH, sizeof(struct dispatch))) == NULL)
  132.         {
  133.             fprintf(stderr, "malloc failed (A, %d)\n", i);
  134.     
  135.             exit(1);
  136.         }
  137.         if ((fontcache[i].image = (u_char *)
  138.             vpalloc(IMG_SIZE, 1)) == NULL)
  139.         {
  140.             fprintf(stderr, "malloc failed (B, %d)\n", i);
  141.             exit(1);
  142.         }
  143.     }
  144. }
  145.  
  146. /*
  147.  *    loadfont -- load vfont
  148.  *
  149.  */
  150. loadfont(fnum, psize)
  151. int fnum, psize;
  152. {
  153.     int i, c, sel;
  154.  
  155.     if (cfnum == fnum && cpsize == psize)
  156.         return;
  157.     for (i=0; i < MAX_FONT; i++)
  158.     {
  159.         if (fontcache[i].fnum == fnum && fontcache[i].psize == psize)
  160.         {
  161.             cfnum = fnum;
  162.             cpsize = psize;
  163.             cdsp = fontcache[i].dsp;
  164.             imageTable = fontcache[i].image;
  165.             fontcache[i].count = use_count++;
  166.             return;
  167.         }
  168.     }
  169.     /* not in cached set => load in place of LRU font */
  170.     c = use_count;
  171.     sel = -1;
  172.     for (i=0; i < MAX_FONT; i++)
  173.     {
  174.         if (fontcache[i].count < c)
  175.         {
  176.             c = fontcache[i].count;
  177.             sel = i;
  178.         }
  179.     }
  180.     assert(sel != -1);
  181.     getfont(fnum, psize, sel);
  182.     /* recursively call loadfont to properly select the
  183.      * font we've just loaded.  i.e. retry loadfont operation
  184.      */
  185.     loadfont(fnum, psize);
  186. }
  187.  
  188.  
  189. getfont(fnum, psize, position)
  190. int fnum, psize, position;
  191. {
  192.     static char fontBuf[BUFSIZ];
  193.     int fd;        /* file handle for vfont file */
  194.     int i;
  195.     unsigned int len;
  196.  
  197.     assert(fnum <= (strlen(FONTS)-1));
  198. #ifdef UNIX
  199.     sprintf(fontBuf, "%s%c.%d", fontFamily, tolower(fpos[fnum]), psize);
  200.     if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
  201.     {
  202.         sprintf(fontBuf, "%s%c.%d", fontFamily, fpos[fnum], psize);
  203.         if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
  204.         {
  205.             fprintf(stderr,
  206.                 "lcat: Could not load font %s\n", fontBuf);
  207.             exit(1);
  208.         }
  209.     }
  210. #else
  211.     sprintf(fontBuf, "%s%c.%d", fontFamily, fpos[fnum], psize);
  212.  
  213.     if ((fd = open(fontBuf, O_BINARY|O_RDONLY)) < 0)
  214.     {
  215.         fprintf(stderr, "lcat: Could not load font %s\n", fontBuf);
  216.         exit(1);
  217.     }
  218. #endif
  219.     DEBUGPRINTF(diagFile, "Loaded font %s (dpi: %d)\n", fontBuf, gl_dpi);
  220.     fprintf(stderr, "Loaded font %s (dpi: %d)\n", fontBuf, gl_dpi);
  221.     len = sizeof(struct header);
  222.     if (read(fd, &vf_header, len) != len)
  223.     {
  224.         fprintf(stderr, "lcat: Bad font file header\n");
  225.         exit(1);
  226.     }
  227.     if (vf_header.magic != VFONT_MAGIC)
  228.     {
  229.         fprintf(stderr, "lcat: Bad font magic number\n");
  230.         exit(1);
  231.     }
  232.     len = NUM_DISPATCH*sizeof(struct dispatch);
  233.     if (read(fd, fontcache[position].dsp, len) != len)
  234.     {
  235.         fprintf(stderr, "lcat: Could not load font dispatch table\n");
  236.         exit(1);
  237.     }
  238.     len = vf_header.size;
  239.     if (len > IMG_SIZE)
  240.     {
  241.         fprintf(stderr, "lcat: image table size (= %u) TOO BIG\n", len);
  242.         exit(1);
  243.     }
  244.     if ((unsigned)read(fd, fontcache[position].image, len) != len)
  245.     {
  246.         fprintf(stderr, "lcat: Error reading image table\n");
  247.         exit(1);
  248.     }
  249.     close(fd);
  250.     fontcache[position].fnum = fnum;
  251.     fontcache[position].psize = psize;
  252.     return;
  253. }
  254.  
  255. #define CAT_L    '\004'
  256. #define CAT_I    '\005'
  257. #define CAT_F    '\013'
  258. #define CAT_FI    '\0122'
  259. #define CAT_FL    '\0123'
  260. #define CAT_FF    '\0124'
  261. #define CAT_FFL    '\0126'
  262. #define CAT_FFI    '\0127'
  263.  
  264. flashrast(ch, ps, ftype)
  265. int    ch, ps, ftype;
  266. {
  267.     int up, down, left, right;
  268.     register int idx;
  269.     register int i,j,H,V;
  270.     u_char huge *bp;
  271.     u_char huge *vp;
  272.     int points;
  273.     long x;
  274.     long oxpos;
  275.  
  276.     points = (gl_dpi == 150) ? ps>>1: ps;
  277.     if (ftype != cfnum || points != cpsize)
  278.         loadfont(ftype, points);
  279.  
  280.     idx = (ftype==SPEC_FONT) ? spectab[ch] : asctab[ch];
  281.     /*
  282.      * composite glyphs ff, fi, fl, ffi, ffl get special treatment
  283.      * since they are not available on all fonts.
  284.      * If we don't have the glyph, we call flashrast recursivelly
  285.      * until all but the last characters making up the composite
  286.      * glyph have been printed.  Then we continue executing
  287.      * flashrast with the last character.
  288.      */
  289.     if (ftype != SPEC_FONT)
  290.         switch (ch) {
  291.         case CAT_FFI:
  292.             if (cdsp[idx].nbytes > 0)
  293.                 break;
  294.             flashrast(CAT_F, ps, ftype);
  295.             idx = asctab[CAT_F];
  296.             xpos += cdsp[idx].width;
  297.             idx = asctab[CAT_FI];
  298.             /* NOTE --> NO BREAK HERE */
  299.         case CAT_FI:
  300.             if (cdsp[idx].nbytes > 0)
  301.                 break;
  302.             flashrast(CAT_F, ps, ftype);
  303.             idx = asctab[CAT_F];
  304.             xpos += cdsp[idx].width;
  305.             idx = asctab[CAT_I];
  306.             break;
  307.         case CAT_FFL:
  308.             if (cdsp[idx].nbytes > 0)
  309.                 break;
  310.             flashrast(CAT_F, ps, ftype);
  311.             idx = asctab[CAT_F];
  312.             xpos += cdsp[idx].width;
  313.             idx = asctab[CAT_FL];
  314.             /* NOTE --> NO BREAK HERE */
  315.         case CAT_FL:
  316.             if (cdsp[idx].nbytes > 0)
  317.                 break;
  318.             flashrast(CAT_F, ps, ftype);
  319.             idx = asctab[CAT_F];
  320.             xpos += cdsp[idx].width;
  321.             idx = asctab[CAT_L];
  322.             break;
  323.         case CAT_FF:
  324.             if (cdsp[idx].nbytes > 0)
  325.                 break;
  326.             flashrast(CAT_F, ps, ftype);
  327.             idx = asctab[CAT_F];
  328.             xpos += cdsp[idx].width;
  329.             break;
  330.         }
  331. #ifdef VERBOSE
  332.     if (idx >= ' ' && idx <= 126)
  333.         putchar(idx);
  334. #endif VERBOSE
  335.     up = cdsp[idx].up;
  336.     down = cdsp[idx].down;
  337.     left = cdsp[idx].left;
  338.     right = cdsp[idx].right;
  339.     V = up + down;
  340.     H = (left + right + 7) / 8;
  341.     bp = imageTable + cdsp[idx].addr;
  342.     DEBUGPRINTF(diagFile, "ch=%d,fnt=%d,idx=%d,V=%d,H=%d\n", ch, ftype, idx, V, H);
  343.     x = xpos + left + right;
  344.     max_x = MAX(max_x, x);
  345.     max_up = MAX(max_up, up);
  346.     max_down = MAX(max_down, down);
  347.     oxpos = xpos;
  348.     xpos -= left;
  349.     min_x = MIN(min_x, xpos);
  350.     DEBUGPRINTF(diagFile, "y_base=%ld,min_x=%ld,max_x=%ld,max_up=%ld,max_down=%ld\n",
  351.         y_base, min_x, max_x, max_up, max_down);
  352. vp=&raster[BASELINE - up][(int)(xpos >> 3)]; DEBUGPRINTF(diagFile, "\ttop of cell %lx\n", vp);
  353.     DEBUGPRINTF(diagFile, "vp = %lx, xposMOD8= %d, xpos = %ld, V=%d, H=%d, bp=%lx\n", vp, (int)(xpos%8), xpos, V, H, bp);
  354.     for (i = 0; i < V; i++, bp+=H)
  355.     {
  356.         vp = &raster[BASELINE - up + i][(int)(xpos >> 3)];
  357.         bit_move(vp, (int)(xpos%8), bp, H);
  358.     }
  359.     xpos = oxpos;
  360. }
  361.  
  362. /*
  363.  *    print_raster -- we print the raster from y_base-max_up to
  364.  *    y_base+max_down
  365.  */
  366. print_raster()
  367. {
  368.     long l_width;    /* width of line in bytes */
  369.     int i,j;
  370.     u_char huge* vp;
  371.     long lx, ly;
  372. #ifndef LASERJET
  373. #define MAX_REP_COUNT    128
  374.     int count, offset;
  375.     char c;
  376. #endif
  377.  
  378. #ifdef VERBOSE
  379.     putchar('\n');
  380. #endif VERBOSE
  381.     lx = min_x*720L/dpi;
  382.     ly = (y_base-max_up)*720L/dpi;
  383.     fprintf(outFile, "\033&a%ldh%ldV", lx, ly);
  384.     l_width = ((max_x - min_x + 7) / 8) + 1;
  385.     DEBUGPRINTF(diagFile, "move(%ld, %ld), l_width=%ld\n", lx, ly, l_width);
  386.     if (l_width >= RASTWIDTH)
  387.     {
  388.         fprintf(stderr, "print_raster: l_width(%ld) exceeds RASTWIDTH\n",
  389.             l_width);
  390.         exit(1);
  391.     }
  392.     fprintf(outFile, "\033*t%dR\033*r%ldS", dpi, l_width<<3);
  393.     fprintf(outFile, "\033*r1A");
  394.     for (i = BASELINE - max_up; i <= BASELINE + max_down; i++)
  395.     {
  396.         vp = &raster[i][min_x >> 3];
  397.         DEBUGPRINTF(diagFile, "printing line %lx\n", vp);
  398. #ifdef LASERJET
  399.         fprintf(outFile, "\033*b%ldW", l_width);
  400.         fwrite((void *)vp, l_width, 1, outFile);
  401. #ifdef BSD
  402.         bzero(vp, l_width);
  403. #else
  404.         memset((void *)vp, '\0', l_width);
  405. #endif
  406. #else
  407.         for (offset = 0; offset < l_width;)
  408.         {
  409.             for (count = 0, c = *vp;
  410. c == *vp && offset < l_width && count < MAX_REP_COUNT; offset++, count++)
  411.                 *vp++ = 0;
  412.             if (count <= 1)
  413.                 push_buf(c);
  414.             else {
  415.                 flush_buf();
  416.                 multiprint(c, count);
  417.             }
  418.         }
  419.         flush_outbuf();
  420. #endif
  421. #ifdef XXX
  422.         for (j = 0; j < l_width; j++)
  423.         {
  424.             putc(*vp, outFile);
  425.             *vp++ = 0;    /* ready raster for next pass */
  426.         }
  427. #endif XXX
  428.     }
  429.     fprintf(outFile, "\033*rB");
  430. }
  431.  
  432. vf_move(x, y)
  433. long x, y;
  434. {
  435.     xpos = x * dpi/720;
  436.     ypos = y * dpi/720;
  437.  
  438.     if (new_page || (y_base != ypos))
  439.     {
  440.         if (new_page)
  441.             new_page = FALSE;
  442.         else
  443.             print_raster();
  444.         y_base = ypos;
  445.         max_up = max_down = 0;
  446.         min_x = max_x = xpos;
  447.     }
  448. }
  449.  
  450. vf_newpage()
  451. {
  452.     new_page = TRUE;
  453.     print_raster();
  454.     putc('\f', outFile);
  455.     fflush(outFile);
  456. }
  457.  
  458. prt(s, vp, nb, nl)
  459. char *s;
  460. u_char huge* vp;
  461. int nb, nl;
  462. {
  463.     int i;
  464.  
  465.     DEBUGPRINTF(diagFile, "%s= ", s);
  466.     for(i=0; i< nb; i++)
  467.         DEBUGPRINTF(diagFile, "%2x, ", *vp++);
  468.     if (nl)
  469.         DEBUGPRINTF(diagFile, "%2x\n", *vp);
  470.     else
  471.         DEBUGPRINTF(diagFile, "%2x\t", *vp);
  472. }
  473.  
  474. #ifndef LASERJET
  475. /*
  476.  * routines used with the DeskJet graphics compression scheme
  477.  */
  478. #define MAXBUF 400
  479. char out_buffer[MAXBUF];
  480. char *outbuf = out_buffer;
  481. int outoff = 0;
  482.  
  483. flush_outbuf()
  484. {
  485.     flush_buf();
  486.     fprintf(outFile, "\033*b2m%dW", outoff);
  487.     fwrite(out_buffer, outoff, 1, outFile);
  488.     outbuf = out_buffer;
  489.     outoff = 0;
  490. }
  491.  
  492. #define PUSHBUFLEN MAX_REP_COUNT
  493. char pushbuf[PUSHBUFLEN];
  494. int pushoff = 0;
  495.  
  496. push_buf(c)
  497. char c;
  498. {
  499.     pushbuf[pushoff++] = c;
  500.     if (pushoff >= PUSHBUFLEN)
  501.         flush_buf();
  502. }
  503.  
  504. multiprint(c, count)
  505. char c;
  506. int count;
  507. {
  508.     *outbuf++ = -(count-1);
  509.     *outbuf++ = c;
  510.     outoff += 2;
  511. }
  512.  
  513. flush_buf()
  514. {
  515.     if (pushoff == 0)
  516.         return;
  517.     assert(outoff+pushoff+1 < MAXBUF);
  518.     *outbuf++ = pushoff-1;
  519. #ifdef BSD
  520.     bcopy(pushbuf, outbuf, pushoff);
  521. #else
  522.     memcpy(outbuf, pushbuf, pushoff);
  523. #endif
  524.     outbuf += pushoff;
  525.     outoff += (pushoff + 1);
  526.     pushoff = 0;
  527. }
  528. #endif /* !LASERJET */
  529.  
  530.