1 /*
2  *   Here's some code to handle font libraries.  Not needed unless you are
3  *   running on a system that can't handle files well.  Not endorsed by
4  *   Tomas Rokicki or Radical Eye Software; use at your own risk.
5  */
6 #ifdef FONTLIB
7 #include "dvips.h" /* The copyright notice in that file is included too! */
8 #include "paths.h"
9 /*
10  *   The external declarations:
11  */
12 #include "protos_add.h"
13 
14 /*
15  * font library structures
16  */
17 struct fli_entry {
18    unsigned long  offset;
19    char          *name;
20 };
21 
22 struct fli_size {
23    unsigned long     size;
24    halfword          entries;
25    struct fli_entry *entry;
26 };
27 
28 struct fli_lib {
29    char            *name;
30    halfword         sizes;
31    struct fli_size *size;
32    struct fli_lib  *next;
33 };
34 
35 struct fli_lib *firstlib = NULL;
36 
37 struct fli_centry {
38    struct fli_lib  *lib;
39    FILE            *fp;
40 };
41 
42 #define FLICSIZE 4
43 struct fli_centry *fli_cache[FLICSIZE];
44 
45 Boolean flib = 0;  /* non zero if reading a font library */
46 
47 halfword
pkdouble(void)48 pkdouble(void)
49 {
50    register halfword i;
51    i = pkbyte();
52    i = i * 256 + pkbyte();
53    return(i);
54 }
55 /*
56  *   fliload opens each font library, then reads in its
57  *   directory for later use.
58  *   fli_cache is initialized.
59  */
60 void
fliload(void)61 fliload(void)
62 {
63    int i;
64    halfword version1, version2;
65    Boolean needext;
66    char fontname[50];
67    char name[50];
68    char *fli;
69    unsigned long dpi;
70    halfword len, numsizes, numfonts;
71    halfword numflib = 0;
72    struct fli_lib *lib=NULL, *next_lib=NULL;
73    struct fli_size *size;
74    struct fli_entry *entry;
75 
76    /* initialise fli cache */
77    for (i=0; i<FLICSIZE; i++) {
78       fli_cache[i] = (struct fli_centry *)
79                       mymalloc((integer)sizeof(struct fli_centry));
80       fli_cache[i]->lib = (struct fli_lib *)NULL;
81       fli_cache[i]->fp = (FILE *)NULL;
82    }
83 
84    fli = fliname;
85 
86    while (*fli) {
87       /* get next font library name from fliname */
88       needext=1;
89       for (i=0; *fli && *fli!=PATHSEP; i++)
90          if ( (name[i] = *fli++) == '.')
91             needext=0;
92       name[i] = '\0';
93       if (*fli)
94          fli++;  /* skip PATHSEP */
95       if (*name) {
96          /* got fli name, now search for it */
97          if (needext)
98             strcat(name,".fli");
99 
100          if ( (pkfile=search(flipath,name,READBIN)) != (FILE *)NULL ) {
101             /* for each font library */
102             for (i=0; i<4; i++) {
103               fontname[i] = pkbyte();  /* read header */
104             }
105             version1 = pkbyte();
106             version2 = pkbyte();
107             if (strncmp(fontname,"FLIB",4)!=0 || version1 != 2 || version2 != 0)
108                badpk("incorrect font library format");
109 
110             (void) pkdouble();       /* ignore directory length */
111             numsizes = pkdouble();   /* number of sizes */
112             numfonts = pkdouble();   /* number of fonts */
113             len = pkdouble();        /* length of comment */
114             for (i=0; i<len; i++)
115                pkbyte();       /* skip comment */
116 #ifdef DEBUG
117    if (dd(D_FONTS))
118       fprintf(stderr,"Font library %s has %d font size%s, %d font%s\n",
119          name, numsizes , numsizes !=1 ? "s" : "",
120          numfonts, numfonts!=1 ? "s" : "");
121 #endif /* DEBUG */
122 
123             next_lib =  (struct fli_lib *)
124                       mymalloc((integer)sizeof(struct fli_lib));
125             if (firstlib == (struct fli_lib *)NULL)
126                firstlib = next_lib;
127             else
128                lib->next = next_lib;
129             lib = next_lib;
130             size = (struct fli_size *)
131                         mymalloc((integer)numsizes * sizeof(struct fli_size));
132             entry = (struct fli_entry *)
133                         mymalloc((integer)numfonts * sizeof(struct fli_entry));
134             lib->name = newstring(name);
135             lib->sizes = numsizes;
136             lib->size = size;
137             lib->next = (struct fli_lib *)NULL;
138 
139             for (;numsizes>0; numsizes--, size++) {
140                /* for each font size in this library */
141                pkdouble();      /* length of size entry - ignore */
142                numfonts = pkdouble(); /* number of fonts */
143                dpi = pkquad();        /* DPI (fixed point 16.16) */
144 
145 #ifdef DEBUG
146    if (dd(D_FONTS))
147       fprintf(stderr,"Font library %s size %.5gdpi has %d font%s\n",
148                   name, dpi/65536.0, numfonts, numfonts!=1 ? "s" : "");
149 #endif /* DEBUG */
150                size->size    = dpi;
151                size->entries = numfonts;
152                size->entry   = entry;
153                   for (;numfonts > 0; numfonts--, entry++) {
154                      /* read each entry */
155                      pkquad();            /* ignore length of font */
156                      entry->offset = pkquad();  /* offset to font */
157                      len = pkbyte();            /* length of name */
158                      for (i=0; i<len; i++)
159                         fontname[i] = pkbyte();
160                      fontname[len] = '\0';
161                      entry->name = newstring(fontname);
162                   } /* end for numfonts>0 */
163             }  /* end for numsizes>0 */
164             if (numflib < FLICSIZE) { /* leave first few open */
165                fli_cache[numflib]->lib = lib;
166                fli_cache[numflib]->fp = pkfile;
167             }
168             else
169                fclose(pkfile);
170             numflib++;
171          }  /* end if opened library */
172       } /* end if (*name) */
173    }
174 }
175 
176 
177 /*
178  *   flisearch searches all the font libraries for a PK font.
179  *   returns FILE pointer positioned to PK font in font library
180  *   flisearch caches file pointers for 4 font libraries.
181  */
182 FILE *
flisearch(char * n,halfword dpi)183 flisearch(char *n, halfword dpi)
184 {
185    halfword dpi1, numsizes, numfonts;
186    struct fli_lib *lib=NULL;
187    struct fli_size *size;
188    struct fli_entry *entry;
189    struct fli_centry *centry;
190    int i;
191    Boolean found;
192 
193    if (firstlib == (struct fli_lib *)NULL)
194       return((FILE *)NULL);  /* return if no font libraries */
195 
196 #ifdef DEBUG
197       if (dd(D_FONTS)) {
198          fprintf(stderr,"Trying %s at %ddpi\nfli open:", n, dpi);
199           for (i=0; i<FLICSIZE; i++)  /* dump cache contents */
200             if (fli_cache[i]->lib != (struct fli_lib *)NULL)
201               fprintf(stderr, "   %s",(fli_cache[i]->lib)->name);
202          fprintf(stderr,"\n");
203       }
204 #endif /* DEBUG */
205    for (lib = firstlib; lib != (struct fli_lib *)NULL; lib = lib->next ) {
206       /* for each font library */
207       numsizes = lib->sizes;
208       size = lib->size;
209 #ifdef DEBUG
210       if (dd(D_FONTS))
211          fprintf(stderr,"  Searching %s\n", lib->name);
212 #endif /* DEBUG */
213       for (; numsizes>0; numsizes--, size++) {
214          /* for each font size in this library */
215          dpi1 = (halfword)((size->size+32768L)/65536);
216          if ( dpi1 == dpi ) {
217             /* if correct size then search for font */
218 #ifdef DEBUG
219             if (dd(D_FONTS))
220                fprintf(stderr, "    Checking size %ddpi\n",dpi1);
221 #endif /* DEBUG */
222             entry = size->entry;
223             for (numfonts=size->entries;numfonts > 0; numfonts--, entry++) {
224                if (strcmp(entry->name,n)==0) {
225                   /* if correct font name then look for it in cache */
226                      found = 0;
227                      for (i=0; i<FLICSIZE && !found; i++) {  /* check if fli in cache */
228                         if ( fli_cache[i]->lib == lib ) {
229                            /* found it, so move to front */
230                            centry = fli_cache[i];
231                            for (; i>0; i--)
232                              fli_cache[i] = fli_cache[i-1];
233                            found=1;
234                            fli_cache[0] = centry;
235                            pkfile = fli_cache[0]->fp;  /* font libary already open */
236                         }
237                      }
238                      if (!found) { /* if not in cache then re-open it */
239                         /* make space at front */
240                         fclose(fli_cache[FLICSIZE-1]->fp);
241                         centry = fli_cache[FLICSIZE-1];
242                         for (i=FLICSIZE-1; i>0; i--)
243                              fli_cache[i] = fli_cache[i-1];
244                         /* put this font library at front */
245                         if ( (pkfile=search(flipath,lib->name,READBIN)) == (FILE *)NULL ) {
246                            sprintf(errbuf,"Can't reopen font library %s", lib->name);
247                            error(errbuf);
248                            return((FILE *)NULL);
249 			}
250                         fli_cache[0] = centry;
251                         fli_cache[0]->lib = lib;
252                         fli_cache[0]->fp  = pkfile;
253                      }
254                      flib = 1;  /* tell loadfont() not to close it */
255                      /* then seek font within library */
256                      sprintf(name,"%s %s %ddpi",lib->name, n, dpi1);
257                      if (fseek(pkfile,entry->offset,0) )
258                            badpk("couldn't seek font");
259                         /* make sure it is a PK font */
260                         if (pkbyte()==247) /* pre byte */
261                            if (pkbyte()==89) {  /* id byte */
262                               if ( fseek(pkfile,entry->offset,0) )
263                                  badpk("couldn't seek font");
264                               return(pkfile); /* found it */
265                            }
266                         sprintf(errbuf,"%s %s %ddpi isn't PK format, ignoring",
267                               lib->name, n, dpi1);
268                         error(errbuf);
269                } /* end if name correct */
270             } /* end for numfonts>0 */
271          }
272          else {
273             /* if not correct size then skip */
274 #ifdef DEBUG
275       if (dd(D_FONTS))
276          fprintf(stderr, "    Skipping size %ddpi\n", dpi1);
277 #endif /* DEBUG */
278          }
279       }  /* end for numsizes>0 */
280    }
281    return((FILE *)NULL);
282 }
283 
284 /* parse the font library path, putting all directory names in path,
285  * and all font library names in name.
286  * Directory names have a trailing DIRSEP.
287  */
288 char *
fliparse(char * path,char * name)289 fliparse(char *path, char *name)
290 {
291    char *p, *prevp;           /* pointers to path */
292    char *n, *prevn;           /* pointers to name */
293    char *s;
294 
295    p = path;
296    n = name;
297    s = path;
298 
299    while (*s) {
300       prevp = p;
301       prevn = n;
302       while (*s && *s != PATHSEP) {
303          /* copy till PATHSEP */
304          *p++ = *s;
305          *n++ = *s;
306          s++;
307       }
308       *n = '\0';
309       if (*s)
310          s++;  /* skip PATHSEP */
311 
312       if ( *prevn=='\0' || prevn[strlen(prevn)-1] == DIRSEP ) {
313          n = prevn; /* ignore name if it is dir */
314          if (*prevn)
315             p--;     /* backup over DIRSEP */
316          *p++ = PATHSEP;
317          prevp = p;
318       }
319       else {
320          p = prevp; /* ignore path if it is library name */
321          *n++ = PATHSEP;
322          prevn = n;
323       }
324 
325    }
326    *p = '\0';
327    *n = '\0';
328    if (n!=name && *--n==PATHSEP)
329       *n = '\0'; /* remove trailing PATHSEP from name */
330    if (p!=path && *--p==PATHSEP)
331       *p = '\0'; /* remove trailing PATHSEP from path */
332    return(path);
333 }               /* end fliparse */
334 #else
335 /*
336  *   Some systems don't like .o files that compile to nothing, so we
337  *   provide a stub routine.
338  */
fliload()339 void fliload() {}
340 #endif
341 
342