]> git.karo-electronics.de Git - gbdfed.git/blob - bdfpsf.c
Fixup several compile faults due to changes in recent distributions,
[gbdfed.git] / bdfpsf.c
1 /*
2  * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27
28 #include "bdfP.h"
29
30 /**************************************************************************
31  *
32  * PSF1 Macros and values.
33  *
34  **************************************************************************/
35
36 /*
37  * Macros that specify the indexes of the mode and height fields of the header
38  * info passed to the PSF1 loader.
39  */
40 #define _BDF_PSF1MODE   2
41 #define _BDF_PSF1HEIGHT 3
42
43 /*
44  * Flags which can appear in the third byte of the header (PSF1 mode).  HAS512
45  * means the font contains up to 512 glyphs.  Otherwise the font has 256
46  * glyphs.  HASTAB and HASSEQ indicate the glyphs are followed by a Unicode
47  * mapping table.
48  *
49  * The HASTAB and HASSEQ flags appear to be essentially equivalent.
50  */
51 #define _BDF_PSF1_HAS512 0x01
52 #define _BDF_PSF1_HASTAB 0x02
53 #define _BDF_PSF1_HASSEQ 0x04
54
55 /**************************************************************************
56  *
57  * PSF2 Macros
58  *
59  **************************************************************************/
60
61 #define _BDF_PSF2_HASTAB 0x01
62
63 /*
64  * Little endian versions of the PSF magic numbers.
65  */
66 unsigned char _bdf_psf1magic[] = {0x36, 0x04};
67 unsigned char _bdf_psf2magic[] = {0x72, 0xb5, 0x4a, 0x86};
68
69 /*
70  * The special header for PSF fonts that specify a list of partial
71  * fonts.
72  */
73 char _bdf_psfcombined[] = {'#', ' ', 'c', 'o'};
74
75 /*
76  * The PSF2 internal header.
77  */
78 typedef struct {
79     unsigned int version;
80     unsigned int headersize;
81     unsigned int flags;
82     unsigned int length;
83     unsigned int bpc;
84     unsigned int height;
85     unsigned int width;
86 } _bdf_psfhdr_t;
87
88 /**************************************************************************
89  *
90  * Support functions.
91  *
92  **************************************************************************/
93
94 #define _swap_endian(n) ((n) >> 16) | (((n) & 0xffff) << 16)
95
96 static int
97 _bdf_psf_load_map(FILE *in, bdf_font_t *font, int psf2, int *res)
98 {
99     int i, more, c0, c1, cnt;
100     unsigned int code;
101     unsigned char buf[4];
102     bdf_glyph_t *gp;
103
104     gp = font->glyphs;
105
106     while ((c0 = getc(in)) >= 0) {
107         /*
108          * If we are still reading bytes after the end of the glyphs,
109          * the table is too int.
110          */
111         if (gp == font->glyphs + font->glyphs_used)
112           return BDF_PSF_LONG_TABLE;
113
114         cnt = 0;
115         *res = gp->encoding;
116         if (!psf2) {
117             if ((c1 = getc(in)) < 0)
118               return BDF_PSF_SHORT_TABLE;
119             if (bdf_little_endian())
120               code = (c1 << 8) | (c0 & 0xff);
121             else
122               code = (c0 << 8) | (c1 & 0xff);
123
124             /*
125              * Convert to UTF-8.
126              */
127             if (code != 0xffff) {
128                 if (code < 0x80)
129                   buf[cnt++] = code & 0xff;
130                 else if (code < 0x800) {
131                     buf[cnt++] = 0xc0 | (code >> 6);
132                     buf[cnt++] = 0x80 | (code & 0x3f);
133                 } else if (code < 0x10000) {
134                     buf[cnt++] = 0xe0 | (code >> 12);
135                     buf[cnt++] = 0x80 | ((code >> 6) & 0x3f);
136                     buf[cnt++] = 0x80 | (code & 0x3f);
137                 } else if (code < 0x200000) {
138                     buf[cnt++] = 0xf0 | (code >> 18);
139                     buf[cnt++] = 0x80 | ((code >> 12) & 0x3f);
140                     buf[cnt++] = 0x80 | ((code >> 6) & 0x3f);
141                     buf[cnt++] = 0x80 | (code & 0x3f);
142                 } else if (code < 0x4000000) {
143                     buf[cnt++] = 0xf8 | (code >> 24);
144                     buf[cnt++] = 0x80 | ((code >> 18) & 0x3f);
145                     buf[cnt++] = 0x80 | ((code >> 12) & 0x3f);
146                     buf[cnt++] = 0x80 | ((code >> 6) & 0x3f);
147                     buf[cnt++] = 0x80 | (code & 0x3f);
148                 } else if (code < 0x7fffffff) {
149                     buf[cnt++] = 0xfc | (code >> 30);
150                     buf[cnt++] = 0x80 | ((code >> 24) & 0x3f);
151                     buf[cnt++] = 0x80 | ((code >> 18) & 0x3f);
152                     buf[cnt++] = 0x80 | ((code >> 12) & 0x3f);
153                     buf[cnt++] = 0x80 | ((code >> 6) & 0x3f);
154                     buf[cnt++] = 0x80 | (code & 0x3f);
155                 }
156             } else
157               buf[cnt++] = 0xff;
158         } else {
159             buf[cnt++] = c0;
160             if (c0 < 0xfd && (c0 & 0x80) != 0) {
161                 /*
162                  * Only look for more if the byte is not 0xfe or 0xff,
163                  * PSF separators.
164                  */
165                 more = 0;
166                 if ((c0 & 0xe0) == 0xc0)
167                   more = 1;
168                 else if ((c0 & 0xf0) == 0xe0)
169                   more = 2;
170                 else if ((c0 & 0xf0) == 0xf0)
171                   more = 3;
172
173                 for (i = 0; i < more; i++) {
174                     if ((c0 = getc(in)) < 0)
175                       return BDF_PSF_SHORT_TABLE;
176                     else if (c0 > 0xfd)
177                       return BDF_PSF_CORRUPT_UTF8;
178                     buf[cnt++] = c0;
179                 }
180             }
181         }
182         if (buf[0] != 0xff) {
183             if (gp->unicode.map_used + cnt > gp->unicode.map_size) {
184                 more = ((cnt >> 2) + ((cnt & 3) ? 1 : 0)) << 2;
185                 if (gp->unicode.map_size == 0)
186                   gp->unicode.map = (unsigned char *)
187                       malloc(sizeof(unsigned char) * more);
188                 else
189                   gp->unicode.map = (unsigned char *)
190                       realloc((char *) gp->unicode.map,
191                               sizeof(unsigned char) *
192                               (gp->unicode.map_size + more));
193                 gp->unicode.map_size += more;
194             }
195             (void) memcpy((char *) (gp->unicode.map + gp->unicode.map_used),
196                           (char *) buf, sizeof(unsigned char) * cnt);
197             gp->unicode.map_used += cnt;
198         } else
199           gp++;
200
201     }
202     return BDF_OK;
203 }
204
205 static int
206 _bdf_psf_dump_map(FILE *out, bdf_font_t *font, bdf_glyphlist_t *glyphs)
207 {
208     int seq;
209     unsigned int i, nglyphs, n;
210     int code = -1;
211     unsigned char *map, *map_end;
212     bdf_glyph_t *gp;
213
214     nglyphs = (glyphs->glyphs_used > 512) ? 512 : glyphs->glyphs_used;
215     for (i = 0, gp = glyphs->glyphs; i < nglyphs; i++, gp++) {
216
217         if (nglyphs > 256)
218           fprintf(out, "0x%03x", i);
219         else
220           fprintf(out, "0x%02x", i);
221
222         map = gp->unicode.map;
223         map_end = map + gp->unicode.map_used;
224
225         seq = 0;
226         while (map < map_end) {
227             n = 1;
228
229             if (*map == 0xfe) {
230                 seq = 2;
231                 map++;
232                 continue;
233             }
234
235             /*
236              * Convert from UTF-8 to UTF-32.
237              */
238             if ((*map & 0x80) == 0)
239               /*
240                * One byte character.
241                */
242               code = (unsigned short) *map;
243             else if (*map < 0xe0) {
244                 /*
245                  * Two byte character.
246                  */
247                 if (map + 2 >= map_end)
248                   return BDF_PSF_CORRUPT_UTF8;
249                 code = ((*map & 0x1f) << 6) | (*(map + 1) & 0x3f);
250                 n = 2;
251             } else if (*map < 0xf0) {
252                 /*
253                  * Three byte character.
254                  */
255                 if (map + 3 >= map_end)
256                   return BDF_PSF_CORRUPT_UTF8;
257                 code = ((*map & 0x0f) << 12) |
258                     ((*(map + 1) & 0x3f) << 6) | (*(map + 2) & 0x3f);
259                 n = 3;
260             } else if (*map < 0xf8) {
261                 /*
262                  * Four byte character.
263                  */
264                 if (map + 4 >= map_end)
265                   return BDF_PSF_CORRUPT_UTF8;
266                 code = ((*map & 0x07) << 18) |
267                     ((*(map + 1) & 0x3f) << 12) |
268                     ((*(map + 2) & 0x3f) << 6) | (*(map + 3) & 0x3f);
269                 n = 4;
270             } else if (*map < 0xfc) {
271                 /*
272                  * Five byte character.
273                  */
274                 if (map + 5 >= map_end)
275                   return BDF_PSF_CORRUPT_UTF8;
276                 code = ((*map & 0x03) << 24) |
277                     ((*(map + 1) & 0x3f) << 18) |
278                     ((*(map + 2) & 0x3f) << 12) |
279                     ((*(map + 3) & 0x3f) << 6) |
280                     (*(map + 4) & 0x3f);
281                 n = 5;
282             } else if (*map < 0xfe) {
283                 /*
284                  * Six byte character.
285                  */
286                 if (map + 6 >= map_end)
287                   return BDF_PSF_CORRUPT_UTF8;
288                 code = ((*map & 0x01) << 30) |
289                     ((*(map + 1) & 0x3f) << 24) |
290                     ((*(map + 2) & 0x3f) << 18) |
291                     ((*(map + 3) & 0x3f) << 12) |
292                     ((*(map + 4) & 0x3f) << 6) |
293                     (*(map + 5) & 0x3f);
294                 n = 6;
295             }
296             /*
297              * Print the code(s).  If we are printing the first one,
298              * then print a tab, otherwise we are printing separating
299              * spaces.
300              */
301             if (map == gp->unicode.map)
302               putc('\t', out);
303             else
304               putc(((seq == 1) ? ',' : ' '), out);
305             if (n < 5)
306               fprintf(out, "U+%04X", code);
307             else
308               fprintf(out, "U+%06X", code);
309             map += n;
310             seq -= (seq == 2);
311         }
312
313         /*
314          * Print the line separator.
315          */
316         putc('\n', out);
317
318         /*
319          * Free the current glyph storage.
320          */
321         if (gp->name != 0)
322           free(gp->name);
323         if (gp->bytes > 0)
324           free((char *) gp->bitmap);
325         if (gp->unicode.map_size > 0)
326           free((char *) gp->unicode.map);
327     }
328
329     /*
330      * Free the storage for the glyph list.
331      */
332     if (glyphs->glyphs_size > 0)
333       free((char *) glyphs->glyphs);
334
335     return BDF_OK;
336 }
337
338 /**************************************************************************
339  *
340  * Public functions.
341  *
342  **************************************************************************/
343
344 /*
345  * Return an array of strings with the Unicode encodings already formatted for
346  * use with the GUI.
347  */
348 char **
349 _bdf_psf_unpack_mapping(bdf_psf_unimap_t *unimap, int *num_seq)
350 {
351     int ns, nc, sum, c;
352     int code = -1;
353     unsigned char *mp, *ep;
354     char **list, *lp;
355
356     list = 0;
357     if (!num_seq)
358       return list;
359     *num_seq = 0;
360
361     if (unimap == 0 || unimap->map_used == 0)
362       return list;
363
364     /*
365      * This routine will calculate the amount of storage is needed to be
366      * allocated as one big block so an array of strings can be returned.
367      * That way it can be deallocated as a single item by the caller.
368      */
369
370
371     /*
372      * Count the total number of characters and sequences at the same time.
373      */
374     mp = unimap->map;
375     ep = mp + unimap->map_used;
376     sum = ns = nc = 0;
377     while (mp < ep) {
378         if (*mp == 0xfe) {
379             sum = 1;
380             ns++;
381             mp++;
382             continue;
383         }
384
385         c = 1;
386         if (*mp < 0xe0)
387           c = 2;
388         else if (*mp < 0xf0)
389           c = 3;
390         else if (*mp < 0xf8)
391           c = 4;
392         else if (*mp < 0xfc)
393           c = 5;
394         else if (*mp < 0xfe)
395           c = 6;
396
397         nc++;
398
399         mp += c;
400         ns += !sum;
401     }
402
403     *num_seq = ns;
404
405     /*
406      * The block of storage will need this many bytes for pointers to the
407      * sequences.
408      */
409     sum = sizeof(unsigned char *) * ns;
410
411     /*
412      * Each character uses up to 8 bytes in U+XXXXXX form and each is followed
413      * by either space or a null, so each is basically nine bytes including
414      * the trailing NULL.
415      */
416     sum += nc * 9;
417
418     list = (char **) malloc(sum);
419     lp = (char *) (list + ns);
420
421     /*
422      * Now generate the codes one at a time.
423      */
424     list[0] = lp;
425
426     ns = sum = 0;
427     mp = unimap->map;
428     while (mp < ep) {
429         if (*mp == 0xfe) {
430             if (sum == 1)
431               /*
432                * The last thing added was a sequence, so move up to the
433                * next sequence.
434                */
435               list[++ns] = ++lp;
436
437             sum = 1;
438             mp++;
439             continue;
440         }
441
442         nc = 1;
443
444         /*
445          * Convert from UTF-8 to UTF-32.
446          */
447         if (*mp < 0x80)
448           /*
449            * One byte character.
450            */
451           code = (unsigned short) *mp;
452         else if (*mp < 0xe0) {
453             /*
454              * Two byte character.
455              */
456             code = ((*mp & 0x1f) << 6) | (*(mp + 1) & 0x3f);
457             nc = 2;
458         } else if (*mp < 0xf0) {
459             /*
460              * Three byte character.
461              */
462             code = ((*mp & 0x0f) << 12) |
463                 ((*(mp + 1) & 0x3f) << 6) | (*(mp + 2) & 0x3f);
464             nc = 3;
465         } else if (*mp < 0xf8) {
466             /*
467              * Four byte character.
468              */
469             code = ((*mp & 0x07) << 18) |
470                 ((*(mp + 1) & 0x3f) << 12) |
471                 ((*(mp + 2) & 0x3f) << 6) | (*(mp + 3) & 0x3f);
472             nc = 4;
473         } else if (*mp < 0xfc) {
474             /*
475              * Five byte character.
476              */
477             code = ((*mp & 0x03) << 24) |
478                 ((*(mp + 1) & 0x3f) << 18) |
479                 ((*(mp + 2) & 0x3f) << 12) |
480                 ((*(mp + 3) & 0x3f) << 6) |
481                 (*(mp + 4) & 0x3f);
482             nc = 5;
483         } else if (*mp < 0xfe) {
484             /*
485              * Six byte character.
486              */
487             code = ((*mp & 0x01) << 30) |
488                 ((*(mp + 1) & 0x3f) << 24) |
489                 ((*(mp + 2) & 0x3f) << 18) |
490                 ((*(mp + 3) & 0x3f) << 12) |
491                 ((*(mp + 4) & 0x3f) << 6) |
492                 (*(mp + 5) & 0x3f);
493             nc = 6;
494         }
495
496         /*
497          * Add to the string.
498          */
499
500         if (lp > list[ns])
501           *lp++ = ' ';
502         if (nc < 5)
503           sprintf(lp, "U+%04X", code);
504         else
505           sprintf(lp, "U+%06X", code);
506         lp += 7;
507
508         mp += nc;
509
510         if (mp < ep && !sum)
511           list[++ns] = ++lp;
512     }
513     return list;
514 }
515
516 /*
517  * Routine used to insure the list of mappings is in ascending order
518  * by length of string.
519  */
520 static int
521 cmplen(const void *a, const void *b)
522 {
523     int n;
524     char *as = *((char **)a);
525     char *bs = *((char **)b);
526
527     n = strlen(as) - strlen(bs);
528     return (n) ? n : strcmp(as, bs);
529 }
530
531 /*
532  * Taking a list of strings, generate a packed UTF-8 representation to
533  * be stored back into a Unicode map.
534  */
535 int
536 _bdf_psf_pack_mapping(char **list, int len, int encoding,
537                       bdf_psf_unimap_t *map)
538 {
539     int i, j, ncodes, bytes = 3;
540     char *lp, *elp;
541     unsigned int codes[128];
542
543     if (list == 0 || len == 0 || map == 0)
544       return 0;
545
546     map->map_used = 0;
547
548     /*
549      * First thing that needs to be done is to make sure the list is sorted by
550      * length so the single character mappings come first.
551      */
552     qsort((char *) list, len, sizeof(char *), cmplen);
553
554     for (i = 0; i < len; i++) {
555         lp = list[i];
556         ncodes = 0;
557         while (*lp) {
558             /*
559              * Skip anything that isn't expected.
560              */
561             while (*lp && *lp != 'U' && *lp != 'u' && *lp != '0')
562               lp++;
563             if (*lp == 0)
564               continue;
565             codes[ncodes] = _bdf_atoul(lp, &elp, 16);
566
567             /*
568              * Determine how many UTF-8 bytes the current code will
569              * take.
570              */
571             if (codes[ncodes] < 0x80)
572               bytes++;
573             else if (codes[ncodes] < 0x800)
574               bytes += 2;
575             else if (codes[ncodes] < 0x10000)
576               bytes += 3;
577             else if (codes[ncodes] < 0x200000)
578               bytes += 4;
579             else if (codes[ncodes] < 0x4000000)
580               bytes += 5;
581             else if (codes[ncodes] < 0x7fffffff)
582               bytes += 6;
583             ncodes++;
584             lp = elp;
585         }
586         /*
587          * Make sure there is enough room in the map for this number of bytes.
588          * The number includes the encoding and the 0xff at the end on the
589          * first pass.
590          */
591         if (map->map_used + bytes > map->map_size) {
592             if (map->map_size == 0)
593               map->map = (unsigned char *)
594                   malloc(sizeof(unsigned char *) * 128);
595             else
596               map->map = (unsigned char *)
597                   realloc((char *) map->map,
598                           sizeof(unsigned char) * (map->map_size + 128));
599             map->map_size += 128;
600         }
601
602         if (ncodes > 1)
603           /*
604            * Have to increment the number of bytes by 1 to include the
605            * PSF2 sequence marker.
606            */
607           map->map[map->map_used++] = 0xfe;
608
609         /*
610          * Go through the codes and convert to UTF-8.
611          */
612         for (j = 0; j < ncodes; j++) {
613             if (codes[j] < 0x80)
614               map->map[map->map_used++] = (codes[j] & 0x7f);
615             else if (codes[j] < 0x800) {
616                 map->map[map->map_used++] = 0xc0 | ((codes[j] >> 6) & 0xff);
617                 map->map[map->map_used++] = 0x80 | (codes[j] & 0x3f);
618             } else if (codes[j] < 0x10000) {
619                 map->map[map->map_used++] = 0xe0 | ((codes[j] >> 12) & 0xff);
620                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 6) & 0x3f);
621                 map->map[map->map_used++] = 0x80 | (codes[j] & 0x3f);
622             } else if (codes[j] < 0x200000) {
623                 map->map[map->map_used++] = 0xf0 | ((codes[j] >> 18) & 0xff);
624                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 12) & 0x3f);
625                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 6) & 0x3f);
626                 map->map[map->map_used++] = 0x80 | (codes[j] & 0x3f);
627             } else if (codes[j] < 0x4000000) {
628                 map->map[map->map_used++] = 0xf8 | ((codes[j] >> 24) & 0xff);
629                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 18) & 0xff);
630                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 12) & 0x3f);
631                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 6) & 0x3f);
632                 map->map[map->map_used++] = 0x80 | (codes[j] & 0x3f);
633             } else if (codes[j] < 0x7fffffff) {
634                 map->map[map->map_used++] = 0xfc | ((codes[j] >> 30) & 0xff);
635                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 24) & 0xff);
636                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 18) & 0xff);
637                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 12) & 0x3f);
638                 map->map[map->map_used++] = 0x80 | ((codes[j] >> 6) & 0x3f);
639                 map->map[map->map_used++] = 0x80 | (codes[j] & 0x3f);
640             }
641         }
642         bytes = 0;
643     }
644
645     return BDF_OK;
646 }
647
648 bdf_font_t *
649 bdf_load_psf(FILE *in, unsigned char *magic, bdf_options_t *opts,
650              bdf_callback_t callback, void *data, int *awidth)
651 {
652     int i, enc;
653     unsigned short dwidth, swidth;
654     bdf_glyph_t *gp;
655     bdf_font_t *fp;
656     _bdf_psfhdr_t hdr;
657     bdf_callback_struct_t cb;
658     char msgbuf[1024];
659
660     /*
661      * Check options for loading the Unicode table or not.
662      */
663
664     if (*magic == 0x36) {
665         /*
666          * PSF1 font.
667          */
668         hdr.version = 0;
669         hdr.width = 8;
670         hdr.height = hdr.bpc = (int) magic[_BDF_PSF1HEIGHT];
671         hdr.length = (magic[_BDF_PSF1MODE] & _BDF_PSF1_HAS512) ? 512 : 256;
672         hdr.flags = (magic[_BDF_PSF1MODE] & _BDF_PSF1_HASTAB) ?
673             _BDF_PSF2_HASTAB : 0;
674     } else {
675         /*
676          * PSF2 font.
677          */
678         fread((char *) &hdr, sizeof(_bdf_psfhdr_t), 1, in);
679         if (!bdf_little_endian()) {
680             /*
681              * Need to convert all the integers to big endian.
682              */
683             hdr.version = _swap_endian(hdr.version);
684             hdr.headersize = _swap_endian(hdr.headersize);
685             hdr.flags = _swap_endian(hdr.flags);
686             hdr.length = _swap_endian(hdr.length);
687             hdr.bpc = _swap_endian(hdr.bpc);
688             hdr.height = _swap_endian(hdr.height);
689             hdr.width = _swap_endian(hdr.width);
690         }
691     }
692
693     /*
694      * The point size of the font will be the height, the resolution will
695      * default to 72dpi, and the spacing will default to character cell.
696      */
697     fp = bdf_new_font(0, (int) hdr.height, 72, 72, BDF_CHARCELL, 1);
698
699     /*
700      * Force the bits per pixel to be 1.
701      */
702     fp->bpp = 1;
703
704     /*
705      * Set the font width and average width.
706      */
707     *awidth = fp->bbx.width = hdr.width;
708
709     /*
710      * Set the rest of the font bounding box parameters.
711      */
712     fp->font_ascent = fp->bbx.ascent;
713     fp->font_descent = fp->bbx.descent;
714
715 #if 0
716     /*
717      * MAY NOT BE NEEDED ANY MORE.
718      */
719
720     /*
721      * Adjust the ascent and descent by hand for point sizes other than 16.
722      */
723     if (hdr.height != 16) {
724         fp->bbx.ascent++;
725         fp->bbx.descent--;
726     }
727 #endif
728
729     /*
730      * Default the font ascent and descent to that of the bounding box.
731      */
732     fp->font_ascent = fp->bbx.ascent;
733     fp->font_descent = fp->bbx.descent;
734
735     /*
736      * Allocate the expected number of glyphs.
737      */
738     fp->glyphs_size = hdr.length;
739     fp->glyphs = (bdf_glyph_t *) malloc(sizeof(bdf_glyph_t) * fp->glyphs_size);
740     (void) memset((char *) fp->glyphs, 0,
741                   sizeof(bdf_glyph_t) * fp->glyphs_size);
742
743     /*
744      * Determine the default scalable and device width for each character.
745      */
746     dwidth = fp->bbx.width;
747     swidth = (unsigned short)
748         (((double) dwidth) * 72000.0) /
749         ((double) fp->point_size * fp->resolution_x);
750
751     /*
752      * Set up to call the callback.
753      */
754     if (callback != 0) {
755         cb.reason = BDF_LOAD_START;
756         cb.current = 0;
757         cb.total = fp->glyphs_size;
758         (*callback)(&cb, data);
759     }
760
761     /*
762      * Now load the glyphs, assigning a default encoding.
763      */
764     for (i = 0, gp = fp->glyphs; i < fp->glyphs_size; i++, gp++) {
765         gp->encoding = i;
766         gp->dwidth = dwidth;
767         gp->swidth = swidth;
768         (void) memcpy((char *) &gp->bbx, (char *) &fp->bbx, sizeof(bdf_bbx_t));
769
770         gp->bytes = hdr.bpc;
771         gp->bitmap = (unsigned char *) malloc(hdr.bpc);
772         fread((char *) gp->bitmap, hdr.bpc, 1, in);
773         fp->glyphs_used++;
774
775         /*
776          * Call the callback if indicated.
777          */
778         if (callback != 0) {
779             cb.reason = BDF_LOADING;
780             cb.total = fp->glyphs_size;
781             cb.current = fp->glyphs_used;
782             (*callback)(&cb, data);
783         }
784     }
785
786     /*
787      * Now load the Unicode mapping table if it exists.
788      */
789     if (hdr.flags & _BDF_PSF2_HASTAB) {
790         msgbuf[0] = 0;
791         switch (_bdf_psf_load_map(in, fp, (*magic == 0x72), &enc)) {
792           case BDF_PSF_SHORT_TABLE:
793             sprintf(msgbuf, "PSF Unicode table too short at 0x%04X (%d).",
794                     (unsigned short) (enc & 0xffff), enc);
795             break;
796           case BDF_PSF_LONG_TABLE:
797             strcpy(msgbuf, "PSF Unicode table too int.");
798             break;
799           case BDF_PSF_CORRUPT_UTF8:
800             sprintf(msgbuf, "PSF UTF-8 sequence corrupt at 0x%04X (%d).",
801                     (unsigned short) (enc & 0xffff), enc);
802             break;
803           case BDF_PSF_BUFFER_OVRFL:
804             sprintf(msgbuf, "PSF mapping buffer overflow at 0x%04X (%d).",
805                     (unsigned short) (enc & 0xffff), enc);
806             break;
807         }
808         if (msgbuf[0] != 0)
809           _bdf_add_acmsg(fp, msgbuf, strlen(msgbuf));
810     }
811
812     sprintf(msgbuf, "Font converted from PSF%c to BDF.",
813             (*magic == 0x36) ? '1' : '2');
814     _bdf_add_comment(fp, msgbuf, 32);
815     _bdf_add_acmsg(fp, msgbuf, 32);
816
817     return fp;
818 }
819
820 /*
821  * Exports all PSF fonts in PSF2 format for now.  start and end are
822  * supplied when a partial font needs to be created.
823  */
824 int
825 bdf_export_psf(FILE *out, bdf_font_t *font, bdf_options_t *opts, int start,
826                int end)
827 {
828     unsigned int i, nglyphs, flags;
829     _bdf_psfhdr_t hdr;
830     bdf_glyph_t *gp;
831     bdf_font_t tmpfont;
832     bdf_glyphlist_t glyphs;
833     bdf_glyph_t cell;
834
835     if (font->glyphs_used == 0)
836       return BDF_EMPTY_FONT;
837
838     /*
839      * This routine only exports from CHARCELL and MONOWIDTH fonts, padding
840      * the glyphs as it writes.
841      */
842     if (font->spacing == BDF_PROPORTIONAL)
843       return BDF_EMPTY_FONT;
844
845     if (start == end)
846       return BDF_BAD_RANGE;
847
848     /*
849      * Make a copy of the glyphs so we can get the smallest bounding box for
850      * the glyphs being exported.  This also does a bit of range checking.
851      */
852     (void) memset((char *) &glyphs, 0, sizeof(bdf_glyphlist_t));
853     bdf_copy_glyphs(font, start, end, &glyphs, 0);
854
855     /*
856      * At this point, if only the Unicode table is desired, then
857      * call the routine that prints the plain text version.
858      */
859     if ((opts->psf_flags == BDF_PSF_UNIMAP))
860       return _bdf_psf_dump_map(out, font, &glyphs);
861
862     /*
863      * Set up the temporary font so glyph padding will happen like it is
864      * supposed to.
865      */
866     tmpfont.bpp = glyphs.bpp;
867     (void) memcpy((char *) &tmpfont.bbx, (char *) &glyphs.bbx,
868                   sizeof(bdf_bbx_t));
869
870     /*
871      * Create the header.  The extra 4 on the header size account
872      * for the magic number.
873      *
874      * Number of glyphs and flags have to be calculated properly before writing
875      * so it isn't necessary to go back and rewrite the header after the font
876      * has been written.  That causes havoc when writing to stdout.
877      */
878     hdr.version = hdr.flags = 0;
879     hdr.headersize = sizeof(_bdf_psfhdr_t) + 4;
880     hdr.length = (glyphs.glyphs_used > 512) ? 512 : glyphs.glyphs_used;
881     hdr.width = glyphs.bbx.width;
882     hdr.height = glyphs.bbx.height;
883     hdr.bpc = hdr.height * ((hdr.width + 7) >> 3);
884
885     /*
886      * Determine if the font will have a Unicode mapping table.
887      */
888     for (i = 0; i < hdr.length; i++) {
889         if (glyphs.glyphs[i].unicode.map_used > 0) {
890             hdr.flags |= _BDF_PSF2_HASTAB;
891             break;
892         }
893     }
894
895     /*
896      * Save these values so it doesn't get whacked in an endian conversion.
897      */
898     nglyphs = hdr.length;
899     flags = hdr.flags;
900
901     /*
902      * Set up a structure for padding glyphs to cell boundaries.
903      */
904     cell.bytes = hdr.bpc;
905     cell.bitmap = (unsigned char *) malloc(cell.bytes);
906     (void) memcpy((char *) &cell.bbx, (char *) &glyphs.bbx, sizeof(bdf_bbx_t));
907
908     if (!bdf_little_endian()) {
909         /*
910          * Swap the integers into little endian order before writing.
911          */
912         hdr.version = _swap_endian(hdr.version);
913         hdr.headersize = _swap_endian(hdr.headersize);
914         hdr.flags = _swap_endian(hdr.flags);
915         hdr.length = _swap_endian(hdr.length);
916         hdr.bpc = _swap_endian(hdr.bpc);
917         hdr.height = _swap_endian(hdr.height);
918         hdr.width = _swap_endian(hdr.width);
919     }
920
921     /*
922      * Write the header.
923      */
924     fwrite((char *) _bdf_psf2magic, sizeof(unsigned char), 4, out);
925     fwrite((char *) &hdr, sizeof(_bdf_psfhdr_t), 1, out);
926
927     /*
928      * Generate the glyphs, padding them out to the dimensions of the
929      * font.
930      */
931     for (i = 0, gp = glyphs.glyphs; i < nglyphs; i++, gp++) {
932         /*
933          * We only need to do cropping on CHARCELL glyphs because MONOWIDTH
934          * glyphs are already cropped to their minimum dimensions.
935          */
936         if (font->spacing == BDF_CHARCELL)
937           _bdf_crop_glyph(&tmpfont, gp);
938         _bdf_pad_cell(&tmpfont, gp, &cell);
939         fwrite((char *) cell.bitmap, sizeof(unsigned char), cell.bytes, out);
940     }
941
942     /*
943      * Now generate the Unicode table if called for.
944      */
945     if ((opts->psf_flags & BDF_PSF_UNIMAP) && (flags & _BDF_PSF2_HASTAB)) {
946         for (gp = glyphs.glyphs, i = 0; i < nglyphs; i++, gp++) {
947             if (gp->unicode.map_used > 0)
948               fwrite((char *) gp->unicode.map, sizeof(unsigned char),
949                      gp->unicode.map_used, out);
950             putc(0xff, out);
951         }
952     }
953
954     /*
955      * Finally, dispose of the glyph copies.
956      */
957     for (i = 0, gp = glyphs.glyphs; i < glyphs.glyphs_used; i++, gp++) {
958         if (gp->name != 0)
959           free(gp->name);
960         if (gp->bytes > 0)
961           free((char *) gp->bitmap);
962         if (gp->unicode.map_size > 0)
963           free((char *) gp->unicode.map);
964     }
965     if (glyphs.glyphs_size > 0)
966       free((char *) glyphs.glyphs);
967
968     return BDF_OK;
969 }
970
971 #undef _swap_endian