home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / cat2deskjet / part03 / railmag.c next >
Encoding:
C/C++ Source or Header  |  1990-08-30  |  21.3 KB  |  827 lines

  1. /*
  2.  *    railmag.c -- downloads vfonts to a Hewlett-Packard DeskJet.
  3.  *  Copyright (C) 1990 Vassilis Prevelakis
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation and included with this distribution in the
  8.  *  file named LICENSE.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  Bug fixes, comments etc. to:
  20.  *       Vasilis Prevelakis
  21.  *       Centre Universitaire d'Informatique (CUI)
  22.  *       12 Rue du Lac, Geneva, Switzerland CH-1207
  23.  *  email: vp@cui.unige.ch
  24.  *  uucp:  ...!mcsun!cui!vp
  25.  *
  26.  */
  27.  
  28. #include <assert.h>
  29. #include <stdio.h>
  30. #ifdef UNIX
  31. #include <string.h>
  32. #include <vfont.h>
  33. #include <sys/file.h>
  34. #else
  35. #include <string.h>
  36. #include <vp/vfont.h>
  37. #include <fcntl.h>
  38. #include <alloc.h>
  39. #endif
  40.  
  41. typedef unsigned short    u_short;
  42. typedef unsigned char    u_char;
  43.  
  44. #ifdef UNIX
  45. #define max(X, Y)    ((X > Y) ? X : Y)
  46. #define min(X, Y)    ((X < Y) ? X : Y)
  47. #endif
  48.  
  49. #define FDB_LEN    sizeof(struct fdb)
  50.  
  51. struct fdb {
  52.     u_short    size;        /* always 72 */
  53.     u_char    format;        /* DeskJet only: header format (5 or 9) */
  54.     u_char    ftype;        /* zero for 7-bit font */
  55.     short    xxx1;        /* RESERVED, must be zero */
  56.     u_short    baseline;    /* in dots */
  57.     u_short cell_width;    /* in dots */
  58.     u_short cell_height;    /* in dots */
  59.     u_char orientation;    /* 0 portrait, 1 landscape */
  60.     u_char spacing;        /* 0 fixed, 1 proportional */
  61.     u_short symbol;
  62.     u_short pitch;        /* in quarter dots */
  63.     u_short height;        /* in quarter dots */
  64.     u_short xHeight;    /* in quarter dots -- IGNORED */
  65.     u_char w_type;        /* IGNORED, == 0 */
  66.     u_char style;
  67.     char str_weight;
  68.     u_char typeface;
  69.     u_char    slant;        /* DeskJet only */
  70.     u_char s_style;
  71.     u_char quality;        /* DeskJet only */
  72.     u_char placement;    /* DeskJet only */
  73.     char ud_dst;
  74.     u_char ud_height;    /* IGNORED, == 3 */
  75.     u_short    t_height;    /* IGNORED, == 0 */
  76.     u_short t_width;    /* IGNORED, == 0 */
  77.     u_short firstcode;    /* DeskJet only */
  78.     u_short lastcode;     /* DeskJet only */
  79.     u_char ext_pitch;    /* IGNORED by DeskJet == 0 */
  80.     u_char ext_height;    /* IGNORED by DeskJet == 0 */
  81.     short xxx5[3];        /* RESERVED, must be zero */
  82. #define MAXNAME 16
  83.     char fname[MAXNAME];
  84.     /* following fields DeskJet only */
  85.     u_short hres;        /* horizontal resolution == 600 */
  86.     u_short vres;        /* vertical resolution == 300 */
  87.     char ud2_dst;
  88.     u_char ud2_height;
  89.     char bud_dst;
  90.     u_char bud_height;
  91.     u_short psbs;        /* number of subsequent bytes == 20 */
  92.     u_short font_size;
  93.     char oneway;
  94.     char compressed;
  95.     u_char holdtime;
  96.     char nohalfpitch;
  97.     char nodoublepitch;
  98.     char nohalfheight;
  99.     char nobold;
  100.     char nodraft;
  101.     char boldmethod;
  102.     char xxx7;        /* RESERVED, must be zero */
  103.     u_short baseoff2;
  104. /* following fields used by DeskJet PLUS **ONLY** */
  105.     u_short baseoff3;
  106.     u_short baseoff4;
  107. } myfdb;
  108.  
  109. #define CDB_LEN    sizeof(struct cdb)
  110. struct cdb {
  111.     u_char    format;        /* 9 for large, 5 for small! */
  112.     u_char    continuation;
  113.     u_char    size;        /* always == 6 */
  114.     u_char    type;        /* single pass (=0) or pass number (=2,3,4,5) */
  115.     u_char    width;
  116.     u_char    compr_width;
  117.     u_char    left_pad;
  118.     u_char    right_pad;
  119. };
  120.  
  121. #define NCHAR 127
  122. /* NPASS is the maximum number of passes that the printer can make
  123.  * when printing a character, its 2 for the original DeskJet and 4 for
  124.  * the DeskJet PLUS.
  125.  */
  126. #define NPASS 4
  127. struct char_info {
  128.     struct cdb mycdb;
  129.     int cwidth;    /* width in bytes */
  130.     int cheight;    /* character height */
  131.     int top_pad;    /* blank rows above character cell */
  132.     int bottom_pad;    /* blank rows bellow character cell */
  133.     u_char *flagbytes[NPASS];    /* flag bytes for each pass */
  134.     int flaglen;            /* size of flagbytes, same on all passes */
  135.     u_char *databytes[NPASS];    /* data bytes for each pass */
  136.     int datalen[NPASS];            /* size of databytes for each pass */
  137.     
  138. } cinfo[NCHAR];
  139.  
  140. #define IMG_SIZE    50000
  141. #define DATA_SIZE    5000
  142. struct header vf_header;
  143. struct dispatch dsp[NUM_DISPATCH];
  144. #ifdef UNIX
  145. u_char imageTable[IMG_SIZE];
  146. u_char raster[IMG_SIZE];
  147. u_char dataptr[DATA_SIZE];
  148. #else
  149. u_char *imageTable;
  150. u_char *raster;
  151. u_char *dataptr;
  152. #endif
  153. char *fontname;
  154. FILE* printer;    /* file descriptor for printer */
  155. u_short font_size;
  156.  
  157. /* for the DeskJet the value used for dots is 300 despite the
  158.  * fact that the fonts are defined in 600ths of an inch.
  159.  */
  160. #define DPI 300
  161.  
  162. /* number of pins on the DeskJet print head */
  163. #define DJ_CELLHEIGHT 50
  164.  
  165. main(argc, argv)
  166. int argc;
  167. char *argv[];
  168. {
  169.  
  170.     int wt = 0;
  171.     char *sname = "2000V";    /* by default use ESC(2000V to select */
  172.     char *fname = NULL;
  173. #ifdef MSDOS
  174.     char* printername = NULL;
  175. #endif
  176.     int isprop = 1;        /* proportional spacing by default */
  177.     int nofid = 0;        /* do not generate fontid info */
  178.     int isperm = 1;        /* by default fornts are permanent */
  179.     int fpitch = -1;
  180.     int offset = 0;        /* for BSD vfonts that have ascii mapping */
  181.                 /* i.e. 33rd character of vfont is "!" */
  182.     int fid = 2;        /* a bit arbitrary */
  183.     int tpface = 30;    /* use an undefined typeface */
  184.     int i;
  185.     char *vp;
  186.     int npass, pass;    /* number of passes per char */
  187.  
  188. #ifndef UNIX
  189.     /* allocate things that should have been global!!! */
  190.     if ((imageTable = malloc(IMG_SIZE)) == NULL)
  191.     {
  192.         fprintf(stderr, "Couldn't allocate memory for imageTable\n");
  193.         exit(1);
  194.     }
  195.     if ((raster = malloc(IMG_SIZE)) == NULL)
  196.     {
  197.         fprintf(stderr, "Couldn't allocate memory for raster\n");
  198.         exit(1);
  199.     }
  200.     if ((dataptr = malloc(DATA_SIZE)) == NULL)
  201.     {
  202.         fprintf(stderr, "Couldn't allocate memory for dataptr\n");
  203.         exit(1);
  204.     }
  205. #endif
  206.     argv++;
  207.     argc--;
  208.     if (argc > 0)    /* process parameters */
  209.     {
  210.         while (argc > 0 && **argv == '-')
  211.         {
  212.             switch (*(*argv+1)) {
  213.             case 'T':
  214.                 isperm = 0;
  215.                 argv++;
  216.                 argc--;
  217.                 break;
  218.             case 'D':
  219.                 nofid = 1;
  220.                 argv++;
  221.                 argc--;
  222.                 break;
  223.             case 'f':
  224.                 isprop = 0;
  225.                 argv++;
  226.                 argc--;
  227.                 break;
  228.             case 'p':
  229.                 isprop = 0;    /* force fixed width */
  230.                 fpitch = atoi(*(++argv));
  231.                 argv++;
  232.                 argc -= 2;
  233.                 break;
  234.             case 'o':
  235.                 offset = atoi(*(++argv));
  236.                 argv++;
  237.                 argc -= 2;
  238.                 break;
  239.             case 'n':
  240.                 fname = *++argv;
  241.                 argv++;
  242.                 argc -= 2;
  243.                 break;
  244. #ifndef UNIX
  245.             case 'F':
  246.                 printername = *++argv;
  247.                 argv++;
  248.                 argc -= 2;
  249.                 break;
  250. #endif
  251.             case 's':
  252.                 sname = *++argv;
  253.                 argv++;
  254.                 argc -= 2;
  255.                 break;
  256.             case 'i':
  257.                 fid = atoi(*(++argv));
  258.                 argv++;
  259.                 argc -= 2;
  260.                 break;
  261.             case 't':
  262.                 tpface = atoi(*(++argv));
  263.                 argv++;
  264.                 argc -= 2;
  265.                 break;
  266.             default:
  267.                 usage(1);
  268.             }
  269.         }
  270.     
  271.         /*
  272.          * filename
  273.          */
  274.         if (argc <= 0)
  275.             usage(2);
  276.         else {
  277.             fontname = *argv++;
  278.             argc--;
  279.         }
  280.         if (argc > 0)
  281.             usage(3);
  282.     }
  283.  
  284.     if (nofid)
  285.         fid = -1;
  286. #ifdef UNIX
  287.     /* under unix railmag is just a filter */
  288.     printer = stdout;
  289. #else
  290.     /* under MSDOS we have to go to the printer directly */
  291.     if (printername == NULL)
  292.         printername = "PRN:";
  293.  
  294.     if ((printer = fopen(printername, "wb")) == NULL)
  295.     {
  296.         fprintf(stderr, "Could not open printer %s.\n", printername);
  297.         exit(1);
  298.     }
  299. #endif
  300.  
  301.     loadfont(fontname);
  302.     myfdb.size = 72;
  303.     myfdb.ftype = 1;
  304.     myfdb.cell_height = vf_header.maxy;
  305.     /* raise cell_height to the next DJ_CELLHEIGHT multiple */
  306.     myfdb.cell_height += (DJ_CELLHEIGHT-(myfdb.cell_height%DJ_CELLHEIGHT));
  307.  
  308.     /* baseline is calculated as the the distance from the top of
  309.      * the BOTTOM pass for the font.
  310.      */
  311.     if ((myfdb.baseline = calcmaxdown(1, NCHAR)) > DJ_CELLHEIGHT)
  312.     {
  313.         fprintf(stderr, "Baseline (%d) greater than DJ_CELLHEIGHT\n",
  314.             myfdb.baseline);
  315.         exit(1);
  316.     }
  317.     myfdb.baseline = DJ_CELLHEIGHT - myfdb.baseline;
  318.  
  319.     myfdb.orientation = (fontname[strlen(fontname)-1] == 'r') ? 1 : 0;
  320.     myfdb.spacing = isprop;
  321.     myfdb.symbol = symbol_cvt(sname);
  322.     /*
  323.      * if fpitch is specified force cell width and pitch
  324.      * otherwise calculate them from the header
  325.      */
  326.     if (fpitch > 0)
  327.     {
  328.         myfdb.cell_width = DPI/fpitch;
  329.         /* multiply by four because these are quater dots */
  330.         myfdb.pitch = myfdb.cell_width * 4;
  331.     } else {
  332.         myfdb.cell_width = vf_header.maxx;
  333.         /* multiply by four because these are quater dots */
  334.         myfdb.pitch = dsp['m'].width * 4;
  335.     }
  336.     myfdb.height = myfdb.cell_height * 4;
  337.     myfdb.xHeight = dsp['x'].up * 4;
  338.     myfdb.w_type = wt;
  339.     /* following four should really be derived from fontname */
  340.     myfdb.style = 0;
  341.     myfdb.str_weight = 0;
  342.     myfdb.typeface = tpface;
  343.     myfdb.s_style = 0;
  344.  
  345.     myfdb.ud_dst = -(dsp['_'].down + 4);
  346.     myfdb.ud_height = 3;
  347.     myfdb.t_height = vf_header.maxy * 4;
  348.     myfdb.t_width = average('a', 'z') * 4;
  349.     myfdb.ext_pitch = myfdb.ext_height = 0;
  350.     if (fname != NULL)
  351.         strncpy(myfdb.fname, fname, MAXNAME);
  352.     else {
  353.         /* use basename(fontname) */
  354. #ifdef BSD
  355.         vp = rindex(fontname, '/');
  356. #else
  357.         vp = strrchr(fontname, '/');
  358. #endif
  359.         strncpy(myfdb.fname, (vp != NULL) ? vp+1 : fontname, MAXNAME);
  360.     }
  361.  
  362.     /* all the following values are for the DeskJet only */
  363.     myfdb.slant = 0;    /* ignored */
  364.     myfdb.quality = 2;    /* letter quality */
  365.     myfdb.placement = 0;    /* ignored */
  366.     myfdb.firstcode = offset + 1;
  367.     myfdb.lastcode = NCHAR;
  368.     myfdb.hres = 600;    /* horizontal resolution == 600 */
  369.     myfdb.vres = 300;    /* vertical resolution == 300 */
  370.     myfdb.ud2_dst = -(dsp['_'].down);
  371.     myfdb.ud2_height = 3;
  372.     myfdb.bud_dst = -(dsp['_'].down + 4);
  373.     myfdb.bud_height = 3;
  374.     myfdb.psbs = 20;    /* number of subsequent bytes == 20 */
  375.     myfdb.font_size = 0;    /* fill it up later */
  376.     myfdb.oneway = 0;    /* bidirectional */
  377.     myfdb.compressed = 0;    /* no compression info */
  378.     myfdb.nohalfpitch = 0;    /* allow half pitch */
  379.     myfdb.nodoublepitch = 0;    /* allow double pitch */
  380.     myfdb.nohalfheight= 0;    /* allow half height */
  381.     myfdb.nobold = 0;    /* allow algorithmic bold */
  382.     myfdb.nodraft = 0;    /* allow draft mode */
  383.     myfdb.boldmethod = 1;    /* dark bold, if too dark try = 0 */
  384.     /* now for the tricky fields! */
  385.     /* since cell_height is a multiple of DJ_CELLHEIGHT: */
  386.     npass = myfdb.cell_height / DJ_CELLHEIGHT;
  387.     if (npass <= 2)
  388.     {
  389.         myfdb.format = 5;    /* DeskJet type font */
  390.         myfdb.holdtime = 0;    /* RESERVED == 0 */
  391.     } else {
  392.         myfdb.format = 9;    /* DeskJet PLUS type font */
  393.         myfdb.holdtime = 80;    /* just a guess */
  394.     }
  395.     if (npass >= 2)
  396.         myfdb.baseoff2 = myfdb.baseline + DJ_CELLHEIGHT;
  397.     else
  398.         myfdb.baseoff2 = 0;
  399. /* following fields used by DeskJet PLUS **ONLY** */
  400.     if (npass >= 3)
  401.         myfdb.baseoff3 = myfdb.baseline + 2*DJ_CELLHEIGHT;
  402.     else
  403.         myfdb.baseoff3 = 0;
  404.     if (npass >= 4)
  405.         myfdb.baseoff4 = myfdb.baseline + 3*DJ_CELLHEIGHT;
  406.     else
  407.         myfdb.baseoff4 = 0;
  408.  
  409. fprintf(stderr, "main: npass=%d, cell_height=%d, baseline=%d\n",
  410.     npass, myfdb.cell_height, myfdb.baseline);
  411.     /* convert each character and calculate size of font */
  412.     /* the numbers for the header come from the deskjet developers
  413.      * guide:
  414.      *     +-----------------+--------------+--------------+
  415.      *     | Font type       | <= 128 chars | <= 256 chars |
  416.      *     +-----------------+--------------+--------------+
  417.      *     | fixed, no compr |     320      |     832      |
  418.      *     +-----------------+--------------+--------------+
  419.      *     | fixed, compr    |     448      |    1088      |
  420.      *     +-----------------+--------------+--------------+
  421.      *     | fixed, no compr |     576      |    1344      |
  422.      *     +-----------------+--------------+--------------+
  423.      * Here we deal only with 127 char fonts without compression,
  424.      * so we have to select between 448 and 576.
  425.      */
  426.     if (isprop)
  427.         font_size = 576;
  428.     else
  429.         font_size = 448;
  430.  
  431.     for (i = 1; i < NCHAR-offset; i++)
  432.         font_size += char_cvt(i, npass);
  433.     myfdb.font_size = font_size;
  434.  
  435.     /* if DJ+ font divide size by 1024 cause the DJ+ wants Kbytes */
  436.     if (myfdb.format == 9)
  437.         myfdb.font_size /= 1024;
  438.  
  439.     /*
  440.      * fid specifies font position, so that more than one font
  441.      * can be loaded simultaneously.
  442.      */
  443.     pr_header(fid);
  444.  
  445.     /*
  446.      * BSD vfonts are arranged in ASCII order, i.e. '!' is number 33
  447.      * for these fonts offset should be zero!
  448.      */
  449.  
  450.     if (npass == 1)
  451.         for (i = 1; i < NCHAR-offset; i++)
  452.             pr_glyph(i, i+offset, 0, 0);
  453.     else
  454.         for (pass = 0; pass < npass; pass++)
  455.             for (i = 1; i < NCHAR-offset; i++)
  456.                 pr_glyph(i, i+offset, npass-pass-1, pass+2);
  457.  
  458.     pr_trailer(fid, isperm);
  459. }
  460.  
  461. usage(i)
  462. int i;
  463. {
  464. #ifdef UNIX
  465.     fprintf(stderr, "usage(%d): railmag [-n name] [-s sname] [-f] [-p nn] [-o nn] [-i fid] fontname\n", i);
  466. #else
  467.     fprintf(stderr, "usage(%d): railmag [-n name] [-s sname] [-f] [-p nn] [-o nn] [-i fid]\n\t[-F filename] [-D] fontname\n", i);
  468. #endif
  469.     exit(-1);
  470. }
  471.  
  472.  
  473.  
  474. symbol_cvt(s)
  475. char *s;
  476. {
  477.     return((s[strlen(s)-1] - '@') + (atoi(s) * 32));
  478. }
  479.  
  480. calcmaxdown(st, fin)
  481. int st, fin;
  482. {
  483.     int i, w;
  484.     long res;
  485.  
  486.     res = 0;
  487.     for (i = st; i <= fin; i++)
  488.     {
  489.         w = dsp[i].down;
  490.         res = (res > w) ? res : w;
  491.     }
  492.     return(res);
  493. }
  494.  
  495. average(st, fin)
  496. int st, fin;
  497. {
  498.     int i;
  499.     long sum;
  500.  
  501.     sum = 0;
  502.     for (i = st; i <= fin; i++)
  503.         sum += dsp[i].width;
  504.     return(sum/(i-st));
  505. }
  506.  
  507. pr_header(fid)
  508. int fid;
  509. {
  510.     if (fid >= 0)
  511.         fprintf(printer, "\033*c%dD", fid);    /* select font */
  512.     fprintf(printer, "\033)s%dW", FDB_LEN);
  513. #ifdef MSDOS
  514. /* swap bytes on all shorts */
  515. #define vp_swab(X) ((((u_short)X & 0xff) << 8) | (((u_short)X & 0xff00) >> 8))
  516.     myfdb.size = vp_swab(myfdb.size);
  517.     myfdb.baseline = vp_swab(myfdb.baseline);
  518.     myfdb.cell_width = vp_swab(myfdb.cell_width);
  519.     myfdb.cell_height = vp_swab(myfdb.cell_height);
  520.     myfdb.symbol = vp_swab(myfdb.symbol);
  521.     myfdb.pitch = vp_swab(myfdb.pitch);
  522.     myfdb.height = vp_swab(myfdb.height);
  523.     myfdb.xHeight = vp_swab(myfdb.xHeight);
  524.     myfdb.t_height = vp_swab(myfdb.t_height);
  525.     myfdb.t_width = vp_swab(myfdb.t_width);
  526.     myfdb.firstcode = vp_swab(myfdb.firstcode);
  527.     myfdb.lastcode = vp_swab(myfdb.lastcode);
  528.     myfdb.hres = vp_swab(myfdb.hres);
  529.     myfdb.vres = vp_swab(myfdb.vres);
  530.     myfdb.psbs = vp_swab(myfdb.psbs);
  531.     myfdb.font_size = vp_swab(myfdb.font_size);
  532.     myfdb.baseoff2 = vp_swab(myfdb.baseoff2);
  533.     myfdb.baseoff3 = vp_swab(myfdb.baseoff3);
  534.     myfdb.baseoff4 = vp_swab(myfdb.baseoff4);
  535. #endif
  536.     fwrite(&myfdb, FDB_LEN, 1, printer);
  537. }
  538.  
  539. pr_trailer(fid, isperm)
  540. int fid, isperm;
  541. {
  542.     if (fid < 0)
  543.         return;
  544.     if (isperm)
  545.         fprintf(printer, "\033*c5F");    /* make font permanent, */
  546.     fprintf(printer, "\033(%dX", fid);    /* and select it */
  547. }
  548.  
  549. int char_cvt(idx, npass)
  550. int idx;
  551. int npass;
  552. {
  553.     int i, j;
  554.     unsigned char *vp, *cp;
  555.     int bottom_pad, top_pad, cheight, cwidth;
  556.     int maxheight, maxbase;
  557.     int size, band;
  558. static long int mem = 0L;
  559.  
  560.     if (dsp[idx].nbytes == 0)
  561.         return(0);
  562.  
  563.     cheight = cinfo[idx].cheight = dsp[idx].up + dsp[idx].down;
  564.     cinfo[idx].mycdb.format = myfdb.format; /* same as the font format */
  565.     cinfo[idx].mycdb.continuation = 0;    /* always == 0 */
  566.     cinfo[idx].mycdb.size = 6;        /* always == 6 */
  567.     /* we leave the type undefined, as it will be filled by pr_glyph */
  568.     cinfo[idx].mycdb.type = -1;    /* illegal value */
  569.  
  570.     /* double as its in 600ths of an inch */
  571.     cinfo[idx].mycdb.width = (dsp[idx].left + dsp[idx].right) * 2;
  572.     /* flaglen is same as width */
  573.     cinfo[idx].flaglen =  cinfo[idx].mycdb.width;
  574.     /* width in whole bytes */
  575.     cwidth = cinfo[idx].cwidth = (dsp[idx].left + dsp[idx].right + 7) /8;
  576.     cinfo[idx].mycdb.compr_width = 0;
  577.     /* double as its in 600ths of an inch */
  578.     cinfo[idx].mycdb.left_pad = 2 * max(-dsp[idx].left, 0);
  579.     /* double as its in 600ths of an inch */
  580.     cinfo[idx].mycdb.right_pad = 0;
  581.  
  582.     /* bottom_pad is the distance between the bottom of the character
  583.      * cell to the bottom of the design cell
  584.      */
  585.     bottom_pad = cinfo[idx].bottom_pad =
  586.         (DJ_CELLHEIGHT - myfdb.baseline) - dsp[idx].down;
  587.     /* top_pad is the distance between the top of the character cell
  588.      * and the top of the design cell.
  589.      */
  590.     top_pad = cinfo[idx].top_pad =
  591.         myfdb.cell_height - (cheight + bottom_pad);
  592.     vp = raster;
  593.     for (i=0; i<top_pad; i++)
  594.         for (j=0; j<cwidth; j++)
  595.             *vp++ = 0;
  596.     cp = &imageTable[dsp[idx].addr];
  597.     for (i=0; i<cheight; i++)
  598.         for (j=0; j<cwidth; j++)
  599.             *vp++ = *cp++;
  600.     for (i=0; i<bottom_pad; i++)
  601.         for (j=0; j<cwidth; j++)
  602.             *vp++ = 0;
  603.     /*
  604.      * at this stage raster contains the character bitmap
  605.      * (row order) correctly centered within the design cell,
  606.      */
  607.     size = CDB_LEN + npass*cwidth;
  608.     for (band=0; band < npass; band++)
  609.     {
  610.         u_char *dp, *fp;
  611.         int len;
  612.  
  613.         if ((fp = cinfo[idx].flagbytes[band]= (u_char*)malloc(cinfo[idx].flaglen))==NULL)
  614.         {
  615.             fprintf(stderr, "Couldn't allocate flagbytes for char %d\n", idx);
  616.             fprintf(stderr, "Pass %d, memory given so far = %ld\n", band, mem);
  617.             exit(1);
  618.         }
  619.         mem += cinfo[idx].flaglen;
  620.         /*
  621.           * We will now convert the character bitmap
  622.           * into something acceptable to the DeskJet.
  623.           * We feed the bitmap to rast_cvt() which creates flag and data
  624.           * bytes suitable for the DeskJet.
  625.           */
  626.         dp = dataptr;
  627.         /*
  628.          * Since we don't know how many databytes will be needed,
  629.          * we use a temporary area, and after they have been generated
  630.          * we allocate the memory and copy them.
  631.          */
  632.         rast_cvt(raster + band * (DJ_CELLHEIGHT * cwidth),
  633.             cinfo[idx].mycdb.width/2, cwidth, &dp, &fp);
  634.             
  635.         len = cinfo[idx].datalen[band] = dp - dataptr;
  636.         size += len;
  637.         if (len > 0)
  638.         {
  639.             if ((cinfo[idx].databytes[band] = (u_char*)malloc(len))==NULL)
  640.             {
  641.                 fprintf(stderr,
  642.                     "Couldn't allocate databytes for char %d\n", idx);
  643.                 fprintf(stderr,
  644.                     "Pass %d, memory given so far = %ld\n", band, mem);
  645.                 exit(1);
  646.             }
  647.             mem += len;
  648.             memcpy(cinfo[idx].databytes[band], dataptr, len);
  649.         }
  650.     }
  651.     /* we now return the memory taken up by this character */
  652.     return(size);
  653. }
  654.  
  655. /*
  656.  * pr_glyph -- send the definition of a character glyph to the printer.
  657.  *
  658.  *    idx is the position of the glyph in the vfont file and
  659.  *    dstidx will be the position that the glyph will occupy
  660.  *    in the downloaded font.
  661.  *    type designates the pass number, while band designates
  662.  *    the band of the design cell corresponding to the current
  663.  *    pass.
  664.  */
  665. pr_glyph(idx, dstidx, band, type)
  666. int idx, dstidx, band, type;
  667. {
  668.     struct char_info *cp;
  669.  
  670.     if (dsp[idx].nbytes == 0)
  671.         return;
  672.  
  673.     cp = &cinfo[idx];
  674.     cp->mycdb.type = type;
  675.  
  676.     fprintf(printer, "\033*c%dE", dstidx);
  677.     fprintf(printer, "\033(s%dW", CDB_LEN+cp->flaglen+cp->datalen[band]);
  678.     fwrite(&cinfo[idx].mycdb, CDB_LEN, 1, printer);
  679.     fwrite(cp->flagbytes[band], cp->flaglen, 1, printer);
  680.     if (cp->datalen[band] > 0)
  681.         fwrite(cp->databytes[band], cp->datalen[band], 1, printer);
  682. }
  683.  
  684. /*
  685.  * rast_cvt -- convert raster to DeskJet format
  686.  * 
  687.  * NOTE: the data in the source raster ARE MODIFIED by rast_cvt!!!
  688.  * Also this routine assumes that character raster is padded so that
  689.  * it its height is exactly equal to the DeskJet cell height (DJ_CELLHEIGHT).
  690.  * 
  691.  * Now some comments:
  692.  * 
  693.  * Think of the raster as a two dimentional array of boxes 1 byte wide
  694.  * and 8 bytes high.  Since our raster is DJ_CELLHEIGHT (==50) bytes high
  695.  * there will be two rows at the bottom that will be left out.  These
  696.  * two rows form a little box.
  697.  * 
  698.  * We now pick each box isolate the most significant bit in each byte.
  699.  * We then use the following scheme to put all those bits in one byte:
  700.  * 
  701.  *        1 A0000000       A0000000
  702.  *        2 B0000000       0B000000
  703.  *        3 C0000000       00C00000  |
  704.  *        4 D0000000 --->  000D0000  |
  705.  *        5 E0000000       0000E000 \|/
  706.  *        6 F0000000       00000F00
  707.  *        7 G0000000       000000G0
  708.  *        8 H0000000       0000000H
  709.  *                        ----------
  710.  *                          ABCDEFGH
  711.  * We now have the grouped the first column of our box in one byte
  712.  * we then shift all the bytes of that box one bit to the left and
  713.  * repeat the whole process until all the columns of the box have been
  714.  * stored in bytes.  We then move to the next box and so on.
  715.  * 
  716.  * The last two rows are treated similarly.
  717.  */
  718.  
  719. rast_cvt(raster, width, cwidth, dataptr, flagptr)
  720. u_char *raster;
  721. int width;
  722. int cwidth;
  723. u_char **dataptr;
  724. u_char **flagptr;
  725. {
  726.     register u_char *vp;
  727.     register u_char *dp = *dataptr;
  728.     register u_char *fp = *flagptr;
  729.     u_char w, flag;
  730.     int boxes, cols, row;
  731.     int remw;
  732.     int i;
  733.  
  734.     for (remw = width; remw > 0; remw -= 8, raster++)
  735.         for (cols = 1; cols <= min(8, remw); cols++)
  736.         {
  737.             flag = 0;
  738.             for (row = 0; row < DJ_CELLHEIGHT-2; row += 8)
  739.             {
  740.                 w = 0;    /* initialize data byte */
  741.                 vp = raster+(row*cwidth);
  742.                 for (i = 0; i <8; i++)
  743.                 {
  744.                     w |= ((*vp & 0x80) >> i);
  745.                     (*vp) <<= 1;    /* move next column to MSB position */
  746.                     vp += cwidth;
  747.                 }
  748.                 flag >>= 1;
  749.                 if (w != 0)
  750.                 {
  751.                     flag |= 0x80;
  752.                     *dp++ = w;
  753.                 }
  754.             }
  755.             /* and now the last (little) box */
  756.             w = (*vp & 0x80);        /* 49th bit */
  757.             (*vp) <<= 1;
  758.             vp += cwidth;
  759.             w |= ((*vp & 0x80) >> 1);    /* 50th bit */
  760.             (*vp) <<= 1;
  761.             vp += cwidth;
  762.             /* here we both set the flag and leave MSBit clear */
  763.             flag >>= 2;
  764.             if (w != 0)
  765.             {
  766.                 flag |= 0x40;
  767.                 *dp++ = w;
  768.             }
  769.             *fp++ = flag;
  770.             *fp++ = 0;        /* leave next column blank */
  771.         }
  772.     *flagptr = fp;
  773.     *dataptr = dp;
  774. }
  775.  
  776. loadfont(fontBuf)
  777. char    *fontBuf;
  778. {
  779.     int fd;        /* file handle for vfont file */
  780.     int i;
  781.     int len;
  782.     unsigned int size;
  783.  
  784. #ifdef UNIX
  785.     if ((fd = open(fontBuf, O_RDONLY)) < 0)
  786. #else
  787.     if ((fd = open(fontBuf, O_RDONLY|O_BINARY)) < 0)
  788. #endif
  789.     {
  790.         fprintf(stderr, "railmag: Could not load font %s\n", fontBuf);
  791.         exit(1);
  792.     }
  793.     fprintf(stderr, "Loaded font %s\n", fontBuf);
  794.     len = sizeof(struct header);
  795.     if (read(fd, &vf_header, len) != len)
  796.     {
  797.         fprintf(stderr, "railmag: Bad font file header\n");
  798.         exit(1);
  799.     }
  800.     if (vf_header.magic != VFONT_MAGIC)
  801.     {
  802.         fprintf(stderr, "railmag: Bad font magic number\n");
  803.         exit(1);
  804.     }
  805.     len = NUM_DISPATCH*sizeof(struct dispatch);
  806.     if ((i=read(fd, dsp, len)) != len)
  807.     {
  808.         fprintf(stderr,
  809.             "railmag: Could not load font dispatch table\n");
  810.         fprintf(stderr, "\tlen = %d, read = %d\n", len, i);
  811.         exit(1);
  812.     }
  813.     size = vf_header.size;
  814.     if (size > IMG_SIZE)
  815.     {
  816.         fprintf(stderr, "railmag: image table size (= %u) TOO BIG\n",
  817.             size);
  818.         exit(1);
  819.     }
  820.     if (read(fd, imageTable, size) != size)
  821.     {
  822.         fprintf(stderr, "railmag: Error reading image table\n");
  823.         exit(1);
  824.     }
  825.     return;
  826. }
  827.