# HG changeset patch # User eugeni # Date 1164754202 0 # Node ID c611dfc4cb85e2f9f144ee522154e47d4498c629 # Parent 5337cdeec16968604101fd88096ca45e7c5f5e7f If a glyph is not found in the current font, switch to another one. diff -r 5337cdeec169 -r c611dfc4cb85 help/help_mp-en.h --- a/help/help_mp-en.h Tue Nov 28 22:44:40 2006 +0000 +++ b/help/help_mp-en.h Tue Nov 28 22:50:02 2006 +0000 @@ -2041,3 +2041,6 @@ #define MSGTR_LIBASS_EventHeightHasChanged "[ass] Warning! Event height has changed! \n" #define MSGTR_LIBASS_TooManySimultaneousEvents "[ass] Too many simultaneous events!\n" +// ass_font.c +#define MSGTR_LIBASS_GlyphNotFoundReselectingFont "[ass] Glyph 0x%X not found, reselecting font for (%s, %d, %d)\n" +#define MSGTR_LIBASS_GlyphNotFound "[ass] Glyph 0x%X not found in font for (%s, %d, %d)\n" diff -r 5337cdeec169 -r c611dfc4cb85 libass/ass_font.c --- a/libass/ass_font.c Tue Nov 28 22:44:40 2006 +0000 +++ b/libass/ass_font.c Tue Nov 28 22:50:02 2006 +0000 @@ -86,6 +86,10 @@ font->v.x = font->v.y = 0; font->size = 0; +#ifdef HAVE_FONTCONFIG + font->charset = FcCharSetCreate(); +#endif + ass_font_cache_add(font); return font; @@ -118,6 +122,40 @@ } } +#ifdef HAVE_FONTCONFIG +static void ass_font_reselect(void* fontconfig_priv, ass_font_t* font) +{ + char* path; + int index; + FT_Face face; + int error; + + path = fontconfig_select_with_charset(fontconfig_priv, font->desc.family, font->desc.bold, + font->desc.italic, &index, font->charset); + if (strcasecmp(path, font->path) == 0 && index == font->index) { + free(path); + return; + } + + error = FT_New_Face(font->ftlibrary, path, index, &face); + if (error) { + mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index); + return; + } + charmap_magic(face); + + if (font->face) FT_Done_Face(font->face); + free(font->path); + + font->face = face; + font->path = strdup(path); + font->index = index; + + FT_Set_Transform(font->face, &font->m, &font->v); + FT_Set_Pixel_Sizes(font->face, 0, font->size); +} +#endif + FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch) { int error; @@ -128,6 +166,20 @@ return 0; index = FT_Get_Char_Index(font->face, ch); +#ifdef HAVE_FONTCONFIG + FcCharSetAddChar(font->charset, ch); + if (index == 0) { + mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_GlyphNotFoundReselectingFont, + ch, font->desc.family, font->desc.bold, font->desc.italic); + ass_font_reselect(fontconfig_priv, font); + index = FT_Get_Char_Index(font->face, ch); + if (index == 0) { + mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound, + ch, font->desc.family, font->desc.bold, font->desc.italic); + } + } +#endif + error = FT_Load_Glyph(font->face, index, FT_LOAD_NO_BITMAP ); if (error) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); @@ -157,5 +209,8 @@ if (font->face) FT_Done_Face(font->face); if (font->path) free(font->path); if (font->desc.family) free(font->desc.family); +#ifdef HAVE_FONTCONFIG + if (font->charset) FcCharSetDestroy(font->charset); +#endif free(font); } diff -r 5337cdeec169 -r c611dfc4cb85 libass/ass_font.h --- a/libass/ass_font.h Tue Nov 28 22:44:40 2006 +0000 +++ b/libass/ass_font.h Tue Nov 28 22:50:02 2006 +0000 @@ -21,6 +21,10 @@ #ifndef __ASS_FONT_H__ #define __ASS_FONT_H__ +#ifdef HAVE_FONTCONFIG +#include +#endif + typedef struct ass_font_desc_s { char* family; unsigned bold; @@ -36,6 +40,9 @@ FT_Matrix m; // current transformation FT_Vector v; // current shift int size; +#ifdef HAVE_FONTCONFIG + FcCharSet* charset; +#endif } ass_font_t; ass_font_t* ass_font_new(FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc); diff -r 5337cdeec169 -r c611dfc4cb85 libass/ass_fontconfig.c --- a/libass/ass_fontconfig.c Tue Nov 28 22:44:40 2006 +0000 +++ b/libass/ass_fontconfig.c Tue Nov 28 22:50:02 2006 +0000 @@ -53,7 +53,8 @@ * \param index out: font index inside a file * \return font file path */ -static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index) +static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, + FcCharSet* charset) { FcBool rc; FcResult result; @@ -61,6 +62,9 @@ int val_i; FcChar8* val_s; FcBool val_b; + FcCharSet* val_cs; + FcFontSet* fset; + int curf, bestf, bestdiff = 0; *index = 0; @@ -78,16 +82,43 @@ rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern); if (!rc) return 0; - - rpat = FcFontMatch(priv->config, pat, &result); - if (!rpat) + + fset = FcFontSort(priv->config, pat, FcTrue, NULL, &result); + + bestf = -1; + if (charset) + bestdiff = FcCharSetCount(charset) + 1; + for (curf = 0; curf < fset->nfont; ++curf) { + rpat = fset->fonts[curf]; + + result = FcPatternGetBool(rpat, FC_OUTLINE, 0, &val_b); + if (result != FcResultMatch) + continue; + if (val_b != FcTrue) + continue; + + if (charset) { + int diff; + result = FcPatternGetCharSet(rpat, FC_CHARSET, 0, &val_cs); + if (result != FcResultMatch) + continue; + diff = FcCharSetSubtractCount(charset, val_cs); + if (diff < bestdiff) { + bestdiff = diff; + bestf = curf; + } + if (diff == 0) + break; + } else { + bestf = curf; + break; + } + } + + if (bestf < 0) return 0; - - result = FcPatternGetBool(rpat, FC_OUTLINE, 0, &val_b); - if (result != FcResultMatch) - return 0; - if (val_b != FcTrue) - return 0; + + rpat = fset->fonts[bestf]; result = FcPatternGetInteger(rpat, FC_INDEX, 0, &val_i); if (result != FcResultMatch) @@ -118,13 +149,14 @@ * \param index out: font index inside a file * \return font file path */ -char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index) +char* fontconfig_select_with_charset(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, + FcCharSet* charset) { char* res = 0; if (family && *family) - res = _select_font(priv, family, bold, italic, index); + res = _select_font(priv, family, bold, italic, index, charset); if (!res && priv->family_default) { - res = _select_font(priv, priv->family_default, bold, italic, index); + res = _select_font(priv, priv->family_default, bold, italic, index, charset); if (res) mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingDefaultFontFamily, family, bold, italic, res, *index); @@ -136,7 +168,7 @@ family, bold, italic, res, *index); } if (!res) { - res = _select_font(priv, "Arial", bold, italic, index); + res = _select_font(priv, "Arial", bold, italic, index, charset); if (res) mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingArialFontFamily, family, bold, italic, res, *index); @@ -147,6 +179,11 @@ return res; } +char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index) +{ + return fontconfig_select_with_charset(priv, family, bold, italic, index, 0); +} + /** * \brief Init fontconfig. * \param dir additional directoryu for fonts diff -r 5337cdeec169 -r c611dfc4cb85 libass/ass_fontconfig.h --- a/libass/ass_fontconfig.h Tue Nov 28 22:44:40 2006 +0000 +++ b/libass/ass_fontconfig.h Tue Nov 28 22:50:02 2006 +0000 @@ -21,11 +21,19 @@ #ifndef __ASS_FONTCONFIG_H__ #define __ASS_FONTCONFIG_H__ +#ifdef HAVE_FONTCONFIG +#include +#endif + typedef struct fc_instance_s fc_instance_t; fc_instance_t* fontconfig_init(const char* dir, const char* family, const char* path); char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index); void fontconfig_done(fc_instance_t* priv); +#ifdef HAVE_FONTCONFIG +char* fontconfig_select_with_charset(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, FcCharSet* charset); #endif +#endif +