2 Copyright (c) 2002-2003 by Juliusz Chroboczek
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include <sys/types.h>
35 #include <X11/fonts/fontenc.h>
37 #include FT_FREETYPE_H
38 #include FT_SFNT_NAMES_H
39 #include FT_TRUETYPE_TABLES_H
40 #include FT_TRUETYPE_IDS_H
41 #include FT_TYPE1_TABLES_H
52 #ifndef MAXFONTFILENAMELEN
53 #define MAXFONTFILENAMELEN 1024
55 #ifndef MAXFONTNAMELEN
56 #define MAXFONTNAMELEN 1024
59 /* Two levels of macro calls are needed so that we stringify the value
60 of MAXFONT... and not the string "MAXFONT..." */
62 #define STRINGIFY(x) QUOTE(x)
64 static const char *encodings_array[] =
66 "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5",
67 "iso8859-6", "iso8859-6.8", "iso8859-6.8x", "iso8859-6.16",
68 "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10",
69 "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14",
70 "iso8859-15", "iso8859-16",
71 "ansi-1251", "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni",
73 "sun.unicode.india-0", "suneu-greek",
74 "adobe-standard", "adobe-symbol",
75 "ibm-cp437", "ibm-cp850", "ibm-cp852", "ibm-cp866", "microsoft-cp1252",
76 /* But not "adobe-dingbats", as it uses generic glyph names. */
77 "cns11643-1", "cns11643-2", "cns11643-3",
78 "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0",
79 "jisx0212.1990-0", "big5-0", "big5.eten-0", "big5hkscs-0",
80 "gb2312.1980-0", "gb18030.2000-0", "gb18030.2000-1",
81 "ksc5601.1987-0", "ksc5601.1992-3"};
83 static const char *extra_encodings_array[] =
84 { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" };
86 static ListPtr encodings, extra_encodings;
87 static const char *outfilename;
89 #define countof(_a) (sizeof(_a)/sizeof((_a)[0]))
91 static int doDirectory(const char*, int, ListPtr);
92 static int checkEncoding(FT_Face face, char *encoding_name);
93 static int checkExtraEncoding(FT_Face face, char *encoding_name, int found);
94 static int find_cmap(int type, int pid, int eid, FT_Face face);
95 static const char* notice_foundry(const char *notice);
96 static const char* vendor_foundry(const signed char *vendor);
97 static int readFontScale(HashTablePtr entries, char *dirname);
98 ListPtr makeXLFD(char *filename, FT_Face face, int);
99 static int readEncodings(ListPtr encodings, char *dirname);
101 static FT_Library ft_library;
102 static float bigEncodingFuzz = 0.02;
105 static int doScalable;
106 static int doBitmaps;
107 static int doISO10646_1_encoding;
108 static int onlyEncodings;
109 static ListPtr encodingsToDo;
110 static int reencodeLegacy;
111 static char *encodingPrefix;
112 static char *exclusionSuffix;
118 "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n"
119 " [ -a encoding ] [ -f fuzz ] [ -l ] "
120 " [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n"
121 " [-u] [-U] [ directory ]...\n");
125 main(int argc, char **argv)
130 char prefix[NPREFIX];
132 encodingPrefix = NULL;
133 exclusionSuffix = NULL;
135 if(getcwd(prefix, NPREFIX - 1) == NULL) {
136 perror("Couldn't get cwd");
139 if(prefix[strlen(prefix) - 1] != '/')
141 encodingPrefix = dsprintf("%s", prefix);
145 encodings = makeList(encodings_array, countof(encodings_array), NULL, 0);
147 extra_encodings = makeList(extra_encodings_array,
148 countof(extra_encodings_array),
151 doISO10646_1_encoding = 1;
156 encodingsToDo = NULL;
160 if(argv[argn][0] == '\0' || argv[argn][0] != '-')
162 if(argv[argn][1] == '-') {
165 } else if (strcmp(argv[argn], "-x") == 0) {
166 if(argn >= argc - 1) {
170 exclusionSuffix = argv[argn + 1];
172 } else if(strcmp(argv[argn], "-a") == 0) {
173 if(argn >= argc - 1) {
177 makeList(&argv[argn + 1], 1, encodings, 0);
179 } else if(strcmp(argv[argn], "-p") == 0) {
180 if(argn >= argc - 1) {
184 if(strlen(argv[argn + 1]) > NPREFIX - 1) {
188 free(encodingPrefix);
189 encodingPrefix = dsprintf("%s", argv[argn + 1]);
191 } else if(strcmp(argv[argn], "-e") == 0) {
192 if(argn >= argc - 1) {
196 rc = readEncodings(encodingsToDo, argv[argn + 1]);
200 } else if(strcmp(argv[argn], "-b") == 0) {
203 } else if(strcmp(argv[argn], "-u") == 0) {
204 doISO10646_1_encoding = 0;
206 } else if(strcmp(argv[argn], "-U") == 0) {
207 doISO10646_1_encoding = 1;
209 } else if(strcmp(argv[argn], "-s") == 0) {
212 } else if(strcmp(argv[argn], "-n") == 0) {
215 } else if(strcmp(argv[argn], "-r") == 0) {
218 } else if(strcmp(argv[argn], "-l") == 0) {
219 reencodeLegacy = !reencodeLegacy;
221 } else if(strcmp(argv[argn], "-o") == 0) {
222 if(argn >= argc - 1) {
226 outfilename = argv[argn + 1];
228 } else if(strcmp(argv[argn], "-f") == 0) {
229 if(argn >= argc - 1) {
233 bigEncodingFuzz = atof(argv[argn + 1]) / 100.0;
235 } else if (strcmp(argv[argn], "-r") == 0) { /* ignore for now */
237 } else if (strcmp(argv[argn], "-n") == 0) {
245 if(outfilename == NULL) {
247 outfilename = "fonts.dir";
249 outfilename = "fonts.scale";
252 ftrc = FT_Init_FreeType(&ft_library);
254 fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc);
258 ll = listLength(encodingsToDo);
261 doDirectory(".", ll, encodingsToDo);
264 doDirectory(argv[argn], ll, encodingsToDo);
271 getNameHelper(FT_Face face, int nid, int pid, int eid,
272 FT_SfntName *name_return)
277 n = FT_Get_Sfnt_Name_Count(face);
281 for(i = 0; i < n; i++) {
282 if(FT_Get_Sfnt_Name(face, i, &name))
284 if(name.name_id == nid &&
285 name.platform_id == pid &&
286 (eid < 0 || name.encoding_id == eid)) {
287 switch(name.platform_id) {
288 case TT_PLATFORM_APPLE_UNICODE:
289 case TT_PLATFORM_MACINTOSH:
290 if(name.language_id != TT_MAC_LANGID_ENGLISH)
293 case TT_PLATFORM_MICROSOFT:
294 if(name.language_id != TT_MS_LANGID_ENGLISH_UNITED_STATES &&
295 name.language_id != TT_MS_LANGID_ENGLISH_UNITED_KINGDOM)
301 if(name.string_len > 0) {
311 getName(FT_Face face, int nid)
317 if(getNameHelper(face, nid,
318 TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, &name) ||
319 getNameHelper(face, nid,
320 TT_PLATFORM_APPLE_UNICODE, -1, &name)) {
321 string = malloc(name.string_len / 2 + 1);
323 fprintf(stderr, "Couldn't allocate name\n");
326 for(i = 0; i < name.string_len / 2; i++) {
327 if(name.string[2 * i] != 0)
330 string[i] = name.string[2 * i + 1];
336 /* Pretend that Apple Roman is ISO 8859-1. */
337 if(getNameHelper(face, nid, TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN,
339 string = malloc(name.string_len + 1);
341 fprintf(stderr, "Couldn't allocate name\n");
344 memcpy(string, name.string, name.string_len);
345 string[name.string_len] = '\0';
353 os2Weight(int weight)
357 else if(weight < 250)
359 else if(weight < 350)
361 else if(weight < 450)
362 return "medium"; /* officially "normal" */
363 else if(weight < 550)
365 else if(weight < 650)
367 else if(weight < 750)
369 else if(weight < 850)
379 return "ultracondensed";
381 return "extracondensed";
385 return "semicondensed";
389 return "semiexpanded";
393 return "extraexpanded";
395 return "ultraexpanded";
398 static const char *widths[] = {
399 "ultracondensed", "extracondensed", "condensed", "semicondensed",
400 "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded"
403 #define NUMWIDTHS (sizeof(widths) / sizeof(widths[0]))
406 nameWidth(const char *name)
410 int n = strlen(name);
412 if(n >= 499) return NULL;
413 for(i = 0; i < n; i++)
414 buf[i] = tolower(name[i]);
417 for(i = 0; i < NUMWIDTHS; i++)
418 if(strstr(buf, widths[i]))
424 t1Weight(const char *weight)
428 if(strcmp(weight, "Thin") == 0)
430 if(strcmp(weight, "ExtraLight") == 0) /* FontForge uses this for 200*/
432 if(strcmp(weight, "Light") == 0)
434 if(strcmp(weight, "Regular") == 0)
436 if(strcmp(weight, "Normal") == 0)
438 if(strcmp(weight, "Medium") == 0)
440 if(strcmp(weight, "Book") == 0)
442 if(strcmp(weight, "Roman") == 0) /* Some URW++ fonts do that! */
444 if(strcmp(weight, "Demi") == 0)
446 if(strcmp(weight, "DemiBold") == 0)
448 if(strcmp(weight, "SemiBold") == 0) /* some TeX fonts apparently do that */
450 else if(strcmp(weight, "Bold") == 0)
452 else if(strcmp(weight, "Heavy") == 0) /* FontForge uses this for 800*/
454 else if(strcmp(weight, "Black") == 0)
457 fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight);
466 c < 0x20 || c > 0x7E ||
467 c == '[' || c == ']' || c == '(' || c == ')' || c == '\\' || c == '-';
473 int i, len, safe_flag = 1;
477 while(s[i] != '\0') {
483 if(safe_flag) return s;
488 perror("Couldn't allocate string");
492 for(i = 0; i < len; i++) {
503 makeXLFD(char *filename, FT_Face face, int isBitmap)
506 const char *foundry, *family, *weight, *slant, *sWidth, *adstyle,
507 *spacing, *full_name;
512 PS_FontInfoRec *t1info, t1info_rec;
524 head = FT_Get_Sfnt_Table(face, ft_sfnt_head);
525 hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
526 os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
527 post = FT_Get_Sfnt_Table(face, ft_sfnt_post);
529 rc = FT_Get_PS_Font_Info(face, &t1info_rec);
531 t1info = &t1info_rec;
536 family = getName(face, TT_NAME_ID_FONT_FAMILY);
538 family = getName(face, TT_NAME_ID_FULL_NAME);
540 family = getName(face, TT_NAME_ID_PS_NAME);
543 full_name = getName(face, TT_NAME_ID_FULL_NAME);
545 full_name = getName(face, TT_NAME_ID_PS_NAME);
547 if(os2 && os2->version != 0xFFFF) {
549 weight = os2Weight(os2->usWeightClass);
551 sWidth = os2Width(os2->usWidthClass);
553 foundry = vendor_foundry(os2->achVendID);
555 slant = os2->fsSelection & 1 ? "i" : "r";
560 if(post->isFixedPitch) {
561 if(hhea->min_Left_Side_Bearing >= 0 &&
562 hhea->xMax_Extent <= hhea->advance_Width_Max) {
575 family = t1info->family_name;
577 family = t1info->full_name;
579 full_name = t1info->full_name;
581 foundry = notice_foundry(t1info->notice);
583 weight = t1Weight(t1info->weight);
585 spacing = t1info->is_fixed_pitch ? "m" : "p";
587 /* Bitstream fonts have positive italic angle. */
589 t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ?
595 fprintf(stderr, "Couldn't determine full name for %s\n", filename);
596 full_name = filename;
601 slant = head->Mac_Style & 2 ? "i" : "r";
603 weight = head->Mac_Style & 1 ? "bold" : "medium";
607 fprintf(stderr, "Couldn't determine slant for %s\n", filename);
612 fprintf(stderr, "Couldn't determine weight for %s\n", filename);
618 notice = getName(face, TT_NAME_ID_TRADEMARK);
620 foundry = notice_foundry(notice);
623 notice = getName(face, TT_NAME_ID_MANUFACTURER);
625 foundry = notice_foundry(notice);
630 if(strcmp(slant, "i") == 0) {
631 if(strstr(full_name, "Oblique"))
633 if(strstr(full_name, "Slanted"))
638 sWidth = nameWidth(full_name);
640 if(!foundry) foundry = "misc";
642 fprintf(stderr, "Couldn't get family name for %s\n", filename);
646 if(!weight) weight = "medium";
647 if(!slant) slant = "r";
648 if(!sWidth) sWidth = "normal";
649 if(!adstyle) adstyle = "";
650 if(!spacing) spacing = "p";
652 /* Yes, it's a memory leak. */
653 foundry = safe(foundry);
654 family = safe(family);
657 xlfd = listConsF(xlfd,
658 "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0",
660 weight, slant, sWidth, adstyle, spacing);
662 int i, w, h, xres, yres;
663 for(i = 0; i < face->num_fixed_sizes; i++) {
664 w = face->available_sizes[i].width;
665 h = face->available_sizes[i].height;
667 yres = (double)h / w * xres;
668 xlfd = listConsF(xlfd,
669 "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d",
671 weight, slant, sWidth, adstyle,
672 h, (int)(h / (double)yres * 72.27 * 10 + 0.5),
681 readFontScale(HashTablePtr entries, char *dirname)
683 int n = strlen(dirname);
687 char file[MAXFONTFILENAMELEN+1], font[MAXFONTNAMELEN+1];
689 if(dirname[n - 1] == '/')
690 filename = dsprintf("%sfonts.scale", dirname);
692 filename = dsprintf("%s/fonts.scale", dirname);
696 in = fopen(filename, "r");
700 perror("open(fonts.scale)");
704 rc = fscanf(in, "%d\n", &count);
706 fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname);
711 for(i = 0; i < count; i++) {
713 "%" STRINGIFY(MAXFONTFILENAMELEN) "s "
714 "%" STRINGIFY(MAXFONTNAMELEN) "[^\n]\n",
718 putHash(entries, font, file, 100);
725 filePrio(char *filename)
727 int n = strlen(filename);
730 if(strcmp(filename + n - 4, ".otf") == 0)
732 if(strcmp(filename + n - 4, ".OTF") == 0)
734 if(strcmp(filename + n - 4, ".ttf") == 0)
736 if(strcmp(filename + n - 4, ".TTF") == 0)
738 if(strcmp(filename + n - 4, ".pcf") == 0)
740 if(strcmp(filename + n - 4, ".PCF") == 0)
742 if(strcmp(filename + n - 3, ".gz") == 0)
744 #ifdef X_BZIP2_FONT_COMPRESSION
745 if(strcmp(filename + n - 4, ".bz2") == 0)
748 if(strcmp(filename + n - 2, ".Z") == 0)
750 if(strcmp(filename + n - 4, ".bdf") == 0)
752 if(strcmp(filename + n - 4, ".BDF") == 0)
758 doDirectory(const char *dirname_given, int numEncodings, ListPtr encodingsToDo)
760 char *dirname, *fontscale_name, *filename, *encdir;
761 FILE *fontscale, *encfile;
763 struct dirent *entry;
766 ListPtr encoding, xlfd, lp;
767 HashTablePtr entries;
768 HashBucketPtr *array;
773 xl = strlen (exclusionSuffix);
775 i = strlen(dirname_given);
777 dirname = dsprintf("./");
778 else if(dirname_given[i - 1] != '/')
779 dirname = dsprintf("%s/", dirname_given);
781 dirname = dsprintf("%s", dirname_given);
783 if(dirname == NULL) {
791 entries = makeHashTable();
792 if(doBitmaps && !doScalable) {
793 readFontScale(entries, dirname);
796 if(strcmp(outfilename, "-") == 0)
797 fontscale_name = NULL;
799 if(outfilename[0] == '/')
800 fontscale_name = dsprintf("%s", outfilename);
802 fontscale_name = dsprintf("%s%s", dirname, outfilename);
803 if(fontscale_name == NULL) {
804 perror("fontscale_name");
809 dirp = opendir(dirname);
811 fprintf(stderr, "%s: ", dirname);
816 if(fontscale_name == NULL)
819 fontscale = fopen(fontscale_name, "wb");
821 if(fontscale == NULL) {
822 fprintf(stderr, "%s: ", fontscale_name);
827 while((entry = readdir(dirp)) != NULL) {
829 char *xlfd_name = NULL;
830 struct stat file_stat;
835 int dl = strlen (entry->d_name);
836 if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0)
840 filename = dsprintf("%s%s", dirname, entry->d_name);
842 /* check if file is a symbolic link*/
843 ret = lstat (filename, &file_stat);
845 if (S_ISLNK(file_stat.st_mode)) {
847 /* Use realpath to get the absolute path
848 by removing the ./ and ../ */
850 char base_canon_fname[PATH_MAX] = {0,};
851 char *canon_fname = NULL, *canon_dirname = NULL;
854 canon_dirname = realpath (dirname, NULL);
855 canon_fname = realpath (filename, NULL);
856 /* skip broken symlinks (Novell Bug #529815) */
860 base_strlen = strlen (strrchr (canon_fname, '/'));
862 strncpy (base_canon_fname, canon_fname, strlen(canon_fname) - base_strlen);
864 /* skip the symbolic, if both the symlink and reference file
865 are residing in the same directory */
866 if (strcmp (base_canon_fname, canon_dirname) == 0)
872 rc = bitmapIdentify(filename, &xlfd_name);
880 ftrc = FT_New_Face(ft_library, filename, 0, &face);
885 isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
888 /* Workaround for bitmap-only SFNT fonts */
889 if(FT_IS_SFNT(face) && face->num_fixed_sizes > 0 &&
890 strcmp(FT_Get_X11_Font_Format(face), "TrueType") == 0) {
892 maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
893 if(maxp != NULL && maxp->maxContours == 0)
907 BDF_PropertyRec prop;
908 rc = FT_Get_BDF_Property(face, "FONT", &prop);
909 if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) {
910 xlfd_name = malloc(strlen(prop.u.atom) + 1);
911 if(xlfd_name == NULL)
913 strcpy(xlfd_name, prop.u.atom);
919 /* We know it's a bitmap font, and we know its XLFD */
920 int n = strlen(xlfd_name);
922 n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) {
926 memcpy(s, xlfd_name, n - 11);
928 xlfd = listCons(s, xlfd);
930 /* Not a reencodable font -- skip all the rest of the loop body */
931 putHash(entries, xlfd_name, entry->d_name, filePrio(entry->d_name));
937 ftrc = FT_New_Face(ft_library, filename, 0, &face);
941 isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
944 if(face->num_fixed_sizes > 0) {
946 maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp);
947 if(maxp != NULL && maxp->maxContours == 0)
954 xlfd = makeXLFD(entry->d_name, face, isBitmap);
958 for(lp = xlfd; lp; lp = lp->next) {
959 char buf[MAXFONTNAMELEN];
960 for(encoding = encodings; encoding; encoding = encoding->next) {
961 if(checkEncoding(face, encoding->value)) {
963 snprintf(buf, MAXFONTNAMELEN, "%s-%s",
964 lp->value, encoding->value);
965 putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
968 for(encoding = extra_encodings; encoding;
969 encoding = encoding->next) {
970 if(checkExtraEncoding(face, encoding->value, found)) {
971 /* Do not set found! */
972 snprintf(buf, MAXFONTNAMELEN, "%s-%s",
973 lp->value, encoding->value);
974 putHash(entries, buf, entry->d_name, filePrio(entry->d_name));
981 deepDestroyList(xlfd);
987 n = hashElements(entries);
988 fprintf(fontscale, "%d\n", n);
989 array = hashArray(entries, 1);
990 for(i = 0; i < n; i++)
991 fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key);
992 destroyHashArray(array);
996 free(fontscale_name);
1000 encdir = dsprintf("%s%s", dirname, "encodings.dir");
1002 if(encdir == NULL) {
1003 perror("encodings");
1009 encfile = fopen(encdir, "w");
1010 if(encfile == NULL) {
1011 perror("open(encodings.dir)");
1014 fprintf(encfile, "%d\n", numEncodings);
1015 encodingsToDo = sortList(encodingsToDo);
1016 for(lp = encodingsToDo; lp; lp = lp->next) {
1017 fprintf(encfile, "%s\n", lp->value);
1026 #define CODE_IGNORED(c) ((c) < 0x20 || \
1027 ((c) >= 0x7F && (c) <= 0xA0) || \
1028 (c) == 0xAD || (c) == 0xF71B)
1031 checkEncoding(FT_Face face, char *encoding_name)
1033 FontEncPtr encoding;
1038 encoding = FontEncFind(encoding_name, NULL);
1042 /* An encoding is ``small'' if one of the following is true:
1043 - it is linear and has no more than 256 codepoints; or
1044 - it is a matrix encoding and has no more than one column.
1046 For small encodings using Unicode indices, we require perfect
1047 coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility.
1049 For large encodings, we require coverage up to bigEncodingFuzz.
1051 For encodings using PS names (currently Adobe Standard and
1052 Adobe Symbol only), we require perfect coverage. */
1055 if(FT_Has_PS_Glyph_Names(face)) {
1056 for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1057 if(mapping->type == FONT_ENCODING_POSTSCRIPT) {
1058 if(encoding->row_size > 0) {
1059 for(i = encoding->first; i < encoding->size; i++) {
1060 for(j = encoding->first_col;
1061 j < encoding->row_size;
1063 n = FontEncName((i<<8) | j, mapping);
1064 if(n && FT_Get_Name_Index(face, n) == 0) {
1071 for(i = encoding->first; i < encoding->size; i++) {
1072 n = FontEncName(i, mapping);
1073 if(n && FT_Get_Name_Index(face, n) == 0) {
1083 for(mapping = encoding->mappings; mapping; mapping = mapping->next) {
1084 if(find_cmap(mapping->type, mapping->pid, mapping->eid, face)) {
1085 int total = 0, failed = 0;
1086 if(encoding->row_size > 0) {
1088 (encoding->size - encoding->first) *
1089 (encoding->row_size - encoding->first_col);
1090 for(i = encoding->first; i < encoding->size; i++) {
1091 for(j = encoding->first_col;
1092 j < encoding->row_size;
1094 c = FontEncRecode((i<<8) | j, mapping);
1095 if(CODE_IGNORED(c)) {
1098 if(FT_Get_Char_Index(face, c) == 0) {
1102 if((encoding->size <= 1 && failed > 0) ||
1103 ((float)failed >= bigEncodingFuzz * estimate)) {
1109 if((float)failed >= total * bigEncodingFuzz)
1114 int estimate = encoding->size - encoding->first;
1115 /* For the KOI8 encodings, we ignore the lack of
1116 linedrawing and pseudo-math characters */
1117 if(strncmp(encoding->name, "koi8-", 5) == 0)
1121 for(i = encoding->first; i < encoding->size; i++) {
1122 c = FontEncRecode(i, mapping);
1123 if(CODE_IGNORED(c) ||
1124 (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) {
1127 if(FT_Get_Char_Index(face, c) == 0) {
1131 if((encoding->size <= 256 && failed > 0) ||
1132 ((float)failed >= bigEncodingFuzz * estimate)) {
1137 if((float)failed >= total * bigEncodingFuzz)
1148 find_cmap(int type, int pid, int eid, FT_Face face)
1151 FT_CharMap cmap = NULL;
1153 n = face->num_charmaps;
1156 case FONT_ENCODING_TRUETYPE: /* specific cmap */
1157 for(i=0; i<n; i++) {
1158 cmap = face->charmaps[i];
1159 if(cmap->platform_id == pid && cmap->encoding_id == eid) {
1160 rc = FT_Set_Charmap(face, cmap);
1166 case FONT_ENCODING_UNICODE: /* any Unicode cmap */
1167 /* prefer Microsoft Unicode */
1168 for(i=0; i<n; i++) {
1169 cmap = face->charmaps[i];
1170 if(cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1171 cmap->encoding_id == TT_MS_ID_UNICODE_CS) {
1172 rc = FT_Set_Charmap(face, cmap);
1177 /* Try Apple Unicode */
1178 for(i=0; i<n; i++) {
1179 cmap = face->charmaps[i];
1180 if(cmap->platform_id == TT_PLATFORM_APPLE_UNICODE) {
1181 rc = FT_Set_Charmap(face, cmap);
1187 for(i=0; i<n; i++) {
1188 cmap = face->charmaps[i];
1189 if(cmap->platform_id == TT_PLATFORM_ISO) {
1190 rc = FT_Set_Charmap(face, cmap);
1203 checkExtraEncoding(FT_Face face, char *encoding_name, int found)
1207 if(strcasecmp(encoding_name, "iso10646-1") == 0) {
1208 if(doISO10646_1_encoding && find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) {
1210 /* Export as Unicode if there are at least 15 BMP
1211 characters that are not a space or ignored. */
1212 for(c = 0x21; c < 0x10000; c++) {
1215 if(FT_Get_Char_Index(face, c) > 0)
1223 } else if(strcasecmp(encoding_name, "microsoft-symbol") == 0) {
1224 if(find_cmap(FONT_ENCODING_TRUETYPE,
1225 TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS,
1230 } else if(strcasecmp(encoding_name, "adobe-fontspecific") == 0) {
1232 if(FT_Has_PS_Glyph_Names(face))
1239 fprintf(stderr, "Unknown extra encoding %s\n", encoding_name);
1245 notice_foundry(const char *notice)
1248 for(i = 0; i < countof(notice_foundries); i++)
1249 if(notice && strstr(notice, notice_foundries[i][0]))
1250 return notice_foundries[i][1];
1255 vendor_match(const signed char *vendor, const char *vendor_string)
1257 /* vendor is not necessarily NUL-terminated. */
1259 len = strlen(vendor_string);
1260 if(memcmp(vendor, vendor_string, len) != 0)
1262 for(i = len; i < 4; i++)
1263 if(vendor[i] != ' ' && vendor[i] != '\0')
1269 vendor_foundry(const signed char *vendor)
1272 for(i = 0; i < countof(vendor_foundries); i++)
1273 if(vendor_match(vendor, vendor_foundries[i][0]))
1274 return vendor_foundries[i][1];
1279 readEncodings(ListPtr encodings, char *dirname)
1283 struct dirent *file;
1284 char **names, **name;
1286 if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/')
1287 dirname[strlen(dirname) - 1] = '\0';
1289 dirp = opendir(dirname);
1295 while((file = readdir(dirp)) != NULL) {
1296 fullname = dsprintf("%s/%s", dirname, file->d_name);
1297 if(fullname == NULL) {
1298 fprintf(stderr, "Couldn't allocate fullname\n");
1303 names = FontEncIdentify(fullname);
1307 for(name = names; *name; name++) {
1308 if(fullname[0] != '/' && !relative) {
1310 n = dsprintf("%s%s", encodingPrefix, fullname);
1312 fprintf(stderr, "Couldn't allocate name\n");
1316 encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n);
1320 listConsF(encodingsToDo, "%s %s", *name, fullname);
1322 if(encodingsToDo == NULL) {
1323 fprintf(stderr, "Couldn't allocate encodings\n");
1328 free(names); /* only the spine */