[PATCH 2/5] dwrite: Fix lfItalic flag as returned by ConvertFontToLOGFONT()

Nikolay Sivov nsivov at codeweavers.com
Sun Dec 4 10:22:13 CST 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |   2 +
 dlls/dwrite/font.c           |  20 ++++++
 dlls/dwrite/gdiinterop.c     |   7 +-
 dlls/dwrite/opentype.c       |   9 ++-
 dlls/dwrite/tests/font.c     | 157 ++++++++++++++++++++++++++++++++++---------
 5 files changed, 155 insertions(+), 40 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index dad0f47..77b6c4a 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -200,6 +200,7 @@ extern HRESULT create_fontfacereference(IDWriteFactory4*,IDWriteFontFile*,UINT32
 extern HRESULT factory_get_cached_fontface(IDWriteFactory4*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace**,
     struct list**) DECLSPEC_HIDDEN;
 extern void    factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN;
+extern void    get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
 
 /* Opentype font table functions */
 struct dwrite_font_props {
@@ -207,6 +208,7 @@ struct dwrite_font_props {
     DWRITE_FONT_STRETCH stretch;
     DWRITE_FONT_WEIGHT weight;
     DWRITE_PANOSE panose;
+    LOGFONTW lf;
 };
 
 struct file_stream_desc {
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 76a90bd..356000c 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -19,6 +19,8 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+
+#include <assert.h>
 #include <math.h>
 
 #define COBJMACROS
@@ -90,6 +92,8 @@ struct dwrite_font_data {
 
     USHORT simulations;
 
+    LOGFONTW lf;
+
     /* used to mark font as tested when scanning for simulation candidate */
     BOOL bold_sim_tested : 1;
     BOOL oblique_sim_tested : 1;
@@ -1673,6 +1677,20 @@ static const IDWriteFont3Vtbl dwritefontvtbl = {
     dwritefont3_GetLocality
 };
 
+static struct dwrite_font *unsafe_impl_from_IDWriteFont(IDWriteFont *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == (IDWriteFontVtbl*)&dwritefontvtbl);
+    return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont3_iface);
+}
+
+void get_logfont_from_font(IDWriteFont *iface, LOGFONTW *lf)
+{
+    struct dwrite_font *font = unsafe_impl_from_IDWriteFont(iface);
+    *lf = font->data->lf;
+}
+
 static HRESULT create_font(struct dwrite_font_data *data, IDWriteFontFamily1 *family, IDWriteFont3 **font)
 {
     struct dwrite_font *This;
@@ -3244,6 +3262,7 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized
     data->stretch = props.stretch;
     data->weight = props.weight;
     data->panose = props.panose;
+    data->lf = props.lf;
 
     fontstrings_get_en_string(*family_name, familyW, sizeof(familyW)/sizeof(WCHAR));
     fontstrings_get_en_string(data->names, faceW, sizeof(faceW)/sizeof(WCHAR));
@@ -3446,6 +3465,7 @@ static void fontfamily_add_oblique_simulated_face(struct dwrite_fontfamily_data
 
         if (init_font_data_from_font(family->fonts[regular], DWRITE_FONT_SIMULATIONS_OBLIQUE, facenameW, &obliqueface) == S_OK) {
             obliqueface->oblique_sim_tested = 1;
+            obliqueface->lf.lfItalic = 1;
             fontfamily_add_font(family, obliqueface);
         }
     }
diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c
index 886bebb..e4ef835 100644
--- a/dlls/dwrite/gdiinterop.c
+++ b/dlls/dwrite/gdiinterop.c
@@ -624,11 +624,9 @@ static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop1 *iface,
 {
     struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface);
     static const WCHAR enusW[] = {'e','n','-','u','s',0};
-    DWRITE_FONT_SIMULATIONS simulations;
     IDWriteFontCollection *collection;
     IDWriteLocalizedStrings *name;
     IDWriteFontFamily *family;
-    DWRITE_FONT_STYLE style;
     UINT32 index;
     BOOL exists;
     HRESULT hr;
@@ -654,12 +652,9 @@ static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop1 *iface,
     *is_systemfont = is_system_collection(collection);
     IDWriteFontCollection_Release(collection);
 
-    simulations = IDWriteFont_GetSimulations(font);
-    style = IDWriteFont_GetStyle(font);
-
+    get_logfont_from_font(font, logfont);
     logfont->lfCharSet = DEFAULT_CHARSET;
     logfont->lfWeight = IDWriteFont_GetWeight(font);
-    logfont->lfItalic = style == DWRITE_FONT_STYLE_ITALIC || (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE);
     logfont->lfOutPrecision = OUT_OUTLINE_PRECIS;
     logfont->lfFaceName[0] = 0;
 
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index 3fe4690..e16bf76 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -1285,6 +1285,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
     props->weight = DWRITE_FONT_WEIGHT_NORMAL;
     props->style = DWRITE_FONT_STYLE_NORMAL;
     memset(&props->panose, 0, sizeof(props->panose));
+    memset(&props->lf, 0, sizeof(props->lf));
 
     /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
     if (tt_os2) {
@@ -1306,8 +1307,10 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
 
         if (version >= 4 && (fsSelection & OS2_FSSELECTION_OBLIQUE))
             props->style = DWRITE_FONT_STYLE_OBLIQUE;
-        else if (fsSelection & OS2_FSSELECTION_ITALIC)
+        else if (fsSelection & OS2_FSSELECTION_ITALIC) {
             props->style = DWRITE_FONT_STYLE_ITALIC;
+            props->lf.lfItalic = 1;
+        }
         memcpy(&props->panose, &tt_os2->panose, sizeof(props->panose));
     }
     else if (tt_head) {
@@ -1321,8 +1324,10 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
         if (macStyle & TT_HEAD_MACSTYLE_BOLD)
             props->weight = DWRITE_FONT_WEIGHT_BOLD;
 
-        if (macStyle & TT_HEAD_MACSTYLE_ITALIC)
+        if (macStyle & TT_HEAD_MACSTYLE_ITALIC) {
             props->style = DWRITE_FONT_STYLE_ITALIC;
+            props->lf.lfItalic = 1;
+        }
     }
 
     TRACE("stretch=%d, weight=%d, style %d\n", props->stretch, props->weight, props->style);
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 8df6f44..d3c9d42 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -132,6 +132,17 @@ typedef struct
     SHORT glyphdata_format;
 } TT_HEAD;
 
+enum TT_HEAD_MACSTYLE
+{
+    TT_HEAD_MACSTYLE_BOLD      = 1 << 0,
+    TT_HEAD_MACSTYLE_ITALIC    = 1 << 1,
+    TT_HEAD_MACSTYLE_UNDERLINE = 1 << 2,
+    TT_HEAD_MACSTYLE_OUTLINE   = 1 << 3,
+    TT_HEAD_MACSTYLE_SHADOW    = 1 << 4,
+    TT_HEAD_MACSTYLE_CONDENSED = 1 << 5,
+    TT_HEAD_MACSTYLE_EXTENDED  = 1 << 6,
+};
+
 typedef struct
 {
     USHORT version;
@@ -3445,6 +3456,61 @@ static void test_TryGetFontTable(void)
     DELETE_FONTFILE(path);
 }
 
+static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
+{
+    DWRITE_FONT_STYLE style;
+
+    /* These are rendering time properties. */
+    logfont->lfHeight = 0;
+    logfont->lfWidth = 0;
+    logfont->lfEscapement = 0;
+    logfont->lfOrientation = 0;
+    logfont->lfUnderline = 0;
+    logfont->lfStrikeOut = 0;
+
+    logfont->lfItalic = 0;
+
+    if (IDWriteFont_GetSimulations(font) & DWRITE_FONT_SIMULATIONS_OBLIQUE)
+        logfont->lfItalic = 1;
+
+    style = IDWriteFont_GetStyle(font);
+    if (!logfont->lfItalic && ((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE))) {
+        void *os2_context, *head_context;
+        IDWriteFontFace *fontface;
+        const TT_OS2_V2 *tt_os2;
+        const TT_HEAD *tt_head;
+        UINT32 size;
+        BOOL exists;
+        HRESULT hr;
+
+        hr = IDWriteFont_CreateFontFace(font, &fontface);
+        ok(hr == S_OK, "Failed to create font face, %#x\n", hr);
+
+        hr = IDWriteFontFace_TryGetFontTable(fontface, MS_0S2_TAG, (const void **)&tt_os2, &size,
+            &os2_context, &exists);
+        ok(hr == S_OK, "Failed to get OS/2 table, %#x\n", hr);
+
+        hr = IDWriteFontFace_TryGetFontTable(fontface, MS_HEAD_TAG, (const void **)&tt_head, &size,
+            &head_context, &exists);
+        ok(hr == S_OK, "Failed to get head table, %#x\n", hr);
+
+        if (tt_os2) {
+            USHORT fsSelection = GET_BE_WORD(tt_os2->fsSelection);
+            logfont->lfItalic = !!(fsSelection & OS2_FSSELECTION_ITALIC);
+        }
+        else if (tt_head) {
+            USHORT macStyle = GET_BE_WORD(tt_head->macStyle);
+            logfont->lfItalic = !!(macStyle & TT_HEAD_MACSTYLE_ITALIC);
+        }
+
+        if (tt_os2)
+            IDWriteFontFace_ReleaseFontTable(fontface, os2_context);
+        if (tt_head)
+            IDWriteFontFace_ReleaseFontTable(fontface, head_context);
+        IDWriteFontFace_Release(fontface);
+    }
+}
+
 static void test_ConvertFontToLOGFONT(void)
 {
     IDWriteFactory *factory, *factory2;
@@ -3453,6 +3519,7 @@ static void test_ConvertFontToLOGFONT(void)
     IDWriteFontFamily *family;
     IDWriteFont *font;
     LOGFONTW logfont;
+    UINT32 i, count;
     BOOL system;
     HRESULT hr;
 
@@ -3486,41 +3553,67 @@ if (0) { /* crashes on native */
     ok(!system, "got %d\n", system);
     ok(logfont.lfFaceName[0] == 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
 
-    system = FALSE;
+    count = IDWriteFontCollection_GetFontFamilyCount(collection);
+    for (i = 0; i < count; i++) {
+        WCHAR nameW[128], familynameW[64], facenameW[64];
+        IDWriteLocalizedStrings *names;
+        DWRITE_FONT_SIMULATIONS sim;
+        IDWriteFontFamily *family;
+        UINT32 font_count, j;
+        IDWriteFont *font;
+        LOGFONTW lf;
 
-    logfont.lfHeight = 10;
-    logfont.lfWidth = 11;
-    logfont.lfEscapement = 10;
-    logfont.lfOrientation = 10;
-    logfont.lfWeight = 0;
-    logfont.lfItalic = 1;
-    logfont.lfUnderline = 1;
-    logfont.lfStrikeOut = 1;
-    logfont.lfCharSet = 0;
-    logfont.lfOutPrecision = 0;
-    logfont.lfClipPrecision = 0;
-    logfont.lfQuality = 0;
-    logfont.lfPitchAndFamily = 0;
-    logfont.lfFaceName[0] = 0;
+        hr = IDWriteFontCollection_GetFontFamily(collection, i, &family);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, &logfont, &system);
-    ok(hr == S_OK, "got 0x%08x\n", hr);
-    ok(system, "got %d\n", system);
+        hr = IDWriteFontFamily_GetFamilyNames(family, &names);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
 
-    ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight);
-    ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth);
-    ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement);
-    ok(logfont.lfOrientation == 0, "got %d\n", logfont.lfOrientation);
-    ok(logfont.lfWeight > 0, "got %d\n", logfont.lfWeight);
-    ok(logfont.lfItalic == 0, "got %d\n", logfont.lfItalic);
-    ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline);
-    ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut);
-    ok(logfont.lfCharSet == DEFAULT_CHARSET, "got %d\n", logfont.lfCharSet);
-    ok(logfont.lfOutPrecision == OUT_OUTLINE_PRECIS, "got %d\n", logfont.lfOutPrecision);
-    ok(logfont.lfClipPrecision == 0, "got %d\n", logfont.lfClipPrecision);
-    ok(logfont.lfQuality == 0, "got %d\n", logfont.lfQuality);
-    ok(logfont.lfPitchAndFamily == 0, "got %d\n", logfont.lfPitchAndFamily);
-    ok(logfont.lfFaceName[0] != 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
+        get_enus_string(names, familynameW, sizeof(familynameW)/sizeof(familynameW[0]));
+        IDWriteLocalizedStrings_Release(names);
+
+        font_count = IDWriteFontFamily_GetFontCount(family);
+
+        for (j = 0; j < font_count; j++) {
+            static const WCHAR spaceW[] = {' ', 0};
+
+            hr = IDWriteFontFamily_GetFont(family, j, &font);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+
+            hr = IDWriteFont_GetFaceNames(font, &names);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+
+            get_enus_string(names, facenameW, sizeof(facenameW)/sizeof(facenameW[0]));
+            IDWriteLocalizedStrings_Release(names);
+
+            lstrcpyW(nameW, familynameW);
+            lstrcatW(nameW, spaceW);
+            lstrcatW(nameW, facenameW);
+
+            system = FALSE;
+            memset(&logfont, 0xcc, sizeof(logfont));
+            hr = IDWriteGdiInterop_ConvertFontToLOGFONT(interop, font, &logfont, &system);
+            ok(hr == S_OK, "got 0x%08x\n", hr);
+            ok(system, "got %d\n", system);
+
+            sim = IDWriteFont_GetSimulations(font);
+
+            get_logfont_from_font(font, &lf);
+            ok(logfont.lfItalic == lf.lfItalic, "%s: unexpected italic flag %d, oblique simulation %s\n",
+                wine_dbgstr_w(nameW), logfont.lfItalic, sim & DWRITE_FONT_SIMULATIONS_OBLIQUE ? "yes" : "no");
+
+            ok(logfont.lfWeight > 0, "got %d\n", logfont.lfWeight);
+            ok(logfont.lfOutPrecision == OUT_OUTLINE_PRECIS, "got %d\n", logfont.lfOutPrecision);
+            ok(logfont.lfClipPrecision == 0, "got %d\n", logfont.lfClipPrecision);
+            ok(logfont.lfQuality == 0, "got %d\n", logfont.lfQuality);
+            ok(logfont.lfPitchAndFamily == 0, "got %d\n", logfont.lfPitchAndFamily);
+            ok(logfont.lfFaceName[0] != 0, "got face name %s\n", wine_dbgstr_w(logfont.lfFaceName));
+
+            IDWriteFont_Release(font);
+        }
+
+        IDWriteFontFamily_Release(family);
+    }
 
     IDWriteFactory_Release(factory2);
 
-- 
2.10.2




More information about the wine-patches mailing list