]> granicus.if.org Git - libass/commitdiff
If a glyph is not found in the current font, switch to another one.
authoreugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>
Tue, 28 Nov 2006 22:50:02 +0000 (22:50 +0000)
committereugeni <eugeni@b3059339-0415-0410-9bf9-f77b7e298cf2>
Tue, 28 Nov 2006 22:50:02 +0000 (22:50 +0000)
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@21367 b3059339-0415-0410-9bf9-f77b7e298cf2

libass/ass_font.c
libass/ass_font.h
libass/ass_fontconfig.c
libass/ass_fontconfig.h

index 3120db04f29b118ab56c702c3ef98d69eb4b7a10..2a44c9fc2ccb45acc707dfeaf09912837ba806fa 100644 (file)
@@ -86,6 +86,10 @@ ass_font_t* ass_font_new(FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* d
        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 @@ void ass_font_set_size(ass_font_t* font, int size)
        }
 }
 
+#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 @@ FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch
                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 @@ void ass_font_free(ass_font_t* font)
        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);
 }
index f1ae7a6e16ad3bfcca8505c038d04536f6af23be..aac42e9a2486514cba6783ac5f65630752bd49f9 100644 (file)
 #ifndef __ASS_FONT_H__
 #define __ASS_FONT_H__
 
+#ifdef HAVE_FONTCONFIG
+#include <fontconfig/fontconfig.h>
+#endif
+
 typedef struct ass_font_desc_s {
        char* family;
        unsigned bold;
@@ -36,6 +40,9 @@ typedef struct ass_font_s {
        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);
index b4ac44e863b4775ad264d3cc181ca32fb440db9b..8cb6db205eb3316cbbf92d844e44d376f0ae54c7 100644 (file)
@@ -53,7 +53,8 @@ struct fc_instance_s {
  * \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 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
        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 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
        rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern);
        if (!rc)
                return 0;
-       
-       rpat = FcFontMatch(priv->config, pat, &result);
-       if (!rpat)
-               return 0;
-       
-       result = FcPatternGetBool(rpat, FC_OUTLINE, 0, &val_b);
-       if (result != FcResultMatch)
-               return 0;
-       if (val_b != FcTrue)
+
+       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;
+
+       rpat = fset->fonts[bestf];
        
        result = FcPatternGetInteger(rpat, FC_INDEX, 0, &val_i);
        if (result != FcResultMatch)
@@ -118,13 +149,14 @@ static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold
  * \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 @@ char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold,
                       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 @@ char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold,
        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
index e2e71a9fd99214e86d21f7d0230c73d668194844..9aa1746908963020b8a46b164d4d2f78b3999f25 100644 (file)
 #ifndef __ASS_FONTCONFIG_H__
 #define __ASS_FONTCONFIG_H__
 
+#ifdef HAVE_FONTCONFIG
+#include <fontconfig/fontconfig.h>
+#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