summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2011-09-04 15:54:38 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:42:40 +0200
commit33f5954eb6849ac228491b729bcc11e922f62060 (patch)
tree835327dc82180533c3194c99fc51f1afa703be84
parent7b189b839d37bfb0d584c0c291280d427535bfda (diff)
downloadlibass-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.
-rw-r--r--libass/ass_fontconfig.c21
-rw-r--r--libass/ass_fontselect.c85
-rw-r--r--libass/ass_types.h3
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