diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 6fe211eac3d..27aa129c0de 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -426,6 +426,7 @@ struct gdi_font *alloc_gdi_font( const WCHAR *file, void *data_ptr, SIZE_T data_ font->refcount = 1; font->matrix.eM11 = font->matrix.eM22 = 1.0; font->scale_y = 1.0; + font->kern_count = -1; if (file) { @@ -468,6 +469,7 @@ void free_gdi_font( struct gdi_font *font ) HeapFree( GetProcessHeap(), 0, font->otm.otmpFaceName ); HeapFree( GetProcessHeap(), 0, font->otm.otmpFullName ); HeapFree( GetProcessHeap(), 0, font->gm ); + HeapFree( GetProcessHeap(), 0, font->kern_pairs ); HeapFree( GetProcessHeap(), 0, font ); } @@ -1179,17 +1181,27 @@ static DWORD CDECL font_GetGlyphOutline( PHYSDEV dev, UINT glyph, UINT format, static DWORD CDECL font_GetKerningPairs( PHYSDEV dev, DWORD count, KERNINGPAIR *pairs ) { struct font_physdev *physdev = get_font_dev( dev ); - DWORD ret; if (!physdev->font) { dev = GET_NEXT_PHYSDEV( dev, pGetKerningPairs ); return dev->funcs->pGetKerningPairs( dev, count, pairs ); } + EnterCriticalSection( &font_cs ); - ret = font_funcs->pGetKerningPairs( physdev->font, count, pairs ); + if (physdev->font->kern_count == -1) + physdev->font->kern_count = font_funcs->get_kerning_pairs( physdev->font, + &physdev->font->kern_pairs ); LeaveCriticalSection( &font_cs ); - return ret; + + if (count && pairs) + { + count = min( count, physdev->font->kern_count ); + memcpy( pairs, physdev->font->kern_pairs, count * sizeof(*pairs) ); + } + else count = physdev->font->kern_count; + + return count; } diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 01a66600063..16fb92dd73b 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -302,8 +302,6 @@ typedef struct { struct tagGdiFont { struct gdi_font *gdi_font; - DWORD total_kern_pairs; - KERNINGPAIR *kern_pairs; struct list child_fonts; /* the following members can be accessed without locking, they are never modified after creation */ @@ -4021,8 +4019,6 @@ static UINT get_nearest_charset(const WCHAR *family_name, Face *face, UINT *cp) static BOOL CDECL freetype_alloc_font( struct gdi_font *font ) { GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); - ret->total_kern_pairs = (DWORD)-1; - ret->kern_pairs = NULL; list_init(&ret->child_fonts); ret->gdi_font = font; font->private = ret; @@ -4048,7 +4044,6 @@ static void CDECL freetype_destroy_font( struct gdi_font *gdi_font ) if (font->ft_face) pFT_Done_Face(font->ft_face); if (font->mapping) unmap_font_file( font->mapping ); - HeapFree(GetProcessHeap(), 0, font->kern_pairs); HeapFree(GetProcessHeap(), 0, font->GSUB_Table); HeapFree(GetProcessHeap(), 0, font); } @@ -7458,31 +7453,18 @@ static DWORD parse_format0_kern_subtable(GdiFont *font, } /************************************************************* - * freetype_GetKerningPairs + * freetype_get_kerning_pairs */ -static DWORD CDECL freetype_GetKerningPairs( struct gdi_font *gdi_font, DWORD cPairs, KERNINGPAIR *kern_pair ) +static DWORD CDECL freetype_get_kerning_pairs( struct gdi_font *gdi_font, KERNINGPAIR **pairs ) { GdiFont *font = get_font_ptr(gdi_font); - DWORD length; + DWORD length, count = 0; void *buf; const struct TT_kern_table *tt_kern_table; const struct TT_kern_subtable *tt_kern_subtable; USHORT i, nTables; USHORT *glyph_to_char; - if (font->total_kern_pairs != (DWORD)-1) - { - if (cPairs && kern_pair) - { - cPairs = min(cPairs, font->total_kern_pairs); - memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair)); - } - else cPairs = font->total_kern_pairs; - return cPairs; - } - - font->total_kern_pairs = 0; - length = freetype_get_font_data(gdi_font, MS_KERN_TAG, 0, NULL, 0); if (length == GDI_ERROR) @@ -7563,21 +7545,19 @@ static DWORD CDECL freetype_GetKerningPairs( struct gdi_font *gdi_font, DWORD cP */ if (tt_kern_subtable_copy.coverage.bits.format == 0) { - DWORD new_chunk, old_total = font->total_kern_pairs; + DWORD new_chunk, old_total = count; new_chunk = parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1), glyph_to_char, NULL, 0); - font->total_kern_pairs += new_chunk; + count += new_chunk; - if (!font->kern_pairs) - font->kern_pairs = HeapAlloc(GetProcessHeap(), 0, - font->total_kern_pairs * sizeof(*font->kern_pairs)); + if (!*pairs) + *pairs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(**pairs)); else - font->kern_pairs = HeapReAlloc(GetProcessHeap(), 0, font->kern_pairs, - font->total_kern_pairs * sizeof(*font->kern_pairs)); + *pairs = HeapReAlloc(GetProcessHeap(), 0, *pairs, count * sizeof(**pairs)); parse_format0_kern_subtable(font, (const struct TT_format0_kern_subtable *)(tt_kern_subtable + 1), - glyph_to_char, font->kern_pairs + old_total, new_chunk); + glyph_to_char, *pairs + old_total, new_chunk); } else TRACE("skipping kerning table format %u\n", tt_kern_subtable_copy.coverage.bits.format); @@ -7587,14 +7567,7 @@ static DWORD CDECL freetype_GetKerningPairs( struct gdi_font *gdi_font, DWORD cP HeapFree(GetProcessHeap(), 0, glyph_to_char); HeapFree(GetProcessHeap(), 0, buf); - - if (cPairs && kern_pair) - { - cPairs = min(cPairs, font->total_kern_pairs); - memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair)); - } - else cPairs = font->total_kern_pairs; - return cPairs; + return count; } static const struct font_backend_funcs font_funcs = @@ -7603,7 +7576,6 @@ static const struct font_backend_funcs font_funcs = freetype_FontIsLinked, freetype_GetCharWidthInfo, freetype_GetFontUnicodeRanges, - freetype_GetKerningPairs, freetype_SelectFont, freetype_AddFontResourceEx, freetype_RemoveFontResourceEx, @@ -7616,6 +7588,7 @@ static const struct font_backend_funcs font_funcs = freetype_get_glyph_outline, freetype_set_outline_text_metrics, freetype_set_bitmap_text_metrics, + freetype_get_kerning_pairs, freetype_destroy_font }; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 1f744d1bf2b..8036dfb986b 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -313,6 +313,8 @@ struct gdi_font DWORD gm_size; struct glyph_metrics **gm; OUTLINETEXTMETRICW otm; + KERNINGPAIR *kern_pairs; + int kern_count; /* the following members can be accessed without locking, they are never modified after creation */ void *private; /* font backend private data */ DWORD handle; @@ -359,7 +361,6 @@ struct font_backend_funcs BOOL (CDECL *pFontIsLinked)( struct gdi_font *font ); BOOL (CDECL *pGetCharWidthInfo)( struct gdi_font *font, struct char_width_info *info ); DWORD (CDECL *pGetFontUnicodeRanges)( struct gdi_font *font, GLYPHSET *glyphset ); - DWORD (CDECL *pGetKerningPairs)( struct gdi_font *font, DWORD count, KERNINGPAIR *pairs ); struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont, UINT *aa_flags, UINT default_aa_flags ); INT (CDECL *pAddFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv ); @@ -377,6 +378,7 @@ struct font_backend_funcs GLYPHMETRICS *gm, ABC *abc, DWORD buflen, void *buf, const MAT2 *mat ); BOOL (CDECL *set_outline_text_metrics)( struct gdi_font *font ); BOOL (CDECL *set_bitmap_text_metrics)( struct gdi_font *font ); + DWORD (CDECL *get_kerning_pairs)( struct gdi_font *gdi_font, KERNINGPAIR **kern_pair ); void (CDECL *destroy_font)( struct gdi_font *font ); };