Mercurial > mplayer.hg
changeset 21619:b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
lookup prefers earlier opened fonts.
This way glyph lookup is stable, which means that:
- cache cleanup is never required after font reselecting;
- a single unrecognized char won't change the appearance of all the others.
author | eugeni |
---|---|
date | Sat, 16 Dec 2006 19:34:00 +0000 |
parents | 8111d4625194 |
children | ef93ebaef504 |
files | libass/ass_font.c libass/ass_font.h libass/ass_render.c |
diffstat | 3 files changed, 59 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/libass/ass_font.c Sat Dec 16 19:29:33 2006 +0000 +++ b/libass/ass_font.c Sat Dec 16 19:34:00 2006 +0000 @@ -96,7 +96,8 @@ font = calloc(1, sizeof(ass_font_t)); font->ftlibrary = ftlibrary; - font->face = face; + font->faces[0] = face; + font->n_faces = 1; font->desc.family = strdup(desc->family); font->desc.bold = desc->bold; font->desc.italic = desc->italic; @@ -117,20 +118,24 @@ void ass_font_set_transform(ass_font_t* font, FT_Matrix* m, FT_Vector* v) { + int i; font->m.xx = m->xx; font->m.xy = m->xy; font->m.yx = m->yx; font->m.yy = m->yy; font->v.x = v->x; font->v.y = v->y; - FT_Set_Transform(font->face, &font->m, &font->v); + for (i = 0; i < font->n_faces; ++i) + FT_Set_Transform(font->faces[i], &font->m, &font->v); } void ass_font_set_size(ass_font_t* font, int size) { + int i; if (font->size != size) { font->size = size; - FT_Set_Pixel_Sizes(font->face, 0, size); + for (i = 0; i < font->n_faces; ++i) + FT_Set_Pixel_Sizes(font->faces[i], 0, size); } } @@ -141,6 +146,9 @@ int index; FT_Face face; int error; + + if (font->n_faces == ASS_FONT_MAX_FACES) + return; path = fontconfig_select_with_charset(fontconfig_priv, font->desc.family, font->desc.bold, font->desc.italic, &index, font->charset); @@ -158,18 +166,18 @@ return; } - if (font->face) FT_Done_Face(font->face); - - font->face = face; + font->faces[font->n_faces++] = face; - FT_Set_Transform(font->face, &font->m, &font->v); - FT_Set_Pixel_Sizes(font->face, 0, font->size); + FT_Set_Transform(face, &font->m, &font->v); + FT_Set_Pixel_Sizes(face, 0, font->size); } #endif void ass_font_get_asc_desc(ass_font_t* font, uint32_t ch, int* asc, int* desc) { - FT_Face face = font->face; + int i; + for (i = 0; i < font->n_faces; ++i) { + FT_Face face = font->faces[i]; if (FT_Get_Char_Index(face, ch)) { int v, v2; v = face->size->metrics.ascender; @@ -180,6 +188,7 @@ v2 = - FT_MulFix(face->bbox.yMin, face->size->metrics.y_scale); *desc = (v > v2 * 0.9) ? v : v2; return; + } } *asc = *desc = 0; @@ -188,20 +197,31 @@ FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch) { int error; - int index; + int index = 0; + int i; FT_Glyph glyph; + FT_Face face = 0; if (ch < 0x20) return 0; - - index = FT_Get_Char_Index(font->face, ch); + if (font->n_faces == 0) + return 0; + + for (i = 0; i < font->n_faces; ++i) { + face = font->faces[i]; + index = FT_Get_Char_Index(face, ch); + if (index) + break; + } + #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, ch); - index = FT_Get_Char_Index(font->face, ch); + face = font->faces[font->n_faces - 1]; + index = FT_Get_Char_Index(face, ch); if (index == 0) { mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound, ch, font->desc.family, font->desc.bold, font->desc.italic); @@ -209,7 +229,7 @@ } #endif - error = FT_Load_Glyph(font->face, index, FT_LOAD_NO_BITMAP ); + error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP ); if (error) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); return 0; @@ -219,12 +239,12 @@ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || \ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10)) // FreeType >= 2.1.10 required - if (!(font->face->style_flags & FT_STYLE_FLAG_ITALIC) && + if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) && (font->desc.italic > 55)) { - FT_GlyphSlot_Oblique(font->face->glyph); + FT_GlyphSlot_Oblique(face->glyph); } #endif - error = FT_Get_Glyph(font->face->glyph, &glyph); + error = FT_Get_Glyph(face->glyph, &glyph); if (error) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph); return 0; @@ -236,20 +256,28 @@ FT_Vector ass_font_get_kerning(ass_font_t* font, uint32_t c1, uint32_t c2) { FT_Vector v = {0, 0}; - int i1, i2; - - if (!FT_HAS_KERNING(font->face)) - return v; - i1 = FT_Get_Char_Index(font->face, c1); - i2 = FT_Get_Char_Index(font->face, c2); - if (i1 && i2) - FT_Get_Kerning(font->face, i1, i2, FT_KERNING_DEFAULT, &v); + int i; + + for (i = 0; i < font->n_faces; ++i) { + FT_Face face = font->faces[i]; + int i1 = FT_Get_Char_Index(face, c1); + int i2 = FT_Get_Char_Index(face, c2); + if (i1 && i2) { + if (FT_HAS_KERNING(face)) + FT_Get_Kerning(face, i1, i2, FT_KERNING_DEFAULT, &v); + return v; + } + if (i1 || i2) // these glyphs are from different font faces, no kerning information + return v; + } return v; } void ass_font_free(ass_font_t* font) { - if (font->face) FT_Done_Face(font->face); + int i; + for (i = 0; i < font->n_faces; ++i) + if (font->faces[i]) FT_Done_Face(font->faces[i]); if (font->desc.family) free(font->desc.family); #ifdef HAVE_FONTCONFIG if (font->charset) FcCharSetDestroy(font->charset);
--- a/libass/ass_font.h Sat Dec 16 19:29:33 2006 +0000 +++ b/libass/ass_font.h Sat Dec 16 19:34:00 2006 +0000 @@ -31,10 +31,13 @@ unsigned italic; } ass_font_desc_t; +#define ASS_FONT_MAX_FACES 10 + typedef struct ass_font_s { ass_font_desc_t desc; FT_Library ftlibrary; - FT_Face face; + FT_Face faces[ASS_FONT_MAX_FACES]; + int n_faces; FT_Matrix m; // current transformation FT_Vector v; // current shift int size;
--- a/libass/ass_render.c Sat Dec 16 19:29:33 2006 +0000 +++ b/libass/ass_render.c Sat Dec 16 19:34:00 2006 +0000 @@ -595,7 +595,7 @@ #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) error = FT_Stroker_New( ass_renderer->ftlibrary, &render_context.stroker ); #else // < 2.2 - error = FT_Stroker_New( render_context.font->face->memory, &render_context.stroker ); + error = FT_Stroker_New( render_context.font->faces[0]->memory, &render_context.stroker ); #endif if (error) { mp_msg(MSGT_ASS, MSGL_V, "failed to get stroker\n");