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