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 */
|
/* 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_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 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 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*,
|
extern void opentype_get_font_properties(IDWriteFontFileStream*,DWRITE_FONT_FACE_TYPE,UINT32,DWRITE_FONT_STRETCH*,
|
||||||
DWRITE_FONT_WEIGHT*,DWRITE_FONT_STYLE*) DECLSPEC_HIDDEN;
|
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 BOOL freetype_is_monospaced(IDWriteFontFace2*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT freetype_get_glyph_outline(IDWriteFontFace2*,FLOAT,UINT16,USHORT,struct glyph_outline**) 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_glyphcount(IDWriteFontFace2*) DECLSPEC_HIDDEN;
|
||||||
|
extern UINT16 freetype_get_glyphindex(IDWriteFontFace2*,UINT32) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Glyph shaping */
|
/* Glyph shaping */
|
||||||
enum SCRIPT_JUSTIFY
|
enum SCRIPT_JUSTIFY
|
||||||
|
|
|
@ -388,17 +388,12 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UI
|
||||||
UINT32 count, UINT16 *glyph_indices)
|
UINT32 count, UINT16 *glyph_indices)
|
||||||
{
|
{
|
||||||
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
|
||||||
unsigned int i;
|
UINT32 i;
|
||||||
void *data;
|
|
||||||
|
|
||||||
TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
|
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++)
|
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;
|
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 void *ft_handle = NULL;
|
||||||
static FT_Library library = 0;
|
static FT_Library library = 0;
|
||||||
static FTC_Manager cache_manager = 0;
|
static FTC_Manager cache_manager = 0;
|
||||||
|
static FTC_CMapCache cmap_cache = 0;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FT_Int major;
|
FT_Int major;
|
||||||
|
@ -67,6 +68,8 @@ MAKE_FUNCPTR(FT_Library_Version);
|
||||||
MAKE_FUNCPTR(FT_Load_Glyph);
|
MAKE_FUNCPTR(FT_Load_Glyph);
|
||||||
MAKE_FUNCPTR(FT_New_Memory_Face);
|
MAKE_FUNCPTR(FT_New_Memory_Face);
|
||||||
MAKE_FUNCPTR(FT_Outline_Transform);
|
MAKE_FUNCPTR(FT_Outline_Transform);
|
||||||
|
MAKE_FUNCPTR(FTC_CMapCache_Lookup);
|
||||||
|
MAKE_FUNCPTR(FTC_CMapCache_New);
|
||||||
MAKE_FUNCPTR(FTC_Manager_New);
|
MAKE_FUNCPTR(FTC_Manager_New);
|
||||||
MAKE_FUNCPTR(FTC_Manager_Done);
|
MAKE_FUNCPTR(FTC_Manager_Done);
|
||||||
MAKE_FUNCPTR(FTC_Manager_LookupFace);
|
MAKE_FUNCPTR(FTC_Manager_LookupFace);
|
||||||
|
@ -137,6 +140,8 @@ BOOL init_freetype(void)
|
||||||
LOAD_FUNCPTR(FT_Load_Glyph)
|
LOAD_FUNCPTR(FT_Load_Glyph)
|
||||||
LOAD_FUNCPTR(FT_New_Memory_Face)
|
LOAD_FUNCPTR(FT_New_Memory_Face)
|
||||||
LOAD_FUNCPTR(FT_Outline_Transform)
|
LOAD_FUNCPTR(FT_Outline_Transform)
|
||||||
|
LOAD_FUNCPTR(FTC_CMapCache_Lookup)
|
||||||
|
LOAD_FUNCPTR(FTC_CMapCache_New)
|
||||||
LOAD_FUNCPTR(FTC_Manager_New)
|
LOAD_FUNCPTR(FTC_Manager_New)
|
||||||
LOAD_FUNCPTR(FTC_Manager_Done)
|
LOAD_FUNCPTR(FTC_Manager_Done)
|
||||||
LOAD_FUNCPTR(FTC_Manager_LookupFace)
|
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);
|
pFT_Library_Version(library, &FT_Version.major, &FT_Version.minor, &FT_Version.patch);
|
||||||
|
|
||||||
/* init cache manager */
|
/* 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");
|
ERR("Failed to init FreeType cache\n");
|
||||||
|
pFTC_Manager_Done(cache_manager);
|
||||||
pFT_Done_FreeType(library);
|
pFT_Done_FreeType(library);
|
||||||
wine_dlclose(ft_handle, NULL, 0);
|
wine_dlclose(ft_handle, NULL, 0);
|
||||||
ft_handle = NULL;
|
ft_handle = NULL;
|
||||||
|
@ -388,6 +396,17 @@ UINT16 freetype_get_glyphcount(IDWriteFontFace2 *fontface)
|
||||||
return count;
|
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 */
|
#else /* HAVE_FREETYPE */
|
||||||
|
|
||||||
BOOL init_freetype(void)
|
BOOL init_freetype(void)
|
||||||
|
@ -424,4 +443,9 @@ UINT16 freetype_get_glyphcount(IDWriteFontFace2 *fontface)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT16 freetype_get_glyphindex(IDWriteFontFace2 *fontface, UINT32 codepoint)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_FREETYPE */
|
#endif /* HAVE_FREETYPE */
|
||||||
|
|
|
@ -757,106 +757,6 @@ HRESULT opentype_get_font_table(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_
|
||||||
* CMAP
|
* 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)
|
static UINT32 opentype_cmap_get_unicode_ranges_count(const CMAP_Header *CMAP_Table)
|
||||||
{
|
{
|
||||||
UINT32 count = 0;
|
UINT32 count = 0;
|
||||||
|
|
Loading…
Reference in New Issue