dwrite: Use FreeType CMAP cache system instead of parsing tables manually.
This commit is contained in:
parent
efe4be6571
commit
6ff14a9213
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue