~ubuntu-branches/ubuntu/precise/xfonts-utils/precise

« back to all changes in this revision

Viewing changes to mkfontscale/mkfontscale.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-12-18 17:10:27 UTC
  • mfrom: (1.1.1 upstream) (0.1.2 etch)
  • Revision ID: james.westby@ubuntu.com-20061218171027-ayzuv41s4ufth700
Tags: 1:1.0.1-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu change:
  - debian/control: Replace/Conflict bdftopcf to smooth upgrades
    from 6.06 LTS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (c) 2002-2003 by Juliusz Chroboczek
 
3
 
 
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
 
5
  of this software and associated documentation files (the "Software"), to deal
 
6
  in the Software without restriction, including without limitation the rights
 
7
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
8
  copies of the Software, and to permit persons to whom the Software is
 
9
  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 THE
 
17
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
18
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
19
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
20
  THE SOFTWARE.
 
21
*/
 
22
/* $XdotOrg: xc/programs/mkfontscale/mkfontscale.c,v 1.2 2004/04/23 19:54:36 eich Exp $ */
 
23
/* $XFree86: xc/programs/mkfontscale/mkfontscale.c,v 1.21 2003/12/10 02:58:07 dawes Exp $ */
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
#include <sys/types.h>
 
30
#include <dirent.h>
 
31
#include <unistd.h>
 
32
#include <errno.h>
 
33
 
 
34
#include <X11/Xos.h>
 
35
#include <X11/fonts/fontenc.h>
 
36
#include <ft2build.h>
 
37
#include FT_FREETYPE_H
 
38
#include FT_SFNT_NAMES_H
 
39
#include FT_TRUETYPE_TABLES_H
 
40
#include FT_TRUETYPE_IDS_H
 
41
#include FT_TYPE1_TABLES_H
 
42
#include FT_BDF_H
 
43
#include FT_TRUETYPE_TABLES_H
 
44
 
 
45
#include "list.h"
 
46
#include "hash.h"
 
47
#include "data.h"
 
48
#include "ident.h"
 
49
 
 
50
#ifdef NEED_SNPRINTF
 
51
#undef SCOPE
 
52
#define SCOPE static
 
53
#include "snprintf.c"
 
54
#endif
 
55
 
 
56
#define NPREFIX 1024
 
57
 
 
58
#ifndef MAXFONTFILENAMELEN
 
59
#define MAXFONTFILENAMELEN 1024
 
60
#endif
 
61
#ifndef MAXFONTNAMELEN
 
62
#define MAXFONTNAMELEN 1024
 
63
#endif
 
64
 
 
65
char *encodings_array[] =
 
66
    { "ascii-0",
 
67
      "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
 
68
      "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
 
69
      "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
 
70
      "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
 
71
      "iso8859-15", "iso8859-16",
 
72
      "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
 
73
      "tis620-2",
 
74
      "sun.unicode.india-0", "suneu-greek",
 
75
      "adobe-standard", "adobe-symbol",
 
76
      "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
 
77
      /* But not "adobe-dingbats", as it uses generic glyph names. */
 
78
      "cns11643-1", "cns11643-2", "cns11643-3",
 
79
      "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
 
80
      "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
 
81
      "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
 
82
      "ksc5601.1987-0", "ksc5601.1992-3"};
 
83
 
 
84
char *extra_encodings_array[] =
 
85
    { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
 
86
 
 
87
ListPtr encodings, extra_encodings;
 
88
char *outfilename;
 
89
 
 
90
#define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
 
91
 
 
92
static int doDirectory(char*, int, ListPtr);
 
93
static int checkEncoding(FT_Face face, char *encoding_name);
 
94
static int checkExtraEncoding(FT_Face face, char *encoding_name, int found);
 
95
static int find_cmap(int type, int pid, int eid, FT_Face face);
 
96
static char* notice_foundry(char *notice);
 
97
static char* vendor_foundry(signed char *vendor);
 
98
static int readFontScale(HashTablePtr entries, char *dirname);
 
99
ListPtr makeXLFD(char *filename, FT_Face face, int);
 
100
static int readEncodings(ListPtr encodings, char *dirname);
 
101
 
 
102
static FT_Library ft_library;
 
103
static float bigEncodingFuzz = 0.02;
 
104
 
 
105
static int relative;
 
106
static int doScalable;
 
107
static int doBitmaps;
 
108
static int doISO10646_1_encoding;
 
109
static int onlyEncodings;
 
110
static ListPtr encodingsToDo;
 
111
static int reencodeLegacy;
 
112
static char *encodingPrefix;
 
113
static char *exclusionSuffix;
 
114
 
 
115
static void
 
116
usage(void)
 
117
{
 
118
    fprintf(stderr, 
 
119
            "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
 
120
            "            [ -a encoding ] [ -f fuzz ] [ -l ] "
 
121
            "            [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
 
122
            "            [-u] [-U] [ directory ]...\n");
 
123
}
 
124
 
 
125
int
 
126
main(int argc, char **argv)
 
127
{
 
128
    int argn;
 
129
    FT_Error ftrc;
 
130
    int rc, ll = 0;
 
131
    char prefix[NPREFIX];
 
132
 
 
133
    encodingPrefix = NULL;
 
134
    exclusionSuffix = NULL;
 
135
 
 
136
    if(getcwd(prefix, NPREFIX - 1) == NULL) {
 
137
        perror("Couldn't get cwd");
 
138
        exit(1);
 
139
    }
 
140
    if(prefix[strlen(prefix) - 1] != '/')
 
141
        strcat(prefix, "/");
 
142
    encodingPrefix = dsprintf("%s", prefix);
 
143
 
 
144
    outfilename = NULL;
 
145
 
 
146
    encodings = makeList(encodings_array, countof(encodings_array), NULL, 0);
 
147
 
 
148
    extra_encodings = makeList(extra_encodings_array, 
 
149
                               countof(extra_encodings_array),
 
150
                               NULL, 0);
 
151
    doBitmaps = 0;
 
152
    doISO10646_1_encoding = 1;
 
153
    doScalable = 1;
 
154
    onlyEncodings = 0;
 
155
    relative = 0;
 
156
    reencodeLegacy = 1;
 
157
    encodingsToDo = NULL;
 
158
 
 
159
    argn = 1;
 
160
    while(argn < argc) {
 
161
        if(argv[argn][0] == '\0' || argv[argn][0] != '-')
 
162
            break;
 
163
        if(argv[argn][1] == '-') {
 
164
            argn++;
 
165
            break;
 
166
        } else if (strcmp(argv[argn], "-x") == 0) {
 
167
            if(argn >= argc - 1) {
 
168
                usage();
 
169
                exit(1);
 
170
            }
 
171
            exclusionSuffix = argv[argn + 1];
 
172
            argn += 2;
 
173
        } else if(strcmp(argv[argn], "-a") == 0) {
 
174
            if(argn >= argc - 1) {
 
175
                usage();
 
176
                exit(1);
 
177
            }
 
178
            makeList(&argv[argn + 1], 1, encodings, 0);
 
179
            argn += 2;
 
180
        } else if(strcmp(argv[argn], "-p") == 0) {
 
181
            if(argn >= argc - 1) {
 
182
                usage();
 
183
                exit(1);
 
184
            }
 
185
            if(strlen(argv[argn + 1]) > NPREFIX - 1) {
 
186
                usage();
 
187
                exit(1);
 
188
            }
 
189
            free(encodingPrefix);
 
190
            encodingPrefix = dsprintf("%s", argv[argn + 1]);
 
191
            argn += 2;
 
192
        } else if(strcmp(argv[argn], "-e") == 0) {
 
193
            if(argn >= argc - 1) {
 
194
                usage();
 
195
                exit(1);
 
196
            }
 
197
            rc = readEncodings(encodingsToDo, argv[argn + 1]);
 
198
            if(rc < 0)
 
199
                exit(1);
 
200
            argn += 2;
 
201
        } else if(strcmp(argv[argn], "-b") == 0) {
 
202
            doBitmaps = 1;
 
203
            argn++;
 
204
        } else if(strcmp(argv[argn], "-u") == 0) {
 
205
            doISO10646_1_encoding = 0;
 
206
            argn++;
 
207
        } else if(strcmp(argv[argn], "-U") == 0) {
 
208
            doISO10646_1_encoding = 1;
 
209
            argn++;            
 
210
        } else if(strcmp(argv[argn], "-s") == 0) {
 
211
            doScalable = 0;
 
212
            argn++;
 
213
        } else if(strcmp(argv[argn], "-n") == 0) {
 
214
            onlyEncodings = 1;
 
215
            argn++;
 
216
        } else if(strcmp(argv[argn], "-r") == 0) {
 
217
            relative = 1;
 
218
            argn++;
 
219
        } else if(strcmp(argv[argn], "-l") == 0) {
 
220
            reencodeLegacy = !reencodeLegacy;
 
221
            argn++;
 
222
        } else if(strcmp(argv[argn], "-o") == 0) {
 
223
            if(argn >= argc - 1) {
 
224
                usage();
 
225
                exit(1);
 
226
            }
 
227
            outfilename = argv[argn + 1];
 
228
            argn += 2;
 
229
        } else if(strcmp(argv[argn], "-f") == 0) {
 
230
            if(argn >= argc - 1) {
 
231
                usage();
 
232
                exit(1);
 
233
            }
 
234
            bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
 
235
            argn += 2;
 
236
        } else if (strcmp(argv[argn], "-r") == 0) { /* ignore for now */
 
237
            argn++;
 
238
        } else if (strcmp(argv[argn], "-n") == 0) {
 
239
            argn++;
 
240
        } else {
 
241
            usage();
 
242
            exit(1);
 
243
        }
 
244
    }
 
245
 
 
246
    if(outfilename == NULL) {
 
247
        if(doBitmaps)
 
248
            outfilename = "fonts.dir";
 
249
        else 
 
250
            outfilename = "fonts.scale";
 
251
    }
 
252
 
 
253
    ftrc = FT_Init_FreeType(&ft_library);
 
254
    if(ftrc) {
 
255
        fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
 
256
        exit(1);
 
257
    }
 
258
 
 
259
    ll = listLength(encodingsToDo);
 
260
 
 
261
    if (argn == argc)
 
262
        doDirectory(".", ll, encodingsToDo);
 
263
    else
 
264
        while(argn < argc) {
 
265
            doDirectory(argv[argn], ll, encodingsToDo);
 
266
            argn++;
 
267
        }
 
268
    return 0;
 
269
}
 
270
 
 
271
static int
 
272
getNameHelper(FT_Face face, int nid, int pid, int eid,
 
273
              FT_SfntName *name_return)
 
274
{
 
275
    FT_SfntName name;
 
276
    int n, i;
 
277
 
 
278
    n = FT_Get_Sfnt_Name_Count(face);
 
279
    if(n <= 0)
 
280
        return 0;
 
281
 
 
282
    for(i = 0; i < n; i++) {
 
283
        if(FT_Get_Sfnt_Name(face, i, &name))
 
284
            continue;
 
285
        if(name.name_id == nid &&
 
286
           name.platform_id == pid &&
 
287
           (eid < 0 || name.encoding_id == eid)) {
 
288
            switch(name.platform_id) {
 
289
            case TT_PLATFORM_APPLE_UNICODE:
 
290
            case TT_PLATFORM_MACINTOSH:
 
291
                if(name.language_id != TT_MAC_LANGID_ENGLISH)
 
292
                    continue;
 
293
                break;
 
294
            case TT_PLATFORM_MICROSOFT:
 
295
                if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
 
296
                   name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
 
297
                    continue;
 
298
                break;
 
299
            default:
 
300
                continue;
 
301
            }
 
302
            if(name.string_len > 0) {
 
303
                *name_return = name;
 
304
                return 1;
 
305
            }
 
306
        }
 
307
    }
 
308
    return 0;
 
309
}
 
310
 
 
311
static char *
 
312
getName(FT_Face face, int nid)
 
313
{
 
314
    FT_SfntName name;
 
315
    char *string;
 
316
    int i;
 
317
 
 
318
    if(getNameHelper(face, nid, 
 
319
                     TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
 
320
       getNameHelper(face, nid, 
 
321
                     TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
 
322
        string = malloc(name.string_len / 2 + 1);
 
323
        if(string == NULL) {
 
324
            fprintf(stderr, "Couldn't allocate name\n");
 
325
            exit(1);
 
326
        }
 
327
        for(i = 0; i < name.string_len / 2; i++) {
 
328
            if(name.string[2 * i] != 0)
 
329
                string[i] = '?';
 
330
            else
 
331
                string[i] = name.string[2 * i + 1];
 
332
        }
 
333
        string[i] = '\0';
 
334
        return string;
 
335
    }
 
336
 
 
337
    /* Pretend that Apple Roman is ISO 8859-1. */
 
338
    if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
 
339
                     &name)) {
 
340
        string = malloc(name.string_len + 1);
 
341
        if(string == NULL) {
 
342
            fprintf(stderr, "Couldn't allocate name\n");
 
343
            exit(1);
 
344
        }
 
345
        memcpy(string, name.string, name.string_len);
 
346
        string[name.string_len] = '\0';
 
347
        return string;
 
348
    }
 
349
 
 
350
    return NULL;
 
351
}
 
352
 
 
353
static char*
 
354
os2Weight(int weight)
 
355
{
 
356
    if(weight < 150)
 
357
        return "thin";
 
358
    else if(weight < 250)
 
359
        return "extralight";
 
360
    else if(weight < 350)
 
361
        return "light";
 
362
    else if(weight < 450)
 
363
        return "medium";        /* officially "normal" */
 
364
    else if(weight < 550)
 
365
        return "medium";
 
366
    else if(weight < 650)
 
367
        return "semibold";
 
368
    else if(weight < 750)
 
369
        return "bold";
 
370
    else if(weight < 850)
 
371
        return "extrabold";
 
372
    else 
 
373
        return "black";
 
374
}
 
375
 
 
376
static char*
 
377
os2Width(int width)
 
378
{
 
379
    if(width <= 1)
 
380
        return "ultracondensed";
 
381
    else if(width <= 2)
 
382
        return "extracondensed";
 
383
    else if(width <= 3)
 
384
        return "condensed";
 
385
    else if(width <= 4)
 
386
        return "semicondensed";
 
387
    else if(width <= 5)
 
388
        return "normal";
 
389
    else if(width <= 6)
 
390
        return "semiexpanded";
 
391
    else if(width <= 7)
 
392
        return "expanded";
 
393
    else if(width <= 8)
 
394
        return "extraexpanded";
 
395
    else
 
396
        return "ultraexpanded";
 
397
}
 
398
 
 
399
static char *widths[] = {
 
400
    "ultracondensed", "extracondensed", "condensed", "semicondensed",
 
401
    "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded" 
 
402
};
 
403
 
 
404
#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
 
405
 
 
406
static char*
 
407
nameWidth(char *name)
 
408
{
 
409
    char buf[500];
 
410
    int i;
 
411
    int n = strlen(name);
 
412
 
 
413
    if(n >= 499) return NULL;
 
414
    for(i = 0; i < n; i++)
 
415
        buf[i] = tolower(name[i]);
 
416
    buf[i] = '\0';
 
417
 
 
418
    for(i = 0; i < NUMWIDTHS; i++)
 
419
        if(strstr(buf, widths[i]))
 
420
            return widths[i];
 
421
    return NULL;
 
422
}
 
423
 
 
424
static char*
 
425
t1Weight(char *weight)
 
426
{
 
427
    if(!weight)
 
428
        return NULL;
 
429
    if(strcmp(weight, "Thin") == 0)
 
430
        return "thin";
 
431
    if(strcmp(weight, "Light") == 0)
 
432
        return "light";
 
433
    if(strcmp(weight, "Regular") == 0)
 
434
        return "medium";
 
435
    if(strcmp(weight, "Normal") == 0)
 
436
        return "medium";
 
437
    if(strcmp(weight, "Medium") == 0)
 
438
        return "medium";
 
439
    if(strcmp(weight, "Book") == 0)
 
440
        return "medium";
 
441
    if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
 
442
        return "medium";
 
443
    if(strcmp(weight, "Demi") == 0)
 
444
        return "semibold";
 
445
    if(strcmp(weight, "DemiBold") == 0)
 
446
        return "semibold";
 
447
    else if(strcmp(weight, "Bold") == 0)
 
448
        return "bold";
 
449
    else if(strcmp(weight, "Black") == 0)
 
450
        return "black";
 
451
    else {
 
452
        fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
 
453
        return NULL;
 
454
    }
 
455
}
 
456
 
 
457
static int
 
458
unsafe(char c)
 
459
{
 
460
    return 
 
461
        c < 0x20 || c > 0x7E ||
 
462
        c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
 
463
}
 
464
 
 
465
static char *
 
466
safe(char* s)
 
467
{
 
468
    int i, len, safe_flag = 1;
 
469
    char *t;
 
470
 
 
471
    i = 0;
 
472
    while(s[i] != '\0') {
 
473
        if(unsafe(s[i]))
 
474
            safe_flag = 0;
 
475
        i++;
 
476
    }
 
477
 
 
478
    if(safe_flag) return s;
 
479
 
 
480
    len = i;
 
481
    t = malloc(len + 1);
 
482
    if(t == NULL) {
 
483
        perror("Couldn't allocate string");
 
484
        exit(1);
 
485
    }
 
486
 
 
487
    for(i = 0; i < len; i++) {
 
488
        if(unsafe(s[i]))
 
489
            t[i] = ' ';
 
490
        else
 
491
            t[i] = s[i];
 
492
    }
 
493
    t[i] = '\0';
 
494
    return t;
 
495
}
 
496
 
 
497
ListPtr
 
498
makeXLFD(char *filename, FT_Face face, int isBitmap)
 
499
{
 
500
    ListPtr xlfd = NULL;
 
501
    char *foundry, *family, *weight, *slant, *sWidth, *adstyle, 
 
502
        *spacing, *full_name;
 
503
    TT_Header *head;
 
504
    TT_HoriHeader *hhea;
 
505
    TT_OS2 *os2;
 
506
    TT_Postscript *post;
 
507
    PS_FontInfoRec *t1info, t1info_rec;
 
508
    int rc;
 
509
 
 
510
    foundry = NULL;
 
511
    family = NULL;
 
512
    weight = NULL;
 
513
    slant = NULL;
 
514
    sWidth = NULL;
 
515
    adstyle = NULL;
 
516
    spacing = NULL;
 
517
    full_name = NULL;
 
518
 
 
519
    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
 
520
    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
 
521
    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
 
522
    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
 
523
 
 
524
    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
 
525
    if(rc == 0)
 
526
        t1info = &t1info_rec;
 
527
    else
 
528
        t1info = NULL;
 
529
        
 
530
    if(!family)
 
531
        family = getName(face, TT_NAME_ID_FONT_FAMILY);
 
532
    if(!family)
 
533
        family = getName(face, TT_NAME_ID_FULL_NAME);
 
534
    if(!family)
 
535
        family = getName(face, TT_NAME_ID_PS_NAME);
 
536
 
 
537
    if(!full_name)
 
538
        full_name = getName(face, TT_NAME_ID_FULL_NAME);
 
539
    if(!full_name)
 
540
        full_name = getName(face, TT_NAME_ID_PS_NAME);
 
541
 
 
542
    if(os2 && os2->version != 0xFFFF) {
 
543
        if(!weight)
 
544
            weight = os2Weight(os2->usWeightClass);
 
545
        if(!sWidth)
 
546
            sWidth = os2Width(os2->usWidthClass);
 
547
        if(!foundry)
 
548
            foundry = vendor_foundry(os2->achVendID);
 
549
        if(!slant)
 
550
            slant = os2->fsSelection & 1 ? "i" : "r";
 
551
    }
 
552
 
 
553
    if(post) {
 
554
        if(!spacing) {
 
555
            if(post->isFixedPitch) {
 
556
                if(hhea->min_Left_Side_Bearing >= 0 &&
 
557
                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
 
558
                    spacing = "c";
 
559
                } else {
 
560
                    spacing = "m";
 
561
                }
 
562
            } else {
 
563
                spacing = "p";
 
564
            }
 
565
        }
 
566
    }
 
567
            
 
568
    if(t1info) {
 
569
        if(!family)
 
570
            family = t1info->family_name;
 
571
        if(!family)
 
572
            family = t1info->full_name;
 
573
        if(!full_name)
 
574
            full_name = t1info->full_name;
 
575
        if(!foundry)
 
576
            foundry = notice_foundry(t1info->notice);
 
577
        if(!weight)
 
578
            weight = t1Weight(t1info->weight);
 
579
        if(!spacing)
 
580
            spacing = t1info->is_fixed_pitch ? "m" : "p";
 
581
        if(!slant) {
 
582
            /* Bitstream fonts have positive italic angle. */
 
583
            slant =
 
584
                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
 
585
                "i" : "r";
 
586
        }
 
587
    }
 
588
 
 
589
    if(!full_name) {
 
590
        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
 
591
        full_name = filename;
 
592
    }
 
593
 
 
594
    if(head) {
 
595
        if(!slant)
 
596
            slant = head->Mac_Style & 2 ? "i" : "r";
 
597
        if(!weight)
 
598
            weight = head->Mac_Style & 1 ? "bold" : "medium";
 
599
    }
 
600
 
 
601
    if(!slant) {
 
602
        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
 
603
        slant = "r";
 
604
    }
 
605
 
 
606
    if(!weight) {
 
607
        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
 
608
        weight = "medium";
 
609
    }
 
610
 
 
611
    if(!foundry) {
 
612
        char *notice;
 
613
        notice = getName(face, TT_NAME_ID_TRADEMARK);
 
614
        if(notice) {
 
615
            foundry = notice_foundry(notice);
 
616
        }
 
617
        if(!foundry) {
 
618
            notice = getName(face, TT_NAME_ID_MANUFACTURER);
 
619
            if(notice) {
 
620
                foundry = notice_foundry(notice);
 
621
            }
 
622
        }
 
623
    }
 
624
 
 
625
    if(strcmp(slant, "i") == 0) {
 
626
        if(strstr(full_name, "Oblique"))
 
627
            slant = "o";
 
628
        if(strstr(full_name, "Slanted"))
 
629
            slant = "o";
 
630
    }
 
631
 
 
632
    if(!sWidth)
 
633
        sWidth = nameWidth(full_name);
 
634
 
 
635
    if(!foundry) foundry = "misc";
 
636
    if(!family) {
 
637
        fprintf(stderr, "Couldn't get family name for %s\n", filename);
 
638
        family = filename;
 
639
    }
 
640
 
 
641
    if(!weight) weight = "medium";
 
642
    if(!slant) slant = "r";
 
643
    if(!sWidth) sWidth = "normal";
 
644
    if(!adstyle) adstyle = "";
 
645
    if(!spacing) spacing = "p";
 
646
 
 
647
    /* Yes, it's a memory leak. */
 
648
    foundry = safe(foundry);
 
649
    family = safe(family);
 
650
 
 
651
    if(!isBitmap) {
 
652
        xlfd = listConsF(xlfd,
 
653
                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
 
654
                         foundry, family,
 
655
                         weight, slant, sWidth, adstyle, spacing);
 
656
    } else {
 
657
        int i, w, h, xres, yres;
 
658
        for(i = 0; i < face->num_fixed_sizes; i++) {
 
659
            w = face->available_sizes[i].width;
 
660
            h = face->available_sizes[i].height;
 
661
            xres = 75;
 
662
            yres = (double)h / w * xres;
 
663
            xlfd = listConsF(xlfd,
 
664
                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
 
665
                             foundry, family,
 
666
                             weight, slant, sWidth, adstyle,
 
667
                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
 
668
                             xres, yres,
 
669
                             spacing, 60);
 
670
        }
 
671
    }
 
672
    return xlfd;
 
673
}
 
674
 
 
675
static int
 
676
readFontScale(HashTablePtr entries, char *dirname)
 
677
{
 
678
    int n = strlen(dirname);
 
679
    char *filename;
 
680
    FILE *in;
 
681
    int rc, count, i;
 
682
    char file[MAXFONTFILENAMELEN], font[MAXFONTNAMELEN];
 
683
    char format[100];
 
684
 
 
685
    snprintf(format, 100, "%%%ds %%%d[^\n]\n", 
 
686
             MAXFONTFILENAMELEN, MAXFONTNAMELEN);
 
687
 
 
688
    if(dirname[n - 1] == '/')
 
689
        filename = dsprintf("%sfonts.scale", dirname);
 
690
    else
 
691
        filename = dsprintf("%s/fonts.scale", dirname);
 
692
    if(filename == NULL)
 
693
        return -1;
 
694
 
 
695
    in = fopen(filename, "r");
 
696
    free(filename);
 
697
    if(in == NULL) {
 
698
        if(errno != ENOENT)
 
699
            perror("open(fonts.scale)");
 
700
        return -1;
 
701
    }
 
702
 
 
703
    rc = fscanf(in, "%d\n", &count);
 
704
    if(rc != 1) {
 
705
        fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
 
706
        fclose(in);
 
707
        return -1;
 
708
    }
 
709
 
 
710
    for(i = 0; i < count; i++) {
 
711
        rc = fscanf(in, format, file, font);
 
712
        if(rc != 2)
 
713
            break;
 
714
        putHash(entries, font, file, 100);
 
715
    }
 
716
    fclose(in);
 
717
    return 1;
 
718
}
 
719
 
 
720
static int
 
721
filePrio(char *filename)
 
722
{
 
723
    int n = strlen(filename);
 
724
    if(n < 4)
 
725
        return 0;
 
726
    if(strcmp(filename + n - 4, ".otf") == 0)
 
727
        return 4;
 
728
    if(strcmp(filename + n - 4, ".OTF") == 0)
 
729
        return 4;
 
730
    if(strcmp(filename + n - 4, ".ttf") == 0)
 
731
        return 3;
 
732
    if(strcmp(filename + n - 4, ".TTF") == 0)
 
733
        return 3;
 
734
    if(strcmp(filename + n - 3, ".gz") == 0)
 
735
        return 2;
 
736
    if(strcmp(filename + n - 2, ".Z") == 0)
 
737
        return 1;
 
738
    return 0;
 
739
}
 
740
 
 
741
static int
 
742
doDirectory(char *dirname_given, int numEncodings, ListPtr encodingsToDo)
 
743
{
 
744
    char *dirname, *fontscale_name, *filename, *encdir;
 
745
    FILE *fontscale, *encfile;
 
746
    DIR *dirp;
 
747
    struct dirent *entry;
 
748
    FT_Error ftrc;
 
749
    FT_Face face;
 
750
    ListPtr encoding, xlfd, lp;
 
751
    HashTablePtr entries;
 
752
    HashBucketPtr *array;
 
753
    int i, n, found, rc;
 
754
    int isBitmap=0,xl=0;
 
755
 
 
756
    if (exclusionSuffix)
 
757
        xl = strlen (exclusionSuffix);
 
758
 
 
759
    i = strlen(dirname_given);
 
760
    if(i == 0)
 
761
        dirname = dsprintf("./");
 
762
    else if(dirname_given[i - 1] != '/')
 
763
        dirname = dsprintf("%s/", dirname_given);
 
764
    else
 
765
        dirname = dsprintf("%s", dirname_given);
 
766
 
 
767
    if(dirname == NULL) {
 
768
        perror("dirname");
 
769
        exit(1);
 
770
    }
 
771
 
 
772
    if (onlyEncodings) 
 
773
        goto encodings;
 
774
    
 
775
    entries = makeHashTable();
 
776
    if(doBitmaps && !doScalable) {
 
777
        readFontScale(entries, dirname);
 
778
    }
 
779
 
 
780
    if(strcmp(outfilename, "-") == 0)
 
781
        fontscale_name = NULL;
 
782
    else {
 
783
        if(outfilename[0] == '/')
 
784
            fontscale_name = dsprintf("%s", outfilename);
 
785
        else
 
786
            fontscale_name = dsprintf("%s%s", dirname, outfilename);
 
787
        if(fontscale_name == NULL) {
 
788
            perror("fontscale_name");
 
789
            exit(1);
 
790
        }
 
791
    }
 
792
 
 
793
    dirp = opendir(dirname);
 
794
    if(dirp == NULL) {
 
795
        fprintf(stderr, "%s: ", dirname);
 
796
        perror("opendir");
 
797
        return 0;
 
798
    }
 
799
 
 
800
    if(fontscale_name == NULL)
 
801
        fontscale = stdout;
 
802
    else
 
803
        fontscale = fopen(fontscale_name, "w");
 
804
 
 
805
    if(fontscale == NULL) {
 
806
        fprintf(stderr, "%s: ", fontscale_name);
 
807
        perror("fopen(w)");
 
808
        return 0;
 
809
    }
 
810
 
 
811
    while((entry = readdir(dirp)) != NULL) {
 
812
        int have_face = 0;
 
813
        char *xlfd_name = NULL;
 
814
        xlfd = NULL;
 
815
 
 
816
        if (xl) {
 
817
            int dl = strlen (entry->d_name);
 
818
            if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
 
819
                continue;
 
820
        }
 
821
 
 
822
        filename = dsprintf("%s%s", dirname, entry->d_name);
 
823
 
 
824
        if(doBitmaps)
 
825
            rc = bitmapIdentify(filename, &xlfd_name);
 
826
        else
 
827
            rc = 0;
 
828
 
 
829
        if(rc < 0)
 
830
            goto done;
 
831
 
 
832
        if(rc == 0) {
 
833
            ftrc = FT_New_Face(ft_library, filename, 0, &face);
 
834
            if(ftrc)
 
835
                goto done;
 
836
            have_face = 1;
 
837
 
 
838
            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
 
839
 
 
840
            if(!isBitmap) {
 
841
                /* Workaround for bitmap-only TTF fonts */
 
842
                if(face->num_fixed_sizes > 0) {
 
843
                    TT_MaxProfile *maxp;
 
844
                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
 
845
                    if(maxp != NULL && maxp->maxContours == 0)
 
846
                        isBitmap = 1;
 
847
                }
 
848
            }
 
849
        
 
850
            if(isBitmap) {
 
851
                if(!doBitmaps)
 
852
                    goto done;
 
853
            } else {
 
854
                if(!doScalable)
 
855
                    goto done;
 
856
            }
 
857
 
 
858
            if(isBitmap) {
 
859
                BDF_PropertyRec prop;
 
860
                rc = FT_Get_BDF_Property(face, "FONT", &prop);
 
861
                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
 
862
                    xlfd_name = malloc(strlen(prop.u.atom) + 1);
 
863
                    if(xlfd_name == NULL)
 
864
                        goto done;
 
865
                    strcpy(xlfd_name, prop.u.atom);
 
866
                }
 
867
            }
 
868
        }
 
869
 
 
870
        if(xlfd_name) {
 
871
            /* We know it's a bitmap font, and we know its XLFD */
 
872
            int n = strlen(xlfd_name);
 
873
            if(reencodeLegacy &&
 
874
               n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
 
875
                char *s;
 
876
 
 
877
                s = malloc(n - 10);
 
878
                memcpy(s, xlfd_name, n - 11);
 
879
                s[n - 11] = '\0';
 
880
                xlfd = listCons(s, xlfd);
 
881
            } else {
 
882
                /* Not a reencodable font -- skip all the rest of the loop body */
 
883
                putHash(entries, xlfd_name, entry->d_name, filePrio(entry->d_name));
 
884
                goto done;
 
885
            }
 
886
        }
 
887
 
 
888
        if(!have_face) {
 
889
            ftrc = FT_New_Face(ft_library, filename, 0, &face);
 
890
            if(ftrc)
 
891
                goto done;
 
892
            have_face = 1;
 
893
            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
 
894
 
 
895
            if(!isBitmap) {
 
896
                if(face->num_fixed_sizes > 0) {
 
897
                    TT_MaxProfile *maxp;
 
898
                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
 
899
                    if(maxp != NULL && maxp->maxContours == 0)
 
900
                        isBitmap = 1;
 
901
                }
 
902
            }
 
903
        }
 
904
 
 
905
        if(xlfd == NULL)
 
906
            xlfd = makeXLFD(entry->d_name, face, isBitmap);
 
907
 
 
908
        found = 0;
 
909
 
 
910
        for(lp = xlfd; lp; lp = lp->next) {
 
911
            char buf[MAXFONTNAMELEN];
 
912
            for(encoding = encodings; encoding; encoding = encoding->next) {
 
913
                if(checkEncoding(face, encoding->value)) {
 
914
                    found = 1;
 
915
                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
 
916
                            lp->value, encoding->value);
 
917
                    putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
 
918
                }
 
919
            }
 
920
            for(encoding = extra_encodings; encoding; 
 
921
                encoding = encoding->next) {
 
922
                if(checkExtraEncoding(face, encoding->value, found)) {
 
923
                    /* Do not set found! */
 
924
                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
 
925
                            lp->value, encoding->value);
 
926
                    putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
 
927
                }
 
928
            }
 
929
        }
 
930
    done:
 
931
        if(have_face) {
 
932
            FT_Done_Face(face);
 
933
            have_face = 0;
 
934
        }
 
935
        deepDestroyList(xlfd);
 
936
        xlfd = NULL;
 
937
        free(filename);
 
938
    }
 
939
 
 
940
    closedir(dirp);
 
941
    n = hashElements(entries);
 
942
    fprintf(fontscale, "%d\n", n);
 
943
    array = hashArray(entries, 1);
 
944
    for(i = 0; i < n; i++)
 
945
        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
 
946
    destroyHashArray(array);
 
947
    entries = NULL;
 
948
    if(fontscale_name) {
 
949
        fclose(fontscale);
 
950
        free(fontscale_name);
 
951
    }
 
952
 
 
953
 encodings:
 
954
    encdir = dsprintf("%s%s", dirname, "encodings.dir");
 
955
 
 
956
    if(encdir == NULL) {
 
957
        perror("encodings");
 
958
        exit(1);
 
959
    }
 
960
    unlink(encdir);
 
961
 
 
962
    if (numEncodings) {
 
963
        encfile = fopen(encdir, "w");
 
964
        if(encfile == NULL) {
 
965
            perror("open(encodings.dir)");
 
966
            exit(1);
 
967
        }
 
968
        fprintf(encfile, "%d\n", numEncodings);
 
969
        for(lp = encodingsToDo; lp; lp = lp->next) {
 
970
            fprintf(encfile, "%s\n", lp->value);
 
971
        }
 
972
        fclose (encfile);
 
973
    }
 
974
 
 
975
    free(dirname);
 
976
    return 1;
 
977
}
 
978
 
 
979
#define CODE_IGNORED(c) ((c) < 0x20 || \
 
980
                         ((c) >= 0x7F && (c) <= 0xA0) || \
 
981
                         (c) == 0xAD || (c) == 0xF71B)
 
982
   
 
983
static int
 
984
checkEncoding(FT_Face face, char *encoding_name)
 
985
{
 
986
    FontEncPtr encoding;
 
987
    FontMapPtr mapping;
 
988
    int i, j, c, koi8;
 
989
    char *n;
 
990
 
 
991
    encoding = FontEncFind(encoding_name, NULL);
 
992
    if(!encoding)
 
993
        return 0;
 
994
 
 
995
    /* An encoding is ``small'' if one of the following is true:
 
996
         - it is linear and has no more than 256 codepoints; or
 
997
         - it is a matrix encoding and has no more than one column.
 
998
       
 
999
       For small encodings using Unicode indices, we require perfect
 
1000
       coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
 
1001
 
 
1002
       For large encodings, we require coverage up to bigEncodingFuzz.
 
1003
 
 
1004
       For encodings using PS names (currently Adobe Standard and
 
1005
       Adobe Symbol only), we require perfect coverage. */
 
1006
 
 
1007
 
 
1008
    if(FT_Has_PS_Glyph_Names(face)) {
 
1009
        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
 
1010
            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
 
1011
                if(encoding->row_size > 0) {
 
1012
                    for(i = encoding->first; i < encoding->size; i++) {
 
1013
                        for(j = encoding->first_col; 
 
1014
                            j < encoding->row_size; 
 
1015
                            j++) {
 
1016
                            n = FontEncName((i<<8) | j, mapping);
 
1017
                            if(n && FT_Get_Name_Index(face, n) == 0) {
 
1018
                                return 0;
 
1019
                            }
 
1020
                        }
 
1021
                    }
 
1022
                    return 1;
 
1023
                } else {
 
1024
                    for(i = encoding->first; i < encoding->size; i++) {
 
1025
                        n = FontEncName(i, mapping);
 
1026
                        if(n && FT_Get_Name_Index(face, n) == 0) {
 
1027
                            return 0;
 
1028
                        }
 
1029
                    }
 
1030
                    return 1;
 
1031
                }
 
1032
            }
 
1033
        }
 
1034
    }
 
1035
 
 
1036
    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
 
1037
        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
 
1038
            int total = 0, failed = 0;
 
1039
            if(encoding->row_size > 0) {
 
1040
                int estimate = 
 
1041
                    (encoding->size - encoding->first) *
 
1042
                    (encoding->row_size - encoding->first_col);
 
1043
                for(i = encoding->first; i < encoding->size; i++) {
 
1044
                    for(j = encoding->first_col; 
 
1045
                        j < encoding->row_size; 
 
1046
                        j++) {
 
1047
                        c = FontEncRecode((i<<8) | j, mapping);
 
1048
                        if(CODE_IGNORED(c)) {
 
1049
                            continue;
 
1050
                        } else {
 
1051
                            if(FT_Get_Char_Index(face, c) == 0) {
 
1052
                                failed++;
 
1053
                            }
 
1054
                            total++;
 
1055
                            if((encoding->size <= 1 && failed > 0) ||
 
1056
                               ((float)failed >= bigEncodingFuzz * estimate)) {
 
1057
                                return 0;
 
1058
                            }
 
1059
                        }
 
1060
                    }
 
1061
                }
 
1062
                if((float)failed >= total * bigEncodingFuzz)
 
1063
                    return 0;
 
1064
                else
 
1065
                    return 1;
 
1066
            } else {
 
1067
                int estimate = encoding->size - encoding->first;
 
1068
                /* For the KOI8 encodings, we ignore the lack of
 
1069
                   linedrawing and pseudo-math characters */
 
1070
                if(strncmp(encoding->name, "koi8-", 5) == 0)
 
1071
                    koi8 = 1;
 
1072
                else
 
1073
                    koi8 = 0;
 
1074
                for(i = encoding->first; i < encoding->size; i++) {
 
1075
                    c = FontEncRecode(i, mapping);
 
1076
                    if(CODE_IGNORED(c) ||
 
1077
                       (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
 
1078
                        continue;
 
1079
                    } else {
 
1080
                        if(FT_Get_Char_Index(face, c) == 0) {
 
1081
                            failed++;
 
1082
                        }
 
1083
                        total++;
 
1084
                        if((encoding->size <= 256 && failed > 0) ||
 
1085
                           ((float)failed >= bigEncodingFuzz * estimate)) {
 
1086
                            return 0;
 
1087
                        }
 
1088
                    }
 
1089
                }
 
1090
                if((float)failed >= total * bigEncodingFuzz)
 
1091
                    return 0;
 
1092
                else
 
1093
                    return 1;
 
1094
            }
 
1095
        }
 
1096
    }
 
1097
    return 0;
 
1098
}
 
1099
 
 
1100
static int 
 
1101
find_cmap(int type, int pid, int eid, FT_Face face)
 
1102
{
 
1103
    int i, n, rc;
 
1104
    FT_CharMap cmap = NULL;
 
1105
 
 
1106
    n = face->num_charmaps;
 
1107
 
 
1108
    switch(type) {
 
1109
    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
 
1110
        for(i=0; i<n; i++) {
 
1111
            cmap = face->charmaps[i];
 
1112
            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
 
1113
                rc = FT_Set_Charmap(face, cmap);
 
1114
                if(rc == 0)
 
1115
                    return 1;
 
1116
            }
 
1117
        }
 
1118
        break;
 
1119
    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
 
1120
        /* prefer Microsoft Unicode */
 
1121
        for(i=0; i<n; i++) {
 
1122
            cmap = face->charmaps[i];
 
1123
            if(cmap->platform_id == TT_PLATFORM_MICROSOFT && 
 
1124
               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
 
1125
                rc = FT_Set_Charmap(face, cmap);
 
1126
                if(rc == 0)
 
1127
                    return 1;
 
1128
            }
 
1129
        }
 
1130
        break;
 
1131
        /* Try Apple Unicode */
 
1132
        for(i=0; i<n; i++) {
 
1133
            cmap = face->charmaps[i];
 
1134
            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
 
1135
                rc = FT_Set_Charmap(face, cmap);
 
1136
                if(rc == 0)
 
1137
                    return 1;
 
1138
            }
 
1139
        }
 
1140
        /* ISO Unicode? */
 
1141
        for(i=0; i<n; i++) {
 
1142
            cmap = face->charmaps[i];
 
1143
            if(cmap->platform_id == TT_PLATFORM_ISO) {
 
1144
                rc = FT_Set_Charmap(face, cmap);
 
1145
                if(rc == 0)
 
1146
                    return 1;
 
1147
            }
 
1148
        }
 
1149
        break;
 
1150
    default:
 
1151
        return 0;
 
1152
    }
 
1153
    return 0;
 
1154
}
 
1155
 
 
1156
static int
 
1157
checkExtraEncoding(FT_Face face, char *encoding_name, int found)
 
1158
{
 
1159
    int c;
 
1160
 
 
1161
    if(strcasecmp(encoding_name, "iso10646-1") == 0) {
 
1162
        if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
 
1163
            int found = 0;
 
1164
             /* Export as Unicode if there are at least 15 BMP
 
1165
               characters that are not a space or ignored. */
 
1166
            for(c = 0x21; c < 0x10000; c++) {
 
1167
                if(CODE_IGNORED(c))
 
1168
                    continue;
 
1169
                if(FT_Get_Char_Index(face, c) > 0)
 
1170
                    found++;
 
1171
                if(found >= 15)
 
1172
                    return 1;
 
1173
            }
 
1174
            return 0;
 
1175
        } else
 
1176
            return 0;
 
1177
    } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
 
1178
        if(find_cmap(FONT_ENCODING_TRUETYPE,
 
1179
                     TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
 
1180
                     face))
 
1181
            return 1;
 
1182
        else
 
1183
            return 0;
 
1184
    } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
 
1185
        if(!found) {
 
1186
            if(FT_Has_PS_Glyph_Names(face))
 
1187
                return 1;
 
1188
            else
 
1189
                return 0;
 
1190
        } else
 
1191
            return 0;
 
1192
    } else {
 
1193
        fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
 
1194
        return 0;
 
1195
    }
 
1196
}
 
1197
 
 
1198
static char*
 
1199
notice_foundry(char *notice)
 
1200
{
 
1201
    int i;
 
1202
    for(i = 0; i < countof(notice_foundries); i++)
 
1203
        if(notice && strstr(notice, notice_foundries[i][0]))
 
1204
            return notice_foundries[i][1];
 
1205
    return NULL;
 
1206
}
 
1207
 
 
1208
static int
 
1209
vendor_match(signed char *vendor, char *vendor_string)
 
1210
{
 
1211
    /* vendor is not necessarily NUL-terminated. */
 
1212
    int i, len;
 
1213
    len = strlen(vendor_string);
 
1214
    if(memcmp(vendor, vendor_string, len) != 0)
 
1215
        return 0;
 
1216
    for(i = len; i < 4; i++)
 
1217
        if(vendor[i] != ' ' && vendor[i] != '\0')
 
1218
            return 0;
 
1219
    return 1;
 
1220
}
 
1221
 
 
1222
static char*
 
1223
vendor_foundry(signed char *vendor)
 
1224
{
 
1225
    int i;
 
1226
    for(i = 0; i < countof(vendor_foundries); i++)
 
1227
        if(vendor_match(vendor, vendor_foundries[i][0]))
 
1228
            return vendor_foundries[i][1];
 
1229
    return NULL;
 
1230
}
 
1231
 
 
1232
static int
 
1233
readEncodings(ListPtr encodings, char *dirname)
 
1234
{
 
1235
    char *fullname;
 
1236
    DIR *dirp;
 
1237
    struct dirent *file;
 
1238
    char **names, **name;
 
1239
 
 
1240
    if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
 
1241
        dirname[strlen(dirname) - 1] = '\0';
 
1242
 
 
1243
    dirp = opendir(dirname);
 
1244
    if(dirp == NULL) {
 
1245
        perror("opendir");
 
1246
        return -1;
 
1247
    }
 
1248
 
 
1249
    while((file = readdir(dirp)) != NULL) {
 
1250
        fullname = dsprintf("%s/%s", dirname, file->d_name);
 
1251
        if(fullname == NULL) {
 
1252
            fprintf(stderr, "Couldn't allocate fullname\n");
 
1253
            closedir(dirp);
 
1254
            return -1;
 
1255
        }
 
1256
        
 
1257
        names = FontEncIdentify(fullname);
 
1258
        if(!names)
 
1259
            continue;
 
1260
 
 
1261
        for(name = names; *name; name++) {
 
1262
            if(fullname[0] != '/' && !relative) {
 
1263
                char *n;
 
1264
                n = dsprintf("%s%s", encodingPrefix, fullname);
 
1265
                if(n == NULL) {
 
1266
                    fprintf(stderr, "Couldn't allocate name\n");
 
1267
                    closedir(dirp);
 
1268
                    return -1;
 
1269
                }
 
1270
                encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
 
1271
                free(n);
 
1272
            } else {
 
1273
                encodingsToDo = 
 
1274
                    listConsF(encodingsToDo, "%s %s", *name, fullname);
 
1275
            }
 
1276
            if(encodingsToDo == NULL) {
 
1277
                fprintf(stderr, "Couldn't allocate encodings\n");
 
1278
                closedir(dirp);
 
1279
                return -1;
 
1280
            }
 
1281
        }
 
1282
        free(names);            /* only the spine */
 
1283
    }
 
1284
    closedir(dirp);
 
1285
    return 0;
 
1286
}