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