Huw Davies : dwrite/tests: Add tests for GetGdiCompatibleMetrics.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jul 6 06:37:36 CDT 2015


Module: wine
Branch: master
Commit: bbf5b249ca882df07b326b50027d27baa5b586c8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bbf5b249ca882df07b326b50027d27baa5b586c8

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri Jul  3 15:53:07 2015 +0100

dwrite/tests: Add tests for GetGdiCompatibleMetrics.

---

 dlls/dwrite/tests/font.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 221 insertions(+), 4 deletions(-)

diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 111762c..d3ac83c 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -19,9 +19,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <math.h>
+
 #define COBJMACROS
 
 #include "windows.h"
+#include "winternl.h"
 #include "dwrite_2.h"
 #include "initguid.h"
 #include "d2d1.h"
@@ -33,6 +36,7 @@
                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
 
 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
+#define MS_VDMX_TAG MS_MAKE_TAG('V','D','M','X')
 
 #define EXPECT_HR(hr,hr_exp) \
     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
@@ -87,6 +91,7 @@ static inline BOOL heap_free(void *mem)
 
 static const WCHAR test_fontfile[] = {'w','i','n','e','_','t','e','s','t','_','f','o','n','t','.','t','t','f',0};
 static const WCHAR tahomaW[] = {'T','a','h','o','m','a',0};
+static const WCHAR arialW[] = {'A','r','i','a','l',0};
 static const WCHAR tahomaUppercaseW[] = {'T','A','H','O','M','A',0};
 static const WCHAR tahomaStrangecaseW[] = {'t','A','h','O','m','A',0};
 static const WCHAR blahW[]  = {'B','l','a','h','!',0};
@@ -2255,11 +2260,11 @@ static void test_GetFontFromFontFace(void)
     DELETE_FONTFILE(path);
 }
 
-static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STYLE style)
+static IDWriteFont *get_font(IDWriteFactory *factory, const WCHAR *name, DWRITE_FONT_STYLE style)
 {
     IDWriteFontCollection *collection;
     IDWriteFontFamily *family;
-    IDWriteFont *font;
+    IDWriteFont *font = NULL;
     UINT32 index;
     BOOL exists;
     HRESULT hr;
@@ -2269,9 +2274,9 @@ static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STY
 
     index = ~0;
     exists = FALSE;
-    hr = IDWriteFontCollection_FindFamilyName(collection, tahomaW, &index, &exists);
+    hr = IDWriteFontCollection_FindFamilyName(collection, name, &index, &exists);
     ok(hr == S_OK, "got 0x%08x\n", hr);
-    ok(exists, "got %d\n", exists);
+    if (!exists) goto not_found;
 
     hr = IDWriteFontCollection_GetFontFamily(collection, index, &family);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -2281,10 +2286,18 @@ static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STY
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
     IDWriteFontFamily_Release(family);
+not_found:
     IDWriteFontCollection_Release(collection);
     return font;
 }
 
+static IDWriteFont *get_tahoma_instance(IDWriteFactory *factory, DWRITE_FONT_STYLE style)
+{
+    IDWriteFont *font = get_font(factory, tahomaW, style);
+    ok(font != NULL, "failed to get Tahoma\n");
+    return font;
+}
+
 static void test_GetFirstMatchingFont(void)
 {
     DWRITE_FONT_SIMULATIONS simulations;
@@ -3418,6 +3431,209 @@ static void test_CreateGlyphRunAnalysis(void)
     IDWriteFactory_Release(factory);
 }
 
+#define round(x) ((int)floor((x) + 0.5))
+
+struct VDMX_Header
+{
+    WORD version;
+    WORD numRecs;
+    WORD numRatios;
+};
+
+struct VDMX_Ratio
+{
+    BYTE bCharSet;
+    BYTE xRatio;
+    BYTE yStartRatio;
+    BYTE yEndRatio;
+};
+
+struct VDMX_group
+{
+    WORD recs;
+    BYTE startsz;
+    BYTE endsz;
+};
+
+struct VDMX_vTable
+{
+    WORD yPelHeight;
+    SHORT yMax;
+    SHORT yMin;
+};
+
+#ifdef WORDS_BIGENDIAN
+#define GET_BE_WORD(x) (x)
+#else
+#define GET_BE_WORD(x) RtlUshortByteSwap(x)
+#endif
+
+static const struct VDMX_group *find_vdmx_group(const struct VDMX_Header *hdr)
+{
+    WORD num_ratios, i, group_offset = 0;
+    struct VDMX_Ratio *ratios = (struct VDMX_Ratio*)(hdr + 1);
+    BYTE dev_x_ratio = 1, dev_y_ratio = 1;
+
+    num_ratios = GET_BE_WORD(hdr->numRatios);
+
+    for (i = 0; i < num_ratios; i++)
+    {
+        if (!ratios[i].bCharSet) continue;
+
+        if ((ratios[i].xRatio == 0 && ratios[i].yStartRatio == 0 &&
+             ratios[i].yEndRatio == 0) ||
+	   (ratios[i].xRatio == dev_x_ratio && ratios[i].yStartRatio <= dev_y_ratio &&
+            ratios[i].yEndRatio >= dev_y_ratio))
+        {
+            group_offset = GET_BE_WORD(*((WORD *)(ratios + num_ratios) + i));
+            break;
+        }
+    }
+    if (group_offset)
+        return (const struct VDMX_group *)((BYTE *)hdr + group_offset);
+    return NULL;
+}
+
+static BOOL get_vdmx_size(const struct VDMX_group *group, int emsize, int *a, int *d)
+{
+    WORD recs, i;
+    const struct VDMX_vTable *tables;
+
+    if (!group) return FALSE;
+
+    recs = GET_BE_WORD(group->recs);
+    if (emsize < group->startsz || emsize >= group->endsz) return FALSE;
+
+    tables = (const struct VDMX_vTable *)(group + 1);
+    for (i = 0; i < recs; i++)
+    {
+        WORD ppem = GET_BE_WORD(tables[i].yPelHeight);
+        if (ppem > emsize)
+        {
+            /* FIXME: Supposed to interpolate */
+            trace("FIXME interpolate %d\n", emsize);
+            return FALSE;
+        }
+
+        if (ppem == emsize)
+        {
+            *a = (SHORT)GET_BE_WORD(tables[i].yMax);
+            *d = -(SHORT)GET_BE_WORD(tables[i].yMin);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static void test_GetGdiCompatibleMetrics_face(IDWriteFontFace *face)
+{
+    HRESULT hr;
+    DWRITE_FONT_METRICS design_metrics, comp_metrics;
+    FLOAT emsize, scale;
+    int ascent, descent, expect;
+    const struct VDMX_Header *vdmx;
+    UINT32 vdmx_len;
+    void *vdmx_ctx;
+    BOOL exists;
+    const struct VDMX_group *vdmx_group = NULL;
+
+    IDWriteFontFace_GetMetrics(face, &design_metrics);
+
+    hr = IDWriteFontFace_TryGetFontTable(face, MS_VDMX_TAG, (const void **)&vdmx,
+                                         &vdmx_len, &vdmx_ctx, &exists);
+    if (hr != S_OK || !exists)
+        vdmx = NULL;
+    else
+        vdmx_group = find_vdmx_group(vdmx);
+
+    for (emsize = 5; emsize <= design_metrics.designUnitsPerEm; emsize++)
+    {
+        scale = emsize / design_metrics.designUnitsPerEm;
+        hr = IDWriteFontFace_GetGdiCompatibleMetrics(face, emsize, 1.0, NULL, &comp_metrics);
+todo_wine
+        ok(hr == S_OK, "got %08x\n", hr);
+        if (hr != S_OK) return;
+
+        if (!get_vdmx_size(vdmx_group, emsize, &ascent, &descent))
+        {
+            ascent = round(design_metrics.ascent * scale);
+            descent = round(design_metrics.descent * scale);
+        }
+
+        ok(comp_metrics.designUnitsPerEm == design_metrics.designUnitsPerEm,
+           "%.2f: emsize: got %d expect %d\n",
+           emsize, comp_metrics.designUnitsPerEm, design_metrics.designUnitsPerEm);
+
+        ok(comp_metrics.ascent == round(ascent / scale), "%.2f a: got %d expect %d\n",
+           emsize, comp_metrics.ascent, round(ascent / scale));
+
+        ok(comp_metrics.descent == round(descent / scale), "%.2f d: got %d expect %d\n",
+           emsize, comp_metrics.descent, round(descent / scale));
+
+        expect = round(round(design_metrics.lineGap * scale) / scale);
+        ok(comp_metrics.lineGap == expect, "%.2f lg: got %d expect %d\n",
+           emsize, comp_metrics.lineGap, expect);
+
+        expect = round(round(design_metrics.capHeight * scale) / scale);
+        ok(comp_metrics.capHeight == expect, "%.2f capH: got %d expect %d\n",
+           emsize, comp_metrics.capHeight, expect);
+
+        expect = round(round(design_metrics.xHeight * scale) / scale);
+        ok(comp_metrics.xHeight == expect, "%.2f xH: got %d expect %d\n",
+           emsize, comp_metrics.xHeight, expect);
+
+        expect = round(round(design_metrics.underlinePosition * scale) / scale);
+        ok(comp_metrics.underlinePosition == expect, "%.2f ulP: got %d expect %d\n",
+            emsize, comp_metrics.underlinePosition, expect);
+
+        expect = round(round(design_metrics.underlineThickness * scale) / scale);
+        ok(comp_metrics.underlineThickness == expect, "%.2f ulTh: got %d expect %d\n",
+           emsize, comp_metrics.underlineThickness, expect);
+
+        expect = round(round(design_metrics.strikethroughPosition * scale) / scale);
+        ok(comp_metrics.strikethroughPosition == expect, "%.2f stP: got %d expect %d\n",
+           emsize, comp_metrics.strikethroughPosition, expect);
+
+        expect = round(round(design_metrics.strikethroughThickness * scale) / scale);
+        ok(comp_metrics.strikethroughThickness == expect, "%.2f stTh: got %d expect %d\n",
+           emsize, comp_metrics.strikethroughThickness, expect);
+    }
+
+    if (vdmx) IDWriteFontFace_ReleaseFontTable(face, vdmx_ctx);
+}
+
+static void test_GetGdiCompatibleMetrics(void)
+{
+    IDWriteFactory *factory;
+    IDWriteFont *font;
+    IDWriteFontFace *fontface;
+    HRESULT hr;
+
+    factory = create_factory();
+
+    font = get_font(factory, tahomaW, DWRITE_FONT_STYLE_NORMAL);
+    hr = IDWriteFont_CreateFontFace(font, &fontface);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IDWriteFont_Release(font);
+    test_GetGdiCompatibleMetrics_face(fontface);
+    IDWriteFontFace_Release(fontface);
+
+    font = get_font(factory, arialW, DWRITE_FONT_STYLE_NORMAL);
+    if (!font)
+        skip("Skipping tests with Arial\n");
+    else
+    {
+        hr = IDWriteFont_CreateFontFace(font, &fontface);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        IDWriteFont_Release(font);
+
+        test_GetGdiCompatibleMetrics_face(fontface);
+        IDWriteFontFace_Release(fontface);
+    }
+
+    IDWriteFactory_Release(factory);
+}
+
 START_TEST(font)
 {
     IDWriteFactory *factory;
@@ -3461,6 +3677,7 @@ START_TEST(font)
     test_GetKerningPairAdjustments();
     test_CreateRenderingParams();
     test_CreateGlyphRunAnalysis();
+    test_GetGdiCompatibleMetrics();
 
     IDWriteFactory_Release(factory);
 }




More information about the wine-cvs mailing list