mkfontscale.c revision eaa89f16
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"
51ea6ae205Smrg#include "hash.h"
52ea6ae205Smrg#include "data.h"
53ea6ae205Smrg#include "ident.h"
54ea6ae205Smrg
55ea6ae205Smrg#define NPREFIX 1024
56ea6ae205Smrg
57ea6ae205Smrg#ifndef MAXFONTFILENAMELEN
58ea6ae205Smrg#define MAXFONTFILENAMELEN 1024
59ea6ae205Smrg#endif
60ea6ae205Smrg#ifndef MAXFONTNAMELEN
61ea6ae205Smrg#define MAXFONTNAMELEN 1024
62ea6ae205Smrg#endif
63ea6ae205Smrg
64245f6787Smrg/* Two levels of macro calls are needed so that we stringify the value
65245f6787Smrg   of MAXFONT... and not the string "MAXFONT..." */
66245f6787Smrg#define QUOTE(x)	#x
67245f6787Smrg#define STRINGIFY(x)	QUOTE(x)
68245f6787Smrg
6914734546Smrgstatic char *encodings_array[] =
70ea6ae205Smrg    { "ascii-0",
71ea6ae205Smrg      "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
72ea6ae205Smrg      "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
73ea6ae205Smrg      "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
74ea6ae205Smrg      "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
75ea6ae205Smrg      "iso8859-15", "iso8859-16",
76ea6ae205Smrg      "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
77ea6ae205Smrg      "tis620-2",
78ea6ae205Smrg      "sun.unicode.india-0", "suneu-greek",
79ea6ae205Smrg      "adobe-standard", "adobe-symbol",
80ea6ae205Smrg      "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
81ea6ae205Smrg      /* But not "adobe-dingbats", as it uses generic glyph names. */
82ea6ae205Smrg      "cns11643-1", "cns11643-2", "cns11643-3",
83ea6ae205Smrg      "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
84ea6ae205Smrg      "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
85ea6ae205Smrg      "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
86ea6ae205Smrg      "ksc5601.1987-0", "ksc5601.1992-3"};
87ea6ae205Smrg
8814734546Smrgstatic char *extra_encodings_array[] =
89ea6ae205Smrg    { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
90ea6ae205Smrg
91e83ac88aSmrgstatic ListPtr encodings, extra_encodings;
92663cdc11Smrgstatic const char *outfilename;
93ea6ae205Smrg
94ea6ae205Smrg#define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
95ea6ae205Smrg
96663cdc11Smrgstatic int doDirectory(const char*, int, ListPtr);
97ea6ae205Smrgstatic int checkEncoding(FT_Face face, char *encoding_name);
98ea6ae205Smrgstatic int checkExtraEncoding(FT_Face face, char *encoding_name, int found);
99ea6ae205Smrgstatic int find_cmap(int type, int pid, int eid, FT_Face face);
100663cdc11Smrgstatic const char* notice_foundry(const char *notice);
101663cdc11Smrgstatic const char* vendor_foundry(const signed char *vendor);
102ea6ae205Smrgstatic int readFontScale(HashTablePtr entries, char *dirname);
103ea6ae205SmrgListPtr makeXLFD(char *filename, FT_Face face, int);
104ea6ae205Smrgstatic int readEncodings(ListPtr encodings, char *dirname);
105ea6ae205Smrg
106ea6ae205Smrgstatic FT_Library ft_library;
107ea6ae205Smrgstatic float bigEncodingFuzz = 0.02;
108ea6ae205Smrg
109ea6ae205Smrgstatic int relative;
110ea6ae205Smrgstatic int doScalable;
111ea6ae205Smrgstatic int doBitmaps;
112ea6ae205Smrgstatic int doISO10646_1_encoding;
113ea6ae205Smrgstatic int onlyEncodings;
114ea6ae205Smrgstatic ListPtr encodingsToDo;
115ea6ae205Smrgstatic int reencodeLegacy;
116ea6ae205Smrgstatic char *encodingPrefix;
117ea6ae205Smrgstatic char *exclusionSuffix;
118af7d3019Smrgstatic char *ProgramName;
119ea6ae205Smrg
120af7d3019Smrgstatic void _X_NORETURN _X_COLD
121ea6ae205Smrgusage(void)
122ea6ae205Smrg{
123af7d3019Smrg    fprintf(stderr, "Usage:\n"
124ea6ae205Smrg            "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
125af7d3019Smrg            "            [ -a encoding ] [ -f fuzz ] [ -l ]\n"
126ea6ae205Smrg            "            [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
127af7d3019Smrg            "            [-u] [-U] [-v] [ directory ]...\n");
128af7d3019Smrg    exit(1);
129af7d3019Smrg}
130af7d3019Smrg
131af7d3019Smrgstatic void _X_NORETURN _X_COLD
132af7d3019Smrgmissing_arg (const char *option)
133af7d3019Smrg{
134af7d3019Smrg    fprintf(stderr, "%s: %s requires an argument\n", ProgramName, option);
135af7d3019Smrg    usage();
136ea6ae205Smrg}
137ea6ae205Smrg
138ea6ae205Smrgint
139ea6ae205Smrgmain(int argc, char **argv)
140ea6ae205Smrg{
141ea6ae205Smrg    int argn;
142ea6ae205Smrg    FT_Error ftrc;
143ea6ae205Smrg    int rc, ll = 0;
144ea6ae205Smrg    char prefix[NPREFIX];
145ea6ae205Smrg
146af7d3019Smrg    ProgramName = argv[0];
147ea6ae205Smrg    encodingPrefix = NULL;
148ea6ae205Smrg    exclusionSuffix = NULL;
149ea6ae205Smrg
150ea6ae205Smrg    if(getcwd(prefix, NPREFIX - 1) == NULL) {
151ea6ae205Smrg        perror("Couldn't get cwd");
152ea6ae205Smrg        exit(1);
153ea6ae205Smrg    }
154ea6ae205Smrg    if(prefix[strlen(prefix) - 1] != '/')
155ea6ae205Smrg        strcat(prefix, "/");
156ea6ae205Smrg    encodingPrefix = dsprintf("%s", prefix);
157ea6ae205Smrg
158ea6ae205Smrg    outfilename = NULL;
159ea6ae205Smrg
160ea6ae205Smrg    encodings = makeList(encodings_array, countof(encodings_array), NULL, 0);
161ea6ae205Smrg
162663cdc11Smrg    extra_encodings = makeList(extra_encodings_array,
163ea6ae205Smrg                               countof(extra_encodings_array),
164ea6ae205Smrg                               NULL, 0);
165ea6ae205Smrg    doBitmaps = 0;
166ea6ae205Smrg    doISO10646_1_encoding = 1;
167ea6ae205Smrg    doScalable = 1;
168ea6ae205Smrg    onlyEncodings = 0;
169ea6ae205Smrg    relative = 0;
170ea6ae205Smrg    reencodeLegacy = 1;
171ea6ae205Smrg    encodingsToDo = NULL;
172ea6ae205Smrg
173ea6ae205Smrg    argn = 1;
174ea6ae205Smrg    while(argn < argc) {
175ea6ae205Smrg        if(argv[argn][0] == '\0' || argv[argn][0] != '-')
176ea6ae205Smrg            break;
177ea6ae205Smrg        if(argv[argn][1] == '-') {
178ea6ae205Smrg            argn++;
179ea6ae205Smrg            break;
180ea6ae205Smrg        } else if (strcmp(argv[argn], "-x") == 0) {
181ea6ae205Smrg            if(argn >= argc - 1) {
182af7d3019Smrg                missing_arg("-x");
183ea6ae205Smrg            }
184ea6ae205Smrg            exclusionSuffix = argv[argn + 1];
185ea6ae205Smrg            argn += 2;
186ea6ae205Smrg        } else if(strcmp(argv[argn], "-a") == 0) {
187ea6ae205Smrg            if(argn >= argc - 1) {
188af7d3019Smrg                missing_arg("-a");
189ea6ae205Smrg            }
190ea6ae205Smrg            makeList(&argv[argn + 1], 1, encodings, 0);
191ea6ae205Smrg            argn += 2;
192ea6ae205Smrg        } else if(strcmp(argv[argn], "-p") == 0) {
193ea6ae205Smrg            if(argn >= argc - 1) {
194af7d3019Smrg                missing_arg("-p");
195ea6ae205Smrg            }
196ea6ae205Smrg            if(strlen(argv[argn + 1]) > NPREFIX - 1) {
197af7d3019Smrg                fprintf(stderr, "%s: argument to -p cannot be longer than "
198af7d3019Smrg                        "%d characters\n", ProgramName, NPREFIX - 1);
199ea6ae205Smrg                usage();
200ea6ae205Smrg            }
201ea6ae205Smrg            free(encodingPrefix);
202ea6ae205Smrg            encodingPrefix = dsprintf("%s", argv[argn + 1]);
203ea6ae205Smrg            argn += 2;
204ea6ae205Smrg        } else if(strcmp(argv[argn], "-e") == 0) {
205ea6ae205Smrg            if(argn >= argc - 1) {
206af7d3019Smrg                missing_arg("-e");
207ea6ae205Smrg            }
208ea6ae205Smrg            rc = readEncodings(encodingsToDo, argv[argn + 1]);
209ea6ae205Smrg            if(rc < 0)
210ea6ae205Smrg                exit(1);
211ea6ae205Smrg            argn += 2;
212ea6ae205Smrg        } else if(strcmp(argv[argn], "-b") == 0) {
213ea6ae205Smrg            doBitmaps = 1;
214ea6ae205Smrg            argn++;
215ea6ae205Smrg        } else if(strcmp(argv[argn], "-u") == 0) {
216ea6ae205Smrg            doISO10646_1_encoding = 0;
217ea6ae205Smrg            argn++;
218ea6ae205Smrg        } else if(strcmp(argv[argn], "-U") == 0) {
219ea6ae205Smrg            doISO10646_1_encoding = 1;
220663cdc11Smrg            argn++;
221ea6ae205Smrg        } else if(strcmp(argv[argn], "-s") == 0) {
222ea6ae205Smrg            doScalable = 0;
223ea6ae205Smrg            argn++;
224ea6ae205Smrg        } else if(strcmp(argv[argn], "-n") == 0) {
225ea6ae205Smrg            onlyEncodings = 1;
226ea6ae205Smrg            argn++;
227ea6ae205Smrg        } else if(strcmp(argv[argn], "-r") == 0) {
228ea6ae205Smrg            relative = 1;
229ea6ae205Smrg            argn++;
230ea6ae205Smrg        } else if(strcmp(argv[argn], "-l") == 0) {
231ea6ae205Smrg            reencodeLegacy = !reencodeLegacy;
232ea6ae205Smrg            argn++;
233ea6ae205Smrg        } else if(strcmp(argv[argn], "-o") == 0) {
234ea6ae205Smrg            if(argn >= argc - 1) {
235af7d3019Smrg                missing_arg("-o");
236ea6ae205Smrg            }
237ea6ae205Smrg            outfilename = argv[argn + 1];
238ea6ae205Smrg            argn += 2;
239ea6ae205Smrg        } else if(strcmp(argv[argn], "-f") == 0) {
240ea6ae205Smrg            if(argn >= argc - 1) {
241af7d3019Smrg                missing_arg("-f");
242ea6ae205Smrg            }
243ea6ae205Smrg            bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
244ea6ae205Smrg            argn += 2;
245af7d3019Smrg	} else if (strcmp(argv[argn], "-v") == 0) {
246af7d3019Smrg	    printf("%s\n", PACKAGE_STRING);
247af7d3019Smrg	    exit(0);
248ea6ae205Smrg	} else {
249ea6ae205Smrg            usage();
250ea6ae205Smrg        }
251ea6ae205Smrg    }
252ea6ae205Smrg
253ea6ae205Smrg    if(outfilename == NULL) {
254ea6ae205Smrg        if(doBitmaps)
255ea6ae205Smrg            outfilename = "fonts.dir";
256663cdc11Smrg        else
257ea6ae205Smrg            outfilename = "fonts.scale";
258ea6ae205Smrg    }
259ea6ae205Smrg
260ea6ae205Smrg    ftrc = FT_Init_FreeType(&ft_library);
261ea6ae205Smrg    if(ftrc) {
262ea6ae205Smrg        fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
263ea6ae205Smrg        exit(1);
264ea6ae205Smrg    }
265ea6ae205Smrg
266ea6ae205Smrg    ll = listLength(encodingsToDo);
267ea6ae205Smrg
268ea6ae205Smrg    if (argn == argc)
269ea6ae205Smrg        doDirectory(".", ll, encodingsToDo);
270ea6ae205Smrg    else
271ea6ae205Smrg        while(argn < argc) {
272ea6ae205Smrg            doDirectory(argv[argn], ll, encodingsToDo);
273ea6ae205Smrg            argn++;
274ea6ae205Smrg        }
275ea6ae205Smrg    return 0;
276ea6ae205Smrg}
277ea6ae205Smrg
278ea6ae205Smrgstatic int
279ea6ae205SmrggetNameHelper(FT_Face face, int nid, int pid, int eid,
280ea6ae205Smrg              FT_SfntName *name_return)
281ea6ae205Smrg{
282ea6ae205Smrg    FT_SfntName name;
283ea6ae205Smrg    int n, i;
284ea6ae205Smrg
285ea6ae205Smrg    n = FT_Get_Sfnt_Name_Count(face);
286ea6ae205Smrg    if(n <= 0)
287ea6ae205Smrg        return 0;
288ea6ae205Smrg
289ea6ae205Smrg    for(i = 0; i < n; i++) {
290ea6ae205Smrg        if(FT_Get_Sfnt_Name(face, i, &name))
291ea6ae205Smrg            continue;
292ea6ae205Smrg        if(name.name_id == nid &&
293ea6ae205Smrg           name.platform_id == pid &&
294ea6ae205Smrg           (eid < 0 || name.encoding_id == eid)) {
295ea6ae205Smrg            switch(name.platform_id) {
296ea6ae205Smrg            case TT_PLATFORM_APPLE_UNICODE:
297ea6ae205Smrg            case TT_PLATFORM_MACINTOSH:
298ea6ae205Smrg                if(name.language_id != TT_MAC_LANGID_ENGLISH)
299ea6ae205Smrg                    continue;
300ea6ae205Smrg                break;
301ea6ae205Smrg            case TT_PLATFORM_MICROSOFT:
302ea6ae205Smrg                if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
303ea6ae205Smrg                   name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
304ea6ae205Smrg                    continue;
305ea6ae205Smrg                break;
306ea6ae205Smrg            default:
307ea6ae205Smrg                continue;
308ea6ae205Smrg            }
309ea6ae205Smrg            if(name.string_len > 0) {
310ea6ae205Smrg                *name_return = name;
311ea6ae205Smrg                return 1;
312ea6ae205Smrg            }
313ea6ae205Smrg        }
314ea6ae205Smrg    }
315ea6ae205Smrg    return 0;
316ea6ae205Smrg}
317ea6ae205Smrg
318ea6ae205Smrgstatic char *
319ea6ae205SmrggetName(FT_Face face, int nid)
320ea6ae205Smrg{
321ea6ae205Smrg    FT_SfntName name;
322ea6ae205Smrg    char *string;
323ea6ae205Smrg    int i;
324ea6ae205Smrg
325663cdc11Smrg    if(getNameHelper(face, nid,
326ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
327663cdc11Smrg       getNameHelper(face, nid,
328ea6ae205Smrg                     TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
329ea6ae205Smrg        string = malloc(name.string_len / 2 + 1);
330ea6ae205Smrg        if(string == NULL) {
331ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
332ea6ae205Smrg            exit(1);
333ea6ae205Smrg        }
334ea6ae205Smrg        for(i = 0; i < name.string_len / 2; i++) {
335ea6ae205Smrg            if(name.string[2 * i] != 0)
336ea6ae205Smrg                string[i] = '?';
337ea6ae205Smrg            else
338ea6ae205Smrg                string[i] = name.string[2 * i + 1];
339ea6ae205Smrg        }
340ea6ae205Smrg        string[i] = '\0';
341ea6ae205Smrg        return string;
342ea6ae205Smrg    }
343ea6ae205Smrg
344ea6ae205Smrg    /* Pretend that Apple Roman is ISO 8859-1. */
345ea6ae205Smrg    if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
346ea6ae205Smrg                     &name)) {
347ea6ae205Smrg        string = malloc(name.string_len + 1);
348ea6ae205Smrg        if(string == NULL) {
349ea6ae205Smrg            fprintf(stderr, "Couldn't allocate name\n");
350ea6ae205Smrg            exit(1);
351ea6ae205Smrg        }
352ea6ae205Smrg        memcpy(string, name.string, name.string_len);
353ea6ae205Smrg        string[name.string_len] = '\0';
354ea6ae205Smrg        return string;
355ea6ae205Smrg    }
356ea6ae205Smrg
357ea6ae205Smrg    return NULL;
358ea6ae205Smrg}
359ea6ae205Smrg
360663cdc11Smrgstatic const char*
361ea6ae205Smrgos2Weight(int weight)
362ea6ae205Smrg{
363ea6ae205Smrg    if(weight < 150)
364ea6ae205Smrg        return "thin";
365ea6ae205Smrg    else if(weight < 250)
366ea6ae205Smrg        return "extralight";
367ea6ae205Smrg    else if(weight < 350)
368ea6ae205Smrg        return "light";
369ea6ae205Smrg    else if(weight < 450)
370ea6ae205Smrg        return "medium";        /* officially "normal" */
371ea6ae205Smrg    else if(weight < 550)
372ea6ae205Smrg        return "medium";
373ea6ae205Smrg    else if(weight < 650)
374ea6ae205Smrg        return "semibold";
375ea6ae205Smrg    else if(weight < 750)
376ea6ae205Smrg        return "bold";
377ea6ae205Smrg    else if(weight < 850)
378ea6ae205Smrg        return "extrabold";
379663cdc11Smrg    else
380ea6ae205Smrg        return "black";
381ea6ae205Smrg}
382ea6ae205Smrg
383663cdc11Smrgstatic const char*
384ea6ae205Smrgos2Width(int width)
385ea6ae205Smrg{
386ea6ae205Smrg    if(width <= 1)
387ea6ae205Smrg        return "ultracondensed";
388ea6ae205Smrg    else if(width <= 2)
389ea6ae205Smrg        return "extracondensed";
390ea6ae205Smrg    else if(width <= 3)
391ea6ae205Smrg        return "condensed";
392ea6ae205Smrg    else if(width <= 4)
393ea6ae205Smrg        return "semicondensed";
394ea6ae205Smrg    else if(width <= 5)
395ea6ae205Smrg        return "normal";
396ea6ae205Smrg    else if(width <= 6)
397ea6ae205Smrg        return "semiexpanded";
398ea6ae205Smrg    else if(width <= 7)
399ea6ae205Smrg        return "expanded";
400ea6ae205Smrg    else if(width <= 8)
401ea6ae205Smrg        return "extraexpanded";
402ea6ae205Smrg    else
403ea6ae205Smrg        return "ultraexpanded";
404ea6ae205Smrg}
405ea6ae205Smrg
406663cdc11Smrgstatic const char *widths[] = {
407ea6ae205Smrg    "ultracondensed", "extracondensed", "condensed", "semicondensed",
408663cdc11Smrg    "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
409ea6ae205Smrg};
410ea6ae205Smrg
411ea6ae205Smrg#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
412ea6ae205Smrg
413663cdc11Smrgstatic const char*
414663cdc11SmrgnameWidth(const char *name)
415ea6ae205Smrg{
416ea6ae205Smrg    char buf[500];
417ea6ae205Smrg    int i;
418ea6ae205Smrg    int n = strlen(name);
419ea6ae205Smrg
420ea6ae205Smrg    if(n >= 499) return NULL;
421ea6ae205Smrg    for(i = 0; i < n; i++)
422ea6ae205Smrg        buf[i] = tolower(name[i]);
423ea6ae205Smrg    buf[i] = '\0';
424ea6ae205Smrg
425ea6ae205Smrg    for(i = 0; i < NUMWIDTHS; i++)
426ea6ae205Smrg        if(strstr(buf, widths[i]))
427ea6ae205Smrg            return widths[i];
428ea6ae205Smrg    return NULL;
429ea6ae205Smrg}
430ea6ae205Smrg
431663cdc11Smrgstatic const char*
432663cdc11Smrgt1Weight(const char *weight)
433ea6ae205Smrg{
434ea6ae205Smrg    if(!weight)
435ea6ae205Smrg        return NULL;
436ea6ae205Smrg    if(strcmp(weight, "Thin") == 0)
437ea6ae205Smrg        return "thin";
438663cdc11Smrg    if(strcmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
439663cdc11Smrg        return "extralight";
440ea6ae205Smrg    if(strcmp(weight, "Light") == 0)
441ea6ae205Smrg        return "light";
442ea6ae205Smrg    if(strcmp(weight, "Regular") == 0)
443ea6ae205Smrg        return "medium";
444ea6ae205Smrg    if(strcmp(weight, "Normal") == 0)
445ea6ae205Smrg        return "medium";
446ea6ae205Smrg    if(strcmp(weight, "Medium") == 0)
447ea6ae205Smrg        return "medium";
448ea6ae205Smrg    if(strcmp(weight, "Book") == 0)
449ea6ae205Smrg        return "medium";
450ea6ae205Smrg    if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
451ea6ae205Smrg        return "medium";
452ea6ae205Smrg    if(strcmp(weight, "Demi") == 0)
453ea6ae205Smrg        return "semibold";
454ea6ae205Smrg    if(strcmp(weight, "DemiBold") == 0)
455ea6ae205Smrg        return "semibold";
456ea6ae205Smrg    if(strcmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
457ea6ae205Smrg        return "semibold";
458ea6ae205Smrg    else if(strcmp(weight, "Bold") == 0)
459ea6ae205Smrg        return "bold";
460663cdc11Smrg    else if(strcmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
461663cdc11Smrg        return "extrabold";
462ea6ae205Smrg    else if(strcmp(weight, "Black") == 0)
463ea6ae205Smrg        return "black";
464ea6ae205Smrg    else {
465ea6ae205Smrg        fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
466ea6ae205Smrg        return NULL;
467ea6ae205Smrg    }
468ea6ae205Smrg}
469ea6ae205Smrg
470ea6ae205Smrgstatic int
471ea6ae205Smrgunsafe(char c)
472ea6ae205Smrg{
473663cdc11Smrg    return
474ea6ae205Smrg        c < 0x20 || c > 0x7E ||
475ea6ae205Smrg        c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
476ea6ae205Smrg}
477ea6ae205Smrg
478663cdc11Smrgstatic const char *
479663cdc11Smrgsafe(const char* s)
480ea6ae205Smrg{
481ea6ae205Smrg    int i, len, safe_flag = 1;
482ea6ae205Smrg    char *t;
483ea6ae205Smrg
484ea6ae205Smrg    i = 0;
485ea6ae205Smrg    while(s[i] != '\0') {
486ea6ae205Smrg        if(unsafe(s[i]))
487ea6ae205Smrg            safe_flag = 0;
488ea6ae205Smrg        i++;
489ea6ae205Smrg    }
490ea6ae205Smrg
491af7d3019Smrg    if(safe_flag) return strdup(s);
492ea6ae205Smrg
493ea6ae205Smrg    len = i;
494ea6ae205Smrg    t = malloc(len + 1);
495ea6ae205Smrg    if(t == NULL) {
496ea6ae205Smrg        perror("Couldn't allocate string");
497ea6ae205Smrg        exit(1);
498ea6ae205Smrg    }
499ea6ae205Smrg
500ea6ae205Smrg    for(i = 0; i < len; i++) {
501ea6ae205Smrg        if(unsafe(s[i]))
502ea6ae205Smrg            t[i] = ' ';
503ea6ae205Smrg        else
504ea6ae205Smrg            t[i] = s[i];
505ea6ae205Smrg    }
506ea6ae205Smrg    t[i] = '\0';
507ea6ae205Smrg    return t;
508ea6ae205Smrg}
509ea6ae205Smrg
510ea6ae205SmrgListPtr
511ea6ae205SmrgmakeXLFD(char *filename, FT_Face face, int isBitmap)
512ea6ae205Smrg{
513ea6ae205Smrg    ListPtr xlfd = NULL;
514663cdc11Smrg    const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
515af7d3019Smrg        *spacing, *full_name, *tmp;
516ea6ae205Smrg    TT_Header *head;
517ea6ae205Smrg    TT_HoriHeader *hhea;
518ea6ae205Smrg    TT_OS2 *os2;
519ea6ae205Smrg    TT_Postscript *post;
520ea6ae205Smrg    PS_FontInfoRec *t1info, t1info_rec;
521ea6ae205Smrg    int rc;
522ea6ae205Smrg
523ea6ae205Smrg    foundry = NULL;
524ea6ae205Smrg    family = NULL;
525ea6ae205Smrg    weight = NULL;
526ea6ae205Smrg    slant = NULL;
527ea6ae205Smrg    sWidth = NULL;
528ea6ae205Smrg    adstyle = NULL;
529ea6ae205Smrg    spacing = NULL;
530ea6ae205Smrg    full_name = NULL;
531ea6ae205Smrg
532ea6ae205Smrg    head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
533ea6ae205Smrg    hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
534ea6ae205Smrg    os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
535ea6ae205Smrg    post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
536ea6ae205Smrg
537ea6ae205Smrg    rc = FT_Get_PS_Font_Info(face, &t1info_rec);
538ea6ae205Smrg    if(rc == 0)
539ea6ae205Smrg        t1info = &t1info_rec;
540ea6ae205Smrg    else
541ea6ae205Smrg        t1info = NULL;
542663cdc11Smrg
543ea6ae205Smrg    if(!family)
544ea6ae205Smrg        family = getName(face, TT_NAME_ID_FONT_FAMILY);
545ea6ae205Smrg    if(!family)
546ea6ae205Smrg        family = getName(face, TT_NAME_ID_FULL_NAME);
547ea6ae205Smrg    if(!family)
548ea6ae205Smrg        family = getName(face, TT_NAME_ID_PS_NAME);
549ea6ae205Smrg
550ea6ae205Smrg    if(!full_name)
551ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_FULL_NAME);
552ea6ae205Smrg    if(!full_name)
553ea6ae205Smrg        full_name = getName(face, TT_NAME_ID_PS_NAME);
554ea6ae205Smrg
555ea6ae205Smrg    if(os2 && os2->version != 0xFFFF) {
556ea6ae205Smrg        if(!weight)
557ea6ae205Smrg            weight = os2Weight(os2->usWeightClass);
558ea6ae205Smrg        if(!sWidth)
559ea6ae205Smrg            sWidth = os2Width(os2->usWidthClass);
560ea6ae205Smrg        if(!foundry)
561ea6ae205Smrg            foundry = vendor_foundry(os2->achVendID);
562ea6ae205Smrg        if(!slant)
563ea6ae205Smrg            slant = os2->fsSelection & 1 ? "i" : "r";
564ea6ae205Smrg    }
565ea6ae205Smrg
566ea6ae205Smrg    if(post) {
567ea6ae205Smrg        if(!spacing) {
568ea6ae205Smrg            if(post->isFixedPitch) {
569ea6ae205Smrg                if(hhea->min_Left_Side_Bearing >= 0 &&
570ea6ae205Smrg                   hhea->xMax_Extent <= hhea->advance_Width_Max) {
571ea6ae205Smrg                    spacing = "c";
572ea6ae205Smrg                } else {
573ea6ae205Smrg                    spacing = "m";
574ea6ae205Smrg                }
575ea6ae205Smrg            } else {
576ea6ae205Smrg                spacing = "p";
577ea6ae205Smrg            }
578ea6ae205Smrg        }
579ea6ae205Smrg    }
580663cdc11Smrg
581ea6ae205Smrg    if(t1info) {
582eaa89f16Smrg        if(!family && t1info->family_name)
583af7d3019Smrg            family = strdup(t1info->family_name);
584eaa89f16Smrg        if(!family && t1info->full_name)
585af7d3019Smrg            family = strdup(t1info->full_name);
586eaa89f16Smrg        /* Hershey fonts miss /FamilyName */
587eaa89f16Smrg        if(!family && face->family_name)
588eaa89f16Smrg            family = strdup(face->family_name);
589eaa89f16Smrg        if(!full_name && t1info->full_name)
590af7d3019Smrg            full_name = strdup(t1info->full_name);
591ea6ae205Smrg        if(!foundry)
592ea6ae205Smrg            foundry = notice_foundry(t1info->notice);
593ea6ae205Smrg        if(!weight)
594ea6ae205Smrg            weight = t1Weight(t1info->weight);
595ea6ae205Smrg        if(!spacing)
596ea6ae205Smrg            spacing = t1info->is_fixed_pitch ? "m" : "p";
597ea6ae205Smrg        if(!slant) {
598ea6ae205Smrg            /* Bitstream fonts have positive italic angle. */
599ea6ae205Smrg            slant =
600ea6ae205Smrg                t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
601ea6ae205Smrg                "i" : "r";
602ea6ae205Smrg        }
603ea6ae205Smrg    }
604ea6ae205Smrg
605ea6ae205Smrg    if(!full_name) {
606ea6ae205Smrg        fprintf(stderr, "Couldn't determine full name for %s\n", filename);
607af7d3019Smrg        full_name = strdup(filename);
608ea6ae205Smrg    }
609ea6ae205Smrg
610ea6ae205Smrg    if(head) {
611ea6ae205Smrg        if(!slant)
612ea6ae205Smrg            slant = head->Mac_Style & 2 ? "i" : "r";
613ea6ae205Smrg        if(!weight)
614ea6ae205Smrg            weight = head->Mac_Style & 1 ? "bold" : "medium";
615ea6ae205Smrg    }
616ea6ae205Smrg
617ea6ae205Smrg    if(!slant) {
618ea6ae205Smrg        fprintf(stderr, "Couldn't determine slant for %s\n", filename);
619ea6ae205Smrg        slant = "r";
620ea6ae205Smrg    }
621ea6ae205Smrg
622ea6ae205Smrg    if(!weight) {
623ea6ae205Smrg        fprintf(stderr, "Couldn't determine weight for %s\n", filename);
624ea6ae205Smrg        weight = "medium";
625ea6ae205Smrg    }
626ea6ae205Smrg
627ea6ae205Smrg    if(!foundry) {
628ea6ae205Smrg        char *notice;
629ea6ae205Smrg        notice = getName(face, TT_NAME_ID_TRADEMARK);
630ea6ae205Smrg        if(notice) {
631ea6ae205Smrg            foundry = notice_foundry(notice);
632af7d3019Smrg            free(notice);
633ea6ae205Smrg        }
634ea6ae205Smrg        if(!foundry) {
635ea6ae205Smrg            notice = getName(face, TT_NAME_ID_MANUFACTURER);
636ea6ae205Smrg            if(notice) {
637ea6ae205Smrg                foundry = notice_foundry(notice);
638af7d3019Smrg                free(notice);
639ea6ae205Smrg            }
640ea6ae205Smrg        }
641ea6ae205Smrg    }
642ea6ae205Smrg
643ea6ae205Smrg    if(strcmp(slant, "i") == 0) {
644ea6ae205Smrg        if(strstr(full_name, "Oblique"))
645ea6ae205Smrg            slant = "o";
646ea6ae205Smrg        if(strstr(full_name, "Slanted"))
647ea6ae205Smrg            slant = "o";
648ea6ae205Smrg    }
649ea6ae205Smrg
650ea6ae205Smrg    if(!sWidth)
651ea6ae205Smrg        sWidth = nameWidth(full_name);
652ea6ae205Smrg
653ea6ae205Smrg    if(!foundry) foundry = "misc";
654ea6ae205Smrg    if(!family) {
655ea6ae205Smrg        fprintf(stderr, "Couldn't get family name for %s\n", filename);
656af7d3019Smrg        family = strdup(filename);
657ea6ae205Smrg    }
658ea6ae205Smrg
659ea6ae205Smrg    if(!weight) weight = "medium";
660ea6ae205Smrg    if(!slant) slant = "r";
661ea6ae205Smrg    if(!sWidth) sWidth = "normal";
662ea6ae205Smrg    if(!adstyle) adstyle = "";
663ea6ae205Smrg    if(!spacing) spacing = "p";
664ea6ae205Smrg
665ea6ae205Smrg    foundry = safe(foundry);
666af7d3019Smrg
667af7d3019Smrg    tmp = family;
668ea6ae205Smrg    family = safe(family);
669af7d3019Smrg    free((void *)tmp);
670ea6ae205Smrg
671ea6ae205Smrg    if(!isBitmap) {
672ea6ae205Smrg        xlfd = listConsF(xlfd,
673ea6ae205Smrg                         "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
674ea6ae205Smrg                         foundry, family,
675ea6ae205Smrg                         weight, slant, sWidth, adstyle, spacing);
676ea6ae205Smrg    } else {
677ea6ae205Smrg        int i, w, h, xres, yres;
678ea6ae205Smrg        for(i = 0; i < face->num_fixed_sizes; i++) {
679ea6ae205Smrg            w = face->available_sizes[i].width;
680ea6ae205Smrg            h = face->available_sizes[i].height;
681ea6ae205Smrg            xres = 75;
682ea6ae205Smrg            yres = (double)h / w * xres;
683ea6ae205Smrg            xlfd = listConsF(xlfd,
684ea6ae205Smrg                             "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
685ea6ae205Smrg                             foundry, family,
686ea6ae205Smrg                             weight, slant, sWidth, adstyle,
687ea6ae205Smrg                             h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
688ea6ae205Smrg                             xres, yres,
689ea6ae205Smrg                             spacing, 60);
690ea6ae205Smrg        }
691ea6ae205Smrg    }
692af7d3019Smrg
693af7d3019Smrg    free((void *)family);
694af7d3019Smrg    free((void *)foundry);
695af7d3019Smrg    free((void *)full_name);
696ea6ae205Smrg    return xlfd;
697ea6ae205Smrg}
698ea6ae205Smrg
699ea6ae205Smrgstatic int
700ea6ae205SmrgreadFontScale(HashTablePtr entries, char *dirname)
701ea6ae205Smrg{
702ea6ae205Smrg    int n = strlen(dirname);
703ea6ae205Smrg    char *filename;
704ea6ae205Smrg    FILE *in;
705ea6ae205Smrg    int rc, count, i;
706245f6787Smrg    char file[MAXFONTFILENAMELEN+1], font[MAXFONTNAMELEN+1];
707ea6ae205Smrg
708ea6ae205Smrg    if(dirname[n - 1] == '/')
709ea6ae205Smrg        filename = dsprintf("%sfonts.scale", dirname);
710ea6ae205Smrg    else
711ea6ae205Smrg        filename = dsprintf("%s/fonts.scale", dirname);
712ea6ae205Smrg    if(filename == NULL)
713ea6ae205Smrg        return -1;
714ea6ae205Smrg
715ea6ae205Smrg    in = fopen(filename, "r");
716ea6ae205Smrg    free(filename);
717ea6ae205Smrg    if(in == NULL) {
718ea6ae205Smrg        if(errno != ENOENT)
719ea6ae205Smrg            perror("open(fonts.scale)");
720ea6ae205Smrg        return -1;
721ea6ae205Smrg    }
722ea6ae205Smrg
723ea6ae205Smrg    rc = fscanf(in, "%d\n", &count);
724ea6ae205Smrg    if(rc != 1) {
725ea6ae205Smrg        fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
726ea6ae205Smrg        fclose(in);
727ea6ae205Smrg        return -1;
728ea6ae205Smrg    }
729ea6ae205Smrg
730ea6ae205Smrg    for(i = 0; i < count; i++) {
731245f6787Smrg        rc = fscanf(in,
732245f6787Smrg		    "%" STRINGIFY(MAXFONTFILENAMELEN) "s "
733245f6787Smrg		    "%" STRINGIFY(MAXFONTNAMELEN) "[^\n]\n",
734245f6787Smrg		    file, font);
735ea6ae205Smrg        if(rc != 2)
736ea6ae205Smrg            break;
737ea6ae205Smrg        putHash(entries, font, file, 100);
738ea6ae205Smrg    }
739ea6ae205Smrg    fclose(in);
740ea6ae205Smrg    return 1;
741ea6ae205Smrg}
742ea6ae205Smrg
743ea6ae205Smrgstatic int
744ea6ae205SmrgfilePrio(char *filename)
745ea6ae205Smrg{
746ea6ae205Smrg    int n = strlen(filename);
747ea6ae205Smrg    if(n < 4)
748ea6ae205Smrg        return 0;
749ea6ae205Smrg    if(strcmp(filename + n - 4, ".otf") == 0)
750ea6ae205Smrg        return 6;
751ea6ae205Smrg    if(strcmp(filename + n - 4, ".OTF") == 0)
752ea6ae205Smrg        return 6;
753ea6ae205Smrg    if(strcmp(filename + n - 4, ".ttf") == 0)
754ea6ae205Smrg        return 5;
755ea6ae205Smrg    if(strcmp(filename + n - 4, ".TTF") == 0)
756ea6ae205Smrg        return 5;
757ea6ae205Smrg    if(strcmp(filename + n - 4, ".pcf") == 0)
758ea6ae205Smrg        return 4;
759ea6ae205Smrg    if(strcmp(filename + n - 4, ".PCF") == 0)
760ea6ae205Smrg        return 4;
761ea6ae205Smrg    if(strcmp(filename + n - 3, ".gz") == 0)
762ea6ae205Smrg        return 3;
7637978d3cdSmrg#ifdef X_BZIP2_FONT_COMPRESSION
7647978d3cdSmrg    if(strcmp(filename + n - 4, ".bz2") == 0)
7657978d3cdSmrg        return 2;
7667978d3cdSmrg#endif
767ea6ae205Smrg    if(strcmp(filename + n - 2, ".Z") == 0)
768ea6ae205Smrg        return 2;
769ea6ae205Smrg    if(strcmp(filename + n - 4, ".bdf") == 0)
770ea6ae205Smrg        return 1;
771ea6ae205Smrg    if(strcmp(filename + n - 4, ".BDF") == 0)
772ea6ae205Smrg        return 1;
773ea6ae205Smrg    return 0;
774ea6ae205Smrg}
775ea6ae205Smrg
776ea6ae205Smrgstatic int
777663cdc11SmrgdoDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
778ea6ae205Smrg{
779ea6ae205Smrg    char *dirname, *fontscale_name, *filename, *encdir;
780ea6ae205Smrg    FILE *fontscale, *encfile;
781ea6ae205Smrg    DIR *dirp;
782ea6ae205Smrg    struct dirent *entry;
783ea6ae205Smrg    FT_Error ftrc;
784ea6ae205Smrg    FT_Face face;
785ea6ae205Smrg    ListPtr encoding, xlfd, lp;
786ea6ae205Smrg    HashTablePtr entries;
787ea6ae205Smrg    HashBucketPtr *array;
788ea6ae205Smrg    int i, n, found, rc;
789ea6ae205Smrg    int isBitmap=0,xl=0;
790ea6ae205Smrg
791ea6ae205Smrg    if (exclusionSuffix)
792ea6ae205Smrg        xl = strlen (exclusionSuffix);
793ea6ae205Smrg
794ea6ae205Smrg    i = strlen(dirname_given);
795ea6ae205Smrg    if(i == 0)
796ea6ae205Smrg        dirname = dsprintf("./");
797ea6ae205Smrg    else if(dirname_given[i - 1] != '/')
798ea6ae205Smrg        dirname = dsprintf("%s/", dirname_given);
799ea6ae205Smrg    else
800ea6ae205Smrg        dirname = dsprintf("%s", dirname_given);
801ea6ae205Smrg
802ea6ae205Smrg    if(dirname == NULL) {
803ea6ae205Smrg        perror("dirname");
804ea6ae205Smrg        exit(1);
805ea6ae205Smrg    }
806ea6ae205Smrg
807663cdc11Smrg    if (onlyEncodings)
808ea6ae205Smrg	goto encodings;
809663cdc11Smrg
810ea6ae205Smrg    entries = makeHashTable();
811ea6ae205Smrg    if(doBitmaps && !doScalable) {
812ea6ae205Smrg        readFontScale(entries, dirname);
813ea6ae205Smrg    }
814ea6ae205Smrg
815ea6ae205Smrg    if(strcmp(outfilename, "-") == 0)
816ea6ae205Smrg        fontscale_name = NULL;
817ea6ae205Smrg    else {
818ea6ae205Smrg        if(outfilename[0] == '/')
819ea6ae205Smrg            fontscale_name = dsprintf("%s", outfilename);
820ea6ae205Smrg        else
821ea6ae205Smrg            fontscale_name = dsprintf("%s%s", dirname, outfilename);
822ea6ae205Smrg        if(fontscale_name == NULL) {
823ea6ae205Smrg            perror("fontscale_name");
824ea6ae205Smrg            exit(1);
825ea6ae205Smrg        }
826ea6ae205Smrg    }
827ea6ae205Smrg
828ea6ae205Smrg    dirp = opendir(dirname);
829ea6ae205Smrg    if(dirp == NULL) {
830ea6ae205Smrg        fprintf(stderr, "%s: ", dirname);
831ea6ae205Smrg        perror("opendir");
832ea6ae205Smrg        return 0;
833ea6ae205Smrg    }
834ea6ae205Smrg
835ea6ae205Smrg    if(fontscale_name == NULL)
836ea6ae205Smrg        fontscale = stdout;
837ea6ae205Smrg    else
838ea6ae205Smrg        fontscale = fopen(fontscale_name, "wb");
839ea6ae205Smrg
840ea6ae205Smrg    if(fontscale == NULL) {
841ea6ae205Smrg        fprintf(stderr, "%s: ", fontscale_name);
842ea6ae205Smrg        perror("fopen(w)");
843ea6ae205Smrg        return 0;
844ea6ae205Smrg    }
845ea6ae205Smrg
846ea6ae205Smrg    while((entry = readdir(dirp)) != NULL) {
847ea6ae205Smrg        int have_face = 0;
848ea6ae205Smrg        char *xlfd_name = NULL;
8492d6e8b77Smrg	struct stat f_stat;
8502d6e8b77Smrg	int tprio = 1;
8512d6e8b77Smrg
852ea6ae205Smrg        xlfd = NULL;
853ea6ae205Smrg
854ea6ae205Smrg	if (xl) {
855ea6ae205Smrg	    int dl = strlen (entry->d_name);
856ea6ae205Smrg	    if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
857ea6ae205Smrg		continue;
858ea6ae205Smrg	}
859ea6ae205Smrg
860ea6ae205Smrg        filename = dsprintf("%s%s", dirname, entry->d_name);
861ea6ae205Smrg
8622d6e8b77Smrg#define PRIO(x) ((x << 1) + tprio)
8632d6e8b77Smrg#ifdef DT_LNK
8642d6e8b77Smrg	if (entry->d_type != DT_UNKNOWN) {
8652d6e8b77Smrg	    if (entry->d_type == DT_LNK)
8662d6e8b77Smrg		tprio = 0;
8672d6e8b77Smrg	} else
8682d6e8b77Smrg#endif
8692d6e8b77Smrg#ifdef S_ISLNK
8702d6e8b77Smrg	{
8712d6e8b77Smrg	    if (lstat(filename, &f_stat))
8722d6e8b77Smrg		goto done;
8732d6e8b77Smrg	    if (S_ISLNK(f_stat.st_mode))
8742d6e8b77Smrg		tprio = 0;
8752d6e8b77Smrg	}
8762d6e8b77Smrg#else
8772d6e8b77Smrg	;
8782d6e8b77Smrg#endif
879ea6ae205Smrg        if(doBitmaps)
880ea6ae205Smrg            rc = bitmapIdentify(filename, &xlfd_name);
881ea6ae205Smrg        else
882ea6ae205Smrg            rc = 0;
883ea6ae205Smrg
884ea6ae205Smrg        if(rc < 0)
885ea6ae205Smrg            goto done;
886ea6ae205Smrg
887ea6ae205Smrg        if(rc == 0) {
888ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
889ea6ae205Smrg            if(ftrc)
890ea6ae205Smrg                goto done;
891ea6ae205Smrg            have_face = 1;
892ea6ae205Smrg
893ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
894ea6ae205Smrg
895ea6ae205Smrg            if(!isBitmap) {
896ea6ae205Smrg                /* Workaround for bitmap-only SFNT fonts */
897ea6ae205Smrg                if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
898ea6ae205Smrg                   strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
899ea6ae205Smrg                    TT_MaxProfile *maxp;
900ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
901ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
902ea6ae205Smrg                        isBitmap = 1;
903ea6ae205Smrg                }
904ea6ae205Smrg            }
905663cdc11Smrg
906ea6ae205Smrg            if(isBitmap) {
907ea6ae205Smrg                if(!doBitmaps)
908ea6ae205Smrg                    goto done;
909ea6ae205Smrg            } else {
910ea6ae205Smrg                if(!doScalable)
911ea6ae205Smrg                    goto done;
912ea6ae205Smrg            }
913ea6ae205Smrg
914ea6ae205Smrg            if(isBitmap) {
915ea6ae205Smrg                BDF_PropertyRec prop;
916ea6ae205Smrg                rc = FT_Get_BDF_Property(face, "FONT", &prop);
917ea6ae205Smrg                if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
9182d6e8b77Smrg                    xlfd_name = strdup(prop.u.atom);
919ea6ae205Smrg                    if(xlfd_name == NULL)
920ea6ae205Smrg                        goto done;
921ea6ae205Smrg                }
922ea6ae205Smrg            }
923ea6ae205Smrg        }
924ea6ae205Smrg
925ea6ae205Smrg        if(xlfd_name) {
926ea6ae205Smrg            /* We know it's a bitmap font, and we know its XLFD */
927ea6ae205Smrg            int n = strlen(xlfd_name);
928ea6ae205Smrg            if(reencodeLegacy &&
929ea6ae205Smrg               n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
930ea6ae205Smrg                char *s;
931ea6ae205Smrg
932ea6ae205Smrg                s = malloc(n - 10);
933ea6ae205Smrg                memcpy(s, xlfd_name, n - 11);
934ea6ae205Smrg                s[n - 11] = '\0';
935ea6ae205Smrg                xlfd = listCons(s, xlfd);
936ea6ae205Smrg            } else {
937ea6ae205Smrg                /* Not a reencodable font -- skip all the rest of the loop body */
9382d6e8b77Smrg                putHash(entries, xlfd_name, entry->d_name, PRIO(filePrio(entry->d_name)));
939ea6ae205Smrg                goto done;
940ea6ae205Smrg            }
941ea6ae205Smrg        }
942ea6ae205Smrg
943ea6ae205Smrg        if(!have_face) {
944ea6ae205Smrg            ftrc = FT_New_Face(ft_library, filename, 0, &face);
945ea6ae205Smrg            if(ftrc)
946ea6ae205Smrg                goto done;
947ea6ae205Smrg            have_face = 1;
948ea6ae205Smrg            isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
949ea6ae205Smrg
950ea6ae205Smrg            if(!isBitmap) {
951ea6ae205Smrg                if(face->num_fixed_sizes > 0) {
952ea6ae205Smrg                    TT_MaxProfile *maxp;
953ea6ae205Smrg                    maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
954ea6ae205Smrg                    if(maxp != NULL && maxp->maxContours == 0)
955ea6ae205Smrg                        isBitmap = 1;
956ea6ae205Smrg                }
957ea6ae205Smrg            }
958ea6ae205Smrg        }
959ea6ae205Smrg
960ea6ae205Smrg        if(xlfd == NULL)
961ea6ae205Smrg            xlfd = makeXLFD(entry->d_name, face, isBitmap);
962ea6ae205Smrg
963ea6ae205Smrg        found = 0;
964ea6ae205Smrg
965ea6ae205Smrg        for(lp = xlfd; lp; lp = lp->next) {
966ea6ae205Smrg            char buf[MAXFONTNAMELEN];
967ea6ae205Smrg            for(encoding = encodings; encoding; encoding = encoding->next) {
968ea6ae205Smrg                if(checkEncoding(face, encoding->value)) {
969ea6ae205Smrg                    found = 1;
970ea6ae205Smrg                    snprintf(buf, MAXFONTNAMELEN, "%s-%s",
971ea6ae205Smrg                            lp->value, encoding->value);
9722d6e8b77Smrg                    putHash(entries, buf, entry->d_name, PRIO(filePrio(entry->d_name)));
973ea6ae205Smrg                }
974ea6ae205Smrg            }
975663cdc11Smrg            for(encoding = extra_encodings; encoding;
976ea6ae205Smrg                encoding = encoding->next) {
977ea6ae205Smrg                if(checkExtraEncoding(face, encoding->value, found)) {
978ea6ae205Smrg                    /* Do not set found! */
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            }
984ea6ae205Smrg        }
985ea6ae205Smrg    done:
986245f6787Smrg        if(have_face)
987ea6ae205Smrg            FT_Done_Face(face);
988ea6ae205Smrg        deepDestroyList(xlfd);
989ea6ae205Smrg        xlfd = NULL;
990ea6ae205Smrg        free(filename);
9912d6e8b77Smrg#undef PRIO
992ea6ae205Smrg    }
993ea6ae205Smrg
994ea6ae205Smrg    closedir(dirp);
995ea6ae205Smrg    n = hashElements(entries);
996ea6ae205Smrg    fprintf(fontscale, "%d\n", n);
997ea6ae205Smrg    array = hashArray(entries, 1);
998ea6ae205Smrg    for(i = 0; i < n; i++)
999ea6ae205Smrg        fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
1000ea6ae205Smrg    destroyHashArray(array);
1001ea6ae205Smrg    entries = NULL;
1002ea6ae205Smrg    if(fontscale_name) {
1003ea6ae205Smrg        fclose(fontscale);
1004ea6ae205Smrg        free(fontscale_name);
1005ea6ae205Smrg    }
1006ea6ae205Smrg
1007ea6ae205Smrg encodings:
1008ea6ae205Smrg    encdir = dsprintf("%s%s", dirname, "encodings.dir");
1009ea6ae205Smrg
1010ea6ae205Smrg    if(encdir == NULL) {
1011ea6ae205Smrg	perror("encodings");
1012ea6ae205Smrg	exit(1);
1013ea6ae205Smrg    }
1014ea6ae205Smrg    unlink(encdir);
1015ea6ae205Smrg
1016ea6ae205Smrg    if (numEncodings) {
1017ea6ae205Smrg	encfile = fopen(encdir, "w");
1018ea6ae205Smrg	if(encfile == NULL) {
1019ea6ae205Smrg	    perror("open(encodings.dir)");
1020ea6ae205Smrg	    exit(1);
1021ea6ae205Smrg	}
1022ea6ae205Smrg        fprintf(encfile, "%d\n", numEncodings);
1023245f6787Smrg        encodingsToDo = sortList(encodingsToDo);
1024ea6ae205Smrg        for(lp = encodingsToDo; lp; lp = lp->next) {
1025ea6ae205Smrg            fprintf(encfile, "%s\n", lp->value);
1026ea6ae205Smrg        }
1027ea6ae205Smrg	fclose (encfile);
1028ea6ae205Smrg    }
1029ea6ae205Smrg
1030ea6ae205Smrg    free(dirname);
1031ea6ae205Smrg    return 1;
1032ea6ae205Smrg}
1033ea6ae205Smrg
1034ea6ae205Smrg#define CODE_IGNORED(c) ((c) < 0x20 || \
1035ea6ae205Smrg                         ((c) >= 0x7F && (c) <= 0xA0) || \
1036ea6ae205Smrg                         (c) == 0xAD || (c) == 0xF71B)
1037663cdc11Smrg
1038ea6ae205Smrgstatic int
1039ea6ae205SmrgcheckEncoding(FT_Face face, char *encoding_name)
1040ea6ae205Smrg{
1041ea6ae205Smrg    FontEncPtr encoding;
1042ea6ae205Smrg    FontMapPtr mapping;
1043ea6ae205Smrg    int i, j, c, koi8;
1044ea6ae205Smrg    char *n;
1045ea6ae205Smrg
1046ea6ae205Smrg    encoding = FontEncFind(encoding_name, NULL);
1047ea6ae205Smrg    if(!encoding)
1048ea6ae205Smrg        return 0;
1049ea6ae205Smrg
1050ea6ae205Smrg    /* An encoding is ``small'' if one of the following is true:
1051ea6ae205Smrg         - it is linear and has no more than 256 codepoints; or
1052ea6ae205Smrg         - it is a matrix encoding and has no more than one column.
1053663cdc11Smrg
1054ea6ae205Smrg       For small encodings using Unicode indices, we require perfect
1055ea6ae205Smrg       coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1056ea6ae205Smrg
1057ea6ae205Smrg       For large encodings, we require coverage up to bigEncodingFuzz.
1058ea6ae205Smrg
1059ea6ae205Smrg       For encodings using PS names (currently Adobe Standard and
1060ea6ae205Smrg       Adobe Symbol only), we require perfect coverage. */
1061ea6ae205Smrg
1062ea6ae205Smrg
1063ea6ae205Smrg    if(FT_Has_PS_Glyph_Names(face)) {
1064ea6ae205Smrg        for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1065ea6ae205Smrg            if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
1066ea6ae205Smrg                if(encoding->row_size > 0) {
1067ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1068663cdc11Smrg                        for(j = encoding->first_col;
1069663cdc11Smrg                            j < encoding->row_size;
1070ea6ae205Smrg                            j++) {
1071ea6ae205Smrg                            n = FontEncName((i<<8) | j, mapping);
1072ea6ae205Smrg                            if(n && FT_Get_Name_Index(face, n) == 0) {
1073ea6ae205Smrg                                return 0;
1074ea6ae205Smrg                            }
1075ea6ae205Smrg                        }
1076ea6ae205Smrg                    }
1077ea6ae205Smrg                    return 1;
1078ea6ae205Smrg                } else {
1079ea6ae205Smrg                    for(i = encoding->first; i < encoding->size; i++) {
1080ea6ae205Smrg                        n = FontEncName(i, mapping);
1081ea6ae205Smrg                        if(n && FT_Get_Name_Index(face, n) == 0) {
1082ea6ae205Smrg                            return 0;
1083ea6ae205Smrg                        }
1084ea6ae205Smrg                    }
1085ea6ae205Smrg                    return 1;
1086ea6ae205Smrg                }
1087ea6ae205Smrg            }
1088ea6ae205Smrg        }
1089ea6ae205Smrg    }
1090ea6ae205Smrg
1091ea6ae205Smrg    for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1092ea6ae205Smrg        if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1093ea6ae205Smrg            int total = 0, failed = 0;
1094ea6ae205Smrg            if(encoding->row_size > 0) {
1095663cdc11Smrg                int estimate =
1096ea6ae205Smrg                    (encoding->size - encoding->first) *
1097ea6ae205Smrg                    (encoding->row_size - encoding->first_col);
1098ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1099663cdc11Smrg                    for(j = encoding->first_col;
1100663cdc11Smrg                        j < encoding->row_size;
1101ea6ae205Smrg                        j++) {
1102ea6ae205Smrg                        c = FontEncRecode((i<<8) | j, mapping);
1103ea6ae205Smrg                        if(CODE_IGNORED(c)) {
1104ea6ae205Smrg                            continue;
1105ea6ae205Smrg                        } else {
1106ea6ae205Smrg                            if(FT_Get_Char_Index(face, c) == 0) {
1107ea6ae205Smrg                                failed++;
1108ea6ae205Smrg                            }
1109ea6ae205Smrg                            total++;
1110ea6ae205Smrg                            if((encoding->size <= 1 && failed > 0) ||
1111ea6ae205Smrg                               ((float)failed >= bigEncodingFuzz * estimate)) {
1112ea6ae205Smrg                                return 0;
1113ea6ae205Smrg                            }
1114ea6ae205Smrg                        }
1115ea6ae205Smrg                    }
1116ea6ae205Smrg                }
1117ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1118ea6ae205Smrg                    return 0;
1119ea6ae205Smrg                else
1120ea6ae205Smrg                    return 1;
1121ea6ae205Smrg            } else {
1122ea6ae205Smrg                int estimate = encoding->size - encoding->first;
1123ea6ae205Smrg                /* For the KOI8 encodings, we ignore the lack of
1124ea6ae205Smrg                   linedrawing and pseudo-math characters */
1125ea6ae205Smrg                if(strncmp(encoding->name, "koi8-", 5) == 0)
1126ea6ae205Smrg                    koi8 = 1;
1127ea6ae205Smrg                else
1128ea6ae205Smrg                    koi8 = 0;
1129ea6ae205Smrg                for(i = encoding->first; i < encoding->size; i++) {
1130ea6ae205Smrg                    c = FontEncRecode(i, mapping);
1131ea6ae205Smrg                    if(CODE_IGNORED(c) ||
1132ea6ae205Smrg                       (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1133ea6ae205Smrg                        continue;
1134ea6ae205Smrg                    } else {
1135ea6ae205Smrg                        if(FT_Get_Char_Index(face, c) == 0) {
1136ea6ae205Smrg                            failed++;
1137ea6ae205Smrg                        }
1138ea6ae205Smrg                        total++;
1139ea6ae205Smrg                        if((encoding->size <= 256 && failed > 0) ||
1140ea6ae205Smrg                           ((float)failed >= bigEncodingFuzz * estimate)) {
1141ea6ae205Smrg                            return 0;
1142ea6ae205Smrg                        }
1143ea6ae205Smrg                    }
1144ea6ae205Smrg                }
1145ea6ae205Smrg                if((float)failed >= total * bigEncodingFuzz)
1146ea6ae205Smrg                    return 0;
1147ea6ae205Smrg                else
1148ea6ae205Smrg                    return 1;
1149ea6ae205Smrg            }
1150ea6ae205Smrg        }
1151ea6ae205Smrg    }
1152ea6ae205Smrg    return 0;
1153ea6ae205Smrg}
1154ea6ae205Smrg
1155663cdc11Smrgstatic int
1156ea6ae205Smrgfind_cmap(int type, int pid, int eid, FT_Face face)
1157ea6ae205Smrg{
1158ea6ae205Smrg    int i, n, rc;
1159ea6ae205Smrg    FT_CharMap cmap = NULL;
1160ea6ae205Smrg
1161ea6ae205Smrg    n = face->num_charmaps;
1162ea6ae205Smrg
1163ea6ae205Smrg    switch(type) {
1164ea6ae205Smrg    case FONT_ENCODING_TRUETYPE:  /* specific cmap */
1165ea6ae205Smrg        for(i=0; i<n; i++) {
1166ea6ae205Smrg            cmap = face->charmaps[i];
1167ea6ae205Smrg            if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1168ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1169ea6ae205Smrg                if(rc == 0)
1170ea6ae205Smrg                    return 1;
1171ea6ae205Smrg            }
1172ea6ae205Smrg        }
1173ea6ae205Smrg        break;
1174ea6ae205Smrg    case FONT_ENCODING_UNICODE:   /* any Unicode cmap */
1175ea6ae205Smrg        /* prefer Microsoft Unicode */
1176ea6ae205Smrg        for(i=0; i<n; i++) {
1177ea6ae205Smrg            cmap = face->charmaps[i];
1178663cdc11Smrg            if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1179ea6ae205Smrg               cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
1180ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1181ea6ae205Smrg                if(rc == 0)
1182ea6ae205Smrg                    return 1;
1183ea6ae205Smrg            }
1184ea6ae205Smrg        }
1185ea6ae205Smrg        /* Try Apple Unicode */
1186ea6ae205Smrg        for(i=0; i<n; i++) {
1187ea6ae205Smrg            cmap = face->charmaps[i];
1188ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
1189ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1190ea6ae205Smrg                if(rc == 0)
1191ea6ae205Smrg                    return 1;
1192ea6ae205Smrg            }
1193ea6ae205Smrg        }
1194ea6ae205Smrg        /* ISO Unicode? */
1195ea6ae205Smrg        for(i=0; i<n; i++) {
1196ea6ae205Smrg            cmap = face->charmaps[i];
1197ea6ae205Smrg            if(cmap->platform_id == TT_PLATFORM_ISO) {
1198ea6ae205Smrg                rc = FT_Set_Charmap(face, cmap);
1199ea6ae205Smrg                if(rc == 0)
1200ea6ae205Smrg                    return 1;
1201ea6ae205Smrg            }
1202ea6ae205Smrg        }
1203ea6ae205Smrg        break;
1204ea6ae205Smrg    default:
1205ea6ae205Smrg        return 0;
1206ea6ae205Smrg    }
1207ea6ae205Smrg    return 0;
1208ea6ae205Smrg}
1209ea6ae205Smrg
1210ea6ae205Smrgstatic int
1211ea6ae205SmrgcheckExtraEncoding(FT_Face face, char *encoding_name, int found)
1212ea6ae205Smrg{
1213ea6ae205Smrg    int c;
1214ea6ae205Smrg
1215ea6ae205Smrg    if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1216ea6ae205Smrg        if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
1217ea6ae205Smrg            int found = 0;
1218ea6ae205Smrg             /* Export as Unicode if there are at least 15 BMP
1219ea6ae205Smrg               characters that are not a space or ignored. */
1220ea6ae205Smrg            for(c = 0x21; c < 0x10000; c++) {
1221ea6ae205Smrg                if(CODE_IGNORED(c))
1222ea6ae205Smrg                    continue;
1223ea6ae205Smrg                if(FT_Get_Char_Index(face, c) > 0)
1224ea6ae205Smrg                    found++;
1225ea6ae205Smrg                if(found >= 15)
1226ea6ae205Smrg                    return 1;
1227ea6ae205Smrg            }
1228ea6ae205Smrg            return 0;
1229ea6ae205Smrg        } else
1230ea6ae205Smrg            return 0;
1231ea6ae205Smrg    } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1232ea6ae205Smrg        if(find_cmap(FONT_ENCODING_TRUETYPE,
1233ea6ae205Smrg                     TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
1234ea6ae205Smrg                     face))
1235ea6ae205Smrg            return 1;
1236ea6ae205Smrg        else
1237ea6ae205Smrg            return 0;
1238ea6ae205Smrg    } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1239ea6ae205Smrg        if(!found) {
1240ea6ae205Smrg            if(FT_Has_PS_Glyph_Names(face))
1241ea6ae205Smrg                return 1;
1242ea6ae205Smrg            else
1243ea6ae205Smrg                return 0;
1244ea6ae205Smrg        } else
1245ea6ae205Smrg            return 0;
1246ea6ae205Smrg    } else {
1247ea6ae205Smrg        fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
1248ea6ae205Smrg        return 0;
1249ea6ae205Smrg    }
1250ea6ae205Smrg}
1251ea6ae205Smrg
1252663cdc11Smrgstatic const char*
1253663cdc11Smrgnotice_foundry(const char *notice)
1254ea6ae205Smrg{
1255ea6ae205Smrg    int i;
1256ea6ae205Smrg    for(i = 0; i < countof(notice_foundries); i++)
1257ea6ae205Smrg        if(notice && strstr(notice, notice_foundries[i][0]))
1258ea6ae205Smrg            return notice_foundries[i][1];
1259ea6ae205Smrg    return NULL;
1260ea6ae205Smrg}
1261ea6ae205Smrg
1262ea6ae205Smrgstatic int
1263663cdc11Smrgvendor_match(const signed char *vendor, const char *vendor_string)
1264ea6ae205Smrg{
1265ea6ae205Smrg    /* vendor is not necessarily NUL-terminated. */
1266ea6ae205Smrg    int i, len;
1267ea6ae205Smrg    len = strlen(vendor_string);
1268ea6ae205Smrg    if(memcmp(vendor, vendor_string, len) != 0)
1269ea6ae205Smrg        return 0;
1270ea6ae205Smrg    for(i = len; i < 4; i++)
1271ea6ae205Smrg        if(vendor[i] != ' ' && vendor[i] != '\0')
1272ea6ae205Smrg            return 0;
1273ea6ae205Smrg    return 1;
1274ea6ae205Smrg}
1275ea6ae205Smrg
1276663cdc11Smrgstatic const char*
1277663cdc11Smrgvendor_foundry(const signed char *vendor)
1278ea6ae205Smrg{
1279ea6ae205Smrg    int i;
1280ea6ae205Smrg    for(i = 0; i < countof(vendor_foundries); i++)
1281ea6ae205Smrg        if(vendor_match(vendor, vendor_foundries[i][0]))
1282ea6ae205Smrg            return vendor_foundries[i][1];
1283ea6ae205Smrg    return NULL;
1284ea6ae205Smrg}
1285ea6ae205Smrg
1286ea6ae205Smrgstatic int
1287ea6ae205SmrgreadEncodings(ListPtr encodings, char *dirname)
1288ea6ae205Smrg{
1289ea6ae205Smrg    char *fullname;
1290ea6ae205Smrg    DIR *dirp;
1291ea6ae205Smrg    struct dirent *file;
1292ea6ae205Smrg    char **names, **name;
1293ea6ae205Smrg
1294ea6ae205Smrg    if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1295ea6ae205Smrg        dirname[strlen(dirname) - 1] = '\0';
1296ea6ae205Smrg
1297ea6ae205Smrg    dirp = opendir(dirname);
1298ea6ae205Smrg    if(dirp == NULL) {
1299ea6ae205Smrg        perror("opendir");
1300ea6ae205Smrg        return -1;
1301ea6ae205Smrg    }
1302ea6ae205Smrg
1303ea6ae205Smrg    while((file = readdir(dirp)) != NULL) {
1304ea6ae205Smrg        fullname = dsprintf("%s/%s", dirname, file->d_name);
1305ea6ae205Smrg        if(fullname == NULL) {
1306ea6ae205Smrg            fprintf(stderr, "Couldn't allocate fullname\n");
1307ea6ae205Smrg            closedir(dirp);
1308ea6ae205Smrg            return -1;
1309ea6ae205Smrg        }
1310663cdc11Smrg
1311ea6ae205Smrg        names = FontEncIdentify(fullname);
1312ea6ae205Smrg        if(!names)
1313ea6ae205Smrg            continue;
1314ea6ae205Smrg
1315ea6ae205Smrg        for(name = names; *name; name++) {
1316ea6ae205Smrg            if(fullname[0] != '/' && !relative) {
1317ea6ae205Smrg                char *n;
1318ea6ae205Smrg                n = dsprintf("%s%s", encodingPrefix, fullname);
1319ea6ae205Smrg                if(n == NULL) {
1320ea6ae205Smrg                    fprintf(stderr, "Couldn't allocate name\n");
1321ea6ae205Smrg                    closedir(dirp);
1322ea6ae205Smrg                    return -1;
1323ea6ae205Smrg                }
1324ea6ae205Smrg                encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1325ea6ae205Smrg                free(n);
1326ea6ae205Smrg            } else {
1327663cdc11Smrg                encodingsToDo =
1328ea6ae205Smrg                    listConsF(encodingsToDo, "%s %s", *name, fullname);
1329ea6ae205Smrg            }
1330ea6ae205Smrg            if(encodingsToDo == NULL) {
1331ea6ae205Smrg                fprintf(stderr, "Couldn't allocate encodings\n");
1332ea6ae205Smrg                closedir(dirp);
1333ea6ae205Smrg                return -1;
1334ea6ae205Smrg            }
1335ea6ae205Smrg        }
1336ea6ae205Smrg        free(names);            /* only the spine */
1337ea6ae205Smrg    }
1338ea6ae205Smrg    closedir(dirp);
1339ea6ae205Smrg    return 0;
1340ea6ae205Smrg}
1341