From 0b0a2ce8fdba62199c979f6f03bb9d374da48e45 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 23 Jan 2020 12:24:12 +0300 Subject: [PATCH] dwrite: Evaluate IsSymbolFont() flag at font level. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 16 +++++++++-- dlls/dwrite/font.c | 42 +++++++++++---------------- dlls/dwrite/freetype.c | 23 ++++----------- dlls/dwrite/opentype.c | 55 ++++++++++++++++++++++++++++++++---- dlls/dwrite/tests/font.c | 13 +++------ 5 files changed, 88 insertions(+), 61 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 875f12916bc..76cf40cd1f7 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -183,6 +183,14 @@ struct fontfacecached #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) #define GLYPH_MAX 65536 +enum font_flags +{ + FONT_IS_SYMBOL = 1 << 0, + FONTFACE_IS_MONOSPACED = 1 << 1, + FONTFACE_HAS_KERNING_PAIRS = 1 << 2, + FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3 +}; + struct dwrite_fontface { IDWriteFontFace5 IDWriteFontFace5_iface; @@ -206,7 +214,7 @@ struct dwrite_fontface unsigned int descent; } typo_metrics; INT charmap; - UINT16 flags; + UINT32 flags; struct dwrite_fonttable cmap; struct dwrite_fonttable vdmx; @@ -291,13 +299,15 @@ extern float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface extern struct dwrite_fontface *unsafe_impl_from_IDWriteFontFace(IDWriteFontFace *iface) DECLSPEC_HIDDEN; /* Opentype font table functions */ -struct dwrite_font_props { +struct dwrite_font_props +{ DWRITE_FONT_STYLE style; DWRITE_FONT_STRETCH stretch; DWRITE_FONT_WEIGHT weight; DWRITE_PANOSE panose; FONTSIGNATURE fontsig; LOGFONTW lf; + UINT32 flags; }; struct file_stream_desc { @@ -392,7 +402,7 @@ extern BOOL freetype_has_kerning_pairs(IDWriteFontFace5 *fontface) DECLSPEC_HIDD extern INT32 freetype_get_kerning_pair_adjustment(IDWriteFontFace5 *fontface, UINT16 left, UINT16 right) DECLSPEC_HIDDEN; extern void freetype_get_glyph_bbox(struct dwrite_glyphbitmap *bitmap_desc) DECLSPEC_HIDDEN; extern BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap*) DECLSPEC_HIDDEN; -extern INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) DECLSPEC_HIDDEN; +extern INT freetype_get_charmap_index(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN; extern INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emsize, UINT16 index, DWRITE_MEASURING_MODE measuring_mode, BOOL *has_contours) DECLSPEC_HIDDEN; extern void freetype_get_design_glyph_bbox(IDWriteFontFace4*,UINT16,UINT16,RECT*) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 25b09feb070..f2b86550032 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -69,7 +69,8 @@ struct dwrite_font_propvec { FLOAT weight; }; -struct dwrite_font_data { +struct dwrite_font_data +{ LONG ref; DWRITE_FONT_STYLE style; @@ -77,6 +78,7 @@ struct dwrite_font_data { DWRITE_FONT_WEIGHT weight; DWRITE_PANOSE panose; FONTSIGNATURE fontsig; + UINT32 flags; /* enum font_flags */ struct dwrite_font_propvec propvec; DWRITE_FONT_METRICS1 metrics; @@ -206,13 +208,6 @@ struct dwrite_colorglyphenum #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) #define GLYPH_MAX 65536 -enum fontface_flags { - FONTFACE_IS_SYMBOL = 1 << 0, - FONTFACE_IS_MONOSPACED = 1 << 1, - FONTFACE_HAS_KERNING_PAIRS = 1 << 2, - FONTFACE_HAS_VERTICAL_VARIANTS = 1 << 3 -}; - struct dwrite_fontfile { IDWriteFontFile IDWriteFontFile_iface; LONG ref; @@ -621,7 +616,7 @@ static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace5 *iface) TRACE("%p.\n", iface); - return !!(fontface->flags & FONTFACE_IS_SYMBOL); + return !!(fontface->flags & FONT_IS_SYMBOL); } static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace5 *iface, DWRITE_FONT_METRICS *metrics) @@ -1618,19 +1613,10 @@ static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont3 *iface) static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface) { struct dwrite_font *font = impl_from_IDWriteFont3(iface); - IDWriteFontFace5 *fontface; - HRESULT hr; - BOOL ret; TRACE("%p.\n", iface); - hr = get_fontface_from_font(font, &fontface); - if (FAILED(hr)) - return FALSE; - - ret = IDWriteFontFace5_IsSymbolFont(fontface); - IDWriteFontFace5_Release(fontface); - return ret; + return !!(font->data->flags & FONT_IS_SYMBOL); } static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont3 *iface, IDWriteLocalizedStrings **names) @@ -3695,6 +3681,7 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized data->panose = props.panose; data->fontsig = props.fontsig; data->lf = props.lf; + data->flags = props.flags; fontstrings_get_en_string(*family_name, familyW, ARRAY_SIZE(familyW)); fontstrings_get_en_string(data->names, faceW, ARRAY_SIZE(faceW)); @@ -4651,8 +4638,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li { struct file_stream_desc stream_desc; struct dwrite_fontface *fontface; - HRESULT hr = S_OK; - BOOL is_symbol; + HRESULT hr; int i; *ret = NULL; @@ -4701,9 +4687,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li } } - fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace5_iface, &is_symbol); - if (is_symbol) - fontface->flags |= FONTFACE_IS_SYMBOL; + fontface->charmap = freetype_get_charmap_index(&fontface->IDWriteFontFace5_iface); if (freetype_has_kerning_pairs(&fontface->IDWriteFontFace5_iface)) fontface->flags |= FONTFACE_HAS_KERNING_PAIRS; if (freetype_is_monospaced(&fontface->IDWriteFontFace5_iface)) @@ -4717,15 +4701,19 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li If face is created directly from factory we have to go through properties resolution. */ - if (desc->font_data) { + if (desc->font_data) + { fontface->weight = desc->font_data->weight; fontface->style = desc->font_data->style; fontface->stretch = desc->font_data->stretch; fontface->panose = desc->font_data->panose; fontface->fontsig = desc->font_data->fontsig; fontface->lf = desc->font_data->lf; + if (desc->font_data->flags & FONT_IS_SYMBOL) + fontface->flags |= FONT_IS_SYMBOL; } - else { + else + { IDWriteLocalizedStrings *names; struct dwrite_font_data *data; @@ -4742,6 +4730,8 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li fontface->panose = data->panose; fontface->fontsig = data->fontsig; fontface->lf = data->lf; + if (data->flags & FONT_IS_SYMBOL) + fontface->flags |= FONT_IS_SYMBOL; IDWriteLocalizedStrings_Release(names); release_font_data(data); diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index ffc97f1d8a3..3c54da27f9c 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -855,29 +855,19 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) return ret; } -INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) +INT freetype_get_charmap_index(IDWriteFontFace5 *fontface) { INT charmap_index = -1; FT_Face face; - *is_symbol = FALSE; - EnterCriticalSection(&freetype_cs); - if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0) { - TT_OS2 *os2 = pFT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (pFTC_Manager_LookupFace(cache_manager, fontface, &face) == 0) + { FT_Int i; - if (os2) { - FT_UInt dummy; - if (os2->version == 0) - *is_symbol = pFT_Get_First_Char(face, &dummy) >= 0x100; - else - *is_symbol = !!(os2->ulCodePageRange1 & FS_SYMBOL); - } - for (i = 0; i < face->num_charmaps; i++) - if (face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL) { - *is_symbol = TRUE; + if (face->charmaps[i]->encoding == FT_ENCODING_MS_SYMBOL) + { charmap_index = i; break; } @@ -978,9 +968,8 @@ BOOL freetype_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap) return FALSE; } -INT freetype_get_charmap_index(IDWriteFontFace5 *fontface, BOOL *is_symbol) +INT freetype_get_charmap_index(IDWriteFontFace5 *fontface) { - *is_symbol = FALSE; return -1; } diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c index c5f1d16fac5..02a71b35283 100644 --- a/dlls/dwrite/opentype.c +++ b/dlls/dwrite/opentype.c @@ -44,6 +44,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); #define MS_SBIX_TAG DWRITE_MAKE_OPENTYPE_TAG('s','b','i','x') #define MS_MAXP_TAG DWRITE_MAKE_OPENTYPE_TAG('m','a','x','p') #define MS_CBLC_TAG DWRITE_MAKE_OPENTYPE_TAG('C','B','L','C') +#define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p') /* 'sbix' formats */ #define MS_PNG__TAG DWRITE_MAKE_OPENTYPE_TAG('p','n','g',' ') @@ -131,6 +132,18 @@ enum OPENTYPE_CMAP_TABLE_FORMAT OPENTYPE_CMAP_TABLE_SEGMENTED_COVERAGE = 12 }; +enum opentype_cmap_table_platform +{ + OPENTYPE_CMAP_TABLE_PLATFORM_WIN = 3, +}; + +enum opentype_cmap_table_encoding +{ + OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL = 0, + OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_BMP = 1, + OPENTYPE_CMAP_TABLE_ENCODING_UNICODE_FULL = 10, +}; + /* PANOSE is 10 bytes in size, need to pack the structure properly */ #include "pshpack2.h" typedef struct @@ -1705,6 +1718,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d struct dwrite_fonttable os2, head; const TT_OS2_V2 *tt_os2; const TT_HEAD *tt_head; + BOOL is_symbol; opentype_get_font_table(stream_desc, MS_OS2_TAG, &os2); opentype_get_font_table(stream_desc, MS_HEAD_TAG, &head); @@ -1721,7 +1735,8 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d memset(&props->lf, 0, sizeof(props->lf)); /* DWRITE_FONT_STRETCH enumeration values directly match font data values */ - if (tt_os2) { + if (tt_os2) + { USHORT version = GET_BE_WORD(tt_os2->version); USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection); USHORT usWeightClass = GET_BE_WORD(tt_os2->usWeightClass); @@ -1752,11 +1767,8 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d props->fontsig.fsUsb[2] = GET_BE_DWORD(tt_os2->ulUnicodeRange3); props->fontsig.fsUsb[3] = GET_BE_DWORD(tt_os2->ulUnicodeRange4); - if (GET_BE_WORD(tt_os2->version) == 0) { - props->fontsig.fsCsb[0] = 0; - props->fontsig.fsCsb[1] = 0; - } - else { + if (version) + { props->fontsig.fsCsb[0] = GET_BE_DWORD(tt_os2->ulCodePageRange1); props->fontsig.fsCsb[1] = GET_BE_DWORD(tt_os2->ulCodePageRange2); } @@ -1780,6 +1792,37 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d props->lf.lfWeight = props->weight; + if (!(is_symbol = props->panose.familyKind == DWRITE_PANOSE_FAMILY_SYMBOL)) + { + struct dwrite_fonttable cmap; + int i, offset, num_tables; + + opentype_get_font_table(stream_desc, MS_CMAP_TAG, &cmap); + + if (cmap.data) + { + num_tables = table_read_be_word(&cmap, FIELD_OFFSET(struct cmap_header, num_tables)); + offset = FIELD_OFFSET(struct cmap_header, tables); + + for (i = 0; !is_symbol && i < num_tables; ++i) + { + WORD platform, encoding; + + platform = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) + + FIELD_OFFSET(struct cmap_encoding_record, platformID)); + encoding = table_read_be_word(&cmap, offset + i * sizeof(struct cmap_encoding_record) + + FIELD_OFFSET(struct cmap_encoding_record, encodingID)); + + is_symbol = platform == OPENTYPE_CMAP_TABLE_PLATFORM_WIN && + encoding == OPENTYPE_CMAP_TABLE_ENCODING_SYMBOL; + } + + IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, cmap.context); + } + } + if (is_symbol) + props->flags |= FONT_IS_SYMBOL; + TRACE("stretch=%d, weight=%d, style %d\n", props->stretch, props->weight, props->style); if (os2.data) diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index d7bcfb1f0ab..33603f65719 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -406,7 +406,7 @@ struct cmap_encoding_record struct cmap_header { WORD version; - WORD numTables; + WORD num_tables; struct cmap_encoding_record tables[1]; }; @@ -3544,7 +3544,7 @@ static UINT32 opentype_cmap_get_unicode_ranges(const struct dwrite_fonttable *ta *ranges = NULL; - num_tables = table_read_be_word(table, 0, FIELD_OFFSET(struct cmap_header, numTables)); + num_tables = table_read_be_word(table, 0, FIELD_OFFSET(struct cmap_header, num_tables)); tables = table->data + FIELD_OFFSET(struct cmap_header, tables); for (i = 0; i < num_tables; ++i) @@ -7260,10 +7260,7 @@ static BOOL get_expected_is_symbol(IDWriteFontFace *fontface) if (tt_os2) { - if (tt_os2->version) - is_symbol = !!(GET_BE_DWORD(tt_os2->ulCodePageRange1) & FS_SYMBOL); - if (!is_symbol) - is_symbol = tt_os2->panose.bFamilyType == PAN_FAMILY_PICTORIAL; + is_symbol = tt_os2->panose.bFamilyType == PAN_FAMILY_PICTORIAL; IDWriteFontFace_ReleaseFontTable(fontface, os2_context); } @@ -7275,7 +7272,7 @@ static BOOL get_expected_is_symbol(IDWriteFontFace *fontface) if (FAILED(hr) || !exists) return is_symbol; - num_tables = table_read_be_word(&cmap, 0, FIELD_OFFSET(struct cmap_header, numTables)); + num_tables = table_read_be_word(&cmap, 0, FIELD_OFFSET(struct cmap_header, num_tables)); tables = cmap.data + FIELD_OFFSET(struct cmap_header, tables); for (i = 0; i < num_tables; ++i) @@ -7345,9 +7342,7 @@ static void test_IsSymbolFont(void) is_symbol_face = IDWriteFontFace_IsSymbolFont(fontface); ok(is_symbol_font == is_symbol_face, "Unexpected symbol flag.\n"); - /* FIXME: failures disabled on Wine for now */ is_symbol_expected = get_expected_is_symbol(fontface); - todo_wine_if(is_symbol_expected != is_symbol_face) ok(is_symbol_expected == is_symbol_face, "Unexpected is_symbol flag %d for %s, font %d.\n", is_symbol_face, wine_dbgstr_w(nameW), j);