From c116071fa8d1bbfcf509f1f099ebb789dfd6ae37 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Thu, 18 Aug 2011 00:15:57 +0200 Subject: Add glyph coverage map for embedded fonts Introduce a simple glyph coverage map (created when the font is added) and use it for checking glyph coverage in font selection. This uses a simple linear search at the moment. --- libass/ass_font.c | 2 +- libass/ass_font.h | 1 + libass/ass_fontselect.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/libass/ass_font.c b/libass/ass_font.c index 16207d3..7170e10 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -39,7 +39,7 @@ * Select a good charmap, prefer Microsoft Unicode charmaps. * Otherwise, let FreeType decide. */ -static void charmap_magic(ASS_Library *library, FT_Face face) +void charmap_magic(ASS_Library *library, FT_Face face) { int i; int ms_cmap = -1; diff --git a/libass/ass_font.h b/libass/ass_font.h index f29e301..693cabf 100644 --- a/libass/ass_font.h +++ b/libass/ass_font.h @@ -58,6 +58,7 @@ struct ass_font { double size; }; +void charmap_magic(ASS_Library *library, FT_Face face); ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library, FT_Library ftlibrary, ASS_FontSelector *fontsel, ASS_FontDesc *desc); diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c index e1a57f2..b3702b6 100644 --- a/libass/ass_fontselect.c +++ b/libass/ass_fontselect.c @@ -92,6 +92,44 @@ struct font_provider { void *priv; }; +// simple glyph coverage map +typedef struct coverage_map CoverageMap; +struct coverage_map { + int n_codepoint; + uint32_t *codepoints; +}; + +static int check_glyph_ft(void *data, uint32_t codepoint) +{ + int i; + CoverageMap *coverage = (CoverageMap *)data; + + if (!codepoint) + return 1; + + // XXX: sort at map creation and use bsearch here - is this worth it? + for (i = 0; i < coverage->n_codepoint; i++) + if (coverage->codepoints[i] == codepoint) + return 1; + + return 0; +} + +static void coverage_map_destroy(void *data) +{ + CoverageMap *coverage = (CoverageMap *)data; + + free(coverage->codepoints); + free(coverage); +} + +static ASS_FontProviderFuncs ft_funcs = { + NULL, + check_glyph_ft, + coverage_map_destroy, + NULL, +}; + ASS_FontProvider * ass_font_provider_new(ASS_FontSelector *selector, ASS_FontProviderFuncs *funcs, void *priv) @@ -417,6 +455,33 @@ static int get_font_info(FT_Library lib, FT_Face face, ASS_FontInfo *info) return 1; } +static CoverageMap *get_coverage_map(FT_Face face) +{ + int i = 0; + int n_codepoint = 0; + uint32_t codepoint; + unsigned index; + CoverageMap *coverage = calloc(1, sizeof(CoverageMap)); + + // determine number of codepoints first + codepoint = FT_Get_First_Char(face, &index); + while (index) { + n_codepoint++; + codepoint = FT_Get_Next_Char(face, codepoint, &index); + } + + coverage->codepoints = calloc(n_codepoint, sizeof(uint32_t)); + codepoint = FT_Get_First_Char(face, &index); + while (index) { + coverage->codepoints[i++] = codepoint; + codepoint = FT_Get_Next_Char(face, codepoint, &index); + } + + coverage->n_codepoint = n_codepoint; + + return coverage; +} + /** * \brief Process memory font. * \param priv private data @@ -447,6 +512,8 @@ static void process_fontdata(ASS_FontSelector *priv, ASS_Library *library, } num_faces = face->num_faces; + charmap_magic(library, face); + // get font metadata and add to list ASS_FontInfo info; memset(&info, 0, sizeof(ASS_FontInfo)); @@ -455,7 +522,17 @@ static void process_fontdata(ASS_FontSelector *priv, ASS_Library *library, info.index = face_index; info.path = strdup(name); - priv->font_infos = realloc(priv->font_infos, sizeof(ASS_FontInfo) * (priv->n_font + 1)); + info.uid = priv->uid++; + info.priv = get_coverage_map(face); + info.funcs = ft_funcs; + + // check size + if (priv->n_font >= priv->alloc_font) { + priv->alloc_font = FFMAX(1, 2 * priv->alloc_font); + priv->font_infos = realloc(priv->font_infos, + priv->alloc_font * sizeof(ASS_FontInfo)); + } + memcpy(priv->font_infos + priv->n_font, &info, sizeof(ASS_FontInfo)); priv->n_font++; @@ -484,13 +561,13 @@ ass_fontselect_init(ASS_Library *library, priv->path_default = path ? strdup(path) : NULL; priv->index_default = 0; - // XXX: for now, always add the fontconfig provider - priv->provider = ass_fontconfig_add_provider(library, priv, NULL); - // XXX: use a real font provider for this for (i = 0; i < library->num_fontdata; ++i) process_fontdata(priv, library, ftlibrary, i); + // XXX: for now, always add the fontconfig provider + priv->provider = ass_fontconfig_add_provider(library, priv, NULL); + return priv; } -- cgit v1.2.3