diff --git "a/win32ss/gdi/ntgdi/freetype.c" "b/win32ss/gdi/ntgdi/freetype.c" index 43547c20249..8a50bd8374b 100644 --- "a/win32ss/gdi/ntgdi/freetype.c" +++ "b/win32ss/gdi/ntgdi/freetype.c" @@ -1645,6 +1645,85 @@ UINT FASTCALL IntGetCharSet(INT nIndex, FT_ULong CodePageRange1) /* pixels to points */ #define PX2PT(pixels) FT_MulDiv((pixels), 72, 96) +/* Borrowed and adapted from Wine */ +static BOOL select_charmap(FT_Face ft_face, FT_Encoding encoding) +{ + FT_Error ft_err = FT_Err_Invalid_CharMap_Handle; + FT_CharMap cmap0, cmap1, cmap2, cmap3, cmap_def; + FT_Int i; + + cmap0 = cmap1 = cmap2 = cmap3 = cmap_def = NULL; + + for (i = 0; i < ft_face->num_charmaps; i++) + { + if (ft_face->charmaps[i]->encoding == encoding) + { + switch (ft_face->charmaps[i]->platform_id) + { + default: + cmap_def = ft_face->charmaps[i]; + break; + case 0: /* Apple Unicode */ + cmap0 = ft_face->charmaps[i]; + break; + case 1: /* Macintosh */ + cmap1 = ft_face->charmaps[i]; + break; + case 2: /* ISO */ + cmap2 = ft_face->charmaps[i]; + break; + case 3: /* Microsoft */ + cmap3 = ft_face->charmaps[i]; + break; + } + } +#ifdef __REACTOS__ +// Wine bug: for each loop iteration, a FT_Set_Charmap() call is made. +// ReactOS fix: Instead, loop until we retrieve all the cmap pointers +// of interest, then do one single FT_Set_Charmap() call using the +// preferred cmap. + }{ +#endif + + if (cmap3) /* prefer Microsoft cmap table */ + ft_err = FT_Set_Charmap(ft_face, cmap3); + else if (cmap1) + ft_err = FT_Set_Charmap(ft_face, cmap1); + else if (cmap2) + ft_err = FT_Set_Charmap(ft_face, cmap2); + else if (cmap0) + ft_err = FT_Set_Charmap(ft_face, cmap0); + else if (cmap_def) + ft_err = FT_Set_Charmap(ft_face, cmap_def); + } + + return ft_err == FT_Err_Ok; +} + +/* Borrowed from Wine */ +static FT_Encoding pick_charmap( FT_Face face, int charset ) +{ + static const FT_Encoding regular_order[] = { FT_ENCODING_UNICODE, FT_ENCODING_APPLE_ROMAN, FT_ENCODING_MS_SYMBOL, 0 }; + static const FT_Encoding symbol_order[] = { FT_ENCODING_MS_SYMBOL, FT_ENCODING_UNICODE, FT_ENCODING_APPLE_ROMAN, 0 }; + const FT_Encoding *encs = regular_order; + + if (charset == SYMBOL_CHARSET) encs = symbol_order; + + while (*encs != 0) + { + if (select_charmap( face, *encs )) break; + encs++; + } + + if (!face->charmap && face->num_charmaps) + { + if (!FT_Set_Charmap(face, face->charmaps[0])) + return face->charmap->encoding; + } + + return *encs; +} + static INT FASTCALL IntGdiLoadFontsFromMemory(PGDI_LOAD_FONT pLoadFont, PSHARED_FACE SharedFace, FT_Long FontIndex, INT CharSetIndex) @@ -1961,6 +2040,24 @@ IntGdiLoadFontByIndexFromMemory(PGDI_LOAD_FONT pLoadFont, FT_Long FontIndex) return 0; /* Failure */ } + /* + * In IntGdiLoadFontsFromMemory, when CharSetIndex == -1, + * we will always activate a charmap in the font face. + * + * Note from FreeType documentation: + * https://freetype.org/freetype2/docs/reference/ft2-character_mapping.html#ft_charmap + * + * When a new face is created (either through FT_New_Face or + * FT_Open_Face), the library looks for a Unicode charmap within + * the list and automatically activates it. If there is no + * Unicode charmap, FreeType doesn't set an 'active' charmap. + */ + pick_charmap(Face, DEFAULT_CHARSET); + if (!Face->charmap) + { + DPRINT1("WARNING: Could not find default charmap!\n"); + } + pLoadFont->IsTrueType = FT_IS_SFNT(Face); num_faces = Face->num_faces; SharedFace = SharedFace_Create(Face, pLoadFont->Memory);