mkfontscale.c revision 329eaa64
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>
30329eaa64Smrg#include <strings.h>
31ea6ae205Smrg
32ea6ae205Smrg#include <sys/types.h>
332d6e8b77Smrg#include <sys/stat.h>
34ea6ae205Smrg#include <dirent.h>
35ea6ae205Smrg#include <unistd.h>
36ea6ae205Smrg#include <errno.h>
37ea6ae205Smrg#include <ctype.h>
38ea6ae205Smrg
39ea6ae205Smrg#include <X11/Xos.h>
40af7d3019Smrg#include <X11/Xfuncproto.h>
41ea6ae205Smrg#include <X11/fonts/fontenc.h>
42ea6ae205Smrg#include <ft2build.h>
43ea6ae205Smrg#include FT_FREETYPE_H
44ea6ae205Smrg#include FT_SFNT_NAMES_H
45ea6ae205Smrg#include FT_TRUETYPE_TABLES_H
46ea6ae205Smrg#include FT_TRUETYPE_IDS_H
47ea6ae205Smrg#include FT_TYPE1_TABLES_H
48ea6ae205Smrg#include FT_BDF_H
49ea6ae205Smrg#include FT_XFREE86_H
50ea6ae205Smrg
51ea6ae205Smrg#include "list.h"
527c5a9b20Smrg#include "constlist.h"
53ea6ae205Smrg#include "hash.h"
54ea6ae205Smrg#include "data.h"
55ea6ae205Smrg#include "ident.h"
56ea6ae205Smrg
57ea6ae205Smrg#define NPREFIX 1024
58ea6ae205Smrg
59ea6ae205Smrg#ifndef MAXFONTFILENAMELEN
60ea6ae205Smrg#define MAXFONTFILENAMELEN 1024
61ea6ae205Smrg#endif
62ea6ae205Smrg#ifndef MAXFONTNAMELEN
63ea6ae205Smrg#define MAXFONTNAMELEN 1024
64ea6ae205Smrg#endif
65ea6ae205Smrg
66245f6787Smrg/* Two levels of macro calls are needed so that we stringify the value
67245f6787Smrg   of MAXFONT... and not the string "MAXFONT..." */
68245f6787Smrg#define QUOTE(x)	#x
69245f6787Smrg#define STRINGIFY(x)	QUOTE(x)
70245f6787Smrg
718b165ca7Smrgstatic const char *encodings_array[] =
72ea6ae205Smrg    { "ascii-0",
73ea6ae205Smrg      "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
74ea6ae205Smrg      "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
75ea6ae205Smrg      "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
76ea6ae205Smrg      "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
77ea6ae205Smrg      "iso8859-15", "iso8859-16",
78ea6ae205Smrg      "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
79ea6ae205Smrg      "tis620-2",
80ea6ae205Smrg      "sun.unicode.india-0", "suneu-greek",
81ea6ae205Smrg      "adobe-standard", "adobe-symbol",
82ea6ae205Smrg      "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
83ea6ae205Smrg      /* But not "adobe-dingbats", as it uses generic glyph names. */
84ea6ae205Smrg      "cns11643-1", "cns11643-2", "cns11643-3",
85ea6ae205Smrg      "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
86ea6ae205Smrg      "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
87ea6ae205Smrg      "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
88ea6ae205Smrg      "ksc5601.1987-0", "ksc5601.1992-3"};
89ea6ae205Smrg
908b165ca7Smrgstatic const char *extra_encodings_array[] =
91ea6ae205Smrg    { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
92ea6ae205Smrg
937c5a9b20Smrgstatic ConstListPtr encodings, extra_encodings;
94663cdc11Smrgstatic const char *outfilename;
95ea6ae205Smrg
96ea6ae205Smrg#define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
97ea6ae205Smrg
98663cdc11Smrgstatic int doDirectory(const char*, int, ListPtr);
997c5a9b20Smrgstatic int checkEncoding(FT_Face face, const char *encoding_name);
1007c5a9b20Smrgstatic int checkExtraEncoding(FT_Face face, const char *encoding_name, int found);
101ea6ae205Smrgstatic int find_cmap(int type, int pid, int eid, FT_Face face);
102663cdc11Smrgstatic const char* notice_foundry(const char *notice);
103663cdc11Smrgstatic const char* vendor_foundry(const signed char *vendor);
104ea6ae205Smrgstatic int readFontScale(HashTablePtr entries, char *dirname);
105ea6ae205SmrgListPtr makeXLFD(char *filename, FT_Face face, int);
106ea6ae205Smrgstatic int readEncodings(ListPtr encodings, char *dirname);
107ea6ae205Smrg
108ea6ae205Smrgstatic FT_Library ft_library;
109ea6ae205Smrgstatic float bigEncodingFuzz = 0.02;
110ea6ae205Smrg
111ea6ae205Smrgstatic int relative;
112ea6ae205Smrgstatic int doScalable;
113ea6ae205Smrgstatic int doBitmaps;
114ea6ae205Smrgstatic int doISO10646_1_encoding;
115ea6ae205Smrgstatic int onlyEncodings;
116ea6ae205Smrgstatic ListPtr encodingsToDo;
117ea6ae205Smrgstatic int reencodeLegacy;
118ea6ae205Smrgstatic char *encodingPrefix;
119ea6ae205Smrgstatic char *exclusionSuffix;
120af7d3019Smrgstatic char *ProgramName;
121ea6ae205Smrg
122af7d3019Smrgstatic void _X_NORETURN _X_COLD
123ea6ae205Smrgusage(void)
124ea6ae205Smrg{
125af7d3019Smrg    fprintf(stderr, "Usage:\n"
126ea6ae205Smrg            "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
127af7d3019Smrg            "            [ -a encoding ] [ -f fuzz ] [ -l ]\n"
128ea6ae205Smrg            "            [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
129af7d3019Smrg            "            [-u] [-U] [-v] [ directory ]...\n");
130af7d3019Smrg    exit(1);
131af7d3019Smrg}
132af7d3019Smrg
133af7d3019Smrgstatic void _X_NORETURN _X_COLD
134af7d3019Smrgmissing_arg (const char *option)
135af7d3019Smrg{
136af7d3019Smrg    fprintf(stderr, "%s: %s requires an argument\n", ProgramName, option);
137af7d3019Smrg    usage();
138ea6ae205Smrg}
139ea6ae205Smrg
140ea6ae205Smrgint
141ea6ae205Smrgmain(int argc, char **argv)
142ea6ae205Smrg{
143ea6ae205Smrg    int argn;
144ea6ae205Smrg    FT_Error ftrc;
145ea6ae205Smrg    int rc, ll = 0;
146ea6ae205Smrg    char prefix[NPREFIX];
147ea6ae205Smrg
148af7d3019Smrg    ProgramName = argv[0];
149ea6ae205Smrg    encodingPrefix = NULL;
150ea6ae205Smrg    exclusionSuffix = NULL;
151ea6ae205Smrg
152ea6ae205Smrg    if(getcwd(prefix, NPREFIX - 1) == NULL) {
153ea6ae205Smrg        perror("Couldn't get cwd");
154ea6ae205Smrg        exit(1);
155ea6ae205Smrg    }
156ea6ae205Smrg    if(prefix[strlen(prefix) - 1] != '/')
1577c5a9b20Smrg        encodingPrefix = dsprintf("%s/", prefix);
1587c5a9b20Smrg    else
1597c5a9b20Smrg        encodingPrefix = strdup(prefix);
160ea6ae205Smrg
161ea6ae205Smrg    outfilename = NULL;
162ea6ae205Smrg
1637c5a9b20Smrg    encodings = makeConstList(encodings_array, countof(encodings_array), NULL, 0);
164ea6ae205Smrg
1657c5a9b20Smrg    extra_encodings = makeConstList(extra_encodings_array,
1667c5a9b20Smrg				    countof(extra_encodings_array),
1677c5a9b20Smrg				    NULL, 0);
168ea6ae205Smrg    doBitmaps = 0;
169ea6ae205Smrg    doISO10646_1_encoding = 1;
170ea6ae205Smrg    doScalable = 1;
171ea6ae205Smrg    onlyEncodings = 0;
172ea6ae205Smrg    relative = 0;
173ea6ae205Smrg    reencodeLegacy = 1;
174ea6ae205Smrg    encodingsToDo = NULL;
175ea6ae205Smrg
176ea6ae205Smrg    argn = 1;
177ea6ae205Smrg    while(argn < argc) {
178ea6ae205Smrg        if(argv[argn][0] == '\0' || argv[argn][0] != '-')
179ea6ae205Smrg            break;
180ea6ae205Smrg        if(argv[argn][1] == '-') {
181ea6ae205Smrg            argn++;
182ea6ae205Smrg            break;
183ea6ae205Smrg        } else if (strcmp(argv[argn], "-x") == 0) {
184ea6ae205Smrg            if(argn >= argc - 1) {
185af7d3019Smrg                missing_arg("-x");
186ea6ae205Smrg            }
187ea6ae205Smrg            exclusionSuffix = argv[argn + 1];
188ea6ae205Smrg            argn += 2;
189ea6ae205Smrg        } else if(strcmp(argv[argn], "-a") == 0) {
190ea6ae205Smrg            if(argn >= argc - 1) {
191af7d3019Smrg                missing_arg("-a");
192ea6ae205Smrg            }
1937c5a9b20Smrg            makeConstList((const char **)&argv[argn + 1], 1, encodings, 0);
194ea6ae205Smrg            argn += 2;
195ea6ae205Smrg        } else if(strcmp(argv[argn], "-p") == 0) {
196ea6ae205Smrg            if(argn >= argc - 1) {
197af7d3019Smrg                missing_arg("-p");
198ea6ae205Smrg            }
199ea6ae205Smrg            if(strlen(argv[argn + 1]) > NPREFIX - 1) {
200af7d3019Smrg                fprintf(stderr, "%s: argument to -p cannot be longer than "
201af7d3019Smrg                        "%d characters\n", ProgramName, NPREFIX - 1);
202ea6ae205Smrg                usage();
203ea6ae205Smrg            }
204ea6ae205Smrg            free(encodingPrefix);
2057c5a9b20Smrg            encodingPrefix = strdup(argv[argn + 1]);
206ea6ae205Smrg            argn += 2;
207ea6ae205Smrg        } else if(strcmp(argv[argn], "-e") == 0) {
208ea6ae205Smrg            if(argn >= argc - 1) {
209af7d3019Smrg                missing_arg("-e");
210ea6ae205Smrg            }
211ea6ae205Smrg            rc = readEncodings(encodingsToDo, argv[argn + 1]);
212ea6ae205Smrg            if(rc < 0)
213ea6ae205Smrg                exit(1);
214ea6ae205Smrg            argn += 2;
215ea6ae205Smrg        } else if(strcmp(argv[argn], "-b") == 0) {
216ea6ae205Smrg            doBitmaps = 1;
217ea6ae205Smrg            argn++;
218ea6ae205Smrg        } else if(strcmp(argv[argn], "-u") == 0) {
219ea6ae205Smrg            doISO10646_1_encoding = 0;
220ea6ae205Smrg            argn++;
221ea6ae205Smrg        } else if(strcmp(argv[argn], "-U") == 0) {
222ea6ae205Smrg            doISO10646_1_encoding = 1;
223663cdc11Smrg            argn++;
224ea6ae205Smrg        } else if(strcmp(argv[argn], "-s") == 0) {
225ea6ae205Smrg            doScalable = 0;
226ea6ae205Smrg            argn++;
227ea6ae205Smrg        } else if(strcmp(argv[argn], "-n") == 0) {
228ea6ae205Smrg            onlyEncodings = 1;
229ea6ae205Smrg            argn++;
230ea6ae205Smrg        } else if(strcmp(argv[argn], "-r") == 0) {
231ea6ae205Smrg            relative = 1;
232ea6ae205Smrg            argn++;
233ea6ae205Smrg        } else if(strcmp(argv[argn], "-l") == 0) {
234ea6ae205Smrg            reencodeLegacy = !reencodeLegacy;
235ea6ae205Smrg            argn++;
236ea6ae205Smrg        } else if(strcmp(argv[argn], "-o") == 0) {
237ea6ae205Smrg            if(argn >= argc - 1) {
238af7d3019Smrg                missing_arg("-o");
239ea6ae205Smrg            }
240ea6ae205Smrg            outfilename = argv[argn + 1];
241ea6ae205Smrg            argn += 2;
242ea6ae205Smrg        } else if(strcmp(argv[argn], "-f") == 0) {
243ea6ae205Smrg            if(argn >= argc - 1) {
244af7d3019Smrg                missing_arg("-f");
245ea6ae205Smrg            }
246ea6ae205Smrg            bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
247ea6ae205Smrg            argn += 2;
248af7d3019Smrg	} else if (strcmp(argv[argn], "-v") == 0) {
249af7d3019Smrg	    printf("%s\n", PACKAGE_STRING);
250af7d3019Smrg	    exit(0);
251ea6ae205Smrg	} else {
252ea6ae205Smrg            usage();
253ea6ae205Smrg        }
254ea6ae205Smrg    }
255ea6ae205Smrg
256ea6ae205Smrg    if(outfilename == NULL) {
257ea6ae205Smrg        if(doBitmaps)
258ea6ae205Smrg            outfilename = "fonts.dir";
259663cdc11Smrg        else
260ea6ae205Smrg            outfilename = "fonts.scale";
261ea6ae205Smrg    }
262ea6ae205Smrg
263ea6ae205Smrg    ftrc = FT_Init_FreeType(&ft_library);
264ea6ae205Smrg    if(ftrc) {
265ea6ae205Smrg        fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
266ea6ae205Smrg        exit(1);
267ea6ae205Smrg    }
268ea6ae205Smrg
269ea6ae205Smrg    ll = listLength(encodingsToDo);
270ea6ae205Smrg
271ea6ae205Smrg    if (argn == argc)
272ea6ae205Smrg        doDirectory(".", ll, encodingsToDo);
273ea6ae205Smrg    else
274ea6ae205Smrg        while(argn < argc) {
275ea6ae205Smrg            doDirectory(argv[argn], ll, encodingsToDo);
276ea6ae205Smrg            argn++;
277ea6ae205Smrg        }
278ea6ae205Smrg    return 0;
279ea6ae205Smrg}
280ea6ae205Smrg
281ea6ae205Smrgstatic int
282ea6ae205SmrggetNameHelper(FT_Face face, int nid, int pid, int eid,
283ea6ae205Smrg              FT_SfntName *name_return)
284ea6ae205Smrg{
285ea6ae205Smrg    FT_SfntName name;
286ea6ae205Smrg    int n, i;
287ea6ae205Smrg
288ea6ae205Smrg    n = FT_Get_Sfnt_Name_Count(face);
289ea6ae205Smrg    if(n <= 0)
290ea6ae205Smrg        return 0;
291ea6ae205Smrg
292ea6ae205Smrg    for(i = 0; i < n; i++) {
293ea6ae205Smrg        if(FT_Get_Sfnt_Name(face, i, &name))
294ea6ae205Smrg            continue;
295ea6ae205Smrg        if(name.name_id == nid &&
296ea6ae205Smrg           name.platform_id == pid &&
297ea6ae205Smrg           (eid < 0 || name.encoding_id == eid)) {
298ea6ae205Smrg            switch(name.platform_id) {
299ea6ae205Smrg            case TT_PLATFORM_APPLE_UNICODE:
300ea6ae205Smrg            case TT_PLATFORM_MACINTOSH:
301ea6ae205Smrg                if(name.language_id != TT_MAC_LANGID_ENGLISH)
302ea6ae205Smrg                    continue;
303ea6ae205Smrg                break;
304ea6ae205Smrg            case TT_PLATFORM_MICROSOFT:
305ea6ae205Smrg                if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
306ea6ae205Smrg                   name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
307ea6ae205Smrg                    continue;
308ea6ae205Smrg                break;
309ea6ae205Smrg            default:
310ea6ae205Smrg                continue;
311ea6ae205Smrg            }
312ea6ae205Smrg            if(name.string_len > 0) {
313ea6ae205Smrg                *name_return = name;
314ea6ae205Smrg                return 1;
315ea6ae205Smrg            }
316ea6ae205Smrg        }
317ea6ae205Smrg    }
318ea6ae205Smrg    return 0;
319ea6ae205Smrg}
320ea6ae205Smrg
321ea6ae205Smrgstatic char *
322ea6ae205SmrggetName(FT_Face face, int nid)
323ea6ae205Smrg{
324ea6ae205Smrg    FT_SfntName name;
325ea6ae205Smrg    char *string;
3267c5a9b20Smrg    unsigned int i;
327ea6ae205Smrg
328663cdc11Smrg    if(getNameHelper(face, nid,
329ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
330663cdc11Smrg       getNameHelper(face, nid,
331ea6ae205Smrg                     TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
332ea6ae205Smrg        string = malloc(name.string_len / 2 + 1);
333ea6ae205Smrg        if(string == NULL) {
334ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
335ea6ae205Smrg            exit(1);
336ea6ae205Smrg        }
337ea6ae205Smrg        for(i = 0; i < name.string_len / 2; i++) {
338ea6ae205Smrg            if(name.string[2 * i] != 0)
339ea6ae205Smrg                string[i] = '?';
340ea6ae205Smrg            else
341ea6ae205Smrg                string[i] = name.string[2 * i + 1];
342ea6ae205Smrg        }
343ea6ae205Smrg        string[i] = '\0';
344ea6ae205Smrg        return string;
345ea6ae205Smrg    }
346ea6ae205Smrg
347ea6ae205Smrg    /* Pretend that Apple Roman is ISO 8859-1. */
348ea6ae205Smrg    if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
349ea6ae205Smrg                     &name)) {
350ea6ae205Smrg        string = malloc(name.string_len + 1);
351ea6ae205Smrg        if(string == NULL) {
352ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
353ea6ae205Smrg            exit(1);
354ea6ae205Smrg        }
355ea6ae205Smrg        memcpy(string, name.string, name.string_len);
356ea6ae205Smrg        string[name.string_len] = '\0';
357ea6ae205Smrg        return string;
358ea6ae205Smrg    }
359ea6ae205Smrg
360ea6ae205Smrg    return NULL;
361ea6ae205Smrg}
362ea6ae205Smrg
363663cdc11Smrgstatic const char*
364ea6ae205Smrgos2Weight(int weight)
365ea6ae205Smrg{
366ea6ae205Smrg    if(weight < 150)
367ea6ae205Smrg        return "thin";
368ea6ae205Smrg    else if(weight < 250)
369ea6ae205Smrg        return "extralight";
370ea6ae205Smrg    else if(weight < 350)
371ea6ae205Smrg        return "light";
372ea6ae205Smrg    else if(weight < 450)
373ea6ae205Smrg        return "medium";        /* officially "normal" */
374ea6ae205Smrg    else if(weight < 550)
375ea6ae205Smrg        return "medium";
376ea6ae205Smrg    else if(weight < 650)
377ea6ae205Smrg        return "semibold";
378ea6ae205Smrg    else if(weight < 750)
379ea6ae205Smrg        return "bold";
380ea6ae205Smrg    else if(weight < 850)
381ea6ae205Smrg        return "extrabold";
382663cdc11Smrg    else
383ea6ae205Smrg        return "black";
384ea6ae205Smrg}
385ea6ae205Smrg
386663cdc11Smrgstatic const char*
387ea6ae205Smrgos2Width(int width)
388ea6ae205Smrg{
389ea6ae205Smrg    if(width <= 1)
390ea6ae205Smrg        return "ultracondensed";
391ea6ae205Smrg    else if(width <= 2)
392ea6ae205Smrg        return "extracondensed";
393ea6ae205Smrg    else if(width <= 3)
394ea6ae205Smrg        return "condensed";
395ea6ae205Smrg    else if(width <= 4)
396ea6ae205Smrg        return "semicondensed";
397ea6ae205Smrg    else if(width <= 5)
398ea6ae205Smrg        return "normal";
399ea6ae205Smrg    else if(width <= 6)
400ea6ae205Smrg        return "semiexpanded";
401ea6ae205Smrg    else if(width <= 7)
402ea6ae205Smrg        return "expanded";
403ea6ae205Smrg    else if(width <= 8)
404ea6ae205Smrg        return "extraexpanded";
405ea6ae205Smrg    else
406ea6ae205Smrg        return "ultraexpanded";
407ea6ae205Smrg}
408ea6ae205Smrg
409663cdc11Smrgstatic const char *widths[] = {
410ea6ae205Smrg    "ultracondensed", "extracondensed", "condensed", "semicondensed",
411663cdc11Smrg    "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
412ea6ae205Smrg};
413ea6ae205Smrg
414ea6ae205Smrg#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
415ea6ae205Smrg
416663cdc11Smrgstatic const char*
417663cdc11SmrgnameWidth(const char *name)
418ea6ae205Smrg{
419ea6ae205Smrg    char buf[500];
4207c5a9b20Smrg    unsigned int i;
4217c5a9b20Smrg    size_t n = strlen(name);
422ea6ae205Smrg
423ea6ae205Smrg    if(n >= 499) return NULL;
424ea6ae205Smrg    for(i = 0; i < n; i++)
425ea6ae205Smrg        buf[i] = tolower(name[i]);
426ea6ae205Smrg    buf[i] = '\0';
427ea6ae205Smrg
428ea6ae205Smrg    for(i = 0; i < NUMWIDTHS; i++)
429ea6ae205Smrg        if(strstr(buf, widths[i]))
430ea6ae205Smrg            return widths[i];
431ea6ae205Smrg    return NULL;
432ea6ae205Smrg}
433ea6ae205Smrg
434663cdc11Smrgstatic const char*
435663cdc11Smrgt1Weight(const char *weight)
436ea6ae205Smrg{
437ea6ae205Smrg    if(!weight)
438ea6ae205Smrg        return NULL;
43919108c71Smaya    if(strcasecmp(weight, "Thin") == 0)
440ea6ae205Smrg        return "thin";
44119108c71Smaya    if(strcasecmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
442663cdc11Smrg        return "extralight";
44319108c71Smaya    if(strcasecmp(weight, "Light") == 0)
444ea6ae205Smrg        return "light";
44519108c71Smaya    if(strcasecmp(weight, "Regular") == 0)
446ea6ae205Smrg        return "medium";
44719108c71Smaya    if(strcasecmp(weight, "Normal") == 0)
448ea6ae205Smrg        return "medium";
449329eaa64Smrg    if(strcasecmp(weight, "Plain") == 0)
450329eaa64Smrg        return "medium";
45119108c71Smaya    if(strcasecmp(weight, "Medium") == 0)
452ea6ae205Smrg        return "medium";
45319108c71Smaya    if(strcasecmp(weight, "Book") == 0)
454ea6ae205Smrg        return "medium";
45519108c71Smaya    if(strcasecmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
45619108c71Smaya        return "medium";
45719108c71Smaya    if(strcasecmp(weight, "Demi") == 0)
458ea6ae205Smrg        return "semibold";
45919108c71Smaya    if(strcasecmp(weight, "DemiBold") == 0)
460ea6ae205Smrg        return "semibold";
46119108c71Smaya    if(strcasecmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
462ea6ae205Smrg        return "semibold";
46319108c71Smaya    else if(strcasecmp(weight, "Bold") == 0)
464ea6ae205Smrg        return "bold";
46519108c71Smaya    else if(strcasecmp(weight, "ExtraBold") == 0) /* freefonts uses this */
466663cdc11Smrg        return "extrabold";
467329eaa64Smrg    else if(strcasecmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
468329eaa64Smrg        return "extrabold";
46919108c71Smaya    else if(strcasecmp(weight, "Black") == 0)
470ea6ae205Smrg        return "black";
471ea6ae205Smrg    else {
472ea6ae205Smrg        fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
473ea6ae205Smrg        return NULL;
474ea6ae205Smrg    }
475ea6ae205Smrg}
476ea6ae205Smrg
477ea6ae205Smrgstatic int
478ea6ae205Smrgunsafe(char c)
479ea6ae205Smrg{
480663cdc11Smrg    return
481ea6ae205Smrg        c < 0x20 || c > 0x7E ||
482ea6ae205Smrg        c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
483ea6ae205Smrg}
484ea6ae205Smrg
485663cdc11Smrgstatic const char *
486663cdc11Smrgsafe(const char* s)
487ea6ae205Smrg{
488ea6ae205Smrg    int i, len, safe_flag = 1;
489ea6ae205Smrg    char *t;
490ea6ae205Smrg
491ea6ae205Smrg    i = 0;
492ea6ae205Smrg    while(s[i] != '\0') {
493ea6ae205Smrg        if(unsafe(s[i]))
494ea6ae205Smrg            safe_flag = 0;
495ea6ae205Smrg        i++;
496ea6ae205Smrg    }
497ea6ae205Smrg
498af7d3019Smrg    if(safe_flag) return strdup(s);
499ea6ae205Smrg
500ea6ae205Smrg    len = i;
501ea6ae205Smrg    t = malloc(len + 1);
502ea6ae205Smrg    if(t == NULL) {
503ea6ae205Smrg        perror("Couldn't allocate string");
504ea6ae205Smrg        exit(1);
505ea6ae205Smrg    }
506ea6ae205Smrg
507ea6ae205Smrg    for(i = 0; i < len; i++) {
508ea6ae205Smrg        if(unsafe(s[i]))
509ea6ae205Smrg            t[i] = ' ';
510ea6ae205Smrg        else
511ea6ae205Smrg            t[i] = s[i];
512ea6ae205Smrg    }
513ea6ae205Smrg    t[i] = '\0';
514ea6ae205Smrg    return t;
515ea6ae205Smrg}
516ea6ae205Smrg
517ea6ae205SmrgListPtr
518ea6ae205SmrgmakeXLFD(char *filename, FT_Face face, int isBitmap)
519ea6ae205Smrg{
520ea6ae205Smrg    ListPtr xlfd = NULL;
521663cdc11Smrg    const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
522af7d3019Smrg        *spacing, *full_name, *tmp;
523ea6ae205Smrg    TT_Header *head;
524ea6ae205Smrg    TT_HoriHeader *hhea;
525ea6ae205Smrg    TT_OS2 *os2;
526ea6ae205Smrg    TT_Postscript *post;
527ea6ae205Smrg    PS_FontInfoRec *t1info, t1info_rec;
528ea6ae205Smrg    int rc;
529ea6ae205Smrg
530ea6ae205Smrg    foundry = NULL;
531ea6ae205Smrg    family = NULL;
532ea6ae205Smrg    weight = NULL;
533ea6ae205Smrg    slant = NULL;
534ea6ae205Smrg    sWidth = NULL;
535ea6ae205Smrg    adstyle = NULL;
536ea6ae205Smrg    spacing = NULL;
537ea6ae205Smrg    full_name = NULL;
538ea6ae205Smrg
539ea6ae205Smrg    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
540ea6ae205Smrg    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
541ea6ae205Smrg    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
542ea6ae205Smrg    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
543ea6ae205Smrg
544ea6ae205Smrg    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
545ea6ae205Smrg    if(rc == 0)
546ea6ae205Smrg        t1info = &t1info_rec;
547ea6ae205Smrg    else
548ea6ae205Smrg        t1info = NULL;
549663cdc11Smrg
550ea6ae205Smrg    if(!family)
551ea6ae205Smrg        family = getName(face, TT_NAME_ID_FONT_FAMILY);
552ea6ae205Smrg    if(!family)
553ea6ae205Smrg        family = getName(face, TT_NAME_ID_FULL_NAME);
554ea6ae205Smrg    if(!family)
555ea6ae205Smrg        family = getName(face, TT_NAME_ID_PS_NAME);
556ea6ae205Smrg
557ea6ae205Smrg    if(!full_name)
558ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_FULL_NAME);
559ea6ae205Smrg    if(!full_name)
560ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_PS_NAME);
561ea6ae205Smrg
562ea6ae205Smrg    if(os2 && os2->version != 0xFFFF) {
563ea6ae205Smrg        if(!weight)
564ea6ae205Smrg            weight = os2Weight(os2->usWeightClass);
565ea6ae205Smrg        if(!sWidth)
566ea6ae205Smrg            sWidth = os2Width(os2->usWidthClass);
567ea6ae205Smrg        if(!foundry)
568ea6ae205Smrg            foundry = vendor_foundry(os2->achVendID);
569ea6ae205Smrg        if(!slant)
570ea6ae205Smrg            slant = os2->fsSelection & 1 ? "i" : "r";
571ea6ae205Smrg    }
572ea6ae205Smrg
573ea6ae205Smrg    if(post) {
574ea6ae205Smrg        if(!spacing) {
575ea6ae205Smrg            if(post->isFixedPitch) {
576ea6ae205Smrg                if(hhea->min_Left_Side_Bearing >= 0 &&
577ea6ae205Smrg                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
578ea6ae205Smrg                    spacing = "c";
579ea6ae205Smrg                } else {
580ea6ae205Smrg                    spacing = "m";
581ea6ae205Smrg                }
582ea6ae205Smrg            } else {
583ea6ae205Smrg                spacing = "p";
584ea6ae205Smrg            }
585ea6ae205Smrg        }
586ea6ae205Smrg    }
587663cdc11Smrg
588ea6ae205Smrg    if(t1info) {
589eaa89f16Smrg        if(!family && t1info->family_name)
590af7d3019Smrg            family = strdup(t1info->family_name);
591eaa89f16Smrg        if(!family && t1info->full_name)
592af7d3019Smrg            family = strdup(t1info->full_name);
593eaa89f16Smrg        /* Hershey fonts miss /FamilyName */
594eaa89f16Smrg        if(!family && face->family_name)
595eaa89f16Smrg            family = strdup(face->family_name);
596eaa89f16Smrg        if(!full_name && t1info->full_name)
597af7d3019Smrg            full_name = strdup(t1info->full_name);
598ea6ae205Smrg        if(!foundry)
599ea6ae205Smrg            foundry = notice_foundry(t1info->notice);
600ea6ae205Smrg        if(!weight)
601ea6ae205Smrg            weight = t1Weight(t1info->weight);
602ea6ae205Smrg        if(!spacing)
603ea6ae205Smrg            spacing = t1info->is_fixed_pitch ? "m" : "p";
604ea6ae205Smrg        if(!slant) {
605ea6ae205Smrg            /* Bitstream fonts have positive italic angle. */
606ea6ae205Smrg            slant =
607ea6ae205Smrg                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
608ea6ae205Smrg                "i" : "r";
609ea6ae205Smrg        }
610ea6ae205Smrg    }
611ea6ae205Smrg
612ea6ae205Smrg    if(!full_name) {
613ea6ae205Smrg        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
614af7d3019Smrg        full_name = strdup(filename);
615ea6ae205Smrg    }
616ea6ae205Smrg
617ea6ae205Smrg    if(head) {
618ea6ae205Smrg        if(!slant)
619ea6ae205Smrg            slant = head->Mac_Style & 2 ? "i" : "r";
620ea6ae205Smrg        if(!weight)
621ea6ae205Smrg            weight = head->Mac_Style & 1 ? "bold" : "medium";
622ea6ae205Smrg    }
623ea6ae205Smrg
624ea6ae205Smrg    if(!slant) {
625ea6ae205Smrg        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
626ea6ae205Smrg        slant = "r";
627ea6ae205Smrg    }
628ea6ae205Smrg
629ea6ae205Smrg    if(!weight) {
630ea6ae205Smrg        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
631ea6ae205Smrg        weight = "medium";
632ea6ae205Smrg    }
633ea6ae205Smrg
634ea6ae205Smrg    if(!foundry) {
635ea6ae205Smrg        char *notice;
636ea6ae205Smrg        notice = getName(face, TT_NAME_ID_TRADEMARK);
637ea6ae205Smrg        if(notice) {
638ea6ae205Smrg            foundry = notice_foundry(notice);
639af7d3019Smrg            free(notice);
640ea6ae205Smrg        }
641ea6ae205Smrg        if(!foundry) {
642ea6ae205Smrg            notice = getName(face, TT_NAME_ID_MANUFACTURER);
643ea6ae205Smrg            if(notice) {
644ea6ae205Smrg                foundry = notice_foundry(notice);
645af7d3019Smrg                free(notice);
646ea6ae205Smrg            }
647ea6ae205Smrg        }
648ea6ae205Smrg    }
649ea6ae205Smrg
650ea6ae205Smrg    if(strcmp(slant, "i") == 0) {
651ea6ae205Smrg        if(strstr(full_name, "Oblique"))
652ea6ae205Smrg            slant = "o";
653ea6ae205Smrg        if(strstr(full_name, "Slanted"))
654ea6ae205Smrg            slant = "o";
655ea6ae205Smrg    }
656ea6ae205Smrg
657ea6ae205Smrg    if(!sWidth)
658ea6ae205Smrg        sWidth = nameWidth(full_name);
659ea6ae205Smrg
660ea6ae205Smrg    if(!foundry) foundry = "misc";
661ea6ae205Smrg    if(!family) {
662ea6ae205Smrg        fprintf(stderr, "Couldn't get family name for %s\n", filename);
663af7d3019Smrg        family = strdup(filename);
664ea6ae205Smrg    }
665ea6ae205Smrg
666ea6ae205Smrg    if(!weight) weight = "medium";
667ea6ae205Smrg    if(!slant) slant = "r";
668ea6ae205Smrg    if(!sWidth) sWidth = "normal";
669ea6ae205Smrg    if(!adstyle) adstyle = "";
670ea6ae205Smrg    if(!spacing) spacing = "p";
671ea6ae205Smrg
672ea6ae205Smrg    foundry = safe(foundry);
673af7d3019Smrg
674af7d3019Smrg    tmp = family;
675ea6ae205Smrg    family = safe(family);
676af7d3019Smrg    free((void *)tmp);
677ea6ae205Smrg
678ea6ae205Smrg    if(!isBitmap) {
679ea6ae205Smrg        xlfd = listConsF(xlfd,
680ea6ae205Smrg                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
681ea6ae205Smrg                         foundry, family,
682ea6ae205Smrg                         weight, slant, sWidth, adstyle, spacing);
683ea6ae205Smrg    } else {
684ea6ae205Smrg        int i, w, h, xres, yres;
685ea6ae205Smrg        for(i = 0; i < face->num_fixed_sizes; i++) {
686ea6ae205Smrg            w = face->available_sizes[i].width;
687ea6ae205Smrg            h = face->available_sizes[i].height;
688ea6ae205Smrg            xres = 75;
689ea6ae205Smrg            yres = (double)h / w * xres;
690ea6ae205Smrg            xlfd = listConsF(xlfd,
691ea6ae205Smrg                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
692ea6ae205Smrg                             foundry, family,
693ea6ae205Smrg                             weight, slant, sWidth, adstyle,
694ea6ae205Smrg                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
695ea6ae205Smrg                             xres, yres,
696ea6ae205Smrg                             spacing, 60);
697ea6ae205Smrg        }
698ea6ae205Smrg    }
699af7d3019Smrg
700af7d3019Smrg    free((void *)family);
701af7d3019Smrg    free((void *)foundry);
702af7d3019Smrg    free((void *)full_name);
703ea6ae205Smrg    return xlfd;
704ea6ae205Smrg}
705ea6ae205Smrg
706ea6ae205Smrgstatic int
707ea6ae205SmrgreadFontScale(HashTablePtr entries, char *dirname)
708ea6ae205Smrg{
7097c5a9b20Smrg    size_t n = strlen(dirname);
710ea6ae205Smrg    char *filename;
711ea6ae205Smrg    FILE *in;
712ea6ae205Smrg    int rc, count, i;
713245f6787Smrg    char file[MAXFONTFILENAMELEN+1], font[MAXFONTNAMELEN+1];
714ea6ae205Smrg
715ea6ae205Smrg    if(dirname[n - 1] == '/')
716ea6ae205Smrg        filename = dsprintf("%sfonts.scale", dirname);
717ea6ae205Smrg    else
718ea6ae205Smrg        filename = dsprintf("%s/fonts.scale", dirname);
719ea6ae205Smrg    if(filename == NULL)
720ea6ae205Smrg        return -1;
721ea6ae205Smrg
722ea6ae205Smrg    in = fopen(filename, "r");
723ea6ae205Smrg    free(filename);
724ea6ae205Smrg    if(in == NULL) {
725ea6ae205Smrg        if(errno != ENOENT)
726ea6ae205Smrg            perror("open(fonts.scale)");
727ea6ae205Smrg        return -1;
728ea6ae205Smrg    }
729ea6ae205Smrg
730ea6ae205Smrg    rc = fscanf(in, "%d\n", &count);
731ea6ae205Smrg    if(rc != 1) {
732ea6ae205Smrg        fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
733ea6ae205Smrg        fclose(in);
734ea6ae205Smrg        return -1;
735ea6ae205Smrg    }
736ea6ae205Smrg
737ea6ae205Smrg    for(i = 0; i < count; i++) {
738245f6787Smrg        rc = fscanf(in,
739245f6787Smrg		    "%" STRINGIFY(MAXFONTFILENAMELEN) "s "
740245f6787Smrg		    "%" STRINGIFY(MAXFONTNAMELEN) "[^\n]\n",
741245f6787Smrg		    file, font);
742ea6ae205Smrg        if(rc != 2)
743ea6ae205Smrg            break;
744ea6ae205Smrg        putHash(entries, font, file, 100);
745ea6ae205Smrg    }
746ea6ae205Smrg    fclose(in);
747ea6ae205Smrg    return 1;
748ea6ae205Smrg}
749ea6ae205Smrg
750ea6ae205Smrgstatic int
751ea6ae205SmrgfilePrio(char *filename)
752ea6ae205Smrg{
7537c5a9b20Smrg    size_t n = strlen(filename);
754ea6ae205Smrg    if(n < 4)
755ea6ae205Smrg        return 0;
756ea6ae205Smrg    if(strcmp(filename + n - 4, ".otf") == 0)
757ea6ae205Smrg        return 6;
758ea6ae205Smrg    if(strcmp(filename + n - 4, ".OTF") == 0)
759ea6ae205Smrg        return 6;
760ea6ae205Smrg    if(strcmp(filename + n - 4, ".ttf") == 0)
761ea6ae205Smrg        return 5;
762ea6ae205Smrg    if(strcmp(filename + n - 4, ".TTF") == 0)
763ea6ae205Smrg        return 5;
764ea6ae205Smrg    if(strcmp(filename + n - 4, ".pcf") == 0)
765ea6ae205Smrg        return 4;
766ea6ae205Smrg    if(strcmp(filename + n - 4, ".PCF") == 0)
767ea6ae205Smrg        return 4;
768ea6ae205Smrg    if(strcmp(filename + n - 3, ".gz") == 0)
769ea6ae205Smrg        return 3;
7707978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
7717978d3cdSmrg    if(strcmp(filename + n - 4, ".bz2") == 0)
7727978d3cdSmrg        return 2;
7737978d3cdSmrg#endif
774ea6ae205Smrg    if(strcmp(filename + n - 2, ".Z") == 0)
775ea6ae205Smrg        return 2;
776ea6ae205Smrg    if(strcmp(filename + n - 4, ".bdf") == 0)
777ea6ae205Smrg        return 1;
778ea6ae205Smrg    if(strcmp(filename + n - 4, ".BDF") == 0)
779ea6ae205Smrg        return 1;
780ea6ae205Smrg    return 0;
781ea6ae205Smrg}
782ea6ae205Smrg
783ea6ae205Smrgstatic int
784663cdc11SmrgdoDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
785ea6ae205Smrg{
786ea6ae205Smrg    char *dirname, *fontscale_name, *filename, *encdir;
787ea6ae205Smrg    FILE *fontscale, *encfile;
7887c5a9b20Smrg    struct dirent** namelist;
789ea6ae205Smrg    FT_Error ftrc;
790ea6ae205Smrg    FT_Face face;
7917c5a9b20Smrg    ConstListPtr encoding;
7927c5a9b20Smrg    ListPtr xlfd, lp;
793ea6ae205Smrg    HashTablePtr entries;
794ea6ae205Smrg    HashBucketPtr *array;
7957c5a9b20Smrg    int i, n, dirn, diri, found, rc;
7967c5a9b20Smrg    int isBitmap=0;
7977c5a9b20Smrg    size_t d, xl=0;
798ea6ae205Smrg
799ea6ae205Smrg    if (exclusionSuffix)
800ea6ae205Smrg        xl = strlen (exclusionSuffix);
801ea6ae205Smrg
8027c5a9b20Smrg    d = strlen(dirname_given);
8037c5a9b20Smrg    if(d == 0)
804ea6ae205Smrg        dirname = dsprintf("./");
8057c5a9b20Smrg    else if(dirname_given[d - 1] != '/')
806ea6ae205Smrg        dirname = dsprintf("%s/", dirname_given);
807ea6ae205Smrg    else
8087c5a9b20Smrg        dirname = strdup(dirname_given);
809ea6ae205Smrg
810ea6ae205Smrg    if(dirname == NULL) {
811ea6ae205Smrg        perror("dirname");
812ea6ae205Smrg        exit(1);
813ea6ae205Smrg    }
814ea6ae205Smrg
815663cdc11Smrg    if (onlyEncodings)
816ea6ae205Smrg	goto encodings;
817663cdc11Smrg
818ea6ae205Smrg    entries = makeHashTable();
819ea6ae205Smrg    if(doBitmaps && !doScalable) {
820ea6ae205Smrg        readFontScale(entries, dirname);
821ea6ae205Smrg    }
822ea6ae205Smrg
823ea6ae205Smrg    if(strcmp(outfilename, "-") == 0)
824ea6ae205Smrg        fontscale_name = NULL;
825ea6ae205Smrg    else {
826ea6ae205Smrg        if(outfilename[0] == '/')
8277c5a9b20Smrg            fontscale_name = strdup(outfilename);
828ea6ae205Smrg        else
829ea6ae205Smrg            fontscale_name = dsprintf("%s%s", dirname, outfilename);
830ea6ae205Smrg        if(fontscale_name == NULL) {
831ea6ae205Smrg            perror("fontscale_name");
832ea6ae205Smrg            exit(1);
833ea6ae205Smrg        }
834ea6ae205Smrg    }
835ea6ae205Smrg
8367c5a9b20Smrg    dirn = scandir(dirname, &namelist, NULL, alphasort);
8377c5a9b20Smrg    if(dirn < 0) {
838ea6ae205Smrg        fprintf(stderr, "%s: ", dirname);
8397c5a9b20Smrg        perror("scandir");
840ea6ae205Smrg        return 0;
841ea6ae205Smrg    }
842ea6ae205Smrg
843ea6ae205Smrg    if(fontscale_name == NULL)
844ea6ae205Smrg        fontscale = stdout;
845ea6ae205Smrg    else
846ea6ae205Smrg        fontscale = fopen(fontscale_name, "wb");
847ea6ae205Smrg
848ea6ae205Smrg    if(fontscale == NULL) {
849ea6ae205Smrg        fprintf(stderr, "%s: ", fontscale_name);
850ea6ae205Smrg        perror("fopen(w)");
851ea6ae205Smrg        return 0;
852ea6ae205Smrg    }
853ea6ae205Smrg
8547c5a9b20Smrg    for(diri = dirn - 1; diri >= 0; diri--) {
8557c5a9b20Smrg        struct dirent *entry = namelist[diri];
856ea6ae205Smrg        int have_face = 0;
857ea6ae205Smrg        char *xlfd_name = NULL;
8582d6e8b77Smrg	struct stat f_stat;
8592d6e8b77Smrg	int tprio = 1;
8602d6e8b77Smrg
861ea6ae205Smrg        xlfd = NULL;
862ea6ae205Smrg
863ea6ae205Smrg	if (xl) {
8647c5a9b20Smrg	    size_t dl = strlen (entry->d_name);
865ea6ae205Smrg	    if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
866ea6ae205Smrg		continue;
867ea6ae205Smrg	}
868ea6ae205Smrg
869ea6ae205Smrg        filename = dsprintf("%s%s", dirname, entry->d_name);
870ea6ae205Smrg
8712d6e8b77Smrg#define PRIO(x) ((x << 1) + tprio)
8722d6e8b77Smrg#ifdef DT_LNK
8732d6e8b77Smrg	if (entry->d_type != DT_UNKNOWN) {
8742d6e8b77Smrg	    if (entry->d_type == DT_LNK)
8752d6e8b77Smrg		tprio = 0;
8762d6e8b77Smrg	} else
8772d6e8b77Smrg#endif
8782d6e8b77Smrg#ifdef S_ISLNK
8792d6e8b77Smrg	{
8802d6e8b77Smrg	    if (lstat(filename, &f_stat))
8812d6e8b77Smrg		goto done;
8822d6e8b77Smrg	    if (S_ISLNK(f_stat.st_mode))
8832d6e8b77Smrg		tprio = 0;
8842d6e8b77Smrg	}
8852d6e8b77Smrg#else
8862d6e8b77Smrg	;
8872d6e8b77Smrg#endif
888ea6ae205Smrg        if(doBitmaps)
889ea6ae205Smrg            rc = bitmapIdentify(filename, &xlfd_name);
890ea6ae205Smrg        else
891ea6ae205Smrg            rc = 0;
892ea6ae205Smrg
893ea6ae205Smrg        if(rc < 0)
894ea6ae205Smrg            goto done;
895ea6ae205Smrg
896ea6ae205Smrg        if(rc == 0) {
897ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
898ea6ae205Smrg            if(ftrc)
899ea6ae205Smrg                goto done;
900ea6ae205Smrg            have_face = 1;
901ea6ae205Smrg
902ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
903ea6ae205Smrg
904ea6ae205Smrg            if(!isBitmap) {
905ea6ae205Smrg                /* Workaround for bitmap-only SFNT fonts */
906ea6ae205Smrg                if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
907ea6ae205Smrg                   strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
908ea6ae205Smrg                    TT_MaxProfile *maxp;
909ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
910ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
911ea6ae205Smrg                        isBitmap = 1;
912ea6ae205Smrg                }
913ea6ae205Smrg            }
914663cdc11Smrg
915ea6ae205Smrg            if(isBitmap) {
916ea6ae205Smrg                if(!doBitmaps)
917ea6ae205Smrg                    goto done;
918ea6ae205Smrg            } else {
919ea6ae205Smrg                if(!doScalable)
920ea6ae205Smrg                    goto done;
921ea6ae205Smrg            }
922ea6ae205Smrg
923ea6ae205Smrg            if(isBitmap) {
924ea6ae205Smrg                BDF_PropertyRec prop;
925ea6ae205Smrg                rc = FT_Get_BDF_Property(face, "FONT", &prop);
926ea6ae205Smrg                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
9272d6e8b77Smrg                    xlfd_name = strdup(prop.u.atom);
928ea6ae205Smrg                    if(xlfd_name == NULL)
929ea6ae205Smrg                        goto done;
930ea6ae205Smrg                }
931ea6ae205Smrg            }
932ea6ae205Smrg        }
933ea6ae205Smrg
934ea6ae205Smrg        if(xlfd_name) {
935ea6ae205Smrg            /* We know it's a bitmap font, and we know its XLFD */
9367c5a9b20Smrg            size_t l = strlen(xlfd_name);
937ea6ae205Smrg            if(reencodeLegacy &&
9387c5a9b20Smrg               l >= 12 && strcasecmp(xlfd_name + l - 11, "-iso10646-1") == 0) {
939ea6ae205Smrg                char *s;
940ea6ae205Smrg
9417c5a9b20Smrg                s = malloc(l - 10);
9427c5a9b20Smrg                memcpy(s, xlfd_name, l - 11);
9437c5a9b20Smrg                s[l - 11] = '\0';
944ea6ae205Smrg                xlfd = listCons(s, xlfd);
945ea6ae205Smrg            } else {
946ea6ae205Smrg                /* Not a reencodable font -- skip all the rest of the loop body */
9472d6e8b77Smrg                putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
948ea6ae205Smrg                goto done;
949ea6ae205Smrg            }
950ea6ae205Smrg        }
951ea6ae205Smrg
952ea6ae205Smrg        if(!have_face) {
953ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
954ea6ae205Smrg            if(ftrc)
955ea6ae205Smrg                goto done;
956ea6ae205Smrg            have_face = 1;
957ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
958ea6ae205Smrg
959ea6ae205Smrg            if(!isBitmap) {
960ea6ae205Smrg                if(face->num_fixed_sizes > 0) {
961ea6ae205Smrg                    TT_MaxProfile *maxp;
962ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
963ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
964ea6ae205Smrg                        isBitmap = 1;
965ea6ae205Smrg                }
966ea6ae205Smrg            }
967ea6ae205Smrg        }
968ea6ae205Smrg
969ea6ae205Smrg        if(xlfd == NULL)
970ea6ae205Smrg            xlfd = makeXLFD(entry->d_name, face, isBitmap);
971ea6ae205Smrg
972ea6ae205Smrg        found = 0;
973ea6ae205Smrg
974ea6ae205Smrg        for(lp = xlfd; lp; lp = lp->next) {
975ea6ae205Smrg            char buf[MAXFONTNAMELEN];
976ea6ae205Smrg            for(encoding = encodings; encoding; encoding = encoding->next) {
977ea6ae205Smrg                if(checkEncoding(face, encoding->value)) {
978ea6ae205Smrg                    found = 1;
979ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
980ea6ae205Smrg                            lp->value, encoding->value);
9812d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
982ea6ae205Smrg                }
983ea6ae205Smrg            }
984663cdc11Smrg            for(encoding = extra_encodings; encoding;
985ea6ae205Smrg                encoding = encoding->next) {
986ea6ae205Smrg                if(checkExtraEncoding(face, encoding->value, found)) {
987ea6ae205Smrg                    /* Do not set found! */
988ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
989ea6ae205Smrg                            lp->value, encoding->value);
9902d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
991ea6ae205Smrg                }
992ea6ae205Smrg            }
993ea6ae205Smrg        }
994ea6ae205Smrg    done:
995245f6787Smrg        if(have_face)
996ea6ae205Smrg            FT_Done_Face(face);
997ea6ae205Smrg        deepDestroyList(xlfd);
998ea6ae205Smrg        xlfd = NULL;
999ea6ae205Smrg        free(filename);
10002d6e8b77Smrg#undef PRIO
1001ea6ae205Smrg    }
1002ea6ae205Smrg
10037c5a9b20Smrg    while(dirn--)
10047c5a9b20Smrg        free(namelist[dirn]);
10057c5a9b20Smrg    free(namelist);
1006ea6ae205Smrg    n = hashElements(entries);
1007ea6ae205Smrg    fprintf(fontscale, "%d\n", n);
1008ea6ae205Smrg    array = hashArray(entries, 1);
1009ea6ae205Smrg    for(i = 0; i < n; i++)
1010ea6ae205Smrg        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
1011ea6ae205Smrg    destroyHashArray(array);
1012ea6ae205Smrg    entries = NULL;
1013ea6ae205Smrg    if(fontscale_name) {
1014ea6ae205Smrg        fclose(fontscale);
1015ea6ae205Smrg        free(fontscale_name);
1016ea6ae205Smrg    }
1017ea6ae205Smrg
1018ea6ae205Smrg encodings:
1019ea6ae205Smrg    encdir = dsprintf("%s%s", dirname, "encodings.dir");
1020ea6ae205Smrg
1021ea6ae205Smrg    if(encdir == NULL) {
1022ea6ae205Smrg	perror("encodings");
1023ea6ae205Smrg	exit(1);
1024ea6ae205Smrg    }
1025ea6ae205Smrg    unlink(encdir);
1026ea6ae205Smrg
1027ea6ae205Smrg    if (numEncodings) {
1028ea6ae205Smrg	encfile = fopen(encdir, "w");
1029ea6ae205Smrg	if(encfile == NULL) {
1030ea6ae205Smrg	    perror("open(encodings.dir)");
1031ea6ae205Smrg	    exit(1);
1032ea6ae205Smrg	}
1033ea6ae205Smrg        fprintf(encfile, "%d\n", numEncodings);
1034245f6787Smrg        encodingsToDo = sortList(encodingsToDo);
1035ea6ae205Smrg        for(lp = encodingsToDo; lp; lp = lp->next) {
1036ea6ae205Smrg            fprintf(encfile, "%s\n", lp->value);
1037ea6ae205Smrg        }
1038ea6ae205Smrg	fclose (encfile);
1039ea6ae205Smrg    }
1040ea6ae205Smrg
1041ea6ae205Smrg    free(dirname);
1042ea6ae205Smrg    return 1;
1043ea6ae205Smrg}
1044ea6ae205Smrg
1045ea6ae205Smrg#define CODE_IGNORED(c) ((c) < 0x20 || \
1046ea6ae205Smrg                         ((c) >= 0x7F && (c) <= 0xA0) || \
1047ea6ae205Smrg                         (c) == 0xAD || (c) == 0xF71B)
1048663cdc11Smrg
1049ea6ae205Smrgstatic int
10507c5a9b20SmrgcheckEncoding(FT_Face face, const char *encoding_name)
1051ea6ae205Smrg{
1052ea6ae205Smrg    FontEncPtr encoding;
1053ea6ae205Smrg    FontMapPtr mapping;
1054ea6ae205Smrg    int i, j, c, koi8;
1055ea6ae205Smrg    char *n;
1056ea6ae205Smrg
1057ea6ae205Smrg    encoding = FontEncFind(encoding_name, NULL);
1058ea6ae205Smrg    if(!encoding)
1059ea6ae205Smrg        return 0;
1060ea6ae205Smrg
1061ea6ae205Smrg    /* An encoding is ``small'' if one of the following is true:
1062ea6ae205Smrg         - it is linear and has no more than 256 codepoints; or
1063ea6ae205Smrg         - it is a matrix encoding and has no more than one column.
1064663cdc11Smrg
1065ea6ae205Smrg       For small encodings using Unicode indices, we require perfect
1066ea6ae205Smrg       coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1067ea6ae205Smrg
1068ea6ae205Smrg       For large encodings, we require coverage up to bigEncodingFuzz.
1069ea6ae205Smrg
1070ea6ae205Smrg       For encodings using PS names (currently Adobe Standard and
1071ea6ae205Smrg       Adobe Symbol only), we require perfect coverage. */
1072ea6ae205Smrg
1073ea6ae205Smrg
1074ea6ae205Smrg    if(FT_Has_PS_Glyph_Names(face)) {
1075ea6ae205Smrg        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1076ea6ae205Smrg            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
1077ea6ae205Smrg                if(encoding->row_size > 0) {
1078ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1079663cdc11Smrg                        for(j = encoding->first_col;
1080663cdc11Smrg                            j < encoding->row_size;
1081ea6ae205Smrg                            j++) {
1082ea6ae205Smrg                            n = FontEncName((i<<8) | j, mapping);
1083ea6ae205Smrg                            if(n && FT_Get_Name_Index(face, n) == 0) {
1084ea6ae205Smrg                                return 0;
1085ea6ae205Smrg                            }
1086ea6ae205Smrg                        }
1087ea6ae205Smrg                    }
1088ea6ae205Smrg                    return 1;
1089ea6ae205Smrg                } else {
1090ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1091ea6ae205Smrg                        n = FontEncName(i, mapping);
1092ea6ae205Smrg                        if(n && FT_Get_Name_Index(face, n) == 0) {
1093ea6ae205Smrg                            return 0;
1094ea6ae205Smrg                        }
1095ea6ae205Smrg                    }
1096ea6ae205Smrg                    return 1;
1097ea6ae205Smrg                }
1098ea6ae205Smrg            }
1099ea6ae205Smrg        }
1100ea6ae205Smrg    }
1101ea6ae205Smrg
1102ea6ae205Smrg    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1103ea6ae205Smrg        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1104ea6ae205Smrg            int total = 0, failed = 0;
1105ea6ae205Smrg            if(encoding->row_size > 0) {
1106663cdc11Smrg                int estimate =
1107ea6ae205Smrg                    (encoding->size - encoding->first) *
1108ea6ae205Smrg                    (encoding->row_size - encoding->first_col);
1109ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1110663cdc11Smrg                    for(j = encoding->first_col;
1111663cdc11Smrg                        j < encoding->row_size;
1112ea6ae205Smrg                        j++) {
1113ea6ae205Smrg                        c = FontEncRecode((i<<8) | j, mapping);
1114ea6ae205Smrg                        if(CODE_IGNORED(c)) {
1115ea6ae205Smrg                            continue;
1116ea6ae205Smrg                        } else {
1117ea6ae205Smrg                            if(FT_Get_Char_Index(face, c) == 0) {
1118ea6ae205Smrg                                failed++;
1119ea6ae205Smrg                            }
1120ea6ae205Smrg                            total++;
1121ea6ae205Smrg                            if((encoding->size <= 1 && failed > 0) ||
1122ea6ae205Smrg                               ((float)failed >= bigEncodingFuzz * estimate)) {
1123ea6ae205Smrg                                return 0;
1124ea6ae205Smrg                            }
1125ea6ae205Smrg                        }
1126ea6ae205Smrg                    }
1127ea6ae205Smrg                }
1128ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1129ea6ae205Smrg                    return 0;
1130ea6ae205Smrg                else
1131ea6ae205Smrg                    return 1;
1132ea6ae205Smrg            } else {
1133ea6ae205Smrg                int estimate = encoding->size - encoding->first;
1134ea6ae205Smrg                /* For the KOI8 encodings, we ignore the lack of
1135ea6ae205Smrg                   linedrawing and pseudo-math characters */
1136ea6ae205Smrg                if(strncmp(encoding->name, "koi8-", 5) == 0)
1137ea6ae205Smrg                    koi8 = 1;
1138ea6ae205Smrg                else
1139ea6ae205Smrg                    koi8 = 0;
1140ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1141ea6ae205Smrg                    c = FontEncRecode(i, mapping);
1142ea6ae205Smrg                    if(CODE_IGNORED(c) ||
1143ea6ae205Smrg                       (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1144ea6ae205Smrg                        continue;
1145ea6ae205Smrg                    } else {
1146ea6ae205Smrg                        if(FT_Get_Char_Index(face, c) == 0) {
1147ea6ae205Smrg                            failed++;
1148ea6ae205Smrg                        }
1149ea6ae205Smrg                        total++;
1150ea6ae205Smrg                        if((encoding->size <= 256 && failed > 0) ||
1151ea6ae205Smrg                           ((float)failed >= bigEncodingFuzz * estimate)) {
1152ea6ae205Smrg                            return 0;
1153ea6ae205Smrg                        }
1154ea6ae205Smrg                    }
1155ea6ae205Smrg                }
1156ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1157ea6ae205Smrg                    return 0;
1158ea6ae205Smrg                else
1159ea6ae205Smrg                    return 1;
1160ea6ae205Smrg            }
1161ea6ae205Smrg        }
1162ea6ae205Smrg    }
1163ea6ae205Smrg    return 0;
1164ea6ae205Smrg}
1165ea6ae205Smrg
1166663cdc11Smrgstatic int
1167ea6ae205Smrgfind_cmap(int type, int pid, int eid, FT_Face face)
1168ea6ae205Smrg{
1169ea6ae205Smrg    int i, n, rc;
1170ea6ae205Smrg    FT_CharMap cmap = NULL;
1171ea6ae205Smrg
1172ea6ae205Smrg    n = face->num_charmaps;
1173ea6ae205Smrg
1174ea6ae205Smrg    switch(type) {
1175ea6ae205Smrg    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
1176ea6ae205Smrg        for(i=0; i<n; i++) {
1177ea6ae205Smrg            cmap = face->charmaps[i];
1178ea6ae205Smrg            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1179ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1180ea6ae205Smrg                if(rc == 0)
1181ea6ae205Smrg                    return 1;
1182ea6ae205Smrg            }
1183ea6ae205Smrg        }
1184ea6ae205Smrg        break;
1185ea6ae205Smrg    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
1186ea6ae205Smrg        /* prefer Microsoft Unicode */
1187ea6ae205Smrg        for(i=0; i<n; i++) {
1188ea6ae205Smrg            cmap = face->charmaps[i];
1189663cdc11Smrg            if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1190ea6ae205Smrg               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
1191ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1192ea6ae205Smrg                if(rc == 0)
1193ea6ae205Smrg                    return 1;
1194ea6ae205Smrg            }
1195ea6ae205Smrg        }
1196ea6ae205Smrg        /* Try Apple Unicode */
1197ea6ae205Smrg        for(i=0; i<n; i++) {
1198ea6ae205Smrg            cmap = face->charmaps[i];
1199ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
1200ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1201ea6ae205Smrg                if(rc == 0)
1202ea6ae205Smrg                    return 1;
1203ea6ae205Smrg            }
1204ea6ae205Smrg        }
1205ea6ae205Smrg        /* ISO Unicode? */
1206ea6ae205Smrg        for(i=0; i<n; i++) {
1207ea6ae205Smrg            cmap = face->charmaps[i];
1208ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_ISO) {
1209ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1210ea6ae205Smrg                if(rc == 0)
1211ea6ae205Smrg                    return 1;
1212ea6ae205Smrg            }
1213ea6ae205Smrg        }
1214ea6ae205Smrg        break;
1215ea6ae205Smrg    default:
1216ea6ae205Smrg        return 0;
1217ea6ae205Smrg    }
1218ea6ae205Smrg    return 0;
1219ea6ae205Smrg}
1220ea6ae205Smrg
1221ea6ae205Smrgstatic int
12227c5a9b20SmrgcheckExtraEncoding(FT_Face face, const char *encoding_name, int found)
1223ea6ae205Smrg{
1224ea6ae205Smrg    int c;
1225ea6ae205Smrg
1226ea6ae205Smrg    if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1227ea6ae205Smrg        if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
12287c5a9b20Smrg            int cfound = 0;
1229ea6ae205Smrg             /* Export as Unicode if there are at least 15 BMP
1230ea6ae205Smrg               characters that are not a space or ignored. */
1231ea6ae205Smrg            for(c = 0x21; c < 0x10000; c++) {
1232ea6ae205Smrg                if(CODE_IGNORED(c))
1233ea6ae205Smrg                    continue;
1234ea6ae205Smrg                if(FT_Get_Char_Index(face, c) > 0)
12357c5a9b20Smrg                    cfound++;
12367c5a9b20Smrg                if(cfound >= 15)
1237ea6ae205Smrg                    return 1;
1238ea6ae205Smrg            }
1239ea6ae205Smrg            return 0;
1240ea6ae205Smrg        } else
1241ea6ae205Smrg            return 0;
1242ea6ae205Smrg    } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1243ea6ae205Smrg        if(find_cmap(FONT_ENCODING_TRUETYPE,
1244ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
1245ea6ae205Smrg                     face))
1246ea6ae205Smrg            return 1;
1247ea6ae205Smrg        else
1248ea6ae205Smrg            return 0;
1249ea6ae205Smrg    } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1250ea6ae205Smrg        if(!found) {
1251ea6ae205Smrg            if(FT_Has_PS_Glyph_Names(face))
1252ea6ae205Smrg                return 1;
1253ea6ae205Smrg            else
1254ea6ae205Smrg                return 0;
1255ea6ae205Smrg        } else
1256ea6ae205Smrg            return 0;
1257ea6ae205Smrg    } else {
1258ea6ae205Smrg        fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
1259ea6ae205Smrg        return 0;
1260ea6ae205Smrg    }
1261ea6ae205Smrg}
1262ea6ae205Smrg
1263663cdc11Smrgstatic const char*
1264663cdc11Smrgnotice_foundry(const char *notice)
1265ea6ae205Smrg{
12667c5a9b20Smrg    unsigned int i;
1267ea6ae205Smrg    for(i = 0; i < countof(notice_foundries); i++)
1268ea6ae205Smrg        if(notice && strstr(notice, notice_foundries[i][0]))
1269ea6ae205Smrg            return notice_foundries[i][1];
1270ea6ae205Smrg    return NULL;
1271ea6ae205Smrg}
1272ea6ae205Smrg
1273ea6ae205Smrgstatic int
1274663cdc11Smrgvendor_match(const signed char *vendor, const char *vendor_string)
1275ea6ae205Smrg{
1276ea6ae205Smrg    /* vendor is not necessarily NUL-terminated. */
12777c5a9b20Smrg    size_t i, len;
1278ea6ae205Smrg    len = strlen(vendor_string);
1279ea6ae205Smrg    if(memcmp(vendor, vendor_string, len) != 0)
1280ea6ae205Smrg        return 0;
1281ea6ae205Smrg    for(i = len; i < 4; i++)
1282ea6ae205Smrg        if(vendor[i] != ' ' && vendor[i] != '\0')
1283ea6ae205Smrg            return 0;
1284ea6ae205Smrg    return 1;
1285ea6ae205Smrg}
1286ea6ae205Smrg
1287663cdc11Smrgstatic const char*
1288663cdc11Smrgvendor_foundry(const signed char *vendor)
1289ea6ae205Smrg{
12907c5a9b20Smrg    unsigned int i;
1291ea6ae205Smrg    for(i = 0; i < countof(vendor_foundries); i++)
1292ea6ae205Smrg        if(vendor_match(vendor, vendor_foundries[i][0]))
1293ea6ae205Smrg            return vendor_foundries[i][1];
1294ea6ae205Smrg    return NULL;
1295ea6ae205Smrg}
1296ea6ae205Smrg
1297ea6ae205Smrgstatic int
1298ea6ae205SmrgreadEncodings(ListPtr encodings, char *dirname)
1299ea6ae205Smrg{
1300ea6ae205Smrg    char *fullname;
1301ea6ae205Smrg    DIR *dirp;
1302ea6ae205Smrg    struct dirent *file;
1303ea6ae205Smrg    char **names, **name;
1304ea6ae205Smrg
1305ea6ae205Smrg    if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1306ea6ae205Smrg        dirname[strlen(dirname) - 1] = '\0';
1307ea6ae205Smrg
1308ea6ae205Smrg    dirp = opendir(dirname);
1309ea6ae205Smrg    if(dirp == NULL) {
1310ea6ae205Smrg        perror("opendir");
1311ea6ae205Smrg        return -1;
1312ea6ae205Smrg    }
1313ea6ae205Smrg
1314ea6ae205Smrg    while((file = readdir(dirp)) != NULL) {
1315ea6ae205Smrg        fullname = dsprintf("%s/%s", dirname, file->d_name);
1316ea6ae205Smrg        if(fullname == NULL) {
1317ea6ae205Smrg            fprintf(stderr, "Couldn't allocate fullname\n");
1318ea6ae205Smrg            closedir(dirp);
1319ea6ae205Smrg            return -1;
1320ea6ae205Smrg        }
1321663cdc11Smrg
1322ea6ae205Smrg        names = FontEncIdentify(fullname);
1323ea6ae205Smrg        if(!names)
1324ea6ae205Smrg            continue;
1325ea6ae205Smrg
1326ea6ae205Smrg        for(name = names; *name; name++) {
1327ea6ae205Smrg            if(fullname[0] != '/' && !relative) {
1328ea6ae205Smrg                char *n;
1329ea6ae205Smrg                n = dsprintf("%s%s", encodingPrefix, fullname);
1330ea6ae205Smrg                if(n == NULL) {
1331ea6ae205Smrg                    fprintf(stderr, "Couldn't allocate name\n");
1332ea6ae205Smrg                    closedir(dirp);
1333ea6ae205Smrg                    return -1;
1334ea6ae205Smrg                }
1335ea6ae205Smrg                encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1336ea6ae205Smrg                free(n);
1337ea6ae205Smrg            } else {
1338663cdc11Smrg                encodingsToDo =
1339ea6ae205Smrg                    listConsF(encodingsToDo, "%s %s", *name, fullname);
1340ea6ae205Smrg            }
1341ea6ae205Smrg            if(encodingsToDo == NULL) {
1342ea6ae205Smrg                fprintf(stderr, "Couldn't allocate encodings\n");
1343ea6ae205Smrg                closedir(dirp);
1344ea6ae205Smrg                return -1;
1345ea6ae205Smrg            }
1346ea6ae205Smrg        }
1347ea6ae205Smrg        free(names);            /* only the spine */
1348ea6ae205Smrg    }
1349ea6ae205Smrg    closedir(dirp);
1350ea6ae205Smrg    return 0;
1351ea6ae205Smrg}
1352