summaryrefslogtreecommitdiffstats
path: root/libass
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 /libass
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.
Diffstat (limited to 'libass')
-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