diff options
author | Grigori Goronzy <greg@chown.ath.cx> | 2011-09-04 15:54:38 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@chown.ath.cx> | 2015-07-10 10:42:40 +0200 |
commit | 33f5954eb6849ac228491b729bcc11e922f62060 (patch) | |
tree | 835327dc82180533c3194c99fc51f1afa703be84 /libass | |
parent | 7b189b839d37bfb0d584c0c291280d427535bfda (diff) | |
download | libass-33f5954eb6849ac228491b729bcc11e922f62060.tar.bz2 libass-33f5954eb6849ac228491b729bcc11e922f62060.tar.xz |
Support multiple font family names
Some fonts use localized family names, especially CJK fonts, which
often have English and Japanese or Chinese names. Handle these cases
just like full names.
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_fontconfig.c | 21 | ||||
-rw-r--r-- | libass/ass_fontselect.c | 85 | ||||
-rw-r--r-- | libass/ass_types.h | 3 |
3 files changed, 67 insertions, 42 deletions
diff --git a/libass/ass_fontconfig.c b/libass/ass_fontconfig.c index 4fbf824..6080359 100644 --- a/libass/ass_fontconfig.c +++ b/libass/ass_fontconfig.c @@ -31,7 +31,7 @@ #include "ass_fontselect.h" #include "ass_utils.h" -#define MAX_FULLNAME 100 +#define MAX_NAME 100 static int check_glyph(void *priv, uint32_t code) { @@ -73,7 +73,8 @@ static void scan_fonts(FcConfig *config, ASS_FontProvider *provider) FcBool outline; int index, weight; char *path; - char *fullnames[MAX_FULLNAME]; + char *fullnames[MAX_NAME]; + char *families[MAX_NAME]; // skip non-outline fonts FcResult result = FcPatternGetBool(pat, FC_OUTLINE, 0, &outline); @@ -98,22 +99,24 @@ static void scan_fonts(FcConfig *config, ASS_FontProvider *provider) else meta.weight = FONT_WEIGHT_BOLD; - // family name - result = FcPatternGetString(pat, FC_FAMILY, 0, - (FcChar8 **)&meta.family); - if (result != FcResultMatch) - continue; - // path result = FcPatternGetString(pat, FC_FILE, 0, (FcChar8 **)&path); if (result != FcResultMatch) continue; // read and strdup fullnames + meta.n_family = 0; + while (FcPatternGetString(pat, FC_FAMILY, meta.n_family, + (FcChar8 **)&families[meta.n_family]) == FcResultMatch + && meta.n_family < MAX_NAME) + meta.n_family++; + meta.families = families; + + // read and strdup fullnames meta.n_fullname = 0; while (FcPatternGetString(pat, FC_FULLNAME, meta.n_fullname, (FcChar8 **)&fullnames[meta.n_fullname]) == FcResultMatch - && meta.n_fullname < MAX_FULLNAME) + && meta.n_fullname < MAX_NAME) meta.n_fullname++; meta.fullnames = fullnames; diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index 099b63d..ed4b35f 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -57,8 +57,9 @@ static const char *fallback_fonts[] = { struct font_info { int uid; // unique font face id - char *family; // family name + char **families; // family name char **fullnames; // list of localized fullnames (e.g. Arial Bold Italic) + int n_family; int n_fullname; int slant; @@ -259,9 +260,13 @@ ass_font_provider_add_font(ASS_FontProvider *provider, info->slant = slant; info->weight = weight; info->width = width; - info->family = strdup(meta->family); info->n_fullname = meta->n_fullname; + info->n_family = meta->n_family; info->fullnames = calloc(meta->n_fullname, sizeof(char *)); + info->families = calloc(meta->n_family, sizeof(char *)); + + for (i = 0; i < info->n_family; i++) + info->families[i] = strdup(meta->families[i]); for (i = 0; i < info->n_fullname; i++) info->fullnames[i] = strdup(meta->fullnames[i]); @@ -316,9 +321,11 @@ void ass_font_provider_free(ASS_FontProvider *provider) if (info->provider == provider) { for (j = 0; j < info->n_fullname; j++) free(info->fullnames[j]); + for (j = 0; j < info->n_family; j++) + free(info->families[j]); free(info->fullnames); - free(info->family); + free(info->families); if (info->path) free(info->path); @@ -368,20 +375,21 @@ static unsigned font_info_similarity(ASS_FontInfo *a, ASS_FontInfo *req) // if we don't have any match, compare fullnames against family // sometimes the family name is used similarly if (similarity > 0) { - for (i = 0; i < req->n_fullname; i++) { - if (strcasecmp(a->family, req->fullnames[i]) == 0) - similarity = 0; - } + for (i = 0; i < a->n_family; i++) + for (j = 0; j < req->n_fullname; j++) { + if (strcasecmp(a->families[i], req->fullnames[j]) == 0) + similarity = 0; + } } - // compare shortened family, if no fullname matches - if (similarity > 0 && strcasecmp(a->family, req->family) == 0) - similarity = 2000; - // nothing found? Try fallback fonts - while (similarity > 2000 && *fallback) - if (strcmp(a->family, *fallback++) == 0) - similarity = 5000; + while (similarity > 0 && *fallback) { + for (i = 0; i < a->n_family; i++) { + if (strcmp(a->families[i], *fallback) == 0) + similarity = 5000; + } + fallback++; + } // compare slant similarity += ABS(a->slant - req->slant); @@ -414,7 +422,9 @@ static void font_info_dump(ASS_FontInfo *font_infos, size_t len) // dump font infos for (i = 0; i < len; i++) { printf("font %d\n", i); - printf(" family: '%s'\n", font_infos[i].family); + printf(" families: "); + for (j = 0; j < font_infos[i].n_family; j++) + printf("'%s' ", font_infos[i].families[j]); printf(" fullnames: "); for (j = 0; j < font_infos[i].n_fullname; j++) printf("'%s' ", font_infos[i].fullnames[j]); @@ -461,9 +471,6 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, req.n_fullname = 1; req.fullnames = &req_fullname; req.fullnames[0] = trim_space(strdup(family)); - req.family = trim_space(strdup(family)); - char *p = strchr(req.family, ' '); - if (p) *p = 0; // calculate similarities font_info_req_similarity(font_infos, num_fonts, &req); @@ -485,7 +492,6 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, } free(req.fullnames[0]); - free(req.family); *index = font_infos[idx].index; *uid = font_infos[idx].uid; @@ -499,7 +505,7 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, ASS_FontProvider *provider = font_infos[idx].provider; stream->func = provider->funcs.get_data; stream->priv = font_infos[idx].priv; - return strdup(font_infos[idx].family); + return strdup(font_infos[idx].families[0]); } else return strdup(font_infos[idx].path); } @@ -577,10 +583,11 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) { int i; int num_fullname = 0; + int num_family = 0; int num_names = FT_Get_Sfnt_Name_Count(face); int slant, weight; char *fullnames[MAX_FULLNAME]; - char *family = NULL; + char *families[MAX_FULLNAME]; iconv_t utf16to8; // we're only interested in outlines @@ -589,41 +596,53 @@ get_font_info(FT_Library lib, FT_Face face, ASS_FontProviderMetaData *info) // scan font names utf16to8 = iconv_open("UTF-8", "UTF-16BE"); - for (i = 0; i < num_names && num_fullname < MAX_FULLNAME; i++) { + for (i = 0; i < num_names; i++) { FT_SfntName name; + FT_Get_Sfnt_Name(face, i, &name); + if (name.platform_id == 3 && (name.name_id == 4 || name.name_id == 1)) { char buf[1024]; char *bufptr = buf; size_t inbytes = name.string_len; size_t outbytes = 1024; + iconv(utf16to8, (char**)&name.string, &inbytes, &bufptr, &outbytes); *bufptr = '\0'; - // no primary family name yet - just use the first we encounter as a best guess - if (family == NULL && name.name_id == 1) { - family = strdup(buf); - continue; + + if (name.name_id == 4) { + fullnames[num_fullname] = strdup(buf); + num_fullname++; + } + + if (name.name_id == 1) { + families[num_family] = strdup(buf); + num_family++; } - fullnames[num_fullname] = strdup(buf); - num_fullname++; } + } iconv_close(utf16to8); // check if we got a valid family - if not use whatever FreeType gives us - if (family == NULL) - family = strdup(face->family_name); + if (num_family == 0) { + families[0] = strdup(face->family_name); + num_family++; + } // calculate sensible slant and weight from style attributes slant = 110 * !!(face->style_flags & FT_STYLE_FLAG_ITALIC); weight = 300 * !!(face->style_flags & FT_STYLE_FLAG_BOLD) + 400; // fill our struct - info->family = family; info->slant = slant; info->weight = weight; + info->width = 100; // FIXME, should probably query the OS/2 table + info->families = calloc(sizeof(char *), num_family); info->fullnames = calloc(sizeof(char *), num_fullname); + memcpy(info->families, &families, sizeof(char *) * num_family); memcpy(info->fullnames, &fullnames, sizeof(char *) * num_fullname); + info->n_family = num_family; info->n_fullname = num_fullname; return 1; @@ -638,11 +657,13 @@ static void free_font_info(ASS_FontProviderMetaData *meta) { int i; - free(meta->family); + for (i = 0; i < meta->n_family; i++) + free(meta->families[i]); for (i = 0; i < meta->n_fullname; i++) free(meta->fullnames[i]); + free(meta->families); free(meta->fullnames); } diff --git a/libass/ass_types.h b/libass/ass_types.h index 8411348..7d1e498 100644 --- a/libass/ass_types.h +++ b/libass/ass_types.h @@ -66,8 +66,9 @@ typedef struct font_provider_funcs { * At minimum `family' is required. */ typedef struct font_provider_meta_data { - char *family; // English font family, e.g. "Arial" + char **families; // list of family names, e.g. "Arial" char **fullnames; // list of localized full names, e.g. "Arial Bold" + int n_family; // list of family names int n_fullname; // number of localized full names int slant; // uses the above scale (NONE/ITALIC/OBLIQUE) int weight; // TrueType scale, 100-900 |