mirror of
https://github.com/mpv-player/mpv
synced 2025-01-16 22:37:28 +01:00
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. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@21635 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
eba0f2e158
commit
d6ffde2900
@ -96,7 +96,8 @@ ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_
|
||||
|
||||
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 @@ ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_
|
||||
|
||||
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 @@ static void ass_font_reselect(void* fontconfig_priv, ass_font_t* font, uint32_t
|
||||
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 @@ static void ass_font_reselect(void* fontconfig_priv, ass_font_t* font, uint32_t
|
||||
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 @@ void ass_font_get_asc_desc(ass_font_t* font, uint32_t ch, int* asc, int* desc)
|
||||
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 @@ void ass_font_get_asc_desc(ass_font_t* font, uint32_t ch, int* asc, int* desc)
|
||||
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 @@ FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch
|
||||
}
|
||||
#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 @@ FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch
|
||||
((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_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch
|
||||
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);
|
||||
|
@ -31,10 +31,13 @@ typedef struct ass_font_desc_s {
|
||||
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;
|
||||
|
@ -595,7 +595,7 @@ static void change_border(double border)
|
||||
#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");
|
||||
|
Loading…
Reference in New Issue
Block a user