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