diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-26 22:49:10 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-26 22:49:10 +0000 |
commit | f420965b8e48aff65f0c181cb36cbd9410e88b1b (patch) | |
tree | 2765cce0a55cdbdd1a94e016469bdf8d086728c6 /mkfontscale.c | |
parent | 632e8a138dd16efe41384a4335ec46530da4a04b (diff) |
merge latest (4.3.99.16) from XFree86 (vendor) branch
Diffstat (limited to 'mkfontscale.c')
-rw-r--r-- | mkfontscale.c | 877 |
1 files changed, 665 insertions, 212 deletions
diff --git a/mkfontscale.c b/mkfontscale.c index 95db6e4..3036752 100644 --- a/mkfontscale.c +++ b/mkfontscale.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2002 by Juliusz Chroboczek + Copyright (c) 2002-2003 by Juliusz Chroboczek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,7 +19,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $XFree86: xc/programs/mkfontscale/mkfontscale.c,v 1.4 2003/02/13 03:04:07 dawes Exp $ */ +/* $XFree86: xc/programs/mkfontscale/mkfontscale.c,v 1.17 2003/11/21 05:22:08 dawes Exp $ */ #include <stdio.h> #include <stdlib.h> @@ -27,54 +27,84 @@ #include <sys/types.h> #include <dirent.h> +#include <unistd.h> +#include <errno.h> #include <X11/fonts/fontenc.h> -#include <freetype/freetype.h> -#include <freetype/ftsnames.h> -#include <freetype/tttables.h> -#include <freetype/ttnameid.h> -#include <freetype/t1tables.h> +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_SFNT_NAMES_H +#include FT_TRUETYPE_TABLES_H +#include FT_TRUETYPE_IDS_H +#include FT_TYPE1_TABLES_H +#include FT_BDF_H +#include FT_TRUETYPE_TABLES_H -#define CODE_IGNORED(c) ((c) < 0x20 || \ - ((c) >= 0x7F && (c) <= 0xA0) || \ - (c) == 0xAD) - #include "list.h" +#include "hash.h" #include "data.h" +#include "ident.h" + +#define NPREFIX 1024 + +#ifndef MAXFONTFILENAMELEN +#define MAXFONTFILENAMELEN 1024 +#endif +#ifndef MAXFONTNAMELEN +#define MAXFONTNAMELEN 1024 +#endif char *encodings_array[] = { "iso8859-1", "iso8859-2", "iso8859-3", "iso8859-4", "iso8859-5", "iso8859-6", "iso8859-7", "iso8859-8", "iso8859-9", "iso8859-10", "iso8859-11", "iso8859-12", "iso8859-13", "iso8859-14", "iso8859-15", - "koi8-r", "koi8-u", "koi8-e", - "adobe-standard", "adobe-symbol", "ibm-cp437", "microsoft-cp1252", + "koi8-r", "koi8-u", "koi8-ru", "koi8-e", "koi8-uni", + "tis620-2", + "adobe-standard", "adobe-symbol", + "ibm-cp437", "microsoft-cp1252", /* But not "adobe-dingbats", as it uses generic glyph names. */ "jisx0201.1976-0", "jisx0208.1983-0", "jisx0208.1990-0", - "jisx0212.1190-0", "big5-0", "gb2312.1980-0", + "jisx0212.1990-0", "big5-0", "gb2312.1980-0", "ksc5601.1987-0", "ksc5601.1992-3"}; char *extra_encodings_array[] = { "iso10646-1", "adobe-fontspecific", "microsoft-symbol" }; ListPtr encodings, extra_encodings; +char *outfilename; #define countof(_a) (sizeof(_a)/sizeof((_a)[0])) -int doDirectory(char*); +static int doDirectory(char*, int, ListPtr); static int checkEncoding(FT_Face face, char *encoding_name); static int checkExtraEncoding(FT_Face face, char *encoding_name, int found); static int find_cmap(int type, int pid, int eid, FT_Face face); static char* notice_foundry(char *notice); static char* vendor_foundry(signed char *vendor); +static int readFontScale(HashTablePtr entries, char *dirname); +ListPtr makeXLFD(char *filename, FT_Face face, int); +static int readEncodings(ListPtr encodings, char *dirname); static FT_Library ft_library; static float bigEncodingFuzz = 0.02; +static int relative; +static int doScalable; +static int doBitmaps; +static int onlyEncodings; +static ListPtr encodingsToDo; +static int reencodeLegacy; +static char *encodingPrefix; +static char *exclusionSuffix; + static void usage(void) { fprintf(stderr, - "mkfontscale [ -e encoding ] [ -f fuzz ] [ directory ]\n"); + "mkfontscale [ -b ] [ -s ] [ -o filename ] [-x suffix ]\n" + " [ -a encoding ] [ -f fuzz ] [ -l ] " + " [ -e directory ] [ -p prefix ] [ -n ] [ -r ] \n" + " [ directory ]...\n"); } int @@ -82,12 +112,33 @@ main(int argc, char **argv) { int argn; FT_Error ftrc; + int rc, ll = 0; + char prefix[NPREFIX]; + + encodingPrefix = NULL; + exclusionSuffix = NULL; + + if(getcwd(prefix, NPREFIX - 1) == NULL) { + perror("Couldn't get cwd"); + exit(1); + } + if(prefix[strlen(prefix) - 1] != '/') + strcat(prefix, "/"); + encodingPrefix = dsprintf("%s", prefix); + + outfilename = NULL; encodings = makeList(encodings_array, countof(encodings_array), NULL, 0); extra_encodings = makeList(extra_encodings_array, countof(extra_encodings_array), NULL, 0); + doBitmaps = 0; + doScalable = 1; + onlyEncodings = 0; + relative = 0; + reencodeLegacy = 1; + encodingsToDo = NULL; argn = 1; while(argn < argc) { @@ -96,38 +147,100 @@ main(int argc, char **argv) if(argv[argn][1] == '-') { argn++; break; - } else if(argv[argn][1] == 'e') { + } else if (strcmp(argv[argn], "-x") == 0) { + if(argn >= argc - 1) { + usage(); + exit(1); + } + exclusionSuffix = argv[argn + 1]; + argn += 2; + } else if(strcmp(argv[argn], "-a") == 0) { if(argn >= argc - 1) { usage(); exit(1); } makeList(&argv[argn + 1], 1, encodings, 0); argn += 2; - } else if(argv[argn][1] == 'f') { + } else if(strcmp(argv[argn], "-p") == 0) { + if(argn >= argc - 1) { + usage(); + exit(1); + } + if(strlen(argv[argn + 1]) > NPREFIX - 1) { + usage(); + exit(1); + } + free(encodingPrefix); + encodingPrefix = dsprintf("%s", argv[argn + 1]); + argn += 2; + } else if(strcmp(argv[argn], "-e") == 0) { + if(argn >= argc - 1) { + usage(); + exit(1); + } + rc = readEncodings(encodingsToDo, argv[argn + 1]); + if(rc < 0) + exit(1); + argn += 2; + } else if(strcmp(argv[argn], "-b") == 0) { + doBitmaps = 1; + argn++; + } else if(strcmp(argv[argn], "-s") == 0) { + doScalable = 0; + argn++; + } else if(strcmp(argv[argn], "-n") == 0) { + onlyEncodings = 1; + argn++; + } else if(strcmp(argv[argn], "-r") == 0) { + relative = 1; + argn++; + } else if(strcmp(argv[argn], "-l") == 0) { + reencodeLegacy = !reencodeLegacy; + argn++; + } else if(strcmp(argv[argn], "-o") == 0) { + if(argn >= argc - 1) { + usage(); + exit(1); + } + outfilename = argv[argn + 1]; + argn += 2; + } else if(strcmp(argv[argn], "-f") == 0) { if(argn >= argc - 1) { usage(); exit(1); } bigEncodingFuzz = atof(argv[argn + 1]) / 100.0; argn += 2; - } else { + } else if (strcmp(argv[argn], "-r") == 0) { /* ignore for now */ + argn++; + } else if (strcmp(argv[argn], "-n") == 0) { + argn++; + } else { usage(); exit(1); } } + if(outfilename == NULL) { + if(doBitmaps) + outfilename = "fonts.dir"; + else + outfilename = "fonts.scale"; + } + ftrc = FT_Init_FreeType(&ft_library); if(ftrc) { fprintf(stderr, "Could not initialise FreeType library: %d\n", ftrc); exit(1); } - + + ll = listLength(encodingsToDo); if (argn == argc) - doDirectory("."); + doDirectory(".", ll, encodingsToDo); else while(argn < argc) { - doDirectory(argv[argn]); + doDirectory(argv[argn], ll, encodingsToDo); argn++; } return 0; @@ -261,11 +374,40 @@ os2Width(int width) return "ultraexpanded"; } +static char *widths[] = { + "ultracondensed", "extracondensed", "condensed", "semicondensed", + "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded" +}; + +#define NUMWIDTHS (sizeof(widths) / sizeof(widths[0])) + +static char* +nameWidth(char *name) +{ + char buf[500]; + int i; + int n = strlen(name); + + if(n >= 499) return NULL; + for(i = 0; i < n; i++) + buf[i] = tolower(name[i]); + buf[i] = '\0'; + + for(i = 0; i < NUMWIDTHS; i++) + if(strstr(buf, widths[i])) + return widths[i]; + return NULL; +} + static char* t1Weight(char *weight) { if(!weight) return NULL; + if(strcmp(weight, "Thin") == 0) + return "thin"; + if(strcmp(weight, "Light") == 0) + return "light"; if(strcmp(weight, "Regular") == 0) return "medium"; if(strcmp(weight, "Normal") == 0) @@ -282,23 +424,14 @@ t1Weight(char *weight) return "semibold"; else if(strcmp(weight, "Bold") == 0) return "bold"; + else if(strcmp(weight, "Black") == 0) + return "black"; else { fprintf(stderr, "Unknown Type 1 weight \"%s\"\n", weight); return NULL; } } -static char* -strcat_reliable(char *a, char *b) -{ - char *c = malloc(strlen(a) + strlen(b) + 1); - if(c == NULL) - return NULL; - strcpy(c, a); - strcat(c, b); - return c; -} - static int unsafe(char c) { @@ -339,33 +472,301 @@ safe(char* s) return t; } -int -doDirectory(char *dirname_given) +ListPtr +makeXLFD(char *filename, FT_Face face, int isBitmap) { - char *dirname, *fontscale_name, *filename; - FILE *fontscale; - DIR *dirp; - struct dirent *entry; - FT_Error ftrc; - FT_Face face; + ListPtr xlfd = NULL; + char *foundry, *family, *weight, *slant, *sWidth, *adstyle, + *spacing, *full_name; TT_Header *head; TT_HoriHeader *hhea; TT_OS2 *os2; TT_Postscript *post; PS_FontInfoRec *t1info, t1info_rec; - char *foundry, *family, *weight, *slant, *sWidth, *adstyle, - *spacing, *full_name; - ListPtr encoding, entries = NULL; - int i, found, rc; + int rc; + + foundry = NULL; + family = NULL; + weight = NULL; + slant = NULL; + sWidth = NULL; + adstyle = NULL; + spacing = NULL; + full_name = NULL; + + head = FT_Get_Sfnt_Table(face, ft_sfnt_head); + hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea); + os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); + post = FT_Get_Sfnt_Table(face, ft_sfnt_post); + + rc = FT_Get_PS_Font_Info(face, &t1info_rec); + if(rc == 0) + t1info = &t1info_rec; + else + t1info = NULL; + + if(!family) + family = getName(face, TT_NAME_ID_FONT_FAMILY); + if(!family) + family = getName(face, TT_NAME_ID_FULL_NAME); + if(!family) + family = getName(face, TT_NAME_ID_PS_NAME); + + if(!full_name) + full_name = getName(face, TT_NAME_ID_FULL_NAME); + if(!full_name) + full_name = getName(face, TT_NAME_ID_PS_NAME); + + if(os2 && os2->version != 0xFFFF) { + if(!weight) + weight = os2Weight(os2->usWeightClass); + if(!sWidth) + sWidth = os2Width(os2->usWidthClass); + if(!foundry) + foundry = vendor_foundry(os2->achVendID); + if(!slant) + slant = os2->fsSelection & 1 ? "i" : "r"; + } + + if(post) { + if(!spacing) { + if(post->isFixedPitch) { + if(hhea->min_Left_Side_Bearing >= 0 && + hhea->xMax_Extent <= hhea->advance_Width_Max) { + spacing = "c"; + } else { + spacing = "m"; + } + } else { + spacing = "p"; + } + } + } + + if(t1info) { + if(!family) + family = t1info->family_name; + if(!family) + family = t1info->full_name; + if(!full_name) + full_name = t1info->full_name; + if(!foundry) + foundry = notice_foundry(t1info->notice); + if(!weight) + weight = t1Weight(t1info->weight); + if(!spacing) + spacing = t1info->is_fixed_pitch ? "m" : "p"; + if(!slant) { + /* Bitstream fonts have positive italic angle. */ + slant = + t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ? + "i" : "r"; + } + } + + if(!full_name) { + fprintf(stderr, "Couldn't determine full name for %s\n", filename); + full_name = filename; + } + + if(head) { + if(!slant) + slant = head->Mac_Style & 2 ? "i" : "r"; + if(!weight) + weight = head->Mac_Style & 1 ? "bold" : "medium"; + } + + if(!slant) { + fprintf(stderr, "Couldn't determine slant for %s\n", filename); + slant = "r"; + } + + if(!weight) { + fprintf(stderr, "Couldn't determine weight for %s\n", filename); + weight = "medium"; + } + + if(!foundry) { + char *notice; + notice = getName(face, TT_NAME_ID_TRADEMARK); + if(notice) { + foundry = notice_foundry(notice); + } + if(!foundry) { + notice = getName(face, TT_NAME_ID_MANUFACTURER); + if(notice) { + foundry = notice_foundry(notice); + } + } + } + + if(strcmp(slant, "i") == 0) { + if(strstr(full_name, "Oblique")) + slant = "o"; + if(strstr(full_name, "Slanted")) + slant = "o"; + } + + if(!sWidth) + sWidth = nameWidth(full_name); + + if(!foundry) foundry = "misc"; + if(!family) { + fprintf(stderr, "Couldn't get family name for %s\n", filename); + family = filename; + } + + if(!weight) weight = "medium"; + if(!slant) slant = "r"; + if(!sWidth) sWidth = "normal"; + if(!adstyle) adstyle = ""; + if(!spacing) spacing = "p"; + + /* Yes, it's a memory leak. */ + foundry = safe(foundry); + family = safe(family); + + if(!isBitmap) { + xlfd = listConsF(xlfd, + "-%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0", + foundry, family, + weight, slant, sWidth, adstyle, spacing); + } else { + int i, w, h, xres, yres; + for(i = 0; i < face->num_fixed_sizes; i++) { + w = face->available_sizes[i].width; + h = face->available_sizes[i].height; + xres = 75; + yres = (double)h / w * xres; + xlfd = listConsF(xlfd, + "-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d", + foundry, family, + weight, slant, sWidth, adstyle, + h, (int)(h / (double)yres * 72.27 * 10 + 0.5), + xres, yres, + spacing, 60); + } + } + return xlfd; +} + +static int +readFontScale(HashTablePtr entries, char *dirname) +{ + int n = strlen(dirname); + char *filename; + FILE *in; + int rc, count, i; + char file[MAXFONTFILENAMELEN], font[MAXFONTNAMELEN]; + char format[100]; + + snprintf(format, 100, "%%%ds %%%d[^\n]\n", + MAXFONTFILENAMELEN, MAXFONTNAMELEN); + + if(dirname[n - 1] == '/') + filename = dsprintf("%sfonts.scale", dirname); + else + filename = dsprintf("%s/fonts.scale", dirname); + if(filename == NULL) + return -1; + + in = fopen(filename, "r"); + free(filename); + if(in == NULL) { + if(errno != ENOENT) + perror("open(fonts.scale)"); + return -1; + } + + rc = fscanf(in, "%d\n", &count); + if(rc != 1) { + fprintf(stderr, "Invalid fonts.scale in %s.\n", dirname); + fclose(in); + return -1; + } + + for(i = 0; i < count; i++) { + rc = fscanf(in, format, file, font); + if(rc != 2) + break; + putHash(entries, font, file, 100); + } + fclose(in); + return 1; +} + +static int +filePrio(char *filename) +{ + int n = strlen(filename); + if(n < 4) + return 0; + if(strcmp(filename + n - 4, ".otf") == 0) + return 4; + if(strcmp(filename + n - 4, ".OTF") == 0) + return 4; + if(strcmp(filename + n - 4, ".ttf") == 0) + return 3; + if(strcmp(filename + n - 4, ".TTF") == 0) + return 3; + if(strcmp(filename + n - 3, ".gz") == 0) + return 2; + if(strcmp(filename + n - 2, ".Z") == 0) + return 1; + return 0; +} + +static int +doDirectory(char *dirname_given, int numEncodings, ListPtr encodingsToDo) +{ + char *dirname, *fontscale_name, *filename, *encdir; + FILE *fontscale, *encfile; + DIR *dirp; + struct dirent *entry; + FT_Error ftrc; + FT_Face face; + ListPtr encoding, xlfd, lp; + HashTablePtr entries; + HashBucketPtr *array; + int i, n, found, rc; + int isBitmap=0,xl=0; + + if (exclusionSuffix) + xl = strlen (exclusionSuffix); i = strlen(dirname_given); if(i == 0) - dirname = strcat_reliable(".", "/"); + dirname = dsprintf("./"); else if(dirname_given[i - 1] != '/') - dirname = strcat_reliable(dirname_given, "/"); + dirname = dsprintf("%s/", dirname_given); else - dirname = strcat_reliable(dirname_given, ""); - fontscale_name = strcat_reliable(dirname, "fonts.scale"); + dirname = dsprintf("%s", dirname_given); + + if(dirname == NULL) { + perror("dirname"); + exit(1); + } + + if (onlyEncodings) + goto encodings; + + entries = makeHashTable(); + if(doBitmaps && !doScalable) { + readFontScale(entries, dirname); + } + + if(strcmp(outfilename, "-") == 0) + fontscale_name = NULL; + else { + if(outfilename[0] == '/') + fontscale_name = dsprintf("%s", outfilename); + else + fontscale_name = dsprintf("%s%s", dirname, outfilename); + if(fontscale_name == NULL) { + perror("fontscale_name"); + exit(1); + } + } dirp = opendir(dirname); if(dirp == NULL) { @@ -374,195 +775,189 @@ doDirectory(char *dirname_given) return 0; } - fontscale = fopen(fontscale_name, "w"); + if(fontscale_name == NULL) + fontscale = stdout; + else + fontscale = fopen(fontscale_name, "w"); + if(fontscale == NULL) { fprintf(stderr, "%s: ", fontscale_name); perror("fopen(w)"); return 0; } - - for(;;) { - entry = readdir(dirp); - if(entry == NULL) - break; - filename = strcat_reliable(dirname, entry->d_name); - ftrc = FT_New_Face(ft_library, filename, 0, &face); - if(ftrc) - continue; - if((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) - continue; + while((entry = readdir(dirp)) != NULL) { + int have_face = 0; + char *xlfd_name = NULL; + xlfd = NULL; - found = 0; + if (xl) { + int dl = strlen (entry->d_name); + if (strcmp (entry->d_name + dl - xl, exclusionSuffix) == 0) + continue; + } - foundry = NULL; - family = NULL; - weight = NULL; - slant = NULL; - sWidth = NULL; - adstyle = NULL; - spacing = NULL; - full_name = NULL; - - head = FT_Get_Sfnt_Table(face, ft_sfnt_head); - hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea); - os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); - post = FT_Get_Sfnt_Table(face, ft_sfnt_post); - - rc = FT_Get_PS_Font_Info(face, &t1info_rec); - if(rc == 0) - t1info = &t1info_rec; + filename = dsprintf("%s%s", dirname, entry->d_name); + + if(doBitmaps) + rc = bitmapIdentify(filename, &xlfd_name); else - t1info = NULL; + rc = 0; + + if(rc < 0) + goto done; + + if(rc == 0) { + ftrc = FT_New_Face(ft_library, filename, 0, &face); + if(ftrc) + goto done; + have_face = 1; + + isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0); + + if(!isBitmap) { + /* Workaround for bitmap-only TTF fonts */ + if(face->num_fixed_sizes > 0) { + TT_MaxProfile *maxp; + maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp); + if(maxp != NULL && maxp->maxContours == 0) + isBitmap = 1; + } + } - if(!family) - family = getName(face, TT_NAME_ID_FONT_FAMILY); - if(!family) - family = getName(face, TT_NAME_ID_FULL_NAME); - if(!family) - family = getName(face, TT_NAME_ID_PS_NAME); - - if(!full_name) - full_name = getName(face, TT_NAME_ID_FULL_NAME); - if(!full_name) - full_name = getName(face, TT_NAME_ID_PS_NAME); - - if(os2 && os2->version != 0xFFFF) { - if(!weight) - weight = os2Weight(os2->usWeightClass); - if(!sWidth) - sWidth = os2Width(os2->usWidthClass); - if(!foundry) - foundry = vendor_foundry(os2->achVendID); - if(!slant) - slant = os2->fsSelection & 1 ? "i" : "r"; - } + if(isBitmap) { + if(!doBitmaps) + goto done; + } else { + if(!doScalable) + goto done; + } - if(post) { - if(!spacing) { - if(post->isFixedPitch) { - if(hhea->min_Left_Side_Bearing >= 0 && - hhea->xMax_Extent <= hhea->advance_Width_Max) { - spacing = "c"; - } else { - spacing = "m"; - } - } else { - spacing = "p"; + if(isBitmap) { + BDF_PropertyRec prop; + rc = FT_Get_BDF_Property(face, "FONT", &prop); + if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM) { + xlfd_name = malloc(strlen(prop.u.atom) + 1); + if(xlfd_name == NULL) + goto done; + strcpy(xlfd_name, prop.u.atom); } } } - - if(t1info) { - if(!family) - family = t1info->family_name; - if(!family) - family = t1info->full_name; - if(!full_name) - full_name = t1info->full_name; - if(!foundry) - foundry = notice_foundry(t1info->notice); - if(!weight) - weight = t1Weight(t1info->weight); - if(!spacing) - spacing = t1info->is_fixed_pitch ? "m" : "p"; - if(!slant) { - /* Bitstream fonts have positive italic angle. */ - slant = - t1info->italic_angle <= -4 || t1info->italic_angle >= 4 ? - "i" : "r"; + + if(xlfd_name) { + /* We know it's a bitmap font, and we know its XLFD */ + int n = strlen(xlfd_name); + if(reencodeLegacy && + n >= 12 && strcasecmp(xlfd_name + n - 11, "-iso10646-1") == 0) { + char *s; + + s = malloc(n - 10); + memcpy(s, xlfd_name, n - 11); + s[n - 11] = '\0'; + xlfd = listCons(s, xlfd); + } else { + /* Not a reencodable font -- skip all the rest of the loop body */ + putHash(entries, xlfd_name, entry->d_name, filePrio(entry->d_name)); + goto done; } } - if(head) { - if(!slant) - slant = head->Mac_Style & 2 ? "i" : "r"; - if(!weight) - weight = head->Mac_Style & 1 ? "bold" : "medium"; + if(!have_face) { + ftrc = FT_New_Face(ft_library, filename, 0, &face); + if(ftrc) + goto done; + have_face = 1; + isBitmap = ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0); + + if(!isBitmap) { + if(face->num_fixed_sizes > 0) { + TT_MaxProfile *maxp; + maxp = FT_Get_Sfnt_Table(face, ft_sfnt_maxp); + if(maxp != NULL && maxp->maxContours == 0) + isBitmap = 1; + } + } } - if(!slant) { - fprintf(stderr, "Couldn't determine slant for %s\n", filename); - slant = "r"; - } + if(xlfd == NULL) + xlfd = makeXLFD(entry->d_name, face, isBitmap); - if(!weight) { - fprintf(stderr, "Couldn't determine weight for %s\n", filename); - weight = "medium"; - } + found = 0; - if(!foundry) { - char *notice; - notice = getName(face, TT_NAME_ID_TRADEMARK); - if(notice) { - foundry = notice_foundry(notice); + for(lp = xlfd; lp; lp = lp->next) { + char buf[MAXFONTNAMELEN]; + for(encoding = encodings; encoding; encoding = encoding->next) { + if(checkEncoding(face, encoding->value)) { + found = 1; + snprintf(buf, MAXFONTNAMELEN, "%s-%s", + lp->value, encoding->value); + putHash(entries, buf, entry->d_name, filePrio(entry->d_name)); + } } - if(!foundry) { - notice = getName(face, TT_NAME_ID_MANUFACTURER); - if(notice) { - foundry = notice_foundry(notice); + for(encoding = extra_encodings; encoding; + encoding = encoding->next) { + if(checkExtraEncoding(face, encoding->value, found)) { + /* Do not set found! */ + snprintf(buf, MAXFONTNAMELEN, "%s-%s", + lp->value, encoding->value); + putHash(entries, buf, entry->d_name, filePrio(entry->d_name)); } } } - - if(strcmp(slant, "i") == 0) { - if(strstr(full_name, "Oblique")) - slant = "o"; - if(strstr(full_name, "Slanted")) - slant = "o"; + done: + if(have_face) { + FT_Done_Face(face); + have_face = 0; } + deepDestroyList(xlfd); + xlfd = NULL; + free(filename); + } - if(!foundry) foundry = "misc"; - if(!family) { - fprintf(stderr, "Couldn't get family name for %s\n", filename); - family = entry->d_name; - } + closedir(dirp); + n = hashElements(entries); + fprintf(fontscale, "%d\n", n); + array = hashArray(entries, 1); + for(i = 0; i < n; i++) + fprintf(fontscale, "%s %s\n", array[i]->value, array[i]->key); + destroyHashArray(array); + entries = NULL; + if(fontscale_name) { + fclose(fontscale); + free(fontscale_name); + } - if(!weight) weight = "medium"; - if(!slant) slant = "r"; - if(!sWidth) sWidth = "normal"; - if(!adstyle) adstyle = ""; - if(!spacing) spacing = "p"; - - /* Yes, it's a memory leak. */ - foundry = safe(foundry); - family = safe(family); - - for(encoding = encodings; encoding; encoding = encoding->next) - if(checkEncoding(face, encoding->value)) { - found = 1; - entries = listConsF(entries, - "%s -%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0-%s", - entry->d_name, - foundry, family, - weight, slant, sWidth, adstyle, spacing, - encoding->value); - } - for(encoding = extra_encodings; encoding; encoding = encoding->next) - if(checkExtraEncoding(face, encoding->value, found)) { - /* Do not set found! */ - entries = listConsF(entries, - "%s -%s-%s-%s-%s-%s-%s-0-0-0-0-%s-0-%s", - entry->d_name, - foundry, family, - weight, slant, sWidth, adstyle, spacing, - encoding->value); - } - free(filename); + encodings: + encdir = dsprintf("%s%s", dirname, "encodings.dir"); + + if(encdir == NULL) { + perror("encodings"); + exit(1); } - entries = reverseList(entries); - fprintf(fontscale, "%d\n", listLength(entries)); - while(entries) { - fprintf(fontscale, "%s\n", entries->value); - entries = entries->next; + unlink(encdir); + + if (numEncodings) { + encfile = fopen(encdir, "w"); + if(encfile == NULL) { + perror("open(encodings.dir)"); + exit(1); + } + fprintf(encfile, "%d\n", numEncodings); + for(lp = encodingsToDo; lp; lp = lp->next) { + fprintf(encfile, "%s\n", lp->value); + } + fclose (encfile); } - deepDestroyList(entries); - fclose(fontscale); - free(fontscale_name); + free(dirname); return 1; } +#define CODE_IGNORED(c) ((c) < 0x20 || \ + ((c) >= 0x7F && (c) <= 0xA0) || \ + (c) == 0xAD || (c) == 0xF71B) + static int checkEncoding(FT_Face face, char *encoding_name) { @@ -576,14 +971,16 @@ checkEncoding(FT_Face face, char *encoding_name) return 0; /* An encoding is ``small'' if one of the following is true: - - it uses PostScript glyph names; - it is linear and has no more than 256 codepoints; or - it is a matrix encoding and has no more than one column. - For small encodings, we require perfect coverage except for - CODE_IGNORED and KOI-8 linedrawing glyphs. + For small encodings using Unicode indices, we require perfect + coverage except for CODE_IGNORED and KOI-8 IBM-PC compatibility. - For large encodings, we require coverage up to bigEncodingFuzz. */ + For large encodings, we require coverage up to bigEncodingFuzz. + + For encodings using PS names (currently Adobe Standard and + Adobe Symbol only), we require perfect coverage. */ if(FT_Has_PS_Glyph_Names(face)) { @@ -646,8 +1043,8 @@ checkEncoding(FT_Face face, char *encoding_name) return 1; } else { int estimate = encoding->size - encoding->first; - /* For the KOI8 encodings, ignore the lack of - linedrawing characters */ + /* For the KOI8 encodings, we ignore the lack of + linedrawing and pseudo-math characters */ if(strncmp(encoding->name, "koi8-", 5) == 0) koi8 = 1; else @@ -655,7 +1052,7 @@ checkEncoding(FT_Face face, char *encoding_name) for(i = encoding->first; i < encoding->size; i++) { c = FontEncRecode(i, mapping); if(CODE_IGNORED(c) || - (koi8 && i >= 0x80 && i < 0xA0)) { + (koi8 && ((c >= 0x2200 && c < 0x2600) || c == 0x00b2))) { continue; } else { if(FT_Get_Char_Index(face, c) == 0) { @@ -742,7 +1139,7 @@ checkExtraEncoding(FT_Face face, char *encoding_name, int found) if(strcasecmp(encoding_name, "iso10646-1") == 0) { if(find_cmap(FONT_ENCODING_UNICODE, -1, -1, face)) { int found = 0; - /* Export as Unicode if there are at least 15 BMP + /* Export as Unicode if there are at least 15 BMP characters that are not a space or ignored. */ for(c = 0x21; c < 0x10000; c++) { if(CODE_IGNORED(c)) @@ -809,3 +1206,59 @@ vendor_foundry(signed char *vendor) return vendor_foundries[i][1]; return NULL; } + +static int +readEncodings(ListPtr encodings, char *dirname) +{ + char *fullname; + DIR *dirp; + struct dirent *file; + char **names, **name; + + if(strlen(dirname) > 1 && dirname[strlen(dirname) - 1] == '/') + dirname[strlen(dirname) - 1] = '\0'; + + dirp = opendir(dirname); + if(dirp == NULL) { + perror("opendir"); + return -1; + } + + while((file = readdir(dirp)) != NULL) { + fullname = dsprintf("%s/%s", dirname, file->d_name); + if(fullname == NULL) { + fprintf(stderr, "Couldn't allocate fullname\n"); + closedir(dirp); + return -1; + } + + names = FontEncIdentify(fullname); + if(!names) + continue; + + for(name = names; *name; name++) { + if(fullname[0] != '/' && !relative) { + char *n; + n = dsprintf("%s%s", encodingPrefix, fullname); + if(n == NULL) { + fprintf(stderr, "Couldn't allocate name\n"); + closedir(dirp); + return -1; + } + encodingsToDo = listConsF(encodingsToDo, "%s %s", *name, n); + free(n); + } else { + encodingsToDo = + listConsF(encodingsToDo, "%s %s", *name, fullname); + } + if(encodingsToDo == NULL) { + fprintf(stderr, "Couldn't allocate encodings\n"); + closedir(dirp); + return -1; + } + } + free(names); /* only the spine */ + } + closedir(dirp); + return 0; +} |