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

ttf42.c

Go to the documentation of this file.
00001 /*  $Id: ttf42.c,v 1.6 2000/12/06 18:42:30 dbryson Exp $ */
00002 
00008 #ifdef HAVE_CONFIG_H
00009 # include "psconfig.h"
00010 #endif
00011 
00012 #include <sys/types.h>
00013 #include <unistd.h>
00014 #include <malloc.h>
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include "ttf42_types.h"
00019 #include "ps/ps.h"
00020 #include "ttf42_proto.h"
00021 
00022 /*
00023 **  The following routines (and the header files ttf_proto.h and ttf_types.h
00024 **  come from the ttfps program written by Juliusz Chroboczek with the
00025 **  following license:
00026 **
00027 **  This software is provided with no guarantee, not even of any kind.
00028 **
00029 **  Feel free to do whatever you wish with it as long as you don't ask me
00030 **  to maintain it.
00031 **
00032 **
00033 **                                        J. Chroboczek
00034 **                                        <jec@dcs.ed.ac.uk>
00035 **
00036 **
00037 **  I have combined all the .c files from the original program into this 
00038 **  one file.  DTB.
00039 */
00040 
00041 /*
00042 **  encodings.c
00043 */
00044 
00045 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
00046 
00047 /*#define NULL ((void *)0)*/
00048 
00049 /* char *macEncoding[]={ */
00050 /*   ".notdef", NULL, NULL, NULL, NULL, NULL, */
00051 /*   NULL, NULL, NULL, NULL, NULL, NULL, */
00052 /*   NULL, NULL, NULL, NULL, NULL, NULL, */
00053 /*   NULL, NULL, NULL, NULL, NULL, NULL, */
00054 /*   NULL, NULL, NULL, NULL, NULL, NULL, */
00055 /*   NULL, NULL, "space", "exclam", "quotedbl", "numbersign", */
00056 /*   "dollar", "percent", "ampersand", "quoteright", "parenleft", */
00057 /*   "parenright", "asterisk", "plus", "comma", "hyphen", "period", */
00058 /*   "slash", "zero", "one", "two", "three", "four", "five", "six", */
00059 /*   "seven", "eight", "nine", "colon", "semicolon", "less", "equal", */
00060 /*   "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", */
00061 /*   "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", */
00062 /*   "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", */
00063 /*   "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", */
00064 /*   "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", */
00065 /*   "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", */
00066 /*   "tilde", NULL, "Adieresis", "Aring", "Ccedilla", "Eacute", */
00067 /*   "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", */
00068 /*   "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", */
00069 /*   "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", */
00070 /*   "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", */
00071 /*   "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", */
00072 /*   "degree", "cent", "sterling", "section", "bullet", "paragraph", */
00073 /*   "germandbls", "registered", "copyright", "trademark", "acute", */
00074 /*   "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", */
00075 /*   "lessequal", "greaterequal", "yen", "mu", "partialdiff", "Sigma", */
00076 /*   "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", */
00077 /*   "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", */
00078 /*   "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", */
00079 /*   "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", */
00080 /*   "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", */
00081 /*   "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", */
00082 /*   "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", */
00083 /*   "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", */
00084 /*   "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", */
00085 /*   "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", */
00086 /*   "Ocircumflex", NULL, "Ograve", "Uacute", "Ucircumflex", "Ugrave", */
00087 /*   "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", */
00088 /*   "ring", "cedilla", "hungarumlaut", "ogonek", "caron"}; */
00089 
00090 static char *macGlyphEncoding[]={
00091   ".notdef", ".null", "CR", "space", "exclam", "quotedbl", "numbersign",
00092   "dollar", "percent", "ampersand", "quotesingle", "parenleft",
00093   "parenright", "asterisk", "plus", "comma", "hyphen", "period",
00094   "slash", "zero", "one", "two", "three", "four", "five", "six",
00095   "seven", "eight", "nine", "colon", "semicolon", "less", "equal",
00096   "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H",
00097   "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
00098   "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
00099   "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f",
00100   "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
00101   "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright",
00102   "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde",
00103   "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex",
00104   "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave",
00105   "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex",
00106   "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
00107   "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger",
00108   "degree", "cent", "sterling", "section", "bullet", "paragraph",
00109   "germandbls", "registered", "copyright", "trademark", "acute",
00110   "dieresis", "notequal", "AE", "Oslash", "infinity", "plusinus",
00111   "lessequal", "greaterequal", "yen", "mu1", "partialdiff", "summation",
00112   "product", "pi", "integral", "ordfeminine", "ordmasculine", "Ohm",
00113   "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical",
00114   "florin", "approxequal", "increment", "guillemotleft",
00115   "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", "Otilde",
00116   "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright",
00117   "quoteleft", "quoteright", "divide", "lozenge", "ydieresis",
00118   "Ydieresis", "fraction", "currency", "guilsingleft", "guilsingright",
00119   "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase",
00120   "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute",
00121   "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave",
00122   "Oacute", "Ocircumflex", "applelogo", "Ograve", "Uacute",
00123   "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde",
00124   "overscore", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut",
00125   "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", "Zcaron",
00126   "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn",
00127   "thorn", "minus", "multiply", "onesuperior", "twosuperior",
00128   "threesuperior", "onehalf", "onequarter", "threequarters", "franc",
00129   "Gbreve", "gbreve", "Idot", "Scedilla", "scedilla", "Cacute",
00130   "cacute", "Ccaron", "ccaron", "dmacron"};
00131 
00132 static char *adobeStandardEncoding[]={
00133 ".notdef", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00134 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00135 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00136 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00137 "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
00138 "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
00139 "zero", "one", "two", "three", "four", "five", "six", "seven",
00140 "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
00141 "at", "A", "B", "C", "D", "E", "F", "G",
00142 "H", "I", "J", "K", "L", "M", "N", "O",
00143 "P", "Q", "R", "S", "T", "U", "V", "W",
00144 "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
00145 "quoteleft", "a", "b", "c", "d", "e", "f", "g",
00146 "h", "i", "j", "k", "l", "m", "n", "o",
00147 "p", "q", "r", "s", "t", "u", "v", "w",
00148 "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", NULL,
00149 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00150 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00151 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00152 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00153 NULL, "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section",
00154 "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl",
00155 NULL, "endash", "dagger", "daggerdbl", "periodcentered", NULL, "paragraph", "bullet",
00156 "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", NULL, "questiondown",
00157 NULL, "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
00158 "dieresis", NULL, "ring", "cedilla", NULL, "hungarumlaut", "ogonek", "caron",
00159 "emdash", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00160 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
00161 NULL, "AE", NULL, "ordfeminine", NULL, NULL, NULL, NULL,
00162 "Lslash", "Oslash", "OE", "ordmasculine", NULL, NULL, NULL, NULL,
00163 NULL, "ae", NULL, NULL, NULL, "dotlessi", NULL, NULL,
00164 "lslash", "oslash", "oe", "germandbls", NULL, NULL, NULL, NULL};
00165 
00166 /*
00167 **  util.c
00168 */
00169 
00170 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
00171 
00172 #if 0 /* removed for libps */
00173 static void 
00174 *mymalloc(size_t size)
00175 {
00176   void *p;
00177   if((p=malloc(size))==NULL)
00178     error("Unable to allocate memory\n");
00179   return p;
00180 }
00181 
00182 static void *
00183 mycalloc(size_t nelem, size_t elsize)
00184 {
00185   void *p;
00186   if((p=calloc(nelem, elsize))==NULL)
00187     error("Unable to allocate memory\n");
00188   return p;
00189 }
00190 
00191 static void *
00192 myrealloc(void *ptr, size_t size)
00193 {
00194   void *p;
00195   if((p=realloc(ptr, size))==NULL)
00196     error("Unable to allocate memory\n");
00197   return p;
00198 }
00199 
00200 static off_t
00201 surely_lseek(int fildes, off_t offset, int whence)
00202 {
00203   off_t result;
00204   if((result=lseek(fildes,offset,whence))<0)
00205     error("Bad TTF file");
00206   return result;
00207 }
00208 
00209 static void
00210 error(char *string)
00211 {
00212   fprintf(stderr,"%s\n",string);
00213   exit(3);
00214   /*NOTREACHED*/
00215 }
00216 
00217 static void
00218 syserror(char *string)
00219 {
00220   perror(string);
00221   exit(3);
00222   /*NOTREACHED*/
00223 }
00224 
00225 static ssize_t 
00226 surely_read(int fildes, void *buf, size_t nbyte)
00227 {
00228   ssize_t n;
00229   if((n=read(fildes,buf,nbyte))<nbyte)
00230     error("Bad TTF file");
00231   return n;
00232 }
00233 #endif 
00234 
00235 static char *
00236 unistrncpy(char *dst, char *str, size_t length)
00237 {
00238   int i,j;
00239 
00240   for(i=j=0; i<length; i+=2)
00241     if(str[i]==0)
00242       dst[j++]=str[i+1];
00243   dst[j]='\0';
00244   return dst;
00245 }
00246 
00247 static void
00248 fputpss(char *s, PSStream* fio)
00249 {
00250   while(*s) {
00251     if((*s&0200)==0 && *s>=040 && *s!='(' && *s!=')')
00252       psPutC(*s, fio);
00253     else
00254       psPrintf(fio, "\\%03o", (unsigned char)*s);
00255     s++;
00256   }
00257 }
00258 
00259 /* Hashtables */
00260 
00261 static unsigned 
00262 hash(char *string)
00263 {
00264   int i;
00265   unsigned u=0;
00266   for(i=0; string[i]!='\0'; i++)
00267     u=(u<<2)+string[i];
00268   return u;
00269 }
00270 
00271 static struct hashtable*
00272 make_hashtable(int size)
00273 {
00274   struct hashtable *t;
00275 
00276   t = malloc(sizeof(struct hashtable));
00277   if(t)
00278   {
00279     t->size = size;
00280     t->buckets = calloc(size, sizeof(struct hashtable_bucket*));
00281   }
00282   else
00283     pserrno = PSERR_ERRNO;
00284 
00285   return t;
00286 }
00287 
00288 static void
00289 free_hashtable(struct hashtable* ht)
00290 {
00291   int 
00292     i;
00293     
00294   if(ht)
00295   {
00296     for(i = 0; i < ht->size; i++)
00297       if(ht->buckets[i])
00298       {
00299         if(ht->buckets[i]->entries)
00300           free(ht->buckets[i]->entries);
00301         free(ht->buckets[i]);
00302       }
00303     free(ht->buckets);
00304     free(ht);
00305   }
00306 }
00307 
00308 static int 
00309 puthash(struct hashtable *t, char *key, int value)
00310 {
00311   int i;
00312 
00313   i=hash(key)%t->size;
00314 
00315   if(t->buckets[i] == 0) 
00316   {
00317     t->buckets[i] = malloc(sizeof(struct hashtable_bucket));
00318     t->buckets[i]->entries = malloc(4 * sizeof(struct hashtable_entry));
00319     t->buckets[i]->size = 4;
00320     t->buckets[i]->nentries = 0;
00321   }
00322 
00323   if(t->buckets[i]->nentries >= t->buckets[i]->size) 
00324   {
00325     t->buckets[i]->entries = realloc(t->buckets[i]->entries,
00326                                      t->buckets[i]->size * 2 *
00327                                      sizeof(struct hashtable_entry));
00328     t->buckets[i]->size *= 2;
00329   }
00330 
00331   t->buckets[i]->entries[t->buckets[i]->nentries].key = key;
00332   t->buckets[i]->entries[t->buckets[i]->nentries].value = value;
00333   t->buckets[i]->nentries++;
00334 
00335   return value;
00336 }
00337 
00338 static int
00339 gethash(struct hashtable *t, char *key)
00340 {
00341   int i, j;
00342 
00343   i=hash(key)%t->size;
00344   if(t->buckets[i])
00345     for(j=0; j<t->buckets[i]->nentries; j++)
00346       if(!strcmp(key, t->buckets[i]->entries[j].key))
00347         return t->buckets[i]->entries[j].value;
00348   return -1;
00349 }
00350 
00351 /*
00352 **  parse.c
00353 */
00354 
00355 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
00356 
00357 static struct TableDirectoryEntry *
00358 readDirectory(PSStream *fio, struct OffsetTable *ot)
00359 {
00360   unsigned 
00361     n;
00362     
00363   int 
00364     i;
00365   
00366   struct TableDirectoryEntry
00367     *td = NULL;
00368 
00369   if(psRead(ot, sizeof(struct OffsetTable), 1, fio) == 1)
00370   {
00371     FIX_OffsetTable(*ot);
00372 #if 0  
00373     if(verbosity>=2)
00374       fprintf(stderr,"%d tables\n",ot->numTables);
00375 #endif 
00376     n = sizeof(struct TableDirectoryEntry) * ot->numTables;
00377     td = malloc(n);
00378     if(td)
00379     {
00380       if(psRead(td, n, 1, fio) != 1)
00381       {
00382         free(td);
00383         td = NULL;
00384       }
00385       else
00386       {
00387         for(i = 0; i < ot->numTables; i++)
00388           FIX_TableDirectoryEntry(td[i]);
00389       }
00390     }
00391     else
00392       pserrno = PSERR_ERRNO;
00393   }
00394   
00395   return td;
00396 }
00397 
00398 static char **
00399 readNamingTable(PSStream* fio)
00400 {
00401   USHORT 
00402     format;
00403     
00404   USHORT 
00405     nrecords;
00406     
00407   off_t 
00408     position;
00409     
00410   USHORT 
00411     offset;
00412     
00413   int 
00414     i,
00415     index,maxIndex;
00416     
00417   struct NameRecord 
00418     *records;
00419     
00420   char 
00421     *data;
00422     
00423   char 
00424     **strings;
00425 
00426   position = psTell(fio);
00427 
00428   if(psRead(&format, sizeof(USHORT), 1, fio) != 1)
00429     return NULL;
00430   FIX_UH(format);
00431   
00432   if(format != 0)
00433   {
00434     pserrno = PSERR_BADTTFFILE;
00435     return NULL;
00436   }  
00437   
00438   if(psRead(&nrecords, sizeof(USHORT), 1, fio) != 1)
00439     return NULL;
00440   FIX_UH(nrecords);
00441   
00442   if(psRead(&offset, sizeof(USHORT), 1, fio) != 1)
00443     return NULL;
00444   FIX_UH(offset);
00445   
00446   records = malloc(nrecords * sizeof(struct NameRecord));
00447   if(!records)
00448   {
00449     pserrno = PSERR_ERRNO;
00450     return NULL;
00451   }
00452     
00453   if(psRead(records, sizeof(struct NameRecord), nrecords, fio) != nrecords)
00454   {
00455     free(records);
00456     return NULL;
00457   }
00458 
00459   for(i = 0, maxIndex = -1; i < nrecords; i++) 
00460   {
00461     FIX_NameRecord(records[i]);
00462     index = records[i].offset + records[i].length;
00463     maxIndex = maxIndex > index ? maxIndex : index;
00464   }
00465   
00466   data = malloc(maxIndex);
00467   if(!data)
00468   {
00469     free(records);
00470     pserrno = PSERR_ERRNO;
00471     return NULL;
00472   }
00473   
00474   psSeek(fio, position + offset, SEEK_SET);
00475   if(psRead(data, maxIndex, 1, fio) != 1)
00476   {
00477     free(records);
00478     free(data);
00479     return NULL;
00480   }
00481 
00482   strings = malloc(8 * sizeof(char*));
00483   if(!strings)
00484   {
00485     free(records);
00486     free(data);
00487     pserrno = PSERR_ERRNO;
00488     return NULL;
00489   }
00490   
00491   for(i = 0; i < 8; i++)
00492     strings[i] = NULL;
00493 
00494   for(i = 0; i < nrecords; i++) 
00495   {
00496     if(records[i].platformID==3 && /* Microsoft */
00497        records[i].encodingID==1 && /* UGL */
00498        records[i].languageID==0x0409 && /* US English */
00499        records[i].nameID<=7) 
00500     {
00501       strings[records[i].nameID] = malloc(records[i].length / 2 + 1);
00502       unistrncpy(strings[records[i].nameID],
00503                  data + records[i].offset,
00504                  records[i].length);
00505 #if 0                 
00506       if(verbosity>=2)
00507         fprintf(stderr,"%d: %s\n",records[i].nameID,
00508                 strings[records[i].nameID]);
00509 #endif                
00510     }
00511   }
00512   free(records);
00513   free(data);
00514   return strings;
00515 }
00516 
00517 static int 
00518 readMaxpTable(PSStream *fio)
00519 {
00520   struct {
00521     Fixed version;
00522     USHORT nglyphs;
00523   } data;
00524   
00525   if(psRead(&data, sizeof(data), 1, fio) != 1)
00526     return 0;
00527     
00528   FIX_Fixed(data.version);
00529   FIX_UH(data.nglyphs);
00530   
00531 #if 0
00532   if(verbosity>=2)
00533     fprintf(stderr,"  version %d.%u\n",
00534             data.version.mantissa,data.version.fraction);
00535 #endif
00536             
00537   return data.nglyphs;
00538 }
00539 
00540 static int
00541 readHeadTable(PSStream *fio, struct HeadTable *ht)
00542 {
00543   if(psRead(ht, sizeof(struct HeadTable), 1, fio) != 1)
00544     return 0;
00545     
00546   FIX_HeadTable(*ht);
00547   
00548 #if 0
00549   if(verbosity>=2) {
00550     fprintf(stderr,"  version %d.%d\n",
00551             ht->version.mantissa,ht->version.fraction);
00552     fprintf(stderr,"  font revision %d.%d\n",
00553             ht->fontRevision.mantissa, ht->fontRevision.fraction);
00554   }
00555 #endif  
00556   if(ht->magicNumber != 0x5F0F3CF5)
00557   {
00558     pserrno = PSERR_BADTTFMAGIC;
00559     return 0;
00560   }
00561 #if 0  
00562   if(verbosity>=2)
00563     fprintf(stderr,"  %d units per Em\n",ht->unitsPerEm);
00564 #endif
00565   return 1;
00566 }
00567             
00568 static int 
00569 readPostTable(PSStream *fio, int nglyphs, struct PostTable *pt, 
00570               struct GlyphName **gt)
00571 {
00572   USHORT nglyphspost;
00573   USHORT *glyphNameIndex;
00574   struct GlyphName *glyphNames;
00575   char **glyphNamesTemp;
00576   int i,maxIndex;
00577   CHAR c;
00578 
00579   if(psRead(pt, sizeof(struct PostTable), 1, fio) != 1)
00580     return -1;
00581   FIX_PostTable(*pt);
00582  
00583 #if 0 
00584   if(verbosity>=2)
00585     fprintf(stderr,"  format type %d.%u\n",
00586             pt->formatType.mantissa,pt->formatType.fraction);
00587 #endif            
00588 
00589   switch(pt->formatType.mantissa) 
00590   {
00591     case 1:
00592     return 1;                   /* MacGlyphEncoding */
00593     
00594     case 2:
00595       if(pt->formatType.fraction != 0)
00596       {
00597         pserrno = PSERR_UNKNOWNTTFPOSTFORMAT;
00598         return -1;
00599       }
00600       
00601       if(psRead(&nglyphspost, sizeof(USHORT), 1, fio) != 1)
00602         return -1;
00603       FIX_UH(nglyphspost);
00604       
00605       if(nglyphspost != nglyphs)
00606       {
00607         pserrno = PSERR_INVALIDNGLYPHS;
00608         return -1;
00609       }
00610 #if 0      
00611       if(verbosity>=2)
00612         fprintf(stderr,"  %d glyphs\n",nglyphs);
00613 #endif        
00614       glyphNameIndex = malloc(sizeof(USHORT) * nglyphs);
00615       if(!glyphNameIndex)
00616       {
00617         pserrno = PSERR_ERRNO;
00618         return -1;
00619       }
00620       
00621       if(psRead(glyphNameIndex, sizeof(USHORT), nglyphs, fio) != nglyphs)
00622       {
00623         free(glyphNameIndex);
00624         return -1;
00625       }
00626       glyphNames = calloc(nglyphs, sizeof(struct GlyphName));
00627       if(!glyphNames)
00628       {
00629         free(glyphNameIndex);
00630         return -1;
00631       }
00632       
00633       for(i = 0, maxIndex = -1; i < nglyphs; i++) 
00634       {
00635         FIX_UH(glyphNameIndex[i]);
00636         if(glyphNameIndex[i] < 258) 
00637         {
00638           glyphNames[i].type=0;
00639           glyphNames[i].name.index = glyphNameIndex[i];
00640         } 
00641         else 
00642         {
00643           int index;
00644           glyphNames[i].type = 1;
00645           index = glyphNameIndex[i] - 258;
00646           glyphNames[i].name.index = index;
00647           maxIndex = maxIndex > index ? maxIndex : index;
00648         }
00649       }
00650       free(glyphNameIndex);
00651     
00652       i = 0; 
00653       glyphNamesTemp = calloc(maxIndex + 1, sizeof(char *));
00654       if(!glyphNamesTemp)
00655       {
00656         free(glyphNames);
00657         return -1;
00658       }
00659       
00660       while( i <= maxIndex) 
00661       {
00662         if(psRead(&c, 1, 1, fio) != 1)
00663         {
00664           free(glyphNames);
00665           for(i = 0; i < maxIndex + 1; i++)
00666             if(glyphNamesTemp[i])
00667               free(glyphNamesTemp[i]);
00668           free(glyphNamesTemp);
00669           return -1;
00670         }
00671         glyphNamesTemp[i] = malloc(c + 1);
00672         if(!glyphNamesTemp[i])
00673         {
00674           free(glyphNames);
00675           for(i = 0; i < maxIndex + 1; i++)
00676             if(glyphNamesTemp[i])
00677               free(glyphNamesTemp[i]);
00678           free(glyphNamesTemp);
00679           return -1;
00680         }
00681         if(psRead(glyphNamesTemp[i], c, 1, fio) != 1)
00682         {
00683           free(glyphNames);
00684           for(i = 0; i < maxIndex + 1; i++)
00685             if(glyphNamesTemp[i])
00686               free(glyphNamesTemp[i]);
00687           free(glyphNamesTemp);
00688           return -1;
00689         }          
00690         glyphNamesTemp[i][c] = '\0';
00691 #if 0        
00692         if(verbosity>=3)
00693           fprintf(stderr,"    %d: %s\n",i,glyphNamesTemp[i]);
00694 #endif
00695         i++;
00696       }
00697       
00698       for(i = 0; i < nglyphs; i++)
00699         if(glyphNames[i].type == 1)
00700           glyphNames[i].name.name = strdup(glyphNamesTemp[glyphNames[i].name.index]);
00701           
00702       for(i = 0; i < maxIndex + 1; i++)
00703         if(glyphNamesTemp[i])
00704           free(glyphNamesTemp[i]);
00705           
00706       free(glyphNamesTemp);
00707       *gt = glyphNames;
00708     return 2;
00709     
00710     case 3:
00711     return 3;                   /* no name table */
00712     
00713     default:
00714     return 0;
00715   }
00716   /*NOTREACHED*/
00717 }
00718 
00719 static void *
00720 readLocaTable(PSStream* fio, int nglyphs, int format)
00721 {
00722   int i;
00723   
00724   switch(format) 
00725   {
00726     case 0:
00727     { 
00728       USHORT 
00729         *offsets;
00730       
00731       offsets = malloc((nglyphs + 1) * sizeof(USHORT));
00732       if(!offsets)
00733       {
00734         pserrno = PSERR_ERRNO;
00735         return NULL;
00736       }
00737         
00738       if(psRead(offsets, sizeof(USHORT), nglyphs + 1, fio) != nglyphs + 1)
00739       {
00740         free(offsets);
00741         return NULL;
00742       }
00743       for(i = 0; i <= nglyphs; i++)
00744         FIX_UH(offsets[i]);
00745         
00746       return offsets;
00747     }
00748     /*NOTREACHED*/
00749     
00750     case 1:
00751     {
00752       ULONG 
00753         *offsets;
00754         
00755       offsets = malloc((nglyphs + 1) * sizeof(ULONG));
00756       if(!offsets)
00757       {
00758         pserrno = PSERR_ERRNO;
00759         return NULL;
00760       }
00761         
00762       if(psRead(offsets, sizeof(ULONG), nglyphs + 1, fio) != nglyphs + 1)
00763       {
00764         free(offsets);
00765         return NULL;
00766       }
00767       
00768       for(i = 0; i <= nglyphs; i++)
00769         FIX_UL(offsets[i]);
00770         
00771       return offsets;
00772     }
00773     /*NOTREACHED*/
00774     
00775     default:
00776       pserrno = PSERR_UNKNOWNLOCAFORMAT;
00777     return NULL;
00778     /*NOTREACHED*/
00779   }
00780   /*NOTREACHED*/
00781 }
00782 
00783 static struct Box *
00784 readGlyfTable(PSStream* fio, int nglyphs, int format, void *loca)
00785 {
00786   int 
00787     i;
00788     
00789   struct Box 
00790     *bbox;
00791     
00792   off_t 
00793     base,
00794     offset;
00795 
00796   base = psTell(fio);
00797 
00798   bbox = malloc(nglyphs * sizeof(struct Box));
00799   if(!bbox)
00800   {
00801     pserrno = PSERR_ERRNO;
00802     return NULL;
00803   }
00804     
00805   for(i = 0; i < nglyphs; i++) 
00806   {
00807     if(format == 0)
00808       offset = 2 * ((USHORT*)loca)[i];
00809     else
00810       offset = ((ULONG*)loca)[i];
00811       
00812     psSeek(fio, base + offset + sizeof(SHORT), SEEK_SET);
00813     if(psRead(bbox + i, sizeof(struct Box), 1, fio) != 1)
00814     {
00815       free(bbox);
00816       return NULL;
00817     }
00818     FIX_Box(bbox[i]);
00819   }
00820   
00821   return bbox;
00822 }
00823 
00824 static longHorMetric *
00825 readHmtxTable(PSStream* fio, int nummetrics)
00826 {
00827   longHorMetric 
00828     *metrics;
00829     
00830   int 
00831     i;
00832 
00833   metrics = malloc(nummetrics * sizeof(longHorMetric));
00834   if(!metrics)
00835   {
00836     pserrno = PSERR_ERRNO;
00837     return NULL;
00838   }
00839   
00840   if(psRead(metrics, nummetrics * sizeof(longHorMetric), 1, fio) != 1)
00841   {
00842     free(metrics);
00843     return NULL;
00844   }
00845   
00846   for(i = 0; i < nummetrics; i++) 
00847   {
00848     FIX_longHorMetric(metrics[i]);
00849   }
00850   
00851   return metrics;
00852 }
00853 
00854 static struct HheaTable *
00855 readHheaTable(PSStream* fio)
00856 {
00857   struct HheaTable 
00858     *hhea;
00859     
00860   hhea = malloc(sizeof(struct HheaTable));
00861   if(!hhea)
00862   {
00863     pserrno = PSERR_ERRNO;
00864     return NULL;
00865   }
00866     
00867   if(psRead(hhea, sizeof(struct HheaTable), 1, fio) != 1)
00868   {
00869     free(hhea);
00870     return NULL;
00871   }
00872   FIX_HheaTable(*hhea);
00873   
00874 #if 0  
00875   if(verbosity>=2)
00876     fprintf(stderr,"  version %d.%u\n",
00877             hhea->version.mantissa,hhea->version.fraction);
00878 #endif            
00879 
00880   if(hhea->metricDataFormat != 0)
00881   {
00882     free(hhea);
00883     return NULL;
00884   }
00885   
00886   return hhea;
00887 }
00888 
00889 static int
00890 readKernTable(PSStream* fio, int **nkep, struct KernEntry0 ***kep)
00891 {
00892   struct KernTable 
00893     kt;
00894     
00895   struct KernSubTableHeader 
00896     ksth;
00897     
00898   struct KernSubTable0 
00899     kst;
00900     
00901   int 
00902     i, 
00903     j;
00904     
00905   int 
00906     *nke;
00907     
00908   struct KernEntry0 
00909     **ke;
00910 
00911   if(psRead(&kt, sizeof(struct KernTable), 1, fio) != 1)
00912     return 0;
00913   FIX_KernTable(kt);
00914   
00915 #if 0  
00916   if(verbosity>=2) {
00917     fprintf(stderr,"  version %d\n",
00918            kt.version);
00919     fprintf(stderr,"  %d subtables\n",
00920             kt.nTables);
00921   }
00922 #endif
00923 
00924   nke = malloc(kt.nTables * sizeof(int));
00925   if(!nke)
00926   {
00927     pserrno = PSERR_ERRNO;
00928     return 0;
00929   }
00930   
00931   ke = calloc(kt.nTables, sizeof(struct KernEntry0 *));
00932   if(!ke)
00933   {
00934     pserrno = PSERR_ERRNO;
00935     free(nke);
00936     return 0;
00937   }
00938 
00939   for(i = 0; i < kt.nTables; i++) 
00940   {
00941     if(psRead(&ksth, sizeof(struct KernSubTableHeader), 1, fio) != 1)
00942     {
00943       for(i = 0; i < kt.nTables; i++)
00944         if(ke[i])
00945           free(ke[i]);
00946           
00947       free(ke);
00948       free(nke);
00949       return 0;
00950     }
00951     FIX_KernSubTableHeader(ksth);
00952 
00953 #if 0    
00954     if(verbosity>=2)
00955       fprintf(stderr,"  analyzing subtable %d, version %d... ",
00956               i,
00957               ksth.version);
00958 #endif
00959               
00960     if((ksth.coverage&kernHorizontal) &&
00961        !(ksth.coverage&kernMinimum) &&
00962        !(ksth.coverage&kernCrossStream) &&
00963        (kernFormat(ksth.coverage) == 0)) 
00964     {
00965       if(psRead(&kst, sizeof(struct KernSubTable0), 1, fio) != 1)
00966       {
00967         for(i = 0; i < kt.nTables; i++)
00968           if(ke[i])
00969             free(ke[i]);
00970         free(ke);
00971         free(nke);
00972         return 0;
00973       }
00974       FIX_KernSubTable0(kst);
00975 
00976 #if 0      
00977       if(verbosity>=2)
00978         fprintf(stderr,"reading %d entries.\n",kst.nPairs);
00979 #endif
00980         
00981       nke[i] = kst.nPairs;
00982       ke[i] = malloc(kst.nPairs * sizeof(struct KernEntry0));
00983       if(!ke[i])
00984       {
00985         for(i = 0; i < kt.nTables; i++)
00986           if(ke[i])
00987             free(ke[i]);
00988         free(ke);
00989         free(nke);
00990         return 0;
00991       }
00992       if(psRead(ke[i], kst.nPairs * sizeof(struct KernEntry0), 1, fio) != 1)
00993       {
00994         for(i = 0; i < kt.nTables; i++)
00995           if(ke[i])
00996             free(ke[i]);
00997         free(ke);
00998         free(nke);
00999         return 0;
01000       }
01001       for(j = 0; j < kst.nPairs; j++)
01002         FIX_KernEntry0(ke[i][j]);
01003     } 
01004     else 
01005     {
01006 #if 0    
01007       if(verbosity>=2)
01008         fprintf(stderr,"skipping.\n");
01009 #endif        
01010       psSeek(fio, ksth.length - sizeof(struct KernSubTableHeader), SEEK_CUR);
01011     }
01012   }
01013   
01014   *nkep = nke;
01015   *kep = ke;
01016   return kt.nTables;
01017 }
01018       
01019 /*
01020 **  ps.c
01021 */
01022 
01023 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
01024 
01025 #define CHUNKSIZE 65534
01026 
01027 #define NAMEOF(i) \
01028         ((i)==0?\
01029          ".notdef":\
01030          ((postType==2)?\
01031           ((gnt[i].type==0)?\
01032            (gnt[i].name.index==0?NULL:macGlyphEncoding[gnt[i].name.index]):\
01033            gnt[i].name.name):\
01034           ((i)<258?macGlyphEncoding[i]:NULL)))
01035      
01036 
01037 static void 
01038 printPSFont(PSStream* out, struct HeadTable *ht,
01039             char **strings, int nglyphs, int postType,
01040             struct PostTable *pt, struct GlyphName *gnt,
01041             PSStream* in)
01042 {
01043   printPSHeader(out, ht, strings, pt);
01044   printPSData(out, in);
01045   printPSTrailer(out, nglyphs, postType, gnt);
01046 }
01047 
01048 static void 
01049 printPSHeader(PSStream* out, struct HeadTable *ht,
01050               char **strings, struct PostTable *pt)
01051 {
01052   psPrintf(out, "%%!PS-TrueTypeFont\n");
01053   if(pt->maxMemType42)
01054     psPrintf(out, "%%%%VMUsage: %ld %ld\n", pt->minMemType42, pt->maxMemType42);
01055   psPrintf(out, "%d dict begin\n", 11);
01056   psPrintf(out, "/FontName /%s def\n", strings[6] ? strings[6] : "Unknown");
01057   psPrintf(out, "/Encoding StandardEncoding def\n");
01058   psPrintf(out, "/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n");
01059   psPrintf(out, "/FontBBox [%ld %ld %ld %ld] def\n",
01060           ht->xMin*1000L/ht->unitsPerEm,
01061           ht->yMin*1000L/ht->unitsPerEm,
01062           ht->xMax*1000L/ht->unitsPerEm,
01063           ht->yMax*1000L/ht->unitsPerEm);
01064   psPrintf(out, "/FontType 42 def\n");
01065   psPrintf(out, "/FontInfo 8 dict dup begin\n");
01066   psPrintf(out, "/version (%d.%d) def\n",
01067           ht->fontRevision.mantissa,
01068           ht->fontRevision.fraction);
01069   if(strings[0]) {
01070     psPrintf(out, "/Notice (");
01071     fputpss(strings[0], out);
01072     psPrintf(out, ") def\n");
01073   }
01074   if(strings[4]) {
01075     psPrintf(out, "/FullName (");
01076     fputpss(strings[4], out);
01077     psPrintf(out, ") def\n");
01078   }
01079   if(strings[1]) {
01080     psPrintf(out, "/FamilyName (");
01081     fputpss(strings[1], out);
01082     psPrintf(out, ") def\n");
01083   }
01084   psPrintf(out, "/isFixedPitch %s def\n", pt->isFixedPitch ? "true" : "false");
01085   psPrintf(out, "/UnderlinePosition %ld def\n",
01086            pt->underlinePosition*1000L/ht->unitsPerEm);
01087   psPrintf(out,"/UnderlineThickness %ld def\n",
01088            pt->underlineThickness*1000L/ht->unitsPerEm);
01089   psPrintf(out, "end readonly def\n");
01090 }
01091 
01092 static int
01093 printPSData(PSStream* out, PSStream* in)
01094 {
01095   static char 
01096     xdigits[]="0123456789ABCDEF";
01097 
01098   unsigned char 
01099     *buffer;
01100     
01101   int 
01102     i,
01103     j;
01104 
01105   psSeek(in, 0, SEEK_SET);
01106 
01107   buffer = malloc(CHUNKSIZE);
01108   if(!buffer)
01109   {
01110     pserrno = PSERR_ERRNO;
01111     return 0;
01112   }
01113 
01114   psPrintf(out, "/sfnts [");
01115   for(;;)
01116   {
01117     i = psRead(buffer, 1, CHUNKSIZE, in);
01118     if(i == 0)
01119       break;
01120     psPrintf(out, "\n<");
01121     for(j = 0; j < i; j++) {
01122       if(j != 0 && j % 36 == 0)
01123         psPutC('\n', out);
01124       /* fprintf(out,"%02X",(int)buffer[j]) is too slow */
01125       psPutC(xdigits[(buffer[j]&0xF0)>>4], out);
01126       psPutC(xdigits[buffer[j]&0x0F], out);
01127     }
01128     psPrintf(out, "00>");         /* Adobe bug? */
01129     if(i < CHUNKSIZE)
01130       break;
01131   }
01132   psPrintf(out, "\n] def\n");
01133   free(buffer);
01134   
01135   return 1;
01136 }
01137 
01138 static void
01139 printPSTrailer(PSStream* out, int nglyphs, int postType, 
01140                struct GlyphName *gnt)
01141 {
01142   int 
01143     i,
01144     n;
01145     
01146   char 
01147     *name;
01148 
01149   psPrintf(out, "/CharStrings %d dict dup begin\n", nglyphs);
01150   switch(postType) 
01151   {
01152     case 2:
01153       for(n = i = 0; i < nglyphs; i++) 
01154       {
01155         if(n != 0 && n % 4 == 0)
01156           psPrintf(out, "\n");
01157         name = NAMEOF(i);
01158         if(name) 
01159         {
01160           psPrintf(out, "/%s %d def ", name, i);
01161           n++;
01162         }
01163       }
01164     break;
01165     
01166     default:
01167       if(postType != 1) 
01168       {
01169 #if 0      
01170         if(verbosity > -2)
01171           fprintf(stderr,"No glyph name table; assuming MacGlyphEncoding\n");
01172 #endif          
01173       }
01174       for(i = 0; i < 258 && i < nglyphs; i++) 
01175       {
01176         psPrintf(out, "/%s %d def ", macGlyphEncoding[i], i);
01177         if(i != 0 && i % 4 == 0)
01178           psPrintf(out, "\n");
01179       }
01180     break;
01181   }
01182   psPrintf(out, "end readonly def\n");
01183   psPrintf(out, "FontName currentdict end definefont pop\n");
01184 }
01185 
01186 static void 
01187 printAFM(PSStream* afm, struct HeadTable *ht,
01188          char **strings, int nglyphs, int postType,
01189          struct PostTable *pt, struct GlyphName *gnt,
01190          struct Box *bbox, struct HheaTable *hhea, longHorMetric *hmtx,
01191          int nkern, int *nke, struct KernEntry0 **ke)
01192 {
01193   psPrintf(afm, "StartFontMetrics 3.0\n");
01194   psPrintf(afm, "Comment Automatically generated by libps -- do not edit\n");
01195   printAFMHeader(afm, ht, strings, pt);
01196   printAFMMetrics(afm, ht, nglyphs, postType, gnt,
01197                   bbox, hhea, hmtx);
01198   printAFMKerning(afm, ht, postType, gnt, nkern, nke, ke);
01199   psPrintf(afm, "EndFontMetrics\n");
01200 }
01201 
01202 static void 
01203 printAFMHeader(PSStream* afm, struct HeadTable *ht,
01204                char **strings, struct PostTable *pt)
01205 {
01206   psPrintf(afm, "FontName %s\n", strings[6] ? strings[6] : "Unknown");
01207   if(strings[4])
01208     psPrintf(afm, "FullName %s\n", strings[4]);
01209   if(strings[1])
01210     psPrintf(afm, "FamilyName %s\n", strings[1]);
01211   psPrintf(afm, "IsFixedPitch %s\n", pt->isFixedPitch ? "true" : "false");
01212   psPrintf(afm, "FontBBox %ld %ld %ld %ld\n",
01213           ht->xMin*1000L/ht->unitsPerEm, ht->yMin*1000L/ht->unitsPerEm,
01214           ht->xMax*1000L/ht->unitsPerEm, ht->yMax*1000L/ht->unitsPerEm);
01215   psPrintf(afm, "UnderlinePosition %ld\n",
01216           pt->underlinePosition*1000L/ht->unitsPerEm);
01217   psPrintf(afm, "UnderlineThickness %ld\n",
01218           pt->underlineThickness*1000L/ht->unitsPerEm);
01219   psPrintf(afm, "Version %d.%u\n",
01220           ht->fontRevision.mantissa,
01221           ht->fontRevision.fraction);
01222   if(strings[0])
01223     psPrintf(afm, "Notice %s\n", strings[0]);
01224   psPrintf(afm, "EncodingScheme AdobeStandardEncoding\n");
01225   /*  fprintf(afm,"CapHeight %d\n");
01226       fprintf(afm,"XHeight %d\n");
01227       fprintf(afm,"Ascender %d\n");
01228       fprintf(afm,"Descender %d\n");  */
01229 }
01230 
01231 static int
01232 printAFMMetrics(PSStream* afm, struct HeadTable *ht,
01233                 int nglyphs,int postType, struct GlyphName *gnt,
01234                 struct Box *bbox, 
01235                 struct HheaTable *hhea, longHorMetric *hmtx)
01236 {
01237   int 
01238     i, 
01239     j;
01240     
01241   char 
01242     *name;
01243   
01244   struct hashtable 
01245     *table = NULL;
01246     
01247   char 
01248     *already_done;
01249 
01250   /* Hash all the character names */
01251   table = make_hashtable(nglyphs / 3 + 1);
01252   for(i = 0; i < nglyphs; i++) 
01253   {
01254     name = NAMEOF(i);
01255     if(name)
01256       puthash(table, name, i);
01257   }
01258 
01259   already_done = calloc(nglyphs, sizeof(char));
01260   if(!already_done)
01261   {
01262     free_hashtable(table);
01263     return 0;
01264   }
01265 
01266   psPrintf(afm, "StartCharMetrics %d\n", nglyphs);
01267   /* First, print out the encoded glyphs */
01268   for(i = 0; i < 256; i++) {
01269     if(adobeStandardEncoding[i]) 
01270     {
01271       j = gethash(table, adobeStandardEncoding[i]);
01272       if(j >= 0) 
01273       {
01274         printOneAFMMetric(afm, j, i, adobeStandardEncoding[i], 
01275                           ht, bbox, hhea, hmtx);
01276         already_done[j] = 1;
01277       }
01278     }
01279   }
01280   
01281   /* Now, print out the others */
01282   for(j = 0; j < nglyphs; j++) {
01283     if(!already_done[j]) 
01284     {
01285       name = NAMEOF(j);
01286       printOneAFMMetric(afm, j, -1, name, ht, bbox, hhea, hmtx);
01287     }
01288   }
01289   psPrintf(afm, "EndCharMetrics\n");
01290   free(already_done);
01291   free_hashtable(table);
01292   
01293   return 1;
01294 }
01295 
01296 static void
01297 printOneAFMMetric(PSStream* afm, 
01298                   int index, int code, char *name,
01299                   struct HeadTable *ht,
01300                   struct Box *bbox, 
01301                   struct HheaTable *hhea, longHorMetric *hmtx)
01302 {
01303   if(name) 
01304   {
01305     psPrintf(afm, "C %d ;", code);
01306     if(hhea && hmtx)
01307       psPrintf(afm, " WX %ld ;",
01308               index < hhea->numberOfHMetrics ?
01309               hmtx[index].advanceWidth * 1000L / ht->unitsPerEm :
01310               hmtx[hhea->numberOfHMetrics - 1].advanceWidth * 1000L / ht->unitsPerEm);
01311     psPrintf(afm, " N %s ;", name);
01312     if(bbox)
01313       psPrintf(afm, " B %ld %ld %ld %ld ;",
01314                bbox[index].xMin * 1000L / ht->unitsPerEm, 
01315                bbox[index].yMin * 1000L / ht->unitsPerEm,
01316                bbox[index].xMax * 1000L / ht->unitsPerEm,
01317                bbox[index].yMax * 1000L / ht->unitsPerEm);
01318     psPrintf(afm, "\n");
01319   }
01320 }
01321 
01322 static void
01323 printAFMKerning(PSStream* afm, struct HeadTable *ht,
01324                 int postType, struct GlyphName *gnt,
01325                 int nkern, int *nke, struct KernEntry0 **ke)
01326 {
01327   int 
01328     i,
01329     j,
01330     n;
01331 
01332   for(n = i = 0; i < nkern; i++)
01333     n += nke[i];
01334   if(n == 0)
01335     return;
01336   
01337   psPrintf(afm, "StartKernData\nStartKernPairs %d\n", n);
01338   
01339   for(i = 0; i < nkern; i++)
01340     for(j = 0; j < nke[i]; j++)
01341       psPrintf(afm, "KPX %s %s %ld\n",
01342               NAMEOF(ke[i][j].left),
01343               NAMEOF(ke[i][j].right),
01344               ke[i][j].value * 1000L / ht->unitsPerEm);
01345   psPrintf(afm, "EndKernPairs\nEndKernData\n");
01346 }
01347 
01348 /*
01349 **  ttfps.c
01350 */
01351 
01352 /* Copyright (c) 1997-1998 by Juliusz Chroboczek */
01353 
01354 #if 0
01355 static void endianness_test(void);
01356 static void usage(char*);
01357 #endif
01358 
01371 int 
01372 psTTFToT42PFA(PSStream* ttf, PSStream* pfa, PSStream* afm)
01373 {
01374   int 
01375     i;
01376     
01377   struct OffsetTable 
01378     ot;
01379     
01380   struct HeadTable 
01381     *ht = NULL;
01382     
01383   struct PostTable 
01384     *pt = NULL;
01385     
01386   struct TableDirectoryEntry 
01387     *td = NULL;
01388     
01389   void 
01390     *loca = NULL;
01391     
01392   struct HheaTable 
01393     *hhea = NULL;
01394     
01395   struct Box 
01396     *bbox = NULL;
01397     
01398   longHorMetric 
01399     *hmtx = NULL;
01400     
01401   char 
01402     **strings = NULL;
01403     
01404   struct GlyphName 
01405     *gnt = NULL;
01406     
01407   struct KernEntry0 
01408     **ke = NULL;
01409     
01410   int 
01411     *nke = NULL;
01412     
01413   int 
01414     nglyphs,
01415     postType,
01416     nkern;
01417     
01418   off_t 
01419     headOff=0, 
01420     maxpOff=0, 
01421     postOff=0, 
01422     nameOff=0, 
01423     locaOff=0, 
01424     glyfOff=0, 
01425     hheaOff=0, 
01426     hmtxOff=0, 
01427     kernOff=0;
01428 
01429   int 
01430     c;
01431     
01432   pserrno = PSERR_INVALIDTTFFILE;
01433 
01434   td = readDirectory(ttf, &ot);
01435   if(!td)
01436     return pserrno;
01437 #if 0  
01438   if(verbosity>=2)
01439     fprintf(stderr,"True type version %d.%u\n",
01440             ot.version.mantissa,ot.version.fraction);
01441 #endif            
01442 
01443   for(i = 0; i < ot.numTables; i++) 
01444   {
01445 #if 0  
01446     if(verbosity>=2)
01447       fprintf(stderr,"Found `%c%c%c%c' table\n",
01448               (char)(td[i].tag>>24),
01449               (char)(td[i].tag>>16)&255,
01450               (char)(td[i].tag>>8)&255,
01451               (char)td[i].tag&255);
01452 #endif              
01453     switch(td[i].tag) 
01454     {
01455       case MAKE_ULONG('m','a','x','p'):
01456         maxpOff = td[i].offset;
01457       break;
01458       
01459       case MAKE_ULONG('h','e','a','d'):
01460         headOff = td[i].offset;
01461       break;
01462       
01463       case MAKE_ULONG('p','o','s','t'):
01464         postOff = td[i].offset;
01465       break;
01466       
01467       case MAKE_ULONG('n','a','m','e'):
01468         nameOff = td[i].offset;
01469       break;
01470       
01471       case MAKE_ULONG('l','o','c','a'):
01472         locaOff = td[i].offset;
01473       break;
01474       
01475       case MAKE_ULONG('g','l','y','f'):
01476         glyfOff = td[i].offset;
01477       break;
01478       
01479       case MAKE_ULONG('h','h','e','a'):
01480         hheaOff = td[i].offset;
01481       break;
01482       
01483       case MAKE_ULONG('h','m','t','x'):
01484         hmtxOff = td[i].offset;
01485       break;
01486       
01487       case MAKE_ULONG('k','e','r','n'):
01488         kernOff = td[i].offset;
01489       break;
01490     }
01491   }
01492   if(maxpOff == 0 || headOff == 0 || postOff == 0 || nameOff == 0)
01493     goto Outtahere;
01494 
01495 #if 0
01496   if(verbosity>=1)
01497     fprintf(stderr,"Processing `maxp' table\n");
01498 #endif    
01499   if(psSeek(ttf, maxpOff, SEEK_SET))
01500     goto Outtahere;
01501   nglyphs = readMaxpTable(ttf);
01502 //printf("nglyphs = %d\n", nglyphs);
01503   if(!nglyphs)
01504     goto Outtahere;
01505 #if 0
01506   if(verbosity >= 1)
01507     fprintf(stderr,"  %d glyphs\n",nglyphs);
01508 
01509   if(verbosity>=1)
01510     fprintf(stderr,"Processing `head' table\n");
01511 #endif
01512   if(psSeek(ttf, headOff, SEEK_SET))
01513     goto Outtahere;
01514   ht = malloc(sizeof(struct HeadTable));
01515   if(!ht)
01516   {
01517     pserrno = PSERR_ERRNO;
01518     goto Outtahere;
01519   }
01520   if(!readHeadTable(ttf, ht))
01521     goto Outtahere;
01522 
01523 #if 0
01524   if(verbosity>=1)
01525     fprintf(stderr,"Processing `post' table\n");
01526 #endif    
01527   if(psSeek(ttf, postOff, SEEK_SET))
01528     goto Outtahere;
01529   pt = malloc(sizeof(struct PostTable));
01530   if(!pt)
01531   {
01532     pserrno = PSERR_ERRNO;
01533     goto Outtahere;
01534   }
01535   postType = readPostTable(ttf, nglyphs, pt, &gnt);
01536   if(postType == -1)
01537     goto Outtahere;
01538   
01539 #if 0  
01540   if(verbosity>=1)
01541     fprintf(stderr,"Processing `name' table\n");
01542 #endif
01543   if(psSeek(ttf, nameOff, SEEK_SET))
01544     goto Outtahere;
01545   strings = readNamingTable(ttf);
01546   if(!strings)
01547   {
01548     pserrno = PSERR_ERRNO;
01549     goto Outtahere;
01550   }
01551 
01552   if(afm) 
01553   {
01554     if(locaOff) 
01555     {
01556 #if 0    
01557       if(verbosity>=1)
01558         fprintf(stderr,"Processing `loca' table\n");
01559 #endif        
01560       if(psSeek(ttf, locaOff, SEEK_SET))
01561         goto Outtahere;
01562       loca = readLocaTable(ttf, nglyphs, ht->indexToLocFormat);
01563       if(!loca)
01564         goto Outtahere;
01565         
01566       if(glyfOff) 
01567       {
01568 #if 0      
01569         if(verbosity>=1)
01570           fprintf(stderr,"Processing `glyf' table\n");
01571 #endif          
01572         if(psSeek(ttf, glyfOff, SEEK_SET))
01573           goto Outtahere;
01574         bbox = readGlyfTable(ttf, nglyphs, ht->indexToLocFormat, loca);
01575         if(!bbox)
01576           goto Outtahere;
01577       }
01578       
01579       if(hheaOff) 
01580       {
01581 #if 0      
01582         if(verbosity>=1)
01583           fprintf(stderr,"Processing `hhea' table\n");
01584 #endif
01585         if(psSeek(ttf, hheaOff, SEEK_SET))
01586           goto Outtahere;
01587         hhea = readHheaTable(ttf);
01588         if(!hhea)
01589           goto Outtahere;
01590           
01591         if(hmtxOff) 
01592         {
01593 #if 0        
01594           if(verbosity>=1)
01595             fprintf(stderr,"Processing `hmtx' table\n");
01596 #endif            
01597           if(psSeek(ttf, hmtxOff, SEEK_SET))
01598             goto Outtahere;
01599           hmtx = readHmtxTable(ttf, hhea->numberOfHMetrics);
01600           if(!hmtx)
01601             goto Outtahere;
01602         }
01603       }
01604     }
01605     
01606     if(kernOff) 
01607     {
01608 #if 0    
01609       if(verbosity>=1)
01610         fprintf(stderr,"Processing `kern' table\n");
01611 #endif        
01612       if(psSeek(ttf, kernOff, SEEK_SET))
01613         goto Outtahere;
01614       nkern = readKernTable(ttf, &nke, &ke);
01615     } 
01616     else
01617       nkern = 0;
01618   }
01619 
01620   if(pfa)
01621   {
01622 #if 0  
01623     if(verbosity>=1)
01624       fprintf(stderr,"Generating PS file\n");
01625 #endif    
01626     printPSFont(pfa, ht, strings, nglyphs, postType, pt, gnt, ttf);
01627   }
01628 
01629   if(afm) 
01630   {
01631 #if 0  
01632     if(verbosity>=1)
01633       fprintf(stderr,"Generating AFM file\n");
01634 #endif      
01635     printAFM(afm, ht, strings, nglyphs, postType, pt, gnt,
01636              bbox, hhea, hmtx, nkern, nke, ke);
01637   }
01638 #if 0  
01639   if(verbosity>=1)
01640     fprintf(stderr,"Done.\n");
01641 #endif    
01642 
01643   pserrno = PSERR_NONE;
01644   
01645 Outtahere:
01646   if(ht)
01647     free(ht);
01648   if(pt)
01649     free(pt);
01650   if(td)
01651     free(td);    
01652   if(loca)
01653     free(loca);
01654   if(hhea)
01655     free(hhea);
01656   if(bbox)
01657     free(bbox);
01658   if(hmtx)
01659     free(hmtx);
01660   if(strings)
01661   {
01662     for(i = 0; i < 8; i++)
01663       if(strings[i])
01664         free(strings[i]);
01665     free(strings);
01666   }
01667   if(gnt)
01668   {
01669     for(i = 0; i < nglyphs; i++)
01670       if(gnt[i].type == 1 && gnt[i].name.name)
01671         free(gnt[i].name.name);
01672     free(gnt);
01673   }
01674   if(ke)
01675   {
01676     for(i = 0; i < nkern; i++)
01677       if(ke[i])
01678         free(ke[i]);
01679     free(ke);
01680   }
01681     
01682   if(nke)
01683     free(nke);
01684   
01685   return !pserrno;
01686 }
01687 
01688 #if 0
01689 int verbosity=0;
01690 
01691 int 
01692 main(int argc, char **argv)
01693 {
01694   int fd,i;
01695   FILE *out;
01696   FILE *afm=NULL;
01697   struct OffsetTable ot;
01698   struct HeadTable *ht;
01699   struct PostTable *pt;
01700   struct TableDirectoryEntry *td;
01701   void *loca=NULL;
01702   struct HheaTable *hhea=NULL;
01703   struct Box *bbox=NULL;
01704   longHorMetric *hmtx=NULL;
01705   char **strings=NULL;
01706   struct GlyphName *gnt=NULL;
01707   struct KernEntry0 **ke;
01708   int *nke;
01709   int nglyphs,postType,nkern;
01710   off_t headOff=0, maxpOff=0, postOff=0, nameOff=0, 
01711     locaOff=0, glyfOff=0, hheaOff=0, hmtxOff=0, kernOff=0;
01712 
01713   extern char *optarg;
01714   extern int optind;
01715   int c;
01716 
01717   endianness_test();
01718 
01719   while((c=getopt(argc,argv, "vqa:"))!=EOF)
01720     switch(c) {
01721     case 'v':
01722       verbosity++;
01723       break;
01724     case 'q':
01725       verbosity--;
01726       break;
01727     case 'a':
01728       if((afm=fopen(optarg,"w"))==NULL)
01729         syserror("Couldn't open AFM file");
01730       break;
01731     default:
01732       usage(argv[0]);
01733       exit(2);
01734     }
01735   if(argc-optind!=2) {
01736     usage(argv[0]);
01737     exit(2);
01738   }
01739 
01740   if((fd=open(argv[optind],O_RDONLY))<0)
01741     syserror("Error opening input file");
01742 
01743   if((out=fopen(argv[optind+1],"w"))==NULL)
01744     syserror("Error opening output file");
01745 
01746   td=readDirectory(fd,&ot);
01747   if(verbosity>=2)
01748     fprintf(stderr,"True type version %d.%u\n",
01749             ot.version.mantissa,ot.version.fraction);
01750 
01751   for(i=0;i<ot.numTables;i++) {
01752     if(verbosity>=2)
01753       fprintf(stderr,"Found `%c%c%c%c' table\n",
01754               (char)(td[i].tag>>24),
01755               (char)(td[i].tag>>16)&255,
01756               (char)(td[i].tag>>8)&255,
01757               (char)td[i].tag&255);
01758     switch(td[i].tag) {
01759     case MAKE_ULONG('m','a','x','p'):
01760       maxpOff=td[i].offset;
01761       break;
01762     case MAKE_ULONG('h','e','a','d'):
01763       headOff=td[i].offset;
01764       break;
01765     case MAKE_ULONG('p','o','s','t'):
01766       postOff=td[i].offset;
01767       break;
01768     case MAKE_ULONG('n','a','m','e'):
01769       nameOff=td[i].offset;
01770       break;
01771     case MAKE_ULONG('l','o','c','a'):
01772       locaOff=td[i].offset;
01773       break;
01774     case MAKE_ULONG('g','l','y','f'):
01775       glyfOff=td[i].offset;
01776       break;
01777     case MAKE_ULONG('h','h','e','a'):
01778       hheaOff=td[i].offset;
01779       break;
01780     case MAKE_ULONG('h','m','t','x'):
01781       hmtxOff=td[i].offset;
01782       break;
01783     case MAKE_ULONG('k','e','r','n'):
01784       kernOff=td[i].offset;
01785       break;
01786     }
01787   }
01788   if(maxpOff==0 || headOff==0 || postOff==0 || nameOff==0)
01789     error("Incomplete TTF file\n");
01790 
01791   if(verbosity>=1)
01792     fprintf(stderr,"Processing `maxp' table\n");
01793   surely_lseek(fd,maxpOff,SEEK_SET);
01794   nglyphs=readMaxpTable(fd);
01795   if(verbosity>=1)
01796     fprintf(stderr,"  %d glyphs\n",nglyphs);
01797 
01798   if(verbosity>=1)
01799     fprintf(stderr,"Processing `head' table\n");
01800   surely_lseek(fd,headOff,SEEK_SET);
01801   ht=malloc(sizeof(struct HeadTable));
01802   readHeadTable(fd,ht);
01803 
01804   if(verbosity>=1)
01805     fprintf(stderr,"Processing `post' table\n");
01806   surely_lseek(fd,postOff,SEEK_SET);
01807   pt=malloc(sizeof(struct PostTable));
01808   postType=readPostTable(fd,nglyphs,pt,&gnt);
01809   
01810   if(verbosity>=1)
01811     fprintf(stderr,"Processing `name' table\n");
01812   surely_lseek(fd,nameOff,SEEK_SET);
01813   strings=readNamingTable(fd);
01814 
01815   if(afm) {
01816     if(locaOff) {
01817       if(verbosity>=1)
01818         fprintf(stderr,"Processing `loca' table\n");
01819       surely_lseek(fd,locaOff,SEEK_SET);
01820       loca=readLocaTable(fd,nglyphs,ht->indexToLocFormat);
01821       if(glyfOff) {
01822         if(verbosity>=1)
01823           fprintf(stderr,"Processing `glyf' table\n");
01824         surely_lseek(fd,glyfOff,SEEK_SET);
01825         bbox=readGlyfTable(fd,nglyphs,ht->indexToLocFormat,loca);
01826       }
01827       if(hheaOff) {
01828         if(verbosity>=1)
01829           fprintf(stderr,"Processing `hhea' table\n");
01830         surely_lseek(fd,hheaOff,SEEK_SET);
01831         hhea=readHheaTable(fd);
01832         if(hmtxOff) {
01833           if(verbosity>=1)
01834             fprintf(stderr,"Processing `hmtx' table\n");
01835           surely_lseek(fd,hmtxOff,SEEK_SET);
01836           hmtx=readHmtxTable(fd,hhea->numberOfHMetrics);
01837         }
01838       }
01839     }
01840     if(kernOff) {
01841       if(verbosity>=1)
01842         fprintf(stderr,"Processing `kern' table\n");
01843       surely_lseek(fd,kernOff,SEEK_SET);
01844       nkern=readKernTable(fd,&nke,&ke);
01845     } else
01846       nkern=0;
01847   }
01848   
01849   if(verbosity>=1)
01850     fprintf(stderr,"Generating PS file\n");
01851   printPSFont(out,ht,strings,nglyphs,postType,pt,gnt,fd);
01852   fclose(out);
01853   if(afm) {
01854     if(verbosity>=1)
01855       fprintf(stderr,"Generating AFM file\n");
01856     printAFM(afm,ht,strings,nglyphs,postType,pt,gnt,
01857              bbox,hhea,hmtx,
01858              nkern,nke,ke);
01859     fclose(afm);
01860   }
01861   if(verbosity>=1)
01862     fprintf(stderr,"Done.\n");
01863   close(fd);
01864   return 0;
01865 }
01866 
01867 
01868 static void 
01869 endianness_test()
01870 {
01871   union {
01872     BYTE b[4];
01873     ULONG l;
01874   } x;
01875   ULONG v;
01876 
01877   x.b[0]=1; x.b[1]=2; x.b[2]=3; x.b[3]=4;
01878 
01879   v=UL(x.l);
01880 
01881   if(v!=(((((1<<8)+2)<<8)+3)<<8)+4) {
01882     fprintf(stderr,"Code badly compiled for this architecture\n");
01883     fprintf(stderr,"Please set SMALLENDIAN and recompile\n");
01884     exit(2);
01885   }
01886 }
01887 
01888 static void
01889 usage(char *name)
01890 {
01891   fprintf(stderr,"ttfps 0.3.1\n");
01892   fprintf(stderr,
01893           "Usage: %s [-q[q[q]]] [-v[v[v]]] [-a outfile.afm] infile.ttf outfile.pfa\n",
01894           name);
01895 }
01896 
01897 
01898 #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