Nikolay Sivov : dwrite: Improve parameter validation in GetGdiCompatibleGlyphAdvances(), add some tests.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jul 20 14:20:50 CDT 2015
Module: wine
Branch: master
Commit: 5231715d31cc1f7ebbfca64247383b1aa7fdc2ad
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5231715d31cc1f7ebbfca64247383b1aa7fdc2ad
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Mon Jul 20 15:13:58 2015 +0300
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);
}
More information about the wine-cvs
mailing list