mkfontscale.c revision 8b165ca7
1ea6ae205Smrg/*
2ea6ae205Smrg  Copyright (c) 2002-2003 by Juliusz Chroboczek
3ea6ae205Smrg
4ea6ae205Smrg  Permission is hereby granted, free of charge, to any person obtaining a copy
5ea6ae205Smrg  of this software and associated documentation files (the "Software"), to deal
6ea6ae205Smrg  in the Software without restriction, including without limitation the rights
7ea6ae205Smrg  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8ea6ae205Smrg  copies of the Software, and to permit persons to whom the Software is
9ea6ae205Smrg  furnished to do so, subject to the following conditions:
10ea6ae205Smrg
11ea6ae205Smrg  The above copyright notice and this permission notice shall be included in
12ea6ae205Smrg  all copies or substantial portions of the Software.
13ea6ae205Smrg
14ea6ae205Smrg  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ea6ae205Smrg  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ea6ae205Smrg  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17ea6ae205Smrg  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18ea6ae205Smrg  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19ea6ae205Smrg  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20ea6ae205Smrg  THE SOFTWARE.
21ea6ae205Smrg*/
22ea6ae205Smrg
2340cc5db4Smrg#ifdef HAVE_CONFIG_H
242d6e8b77Smrg#include "config.h"
2540cc5db4Smrg#endif
262d6e8b77Smrg
27ea6ae205Smrg#include <stdio.h>
28ea6ae205Smrg#include <stdlib.h>
29ea6ae205Smrg#include <string.h>
30ea6ae205Smrg
31ea6ae205Smrg#include <sys/types.h>
322d6e8b77Smrg#include <sys/stat.h>
33ea6ae205Smrg#include <dirent.h>
34ea6ae205Smrg#include <unistd.h>
35ea6ae205Smrg#include <errno.h>
36ea6ae205Smrg#include <ctype.h>
37ea6ae205Smrg
38ea6ae205Smrg#include <X11/Xos.h>
39af7d3019Smrg#include <X11/Xfuncproto.h>
40ea6ae205Smrg#include <X11/fonts/fontenc.h>
41ea6ae205Smrg#include <ft2build.h>
42ea6ae205Smrg#include FT_FREETYPE_H
43ea6ae205Smrg#include FT_SFNT_NAMES_H
44ea6ae205Smrg#include FT_TRUETYPE_TABLES_H
45ea6ae205Smrg#include FT_TRUETYPE_IDS_H
46ea6ae205Smrg#include FT_TYPE1_TABLES_H
47ea6ae205Smrg#include FT_BDF_H
48ea6ae205Smrg#include FT_XFREE86_H
49ea6ae205Smrg
50ea6ae205Smrg#include "list.h"
517c5a9b20Smrg#include "constlist.h"
52ea6ae205Smrg#include "hash.h"
53ea6ae205Smrg#include "data.h"
54ea6ae205Smrg#include "ident.h"
55ea6ae205Smrg
56ea6ae205Smrg#define NPREFIX 1024
57ea6ae205Smrg
58ea6ae205Smrg#ifndef MAXFONTFILENAMELEN
59ea6ae205Smrg#define MAXFONTFILENAMELEN 1024
60ea6ae205Smrg#endif
61ea6ae205Smrg#ifndef MAXFONTNAMELEN
62ea6ae205Smrg#define MAXFONTNAMELEN 1024
63ea6ae205Smrg#endif
64ea6ae205Smrg
65245f6787Smrg/* Two levels of macro calls are needed so that we stringify the value
66245f6787Smrg   of MAXFONT... and not the string "MAXFONT..." */
67245f6787Smrg#define QUOTE(x)	#x
68245f6787Smrg#define STRINGIFY(x)	QUOTE(x)
69245f6787Smrg
708b165ca7Smrgstatic const char *encodings_array[] =
71ea6ae205Smrg    { "ascii-0",
72ea6ae205Smrg      "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
73ea6ae205Smrg      "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
74ea6ae205Smrg      "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
75ea6ae205Smrg      "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
76ea6ae205Smrg      "iso8859-15", "iso8859-16",
77ea6ae205Smrg      "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
78ea6ae205Smrg      "tis620-2",
79ea6ae205Smrg      "sun.unicode.india-0", "suneu-greek",
80ea6ae205Smrg      "adobe-standard", "adobe-symbol",
81ea6ae205Smrg      "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
82ea6ae205Smrg      /* But not "adobe-dingbats", as it uses generic glyph names. */
83ea6ae205Smrg      "cns11643-1", "cns11643-2", "cns11643-3",
84ea6ae205Smrg      "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
85ea6ae205Smrg      "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
86ea6ae205Smrg      "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
87ea6ae205Smrg      "ksc5601.1987-0", "ksc5601.1992-3"};
88ea6ae205Smrg
898b165ca7Smrgstatic const char *extra_encodings_array[] =
90ea6ae205Smrg    { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
91ea6ae205Smrg
927c5a9b20Smrgstatic ConstListPtr encodings, extra_encodings;
93663cdc11Smrgstatic const char *outfilename;
94ea6ae205Smrg
95ea6ae205Smrg#define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
96ea6ae205Smrg
97663cdc11Smrgstatic int doDirectory(const char*, int, ListPtr);
987c5a9b20Smrgstatic int checkEncoding(FT_Face face, const char *encoding_name);
997c5a9b20Smrgstatic int checkExtraEncoding(FT_Face face, const char *encoding_name, int found);
100ea6ae205Smrgstatic int find_cmap(int type, int pid, int eid, FT_Face face);
101663cdc11Smrgstatic const char* notice_foundry(const char *notice);
102663cdc11Smrgstatic const char* vendor_foundry(const signed char *vendor);
103ea6ae205Smrgstatic int readFontScale(HashTablePtr entries, char *dirname);
104ea6ae205SmrgListPtr makeXLFD(char *filename, FT_Face face, int);
105ea6ae205Smrgstatic int readEncodings(ListPtr encodings, char *dirname);
106ea6ae205Smrg
107ea6ae205Smrgstatic FT_Library ft_library;
108ea6ae205Smrgstatic float bigEncodingFuzz = 0.02;
109ea6ae205Smrg
110ea6ae205Smrgstatic int relative;
111ea6ae205Smrgstatic int doScalable;
112ea6ae205Smrgstatic int doBitmaps;
113ea6ae205Smrgstatic int doISO10646_1_encoding;
114ea6ae205Smrgstatic int onlyEncodings;
115ea6ae205Smrgstatic ListPtr encodingsToDo;
116ea6ae205Smrgstatic int reencodeLegacy;
117ea6ae205Smrgstatic char *encodingPrefix;
118ea6ae205Smrgstatic char *exclusionSuffix;
119af7d3019Smrgstatic char *ProgramName;
120ea6ae205Smrg
121af7d3019Smrgstatic void _X_NORETURN _X_COLD
122ea6ae205Smrgusage(void)
123ea6ae205Smrg{
124af7d3019Smrg    fprintf(stderr, "Usage:\n"
125ea6ae205Smrg            "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
126af7d3019Smrg            "            [ -a encoding ] [ -f fuzz ] [ -l ]\n"
127ea6ae205Smrg            "            [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
128af7d3019Smrg            "            [-u] [-U] [-v] [ directory ]...\n");
129af7d3019Smrg    exit(1);
130af7d3019Smrg}
131af7d3019Smrg
132af7d3019Smrgstatic void _X_NORETURN _X_COLD
133af7d3019Smrgmissing_arg (const char *option)
134af7d3019Smrg{
135af7d3019Smrg    fprintf(stderr, "%s: %s requires an argument\n", ProgramName, option);
136af7d3019Smrg    usage();
137ea6ae205Smrg}
138ea6ae205Smrg
139ea6ae205Smrgint
140ea6ae205Smrgmain(int argc, char **argv)
141ea6ae205Smrg{
142ea6ae205Smrg    int argn;
143ea6ae205Smrg    FT_Error ftrc;
144ea6ae205Smrg    int rc, ll = 0;
145ea6ae205Smrg    char prefix[NPREFIX];
146ea6ae205Smrg
147af7d3019Smrg    ProgramName = argv[0];
148ea6ae205Smrg    encodingPrefix = NULL;
149ea6ae205Smrg    exclusionSuffix = NULL;
150ea6ae205Smrg
151ea6ae205Smrg    if(getcwd(prefix, NPREFIX - 1) == NULL) {
152ea6ae205Smrg        perror("Couldn't get cwd");
153ea6ae205Smrg        exit(1);
154ea6ae205Smrg    }
155ea6ae205Smrg    if(prefix[strlen(prefix) - 1] != '/')
1567c5a9b20Smrg        encodingPrefix = dsprintf("%s/", prefix);
1577c5a9b20Smrg    else
1587c5a9b20Smrg        encodingPrefix = strdup(prefix);
159ea6ae205Smrg
160ea6ae205Smrg    outfilename = NULL;
161ea6ae205Smrg
1627c5a9b20Smrg    encodings = makeConstList(encodings_array, countof(encodings_array), NULL, 0);
163ea6ae205Smrg
1647c5a9b20Smrg    extra_encodings = makeConstList(extra_encodings_array,
1657c5a9b20Smrg				    countof(extra_encodings_array),
1667c5a9b20Smrg				    NULL, 0);
167ea6ae205Smrg    doBitmaps = 0;
168ea6ae205Smrg    doISO10646_1_encoding = 1;
169ea6ae205Smrg    doScalable = 1;
170ea6ae205Smrg    onlyEncodings = 0;
171ea6ae205Smrg    relative = 0;
172ea6ae205Smrg    reencodeLegacy = 1;
173ea6ae205Smrg    encodingsToDo = NULL;
174ea6ae205Smrg
175ea6ae205Smrg    argn = 1;
176ea6ae205Smrg    while(argn < argc) {
177ea6ae205Smrg        if(argv[argn][0] == '\0' || argv[argn][0] != '-')
178ea6ae205Smrg            break;
179ea6ae205Smrg        if(argv[argn][1] == '-') {
180ea6ae205Smrg            argn++;
181ea6ae205Smrg            break;
182ea6ae205Smrg        } else if (strcmp(argv[argn], "-x") == 0) {
183ea6ae205Smrg            if(argn >= argc - 1) {
184af7d3019Smrg                missing_arg("-x");
185ea6ae205Smrg            }
186ea6ae205Smrg            exclusionSuffix = argv[argn + 1];
187ea6ae205Smrg            argn += 2;
188ea6ae205Smrg        } else if(strcmp(argv[argn], "-a") == 0) {
189ea6ae205Smrg            if(argn >= argc - 1) {
190af7d3019Smrg                missing_arg("-a");
191ea6ae205Smrg            }
1927c5a9b20Smrg            makeConstList((const char **)&argv[argn + 1], 1, encodings, 0);
193ea6ae205Smrg            argn += 2;
194ea6ae205Smrg        } else if(strcmp(argv[argn], "-p") == 0) {
195ea6ae205Smrg            if(argn >= argc - 1) {
196af7d3019Smrg                missing_arg("-p");
197ea6ae205Smrg            }
198ea6ae205Smrg            if(strlen(argv[argn + 1]) > NPREFIX - 1) {
199af7d3019Smrg                fprintf(stderr, "%s: argument to -p cannot be longer than "
200af7d3019Smrg                        "%d characters\n", ProgramName, NPREFIX - 1);
201ea6ae205Smrg                usage();
202ea6ae205Smrg            }
203ea6ae205Smrg            free(encodingPrefix);
2047c5a9b20Smrg            encodingPrefix = strdup(argv[argn + 1]);
205ea6ae205Smrg            argn += 2;
206ea6ae205Smrg        } else if(strcmp(argv[argn], "-e") == 0) {
207ea6ae205Smrg            if(argn >= argc - 1) {
208af7d3019Smrg                missing_arg("-e");
209ea6ae205Smrg            }
210ea6ae205Smrg            rc = readEncodings(encodingsToDo, argv[argn + 1]);
211ea6ae205Smrg            if(rc < 0)
212ea6ae205Smrg                exit(1);
213ea6ae205Smrg            argn += 2;
214ea6ae205Smrg        } else if(strcmp(argv[argn], "-b") == 0) {
215ea6ae205Smrg            doBitmaps = 1;
216ea6ae205Smrg            argn++;
217ea6ae205Smrg        } else if(strcmp(argv[argn], "-u") == 0) {
218ea6ae205Smrg            doISO10646_1_encoding = 0;
219ea6ae205Smrg            argn++;
220ea6ae205Smrg        } else if(strcmp(argv[argn], "-U") == 0) {
221ea6ae205Smrg            doISO10646_1_encoding = 1;
222663cdc11Smrg            argn++;
223ea6ae205Smrg        } else if(strcmp(argv[argn], "-s") == 0) {
224ea6ae205Smrg            doScalable = 0;
225ea6ae205Smrg            argn++;
226ea6ae205Smrg        } else if(strcmp(argv[argn], "-n") == 0) {
227ea6ae205Smrg            onlyEncodings = 1;
228ea6ae205Smrg            argn++;
229ea6ae205Smrg        } else if(strcmp(argv[argn], "-r") == 0) {
230ea6ae205Smrg            relative = 1;
231ea6ae205Smrg            argn++;
232ea6ae205Smrg        } else if(strcmp(argv[argn], "-l") == 0) {
233ea6ae205Smrg            reencodeLegacy = !reencodeLegacy;
234ea6ae205Smrg            argn++;
235ea6ae205Smrg        } else if(strcmp(argv[argn], "-o") == 0) {
236ea6ae205Smrg            if(argn >= argc - 1) {
237af7d3019Smrg                missing_arg("-o");
238ea6ae205Smrg            }
239ea6ae205Smrg            outfilename = argv[argn + 1];
240ea6ae205Smrg            argn += 2;
241ea6ae205Smrg        } else if(strcmp(argv[argn], "-f") == 0) {
242ea6ae205Smrg            if(argn >= argc - 1) {
243af7d3019Smrg                missing_arg("-f");
244ea6ae205Smrg            }
245ea6ae205Smrg            bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
246ea6ae205Smrg            argn += 2;
247af7d3019Smrg	} else if (strcmp(argv[argn], "-v") == 0) {
248af7d3019Smrg	    printf("%s\n", PACKAGE_STRING);
249af7d3019Smrg	    exit(0);
250ea6ae205Smrg	} else {
251ea6ae205Smrg            usage();
252ea6ae205Smrg        }
253ea6ae205Smrg    }
254ea6ae205Smrg
255ea6ae205Smrg    if(outfilename == NULL) {
256ea6ae205Smrg        if(doBitmaps)
257ea6ae205Smrg            outfilename = "fonts.dir";
258663cdc11Smrg        else
259ea6ae205Smrg            outfilename = "fonts.scale";
260ea6ae205Smrg    }
261ea6ae205Smrg
262ea6ae205Smrg    ftrc = FT_Init_FreeType(&ft_library);
263ea6ae205Smrg    if(ftrc) {
264ea6ae205Smrg        fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
265ea6ae205Smrg        exit(1);
266ea6ae205Smrg    }
267ea6ae205Smrg
268ea6ae205Smrg    ll = listLength(encodingsToDo);
269ea6ae205Smrg
270ea6ae205Smrg    if (argn == argc)
271ea6ae205Smrg        doDirectory(".", ll, encodingsToDo);
272ea6ae205Smrg    else
273ea6ae205Smrg        while(argn < argc) {
274ea6ae205Smrg            doDirectory(argv[argn], ll, encodingsToDo);
275ea6ae205Smrg            argn++;
276ea6ae205Smrg        }
277ea6ae205Smrg    return 0;
278ea6ae205Smrg}
279ea6ae205Smrg
280ea6ae205Smrgstatic int
281ea6ae205SmrggetNameHelper(FT_Face face, int nid, int pid, int eid,
282ea6ae205Smrg              FT_SfntName *name_return)
283ea6ae205Smrg{
284ea6ae205Smrg    FT_SfntName name;
285ea6ae205Smrg    int n, i;
286ea6ae205Smrg
287ea6ae205Smrg    n = FT_Get_Sfnt_Name_Count(face);
288ea6ae205Smrg    if(n <= 0)
289ea6ae205Smrg        return 0;
290ea6ae205Smrg
291ea6ae205Smrg    for(i = 0; i < n; i++) {
292ea6ae205Smrg        if(FT_Get_Sfnt_Name(face, i, &name))
293ea6ae205Smrg            continue;
294ea6ae205Smrg        if(name.name_id == nid &&
295ea6ae205Smrg           name.platform_id == pid &&
296ea6ae205Smrg           (eid < 0 || name.encoding_id == eid)) {
297ea6ae205Smrg            switch(name.platform_id) {
298ea6ae205Smrg            case TT_PLATFORM_APPLE_UNICODE:
299ea6ae205Smrg            case TT_PLATFORM_MACINTOSH:
300ea6ae205Smrg                if(name.language_id != TT_MAC_LANGID_ENGLISH)
301ea6ae205Smrg                    continue;
302ea6ae205Smrg                break;
303ea6ae205Smrg            case TT_PLATFORM_MICROSOFT:
304ea6ae205Smrg                if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
305ea6ae205Smrg                   name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
306ea6ae205Smrg                    continue;
307ea6ae205Smrg                break;
308ea6ae205Smrg            default:
309ea6ae205Smrg                continue;
310ea6ae205Smrg            }
311ea6ae205Smrg            if(name.string_len > 0) {
312ea6ae205Smrg                *name_return = name;
313ea6ae205Smrg                return 1;
314ea6ae205Smrg            }
315ea6ae205Smrg        }
316ea6ae205Smrg    }
317ea6ae205Smrg    return 0;
318ea6ae205Smrg}
319ea6ae205Smrg
320ea6ae205Smrgstatic char *
321ea6ae205SmrggetName(FT_Face face, int nid)
322ea6ae205Smrg{
323ea6ae205Smrg    FT_SfntName name;
324ea6ae205Smrg    char *string;
3257c5a9b20Smrg    unsigned int i;
326ea6ae205Smrg
327663cdc11Smrg    if(getNameHelper(face, nid,
328ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
329663cdc11Smrg       getNameHelper(face, nid,
330ea6ae205Smrg                     TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
331ea6ae205Smrg        string = malloc(name.string_len / 2 + 1);
332ea6ae205Smrg        if(string == NULL) {
333ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
334ea6ae205Smrg            exit(1);
335ea6ae205Smrg        }
336ea6ae205Smrg        for(i = 0; i < name.string_len / 2; i++) {
337ea6ae205Smrg            if(name.string[2 * i] != 0)
338ea6ae205Smrg                string[i] = '?';
339ea6ae205Smrg            else
340ea6ae205Smrg                string[i] = name.string[2 * i + 1];
341ea6ae205Smrg        }
342ea6ae205Smrg        string[i] = '\0';
343ea6ae205Smrg        return string;
344ea6ae205Smrg    }
345ea6ae205Smrg
346ea6ae205Smrg    /* Pretend that Apple Roman is ISO 8859-1. */
347ea6ae205Smrg    if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
348ea6ae205Smrg                     &name)) {
349ea6ae205Smrg        string = malloc(name.string_len + 1);
350ea6ae205Smrg        if(string == NULL) {
351ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
352ea6ae205Smrg            exit(1);
353ea6ae205Smrg        }
354ea6ae205Smrg        memcpy(string, name.string, name.string_len);
355ea6ae205Smrg        string[name.string_len] = '\0';
356ea6ae205Smrg        return string;
357ea6ae205Smrg    }
358ea6ae205Smrg
359ea6ae205Smrg    return NULL;
360ea6ae205Smrg}
361ea6ae205Smrg
362663cdc11Smrgstatic const char*
363ea6ae205Smrgos2Weight(int weight)
364ea6ae205Smrg{
365ea6ae205Smrg    if(weight < 150)
366ea6ae205Smrg        return "thin";
367ea6ae205Smrg    else if(weight < 250)
368ea6ae205Smrg        return "extralight";
369ea6ae205Smrg    else if(weight < 350)
370ea6ae205Smrg        return "light";
371ea6ae205Smrg    else if(weight < 450)
372ea6ae205Smrg        return "medium";        /* officially "normal" */
373ea6ae205Smrg    else if(weight < 550)
374ea6ae205Smrg        return "medium";
375ea6ae205Smrg    else if(weight < 650)
376ea6ae205Smrg        return "semibold";
377ea6ae205Smrg    else if(weight < 750)
378ea6ae205Smrg        return "bold";
379ea6ae205Smrg    else if(weight < 850)
380ea6ae205Smrg        return "extrabold";
381663cdc11Smrg    else
382ea6ae205Smrg        return "black";
383ea6ae205Smrg}
384ea6ae205Smrg
385663cdc11Smrgstatic const char*
386ea6ae205Smrgos2Width(int width)
387ea6ae205Smrg{
388ea6ae205Smrg    if(width <= 1)
389ea6ae205Smrg        return "ultracondensed";
390ea6ae205Smrg    else if(width <= 2)
391ea6ae205Smrg        return "extracondensed";
392ea6ae205Smrg    else if(width <= 3)
393ea6ae205Smrg        return "condensed";
394ea6ae205Smrg    else if(width <= 4)
395ea6ae205Smrg        return "semicondensed";
396ea6ae205Smrg    else if(width <= 5)
397ea6ae205Smrg        return "normal";
398ea6ae205Smrg    else if(width <= 6)
399ea6ae205Smrg        return "semiexpanded";
400ea6ae205Smrg    else if(width <= 7)
401ea6ae205Smrg        return "expanded";
402ea6ae205Smrg    else if(width <= 8)
403ea6ae205Smrg        return "extraexpanded";
404ea6ae205Smrg    else
405ea6ae205Smrg        return "ultraexpanded";
406ea6ae205Smrg}
407ea6ae205Smrg
408663cdc11Smrgstatic const char *widths[] = {
409ea6ae205Smrg    "ultracondensed", "extracondensed", "condensed", "semicondensed",
410663cdc11Smrg    "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
411ea6ae205Smrg};
412ea6ae205Smrg
413ea6ae205Smrg#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
414ea6ae205Smrg
415663cdc11Smrgstatic const char*
416663cdc11SmrgnameWidth(const char *name)
417ea6ae205Smrg{
418ea6ae205Smrg    char buf[500];
4197c5a9b20Smrg    unsigned int i;
4207c5a9b20Smrg    size_t n = strlen(name);
421ea6ae205Smrg
422ea6ae205Smrg    if(n >= 499) return NULL;
423ea6ae205Smrg    for(i = 0; i < n; i++)
424ea6ae205Smrg        buf[i] = tolower(name[i]);
425ea6ae205Smrg    buf[i] = '\0';
426ea6ae205Smrg
427ea6ae205Smrg    for(i = 0; i < NUMWIDTHS; i++)
428ea6ae205Smrg        if(strstr(buf, widths[i]))
429ea6ae205Smrg            return widths[i];
430ea6ae205Smrg    return NULL;
431ea6ae205Smrg}
432ea6ae205Smrg
433663cdc11Smrgstatic const char*
434663cdc11Smrgt1Weight(const char *weight)
435ea6ae205Smrg{
436ea6ae205Smrg    if(!weight)
437ea6ae205Smrg        return NULL;
438ea6ae205Smrg    if(strcmp(weight, "Thin") == 0)
439ea6ae205Smrg        return "thin";
440663cdc11Smrg    if(strcmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
441663cdc11Smrg        return "extralight";
442ea6ae205Smrg    if(strcmp(weight, "Light") == 0)
443ea6ae205Smrg        return "light";
444ea6ae205Smrg    if(strcmp(weight, "Regular") == 0)
445ea6ae205Smrg        return "medium";
446ea6ae205Smrg    if(strcmp(weight, "Normal") == 0)
447ea6ae205Smrg        return "medium";
448ea6ae205Smrg    if(strcmp(weight, "Medium") == 0)
449ea6ae205Smrg        return "medium";
450ea6ae205Smrg    if(strcmp(weight, "Book") == 0)
451ea6ae205Smrg        return "medium";
452ea6ae205Smrg    if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
453ea6ae205Smrg        return "medium";
454ea6ae205Smrg    if(strcmp(weight, "Demi") == 0)
455ea6ae205Smrg        return "semibold";
456ea6ae205Smrg    if(strcmp(weight, "DemiBold") == 0)
457ea6ae205Smrg        return "semibold";
458ea6ae205Smrg    if(strcmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
459ea6ae205Smrg        return "semibold";
460ea6ae205Smrg    else if(strcmp(weight, "Bold") == 0)
461ea6ae205Smrg        return "bold";
462663cdc11Smrg    else if(strcmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
463663cdc11Smrg        return "extrabold";
464ea6ae205Smrg    else if(strcmp(weight, "Black") == 0)
465ea6ae205Smrg        return "black";
466ea6ae205Smrg    else {
467ea6ae205Smrg        fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
468ea6ae205Smrg        return NULL;
469ea6ae205Smrg    }
470ea6ae205Smrg}
471ea6ae205Smrg
472ea6ae205Smrgstatic int
473ea6ae205Smrgunsafe(char c)
474ea6ae205Smrg{
475663cdc11Smrg    return
476ea6ae205Smrg        c < 0x20 || c > 0x7E ||
477ea6ae205Smrg        c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
478ea6ae205Smrg}
479ea6ae205Smrg
480663cdc11Smrgstatic const char *
481663cdc11Smrgsafe(const char* s)
482ea6ae205Smrg{
483ea6ae205Smrg    int i, len, safe_flag = 1;
484ea6ae205Smrg    char *t;
485ea6ae205Smrg
486ea6ae205Smrg    i = 0;
487ea6ae205Smrg    while(s[i] != '\0') {
488ea6ae205Smrg        if(unsafe(s[i]))
489ea6ae205Smrg            safe_flag = 0;
490ea6ae205Smrg        i++;
491ea6ae205Smrg    }
492ea6ae205Smrg
493af7d3019Smrg    if(safe_flag) return strdup(s);
494ea6ae205Smrg
495ea6ae205Smrg    len = i;
496ea6ae205Smrg    t = malloc(len + 1);
497ea6ae205Smrg    if(t == NULL) {
498ea6ae205Smrg        perror("Couldn't allocate string");
499ea6ae205Smrg        exit(1);
500ea6ae205Smrg    }
501ea6ae205Smrg
502ea6ae205Smrg    for(i = 0; i < len; i++) {
503ea6ae205Smrg        if(unsafe(s[i]))
504ea6ae205Smrg            t[i] = ' ';
505ea6ae205Smrg        else
506ea6ae205Smrg            t[i] = s[i];
507ea6ae205Smrg    }
508ea6ae205Smrg    t[i] = '\0';
509ea6ae205Smrg    return t;
510ea6ae205Smrg}
511ea6ae205Smrg
512ea6ae205SmrgListPtr
513ea6ae205SmrgmakeXLFD(char *filename, FT_Face face, int isBitmap)
514ea6ae205Smrg{
515ea6ae205Smrg    ListPtr xlfd = NULL;
516663cdc11Smrg    const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
517af7d3019Smrg        *spacing, *full_name, *tmp;
518ea6ae205Smrg    TT_Header *head;
519ea6ae205Smrg    TT_HoriHeader *hhea;
520ea6ae205Smrg    TT_OS2 *os2;
521ea6ae205Smrg    TT_Postscript *post;
522ea6ae205Smrg    PS_FontInfoRec *t1info, t1info_rec;
523ea6ae205Smrg    int rc;
524ea6ae205Smrg
525ea6ae205Smrg    foundry = NULL;
526ea6ae205Smrg    family = NULL;
527ea6ae205Smrg    weight = NULL;
528ea6ae205Smrg    slant = NULL;
529ea6ae205Smrg    sWidth = NULL;
530ea6ae205Smrg    adstyle = NULL;
531ea6ae205Smrg    spacing = NULL;
532ea6ae205Smrg    full_name = NULL;
533ea6ae205Smrg
534ea6ae205Smrg    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
535ea6ae205Smrg    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
536ea6ae205Smrg    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
537ea6ae205Smrg    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
538ea6ae205Smrg
539ea6ae205Smrg    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
540ea6ae205Smrg    if(rc == 0)
541ea6ae205Smrg        t1info = &t1info_rec;
542ea6ae205Smrg    else
543ea6ae205Smrg        t1info = NULL;
544663cdc11Smrg
545ea6ae205Smrg    if(!family)
546ea6ae205Smrg        family = getName(face, TT_NAME_ID_FONT_FAMILY);
547ea6ae205Smrg    if(!family)
548ea6ae205Smrg        family = getName(face, TT_NAME_ID_FULL_NAME);
549ea6ae205Smrg    if(!family)
550ea6ae205Smrg        family = getName(face, TT_NAME_ID_PS_NAME);
551ea6ae205Smrg
552ea6ae205Smrg    if(!full_name)
553ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_FULL_NAME);
554ea6ae205Smrg    if(!full_name)
555ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_PS_NAME);
556ea6ae205Smrg
557ea6ae205Smrg    if(os2 && os2->version != 0xFFFF) {
558ea6ae205Smrg        if(!weight)
559ea6ae205Smrg            weight = os2Weight(os2->usWeightClass);
560ea6ae205Smrg        if(!sWidth)
561ea6ae205Smrg            sWidth = os2Width(os2->usWidthClass);
562ea6ae205Smrg        if(!foundry)
563ea6ae205Smrg            foundry = vendor_foundry(os2->achVendID);
564ea6ae205Smrg        if(!slant)
565ea6ae205Smrg            slant = os2->fsSelection & 1 ? "i" : "r";
566ea6ae205Smrg    }
567ea6ae205Smrg
568ea6ae205Smrg    if(post) {
569ea6ae205Smrg        if(!spacing) {
570ea6ae205Smrg            if(post->isFixedPitch) {
571ea6ae205Smrg                if(hhea->min_Left_Side_Bearing >= 0 &&
572ea6ae205Smrg                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
573ea6ae205Smrg                    spacing = "c";
574ea6ae205Smrg                } else {
575ea6ae205Smrg                    spacing = "m";
576ea6ae205Smrg                }
577ea6ae205Smrg            } else {
578ea6ae205Smrg                spacing = "p";
579ea6ae205Smrg            }
580ea6ae205Smrg        }
581ea6ae205Smrg    }
582663cdc11Smrg
583ea6ae205Smrg    if(t1info) {
584eaa89f16Smrg        if(!family && t1info->family_name)
585af7d3019Smrg            family = strdup(t1info->family_name);
586eaa89f16Smrg        if(!family && t1info->full_name)
587af7d3019Smrg            family = strdup(t1info->full_name);
588eaa89f16Smrg        /* Hershey fonts miss /FamilyName */
589eaa89f16Smrg        if(!family && face->family_name)
590eaa89f16Smrg            family = strdup(face->family_name);
591eaa89f16Smrg        if(!full_name && t1info->full_name)
592af7d3019Smrg            full_name = strdup(t1info->full_name);
593ea6ae205Smrg        if(!foundry)
594ea6ae205Smrg            foundry = notice_foundry(t1info->notice);
595ea6ae205Smrg        if(!weight)
596ea6ae205Smrg            weight = t1Weight(t1info->weight);
597ea6ae205Smrg        if(!spacing)
598ea6ae205Smrg            spacing = t1info->is_fixed_pitch ? "m" : "p";
599ea6ae205Smrg        if(!slant) {
600ea6ae205Smrg            /* Bitstream fonts have positive italic angle. */
601ea6ae205Smrg            slant =
602ea6ae205Smrg                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
603ea6ae205Smrg                "i" : "r";
604ea6ae205Smrg        }
605ea6ae205Smrg    }
606ea6ae205Smrg
607ea6ae205Smrg    if(!full_name) {
608ea6ae205Smrg        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
609af7d3019Smrg        full_name = strdup(filename);
610ea6ae205Smrg    }
611ea6ae205Smrg
612ea6ae205Smrg    if(head) {
613ea6ae205Smrg        if(!slant)
614ea6ae205Smrg            slant = head->Mac_Style & 2 ? "i" : "r";
615ea6ae205Smrg        if(!weight)
616ea6ae205Smrg            weight = head->Mac_Style & 1 ? "bold" : "medium";
617ea6ae205Smrg    }
618ea6ae205Smrg
619ea6ae205Smrg    if(!slant) {
620ea6ae205Smrg        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
621ea6ae205Smrg        slant = "r";
622ea6ae205Smrg    }
623ea6ae205Smrg
624ea6ae205Smrg    if(!weight) {
625ea6ae205Smrg        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
626ea6ae205Smrg        weight = "medium";
627ea6ae205Smrg    }
628ea6ae205Smrg
629ea6ae205Smrg    if(!foundry) {
630ea6ae205Smrg        char *notice;
631ea6ae205Smrg        notice = getName(face, TT_NAME_ID_TRADEMARK);
632ea6ae205Smrg        if(notice) {
633ea6ae205Smrg            foundry = notice_foundry(notice);
634af7d3019Smrg            free(notice);
635ea6ae205Smrg        }
636ea6ae205Smrg        if(!foundry) {
637ea6ae205Smrg            notice = getName(face, TT_NAME_ID_MANUFACTURER);
638ea6ae205Smrg            if(notice) {
639ea6ae205Smrg                foundry = notice_foundry(notice);
640af7d3019Smrg                free(notice);
641ea6ae205Smrg            }
642ea6ae205Smrg        }
643ea6ae205Smrg    }
644ea6ae205Smrg
645ea6ae205Smrg    if(strcmp(slant, "i") == 0) {
646ea6ae205Smrg        if(strstr(full_name, "Oblique"))
647ea6ae205Smrg            slant = "o";
648ea6ae205Smrg        if(strstr(full_name, "Slanted"))
649ea6ae205Smrg            slant = "o";
650ea6ae205Smrg    }
651ea6ae205Smrg
652ea6ae205Smrg    if(!sWidth)
653ea6ae205Smrg        sWidth = nameWidth(full_name);
654ea6ae205Smrg
655ea6ae205Smrg    if(!foundry) foundry = "misc";
656ea6ae205Smrg    if(!family) {
657ea6ae205Smrg        fprintf(stderr, "Couldn't get family name for %s\n", filename);
658af7d3019Smrg        family = strdup(filename);
659ea6ae205Smrg    }
660ea6ae205Smrg
661ea6ae205Smrg    if(!weight) weight = "medium";
662ea6ae205Smrg    if(!slant) slant = "r";
663ea6ae205Smrg    if(!sWidth) sWidth = "normal";
664ea6ae205Smrg    if(!adstyle) adstyle = "";
665ea6ae205Smrg    if(!spacing) spacing = "p";
666ea6ae205Smrg
667ea6ae205Smrg    foundry = safe(foundry);
668af7d3019Smrg
669af7d3019Smrg    tmp = family;
670ea6ae205Smrg    family = safe(family);
671af7d3019Smrg    free((void *)tmp);
672ea6ae205Smrg
673ea6ae205Smrg    if(!isBitmap) {
674ea6ae205Smrg        xlfd = listConsF(xlfd,
675ea6ae205Smrg                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
676ea6ae205Smrg                         foundry, family,
677ea6ae205Smrg                         weight, slant, sWidth, adstyle, spacing);
678ea6ae205Smrg    } else {
679ea6ae205Smrg        int i, w, h, xres, yres;
680ea6ae205Smrg        for(i = 0; i < face->num_fixed_sizes; i++) {
681ea6ae205Smrg            w = face->available_sizes[i].width;
682ea6ae205Smrg            h = face->available_sizes[i].height;
683ea6ae205Smrg            xres = 75;
684ea6ae205Smrg            yres = (double)h / w * xres;
685ea6ae205Smrg            xlfd = listConsF(xlfd,
686ea6ae205Smrg                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
687ea6ae205Smrg                             foundry, family,
688ea6ae205Smrg                             weight, slant, sWidth, adstyle,
689ea6ae205Smrg                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
690ea6ae205Smrg                             xres, yres,
691ea6ae205Smrg                             spacing, 60);
692ea6ae205Smrg        }
693ea6ae205Smrg    }
694af7d3019Smrg
695af7d3019Smrg    free((void *)family);
696af7d3019Smrg    free((void *)foundry);
697af7d3019Smrg    free((void *)full_name);
698ea6ae205Smrg    return xlfd;
699ea6ae205Smrg}
700ea6ae205Smrg
701ea6ae205Smrgstatic int
702ea6ae205SmrgreadFontScale(HashTablePtr entries, char *dirname)
703ea6ae205Smrg{
7047c5a9b20Smrg    size_t n = strlen(dirname);
705ea6ae205Smrg    char *filename;
706ea6ae205Smrg    FILE *in;
707ea6ae205Smrg    int rc, count, i;
708245f6787Smrg    char file[MAXFONTFILENAMELEN+1], font[MAXFONTNAMELEN+1];
709ea6ae205Smrg
710ea6ae205Smrg    if(dirname[n - 1] == '/')
711ea6ae205Smrg        filename = dsprintf("%sfonts.scale", dirname);
712ea6ae205Smrg    else
713ea6ae205Smrg        filename = dsprintf("%s/fonts.scale", dirname);
714ea6ae205Smrg    if(filename == NULL)
715ea6ae205Smrg        return -1;
716ea6ae205Smrg
717ea6ae205Smrg    in = fopen(filename, "r");
718ea6ae205Smrg    free(filename);
719ea6ae205Smrg    if(in == NULL) {
720ea6ae205Smrg        if(errno != ENOENT)
721ea6ae205Smrg            perror("open(fonts.scale)");
722ea6ae205Smrg        return -1;
723ea6ae205Smrg    }
724ea6ae205Smrg
725ea6ae205Smrg    rc = fscanf(in, "%d\n", &count);
726ea6ae205Smrg    if(rc != 1) {
727ea6ae205Smrg        fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
728ea6ae205Smrg        fclose(in);
729ea6ae205Smrg        return -1;
730ea6ae205Smrg    }
731ea6ae205Smrg
732ea6ae205Smrg    for(i = 0; i < count; i++) {
733245f6787Smrg        rc = fscanf(in,
734245f6787Smrg		    "%" STRINGIFY(MAXFONTFILENAMELEN) "s "
735245f6787Smrg		    "%" STRINGIFY(MAXFONTNAMELEN) "[^\n]\n",
736245f6787Smrg		    file, font);
737ea6ae205Smrg        if(rc != 2)
738ea6ae205Smrg            break;
739ea6ae205Smrg        putHash(entries, font, file, 100);
740ea6ae205Smrg    }
741ea6ae205Smrg    fclose(in);
742ea6ae205Smrg    return 1;
743ea6ae205Smrg}
744ea6ae205Smrg
745ea6ae205Smrgstatic int
746ea6ae205SmrgfilePrio(char *filename)
747ea6ae205Smrg{
7487c5a9b20Smrg    size_t n = strlen(filename);
749ea6ae205Smrg    if(n < 4)
750ea6ae205Smrg        return 0;
751ea6ae205Smrg    if(strcmp(filename + n - 4, ".otf") == 0)
752ea6ae205Smrg        return 6;
753ea6ae205Smrg    if(strcmp(filename + n - 4, ".OTF") == 0)
754ea6ae205Smrg        return 6;
755ea6ae205Smrg    if(strcmp(filename + n - 4, ".ttf") == 0)
756ea6ae205Smrg        return 5;
757ea6ae205Smrg    if(strcmp(filename + n - 4, ".TTF") == 0)
758ea6ae205Smrg        return 5;
759ea6ae205Smrg    if(strcmp(filename + n - 4, ".pcf") == 0)
760ea6ae205Smrg        return 4;
761ea6ae205Smrg    if(strcmp(filename + n - 4, ".PCF") == 0)
762ea6ae205Smrg        return 4;
763ea6ae205Smrg    if(strcmp(filename + n - 3, ".gz") == 0)
764ea6ae205Smrg        return 3;
7657978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
7667978d3cdSmrg    if(strcmp(filename + n - 4, ".bz2") == 0)
7677978d3cdSmrg        return 2;
7687978d3cdSmrg#endif
769ea6ae205Smrg    if(strcmp(filename + n - 2, ".Z") == 0)
770ea6ae205Smrg        return 2;
771ea6ae205Smrg    if(strcmp(filename + n - 4, ".bdf") == 0)
772ea6ae205Smrg        return 1;
773ea6ae205Smrg    if(strcmp(filename + n - 4, ".BDF") == 0)
774ea6ae205Smrg        return 1;
775ea6ae205Smrg    return 0;
776ea6ae205Smrg}
777ea6ae205Smrg
778ea6ae205Smrgstatic int
779663cdc11SmrgdoDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
780ea6ae205Smrg{
781ea6ae205Smrg    char *dirname, *fontscale_name, *filename, *encdir;
782ea6ae205Smrg    FILE *fontscale, *encfile;
7837c5a9b20Smrg    struct dirent** namelist;
784ea6ae205Smrg    FT_Error ftrc;
785ea6ae205Smrg    FT_Face face;
7867c5a9b20Smrg    ConstListPtr encoding;
7877c5a9b20Smrg    ListPtr xlfd, lp;
788ea6ae205Smrg    HashTablePtr entries;
789ea6ae205Smrg    HashBucketPtr *array;
7907c5a9b20Smrg    int i, n, dirn, diri, found, rc;
7917c5a9b20Smrg    int isBitmap=0;
7927c5a9b20Smrg    size_t d, xl=0;
793ea6ae205Smrg
794ea6ae205Smrg    if (exclusionSuffix)
795ea6ae205Smrg        xl = strlen (exclusionSuffix);
796ea6ae205Smrg
7977c5a9b20Smrg    d = strlen(dirname_given);
7987c5a9b20Smrg    if(d == 0)
799ea6ae205Smrg        dirname = dsprintf("./");
8007c5a9b20Smrg    else if(dirname_given[d - 1] != '/')
801ea6ae205Smrg        dirname = dsprintf("%s/", dirname_given);
802ea6ae205Smrg    else
8037c5a9b20Smrg        dirname = strdup(dirname_given);
804ea6ae205Smrg
805ea6ae205Smrg    if(dirname == NULL) {
806ea6ae205Smrg        perror("dirname");
807ea6ae205Smrg        exit(1);
808ea6ae205Smrg    }
809ea6ae205Smrg
810663cdc11Smrg    if (onlyEncodings)
811ea6ae205Smrg	goto encodings;
812663cdc11Smrg
813ea6ae205Smrg    entries = makeHashTable();
814ea6ae205Smrg    if(doBitmaps && !doScalable) {
815ea6ae205Smrg        readFontScale(entries, dirname);
816ea6ae205Smrg    }
817ea6ae205Smrg
818ea6ae205Smrg    if(strcmp(outfilename, "-") == 0)
819ea6ae205Smrg        fontscale_name = NULL;
820ea6ae205Smrg    else {
821ea6ae205Smrg        if(outfilename[0] == '/')
8227c5a9b20Smrg            fontscale_name = strdup(outfilename);
823ea6ae205Smrg        else
824ea6ae205Smrg            fontscale_name = dsprintf("%s%s", dirname, outfilename);
825ea6ae205Smrg        if(fontscale_name == NULL) {
826ea6ae205Smrg            perror("fontscale_name");
827ea6ae205Smrg            exit(1);
828ea6ae205Smrg        }
829ea6ae205Smrg    }
830ea6ae205Smrg
8317c5a9b20Smrg    dirn = scandir(dirname, &namelist, NULL, alphasort);
8327c5a9b20Smrg    if(dirn < 0) {
833ea6ae205Smrg        fprintf(stderr, "%s: ", dirname);
8347c5a9b20Smrg        perror("scandir");
835ea6ae205Smrg        return 0;
836ea6ae205Smrg    }
837ea6ae205Smrg
838ea6ae205Smrg    if(fontscale_name == NULL)
839ea6ae205Smrg        fontscale = stdout;
840ea6ae205Smrg    else
841ea6ae205Smrg        fontscale = fopen(fontscale_name, "wb");
842ea6ae205Smrg
843ea6ae205Smrg    if(fontscale == NULL) {
844ea6ae205Smrg        fprintf(stderr, "%s: ", fontscale_name);
845ea6ae205Smrg        perror("fopen(w)");
846ea6ae205Smrg        return 0;
847ea6ae205Smrg    }
848ea6ae205Smrg
8497c5a9b20Smrg    for(diri = dirn - 1; diri >= 0; diri--) {
8507c5a9b20Smrg        struct dirent *entry = namelist[diri];
851ea6ae205Smrg        int have_face = 0;
852ea6ae205Smrg        char *xlfd_name = NULL;
8532d6e8b77Smrg	struct stat f_stat;
8542d6e8b77Smrg	int tprio = 1;
8552d6e8b77Smrg
856ea6ae205Smrg        xlfd = NULL;
857ea6ae205Smrg
858ea6ae205Smrg	if (xl) {
8597c5a9b20Smrg	    size_t dl = strlen (entry->d_name);
860ea6ae205Smrg	    if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
861ea6ae205Smrg		continue;
862ea6ae205Smrg	}
863ea6ae205Smrg
864ea6ae205Smrg        filename = dsprintf("%s%s", dirname, entry->d_name);
865ea6ae205Smrg
8662d6e8b77Smrg#define PRIO(x) ((x << 1) + tprio)
8672d6e8b77Smrg#ifdef DT_LNK
8682d6e8b77Smrg	if (entry->d_type != DT_UNKNOWN) {
8692d6e8b77Smrg	    if (entry->d_type == DT_LNK)
8702d6e8b77Smrg		tprio = 0;
8712d6e8b77Smrg	} else
8722d6e8b77Smrg#endif
8732d6e8b77Smrg#ifdef S_ISLNK
8742d6e8b77Smrg	{
8752d6e8b77Smrg	    if (lstat(filename, &f_stat))
8762d6e8b77Smrg		goto done;
8772d6e8b77Smrg	    if (S_ISLNK(f_stat.st_mode))
8782d6e8b77Smrg		tprio = 0;
8792d6e8b77Smrg	}
8802d6e8b77Smrg#else
8812d6e8b77Smrg	;
8822d6e8b77Smrg#endif
883ea6ae205Smrg        if(doBitmaps)
884ea6ae205Smrg            rc = bitmapIdentify(filename, &xlfd_name);
885ea6ae205Smrg        else
886ea6ae205Smrg            rc = 0;
887ea6ae205Smrg
888ea6ae205Smrg        if(rc < 0)
889ea6ae205Smrg            goto done;
890ea6ae205Smrg
891ea6ae205Smrg        if(rc == 0) {
892ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
893ea6ae205Smrg            if(ftrc)
894ea6ae205Smrg                goto done;
895ea6ae205Smrg            have_face = 1;
896ea6ae205Smrg
897ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
898ea6ae205Smrg
899ea6ae205Smrg            if(!isBitmap) {
900ea6ae205Smrg                /* Workaround for bitmap-only SFNT fonts */
901ea6ae205Smrg                if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
902ea6ae205Smrg                   strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
903ea6ae205Smrg                    TT_MaxProfile *maxp;
904ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
905ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
906ea6ae205Smrg                        isBitmap = 1;
907ea6ae205Smrg                }
908ea6ae205Smrg            }
909663cdc11Smrg
910ea6ae205Smrg            if(isBitmap) {
911ea6ae205Smrg                if(!doBitmaps)
912ea6ae205Smrg                    goto done;
913ea6ae205Smrg            } else {
914ea6ae205Smrg                if(!doScalable)
915ea6ae205Smrg                    goto done;
916ea6ae205Smrg            }
917ea6ae205Smrg
918ea6ae205Smrg            if(isBitmap) {
919ea6ae205Smrg                BDF_PropertyRec prop;
920ea6ae205Smrg                rc = FT_Get_BDF_Property(face, "FONT", &prop);
921ea6ae205Smrg                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
9222d6e8b77Smrg                    xlfd_name = strdup(prop.u.atom);
923ea6ae205Smrg                    if(xlfd_name == NULL)
924ea6ae205Smrg                        goto done;
925ea6ae205Smrg                }
926ea6ae205Smrg            }
927ea6ae205Smrg        }
928ea6ae205Smrg
929ea6ae205Smrg        if(xlfd_name) {
930ea6ae205Smrg            /* We know it's a bitmap font, and we know its XLFD */
9317c5a9b20Smrg            size_t l = strlen(xlfd_name);
932ea6ae205Smrg            if(reencodeLegacy &&
9337c5a9b20Smrg               l >= 12 && strcasecmp(xlfd_name + l - 11, "-iso10646-1") == 0) {
934ea6ae205Smrg                char *s;
935ea6ae205Smrg
9367c5a9b20Smrg                s = malloc(l - 10);
9377c5a9b20Smrg                memcpy(s, xlfd_name, l - 11);
9387c5a9b20Smrg                s[l - 11] = '\0';
939ea6ae205Smrg                xlfd = listCons(s, xlfd);
940ea6ae205Smrg            } else {
941ea6ae205Smrg                /* Not a reencodable font -- skip all the rest of the loop body */
9422d6e8b77Smrg                putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
943ea6ae205Smrg                goto done;
944ea6ae205Smrg            }
945ea6ae205Smrg        }
946ea6ae205Smrg
947ea6ae205Smrg        if(!have_face) {
948ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
949ea6ae205Smrg            if(ftrc)
950ea6ae205Smrg                goto done;
951ea6ae205Smrg            have_face = 1;
952ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
953ea6ae205Smrg
954ea6ae205Smrg            if(!isBitmap) {
955ea6ae205Smrg                if(face->num_fixed_sizes > 0) {
956ea6ae205Smrg                    TT_MaxProfile *maxp;
957ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
958ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
959ea6ae205Smrg                        isBitmap = 1;
960ea6ae205Smrg                }
961ea6ae205Smrg            }
962ea6ae205Smrg        }
963ea6ae205Smrg
964ea6ae205Smrg        if(xlfd == NULL)
965ea6ae205Smrg            xlfd = makeXLFD(entry->d_name, face, isBitmap);
966ea6ae205Smrg
967ea6ae205Smrg        found = 0;
968ea6ae205Smrg
969ea6ae205Smrg        for(lp = xlfd; lp; lp = lp->next) {
970ea6ae205Smrg            char buf[MAXFONTNAMELEN];
971ea6ae205Smrg            for(encoding = encodings; encoding; encoding = encoding->next) {
972ea6ae205Smrg                if(checkEncoding(face, encoding->value)) {
973ea6ae205Smrg                    found = 1;
974ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
975ea6ae205Smrg                            lp->value, encoding->value);
9762d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
977ea6ae205Smrg                }
978ea6ae205Smrg            }
979663cdc11Smrg            for(encoding = extra_encodings; encoding;
980ea6ae205Smrg                encoding = encoding->next) {
981ea6ae205Smrg                if(checkExtraEncoding(face, encoding->value, found)) {
982ea6ae205Smrg                    /* Do not set found! */
983ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
984ea6ae205Smrg                            lp->value, encoding->value);
9852d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
986ea6ae205Smrg                }
987ea6ae205Smrg            }
988ea6ae205Smrg        }
989ea6ae205Smrg    done:
990245f6787Smrg        if(have_face)
991ea6ae205Smrg            FT_Done_Face(face);
992ea6ae205Smrg        deepDestroyList(xlfd);
993ea6ae205Smrg        xlfd = NULL;
994ea6ae205Smrg        free(filename);
9952d6e8b77Smrg#undef PRIO
996ea6ae205Smrg    }
997ea6ae205Smrg
9987c5a9b20Smrg    while(dirn--)
9997c5a9b20Smrg        free(namelist[dirn]);
10007c5a9b20Smrg    free(namelist);
1001ea6ae205Smrg    n = hashElements(entries);
1002ea6ae205Smrg    fprintf(fontscale, "%d\n", n);
1003ea6ae205Smrg    array = hashArray(entries, 1);
1004ea6ae205Smrg    for(i = 0; i < n; i++)
1005ea6ae205Smrg        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
1006ea6ae205Smrg    destroyHashArray(array);
1007ea6ae205Smrg    entries = NULL;
1008ea6ae205Smrg    if(fontscale_name) {
1009ea6ae205Smrg        fclose(fontscale);
1010ea6ae205Smrg        free(fontscale_name);
1011ea6ae205Smrg    }
1012ea6ae205Smrg
1013ea6ae205Smrg encodings:
1014ea6ae205Smrg    encdir = dsprintf("%s%s", dirname, "encodings.dir");
1015ea6ae205Smrg
1016ea6ae205Smrg    if(encdir == NULL) {
1017ea6ae205Smrg	perror("encodings");
1018ea6ae205Smrg	exit(1);
1019ea6ae205Smrg    }
1020ea6ae205Smrg    unlink(encdir);
1021ea6ae205Smrg
1022ea6ae205Smrg    if (numEncodings) {
1023ea6ae205Smrg	encfile = fopen(encdir, "w");
1024ea6ae205Smrg	if(encfile == NULL) {
1025ea6ae205Smrg	    perror("open(encodings.dir)");
1026ea6ae205Smrg	    exit(1);
1027ea6ae205Smrg	}
1028ea6ae205Smrg        fprintf(encfile, "%d\n", numEncodings);
1029245f6787Smrg        encodingsToDo = sortList(encodingsToDo);
1030ea6ae205Smrg        for(lp = encodingsToDo; lp; lp = lp->next) {
1031ea6ae205Smrg            fprintf(encfile, "%s\n", lp->value);
1032ea6ae205Smrg        }
1033ea6ae205Smrg	fclose (encfile);
1034ea6ae205Smrg    }
1035ea6ae205Smrg
1036ea6ae205Smrg    free(dirname);
1037ea6ae205Smrg    return 1;
1038ea6ae205Smrg}
1039ea6ae205Smrg
1040ea6ae205Smrg#define CODE_IGNORED(c) ((c) < 0x20 || \
1041ea6ae205Smrg                         ((c) >= 0x7F && (c) <= 0xA0) || \
1042ea6ae205Smrg                         (c) == 0xAD || (c) == 0xF71B)
1043663cdc11Smrg
1044ea6ae205Smrgstatic int
10457c5a9b20SmrgcheckEncoding(FT_Face face, const char *encoding_name)
1046ea6ae205Smrg{
1047ea6ae205Smrg    FontEncPtr encoding;
1048ea6ae205Smrg    FontMapPtr mapping;
1049ea6ae205Smrg    int i, j, c, koi8;
1050ea6ae205Smrg    char *n;
1051ea6ae205Smrg
1052ea6ae205Smrg    encoding = FontEncFind(encoding_name, NULL);
1053ea6ae205Smrg    if(!encoding)
1054ea6ae205Smrg        return 0;
1055ea6ae205Smrg
1056ea6ae205Smrg    /* An encoding is ``small'' if one of the following is true:
1057ea6ae205Smrg         - it is linear and has no more than 256 codepoints; or
1058ea6ae205Smrg         - it is a matrix encoding and has no more than one column.
1059663cdc11Smrg
1060ea6ae205Smrg       For small encodings using Unicode indices, we require perfect
1061ea6ae205Smrg       coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1062ea6ae205Smrg
1063ea6ae205Smrg       For large encodings, we require coverage up to bigEncodingFuzz.
1064ea6ae205Smrg
1065ea6ae205Smrg       For encodings using PS names (currently Adobe Standard and
1066ea6ae205Smrg       Adobe Symbol only), we require perfect coverage. */
1067ea6ae205Smrg
1068ea6ae205Smrg
1069ea6ae205Smrg    if(FT_Has_PS_Glyph_Names(face)) {
1070ea6ae205Smrg        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1071ea6ae205Smrg            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
1072ea6ae205Smrg                if(encoding->row_size > 0) {
1073ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1074663cdc11Smrg                        for(j = encoding->first_col;
1075663cdc11Smrg                            j < encoding->row_size;
1076ea6ae205Smrg                            j++) {
1077ea6ae205Smrg                            n = FontEncName((i<<8) | j, mapping);
1078ea6ae205Smrg                            if(n && FT_Get_Name_Index(face, n) == 0) {
1079ea6ae205Smrg                                return 0;
1080ea6ae205Smrg                            }
1081ea6ae205Smrg                        }
1082ea6ae205Smrg                    }
1083ea6ae205Smrg                    return 1;
1084ea6ae205Smrg                } else {
1085ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1086ea6ae205Smrg                        n = FontEncName(i, mapping);
1087ea6ae205Smrg                        if(n && FT_Get_Name_Index(face, n) == 0) {
1088ea6ae205Smrg                            return 0;
1089ea6ae205Smrg                        }
1090ea6ae205Smrg                    }
1091ea6ae205Smrg                    return 1;
1092ea6ae205Smrg                }
1093ea6ae205Smrg            }
1094ea6ae205Smrg        }
1095ea6ae205Smrg    }
1096ea6ae205Smrg
1097ea6ae205Smrg    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1098ea6ae205Smrg        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1099ea6ae205Smrg            int total = 0, failed = 0;
1100ea6ae205Smrg            if(encoding->row_size > 0) {
1101663cdc11Smrg                int estimate =
1102ea6ae205Smrg                    (encoding->size - encoding->first) *
1103ea6ae205Smrg                    (encoding->row_size - encoding->first_col);
1104ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1105663cdc11Smrg                    for(j = encoding->first_col;
1106663cdc11Smrg                        j < encoding->row_size;
1107ea6ae205Smrg                        j++) {
1108ea6ae205Smrg                        c = FontEncRecode((i<<8) | j, mapping);
1109ea6ae205Smrg                        if(CODE_IGNORED(c)) {
1110ea6ae205Smrg                            continue;
1111ea6ae205Smrg                        } else {
1112ea6ae205Smrg                            if(FT_Get_Char_Index(face, c) == 0) {
1113ea6ae205Smrg                                failed++;
1114ea6ae205Smrg                            }
1115ea6ae205Smrg                            total++;
1116ea6ae205Smrg                            if((encoding->size <= 1 && failed > 0) ||
1117ea6ae205Smrg                               ((float)failed >= bigEncodingFuzz * estimate)) {
1118ea6ae205Smrg                                return 0;
1119ea6ae205Smrg                            }
1120ea6ae205Smrg                        }
1121ea6ae205Smrg                    }
1122ea6ae205Smrg                }
1123ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1124ea6ae205Smrg                    return 0;
1125ea6ae205Smrg                else
1126ea6ae205Smrg                    return 1;
1127ea6ae205Smrg            } else {
1128ea6ae205Smrg                int estimate = encoding->size - encoding->first;
1129ea6ae205Smrg                /* For the KOI8 encodings, we ignore the lack of
1130ea6ae205Smrg                   linedrawing and pseudo-math characters */
1131ea6ae205Smrg                if(strncmp(encoding->name, "koi8-", 5) == 0)
1132ea6ae205Smrg                    koi8 = 1;
1133ea6ae205Smrg                else
1134ea6ae205Smrg                    koi8 = 0;
1135ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1136ea6ae205Smrg                    c = FontEncRecode(i, mapping);
1137ea6ae205Smrg                    if(CODE_IGNORED(c) ||
1138ea6ae205Smrg                       (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1139ea6ae205Smrg                        continue;
1140ea6ae205Smrg                    } else {
1141ea6ae205Smrg                        if(FT_Get_Char_Index(face, c) == 0) {
1142ea6ae205Smrg                            failed++;
1143ea6ae205Smrg                        }
1144ea6ae205Smrg                        total++;
1145ea6ae205Smrg                        if((encoding->size <= 256 && failed > 0) ||
1146ea6ae205Smrg                           ((float)failed >= bigEncodingFuzz * estimate)) {
1147ea6ae205Smrg                            return 0;
1148ea6ae205Smrg                        }
1149ea6ae205Smrg                    }
1150ea6ae205Smrg                }
1151ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1152ea6ae205Smrg                    return 0;
1153ea6ae205Smrg                else
1154ea6ae205Smrg                    return 1;
1155ea6ae205Smrg            }
1156ea6ae205Smrg        }
1157ea6ae205Smrg    }
1158ea6ae205Smrg    return 0;
1159ea6ae205Smrg}
1160ea6ae205Smrg
1161663cdc11Smrgstatic int
1162ea6ae205Smrgfind_cmap(int type, int pid, int eid, FT_Face face)
1163ea6ae205Smrg{
1164ea6ae205Smrg    int i, n, rc;
1165ea6ae205Smrg    FT_CharMap cmap = NULL;
1166ea6ae205Smrg
1167ea6ae205Smrg    n = face->num_charmaps;
1168ea6ae205Smrg
1169ea6ae205Smrg    switch(type) {
1170ea6ae205Smrg    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
1171ea6ae205Smrg        for(i=0; i<n; i++) {
1172ea6ae205Smrg            cmap = face->charmaps[i];
1173ea6ae205Smrg            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1174ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1175ea6ae205Smrg                if(rc == 0)
1176ea6ae205Smrg                    return 1;
1177ea6ae205Smrg            }
1178ea6ae205Smrg        }
1179ea6ae205Smrg        break;
1180ea6ae205Smrg    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
1181ea6ae205Smrg        /* prefer Microsoft Unicode */
1182ea6ae205Smrg        for(i=0; i<n; i++) {
1183ea6ae205Smrg            cmap = face->charmaps[i];
1184663cdc11Smrg            if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1185ea6ae205Smrg               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
1186ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1187ea6ae205Smrg                if(rc == 0)
1188ea6ae205Smrg                    return 1;
1189ea6ae205Smrg            }
1190ea6ae205Smrg        }
1191ea6ae205Smrg        /* Try Apple Unicode */
1192ea6ae205Smrg        for(i=0; i<n; i++) {
1193ea6ae205Smrg            cmap = face->charmaps[i];
1194ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
1195ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1196ea6ae205Smrg                if(rc == 0)
1197ea6ae205Smrg                    return 1;
1198ea6ae205Smrg            }
1199ea6ae205Smrg        }
1200ea6ae205Smrg        /* ISO Unicode? */
1201ea6ae205Smrg        for(i=0; i<n; i++) {
1202ea6ae205Smrg            cmap = face->charmaps[i];
1203ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_ISO) {
1204ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1205ea6ae205Smrg                if(rc == 0)
1206ea6ae205Smrg                    return 1;
1207ea6ae205Smrg            }
1208ea6ae205Smrg        }
1209ea6ae205Smrg        break;
1210ea6ae205Smrg    default:
1211ea6ae205Smrg        return 0;
1212ea6ae205Smrg    }
1213ea6ae205Smrg    return 0;
1214ea6ae205Smrg}
1215ea6ae205Smrg
1216ea6ae205Smrgstatic int
12177c5a9b20SmrgcheckExtraEncoding(FT_Face face, const char *encoding_name, int found)
1218ea6ae205Smrg{
1219ea6ae205Smrg    int c;
1220ea6ae205Smrg
1221ea6ae205Smrg    if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1222ea6ae205Smrg        if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
12237c5a9b20Smrg            int cfound = 0;
1224ea6ae205Smrg             /* Export as Unicode if there are at least 15 BMP
1225ea6ae205Smrg               characters that are not a space or ignored. */
1226ea6ae205Smrg            for(c = 0x21; c < 0x10000; c++) {
1227ea6ae205Smrg                if(CODE_IGNORED(c))
1228ea6ae205Smrg                    continue;
1229ea6ae205Smrg                if(FT_Get_Char_Index(face, c) > 0)
12307c5a9b20Smrg                    cfound++;
12317c5a9b20Smrg                if(cfound >= 15)
1232ea6ae205Smrg                    return 1;
1233ea6ae205Smrg            }
1234ea6ae205Smrg            return 0;
1235ea6ae205Smrg        } else
1236ea6ae205Smrg            return 0;
1237ea6ae205Smrg    } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1238ea6ae205Smrg        if(find_cmap(FONT_ENCODING_TRUETYPE,
1239ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
1240ea6ae205Smrg                     face))
1241ea6ae205Smrg            return 1;
1242ea6ae205Smrg        else
1243ea6ae205Smrg            return 0;
1244ea6ae205Smrg    } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1245ea6ae205Smrg        if(!found) {
1246ea6ae205Smrg            if(FT_Has_PS_Glyph_Names(face))
1247ea6ae205Smrg                return 1;
1248ea6ae205Smrg            else
1249ea6ae205Smrg                return 0;
1250ea6ae205Smrg        } else
1251ea6ae205Smrg            return 0;
1252ea6ae205Smrg    } else {
1253ea6ae205Smrg        fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
1254ea6ae205Smrg        return 0;
1255ea6ae205Smrg    }
1256ea6ae205Smrg}
1257ea6ae205Smrg
1258663cdc11Smrgstatic const char*
1259663cdc11Smrgnotice_foundry(const char *notice)
1260ea6ae205Smrg{
12617c5a9b20Smrg    unsigned int i;
1262ea6ae205Smrg    for(i = 0; i < countof(notice_foundries); i++)
1263ea6ae205Smrg        if(notice && strstr(notice, notice_foundries[i][0]))
1264ea6ae205Smrg            return notice_foundries[i][1];
1265ea6ae205Smrg    return NULL;
1266ea6ae205Smrg}
1267ea6ae205Smrg
1268ea6ae205Smrgstatic int
1269663cdc11Smrgvendor_match(const signed char *vendor, const char *vendor_string)
1270ea6ae205Smrg{
1271ea6ae205Smrg    /* vendor is not necessarily NUL-terminated. */
12727c5a9b20Smrg    size_t i, len;
1273ea6ae205Smrg    len = strlen(vendor_string);
1274ea6ae205Smrg    if(memcmp(vendor, vendor_string, len) != 0)
1275ea6ae205Smrg        return 0;
1276ea6ae205Smrg    for(i = len; i < 4; i++)
1277ea6ae205Smrg        if(vendor[i] != ' ' && vendor[i] != '\0')
1278ea6ae205Smrg            return 0;
1279ea6ae205Smrg    return 1;
1280ea6ae205Smrg}
1281ea6ae205Smrg
1282663cdc11Smrgstatic const char*
1283663cdc11Smrgvendor_foundry(const signed char *vendor)
1284ea6ae205Smrg{
12857c5a9b20Smrg    unsigned int i;
1286ea6ae205Smrg    for(i = 0; i < countof(vendor_foundries); i++)
1287ea6ae205Smrg        if(vendor_match(vendor, vendor_foundries[i][0]))
1288ea6ae205Smrg            return vendor_foundries[i][1];
1289ea6ae205Smrg    return NULL;
1290ea6ae205Smrg}
1291ea6ae205Smrg
1292ea6ae205Smrgstatic int
1293ea6ae205SmrgreadEncodings(ListPtr encodings, char *dirname)
1294ea6ae205Smrg{
1295ea6ae205Smrg    char *fullname;
1296ea6ae205Smrg    DIR *dirp;
1297ea6ae205Smrg    struct dirent *file;
1298ea6ae205Smrg    char **names, **name;
1299ea6ae205Smrg
1300ea6ae205Smrg    if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1301ea6ae205Smrg        dirname[strlen(dirname) - 1] = '\0';
1302ea6ae205Smrg
1303ea6ae205Smrg    dirp = opendir(dirname);
1304ea6ae205Smrg    if(dirp == NULL) {
1305ea6ae205Smrg        perror("opendir");
1306ea6ae205Smrg        return -1;
1307ea6ae205Smrg    }
1308ea6ae205Smrg
1309ea6ae205Smrg    while((file = readdir(dirp)) != NULL) {
1310ea6ae205Smrg        fullname = dsprintf("%s/%s", dirname, file->d_name);
1311ea6ae205Smrg        if(fullname == NULL) {
1312ea6ae205Smrg            fprintf(stderr, "Couldn't allocate fullname\n");
1313ea6ae205Smrg            closedir(dirp);
1314ea6ae205Smrg            return -1;
1315ea6ae205Smrg        }
1316663cdc11Smrg
1317ea6ae205Smrg        names = FontEncIdentify(fullname);
1318ea6ae205Smrg        if(!names)
1319ea6ae205Smrg            continue;
1320ea6ae205Smrg
1321ea6ae205Smrg        for(name = names; *name; name++) {
1322ea6ae205Smrg            if(fullname[0] != '/' && !relative) {
1323ea6ae205Smrg                char *n;
1324ea6ae205Smrg                n = dsprintf("%s%s", encodingPrefix, fullname);
1325ea6ae205Smrg                if(n == NULL) {
1326ea6ae205Smrg                    fprintf(stderr, "Couldn't allocate name\n");
1327ea6ae205Smrg                    closedir(dirp);
1328ea6ae205Smrg                    return -1;
1329ea6ae205Smrg                }
1330ea6ae205Smrg                encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1331ea6ae205Smrg                free(n);
1332ea6ae205Smrg            } else {
1333663cdc11Smrg                encodingsToDo =
1334ea6ae205Smrg                    listConsF(encodingsToDo, "%s %s", *name, fullname);
1335ea6ae205Smrg            }
1336ea6ae205Smrg            if(encodingsToDo == NULL) {
1337ea6ae205Smrg                fprintf(stderr, "Couldn't allocate encodings\n");
1338ea6ae205Smrg                closedir(dirp);
1339ea6ae205Smrg                return -1;
1340ea6ae205Smrg            }
1341ea6ae205Smrg        }
1342ea6ae205Smrg        free(names);            /* only the spine */
1343ea6ae205Smrg    }
1344ea6ae205Smrg    closedir(dirp);
1345ea6ae205Smrg    return 0;
1346ea6ae205Smrg}
1347