From 38f4a39bdbe6090d39e86b620c772ba5cd88c8a5 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Wed, 17 Aug 2011 18:59:00 +0200 Subject: Never add a face twice to an ASS_Font Introduce a unique ID per font face and check it in add_face to make sure we never add a font face twice. This is useful in case the glyph coverage report is unreliable. --- libass/ass_font.c | 23 ++++++++++++++++------- libass/ass_font.h | 17 +++++++++-------- libass/ass_fontselect.c | 27 ++++++++++++++++++++------- libass/ass_fontselect.h | 12 +++++++----- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/libass/ass_font.c b/libass/ass_font.c index 13ec654..16207d3 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -130,20 +130,27 @@ static void buggy_font_workaround(FT_Face face) static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) { char *path; - int index; + int i, index, uid; + int error, mem_idx; FT_Face face; - int error; - int mem_idx; if (font->n_faces == ASS_FONT_MAX_FACES) return -1; - path = ass_font_select(fontsel, font->library, font->desc.family, - font->desc.bold, font->desc.italic, &index, ch); + path = ass_font_select(fontsel, font->library, font , &index, &uid, ch); if (!path) return -1; + for (i = 0; i < font->n_faces; i++) { + if (font->faces_uid[i] == uid) { + ass_msg(font->library, MSGL_INFO, + "Got a font face that already is available! Skipping."); + free(path); + return -1; + } + } + mem_idx = find_font(font->library, path); if (mem_idx >= 0) { error = @@ -170,7 +177,8 @@ static int add_face(ASS_FontSelector *fontsel, ASS_Font *font, uint32_t ch) charmap_magic(font->library, face); buggy_font_workaround(face); - font->faces[font->n_faces++] = face; + font->faces[font->n_faces] = face; + font->faces_uid[font->n_faces++] = uid; ass_face_set_size(face, font->size); free(path); return font->n_faces - 1; @@ -667,9 +675,10 @@ void ass_font_free(ASS_Font *font) int i; if (font->shaper_priv) ass_shaper_font_data_free(font->shaper_priv); - for (i = 0; i < font->n_faces; ++i) + for (i = 0; i < font->n_faces; ++i) { if (font->faces[i]) FT_Done_Face(font->faces[i]); + } free(font->desc.family); free(font); } diff --git a/libass/ass_font.h b/libass/ass_font.h index 9ccc83a..f29e301 100644 --- a/libass/ass_font.h +++ b/libass/ass_font.h @@ -24,9 +24,13 @@ #include FT_GLYPH_H #include FT_OUTLINE_H +typedef struct ass_font ASS_Font; +typedef struct ass_font_desc ASS_FontDesc; + #include "ass.h" #include "ass_types.h" #include "ass_fontselect.h" +#include "ass_cache.h" #define VERTICAL_LOWER_BOUND 0x02f1 @@ -34,28 +38,25 @@ #define DECO_UNDERLINE 1 #define DECO_STRIKETHROUGH 2 -typedef struct ass_shaper_font_data ASS_ShaperFontData; - -typedef struct { +struct ass_font_desc { char *family; unsigned bold; unsigned italic; int vertical; // @font vertical layout -} ASS_FontDesc; +}; -typedef struct { +struct ass_font { ASS_FontDesc desc; ASS_Library *library; FT_Library ftlibrary; + int faces_uid[ASS_FONT_MAX_FACES]; FT_Face faces[ASS_FONT_MAX_FACES]; ASS_ShaperFontData *shaper_priv; int n_faces; double scale_x, scale_y; // current transform FT_Vector v; // current shift double size; -} ASS_Font; - -#include "ass_cache.h" +}; ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, FT_Library ftlibrary, ASS_FontSelector *fontsel, diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index 2ca6f9d..e1a57f2 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -37,6 +37,7 @@ #include "ass_library.h" #include "ass_fontselect.h" #include "ass_fontconfig.h" +#include "ass_font.h" #define ABS(x) ((x) < 0 ? -(x) : (x)) #define MAX_FULLNAME 100 @@ -44,6 +45,8 @@ // proposed structure for holding font data, used for collection // and matching. strings are utf-8. struct font_info { + int uid; // unique font face id + char *family; // family name char **fullnames; // list of localized fullnames (e.g. Arial Bold Italic) int n_fullname; @@ -66,6 +69,9 @@ struct font_info { }; struct font_selector { + // uid counter + int uid; + // fallbacks char *family_default; char *path_default; @@ -121,6 +127,9 @@ ass_font_provider_add_font(ASS_FontProvider *provider, info = selector->font_infos + selector->n_font; memset(info, 0, sizeof(ASS_FontInfo)); + // set uid + info->uid = selector->uid++; + info->slant = meta->slant; info->weight = meta->weight; info->family = strdup(meta->family); @@ -245,8 +254,8 @@ static int font_info_compare(const void *av, const void *bv) } static char *select_font(ASS_FontSelector *priv, ASS_Library *library, - const char *family, unsigned bold, - unsigned italic, int *index, uint32_t code) + const char *family, unsigned bold, unsigned italic, + int *index, int *uid, uint32_t code) { int num_fonts = priv->n_font; ASS_FontInfo *font_infos = priv->font_infos; @@ -288,6 +297,7 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, if (!font_infos[info_index].path) return NULL; *index = font_infos[info_index].index; + *uid = font_infos[info_index].uid; return strdup(font_infos[info_index].path); } @@ -304,17 +314,19 @@ static char *select_font(ASS_FontSelector *priv, ASS_Library *library, * \return font file path */ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, - const char *family, unsigned bold, unsigned italic, - int *index, uint32_t code) + ASS_Font *font, int *index, int *uid, uint32_t code) { char *res = 0; + const char *family = font->desc.family; + unsigned bold = font->desc.bold; + unsigned italic = font->desc.italic; if (family && *family) - res = select_font(priv, library, family, bold, italic, index, code); + res = select_font(priv, library, family, bold, italic, index, uid, code); if (!res && priv->family_default) { res = select_font(priv, library, priv->family_default, bold, - italic, index, code); + italic, index, uid, code); if (res) ass_msg(library, MSGL_WARN, "fontselect: Using default " "font family: (%s, %d, %d) -> %s, %d", @@ -331,7 +343,7 @@ char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, if (!res) { res = select_font(priv, library, "Arial", bold, italic, - index, code); + index, uid, code); if (res) ass_msg(library, MSGL_WARN, "fontselect: Using 'Arial' " "font family: (%s, %d, %d) -> %s, %d", family, bold, @@ -467,6 +479,7 @@ ass_fontselect_init(ASS_Library *library, int i; ASS_FontSelector *priv = calloc(1, sizeof(ASS_FontSelector)); + priv->uid = 1; priv->family_default = family ? strdup(family) : NULL; priv->path_default = path ? strdup(path) : NULL; priv->index_default = 0; diff --git a/libass/ass_fontselect.h b/libass/ass_fontselect.h index 09c606b..43a32fb 100644 --- a/libass/ass_fontselect.h +++ b/libass/ass_fontselect.h @@ -20,15 +20,18 @@ #define LIBASS_FONTCONFIG_H #include -#include "ass_types.h" -#include "ass.h" #include #include FT_FREETYPE_H +typedef struct ass_shaper_font_data ASS_ShaperFontData; typedef struct font_selector ASS_FontSelector; typedef struct font_provider ASS_FontProvider; typedef struct font_info ASS_FontInfo; +#include "ass_types.h" +#include "ass.h" +#include "ass_font.h" + // get face data typedef void *(*GetFaceFunc)(void *); @@ -58,9 +61,8 @@ ASS_FontSelector * ass_fontselect_init(ASS_Library *library, FT_Library ftlibrary, const char *family, const char *path); -char *ass_font_select(ASS_FontSelector *priv, ASS_Library *lib, - const char *family, unsigned bold, unsigned italic, - int *index, uint32_t code); +char *ass_font_select(ASS_FontSelector *priv, ASS_Library *library, + ASS_Font *font, int *index, int *uid, uint32_t code); void ass_fontselect_free(ASS_FontSelector *priv); // Font provider functions -- cgit v1.2.3