Main Page   Modules   Alphabetical List   Compound List   File List   Compound Members   File Members  

t1lib.c

Go to the documentation of this file.
00001 /*  $Id: t1lib.c,v 1.5 2000/11/30 07:37:40 dbryson Exp $ */
00002 
00003 /*
00004 **  Description:
00005 **  
00006 **    This file is part of libps
00007 **
00008 **
00009 **  Contact:
00010 **
00011 **      Mail:
00012 **
00013 **        Technology Associates, Inc.
00014 **        LIBPS Project
00015 **        1455 Deming Way #11
00016 **        Sparks, NV  89431
00017 **        USA
00018 **
00019 **      Email:
00020 **
00021 **        libps@techass.com
00022 **
00023 **      See our website at:
00024 **
00025 **        libps.sourceforge.net
00026 **
00027 */
00028 
00029 /* t1lib
00030  *
00031  * This file contains functions for reading PFA and PFB files.
00032  *
00033  * (C) 1999 Eddie Kohler <eddietwo@lcs.mit.edu>, after code by
00034  * I. Lee Hetherington <ilh@lcs.mit.edu>. All rights reserved.
00035  *
00036  * Permission is hereby granted to use, modify, and distribute this program
00037  * for any purpose provided this copyright notice remains intact.
00038  *
00039  *
00040  * libps
00041  *
00042  * Made various changes for inclusion in libps including modifying these
00043  * routines to use the PSStream stuff and various name changes.
00044  *
00045  * November 21, 2000 Derry Bryson <derry@techass.com>
00046  */
00047 
00051 #ifdef HAVE_CONFIG_H
00052 # include "psconfig.h"
00053 #endif
00054 
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <ctype.h>
00058 #include <string.h>
00059 #include "ps/ps.h"
00060 #include "t1lib.h"
00061 #ifdef __cplusplus
00062 extern "C" {
00063 #endif
00064 
00065 #define PFA_ASCII       1
00066 #define PFA_EEXEC_TEST  2
00067 #define PFA_HEX         3
00068 #define PFA_BINARY      4
00069 
00070 /* This function returns the value (0-15) of a single hex digit.  It returns
00071    0 for an invalid hex digit. */
00072 
00073 static int
00074 hexval(char c)
00075 {
00076   if (c >= 'A' && c <= 'F')
00077     return c - 'A' + 10;
00078   else if (c >= 'a' && c <= 'f')
00079     return c - 'a' + 10;
00080   else if (c >= '0' && c <= '9')
00081     return c - '0';
00082   else
00083     return 0;
00084 }
00085 
00086 /* This function translates a string of hexadecimal digits into binary data.
00087    We allow an odd number of digits. Returns length of binary data. */
00088 
00089 static int
00090 translate_hex_string(char *s)
00091 {
00092   static char saved_orphan = 0;
00093   int c1 = saved_orphan;
00094   char *start = s;
00095   char *t = s;
00096   for (; *s; s++) {
00097     if (isspace(*s)) continue;
00098     if (c1) {
00099       *t++ = (hexval(c1) << 4) + hexval(*s);
00100       c1 = 0;
00101     } else
00102       c1 = *s;
00103   }
00104   saved_orphan = c1;
00105   return t - start;
00106 }
00107 
00108 /* This function returns 1 if the string contains all '0's. */
00109 
00110 static int
00111 all_zeroes(char *string)
00112 {
00113   if (*string == '\0' || *string == '\n') return 0;
00114   while (*string == '0')
00115     string++;
00116   return *string == '\0' || *string == '\n';
00117 }
00118 
00119 /* This function handles the entire file. */
00120 
00121 #define LINESIZE 1024
00122 
00123 int
00124 process_pfa(PSStream *in, struct font_writer *fw, PSStream *out)
00125 {
00126   /* Loop until no more input. We need to look for `currentfile eexec' to
00127      start eexec section (hex to binary conversion) and line of all zeros to
00128      switch back to ASCII. */
00129   
00130   /* Don't use fgets() in case line-endings are indicated by bare \r's, as
00131      occurs in Macintosh fonts. */
00132 
00133   /* 2.Aug.1999 - At the behest of Tom Kacvinsky <tjk@ams.org>, support binary
00134      PFA fonts. */
00135  
00136   char line[LINESIZE];
00137   int c = 0;
00138   int blocktyp = PFA_ASCII;
00139   
00140   while (c != EOF) {
00141     char *p = line;
00142     c = psGetC(in);
00143     while (c != EOF && c != '\r' && c != '\n' && p < line + LINESIZE - 1) {
00144       *p++ = c;
00145       c = psGetC(in);
00146     }
00147     
00148     /* handle the end of the line */
00149     if (p == line + LINESIZE - 1)
00150       /* buffer overrun: don't append newline even if we have it */
00151       psUngetC(c, in);
00152     else if (c == '\r' && blocktyp == PFA_ASCII) {
00153       /* change CR or CR/LF into LF */
00154       c = psGetC(in);
00155       if (c != '\n') psUngetC(c, in);
00156       *p++ = '\n';
00157     } else if (c != EOF)
00158       *p++ = c;
00159     
00160     *p = 0;
00161     
00162     /* check immediately after "currentfile eexec" for ASCII or binary */
00163     if (blocktyp == PFA_EEXEC_TEST) {
00164       char *last = p;
00165       for (p = line; *p && isspace(*p); p++) ;
00166       if (!*p)
00167         continue;
00168       else if (isxdigit(p[0]) && isxdigit(p[1])
00169                && isxdigit(p[2]) && isxdigit(p[3]))
00170         blocktyp = PFA_HEX;
00171       else
00172         blocktyp = PFA_BINARY;
00173       memmove(line, p, last - p);
00174       p = line + (last - p);
00175     }
00176     
00177     /* now that we have the line, handle it */
00178     if (blocktyp == PFA_ASCII) {
00179       fw->output_ascii(out, line);
00180       if (strncmp(line, "currentfile eexec", 17) == 0) {
00181         for (p = line + 17; isspace(*p); p++) ;
00182         if (!*p) blocktyp = PFA_EEXEC_TEST;
00183       }
00184       
00185     } else { /* blocktyp == PFA_HEX || blocktyp == PFA_BINARY */
00186       if (all_zeroes(line)) {   /* XXX not safe */
00187         fw->output_ascii(out, line);
00188         blocktyp = PFA_ASCII;
00189       } else if (blocktyp == PFA_HEX) {
00190         int len = translate_hex_string(line);
00191         if (len) fw->output_binary(out, (unsigned char *)line, len);
00192       } else
00193         fw->output_binary(out, (unsigned char *)line, p - line);
00194     }
00195   }
00196   
00197   fw->output_end(out);
00198   return 0;  /* a miracle, no errors can occur :) */
00199 }
00200 
00201 /* Process a PFB file. */
00202 
00203 /* XXX Doesn't handle "currentfile eexec" as intelligently as process_pfa
00204    does. */
00205 
00206 static int
00207 handle_pfb_ascii(PSStream* fio, struct font_writer *fw, char *line, int len)
00208 {
00209   /* Divide PFB_ASCII blocks into lines */
00210   int start = 0;
00211   
00212   while (1) {
00213     int pos = start;
00214     
00215     while (pos < len && line[pos] != '\n' && line[pos] != '\r')
00216       pos++;
00217     
00218     if (pos >= len) {
00219       if (pos == start)
00220         return 0;
00221       else if (start == 0 && pos == LINESIZE - 1) {
00222         line[pos] = 0;
00223         fw->output_ascii(fio, line);
00224         return 0;
00225       } else {
00226         memmove(line, line + start, pos - start);
00227         return pos - start;
00228       }
00229       
00230     } else if (pos < len - 1 && line[pos] == '\r' && line[pos+1] == '\n') {
00231       line[pos] = '\n'; line[pos+1] = 0;
00232       fw->output_ascii(fio, line + start);
00233       start = pos + 2;
00234       
00235     } else {
00236       char save = line[pos+1];
00237       line[pos] = '\n'; line[pos+1] = 0;
00238       fw->output_ascii(fio, line + start);
00239       line[pos+1] = save;
00240       start = pos + 1;
00241     }
00242   }
00243 }
00244 
00245 int
00246 process_pfb(PSStream *in, struct font_writer *fw, PSStream *out)
00247 {
00248   int blocktyp = 0;
00249   int block_len = 0;
00250   int c = 0;
00251   int filepos = 0;
00252   int linepos = 0;
00253   char line[LINESIZE];
00254   unsigned char buf[4];
00255   
00256   while (1) {
00257     while (block_len == 0) {
00258       c = psGetC(in);
00259       blocktyp = psGetC(in);
00260       if (c != PFB_MARKER
00261           || (blocktyp != PFB_ASCII && blocktyp != PFB_BINARY
00262               && blocktyp != PFB_DONE)) {
00263         if (c == EOF || blocktyp == EOF)
00264 /*        error("%s corrupted: no end-of-file marker", ifp_filename);*/
00265           pserrno = PSERR_NOEOFMARKER;
00266         else
00267 /*        error("%s corrupted: bad block marker at position %d",
00268                 ifp_filename, filepos);                */
00269           pserrno = PSERR_BADBLOCKMARKER;
00270         blocktyp = PFB_DONE;
00271       }
00272       if (blocktyp == PFB_DONE)
00273         goto done;
00274 
00275 #if 0      
00276       block_len = psGetC(ifp) & 0xFF;
00277       block_len |= (getc(ifp) & 0xFF) << 8;
00278       block_len |= (getc(ifp) & 0xFF) << 16;
00279       block_len |= (getc(ifp) & 0xFF) << 24;
00280       if (feof(ifp)) {
00281         error("%s corrupted: bad block length at position %d",
00282               ifp_filename, filepos);
00283         blocktyp = PFB_DONE;
00284         goto done;
00285       }
00286 #else
00287       if(psRead(buf, 1, 4, in) != 4)
00288       {
00289         pserrno = PSERR_BADBLOCKLEN;
00290         blocktyp = PFB_DONE;
00291         goto done;
00292       }
00293       block_len = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
00294 #endif
00295       filepos += 6;
00296     }
00297 
00298     /* read the block in its entirety, in LINESIZE chunks */
00299     while (block_len > 0) {
00300       int rest = LINESIZE - 1 - linepos; /* leave space for '\0' */
00301       int n = (block_len > rest ? rest : block_len);
00302       int actual = psRead(line + linepos, 1, n, in);
00303       if (actual != n) {
00304 /*      error("%s corrupted: block short by %d bytes at position %d",
00305               ifp_filename, block_len - actual, filepos);*/
00306         block_len = actual;
00307       }
00308       
00309       if (blocktyp == PFB_BINARY)
00310         fw->output_binary(out, (unsigned char *)line, actual);
00311       else
00312         linepos = handle_pfb_ascii(out, fw, line, linepos + actual);
00313       
00314       block_len -= actual;
00315       filepos += actual;
00316     }
00317     
00318     /* handle any leftover line */
00319     if (linepos > 0) {
00320       line[linepos] = 0;
00321       fw->output_ascii(out, line);
00322       linepos = 0;
00323     }
00324   }
00325   
00326 done:
00327   c = psGetC(in);
00328   if (c != EOF)
00329 /*    error("%s corrupted: data after PFB end marker at position %d",
00330           ifp_filename, filepos - 2); */
00331     pserrno = PSERR_DATACORRUPT;
00332     
00333   fw->output_end(out);
00334   
00335   return pserrno;
00336 }
00337 
00338 
00339 #define DEFAULT_BLOCKLEN (1L<<12)
00340 
00341 int
00342 init_pfb_writer(struct pfb_writer *w, int blocklen, PSStream *fio)
00343 {
00344   w->len = DEFAULT_BLOCKLEN;
00345   w->buf = (unsigned char *)malloc(w->len);
00346   if (!w->buf)
00347     return pserrno = PSERR_ERRNO;  
00348   w->max_len = (blocklen <= 0 ? 0xFFFFFFFFU : blocklen);
00349   w->pos = 0;
00350   w->blocktyp = PFB_ASCII;
00351   w->binary_blocks_written = 0;
00352   w->fio = fio;
00353   
00354   return 0;
00355 }
00356 
00357 void
00358 pfb_writer_output_block(struct pfb_writer *w)
00359 {
00360   /* do nothing if nothing in block */
00361   if (w->pos == 0)
00362     return;
00363   
00364   /* output four-byte block length */
00365   psPutC(PFB_MARKER, w->fio);
00366   psPutC(w->blocktyp, w->fio);
00367   psPutC((int)(w->pos & 0xff), w->fio);
00368   psPutC((int)((w->pos >> 8) & 0xff), w->fio);
00369   psPutC((int)((w->pos >> 16) & 0xff), w->fio);
00370   psPutC((int)((w->pos >> 24) & 0xff), w->fio);
00371   
00372   /* output block data */
00373   psWrite(w->buf, 1, w->pos, w->fio);
00374   
00375   /* mark block buffer empty and uninitialized */
00376   w->pos =  0;
00377   if (w->blocktyp == PFB_BINARY)
00378     w->binary_blocks_written++;
00379 }
00380 
00381 void
00382 pfb_writer_grow_buf(struct pfb_writer *w)
00383 {
00384   if (w->len < w->max_len) {
00385     /* grow w->buf */
00386     int new_len = w->len * 2;
00387     unsigned char *new_buf;
00388     if (new_len > w->max_len)
00389       new_len = w->max_len;
00390     new_buf = (unsigned char *)malloc(new_len);
00391     if (!new_buf) {
00392 /*      error("out of memory; continuing with a smaller block size");*/
00393       w->max_len = w->len;
00394       pfb_writer_output_block(w);
00395     } else {
00396       memcpy(new_buf, w->buf, w->len);
00397       free(w->buf);
00398       w->buf = new_buf;
00399       w->len = new_len;
00400     }
00401     
00402   } else
00403     /* buf already the right size, just output the block */
00404     pfb_writer_output_block(w);
00405 }
00406 
00407 void
00408 pfb_writer_end(struct pfb_writer *w)
00409 {
00410   if (w->pos)
00411     pfb_writer_output_block(w);
00412   psPutC(PFB_MARKER, w->fio);
00413   psPutC(PFB_DONE, w->fio);
00414 }
00415 
00416 
00417 
00418 /*
00419  * CRC computation logic
00420  * 
00421  * The logic for this method of calculating the CRC 16 bit polynomial is taken
00422  * from an article by David Schwaderer in the April 1985 issue of PC Tech
00423  * Journal.
00424  */
00425 
00426 static short crctab[] =         /* CRC lookup table */
00427 {
00428   0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
00429   0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
00430   0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
00431   0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
00432   0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
00433   0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
00434   0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
00435   0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
00436   0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
00437   0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
00438   0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
00439   0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
00440   0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
00441   0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
00442   0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
00443   0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
00444   0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
00445   0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
00446   0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
00447   0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
00448   0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
00449   0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
00450   0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
00451   0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
00452   0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
00453   0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
00454   0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
00455   0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
00456   0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
00457   0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
00458   0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
00459   0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
00460 };
00461 
00462 /*
00463  * Update a CRC check on the given buffer.
00464  */
00465 
00466 int
00467 crcbuf(int crc, unsigned int len, unsigned char *buf)
00468 {
00469   register unsigned int i;
00470   for (i=0; i<len; i++)
00471     crc = ((crc >> 8) & 0xff) ^ crctab[(crc ^ *buf++) & 0xff];
00472   return crc & 0xFFFF;
00473 }
00474 
00475 /* This CRC table and routine were borrowed from macutils-2.0b3 */
00476 
00477 static unsigned short hqx_crctab[256] = {
00478     0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
00479     0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
00480     0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
00481     0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
00482     0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
00483     0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
00484     0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
00485     0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
00486     0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
00487     0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
00488     0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
00489     0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
00490     0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
00491     0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
00492     0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
00493     0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
00494     0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
00495     0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
00496     0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
00497     0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
00498     0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
00499     0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
00500     0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
00501     0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
00502     0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
00503     0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
00504     0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
00505     0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
00506     0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
00507     0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
00508     0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
00509     0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
00510 };
00511 
00512 
00513 int
00514 hqx_crcbuf(int crc, unsigned int len, unsigned char *buf)
00515 {
00516   while (len--)
00517     crc = ((crc << 8) & 0xFF00) ^ hqx_crctab[((crc>>8)&0xff) ^ *buf++];
00518   return crc;
00519 }
00520 
00521 #ifdef __cplusplus
00522 }
00523 #endif

Generated at Mon Dec 11 22:46:28 2000 for Postscript Utility Library by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000