[PATCH 2/5] dwrite: Evaluate IsSymbolFont() flag at font level.

Nikolay Sivov nsivov at codeweavers.com
Thu Jan 23 03:24:12 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 875f12916b..76cf40cd1f 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 25b09feb07..f2b8655003 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 ffc97f1d8a..3c54da27f9 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 c5f1d16fac..02a71b3528 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 d7bcfb1f0a..33603f6571 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);
 
-- 
2.24.1




More information about the wine-devel mailing list