From 6ff14a92138ea10f38a29215731d4e63c1acec26 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 20 Feb 2015 13:47:30 +0300 Subject: [PATCH] dwrite: Use FreeType CMAP cache system instead of parsing tables manually. --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 9 +--- dlls/dwrite/freetype.c | 26 ++++++++- dlls/dwrite/opentype.c | 100 ----------------------------------- 4 files changed, 28 insertions(+), 109 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 9a27a5e1739..9481c7468d2 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -126,7 +126,6 @@ extern HRESULT get_family_names_from_stream(IDWriteFontFileStream*,UINT32,DWRITE /* Opentype font table functions */ extern HRESULT opentype_analyze_font(IDWriteFontFileStream*,UINT32*,DWRITE_FONT_FILE_TYPE*,DWRITE_FONT_FACE_TYPE*,BOOL*) DECLSPEC_HIDDEN; extern HRESULT opentype_get_font_table(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,UINT32,const void**,void**,UINT32*,BOOL*) DECLSPEC_HIDDEN; -extern void opentype_cmap_get_glyphindex(void*,UINT32,UINT16*) DECLSPEC_HIDDEN; extern HRESULT opentype_cmap_get_unicode_ranges(void*,UINT32,DWRITE_UNICODE_RANGE*,UINT32*) DECLSPEC_HIDDEN; extern void opentype_get_font_properties(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_STRETCH*, DWRITE_FONT_WEIGHT*,DWRITE_FONT_STYLE*) DECLSPEC_HIDDEN; @@ -162,6 +161,7 @@ extern void freetype_notify_cacheremove(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern BOOL freetype_is_monospaced(IDWriteFontFace2*) DECLSPEC_HIDDEN; extern HRESULT freetype_get_glyph_outline(IDWriteFontFace2*,FLOAT,UINT16,USHORT,struct glyph_outline**) DECLSPEC_HIDDEN; extern UINT16 freetype_get_glyphcount(IDWriteFontFace2*) DECLSPEC_HIDDEN; +extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32) DECLSPEC_HIDDEN; /* Glyph shaping */ enum SCRIPT_JUSTIFY diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 2092576831b..12ce3ca1a24 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -388,17 +388,12 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UI UINT32 count, UINT16 *glyph_indices) { struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface); - unsigned int i; - void *data; + UINT32 i; TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); - data = get_fontface_cmap(This); - if (!data) - return E_FAIL; - for (i = 0; i < count; i++) - opentype_cmap_get_glyphindex(data, codepoints[i], &glyph_indices[i]); + glyph_indices[i] = freetype_get_glyphindex(iface, codepoints[i]); return S_OK; } diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index 3b9681d9c31..84c9cad4c9a 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -53,6 +53,7 @@ static CRITICAL_SECTION freetype_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; static void *ft_handle = NULL; static FT_Library library = 0; static FTC_Manager cache_manager = 0; +static FTC_CMapCache cmap_cache = 0; typedef struct { FT_Int major; @@ -67,6 +68,8 @@ MAKE_FUNCPTR(FT_Library_Version); MAKE_FUNCPTR(FT_Load_Glyph); MAKE_FUNCPTR(FT_New_Memory_Face); MAKE_FUNCPTR(FT_Outline_Transform); +MAKE_FUNCPTR(FTC_CMapCache_Lookup); +MAKE_FUNCPTR(FTC_CMapCache_New); MAKE_FUNCPTR(FTC_Manager_New); MAKE_FUNCPTR(FTC_Manager_Done); MAKE_FUNCPTR(FTC_Manager_LookupFace); @@ -137,6 +140,8 @@ BOOL init_freetype(void) LOAD_FUNCPTR(FT_Load_Glyph) LOAD_FUNCPTR(FT_New_Memory_Face) LOAD_FUNCPTR(FT_Outline_Transform) + LOAD_FUNCPTR(FTC_CMapCache_Lookup) + LOAD_FUNCPTR(FTC_CMapCache_New) LOAD_FUNCPTR(FTC_Manager_New) LOAD_FUNCPTR(FTC_Manager_Done) LOAD_FUNCPTR(FTC_Manager_LookupFace) @@ -153,8 +158,11 @@ BOOL init_freetype(void) pFT_Library_Version(library, &FT_Version.major, &FT_Version.minor, &FT_Version.patch); /* init cache manager */ - if (pFTC_Manager_New(library, 0, 0, 0, &face_requester, NULL, &cache_manager) != 0) { + if (pFTC_Manager_New(library, 0, 0, 0, &face_requester, NULL, &cache_manager) != 0 || + pFTC_CMapCache_New(cache_manager, &cmap_cache) != 0) { + ERR("Failed to init FreeType cache\n"); + pFTC_Manager_Done(cache_manager); pFT_Done_FreeType(library); wine_dlclose(ft_handle, NULL, 0); ft_handle = NULL; @@ -388,6 +396,17 @@ UINT16 freetype_get_glyphcount(IDWriteFontFace2 *fontface) return count; } +UINT16 freetype_get_glyphindex(IDWriteFontFace2 *fontface, UINT32 codepoint) +{ + UINT16 glyph; + + EnterCriticalSection(&freetype_cs); + glyph = pFTC_CMapCache_Lookup(cmap_cache, fontface, -1, codepoint); + LeaveCriticalSection(&freetype_cs); + + return glyph; +} + #else /* HAVE_FREETYPE */ BOOL init_freetype(void) @@ -424,4 +443,9 @@ UINT16 freetype_get_glyphcount(IDWriteFontFace2 *fontface) return 0; } +UINT16 freetype_get_glyphindex(IDWriteFontFace2 *fontface, UINT32 codepoint) +{ + return 0; +} + #endif /* HAVE_FREETYPE */ diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index aabc0491eb4..cbc50907787 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -757,106 +757,6 @@ HRESULT opentype_get_font_table(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_ * CMAP **********/ -static int compare_group(const void *a, const void* b) -{ - const DWORD *chr = a; - const CMAP_SegmentedCoverage_group *group = b; - - if (*chr < GET_BE_DWORD(group->startCharCode)) - return -1; - if (*chr > GET_BE_DWORD(group->endCharCode)) - return 1; - return 0; -} - -static void CMAP4_GetGlyphIndex(CMAP_SegmentMapping_0* format, UINT32 utf32c, UINT16 *pgi) -{ - WORD *startCode; - SHORT *idDelta; - WORD *idRangeOffset; - int segment; - - int segment_count = GET_BE_WORD(format->segCountX2)/2; - /* This is correct because of the padding before startCode */ - startCode = (WORD*)((BYTE*)format + sizeof(CMAP_SegmentMapping_0) + (sizeof(WORD) * segment_count)); - idDelta = (SHORT*)(((BYTE*)startCode) + (sizeof(WORD) * segment_count)); - idRangeOffset = (WORD*)(((BYTE*)idDelta) + (sizeof(WORD) * segment_count)); - - segment = 0; - while(GET_BE_WORD(format->endCode[segment]) < 0xffff) - { - if (utf32c <= GET_BE_WORD(format->endCode[segment])) - break; - segment++; - } - if (segment >= segment_count) - return; - TRACE("Segment %i of %i\n",segment, segment_count); - if (GET_BE_WORD(startCode[segment]) > utf32c) - return; - TRACE("In range %i -> %i\n", GET_BE_WORD(startCode[segment]), GET_BE_WORD(format->endCode[segment])); - if (GET_BE_WORD(idRangeOffset[segment]) == 0) - { - *pgi = (SHORT)(GET_BE_WORD(idDelta[segment])) + utf32c; - } - else - { - WORD ro = GET_BE_WORD(idRangeOffset[segment])/2; - WORD co = (utf32c - GET_BE_WORD(startCode[segment])); - WORD *index = (WORD*)((BYTE*)&idRangeOffset[segment] + (ro + co)); - *pgi = GET_BE_WORD(*index); - } -} - -static void CMAP12_GetGlyphIndex(CMAP_SegmentedCoverage* format, UINT32 utf32c, UINT16 *pgi) -{ - CMAP_SegmentedCoverage_group *group; - - group = bsearch(&utf32c, format->groups, GET_BE_DWORD(format->nGroups), - sizeof(CMAP_SegmentedCoverage_group), compare_group); - - if (group) - { - DWORD offset = utf32c - GET_BE_DWORD(group->startCharCode); - *pgi = GET_BE_DWORD(group->startGlyphID) + offset; - } -} - -void opentype_cmap_get_glyphindex(void *data, UINT32 utf32c, UINT16 *pgi) -{ - CMAP_Header *CMAP_Table = data; - int i; - - *pgi = 0; - - for (i = 0; i < GET_BE_WORD(CMAP_Table->numTables); i++) - { - WORD type; - WORD *table; - - if (GET_BE_WORD(CMAP_Table->tables[i].platformID) != 3) - continue; - - table = (WORD*)(((BYTE*)CMAP_Table) + GET_BE_DWORD(CMAP_Table->tables[i].offset)); - type = GET_BE_WORD(*table); - TRACE("table type %i\n", type); - - switch (type) - { - case OPENTYPE_CMAP_TABLE_SEGMENT_MAPPING: - CMAP4_GetGlyphIndex((CMAP_SegmentMapping_0*) table, utf32c, pgi); - break; - case OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE: - CMAP12_GetGlyphIndex((CMAP_SegmentedCoverage*) table, utf32c, pgi); - break; - default: - TRACE("table type %i unhandled.\n", type); - } - - if (*pgi) return; - } -} - static UINT32 opentype_cmap_get_unicode_ranges_count(const CMAP_Header *CMAP_Table) { UINT32 count = 0;