summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/flib.c
blob: 4a93bab9dc9860884999bb9ffd3d6d49250e6f7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/*
 *   Here's some code to handle font libraries.  Not needed unless you are
 *   running on a system that can't handle files well.  Not endorsed by
 *   Tomas Rokicki or Radical Eye Software; use at your own risk.
 */
#ifdef FONTLIB
#include "dvips.h" /* The copyright notice in that file is included too! */
#include "paths.h"
/*
 *   The external declarations:
 */
#include "protos_add.h"

/*
 * font library structures
 */
struct fli_entry {
   unsigned long  offset;
   char          *name;
};

struct fli_size {
   unsigned long     size;
   halfword          entries;
   struct fli_entry *entry;
};

struct fli_lib {
   char            *name;
   halfword         sizes;
   struct fli_size *size;
   struct fli_lib  *next;
};

struct fli_lib *firstlib = NULL;

struct fli_centry {
   struct fli_lib  *lib;
   FILE            *fp;
};

#define FLICSIZE 4
struct fli_centry *fli_cache[FLICSIZE];

Boolean flib = 0;  /* non zero if reading a font library */

halfword
pkdouble(void)
{
   register halfword i;
   i = pkbyte();
   i = i * 256 + pkbyte();
   return(i);
}
/*
 *   fliload opens each font library, then reads in its
 *   directory for later use.
 *   fli_cache is initialized.
 */
void
fliload(void)
{
   int i;
   halfword version1, version2;
   Boolean needext;
   char fontname[50]; 
   char name[50];
   char *fli;
   unsigned long dpi;
   halfword len, numsizes, numfonts;
   halfword numflib = 0;
   struct fli_lib *lib=NULL, *next_lib=NULL;
   struct fli_size *size;
   struct fli_entry *entry;

   /* initialise fli cache */
   for (i=0; i<FLICSIZE; i++) {
      fli_cache[i] = (struct fli_centry *)
                      mymalloc((integer)sizeof(struct fli_centry)); 
      fli_cache[i]->lib = (struct fli_lib *)NULL;
      fli_cache[i]->fp = (FILE *)NULL;
   }

   fli = fliname;

   while (*fli) {
      /* get next font library name from fliname */
      needext=1;
      for (i=0; *fli && *fli!=PATHSEP; i++)
         if ( (name[i] = *fli++) == '.')
            needext=0;
      name[i] = '\0';
      if (*fli)
         fli++;  /* skip PATHSEP */
      if (*name) { 
         /* got fli name, now search for it */
         if (needext)
            strcat(name,".fli");

         if ( (pkfile=search(flipath,name,READBIN)) != (FILE *)NULL ) {
            /* for each font library */
            for (i=0; i<4; i++) {
              fontname[i] = pkbyte();  /* read header */
            }
            version1 = pkbyte();
            version2 = pkbyte();
            if (strncmp(fontname,"FLIB",4)!=0 || version1 != 2 || version2 != 0)
               badpk("incorrect font library format");

            (void) pkdouble();       /* ignore directory length */
            numsizes = pkdouble();   /* number of sizes */
            numfonts = pkdouble();   /* number of fonts */
            len = pkdouble();        /* length of comment */
            for (i=0; i<len; i++)
               pkbyte();       /* skip comment */
#ifdef DEBUG
   if (dd(D_FONTS))
      fprintf(stderr,"Font library %s has %d font size%s, %d font%s\n",
         name, numsizes , numsizes !=1 ? "s" : "", 
         numfonts, numfonts!=1 ? "s" : "");
#endif /* DEBUG */

            next_lib =  (struct fli_lib *)
                      mymalloc((integer)sizeof(struct fli_lib)); 
            if (firstlib == (struct fli_lib *)NULL)
               firstlib = next_lib;
            else
               lib->next = next_lib;
            lib = next_lib;
            size = (struct fli_size *)
                        mymalloc((integer)numsizes * sizeof(struct fli_size)); 
            entry = (struct fli_entry *)
                        mymalloc((integer)numfonts * sizeof(struct fli_entry)); 
            lib->name = newstring(name);
            lib->sizes = numsizes;
            lib->size = size;
            lib->next = (struct fli_lib *)NULL;

            for (;numsizes>0; numsizes--, size++) { 
               /* for each font size in this library */
               pkdouble();      /* length of size entry - ignore */
               numfonts = pkdouble(); /* number of fonts */
               dpi = pkquad();        /* DPI (fixed point 16.16) */

#ifdef DEBUG
   if (dd(D_FONTS))
      fprintf(stderr,"Font library %s size %.5gdpi has %d font%s\n", 
                  name, dpi/65536.0, numfonts, numfonts!=1 ? "s" : "");
#endif /* DEBUG */
               size->size    = dpi;
               size->entries = numfonts;
               size->entry   = entry;
                  for (;numfonts > 0; numfonts--, entry++) {
                     /* read each entry */
                     pkquad();            /* ignore length of font */
                     entry->offset = pkquad();  /* offset to font */
                     len = pkbyte();            /* length of name */
                     for (i=0; i<len; i++)
                        fontname[i] = pkbyte();
                     fontname[len] = '\0';
                     entry->name = newstring(fontname);
                  } /* end for numfonts>0 */
            }  /* end for numsizes>0 */
            if (numflib < FLICSIZE) { /* leave first few open */
               fli_cache[numflib]->lib = lib;
               fli_cache[numflib]->fp = pkfile;
            }
            else
               fclose(pkfile);
            numflib++;
         }  /* end if opened library */
      } /* end if (*name) */
   }
}
   

/*
 *   flisearch searches all the font libraries for a PK font.
 *   returns FILE pointer positioned to PK font in font library
 *   flisearch caches file pointers for 4 font libraries.
 */
FILE *
flisearch(char *n, halfword dpi)
{
   halfword dpi1, numsizes, numfonts;
   struct fli_lib *lib=NULL;
   struct fli_size *size;
   struct fli_entry *entry;
   struct fli_centry *centry;
   int i;
   Boolean found;
   
   if (firstlib == (struct fli_lib *)NULL)
      return((FILE *)NULL);  /* return if no font libraries */

#ifdef DEBUG
      if (dd(D_FONTS)) { 
         fprintf(stderr,"Trying %s at %ddpi\nfli open:", n, dpi);
          for (i=0; i<FLICSIZE; i++)  /* dump cache contents */
            if (fli_cache[i]->lib != (struct fli_lib *)NULL)
              fprintf(stderr, "   %s",(fli_cache[i]->lib)->name);
         fprintf(stderr,"\n");
      }
#endif /* DEBUG */
   for (lib = firstlib; lib != (struct fli_lib *)NULL; lib = lib->next ) {
      /* for each font library */
      numsizes = lib->sizes;
      size = lib->size;
#ifdef DEBUG
      if (dd(D_FONTS))
         fprintf(stderr,"  Searching %s\n", lib->name);
#endif /* DEBUG */
      for (; numsizes>0; numsizes--, size++) { 
         /* for each font size in this library */
         dpi1 = (halfword)((size->size+32768L)/65536);
         if ( dpi1 == dpi ) {
            /* if correct size then search for font */
#ifdef DEBUG
            if (dd(D_FONTS))
               fprintf(stderr, "    Checking size %ddpi\n",dpi1);
#endif /* DEBUG */
            entry = size->entry;
            for (numfonts=size->entries;numfonts > 0; numfonts--, entry++) {
               if (strcmp(entry->name,n)==0) {
                  /* if correct font name then look for it in cache */
                     found = 0;
                     for (i=0; i<FLICSIZE && !found; i++) {  /* check if fli in cache */
                        if ( fli_cache[i]->lib == lib ) {
                           /* found it, so move to front */
                           centry = fli_cache[i];
                           for (; i>0; i--)
                             fli_cache[i] = fli_cache[i-1];
                           found=1;
                           fli_cache[0] = centry;
                           pkfile = fli_cache[0]->fp;  /* font libary already open */
                        }
                     }
                     if (!found) { /* if not in cache then re-open it */
                        /* make space at front */
                        fclose(fli_cache[FLICSIZE-1]->fp); 
                        centry = fli_cache[FLICSIZE-1];
                        for (i=FLICSIZE-1; i>0; i--)
                             fli_cache[i] = fli_cache[i-1];
                        /* put this font library at front */
                        if ( (pkfile=search(flipath,lib->name,READBIN)) == (FILE *)NULL ) {
                           sprintf(errbuf,"Can't reopen font library %s", lib->name);
                           error(errbuf);
                           return((FILE *)NULL);
			}
                        fli_cache[0] = centry;
                        fli_cache[0]->lib = lib;
                        fli_cache[0]->fp  = pkfile;
                     }
                     flib = 1;  /* tell loadfont() not to close it */
                     /* then seek font within library */
                     sprintf(name,"%s %s %ddpi",lib->name, n, dpi1);
                     if (fseek(pkfile,entry->offset,0) )
                           badpk("couldn't seek font");
                        /* make sure it is a PK font */
                        if (pkbyte()==247) /* pre byte */
                           if (pkbyte()==89) {  /* id byte */
                              if ( fseek(pkfile,entry->offset,0) )
                                 badpk("couldn't seek font");
                              return(pkfile); /* found it */
                           }
                        sprintf(errbuf,"%s %s %ddpi isn't PK format, ignoring",
                              lib->name, n, dpi1);
                        error(errbuf);
               } /* end if name correct */
            } /* end for numfonts>0 */
         }
         else {
            /* if not correct size then skip */
#ifdef DEBUG
      if (dd(D_FONTS))
         fprintf(stderr, "    Skipping size %ddpi\n", dpi1);
#endif /* DEBUG */
         }
      }  /* end for numsizes>0 */
   }
   return((FILE *)NULL);
}

/* parse the font library path, putting all directory names in path, 
 * and all font library names in name.  
 * Directory names have a trailing DIRSEP.
 */
char *
fliparse(char *path, char *name)
{
   char *p, *prevp;           /* pointers to path */
   char *n, *prevn;           /* pointers to name */
   char *s;

   p = path;
   n = name;
   s = path;

   while (*s) {
      prevp = p;
      prevn = n;
      while (*s && *s != PATHSEP) {
         /* copy till PATHSEP */
         *p++ = *s; 
         *n++ = *s;
         s++;
      }  
      *n = '\0';
      if (*s)
         s++;  /* skip PATHSEP */

      if ( *prevn=='\0' || prevn[strlen(prevn)-1] == DIRSEP ) {
         n = prevn; /* ignore name if it is dir */
         if (*prevn)
            p--;     /* backup over DIRSEP */
         *p++ = PATHSEP;
         prevp = p;
      }
      else {
         p = prevp; /* ignore path if it is library name */
         *n++ = PATHSEP;
         prevn = n;
      }

   }
   *p = '\0';
   *n = '\0';
   if (n!=name && *--n==PATHSEP)
      *n = '\0'; /* remove trailing PATHSEP from name */
   if (p!=path && *--p==PATHSEP)
      *p = '\0'; /* remove trailing PATHSEP from path */
   return(path);
}               /* end fliparse */
#else
/*
 *   Some systems don't like .o files that compile to nothing, so we
 *   provide a stub routine.
 */
void fliload() {}
#endif