dwrite: Implement GetMetrics() for IDWriteFont (try2)

Nikolay Sivov nsivov at codeweavers.com
Tue Oct 16 04:58:33 CDT 2012


try2: Tahoma is used for font tests now
-------------- next part --------------
>From 66e508d33ea0d2545de929fa9b90ee3157be1d83 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue, 16 Oct 2012 12:56:23 -0400
Subject: [PATCH 3/3] Implement GetMetrics() for IDWriteFont

---
 dlls/dwrite/font.c       |   69 +++++++++++++++++++++++++++++++-
 dlls/dwrite/tests/font.c |  100 +++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 153 insertions(+), 16 deletions(-)

diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index d145df0..90131b8 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -31,6 +31,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
 #include "pshpack2.h"
 typedef struct
 {
+    ULONG version;
+    ULONG revision;
+    ULONG checksumadj;
+    ULONG magic;
+    USHORT flags;
+    USHORT unitsPerEm;
+    ULONGLONG created;
+    ULONGLONG modified;
+    SHORT xMin;
+    SHORT yMin;
+    SHORT xMax;
+    SHORT yMax;
+    USHORT macStyle;
+    USHORT lowestRecPPEM;
+    SHORT direction_hint;
+    SHORT index_format;
+    SHORT glyphdata_format;
+} TT_HEAD;
+
+typedef struct
+{
+    ULONG Version;
+    ULONG italicAngle;
+    SHORT underlinePosition;
+    SHORT underlineThickness;
+    ULONG fixed_pitch;
+    ULONG minmemType42;
+    ULONG maxmemType42;
+    ULONG minmemType1;
+    ULONG maxmemType1;
+} TT_POST;
+
+typedef struct
+{
     USHORT version;
     SHORT xAvgCharWidth;
     USHORT usWeightClass;
@@ -88,7 +122,10 @@ typedef struct
 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
-#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
+
+#define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
+#define MS_OS2_TAG  MS_MAKE_TAG('O','S','/','2')
+#define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
 
 struct dwrite_fontfamily {
     IDWriteFontFamily IDWriteFontFamily_iface;
@@ -106,6 +143,7 @@ struct dwrite_font {
     DWRITE_FONT_STYLE style;
     DWRITE_FONT_STRETCH stretch;
     DWRITE_FONT_WEIGHT weight;
+    DWRITE_FONT_METRICS metrics;
 };
 
 struct dwrite_fontface {
@@ -423,7 +461,9 @@ static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *ifa
 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
 {
     struct dwrite_font *This = impl_from_IDWriteFont(iface);
-    FIXME("(%p)->(%p): stub\n", This, metrics);
+
+    TRACE("(%p)->(%p)\n", This, metrics);
+    *metrics = This->metrics;
 }
 
 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
@@ -595,12 +635,16 @@ static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **fa
 static void get_font_properties(struct dwrite_font *font, HDC hdc)
 {
     TT_OS2_V2 tt_os2;
+    TT_HEAD tt_head;
+    TT_POST tt_post;
     LONG size;
 
     /* default stretch and weight to normal */
     font->stretch = DWRITE_FONT_STRETCH_NORMAL;
     font->weight = DWRITE_FONT_WEIGHT_NORMAL;
 
+    memset(&font->metrics, 0, sizeof(font->metrics));
+
     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
     if (size != GDI_ERROR)
     {
@@ -615,6 +659,27 @@ static void get_font_properties(struct dwrite_font *font, HDC hdc)
 
         font->weight = GET_BE_WORD(tt_os2.usWeightClass);
         TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
+
+        font->metrics.ascent    = GET_BE_WORD(tt_os2.sTypoAscender);
+        font->metrics.descent   = GET_BE_WORD(tt_os2.sTypoDescender);
+        font->metrics.lineGap   = GET_BE_WORD(tt_os2.sTypoLineGap);
+        font->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
+        font->metrics.xHeight   = GET_BE_WORD(tt_os2.sxHeight);
+        font->metrics.strikethroughPosition  = GET_BE_WORD(tt_os2.yStrikeoutPosition);
+        font->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
+    }
+
+    memset(&tt_head, 0, sizeof(tt_head));
+    if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
+    {
+        font->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
+    }
+
+    memset(&tt_post, 0, sizeof(tt_post));
+    if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
+    {
+        font->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
+        font->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
     }
 }
 
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 83c19da..594ccea 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -40,10 +40,11 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line)
 
 static IDWriteFactory *factory;
 
+static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
+
 static void test_CreateFontFromLOGFONT(void)
 {
-    static const WCHAR arialW[] = {'A','r','i','a','l',0};
-    static const WCHAR arialspW[] = {'A','r','i','a','l',' ',0};
+    static const WCHAR tahomaspW[] = {'T','a','h','o','m','a',' ',0};
     static const WCHAR blahW[]  = {'B','l','a','h','!',0};
     IDWriteGdiInterop *interop;
     DWRITE_FONT_WEIGHT weight;
@@ -65,9 +66,13 @@ static void test_CreateFontFromLOGFONT(void)
         {950, DWRITE_FONT_WEIGHT_BOLD},
         {960, DWRITE_FONT_WEIGHT_BOLD},
     };
+    OUTLINETEXTMETRICW otm;
     HRESULT hr;
     BOOL ret;
+    HDC hdc;
+    HFONT hfont;
     int i;
+    UINT r;
 
     hr = IDWriteFactory_GetGdiInterop(factory, &interop);
     EXPECT_HR(hr, S_OK);
@@ -84,18 +89,30 @@ if (0)
     logfont.lfWidth  = 12;
     logfont.lfWeight = FW_NORMAL;
     logfont.lfItalic = 1;
-    lstrcpyW(logfont.lfFaceName, arialW);
+    lstrcpyW(logfont.lfFaceName, tahomaW);
 
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
     EXPECT_HR(hr, S_OK);
 
+    hfont = CreateFontIndirectW(&logfont);
+    hdc = CreateCompatibleDC(0);
+    SelectObject(hdc, hfont);
+
+    otm.otmSize = sizeof(otm);
+    r = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
+    ok(r, "got %d\n", r);
+    DeleteDC(hdc);
+    DeleteObject(hfont);
+
     /* now check properties */
     weight = IDWriteFont_GetWeight(font);
     ok(weight == DWRITE_FONT_WEIGHT_NORMAL, "got %d\n", weight);
 
     style = IDWriteFont_GetStyle(font);
-    ok(style == DWRITE_FONT_STYLE_ITALIC, "got %d\n", style);
-
+todo_wine {
+    ok(style == DWRITE_FONT_STYLE_OBLIQUE, "got %d\n", style);
+    ok(otm.otmfsSelection == 1, "got 0x%08x\n", otm.otmfsSelection);
+}
     ret = IDWriteFont_IsSymbolFont(font);
     ok(!ret, "got %d\n", ret);
 
@@ -108,7 +125,7 @@ if (0)
         logfont.lfHeight = 12;
         logfont.lfWidth  = 12;
         logfont.lfWeight = weights[i][0];
-        lstrcpyW(logfont.lfFaceName, arialW);
+        lstrcpyW(logfont.lfFaceName, tahomaW);
 
         hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
         EXPECT_HR(hr, S_OK);
@@ -124,7 +141,7 @@ if (0)
     logfont.lfHeight = 12;
     logfont.lfWidth  = 12;
     logfont.lfWeight = 550;
-    lstrcpyW(logfont.lfFaceName, arialW);
+    lstrcpyW(logfont.lfFaceName, tahomaW);
 
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
     EXPECT_HR(hr, S_OK);
@@ -153,7 +170,7 @@ todo_wine {
     logfont.lfHeight = 12;
     logfont.lfWidth  = 12;
     logfont.lfWeight = FW_NORMAL;
-    lstrcpyW(logfont.lfFaceName, arialspW);
+    lstrcpyW(logfont.lfFaceName, tahomaspW);
 
     font = (void*)0xdeadbeef;
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
@@ -264,7 +281,6 @@ if (0) /* crashes on native */
 
 static void test_GetFontFamily(void)
 {
-    static const WCHAR arialW[] = {'A','r','i','a','l',0};
     IDWriteFontFamily *family, *family2;
     IDWriteGdiInterop *interop;
     IDWriteFont *font;
@@ -279,7 +295,7 @@ static void test_GetFontFamily(void)
     logfont.lfWidth  = 12;
     logfont.lfWeight = FW_NORMAL;
     logfont.lfItalic = 1;
-    lstrcpyW(logfont.lfFaceName, arialW);
+    lstrcpyW(logfont.lfFaceName, tahomaW);
 
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
     EXPECT_HR(hr, S_OK);
@@ -311,7 +327,6 @@ if (0) /* crashes on native */
 
 static void test_GetFamilyNames(void)
 {
-    static const WCHAR arialW[] = {'A','r','i','a','l',0};
     IDWriteFontFamily *family;
     IDWriteLocalizedStrings *names, *names2;
     IDWriteGdiInterop *interop;
@@ -329,7 +344,7 @@ static void test_GetFamilyNames(void)
     logfont.lfWidth  = 12;
     logfont.lfWeight = FW_NORMAL;
     logfont.lfItalic = 1;
-    lstrcpyW(logfont.lfFaceName, arialW);
+    lstrcpyW(logfont.lfFaceName, tahomaW);
 
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
     EXPECT_HR(hr, S_OK);
@@ -404,7 +419,6 @@ if (0)
 
 static void test_CreateFontFace(void)
 {
-    static const WCHAR arialW[] = {'A','r','i','a','l',0};
     IDWriteFontFace *fontface, *fontface2;
     IDWriteGdiInterop *interop;
     IDWriteFont *font;
@@ -419,7 +433,7 @@ static void test_CreateFontFace(void)
     logfont.lfWidth  = 12;
     logfont.lfWeight = FW_NORMAL;
     logfont.lfItalic = 1;
-    lstrcpyW(logfont.lfFaceName, arialW);
+    lstrcpyW(logfont.lfFaceName, tahomaW);
 
     hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -452,6 +466,63 @@ if (0) /* crashes on native */
     IDWriteGdiInterop_Release(interop);
 }
 
+static void test_GetMetrics(void)
+{
+    IDWriteGdiInterop *interop;
+    DWRITE_FONT_METRICS metrics;
+    OUTLINETEXTMETRICW otm;
+    IDWriteFont *font;
+    LOGFONTW logfont;
+    HRESULT hr;
+    HDC hdc;
+    HFONT hfont;
+    int ret;
+
+    hr = IDWriteFactory_GetGdiInterop(factory, &interop);
+    EXPECT_HR(hr, S_OK);
+
+    memset(&logfont, 0, sizeof(logfont));
+    logfont.lfHeight = 12;
+    logfont.lfWidth  = 12;
+    logfont.lfWeight = FW_NORMAL;
+    logfont.lfItalic = 1;
+    lstrcpyW(logfont.lfFaceName, tahomaW);
+
+    hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hfont = CreateFontIndirectW(&logfont);
+    hdc = CreateCompatibleDC(0);
+    SelectObject(hdc, hfont);
+
+    otm.otmSize = sizeof(otm);
+    ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
+    ok(ret, "got %d\n", ret);
+    DeleteDC(hdc);
+    DeleteObject(hfont);
+
+if (0) /* crashes on native */
+    IDWriteFont_GetMetrics(font, NULL);
+
+    memset(&metrics, 0, sizeof(metrics));
+    IDWriteFont_GetMetrics(font, &metrics);
+
+    ok(metrics.designUnitsPerEm != 0, "designUnitsPerEm %u\n", metrics.designUnitsPerEm);
+    ok(metrics.ascent != 0, "ascent %u\n", metrics.ascent);
+    ok(metrics.descent != 0, "descent %u\n", metrics.descent);
+todo_wine
+    ok(metrics.lineGap == 0, "lineGap %d\n", metrics.lineGap);
+    ok(metrics.capHeight, "capHeight %u\n", metrics.capHeight);
+    ok(metrics.xHeight != 0, "xHeight %u\n", metrics.xHeight);
+    ok(metrics.underlinePosition < 0, "underlinePosition %d\n", metrics.underlinePosition);
+    ok(metrics.underlineThickness != 0, "underlineThickness %u\n", metrics.underlineThickness);
+    ok(metrics.strikethroughPosition > 0, "strikethroughPosition %d\n", metrics.strikethroughPosition);
+    ok(metrics.strikethroughThickness != 0, "strikethroughThickness %u\n", metrics.strikethroughThickness);
+
+    IDWriteFont_Release(font);
+    IDWriteGdiInterop_Release(interop);
+}
+
 START_TEST(font)
 {
     HRESULT hr;
@@ -469,6 +540,7 @@ START_TEST(font)
     test_GetFontFamily();
     test_GetFamilyNames();
     test_CreateFontFace();
+    test_GetMetrics();
 
     IDWriteFactory_Release(factory);
 }
-- 
1.7.10.4



More information about the wine-patches mailing list