dwrite: Use FreeType CMAP cache system instead of parsing tables manually.

This commit is contained in:
Nikolay Sivov 2015-02-20 13:47:30 +03:00 committed by Alexandre Julliard
parent efe4be6571
commit 6ff14a9213
4 changed files with 28 additions and 109 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;