~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/extras/FreeType/contrib/ttf2bdf/ttf2bdf.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 1996, 1997, 1998, 1999 Computing Research Labs,
 
3
 * New Mexico State University
 
4
 *
 
5
 * Permission is hereby granted, free of charge, to any person obtaining a
 
6
 * copy of this software and associated documentation files (the "Software"),
 
7
 * to deal in the Software without restriction, including without limitation
 
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
9
 * and/or sell copies of the Software, and to permit persons to whom the
 
10
 * Software is furnished to do so, subject to the following conditions:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included in
 
13
 * all copies or substantial portions of the Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
 * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
 
19
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
 
20
 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 
21
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 */
 
23
#ifndef lint
 
24
#ifdef __GNUC__
 
25
static char rcsid[] __attribute__ ((unused)) = "Id: ttf2bdf.c,v 1.25 1999/10/21 16:31:54 mleisher Exp $";
 
26
#else
 
27
static char rcsid[] = "Id: ttf2bdf.c,v 1.25 1999/10/21 16:31:54 mleisher Exp $";
 
28
#endif
 
29
#endif
 
30
 
 
31
#include <stdio.h>
 
32
 
 
33
#ifdef WIN32
 
34
#include <windows.h>
 
35
#else
 
36
#include <stdlib.h>
 
37
#include <unistd.h>
 
38
#endif
 
39
 
 
40
#include <string.h>
 
41
 
 
42
#include "freetype.h"
 
43
 
 
44
/*
 
45
 * Include the remapping support.
 
46
 */
 
47
#include "remap.h"
 
48
 
 
49
/**************************************************************************
 
50
 *
 
51
 * Macros.
 
52
 *
 
53
 **************************************************************************/
 
54
 
 
55
/*
 
56
 * The version of ttf2bdf.
 
57
 */
 
58
#define TTF2BDF_VERSION "2.8"
 
59
 
 
60
/*
 
61
 * Set the default values used to generate a BDF font.
 
62
 */
 
63
#ifndef DEFAULT_PLATFORM_ID
 
64
#define DEFAULT_PLATFORM_ID 3
 
65
#endif
 
66
 
 
67
#ifndef DEFAULT_ENCODING_ID
 
68
#define DEFAULT_ENCODING_ID 1
 
69
#endif
 
70
 
 
71
#ifndef DEFAULT_POINT_SIZE
 
72
#define DEFAULT_POINT_SIZE 12
 
73
#endif
 
74
 
 
75
#ifndef DEFAULT_RESOLUTION
 
76
#define DEFAULT_RESOLUTION 100
 
77
#endif
 
78
 
 
79
/*
 
80
 * Used as a fallback for XLFD names where the character set/encoding can not
 
81
 * be determined.
 
82
 */
 
83
#ifndef DEFAULT_XLFD_CSET
 
84
#define DEFAULT_XLFD_CSET "-FontSpecific-0"
 
85
#endif
 
86
 
 
87
/*
 
88
 * nameID macros for getting strings from the TT font.
 
89
 */
 
90
#define TTF_COPYRIGHT 0
 
91
#define TTF_TYPEFACE  1
 
92
#define TTF_PSNAME    6
 
93
 
 
94
#ifndef MAX
 
95
#define MAX(h,i) ((h) > (i) ? (h) : (i))
 
96
#endif
 
97
 
 
98
#ifndef MIN
 
99
#define MIN(l,o) ((l) < (o) ? (l) : (o))
 
100
#endif
 
101
 
 
102
/**************************************************************************
 
103
 *
 
104
 * General globals set from command line.
 
105
 *
 
106
 **************************************************************************/
 
107
 
 
108
/*
 
109
 * The program name.
 
110
 */
 
111
static char *prog;
 
112
 
 
113
/*
 
114
 * The flag indicating whether messages should be printed or not.
 
115
 */
 
116
static int verbose = 0;
 
117
 
 
118
/*
 
119
 * Flags used when loading glyphs.
 
120
 */
 
121
static int load_flags = TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH;
 
122
 
 
123
/*
 
124
 * The default platform and encoding ID's.
 
125
 */
 
126
static int pid = DEFAULT_PLATFORM_ID;
 
127
static int eid = DEFAULT_ENCODING_ID;
 
128
 
 
129
/*
 
130
 * Default point size and resolutions.
 
131
 */
 
132
static int point_size = DEFAULT_POINT_SIZE;
 
133
static int hres = DEFAULT_RESOLUTION;
 
134
static int vres = DEFAULT_RESOLUTION;
 
135
 
 
136
/*
 
137
 * The user supplied foundry name to use in the XLFD name.
 
138
 */
 
139
static char *foundry_name = 0;
 
140
 
 
141
/*
 
142
 * The user supplied typeface name to use in the XLFD name.
 
143
 */
 
144
static char *face_name = 0;
 
145
 
 
146
/*
 
147
 * The user supplied weight name to use in the XLFD name.
 
148
 */
 
149
static char *weight_name = 0;
 
150
 
 
151
/*
 
152
 * The user supplied slant name to use in the XLFD name.
 
153
 */
 
154
static char *slant_name = 0;
 
155
 
 
156
/*
 
157
 * The user supplied width name to use in the XLFD name.
 
158
 */
 
159
static char *width_name = 0;
 
160
 
 
161
/*
 
162
 * The user supplied additional style name to use in the XLFD name.
 
163
 */
 
164
static char *style_name = 0;
 
165
 
 
166
/*
 
167
 * The user supplied spacing (p = proportional, c = character cell,
 
168
 * m = monospace).
 
169
 */
 
170
static int spacing = 0;
 
171
 
 
172
/*
 
173
 * The dash character to use in the names retrieved from the font.  Default is
 
174
 * the space.
 
175
 */
 
176
static int dashchar = ' ';
 
177
 
 
178
/*
 
179
 * Flag, bitmask, and max code for generating a subset of the glyphs in a font.
 
180
 */
 
181
static int do_subset = 0;
 
182
static unsigned short maxcode;
 
183
static unsigned long subset[2048];
 
184
 
 
185
/*
 
186
 * The flag that indicates the remapping table should be used to
 
187
 * reencode the font.
 
188
 */
 
189
static int do_remap = 0;
 
190
 
 
191
/**************************************************************************
 
192
 *
 
193
 * Internal globals.
 
194
 *
 
195
 **************************************************************************/
 
196
 
 
197
/*
 
198
 * Structure used for calculating the font bounding box as the glyphs are
 
199
 * generated.
 
200
 */
 
201
typedef struct {
 
202
    short minlb;
 
203
    short maxlb;
 
204
    short maxrb;
 
205
    short maxas;
 
206
    short maxds;
 
207
    short rbearing;
 
208
} bbx_t;
 
209
 
 
210
static bbx_t bbx;
 
211
 
 
212
/*
 
213
 * The buffer used to transfer the temporary file to the actual output file.
 
214
 */
 
215
#define TTF2BDF_IOBUFSIZ 8192
 
216
static char iobuf[TTF2BDF_IOBUFSIZ];
 
217
 
 
218
/*
 
219
 * The Units Per Em value used in numerous places.
 
220
 */
 
221
static TT_UShort upm;
 
222
 
 
223
/*
 
224
 * A flag indicating if a CMap was found or not.
 
225
 */
 
226
static TT_UShort nocmap;
 
227
 
 
228
/*
 
229
 * The scaling factor needed to compute the SWIDTH (scalable width) value
 
230
 * for BDF glyphs.
 
231
 */
 
232
static double swscale;
 
233
 
 
234
/*
 
235
 * Mac encoding names used when creating the BDF XLFD font name.
 
236
 */
 
237
static char *mac_encodings[] = {
 
238
    "-MacRoman-0",    "-MacJapanese-0",   "-MacChinese-0",   "-MacKorean-0",
 
239
    "-MacArabic-0",   "-MacHebrew-0",     "-MacGreek-0",     "-MacRussian-0",
 
240
    "-MacRSymbol-0",  "-MacDevanagari-0", "-MacGurmukhi-0",  "-MacGujarati-0",
 
241
    "-MacOriya-0",    "-MacBengali-0",    "-MacTamil-0",     "-MacTelugu-0",
 
242
    "-MacKannada-0",  "-MacMalayalam-0",  "-MacSinhalese-0", "-MacBurmese-0",
 
243
    "-MacKhmer-0",    "-MacThai-0",       "-MacLaotian-0",   "-MacGeorgian-0",
 
244
    "-MacArmenian-0", "-MacMaldivian-0",  "-MacTibetan-0",   "-MacMongolian-0",
 
245
    "-MacGeez-0",     "-MacSlavic-0",     "-MacVietnamese-0","-MacSindhi-0",
 
246
    "-MacUninterp-0"
 
247
};
 
248
static int num_mac_encodings = sizeof(mac_encodings) /
 
249
                               sizeof(mac_encodings[0]);
 
250
 
 
251
/*
 
252
 * ISO encoding names used when creating the BDF XLFD font name.
 
253
 */
 
254
static char *iso_encodings[] = {
 
255
    "-ASCII-0", "-ISO10646-0", "-ISO8859-1"
 
256
};
 
257
static int num_iso_encodings = sizeof(iso_encodings) /
 
258
                               sizeof(iso_encodings[0]);
 
259
 
 
260
/*
 
261
 * Microsoft encoding names used when creating the BDF XLFD font name.
 
262
 */
 
263
static char *ms_encodings[] = {
 
264
    "-Symbol-0", "-ISO10646-1", "-ShiftJIS-0", "-GB2312.1980-0", "-Big5-0",
 
265
    "-KSC5601.1987-0", "-KSC5601.1992-0"
 
266
};
 
267
static int num_ms_encodings = sizeof(ms_encodings) /
 
268
                              sizeof(ms_encodings[0]);
 
269
 
 
270
/*
 
271
 * The propery names for all the XLFD properties.
 
272
 */
 
273
static char *xlfd_props[] = {
 
274
    "FOUNDRY",
 
275
    "FAMILY_NAME",
 
276
    "WEIGHT_NAME",
 
277
    "SLANT",
 
278
    "SETWIDTH_NAME",
 
279
    "ADD_STYLE_NAME",
 
280
    "PIXEL_SIZE",
 
281
    "POINT_SIZE",
 
282
    "RESOLUTION_X",
 
283
    "RESOLUTION_Y",
 
284
    "SPACING",
 
285
    "AVERAGE_WIDTH",
 
286
    "CHARSET_REGISTRY",
 
287
    "CHARSET_ENCODING",
 
288
};
 
289
 
 
290
/**************************************************************************
 
291
 *
 
292
 * Freetype globals.
 
293
 *
 
294
 **************************************************************************/
 
295
 
 
296
static TT_Engine engine;
 
297
static TT_Face face;
 
298
static TT_Face_Properties properties;
 
299
 
 
300
static TT_Instance instance;
 
301
 
 
302
static TT_Glyph glyph;
 
303
static TT_Glyph_Metrics metrics;
 
304
static TT_Instance_Metrics imetrics;
 
305
 
 
306
static TT_Raster_Map raster;
 
307
 
 
308
static TT_CharMap cmap;
 
309
 
 
310
/**************************************************************************
 
311
 *
 
312
 * Freetype related code.
 
313
 *
 
314
 **************************************************************************/
 
315
 
 
316
/*
 
317
 * A generic routine to get a name from the TT name table.  This routine
 
318
 * always looks for English language names and checks three possibilities:
 
319
 * 1. English names with the MS Unicode encoding ID.
 
320
 * 2. English names with the MS unknown encoding ID.
 
321
 * 3. English names with the Apple Unicode encoding ID.
 
322
 *
 
323
 * The particular name ID mut be provided (e.g. nameID = 0 for copyright
 
324
 * string, nameID = 6 for Postscript name, nameID = 1 for typeface name.
 
325
 *
 
326
 * If the `dash' flag is non-zero, all dashes (-) in the name will be replaced
 
327
 * with the character passed.
 
328
 *
 
329
 * Returns the number of bytes added.
 
330
 */
 
331
static int
 
332
#ifdef __STDC__
 
333
ttf_get_english_name(char *name, int nameID, int dash)
 
334
#else
 
335
ttf_get_english_name(name, nameID, dash)
 
336
char *name;
 
337
int nameID, dash;
 
338
#endif
 
339
{
 
340
    TT_UShort slen;
 
341
    int i, j, encid, nrec;
 
342
    unsigned short nrPlatformID, nrEncodingID, nrLanguageID, nrNameID;
 
343
    char *s;
 
344
 
 
345
    nrec = TT_Get_Name_Count(face);
 
346
 
 
347
    for (encid = 1, j = 0; j < 2; j++, encid--) {
 
348
        /*
 
349
         * Locate one of the MS English font names.
 
350
         */
 
351
        for (i = 0; i < nrec; i++) {
 
352
            TT_Get_Name_ID(face, i, &nrPlatformID, &nrEncodingID,
 
353
                           &nrLanguageID, &nrNameID);
 
354
            if (nrPlatformID == 3 &&
 
355
                nrEncodingID == encid &&
 
356
                nrNameID == nameID &&
 
357
                (nrLanguageID == 0x0409 || nrLanguageID == 0x0809 ||
 
358
                 nrLanguageID == 0x0c09 || nrLanguageID == 0x1009 ||
 
359
                 nrLanguageID == 0x1409 || nrLanguageID == 0x1809)) {
 
360
                TT_Get_Name_String(face, i, &s, &slen);
 
361
                break;
 
362
            }
 
363
        }
 
364
 
 
365
        if (i < nrec) {
 
366
            /*
 
367
             * Found one of the MS English font names.  The name is by
 
368
             * definition encoded in Unicode, so copy every second byte into
 
369
             * the `name' parameter, assuming there is enough space.
 
370
             */
 
371
            for (i = 1; s != 0 && i < slen; i += 2) {
 
372
                if (dash)
 
373
                  *name++ = (s[i] == '-' || s[i] == ' ') ? dash : s[i];
 
374
                else if (s[i] == '\r' || s[i] == '\n') {
 
375
                    if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
 
376
                      i += 2;
 
377
                    *name++ = ' ';
 
378
                    *name++ = ' ';
 
379
                } else
 
380
                  *name++ = s[i];
 
381
            }
 
382
            *name = 0;
 
383
            return (slen >> 1);
 
384
        }
 
385
    }
 
386
 
 
387
    /*
 
388
     * No MS English name found, attempt to find an Apple Unicode English
 
389
     * name.
 
390
     */
 
391
    for (i = 0; i < nrec; i++) {
 
392
        TT_Get_Name_ID(face, i, &nrPlatformID, &nrEncodingID,
 
393
                       &nrLanguageID, &nrNameID);
 
394
        if (nrPlatformID == 0 && nrLanguageID == 0 &&
 
395
            nrNameID == nameID) {
 
396
            TT_Get_Name_String(face, i, &s, &slen);
 
397
            break;
 
398
        }
 
399
    }
 
400
 
 
401
    if (i < nrec) {
 
402
        /*
 
403
         * Found the Apple Unicode English name.  The name is by definition
 
404
         * encoded in Unicode, so copy every second byte into the `name'
 
405
         * parameter, assuming there is enough space.
 
406
         */
 
407
        for (i = 1; s != 0 && i < slen; i += 2) {
 
408
            if (dash)
 
409
              *name++ = (s[i] == '-' || s[i] == ' ') ? dash : s[i];
 
410
            else if (s[i] == '\r' || s[i] == '\n') {
 
411
                if (s[i] == '\r' && i + 2 < slen && s[i + 2] == '\n')
 
412
                  i += 2;
 
413
                *name++ = ' ';
 
414
                *name++ = ' ';
 
415
            } else
 
416
              *name++ = s[i];
 
417
        }
 
418
        *name = 0;
 
419
        return (slen >> 1);
 
420
    }
 
421
 
 
422
    return 0;
 
423
}
 
424
 
 
425
/**************************************************************************
 
426
 *
 
427
 * General code.
 
428
 *
 
429
 **************************************************************************/
 
430
 
 
431
/*
 
432
 * Create an XLFD name.  Assumes there is enough space in the string passed
 
433
 * to fit a reasonably long XLFD name into, up to the 256 byte maximum.
 
434
 */
 
435
static void
 
436
#ifdef __STDC__
 
437
make_xlfd_name(char *name, TT_Long awidth, int ismono)
 
438
#else
 
439
make_xlfd_name(name, awidth, ismono)
 
440
char *name;
 
441
TT_Long awidth;
 
442
int ismono;
 
443
#endif
 
444
{
 
445
    TT_Long i;
 
446
    TT_ULong val;
 
447
    char *r, *e;
 
448
    double dr, dp;
 
449
 
 
450
    /*
 
451
     * Default the foundry name to "FreeType" in honor of the project and
 
452
     * because the foundry name is too difficult to automatically determine
 
453
     * from the names in TT fonts. But the user can provide his own.
 
454
     */
 
455
    if (foundry_name == 0) {
 
456
        (void) strcpy(name, "-FreeType");
 
457
        name += 9;
 
458
    } else {
 
459
        *(name++)='-';
 
460
        strcpy(name,foundry_name);
 
461
        name+=strlen(foundry_name);
 
462
    }
 
463
 
 
464
    /*
 
465
     * Add the typeface name from the font.  The fallback default will be
 
466
     * "Unknown".
 
467
     */
 
468
    *name++ = '-';
 
469
    if (face_name == 0) {
 
470
        if((i = ttf_get_english_name(name, TTF_TYPEFACE, dashchar)))
 
471
          name += i;
 
472
        else {
 
473
            (void) strcpy(name, "Unknown");
 
474
            name += 7;
 
475
        }
 
476
    } else {
 
477
        (void) strcpy(name, face_name);
 
478
        name += strlen(face_name);
 
479
    }
 
480
 
 
481
    /*
 
482
     * Add the weight name.  The default will be "Medium".
 
483
     */
 
484
    if (weight_name != 0) {
 
485
        sprintf(name, "-%s", weight_name);
 
486
        name += strlen(weight_name) + 1;
 
487
    } else {
 
488
        if (properties.os2->fsSelection & 0x20) {
 
489
            (void) strcpy(name, "-Bold");
 
490
            name += 5;
 
491
        } else {
 
492
            (void) strcpy(name, "-Medium");
 
493
            name += 7;
 
494
        }
 
495
    }
 
496
 
 
497
    /*
 
498
     * Add the slant name.  The default will be 'R'.
 
499
     */
 
500
    if (slant_name) {
 
501
        sprintf(name, "-%s", slant_name);
 
502
        name += strlen(slant_name) + 1;
 
503
    } else {
 
504
        *name++ = '-';
 
505
        if (properties.os2->fsSelection & 0x01)
 
506
          *name++ = 'I';
 
507
        else
 
508
          *name++ = 'R';
 
509
    }
 
510
 
 
511
    /*
 
512
     * Default the setwidth name to "Normal" but user can specify one.
 
513
     */
 
514
    if (width_name == 0) {
 
515
        (void) strcpy(name, "-Normal");
 
516
        name += 7;
 
517
    } else {
 
518
        *(name++)='-';
 
519
        strcpy(name,width_name);
 
520
        name+=strlen(width_name);
 
521
    }
 
522
 
 
523
    /*
 
524
     * Default the additional style name to NULL but user can specify one.
 
525
     */
 
526
    *name++ = '-';
 
527
    if (style_name != 0) {
 
528
        strcpy(name,style_name);
 
529
        name+=strlen(style_name);
 
530
    }
 
531
 
 
532
    /*
 
533
     * Determine the pixel size from the point size and resolution.
 
534
     */
 
535
    dr = (double) vres;
 
536
    dp = (double) (point_size * 10);
 
537
    val = (unsigned long) (((dp * dr) / 722.7) + 0.5);
 
538
 
 
539
    /*
 
540
     * Set the pixel size, point size, and resolution.
 
541
     */
 
542
    sprintf(name, "-%ld-%d-%d-%d", val, point_size * 10, hres, vres);
 
543
    name += strlen(name);
 
544
 
 
545
    switch (spacing) {
 
546
      case 'p': case 'P': spacing = 'P'; break;
 
547
      case 'm': case 'M': spacing = 'M'; break;
 
548
      case 'c': case 'C': spacing = 'C'; break;
 
549
      default: spacing = 0; break;
 
550
    }
 
551
 
 
552
    /*
 
553
     * Set the spacing.
 
554
     */
 
555
    if (!spacing)
 
556
      spacing = (ismono) ? 'M' : 'P';
 
557
    *name++ = '-';
 
558
    *name++ = spacing;
 
559
 
 
560
    /*
 
561
     * Add the average width.
 
562
     */
 
563
    sprintf(name, "-%ld", awidth);
 
564
    name += strlen(name);
 
565
 
 
566
    /*
 
567
     * Check to see if the remapping table specified a registry and encoding
 
568
     * and use those if they both exist.
 
569
     */
 
570
    ttf2bdf_remap_charset(&r, &e);
 
571
    if (r != 0 && e != 0) {
 
572
        sprintf(name, "-%s-%s", r, e);
 
573
        return;
 
574
    }
 
575
 
 
576
    /*
 
577
     * If the cmap for the platform and encoding id was not found, or the
 
578
     * platform id is unknown, assume the character set registry and encoding
 
579
     * are the XLFD default.
 
580
     */
 
581
    if (nocmap || pid > 3)
 
582
      (void) strcpy(name, DEFAULT_XLFD_CSET);
 
583
    else {
 
584
        /*
 
585
         * Finally, determine the character set registry and encoding from the
 
586
         * platform and encoding ID.
 
587
         */
 
588
        switch (pid) {
 
589
          case 0:
 
590
            /*
 
591
             * Apple Unicode platform, so "Unicode-2.0" is the default.
 
592
             */
 
593
            (void) strcpy(name, "-Unicode-2.0");
 
594
            break;
 
595
          case 1:
 
596
            /*
 
597
             * Macintosh platform, so choose from the Macintosh encoding
 
598
             * strings.
 
599
             */
 
600
            if (eid < 0 || eid >= num_mac_encodings)
 
601
              (void) strcpy(name, DEFAULT_XLFD_CSET);
 
602
            else
 
603
              (void) strcpy(name, mac_encodings[eid]);
 
604
            break;
 
605
          case 2:
 
606
            /*
 
607
             * ISO platform, so choose from the ISO encoding strings.
 
608
             */
 
609
            if (eid < 0 || eid >= num_iso_encodings)
 
610
              (void) strcpy(name, DEFAULT_XLFD_CSET);
 
611
            else
 
612
              (void) strcpy(name, iso_encodings[eid]);
 
613
            break;
 
614
          case 3:
 
615
            /*
 
616
             * Microsoft platform, so choose from the MS encoding strings.
 
617
             */
 
618
            if (eid < 0 || eid >= num_ms_encodings)
 
619
              (void) strcpy(name, DEFAULT_XLFD_CSET);
 
620
            else
 
621
              (void) strcpy(name, ms_encodings[eid]);
 
622
            break;
 
623
        }
 
624
    }
 
625
}
 
626
 
 
627
static int
 
628
#ifdef __STDC__
 
629
generate_font(FILE *out, char *iname, char *oname)
 
630
#else
 
631
generate_font(out, iname, oname)
 
632
FILE *out;
 
633
char *iname, *oname;
 
634
#endif
 
635
{
 
636
    int eof, ismono, i;
 
637
    FILE *tmp;
 
638
    TT_Short maxx, maxy, minx, miny, xoff, yoff, dwidth, swidth;
 
639
    TT_Short y_off, x_off;
 
640
    TT_UShort sx, sy, ex, ey, wd, ht;
 
641
    TT_Long code, idx, ng, aw;
 
642
    TT_UShort remapped_code;
 
643
    unsigned char *bmap;
 
644
    double dw;
 
645
    char *xp, xlfd[256];
 
646
    char *tmpdir, tmpfile[BUFSIZ];
 
647
 
 
648
    /*
 
649
     * Open a temporary file to store the bitmaps in until the exact number
 
650
     * of bitmaps are known.
 
651
     */
 
652
    if ((tmpdir = getenv("TMPDIR")) == 0)
 
653
      tmpdir = "/tmp";
 
654
    sprintf(tmpfile, "%s/ttf2bdf%ld", tmpdir, (long) getpid());
 
655
    if ((tmp = fopen(tmpfile, "w")) == 0) {
 
656
        fprintf(stderr, "%s: unable to open temporary file '%s'.\n",
 
657
                prog, tmpfile);
 
658
        return -1;
 
659
    }
 
660
 
 
661
    /*
 
662
     * Calculate the scale factor for the SWIDTH field.
 
663
     */
 
664
    swscale = ((double) vres) * ((double) point_size);
 
665
 
 
666
    /*
 
667
     * Calculate the font bounding box again so enough storage for the largest
 
668
     * bitmap can be allocated.
 
669
     */
 
670
    minx = (properties.header->xMin * imetrics.x_ppem) / upm;
 
671
    miny = (properties.header->yMin * imetrics.y_ppem) / upm;
 
672
    maxx = (properties.header->xMax * imetrics.x_ppem) / upm;
 
673
    maxy = (properties.header->yMax * imetrics.y_ppem) / upm;
 
674
 
 
675
    maxx -= minx; ++maxx;
 
676
    maxy -= miny; ++maxy;
 
677
 
 
678
    /*
 
679
     * Initialize the flag that tracks if the font is monowidth or not and
 
680
     * initialize the glyph width variable that is used for testing for a
 
681
     * monowidth font.
 
682
     */
 
683
    wd = 0xffff;
 
684
    ismono = 1;
 
685
 
 
686
    /*
 
687
     * Use the upward flow because the version of FreeType being used when
 
688
     * this was written did not support TT_Flow_Down.  This insures that this
 
689
     * routine will not mess up if TT_Flow_Down is implemented at some point.
 
690
     */
 
691
    raster.flow = TT_Flow_Up;
 
692
    raster.width = maxx;
 
693
    raster.rows = maxy;
 
694
    raster.cols = (maxx + 7) >> 3;
 
695
    raster.size = raster.cols * raster.rows;
 
696
    raster.bitmap = (void *) malloc(raster.size);
 
697
 
 
698
    for (ng = code = 0, eof = 0, aw = 0; eof != EOF && code < 0xffff; code++) {
 
699
 
 
700
        /*
 
701
         * If a remap is indicated, attempt to remap the code.  If a remapped
 
702
         * code is not found, then skip generating the glyph.
 
703
         */
 
704
        remapped_code = (TT_UShort) code;
 
705
        if (do_remap && !ttf2bdf_remap(&remapped_code))
 
706
          continue;
 
707
 
 
708
        /*
 
709
         * If a subset is being generated and the code is greater than the max
 
710
         * code of the subset, break out of the loop to avoid doing any more
 
711
         * work.
 
712
         */
 
713
        if (do_subset && remapped_code > maxcode)
 
714
          break;
 
715
 
 
716
        /*
 
717
         * If a subset is being generated and the index is not in the subset
 
718
         * bitmap, just continue.
 
719
         */
 
720
        if (do_subset &&
 
721
            !(subset[remapped_code >> 5] & (1 << (remapped_code & 31))))
 
722
          continue;
 
723
 
 
724
        if (nocmap) {
 
725
            if (code >= properties.num_Glyphs)
 
726
 
 
727
              /*
 
728
               * At this point, all the glyphs are done.
 
729
               */
 
730
              break;
 
731
            idx = code;
 
732
        } else
 
733
          idx = TT_Char_Index(cmap, code);
 
734
 
 
735
        /*
 
736
         * If the glyph could not be loaded for some reason, or a subset is
 
737
         * being generated and the index is not in the subset bitmap, just
 
738
         * continue.
 
739
         */
 
740
 
 
741
        if (idx <= 0 || TT_Load_Glyph(instance, glyph, idx, load_flags))
 
742
          continue;
 
743
 
 
744
        (void) TT_Get_Glyph_Metrics(glyph, &metrics);
 
745
 
 
746
        /*
 
747
         * Clear the raster bitmap.
 
748
         */
 
749
        (void) memset((char *) raster.bitmap, 0, raster.size);
 
750
 
 
751
        /*
 
752
         * Grid fit to determine the x and y offsets that will force the
 
753
         * bitmap to fit into the storage provided.
 
754
         */
 
755
        xoff = (63 - metrics.bbox.xMin) & -64;
 
756
        yoff = (63 - metrics.bbox.yMin) & -64;
 
757
 
 
758
        /*
 
759
         * If the bitmap cannot be generated, simply continue.
 
760
         */
 
761
        if (TT_Get_Glyph_Bitmap(glyph, &raster, xoff, yoff))
 
762
          continue;
 
763
 
 
764
        /*
 
765
         * Determine the DWIDTH (device width, or advance width in TT terms)
 
766
         * and the SWIDTH (scalable width) values.
 
767
         */
 
768
        dwidth = metrics.advance >> 6;
 
769
        dw = (double) dwidth;
 
770
        swidth = (TT_Short) ((dw * 72000.0) / swscale);
 
771
 
 
772
        /*
 
773
         * Determine the actual bounding box of the glyph bitmap.  Do not
 
774
         * forget that the glyph is rendered upside down!
 
775
         */
 
776
        sx = ey = 0xffff;
 
777
        sy = ex = 0;
 
778
        bmap = (unsigned char *) raster.bitmap;
 
779
        for (miny = 0; miny < raster.rows; miny++) {
 
780
            for (minx = 0; minx < raster.width; minx++) {
 
781
                if (bmap[(miny * raster.cols) + (minx >> 3)] &
 
782
                    (0x80 >> (minx & 7))) {
 
783
                    if (minx < sx)
 
784
                      sx = minx;
 
785
                    if (minx > ex)
 
786
                      ex = minx;
 
787
                    if (miny > sy)
 
788
                      sy = miny;
 
789
                    if (miny < ey)
 
790
                      ey = miny;
 
791
                }
 
792
            }
 
793
        }
 
794
 
 
795
        /*
 
796
         * If the glyph is actually an empty bitmap, set the size to 0 all
 
797
         * around.
 
798
         */
 
799
        if (sx == 0xffff && ey == 0xffff && sy == 0 && ex == 0)
 
800
          sx = ex = sy = ey = 0;
 
801
 
 
802
        /*
 
803
         * Increment the number of glyphs generated.
 
804
         */
 
805
        ng++;
 
806
 
 
807
        /*
 
808
         * Test to see if the font is going to be monowidth or not by
 
809
         * comparing the current glyph width against the last one.
 
810
         */
 
811
        if (ismono && (ex - sx) + 1 != wd)
 
812
          ismono = 0;
 
813
 
 
814
        /*
 
815
         * Adjust the font bounding box.
 
816
         */
 
817
        wd = (ex - sx) + 1;
 
818
        ht = (sy - ey) + 1;
 
819
        x_off = sx - (xoff >> 6);
 
820
        y_off = ey - (yoff >> 6);
 
821
 
 
822
        bbx.maxas = MAX(bbx.maxas, ht + y_off);
 
823
        bbx.maxds = MAX(bbx.maxds, -y_off);
 
824
        bbx.rbearing = wd + x_off;
 
825
        bbx.maxrb = MAX(bbx.maxrb, bbx.rbearing);
 
826
        bbx.minlb = MIN(bbx.minlb, x_off);
 
827
        bbx.maxlb = MAX(bbx.maxlb, x_off);
 
828
 
 
829
        /*
 
830
         * Add to the average width accumulator.
 
831
         */
 
832
        aw += wd;
 
833
 
 
834
        /*
 
835
         * Print the bitmap header.
 
836
         */
 
837
        fprintf(tmp, "STARTCHAR %04lX\nENCODING %ld\n", code,
 
838
                (long) remapped_code);
 
839
        fprintf(tmp, "SWIDTH %hd 0\n", swidth);
 
840
        fprintf(tmp, "DWIDTH %hd 0\n", dwidth);
 
841
        fprintf(tmp, "BBX %hd %hd %hd %hd\n", wd, ht, x_off, y_off);
 
842
 
 
843
        /*
 
844
         * Check for an error return here in case the temporary file system
 
845
         * fills up or the file is deleted while it is being used.
 
846
         */
 
847
        eof = fprintf(tmp, "BITMAP\n");
 
848
 
 
849
        /*
 
850
         * Now collect the bits so they can be printed.
 
851
         */
 
852
        for (miny = sy; eof != EOF && miny >= ey; miny--) {
 
853
            for (idx = 0, minx = sx; eof != EOF && minx <= ex; minx++) {
 
854
                if (minx > sx && ((minx - sx) & 7) == 0) {
 
855
                    /*
 
856
                     * Print the next byte.
 
857
                     */
 
858
                    eof = fprintf(tmp, "%02lX", idx & 0xff);
 
859
                    idx = 0;
 
860
                }
 
861
                if (bmap[(miny * raster.cols) + (minx >> 3)] &
 
862
                    (0x80 >> (minx & 7)))
 
863
                  idx |= 0x80 >> ((minx - sx) & 7);
 
864
            }
 
865
            if (eof != EOF)
 
866
              /*
 
867
               * Because of the structure of the loop, the last byte should
 
868
               * always be printed.
 
869
               */
 
870
              fprintf(tmp, "%02lX\n", idx & 0xff);
 
871
        }
 
872
        if (eof != EOF)
 
873
          fprintf(tmp, "ENDCHAR\n");
 
874
    }
 
875
 
 
876
    fclose(tmp);
 
877
 
 
878
    /*
 
879
     * If a write error occured, delete the temporary file and issue an error
 
880
     * message.
 
881
     */
 
882
    if (eof == EOF) {
 
883
        (void) unlink(tmpfile);
 
884
        fprintf(stderr, "%s: problem writing to temporary file '%s'.\n",
 
885
                prog, tmpfile);
 
886
        if (raster.size > 0)
 
887
          free((char *) raster.bitmap);
 
888
        return -1;
 
889
    }
 
890
 
 
891
    /*
 
892
     * If no characters were generated, just unlink the temp file and issue a
 
893
     * warning.
 
894
     */
 
895
    if (ng == 0) {
 
896
        (void) unlink(tmpfile);
 
897
        fprintf(stderr, "%s: no glyphs generated from '%s'.\n", prog, iname);
 
898
        if (raster.size > 0)
 
899
          free((char *) raster.bitmap);
 
900
        return -1;
 
901
    }
 
902
 
 
903
    /*
 
904
     * Reopen the temporary file so it can be copied to the actual output
 
905
     * file.
 
906
     */
 
907
    if ((tmp = fopen(tmpfile, "r")) == 0) {
 
908
        /*
 
909
         * Unable to open the file for read, so attempt to delete it and issue
 
910
         * an error message.
 
911
         */
 
912
        (void) unlink(tmpfile);
 
913
        fprintf(stderr, "%s: unable to open temporary file '%s' for read.\n",
 
914
                prog, tmpfile);
 
915
        if (raster.size > 0)
 
916
          free((char *) raster.bitmap);
 
917
        return -1;
 
918
    }
 
919
 
 
920
    /*
 
921
     * Free up the raster storage.
 
922
     */
 
923
    if (raster.size > 0)
 
924
      free((char *) raster.bitmap);
 
925
 
 
926
    /*
 
927
     * Calculate the average width.
 
928
     */
 
929
    aw = (TT_Long) ((((double) aw / (double) ng) + 0.5) * 10.0);
 
930
 
 
931
    /*
 
932
     * Generate the XLFD font name.
 
933
     */
 
934
    make_xlfd_name(xlfd, aw, ismono);
 
935
 
 
936
    /*
 
937
     * Start writing the font out.
 
938
     */
 
939
    fprintf(out, "STARTFONT 2.1\n");
 
940
 
 
941
    /*
 
942
     * Add the vanity comments.
 
943
     */
 
944
    fprintf(out, "COMMENT\n");
 
945
    fprintf(out, "COMMENT Converted from TrueType font \"%s\" by \"%s %s\".\n",
 
946
            iname, prog, TTF2BDF_VERSION);
 
947
    fprintf(out, "COMMENT\n");
 
948
 
 
949
    fprintf(out, "FONT %s\n", xlfd);
 
950
    fprintf(out, "SIZE %d %d %d\n", point_size, hres, vres);
 
951
 
 
952
    /*
 
953
     * Generate the font bounding box.
 
954
     */
 
955
    fprintf(out, "FONTBOUNDINGBOX %hd %hd %hd %hd\n",
 
956
            bbx.maxrb - bbx.minlb, bbx.maxas + bbx.maxds,
 
957
            bbx.minlb, -bbx.maxds);
 
958
 
 
959
    /*
 
960
     * Print the properties.
 
961
     */
 
962
    fprintf(out, "STARTPROPERTIES %hd\n", 19);
 
963
 
 
964
    /*
 
965
     * Print the font properties from the XLFD name.
 
966
     */
 
967
    for (i = 0, xp = xlfd; i < 14; i++) {
 
968
        /*
 
969
         * Print the XLFD property name.
 
970
         */
 
971
        fprintf(out, "%s ", xlfd_props[i]);
 
972
 
 
973
        /*
 
974
         * Make sure the ATOM properties are wrapped in double quotes.
 
975
         */
 
976
        if (i < 6 || i == 10 || i > 11)
 
977
          putc('"', out);
 
978
 
 
979
        /*
 
980
         * Skip the leading '-' in the XLFD name.
 
981
         */
 
982
        xp++;
 
983
 
 
984
        /*
 
985
         * Skip until the next '-' or NULL.
 
986
         */
 
987
        for (; *xp && *xp != '-'; xp++)
 
988
          putc(*xp, out);
 
989
 
 
990
        /*
 
991
         * Make sure the ATOM properties are wrapped in double quotes.
 
992
         */
 
993
        if (i < 6 || i == 10 || i > 11)
 
994
          putc('"', out);
 
995
 
 
996
        putc('\n', out);
 
997
    }
 
998
 
 
999
    /*
 
1000
     * Make sure to add the FONT_ASCENT and FONT_DESCENT properties
 
1001
     * because X11 can not live without them.
 
1002
     */
 
1003
    fprintf(out, "FONT_ASCENT %hd\nFONT_DESCENT %hd\n",
 
1004
            (properties.horizontal->Ascender * imetrics.y_ppem) / upm,
 
1005
            -((properties.horizontal->Descender * imetrics.y_ppem) / upm));
 
1006
 
 
1007
    /*
 
1008
     * Get the copyright string from the font.
 
1009
     */
 
1010
    (void) ttf_get_english_name(xlfd, TTF_COPYRIGHT, 0);
 
1011
    fprintf(out, "COPYRIGHT \"%s\"\n", xlfd);
 
1012
 
 
1013
    /*
 
1014
     * Last, print the two user-defined properties _TTF_FONTFILE and
 
1015
     * _TTF_PSNAME.  _TTF_FONTFILE provides a reference to the original TT
 
1016
     * font file which some systems can take advantage of, and _TTF_PSNAME
 
1017
     * provides the Postscript name of the font if it exists.
 
1018
     */
 
1019
    (void) ttf_get_english_name(xlfd, TTF_PSNAME, 0);
 
1020
    fprintf(out, "_TTF_FONTFILE \"%s\"\n_TTF_PSNAME \"%s\"\n", iname, xlfd);
 
1021
 
 
1022
    fprintf(out, "ENDPROPERTIES\n");
 
1023
 
 
1024
    /*
 
1025
     * Print the actual number of glyphs to the output file.
 
1026
     */
 
1027
    eof = fprintf(out, "CHARS %ld\n", ng);
 
1028
 
 
1029
    /*
 
1030
     * Copy the temporary file to the output file.
 
1031
     */
 
1032
    while (eof != EOF && (ng = fread(iobuf, 1, TTF2BDF_IOBUFSIZ, tmp))) {
 
1033
        if (fwrite(iobuf, 1, ng, out) == 0)
 
1034
          eof = EOF;
 
1035
    }
 
1036
        
 
1037
    /*
 
1038
     * Close the temporary file and delete it.
 
1039
     */
 
1040
    fclose(tmp);
 
1041
    (void) unlink(tmpfile);
 
1042
 
 
1043
    /*
 
1044
     * If an error occured when writing to the output file, issue a warning
 
1045
     * and return.
 
1046
     */
 
1047
    if (eof == EOF) {
 
1048
        fprintf(stderr, "%s: problem writing to output file '%s'.\n",
 
1049
                prog, oname);
 
1050
        if (raster.size > 0)
 
1051
          free((char *) raster.bitmap);
 
1052
        return -1;
 
1053
    }
 
1054
 
 
1055
    /*
 
1056
     * End the font and do memory cleanup on the glyph and raster structures.
 
1057
     */
 
1058
    eof = fprintf(out, "ENDFONT\n");
 
1059
 
 
1060
    return eof;
 
1061
}
 
1062
 
 
1063
static int
 
1064
#ifdef __STDC__
 
1065
generate_bdf(FILE *out, char *iname, char *oname)
 
1066
#else
 
1067
generate_bdf(out, iname, oname)
 
1068
FILE *out;
 
1069
char *iname, *oname;
 
1070
#endif
 
1071
{
 
1072
    TT_Long i;
 
1073
    TT_UShort p, e;
 
1074
 
 
1075
    /*
 
1076
     * Get the requested cmap.
 
1077
     */
 
1078
    for (i = 0; i < TT_Get_CharMap_Count(face); i++) {
 
1079
        if (!TT_Get_CharMap_ID(face, i, &p, &e) &&
 
1080
            p == pid && e == eid)
 
1081
          break;
 
1082
    }
 
1083
    if (i == TT_Get_CharMap_Count(face) && pid == 3 && eid == 1) {
 
1084
        /*
 
1085
         * Make a special case when this fails with pid == 3 and eid == 1.
 
1086
         * Change to eid == 0 and try again.  This captures the two possible
 
1087
         * cases for MS fonts.  Some other method should be used to cycle
 
1088
         * through all the alternatives later.
 
1089
         */
 
1090
        for (i = 0; i < TT_Get_CharMap_Count(face); i++) {
 
1091
            if (!TT_Get_CharMap_ID(face, i, &p, &e) &&
 
1092
                p == pid && e == 0)
 
1093
              break;
 
1094
        }
 
1095
        if (i < TT_Get_CharMap_Count(face)) {
 
1096
            if (!TT_Get_CharMap(face, i, &cmap))
 
1097
              eid = 0;
 
1098
            else
 
1099
              nocmap = 1;
 
1100
        }
 
1101
    } else {
 
1102
        /*
 
1103
         * A CMap was found for the platform and encoding IDs.
 
1104
         */
 
1105
        if (i < TT_Get_CharMap_Count(face) && TT_Get_CharMap(face, i, &cmap))
 
1106
          nocmap = 1;
 
1107
        else
 
1108
          nocmap = 0;
 
1109
    }
 
1110
 
 
1111
    if (nocmap && verbose) {
 
1112
        fprintf(stderr,
 
1113
                    "%s: no character map for platform %d encoding %d.  ",
 
1114
                    prog, pid, eid);
 
1115
        fprintf(stderr, "Generating all glyphs.\n");
 
1116
    }
 
1117
 
 
1118
    /*
 
1119
     * Now go through and generate the glyph bitmaps themselves.
 
1120
     */
 
1121
    return generate_font(out, iname, oname);
 
1122
}
 
1123
 
 
1124
#define isdig(cc) ((cc) >= '0' && (cc) <= '9')
 
1125
 
 
1126
/*
 
1127
 * Routine to parse a subset specification supplied on the command line.
 
1128
 * The syntax for this specification is the same as the syntax used for
 
1129
 * the XLFD font names (XLFD documentation, page 9).
 
1130
 *
 
1131
 * Example:
 
1132
 *
 
1133
 *  "60 70 80_90" means the glyphs at codes 60, 70, and between 80 and
 
1134
 *  90 inclusive.
 
1135
 */
 
1136
static void
 
1137
#ifdef __STDC__
 
1138
parse_subset(char *s)
 
1139
#else
 
1140
parse_subset(s)
 
1141
char *s;
 
1142
#endif
 
1143
{
 
1144
    long l, r;
 
1145
 
 
1146
    /*
 
1147
     * Make sure to clear the flag and bitmap in case more than one subset is
 
1148
     * specified on the command line.
 
1149
     */
 
1150
    maxcode = 0;
 
1151
    do_subset = 0;
 
1152
    (void) memset((char *) subset, 0, sizeof(unsigned long) * 2048);
 
1153
 
 
1154
    while (*s) {
 
1155
        /*
 
1156
         * Collect the next code value.
 
1157
         */
 
1158
        for (l = r = 0; *s && isdig(*s); s++)
 
1159
          l = (l * 10) + (*s - '0');
 
1160
 
 
1161
        /*
 
1162
         * If the next character is an '_', advance and collect the end of the
 
1163
         * specified range.
 
1164
         */
 
1165
        if (*s == '_') {
 
1166
            s++;
 
1167
            for (; *s && isdig(*s); s++)
 
1168
              r = (r * 10) + (*s - '0');
 
1169
        } else
 
1170
          r = l;
 
1171
 
 
1172
        /*
 
1173
         * Add the range just collected to the subset bitmap and set the flag
 
1174
         * that indicates a subset is wanted.
 
1175
         */
 
1176
        for (; l <= r; l++) {
 
1177
            do_subset = 1;
 
1178
            subset[l >> 5] |= (1 << (l & 31));
 
1179
            if (l > maxcode)
 
1180
              maxcode = l;
 
1181
        }
 
1182
 
 
1183
        /*
 
1184
         * Skip all non-digit characters.
 
1185
         */
 
1186
        while (*s && !isdig(*s))
 
1187
          s++;
 
1188
    }
 
1189
}
 
1190
 
 
1191
static void
 
1192
#ifdef __STDC__
 
1193
usage(int eval)
 
1194
#else
 
1195
usage(eval)
 
1196
int eval;
 
1197
#endif
 
1198
{
 
1199
    fprintf(stderr, "Usage: %s [options below] font.ttf\n", prog);
 
1200
    fprintf(stderr, "-h\t\tThis message.\n");
 
1201
    fprintf(stderr, "-v\t\tPrint warning messages during conversion.\n");
 
1202
    fprintf(stderr,
 
1203
            "-l \"subset\"\tSpecify a subset of glyphs to generate.\n");
 
1204
    fprintf(stderr, "-m mapfile\tGlyph reencoding file.\n");
 
1205
    fprintf(stderr, "-n\t\tTurn off glyph hinting.\n");
 
1206
    fprintf(stderr,
 
1207
            "-c c\t\tSet the character spacing (default: from font).\n");
 
1208
    fprintf(stderr,
 
1209
            "-f name\t\tSet the foundry name (default: freetype).\n");
 
1210
    fprintf(stderr,
 
1211
            "-t name\t\tSet the typeface name (default: from font).\n");
 
1212
    fprintf(stderr, "-w name\t\tSet the weight name (default: Medium).\n");
 
1213
    fprintf(stderr, "-s name\t\tSet the slant name (default: R).\n");
 
1214
    fprintf(stderr, "-k name\t\tSet the width name (default: Normal).\n");
 
1215
    fprintf(stderr,
 
1216
            "-d name\t\tSet the additional style name (default: empty).\n");
 
1217
    fprintf(stderr, "-u char\t\tSet the character to replace '-' in names ");
 
1218
    fprintf(stderr, "(default: space).\n");
 
1219
    fprintf(stderr,
 
1220
            "-pid id\t\tSet the platform ID for encoding (default: %d).\n",
 
1221
            DEFAULT_PLATFORM_ID);
 
1222
    fprintf(stderr,
 
1223
            "-eid id\t\tSet the encoding ID for encoding (default: %d).\n",
 
1224
            DEFAULT_ENCODING_ID);
 
1225
    fprintf(stderr, "-p n\t\tSet the point size (default: %dpt).\n",
 
1226
            DEFAULT_POINT_SIZE);
 
1227
    fprintf(stderr, "-r n\t\tSet the horizontal and vertical resolution ");
 
1228
    fprintf(stderr, "(default: %ddpi).\n", DEFAULT_RESOLUTION);
 
1229
    fprintf(stderr, "-rh n\t\tSet the horizontal resolution ");
 
1230
    fprintf(stderr, "(default: %ddpi)\n", DEFAULT_RESOLUTION);
 
1231
    fprintf(stderr, "-rv n\t\tSet the vertical resolution ");
 
1232
    fprintf(stderr, "(default: %ddpi)\n", DEFAULT_RESOLUTION);
 
1233
    fprintf(stderr,
 
1234
            "-o outfile\tSet the output filename (default: stdout).\n");
 
1235
    exit(eval);
 
1236
}
 
1237
 
 
1238
int
 
1239
#ifdef __STDC__
 
1240
main(int argc, char *argv[])
 
1241
#else
 
1242
main(argc, argv)
 
1243
int argc;
 
1244
char *argv[];
 
1245
#endif
 
1246
{
 
1247
    int res;
 
1248
    char *infile, *outfile, *iname, *oname;
 
1249
    FILE *out, *mapin;
 
1250
 
 
1251
    if ((prog = strrchr(argv[0], '/')))
 
1252
      prog++;
 
1253
    else
 
1254
      prog = argv[0];
 
1255
 
 
1256
    out = stdout;
 
1257
    infile = outfile = 0;
 
1258
 
 
1259
    argc--;
 
1260
    argv++;
 
1261
 
 
1262
    while (argc > 0) {
 
1263
        if (argv[0][0] == '-') {
 
1264
            switch (argv[0][1]) {
 
1265
              case 'v': case 'V':
 
1266
                verbose = 1;
 
1267
                break;
 
1268
              case 'l': case 'L':
 
1269
                argc--;
 
1270
                argv++;
 
1271
                parse_subset(argv[0]);
 
1272
                break;
 
1273
              case 'n': case 'N':
 
1274
                load_flags &= ~TTLOAD_HINT_GLYPH;
 
1275
                break;
 
1276
              case 'c': case 'C':
 
1277
                argc--;
 
1278
                argv++;
 
1279
                spacing = argv[0][0];
 
1280
                break;
 
1281
              case 't': case 'T':
 
1282
                argc--;
 
1283
                argv++;
 
1284
                face_name = argv[0];
 
1285
                break;
 
1286
              case 'w': case 'W':
 
1287
                argc--;
 
1288
                argv++;
 
1289
                weight_name = argv[0];
 
1290
                break;
 
1291
              case 's': case 'S':
 
1292
                argc--;
 
1293
                argv++;
 
1294
                slant_name = argv[0];
 
1295
                break;
 
1296
              case 'k': case 'K':
 
1297
                argc--;
 
1298
                argv++;
 
1299
                width_name = argv[0];
 
1300
                break;
 
1301
              case 'd': case 'D':
 
1302
                argc--;
 
1303
                argv++;
 
1304
                style_name = argv[0];
 
1305
                break;
 
1306
              case 'f': case 'F':
 
1307
                argc--;
 
1308
                argv++;
 
1309
                foundry_name = argv[0];
 
1310
                break;
 
1311
              case 'u': case 'U':
 
1312
                argc--;
 
1313
                argv++;
 
1314
                dashchar = argv[0][0];
 
1315
                break;
 
1316
              case 'p': case 'P':
 
1317
                res = argv[0][2];
 
1318
                argc--;
 
1319
                argv++;
 
1320
                if (res == 'i' || res == 'I')
 
1321
                  /*
 
1322
                   * Set the platform ID.
 
1323
                   */
 
1324
                  pid = atoi(argv[0]);
 
1325
                else
 
1326
                  /*
 
1327
                   * Set the point size.
 
1328
                   */
 
1329
                  point_size = atoi(argv[0]);
 
1330
                break;
 
1331
              case 'e': case 'E':
 
1332
                /*
 
1333
                 * Set the encoding ID.
 
1334
                 */
 
1335
                argc--;
 
1336
                argv++;
 
1337
                eid = atoi(argv[0]);
 
1338
                break;
 
1339
              case 'r':
 
1340
                /*
 
1341
                 * Set the horizontal and vertical resolutions.
 
1342
                 */
 
1343
                if (argv[0][2] == 'h')
 
1344
                  hres = atoi(argv[1]);
 
1345
                else if (argv[0][2] == 'v')
 
1346
                  vres = atoi(argv[1]);
 
1347
                else
 
1348
                  hres = vres = atoi(argv[1]);
 
1349
                argc--;
 
1350
                argv++;
 
1351
                break;
 
1352
              case 'm': case 'M':
 
1353
                /*
 
1354
                 * Try to load a remap table.
 
1355
                 */
 
1356
                argc--;
 
1357
                argv++;
 
1358
 
 
1359
                /*
 
1360
                 * Always reset the `do_remap' variable here in case more than
 
1361
                 * one map file appears on the command line.
 
1362
                 */
 
1363
                do_remap = 0;
 
1364
                if ((mapin = fopen(argv[0], "r")) == 0)
 
1365
                  fprintf(stderr, "%s: unable to open the remap table '%s'.\n",
 
1366
                          prog, argv[0]);
 
1367
                else {
 
1368
                    if (ttf2bdf_load_map(mapin) < 0) {
 
1369
                        fprintf(stderr,
 
1370
                                "%s: problem loading remap table '%s'.\n",
 
1371
                                prog, argv[0]);
 
1372
                        do_remap = 0;
 
1373
                    } else
 
1374
                      do_remap = 1;
 
1375
                    fclose(mapin);
 
1376
                }
 
1377
                break;
 
1378
              case 'o': case 'O':
 
1379
                /*
 
1380
                 * Set the output file name.
 
1381
                 */
 
1382
                argc--;
 
1383
                argv++;
 
1384
                outfile = argv[0];
 
1385
                break;
 
1386
              default:
 
1387
                usage(1);
 
1388
            }
 
1389
        } else
 
1390
          /*
 
1391
           * Set the input file name.
 
1392
           */
 
1393
          infile = argv[0];
 
1394
 
 
1395
        argc--;
 
1396
        argv++;
 
1397
    }
 
1398
 
 
1399
    /*
 
1400
     * Validate the values passed on the command line.
 
1401
     */
 
1402
    if (infile == 0) {
 
1403
        fprintf(stderr, "%s: no input file provided.\n", prog);
 
1404
        usage(1);
 
1405
    }
 
1406
    /*
 
1407
     * Set the input filename that will be passed to the generator
 
1408
     * routine.
 
1409
     */
 
1410
    if ((iname = strrchr(infile, '/')))
 
1411
      iname++;
 
1412
    else
 
1413
      iname = infile;
 
1414
 
 
1415
    /*
 
1416
     * Check the platform and encoding IDs.
 
1417
     */
 
1418
    if (pid < 0 || pid > 255) {
 
1419
        fprintf(stderr, "%s: invalid platform ID '%d'.\n", prog, pid);
 
1420
        exit(1);
 
1421
    }
 
1422
    if (eid < 0 || eid > 65535) {
 
1423
        fprintf(stderr, "%s: invalid encoding ID '%d'.\n", prog, eid);
 
1424
        exit(1);
 
1425
    }
 
1426
 
 
1427
    /*
 
1428
     * Arbitrarily limit the point size to a minimum of 2pt and maximum of
 
1429
     * 256pt.
 
1430
     */
 
1431
    if (point_size < 2 || point_size > 256) {
 
1432
        fprintf(stderr, "%s: invalid point size '%dpt'.\n", prog, point_size);
 
1433
        exit(1);
 
1434
    }
 
1435
 
 
1436
    /*
 
1437
     * Arbitrarily limit the resolutions to a minimum of 10dpi and a maximum
 
1438
     * of 1200dpi.
 
1439
     */
 
1440
    if (hres < 10 || hres > 1200) {
 
1441
        fprintf(stderr, "%s: invalid horizontal resolution '%ddpi'.\n",
 
1442
                prog, hres);
 
1443
        exit(1);
 
1444
    }
 
1445
    if (vres < 10 || vres > 1200) {
 
1446
        fprintf(stderr, "%s: invalid vertical resolution '%ddpi'.\n",
 
1447
                prog, vres);
 
1448
        exit(1);
 
1449
    }
 
1450
 
 
1451
    /*
 
1452
     * Open the output file if specified.
 
1453
     */
 
1454
    if (outfile != 0) {
 
1455
        /*
 
1456
         * Attempt to open the output file.
 
1457
         */
 
1458
        if ((out = fopen(outfile, "w")) == 0) {
 
1459
            fprintf(stderr, "%s: unable to open the output file '%s'.\n",
 
1460
                    prog, outfile);
 
1461
            exit(1);
 
1462
        }
 
1463
        /*
 
1464
         * Set the output filename to be passed to the generator routine.
 
1465
         */
 
1466
        if ((oname = strrchr(outfile, '/')))
 
1467
          oname++;
 
1468
        else
 
1469
          oname = outfile;
 
1470
    } else
 
1471
      /*
 
1472
       * Set the default output file name to <stdout>.
 
1473
       */
 
1474
      oname = "<stdout>";
 
1475
 
 
1476
    /*
 
1477
     * Intialize Freetype.
 
1478
     */
 
1479
    if ((res = TT_Init_FreeType(&engine))) {
 
1480
        /*
 
1481
         * Close the output file.
 
1482
         */
 
1483
        if (out != stdout) {
 
1484
            fclose(out);
 
1485
            (void) unlink(outfile);
 
1486
        }
 
1487
        fprintf(stderr, "%s[%d]: unable to initialize renderer.\n",
 
1488
                prog, res);
 
1489
        exit(1);
 
1490
    }
 
1491
 
 
1492
    /*
 
1493
     * Open the input file.
 
1494
     */
 
1495
    if ((res = TT_Open_Face(engine, infile, &face))) {
 
1496
        if (out != stdout) {
 
1497
            fclose(out);
 
1498
            (void) unlink(outfile);
 
1499
        }
 
1500
        fprintf(stderr, "%s[%d]: unable to open input file '%s'.\n",
 
1501
                prog, res, infile);
 
1502
        exit(1);
 
1503
    }
 
1504
 
 
1505
    /*
 
1506
     * Create a new instance.
 
1507
     */
 
1508
    if ((res = TT_New_Instance(face, &instance))) {
 
1509
        (void) TT_Close_Face(face);
 
1510
        if (out != stdout) {
 
1511
            fclose(out);
 
1512
            (void) unlink(outfile);
 
1513
        }
 
1514
        fprintf(stderr, "%s[%d]: unable to create instance.\n",
 
1515
                prog, res);
 
1516
        exit(1);
 
1517
    }
 
1518
 
 
1519
    /*
 
1520
     * Set the instance resolution and point size and the relevant
 
1521
     * metrics.
 
1522
     */
 
1523
    (void) TT_Set_Instance_Resolutions(instance, hres, vres);
 
1524
    (void) TT_Set_Instance_CharSize(instance, point_size*64);
 
1525
    (void) TT_Get_Instance_Metrics(instance, &imetrics);
 
1526
 
 
1527
    /*
 
1528
     * Get the face properties and set the global units per em value for
 
1529
     * convenience.
 
1530
     */
 
1531
    (void) TT_Get_Face_Properties(face, &properties);
 
1532
    upm = properties.header->Units_Per_EM;
 
1533
 
 
1534
    /*
 
1535
     * Create a new glyph container.
 
1536
     */
 
1537
    if ((res = TT_New_Glyph(face, &glyph))) {
 
1538
        (void) TT_Done_Instance(instance);
 
1539
        (void) TT_Close_Face(face);
 
1540
        if (out != stdout) {
 
1541
            fclose(out);
 
1542
            (void) unlink(outfile);
 
1543
        }
 
1544
        fprintf(stderr, "%s[%d]: unable to create glyph.\n",
 
1545
                prog, res);
 
1546
        exit(1);
 
1547
    }
 
1548
 
 
1549
    /*
 
1550
     * Generate the BDF font from the TrueType font.
 
1551
     */
 
1552
    res = generate_bdf(out, iname, oname);
 
1553
 
 
1554
    /*
 
1555
     * Free up the mapping table if one was loaded.
 
1556
     */
 
1557
    ttf2bdf_free_map();
 
1558
 
 
1559
    /*
 
1560
     * Close the input and output files.
 
1561
     */
 
1562
    (void) TT_Close_Face(face);
 
1563
    if (out != stdout) {
 
1564
        fclose(out);
 
1565
        if (res < 0)
 
1566
          /*
 
1567
           * An error occured when generating the font, so delete the
 
1568
           * output file.
 
1569
           */
 
1570
          (void) unlink(outfile);
 
1571
    }
 
1572
 
 
1573
    /*
 
1574
     * Shut down the renderer.
 
1575
     */
 
1576
    (void) TT_Done_FreeType(engine);
 
1577
 
 
1578
    exit(res);
 
1579
 
 
1580
    return 0;
 
1581
}