From 88cf01a448b1a14c8364294946f349af074c1969 Mon Sep 17 00:00:00 2001 From: Apache553 Date: Sun, 16 Jan 2022 16:52:40 +0800 Subject: font: handle conversion failure better If a conversion fails for a non-Unicode font, let font fallback happen instead of displaying bogus glyphs. --- libass/ass_font.c | 28 ++++++++++++++++++---------- libass/ass_shaper.c | 12 +++++++++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/libass/ass_font.c b/libass/ass_font.c index 3f44a1f..1496924 100644 --- a/libass/ass_font.c +++ b/libass/ass_font.c @@ -82,7 +82,7 @@ static uint32_t convert_unicode_to_mb(FT_Encoding encoding, uint32_t codepoint) codepage = 1361; break; default: - return codepoint; + return 0; } WCHAR input_buffer[2]; @@ -105,7 +105,7 @@ static uint32_t convert_unicode_to_mb(FT_Encoding encoding, uint32_t codepoint) int output_length = WideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, input_buffer, inbuf_size, output_buffer, sizeof(output_buffer), NULL, &conversion_fail); if (output_length == 0 || conversion_fail) - return codepoint; + return 0; return pack_mbcs_bytes(output_buffer, output_length); } @@ -137,7 +137,7 @@ static uint32_t convert_unicode_to_mb(FT_Encoding encoding, uint32_t codepoint) encoding_list = (EncodingList) {{"CP1361", "JOHAB", NULL}}; break; default: - return codepoint; + return 0; } // open iconv context @@ -149,18 +149,18 @@ static uint32_t convert_unicode_to_mb(FT_Encoding encoding, uint32_t codepoint) ++encoding_str; } if (cd == (iconv_t) -1) - return codepoint; + return 0; char input_buffer[4]; char output_buffer[2]; // MS-flavour encodings only need 2 bytes uint32_t result = codepoint; - // convert input codepoint to little endian uint32_t bytearray + // convert input codepoint to little endian uint32_t bytearray, + // result becomes 0 after the loop finishes for (int i = 0; i < 4; ++i) { input_buffer[i] = result & 0xFF; result >>= 8; } - result = codepoint; // do actual convert, only reversible converts are valid, since we are converting unicode to something else size_t inbuf_size = sizeof(input_buffer); @@ -182,7 +182,8 @@ clean: #else static uint32_t convert_unicode_to_mb(FT_Encoding encoding, uint32_t codepoint) { // just a stub - return codepoint; + // we can't handle this cmap, fallback + return 0; } #endif @@ -578,7 +579,9 @@ int ass_font_get_index(ASS_FontSelector *fontsel, ASS_Font *font, for (i = 0; i < font->n_faces && index == 0; ++i) { face = font->faces[i]; - index = FT_Get_Char_Index(face, ass_font_index_magic(face, symbol)); + index = ass_font_index_magic(face, symbol); + if (index) + index = FT_Get_Char_Index(face, index); if (index) *face_index = i; } @@ -592,14 +595,19 @@ int ass_font_get_index(ASS_FontSelector *fontsel, ASS_Font *font, face_idx = *face_index = add_face(fontsel, font, symbol); if (face_idx >= 0) { face = font->faces[face_idx]; - index = FT_Get_Char_Index(face, ass_font_index_magic(face, symbol)); + index = ass_font_index_magic(face, symbol); + if (index) + index = FT_Get_Char_Index(face, index); if (index == 0 && face->num_charmaps > 0) { int i; ass_msg(font->library, MSGL_WARN, "Glyph 0x%X not found, broken font? Trying all charmaps", symbol); for (i = 0; i < face->num_charmaps; i++) { FT_Set_Charmap(face, face->charmaps[i]); - if ((index = FT_Get_Char_Index(face, ass_font_index_magic(face, symbol))) != 0) break; + index = ass_font_index_magic(face, symbol); + if (index) + index = FT_Get_Char_Index(face, index); + if (index) break; } } if (index == 0) { diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index e406fd1..f95dd58 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -283,7 +283,9 @@ get_glyph_nominal(hb_font_t *font, void *font_data, hb_codepoint_t unicode, FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; - *glyph = FT_Get_Char_Index(face, ass_font_index_magic(face, unicode)); + *glyph = ass_font_index_magic(face, unicode); + if (*glyph) + *glyph = FT_Get_Char_Index(face, *glyph); if (!*glyph) return false; @@ -300,7 +302,9 @@ get_glyph_variation(hb_font_t *font, void *font_data, hb_codepoint_t unicode, FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; - *glyph = FT_Face_GetCharVariantIndex(face, ass_font_index_magic(face, unicode), variation); + *glyph = ass_font_index_magic(face, unicode); + if (*glyph) + *glyph = FT_Face_GetCharVariantIndex(face, *glyph, variation); if (!*glyph) return false; @@ -794,7 +798,9 @@ static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) GlyphInfo *info = glyphs + i; FT_Face face = info->font->faces[info->face_index]; info->symbol = shaper->event_text[i]; - info->glyph_index = FT_Get_Char_Index(face, ass_font_index_magic(face, shaper->event_text[i])); + info->glyph_index = ass_font_index_magic(face, shaper->event_text[i]); + if (info->glyph_index) + info->glyph_index = FT_Get_Char_Index(face, info->glyph_index); } free(joins); -- cgit v1.2.3