[PATCH 1/4] dwrite: Improve parameter validation in GetGdiCompatibleGlyphAdvances(), add some tests

Nikolay Sivov nsivov at codeweavers.com
Mon Jul 20 07:13:58 CDT 2015


---

-------------- next part --------------
>From 582cc56b832196db823b8027479a1d85362623b0 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sat, 18 Jul 2015 17:54:57 +0300
Subject: [PATCH 1/5] dwrite: Improve parameter validation in
 GetGdiCompatibleGlyphAdvances(), add some tests

---
 dlls/dwrite/font.c       |  13 +++++-
 dlls/dwrite/tests/font.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 11ff9d0..2d01574 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -771,10 +771,19 @@ static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontF
     TRACE("(%p)->(%.2f %.2f %p %d %d %u %p %p)\n", This, em_size, ppdip, m,
         use_gdi_natural, is_sideways, glyph_count, glyphs, advances);
 
-    if (m && memcmp(m, &identity, sizeof(*m)))
-        FIXME("transform is not supported, %s\n", debugstr_matrix(m));
+    if (em_size < 0.0 || ppdip <= 0.0) {
+        memset(advances, 0, sizeof(*advances) * glyph_count);
+        return E_INVALIDARG;
+    }
 
     scale = em_size * ppdip / This->metrics.designUnitsPerEm;
+    if (scale == 0.0) {
+        memset(advances, 0, sizeof(*advances) * glyph_count);
+        return S_OK;
+    }
+
+    if (m && memcmp(m, &identity, sizeof(*m)))
+        FIXME("transform is not supported, %s\n", debugstr_matrix(m));
 
     for (i = 0; i < glyph_count; i++) {
         hr = IDWriteFontFace2_GetDesignGlyphAdvances(iface, 1, glyphs + i, advances + i, is_sideways);
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 7dc6077..94dccdd 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -3905,6 +3905,121 @@ static void test_GetPanose(void)
     IDWriteFactory_Release(factory);
 }
 
+static INT32 get_gdi_font_advance(HDC hdc, FLOAT emsize)
+{
+    LOGFONTW logfont;
+    HFONT hfont;
+    BOOL ret;
+    ABC abc;
+
+    memset(&logfont, 0, sizeof(logfont));
+    logfont.lfHeight = (LONG)-emsize;
+    logfont.lfWeight = FW_NORMAL;
+    logfont.lfQuality = CLEARTYPE_QUALITY;
+    lstrcpyW(logfont.lfFaceName, tahomaW);
+
+    hfont = CreateFontIndirectW(&logfont);
+    SelectObject(hdc, hfont);
+
+    ret = GetCharABCWidthsW(hdc, 'A', 'A', &abc);
+    ok(ret, "got %d\n", ret);
+
+    DeleteObject(hfont);
+
+    return abc.abcA + abc.abcB + abc.abcC;
+}
+
+static void test_GetGdiCompatibleGlyphAdvances(void)
+{
+    IDWriteFontFace1 *fontface1;
+    IDWriteFontFace *fontface;
+    IDWriteFactory *factory;
+    IDWriteFont *font;
+    HRESULT hr;
+    HDC hdc;
+    UINT32 codepoint;
+    UINT16 glyph;
+    FLOAT emsize;
+    DWRITE_FONT_METRICS1 fm;
+    INT32 advance;
+
+    factory = create_factory();
+    font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL);
+
+    hr = IDWriteFont_CreateFontFace(font, &fontface);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    IDWriteFont_Release(font);
+
+    hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
+    IDWriteFontFace_Release(fontface);
+
+    if (hr != S_OK) {
+        IDWriteFactory_Release(factory);
+        win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n");
+        return;
+    }
+
+    codepoint = 'A';
+    glyph = 0;
+    hr = IDWriteFontFace1_GetGlyphIndices(fontface1, &codepoint, 1, &glyph);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(glyph > 0, "got %u\n", glyph);
+
+    /* zero emsize */
+    advance = 1;
+    hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 0.0,
+        1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    ok(advance == 0, "got %d\n", advance);
+
+    /* negative emsize */
+    advance = 1;
+    hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, -1.0,
+        1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(advance == 0, "got %d\n", advance);
+
+    /* zero ppdip */
+    advance = 1;
+    hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
+        0.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(advance == 0, "got %d\n", advance);
+
+    /* negative ppdip */
+    advance = 1;
+    hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, 1.0,
+        -1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+    ok(advance == 0, "got %d\n", advance);
+
+    IDWriteFontFace1_GetMetrics(fontface1, &fm);
+
+    hdc = CreateCompatibleDC(0);
+
+    for (emsize = 1.0; emsize <= fm.designUnitsPerEm; emsize += 1.0) {
+        INT32 gdi_advance;
+
+        gdi_advance = get_gdi_font_advance(hdc, emsize);
+        hr = IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, emsize,
+            1.0, NULL, FALSE, FALSE, 1, &glyph, &advance);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        /* advance is in design units */
+        advance = (int)floorf(emsize * advance / fm.designUnitsPerEm + 0.5f);
+
+        /* allow 1 pixel difference for large sizes, for Tahoma this happens for 16 sizes in [1, 2048] range */
+        if (emsize > 150.0)
+            ok((advance - gdi_advance) <= 1, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
+        else
+            ok(gdi_advance == advance, "%.0f: got advance %d, expected %d\n", emsize, advance, gdi_advance);
+    }
+
+    DeleteObject(hdc);
+
+    IDWriteFactory_Release(factory);
+}
+
 START_TEST(font)
 {
     IDWriteFactory *factory;
@@ -3950,6 +4065,7 @@ START_TEST(font)
     test_CreateGlyphRunAnalysis();
     test_GetGdiCompatibleMetrics();
     test_GetPanose();
+    test_GetGdiCompatibleGlyphAdvances();
 
     IDWriteFactory_Release(factory);
 }
-- 
2.1.4



More information about the wine-patches mailing list