home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2088 / pk.c
Encoding:
C/C++ Source or Header  |  1990-12-28  |  20.9 KB  |  931 lines

  1. /*    Copyright 1990 Chris Lewis
  2.  */
  3.  
  4.  
  5. #include "defs.h"
  6.  
  7. #ifdef    PK
  8.  
  9. #ifndef lint
  10. static char SCCSid[] = "@(#)pk.c 2.1 Copyright 90/07/18 16:51:38 Chris Lewis";
  11. #endif
  12.  
  13. #define    DRAW
  14. #define    OUTRES    300
  15.  
  16. #include "pk.h"
  17.  
  18. #if    defined(PARTIAL)
  19. #include "pkc.h"
  20. struct needmaps *needmaps = (struct needmaps *) NULL;
  21. #endif
  22.  
  23. extern char *progname;
  24.  
  25. static FILE *fin;
  26. static char *filename;    /* name of *current* font being read */
  27. extern char *malloc();
  28.  
  29. static long flag_byte;
  30. static repeatcount;
  31. static dyn_f;
  32.  
  33. static readraster();
  34.  
  35. static long
  36. get1int() { return(getc(fin)); }
  37.  
  38. static long
  39. get2int() {
  40.     register long c;
  41.     c = get1int();
  42.     c = (c<<8) | (0xff & get1int());
  43.     return(c);
  44. }
  45.  
  46. static long
  47. get4int() {
  48.     register long c;
  49.     c = get2int();
  50.     c = (c << 16) | (0xffff & get2int());
  51.     return(c);
  52. }
  53.  
  54. static long
  55. get3int() {
  56.     register long c;
  57.     c = get2int();
  58.     c = (c << 8) | (0xff & get1int());
  59.     return(c);
  60. }
  61.  
  62. #ifdef VFPRINTF
  63. #include <varargs.h>
  64. /* VARARGS */
  65. pkmsg(va_alist)
  66. va_dcl
  67. {
  68.     va_list args;
  69.     char *fmt;
  70.  
  71.     va_start(args);
  72.     fmt = (char *) va_arg(args, char *);
  73.     VFPRINTF(stderr, fmt, args);
  74.     va_end(args);
  75. }
  76. #else
  77. /* VARARGS1 ARGSUSED */
  78. pkmsg(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  79. char    *fmt;
  80. int    a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; {
  81.     char buf[BUFSIZ];
  82.     sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  83.     fprintf(stderr, buf);
  84. }
  85. #endif
  86.  
  87. static
  88. skipspecials() {
  89.     register int i,c;
  90.     do {
  91.     flag_byte = getc(fin);
  92.     if (flag_byte >= 240) {
  93.         i = 0;
  94.         switch(flag_byte) {
  95.         case PK_xxx4:
  96.             i = (i << 8) + getc(fin);
  97.         case PK_xxx3:
  98.             i = (i << 8) + getc(fin);
  99.         case PK_xxx2:
  100.             i = (i << 8) + getc(fin);
  101.         case PK_xxx1:
  102.             i = (i << 8) + getc(fin);
  103.             DBP((D_PK, "PK_xxx%d: ", flag_byte - PK_xxx1 + 1));
  104.             while(i--) {
  105.             c = getc(fin);
  106.             DBP((D_PK, "%c", c));
  107.             }
  108.             DBP((D_PK, "\n"));
  109.             break;
  110.         case PK_yyy:
  111.             i = get4int();
  112.             DBP((D_PK, "Num special: %d\n", i));
  113.             break;
  114.         case PK_post:
  115.             DBP((D_PK, "Postamble\n"));
  116.             break;
  117.         case PK_no_op:
  118.             DBP((D_PK, "No-op\n"));
  119.             break;
  120.         default:
  121.             pkmsg("PK file %s: Unexpected %ld\n", filename,
  122.             flag_byte);
  123.             exit(1);
  124.         }
  125.     }
  126.     } while (flag_byte >= 240 && flag_byte != PK_post);
  127. }
  128.  
  129. static
  130. readschar(p)
  131. struct pkc *p; {
  132.     p->pkc_pl = get1int() + ((p->pkc_flag&0x3) << 8);
  133.     p->pkc_char = get1int();
  134.     p->pkc_tfm = get3int();
  135.     p->pkc_dx = get1int() * pow2(16);
  136.     p->pkc_dy = 0;
  137.     p->pkc_width = get1int();
  138.     p->pkc_height = get1int();
  139.     p->pkc_x_off = get1int();
  140.     p->pkc_y_off = get1int();
  141.     if (p->pkc_x_off > 127)
  142.     p->pkc_x_off -= 256;
  143.     if (p->pkc_y_off > 127)
  144.     p->pkc_y_off -= 256;
  145.     p->pkc_rlen = p->pkc_pl - 8;
  146.     readraster(p);
  147. }
  148.  
  149. static
  150. readeschar(p)
  151. struct pkc *p; {
  152.     p->pkc_pl = get2int() + ((p->pkc_flag&0x3) << 16);
  153.     p->pkc_char = get1int();
  154.     p->pkc_tfm = get3int();
  155.     p->pkc_dx = get2int() * pow2(16);
  156.     p->pkc_dy = 0;
  157.     p->pkc_width = get2int();
  158.     p->pkc_height = get2int();
  159.     p->pkc_x_off = get2int();
  160.     p->pkc_y_off = get2int();
  161.     if (p->pkc_x_off > 32767)
  162.     p->pkc_x_off -= 65536;
  163.     if (p->pkc_y_off > 32767)
  164.     p->pkc_y_off -= 65536;
  165.     p->pkc_rlen = p->pkc_pl - 13;
  166.     readraster(p);
  167. }
  168.  
  169. static
  170. readlchar(p)
  171. struct pkc *p; {
  172.     p->pkc_pl = get4int();
  173.     p->pkc_char = get4int();
  174.     p->pkc_tfm = get4int();
  175.     p->pkc_dx = get4int();
  176.     p->pkc_dy = get4int();
  177.     p->pkc_width = get4int();
  178.     p->pkc_height = get4int();
  179.     p->pkc_x_off = get4int();
  180.     p->pkc_y_off = get4int();
  181.     p->pkc_rlen = p->pkc_pl - 28;
  182.     readraster(p);
  183. }
  184.  
  185. static
  186. readraster(p)
  187. struct pkc *p; {
  188.     p->pkc_pkr = (int8 *) mustmalloc((int) p->pkc_rlen, filename);
  189.     fread((char *) p->pkc_pkr, 1, (int) p->pkc_rlen, fin);
  190. }
  191.  
  192. /*    Read a character sequence from a PK file */
  193. static struct pkc *
  194. rpkc() {
  195.     register struct pkc *p = (struct pkc *) mustmalloc(sizeof(struct pkc),
  196.     filename);
  197.  
  198.     p->pkc_pkr = NULL;
  199.     p->pkc_sfpr = NULL;
  200.     p->pkc_flag = flag_byte;
  201.     p->pkc_dyn_f = p->pkc_flag >> 4;
  202.     flag_byte &= 0x7;
  203.  
  204.     if (flag_byte == 7)
  205.     readlchar(p);
  206.     else if (flag_byte > 3)
  207.     readeschar(p);
  208.     else
  209.     readschar(p);
  210.     return(p);
  211. }
  212.  
  213. #ifdef    SFP
  214. /*    Read a character sequence from an SFP */
  215. static struct pkc *
  216. rsfpc() {
  217.     register struct pkc *p;
  218.     int len;
  219.  
  220.     if ((len = getc(fin)) == EOF || len != '\033') {
  221.     /* HP fonts when loaded often have trailing nulls due to DOS
  222.        file padding.  Screech on non-null */
  223.     if (len && len != EOF)
  224.         fprintf(stderr,
  225.         "%s: WARNING: trailing garbage in %s, offset %ld, char 0x%02x\n",
  226.         progname, filename, ftell(fin), len);
  227.     flag_byte = PK_post;
  228.     return((struct pkc *) NULL);
  229.     }
  230.  
  231.     p = (struct pkc *) mustmalloc(sizeof(struct pkc), filename);
  232.     p->pkc_pkr = NULL;
  233.     p->pkc_sfpr = NULL;
  234.     p->pkc_flag = 0;
  235.     p->pkc_dyn_f = 0;
  236.  
  237.     if (fscanf(fin, "*c%ldE", &(p->pkc_char)) != 1) {
  238.     pkmsg("SFP file: %s, bad/missing SET CHAR CODE, offset: %ld\n",
  239.         filename, ftell(fin));
  240.     exit(1);
  241.     }
  242.  
  243.     if (fscanf(fin, "\033(s%dW", &len) != 1 || len < 16) {
  244.     pkmsg("SFP file: %s, bad/missing/tooshort CHAR DOWNLOAD sequence\n",
  245.         filename);
  246.     exit(1);
  247.     }
  248.  
  249.     get4int();    /* skip some garbage */
  250.     get2int();    /* skip more garbage (actually, orientation & dummy */
  251.  
  252.     p->pkc_x_off = get2int();
  253.     if (p->pkc_x_off > 32767)
  254.     p->pkc_x_off -= 65536;
  255.     p->pkc_x_off = -p->pkc_x_off;
  256.     p->pkc_y_off = get2int();
  257.     if (p->pkc_y_off > 32767)
  258.     p->pkc_y_off -= 65536;
  259.     p->pkc_width = get2int();
  260.     p->pkc_height = get2int();
  261.     p->pkc_dx = get2int() * pow2(16) / 4;
  262.  
  263.     p->pkc_sfpr = (struct ras *) mustmalloc(sizeof(struct ras), filename);
  264.  
  265.     p->pkc_sfpr->ras_height = p->pkc_height;
  266.     p->pkc_sfpr->ras_width = p->pkc_width;
  267.     p->pkc_sfpr->ras_bline = (p->pkc_width + 7) / 8;
  268.     p->pkc_sfpr->ras_bytes = p->pkc_sfpr->ras_height * p->pkc_sfpr->ras_bline;
  269.     if (p->pkc_sfpr->ras_bytes) {
  270.     p->pkc_sfpr->ras_raster = (int8 *) mustmalloc((int)
  271.         p->pkc_sfpr->ras_bytes, filename);
  272.  
  273.     fread((char *) p->pkc_sfpr->ras_raster, (int) p->pkc_sfpr->ras_bytes,
  274.         1, fin);
  275.     } else {
  276.     free((char *) p->pkc_sfpr);
  277.     p->pkc_sfpr = NULL;
  278.     }
  279.  
  280.     return(p);
  281. }
  282. #endif
  283.  
  284. static struct pkc *
  285. readchar(p)
  286. struct pkp *p; {
  287.     if (p->pkp_flags&PK_PK)
  288.     return(rpkc());
  289. #ifdef    SFP
  290.     else if (p->pkp_flags&PK_SFP)
  291.     return(rsfpc());
  292. #endif
  293.     else
  294.     return((struct pkc *) NULL);
  295. }
  296.  
  297. static int
  298. pkccomp(a, b)
  299. struct pkc **a, **b; {
  300.     if ((*a)->pkc_char < (*b)->pkc_char)
  301.     return(-1);
  302.     else
  303.     return(1);
  304.     /* can't be equal! */
  305. }
  306.  
  307. static
  308. rastbit(x,y,r)
  309. register int x, y;
  310. register struct ras *r; {
  311.     register int bi = y * r->ras_bline + (x >> 3);
  312.  
  313.     /* You don't really want to uncomment this.... ;-) */
  314.     /*    printf("x,y,bi: %d,%d,%d\n", x, y, bi);*/
  315.     return(r->ras_raster[bi] & (0x80 >> (x&7)));
  316. }
  317.  
  318. static int8 *rptr;
  319. static long bitweight;
  320.  
  321. getnyb() {
  322.     register int8 b;
  323.     if (!bitweight) {
  324.     bitweight = 8;
  325.     rptr++;
  326.     }
  327.     b = *rptr;
  328.     bitweight -= 4;
  329. #ifdef    VDEBUG
  330.     DBP((D_PK, "getnyb byte: %x\n", b));
  331.     DBP((D_PK, "getnyb: %x\n", (b >> bitweight) & 0xf));
  332. #endif
  333.     return((b >> bitweight)&0xf);
  334. }
  335.  
  336. #ifdef    NEVER
  337. getbit() {
  338.     register int8 b;
  339.     if (!bitweight) {
  340.     bitweight = 8;
  341.     rptr++;
  342.     }
  343.     b = *rptr;
  344.     bitweight--;
  345.     return((b>>bitweight)&1);
  346. }
  347. #endif
  348.  
  349. /*    Dumps an ASCII version of the SFP raster r, to line n.
  350.     Normally only for debugging, but is also used from pktype
  351.  */
  352.  
  353. dumpr(r, n)
  354. struct ras *r;
  355. int n; {
  356.     int x, y;
  357.     if (!diagFile)
  358.     return;
  359.     fprintf(diagFile, "\n");
  360.     for (y = 0; y < n; y++) {
  361.     fprintf(diagFile, "%3d  ", y);
  362.     for (x = 0; x < r->ras_width; x++) {
  363.         if (rastbit(x, y, r))
  364.         putc('*', diagFile);
  365.         else
  366.         putc(' ', diagFile);
  367.     }
  368.     putc('\n', diagFile);
  369.     }
  370. }
  371.  
  372. static long
  373. pkpack(pc,r)
  374. register struct pkc *pc;
  375. register struct ras *r; {
  376.     long i, j;
  377.     long pkpackret;
  378.     i = getnyb();
  379.     if (i == 0) {
  380.     do {
  381.         j = getnyb();
  382.         i++;
  383.     } while(!j);
  384.     while(i--)
  385.         j = (j << 4) + getnyb();
  386.     pkpackret = (j - 15 + (13 - dyn_f) * 16 + dyn_f);
  387.     } else if (i <= dyn_f)
  388.     pkpackret = (i);
  389.     else if (i < 14)
  390.     pkpackret = ((i - dyn_f - 1)*16 + getnyb() + dyn_f + 1);
  391.     else {
  392.     if (repeatcount) {
  393.         pkmsg("Second repeat count for this row!\n");
  394.         exit(1);
  395.     }
  396.     if (i == 14)
  397.         repeatcount = pkpack(pc,r);
  398.     else
  399.         repeatcount = 1;
  400.     /*sendout(1, repeatcount, pc, r);*/
  401.     pkpackret = (pkpack(pc,r));
  402.     }
  403.     if (pkpackret < 1) {
  404.     pkmsg("pkpack returned < 1! (%s)", filename);
  405.     exit(1);
  406.     }
  407.     return(pkpackret);
  408. }
  409.  
  410. static
  411. getpbits(pc, r)
  412. register struct pkc *pc;
  413. register struct ras *r; {
  414.     register int h_bit        = pc->pkc_width,
  415.          count,
  416.          turnon;
  417.     turnon = pc->pkc_flag&0x8;
  418.     dyn_f = pc->pkc_dyn_f;
  419.     repeatcount = 0;
  420.     r->ras_xcur = r->ras_ycur = 0;
  421.     while(r->ras_ycur < pc->pkc_height) {
  422.     count = pkpack(pc,r);
  423.     while(count > 0) {
  424.         if (count >= h_bit) {
  425.         count -= h_bit;
  426.         while(h_bit--) {
  427.             if (turnon)
  428.             r->ras_raster[r->ras_ycur*r->ras_bline + (r->ras_xcur>>3)]
  429.                 |= (0x80 >> (r->ras_xcur&7));
  430.             r->ras_xcur++;
  431.         }
  432.         r->ras_ycur++;
  433.         r->ras_xcur = 0;
  434.         while(repeatcount --) {
  435. #ifdef    VDEBUG
  436.             DBP((D_PK, "Copy line %d to %d\n", r->ras_ycur,
  437.             r->ras_ycur-1));
  438. #endif
  439.             memcpy((char*)&(r->ras_raster[r->ras_ycur * r->ras_bline]),
  440.                (char*)&(r->ras_raster[(r->ras_ycur - 1) *
  441.                    r->ras_bline]),
  442.                (int) r->ras_bline);
  443.             r->ras_ycur++;
  444.         }
  445.         repeatcount = 0;
  446.         h_bit = pc->pkc_width;
  447.         } else {
  448.         h_bit -= count;
  449.         while(count--) {
  450.             if (turnon)
  451.             r->ras_raster[r->ras_ycur*r->ras_bline +
  452.                 (r->ras_xcur>>3)] |= (0x80 >> (r->ras_xcur&7));
  453.             r->ras_xcur++;
  454.         }
  455.         count = 0;
  456.         }
  457.     }
  458.     turnon = !turnon;
  459.     }
  460.     if (r->ras_ycur != pc->pkc_height ||
  461.     h_bit != pc->pkc_width)
  462.     pkmsg("Bad bit somehow (%s)\n", filename);
  463. }
  464.  
  465. static
  466. getrbits(pc, r)
  467. register struct pkc *pc;
  468. register struct ras *r; {
  469.     register int x, y;
  470.     register int bit = 0;
  471.     for (y = 0; y < pc->pkc_height; y++) {
  472.     for (x = 0; x < pc->pkc_width; x++) {
  473.         if (pc->pkc_pkr[bit >> 3] & (0x80 >> (bit&7)))
  474.         r->ras_raster[y*r->ras_bline + (x>>3)] |= (0x80 >> (x&7));
  475.         bit++;
  476.     }
  477.     }
  478. }
  479.  
  480. /*    Convert a PK raster to an unpacked SFP version.
  481.     (If there's already an SFP version, it's returned instead)
  482.  */
  483. struct ras *
  484. pkrast(pc)
  485. struct pkc *pc; {
  486.     register struct ras *r;
  487.     if (pc->pkc_sfpr)
  488.     return(pc->pkc_sfpr);
  489.     if (!pc->pkc_rlen)
  490.     return(NULL);
  491.  
  492.     pc->pkc_sfpr = r = (struct ras *) mustmalloc(sizeof(struct ras),
  493.     filename);
  494.  
  495.     r->ras_height = pc->pkc_height;
  496.     r->ras_width = pc->pkc_width;
  497.     r->ras_bline = (pc->pkc_width + 7) / 8;
  498.     r->ras_bytes = r->ras_height * r->ras_bline;
  499.     r->ras_raster = (int8 *) mustmalloc((int) r->ras_bytes, filename);
  500.  
  501.     /* initialize bit unpackers */
  502.     rptr = pc->pkc_pkr;
  503.     bitweight = 8;
  504.  
  505.     /* calculate bits here...*/
  506.     if (pc->pkc_dyn_f == 14)
  507.     getrbits(pc, r);
  508.     else
  509.     getpbits(pc, r);
  510.     return(r);
  511. }
  512.  
  513. /*    Read a PK font file header */
  514. static struct pkp *
  515. pk_rpk(p)
  516. register struct pkp *p; {
  517.     register int i,c;
  518.  
  519.     if (getc(fin) != 89) {
  520.     pkmsg("PK file %s: Wrong version of packed file!\n", filename);
  521.     exit(1);
  522.     }
  523.     i = getc(fin);
  524.     if (i > 0) {
  525.     DBP((D_PK, "PKVersion: "));
  526.     while (i--) {
  527.         c = getc(fin);
  528.         DBP((D_PK, "%c", c));
  529.     }
  530.     DBP((D_PK, "\n"));
  531.     }
  532.     p->pkp_bmax = 0;
  533.     p->pkp_dmax = 0;
  534.     p->pkp_wmax = 0;
  535.     p->pkp_xomax = 0;
  536.     p->pkp_ds = get4int();
  537.     p->pkp_cs = get4int();
  538.     p->pkp_hppp = get4int();
  539.     p->pkp_vppp = get4int();
  540.  
  541.     if (p->pkp_hppp != p->pkp_vppp)
  542.     pkmsg("PK file %s: Warning aspect ratio not 1:1\n", filename);
  543.     p->pkp_res = (double) p->pkp_hppp * POINT / pow2(16) + .5;
  544.     p->pkp_npts = ((double) p->pkp_ds / pow2(20)) *
  545.     ((double) p->pkp_res / OUTRES) + .5;
  546.     p->pkp_chars = (struct pkc *) NULL;
  547.     p->pkp_last = (struct pkc *) NULL;
  548.     p->pkp_num = 0;
  549.     p->pkp_list = (struct pkc **) NULL;
  550.  
  551.     /*    Try to guess symset, style, stroke weight and typeface
  552.     These aren't particularly important, but it assists the LJ
  553.     if it's trying to select one of these via characteristic.
  554.     This will only work if the file name reflects the Troff name,
  555.     according to the following conventions:
  556.  
  557.     filename: {<path>/}troffname.pointsize.[pk|sfp]
  558.  
  559.     All ROMAN8 encodings unless MATH8.
  560.     All 0 strokeweight, unless Bold.
  561.     All upright, unless Italic
  562.     All Roman typeface, unless otherwise specified
  563.  
  564.         R    : Normal Roman
  565.         I    : Italic
  566.         B    : Bold
  567.         S    : MATH8 Symbol
  568.         X    : Bold italic
  569.         .X    : <typeface> Bold italic
  570.         .I    : <typeface> Italic
  571.         .B    : <typeface> Bold
  572.         .R    : <typeface> Normal
  573.         H or H.    : Helvetica typeface
  574.         C or C.    : Courier typeface
  575.               typefaces should be extended.
  576.      */
  577.  
  578.     {
  579.     register char *fp;
  580.     register int char1, char2, italic, bold, bolditalic, onechar;
  581.  
  582.     fp = strrchr(filename, '/');
  583.     if (!fp)
  584.         fp = filename;
  585.     else
  586.         fp++;
  587.  
  588.     /* Default settings */
  589.     p->pkp_symset = (8 << 5) - 64 + 'U';    /* ROMAN 8 */
  590.     p->pkp_style = 0;    /* upright */
  591.     p->pkp_sw = 0;        /* stroke 0 */
  592.     p->pkp_typeface = 5;    /* typeface Roman */
  593.  
  594.     char1 = *fp++;
  595.     onechar = (*fp == '.');
  596.  
  597.     if (char1 == 'S' && onechar)
  598.         p->pkp_symset = (8 << 5) - 64 + 'M';    /* MATH 8 */
  599.     else {
  600.  
  601.         char2 = *fp;
  602.  
  603.         italic = ((onechar && char1 == 'I') || char2 == 'I');
  604.         bold = ((onechar && char1 == 'B') || char2 == 'B');
  605.         bolditalic = ((onechar && char1 == 'X') || char2 == 'X');
  606.  
  607.         if (bold || bolditalic)
  608.         p->pkp_sw = 3;
  609.  
  610.         if (italic || bolditalic)
  611.         p->pkp_style = 1;
  612.  
  613.         /* This should be extended, but I don't have a good feeling
  614.            for troff typeface -> HPLJ nomenclature */
  615.         switch(char1) {
  616.         case 'H':
  617.             p->pkp_typeface = 4;    /* Helvetica */
  618.             break;
  619.         case 'C':
  620.             p->pkp_typeface = 3;    /* Courier */
  621.             break;
  622.         /* more? */
  623.         }
  624.     }
  625.     }
  626.  
  627.     return(p);
  628. }
  629.  
  630. #ifdef    SFP
  631.  
  632. /*    Read an SFP header and convert it into the PK internal structure.
  633.  */
  634. static struct pkp *
  635. pk_rsfp(p)
  636. register struct pkp *p; {
  637.     register int c;
  638.     int len;
  639.  
  640.     if (fscanf(fin, ")s%dW", &len) != 1) {
  641.     pkmsg("SFP file %s: Bad CREATE FONT sequence\n", filename);
  642.     exit(1);
  643.     }
  644.  
  645.     if (len < 26) {
  646.     pkmsg("SFP file %s: CREATE FONT sequence too short (%d)\n",
  647.         filename, len);
  648.     exit(1);
  649.     }
  650.  
  651.     get2int();    /* 26 */
  652.     get1int();    /* 0 */
  653.     get1int();    /* 0 or 1 - forced 1 anyways */
  654.     get2int();    /* dummy */
  655.  
  656.     p->pkp_bmax = get2int();    /* baseline */
  657.     p->pkp_wmax = get2int();    /* cell width */
  658.     p->pkp_dmax = get2int() - p->pkp_bmax;    /* cell height */
  659.  
  660.     get1int();    /* 0 port, 1 land - forced 0 */
  661.     get1int();    /* fixed/proportional - forced proportional */
  662.  
  663.     p->pkp_symset = get2int();
  664.  
  665.     get2int();        /* pitch - we calculate this from height */
  666.     c = get2int();    /* retrieved *height* */
  667.     p->pkp_npts = c * POINT / (OUTRES*4) + .5;
  668.  
  669.     get2int();    /* dummy */
  670.     get1int();    /* dummy */
  671.  
  672.     p->pkp_style = get1int();
  673.     p->pkp_sw = get1int();
  674.     p->pkp_typeface = get1int();
  675.  
  676.     p->pkp_xomax = 0;
  677.  
  678.     /* These are simulated so that the PK handlers can figure the font out */
  679.     p->pkp_ds = p->pkp_npts * pow2(20);
  680.     p->pkp_cs = 0;
  681.     p->pkp_hppp = OUTRES * pow2(16) / POINT;
  682.     p->pkp_vppp = OUTRES * pow2(16) / POINT;
  683.     p->pkp_res = (double) p->pkp_hppp * POINT / pow2(16) + .5;
  684.  
  685.     p->pkp_chars = (struct pkc *) NULL;
  686.     p->pkp_last = (struct pkc *) NULL;
  687.     p->pkp_num = 0;
  688.     p->pkp_list = (struct pkc **) NULL;
  689.  
  690.  
  691.     len -= 26;
  692.     while(len--)
  693.     getc(fin);
  694.     return(p);
  695. }
  696. #endif
  697.  
  698. static struct pkp *
  699. readhead() {
  700.     register struct pkp *p = (struct pkp *) mustmalloc(sizeof(struct pkp),
  701.     filename);
  702.     switch(getc(fin)) {
  703.     case PK_pre:
  704.         p->pkp_flags |= PK_PK;
  705.         return(pk_rpk(p));
  706. #ifdef    SFP
  707.     case 0x1b:
  708.         p->pkp_flags |= PK_SFP;
  709.         flag_byte = 0;
  710.         return(pk_rsfp(p));
  711. #endif
  712.     default:
  713.         fprintf(stderr, "PK file: %s don't know what it is!\n",
  714.         filename);
  715.         exit(1);
  716.     }
  717.     /*NOTREACHED*/
  718. }
  719.  
  720. pk_destroy(p)
  721. register struct pkp *p; {
  722.     register struct pkc *pc, *opc;
  723.     for (pc = p->pkp_chars; pc;) {
  724.     if (pc->pkc_pkr)
  725.         free((char *) pc->pkc_pkr);
  726.  
  727.     if (pc->pkc_sfpr) {
  728.         free((char *) pc->pkc_sfpr->ras_raster);
  729.         free((char *) pc->pkc_sfpr);
  730.     }
  731.  
  732.     opc = pc;
  733.     pc = opc->pkc_next;
  734.     free((char *) opc);
  735.     }
  736.     if (p->pkp_list)
  737.     free((char *) p->pkp_list);
  738.     free((char *) p);
  739. }
  740.  
  741. struct pkp *
  742. pk_read(file, fontcode)
  743. char *file; int fontcode; {
  744.     register struct pkp *p;
  745.     register struct pkc *pc, **pcp;
  746. #ifdef    COMPRESS
  747.     int compressed = 0;
  748. #endif
  749.     fin = (FILE *) NULL;
  750.     if (access(filename = file, 4) == 0)
  751.     fin = fopen(filename, "r");
  752. #ifdef    COMPRESS
  753.     else {
  754.     char buf[1024];
  755.     strcpy(buf, file);
  756.     strcat(buf, ".Z");
  757.     if (access(buf, 4) == 0) {
  758.         sprintf(buf, "%s %s.Z", COMPRESS, file);
  759.         fin = popen(buf, "r");
  760.         compressed = 1;
  761.     }
  762.     }
  763. #endif
  764.     if (!fin) {
  765.     pkmsg("Cannot open PK/SFP file %s\n", file);
  766.     exit(1);
  767.     }
  768.     p = readhead();
  769.     if (p->pkp_flags&PK_PK)
  770.     skipspecials();
  771.  
  772.     while ((flag_byte != PK_post) && (pc = readchar(p))) {
  773.     DBP((D_VERB, "type: %s: %d\n", p->pkp_flags&PK_PK? "PK": "SFP",
  774.         pc->pkc_char));
  775. #ifdef    PARTIAL
  776.     if (!needchar(fontcode, pc->pkc_char)) {
  777.         DBP((D_FONT|D_PK, "Dropping char %02x from load\n", pc->pkc_char));
  778.  
  779.         if (pc->pkc_pkr) {
  780.         free((char *) pc->pkc_pkr);
  781.         pc->pkc_pkr = (int8 *) NULL;
  782.         }
  783.  
  784.         if (pc->pkc_sfpr) {
  785.         free((char *) pc->pkc_sfpr->ras_raster);
  786.         free((char *) pc->pkc_sfpr);
  787.         pc->pkc_sfpr = (struct ras *) NULL;
  788.         }
  789.  
  790.         free((char *) pc);
  791.         if (p->pkp_flags&PK_PK)
  792.         skipspecials();
  793.         continue;
  794.     }
  795. #endif
  796.     DBP((D_FONT|D_PK, "Loading char %02x\n", pc->pkc_char));
  797.     p->pkp_num++;
  798.     pc->pkc_next = (struct pkc *) NULL;
  799.     if (!p->pkp_chars)
  800.         p->pkp_chars = pc;
  801.     if (p->pkp_last)
  802.         p->pkp_last->pkc_next = pc;
  803.     p->pkp_last = pc;
  804.     if (p->pkp_flags&PK_PK) {
  805.         p->pkp_bmax = max(p->pkp_bmax, pc->pkc_y_off);
  806.         p->pkp_dmax = max(p->pkp_dmax, pc->pkc_height - pc->pkc_y_off);
  807.         p->pkp_wmax = max(p->pkp_wmax, pc->pkc_width - pc->pkc_x_off);
  808.     }
  809.     p->pkp_xomax = min(p->pkp_xomax, pc->pkc_x_off);
  810.     if (pc->pkc_char == 'a') {
  811.         p->pkp_kh = pc->pkc_y_off;
  812.         p->pkp_kl = pc->pkc_y_off - pc->pkc_height;
  813.     }
  814.     if (p->pkp_flags&PK_PK)
  815.         skipspecials();
  816.     }
  817.     DBP((D_FONT|D_PK, "End of font\n"));
  818. #ifdef    COMPRESS
  819.     if (compressed) {
  820.     if (pclose(fin)) {
  821.         pkmsg("Decompression of %s failed\n", file);
  822.         exit(1);
  823.     }
  824.     } else
  825. #endif
  826.     fclose(fin);
  827.     pcp = p->pkp_list = (struct pkc **)
  828.     mustmalloc((int) (p->pkp_num * sizeof(struct pkc *)), filename);
  829.     for (pc = p->pkp_chars; pc; pc = pc->pkc_next)
  830.     *pcp++ = pc;
  831.     qsort(p->pkp_list, (unsigned) p->pkp_num, sizeof(struct pkc *), pkccomp);
  832.     return(p);
  833. }
  834.  
  835. /*    Emit routines */
  836.  
  837. /*    Emit a font descriptor in SFP format */
  838. epk_desc(p, sfp)
  839. register struct pkp *p;
  840. FILE *sfp; {
  841.  
  842.     fprintf(sfp, "\033)s26W");
  843.     fputshort(26, sfp);
  844.     fputc(0, sfp);
  845.     fputc(1, sfp);    /* font type 1 (33-127 && 160-255 printable) */
  846.     fputshort(0, sfp);
  847.     fputshort(p->pkp_bmax, sfp);    /* baseline position */
  848.     fputshort(p->pkp_wmax, sfp);    /* cell width */
  849.     fputshort(p->pkp_bmax + p->pkp_dmax, sfp);    /* cell height */
  850.     fputc(0, sfp);    /* portrait */
  851.     fputc(1, sfp);    /* proportional */
  852.  
  853.     fputshort((long) p->pkp_symset, sfp);
  854.  
  855.     fputshort((long) (OUTRES * p->pkp_npts * 4) / 120, sfp);
  856.     fputshort((long) (p->pkp_npts * (OUTRES / POINT) * 4), sfp);
  857.     fputshort(0, sfp);
  858.     fputc(0, sfp);
  859.     fputc(p->pkp_style, sfp);
  860.     fputc(p->pkp_sw, sfp);
  861.     fputc(p->pkp_typeface, sfp);
  862.  
  863. }
  864.  
  865. fputshort(val, f)
  866. FILE *f;
  867. long val; {
  868.     fputc(((int) val >> 8) & 0xff, f);
  869.     fputc((int) val & 0xff, f);
  870. }
  871.  
  872.  
  873. /*    Emit a character descriptor in SFP format.
  874.     Notes: if this is a PK font, the PK raster is converted
  875.     to SFP format and dumpped.  If the font was originally
  876.     SFP format, it's dumpped directly.  In either event, epkc_desc
  877.     deletes the SFP raster *and* the PK raster (if the character
  878.     has one), meaning that once this routine has emitted a character,
  879.     you can't emit it again!  Which is why pkc's pkflush completely
  880.     destroys the font.  Why?  Well, SFP's can get rather large, and
  881.     it seems reasonable to get rid of them as quickly as possible.
  882.  
  883.     Returns number of bytes emitted.
  884.  */
  885. epkc_desc(pc, sfp)
  886. register struct pkc *pc;
  887. register FILE *sfp; {
  888.     register struct ras *r;
  889.  
  890.     if (!pc->pkc_pkr && !pc->pkc_sfpr) {
  891.     fprintf(stderr, "%s: already downloaded %02x\n", pc->pkc_char);
  892.     return(0);
  893.     }
  894.  
  895.     /* Emit SET CHARACTER sequence */
  896.     fprintf(sfp, "\033*c%dE", pc->pkc_char);
  897.  
  898.     /* Emit DOWNLOAD CHARACTER sequence */
  899.     fprintf(sfp, "\033(s%dW", 16 + ((pc->pkc_width + 7) / 8) *
  900.     pc->pkc_height);
  901.     fputc(4, sfp);
  902.     fputc(0, sfp);
  903.     fputc(14, sfp);
  904.     fputc(1, sfp);
  905.     fputc(0, sfp);        /* portrait */
  906.     fputc(0, sfp);
  907.     fputshort(-pc->pkc_x_off, sfp);
  908.     fputshort(pc->pkc_y_off, sfp);
  909.     fputshort(pc->pkc_width, sfp);
  910.     fputshort(pc->pkc_height, sfp);
  911.     fputshort(pc->pkc_dx * 4 / pow2(16), sfp);
  912.     r = pkrast(pc);
  913.  
  914.     if (pc->pkc_pkr)
  915.     free((char *) pc->pkc_pkr);
  916.     pc->pkc_pkr = (int8 *) NULL;
  917.  
  918.     if (r) {
  919. #ifdef    VDEBUG
  920.     dumpr(r, r->ras_ycur);
  921. #endif
  922.     fwrite((char *) r->ras_raster, 1, (int) ((pc->pkc_width + 7) / 8) *
  923.         (int) pc->pkc_height, sfp);
  924.     free((char *) r->ras_raster);
  925.     free((char *) r);
  926.     }
  927.     pc->pkc_sfpr = (struct ras *) NULL;
  928.     return(((pc->pkc_width + 7) / 8) * pc->pkc_height);
  929. }
  930. #endif
  931.