[PATCH 1/4 v4] riched20/tests: Rewrite tests for ITextServices_TxGetNaturalSize().
Jactry Zeng
jactry92 at gmail.com
Wed Jun 6 04:25:32 CDT 2018
Thanks! I sent another try.
Huw Davies <huw at codeweavers.com> 于2018年6月4日周一 下午5:28写道:
>
> On Tue, May 29, 2018 at 12:12:06PM +0800, Jactry Zeng wrote:
> > Signed-off-by: Jactry Zeng <jzeng at codeweavers.com>
> > ---
> > dlls/riched20/tests/Makefile.in | 2 +-
> > dlls/riched20/tests/txtsrv.c | 189 ++++++++++++++++++++++++++--------------
> > 2 files changed, 126 insertions(+), 65 deletions(-)
> >
> > diff --git a/dlls/riched20/tests/Makefile.in b/dlls/riched20/tests/Makefile.in
> > index 34c00afa7c..ca381d9dc2 100644
> > --- a/dlls/riched20/tests/Makefile.in
> > +++ b/dlls/riched20/tests/Makefile.in
> > @@ -1,5 +1,5 @@
> > TESTDLL = riched20.dll
> > -IMPORTS = ole32 oleaut32 user32 gdi32
> > +IMPORTS = ole32 oleaut32 user32 gdi32 usp10
> >
> > C_SRCS = \
> > editor.c \
> > diff --git a/dlls/riched20/tests/txtsrv.c b/dlls/riched20/tests/txtsrv.c
> > index 88b5adf13c..76b4eb34f6 100644
> > --- a/dlls/riched20/tests/txtsrv.c
> > +++ b/dlls/riched20/tests/txtsrv.c
> > @@ -37,6 +37,7 @@
> > #include <wine/test.h>
> > #include <oleauto.h>
> > #include <limits.h>
> > +#include <usp10.h>
> >
> > static HMODULE hmoduleRichEdit;
> > static IID *pIID_ITextServices;
> > @@ -697,81 +698,141 @@ static void test_TxSetText(void)
> > ITextHost_Release(host);
> > }
> >
> > +static void hf_from_cf(HFONT *hf, CHARFORMAT2W cf)
> > +{
> > + LOGFONTW lf;
> > +
> > + memset(&lf, 0, sizeof(lf));
> > + lstrcpyW(lf.lfFaceName, cf.szFaceName);
> > + lf.lfHeight = MulDiv(-cf.yHeight, GetDeviceCaps(GetDC(NULL), LOGPIXELSY), 1440);
> > + lf.lfWeight = FW_NORMAL;
> > + if (cf.dwEffects & cf.dwMask & CFM_BOLD)
> > + lf.lfWeight = FW_BOLD;
> > + if (cf.dwMask & CFM_WEIGHT)
> > + lf.lfWeight = cf.wWeight;
> > + if (cf.dwEffects & cf.dwMask & CFM_ITALIC)
> > + lf.lfItalic = TRUE;
> > + if ((cf.dwEffects & cf.dwMask & CFM_UNDERLINE) &&
> > + !(cf.dwEffects & CFE_LINK) &&
> > + cf.bUnderlineType == CFU_CF1UNDERLINE)
> > + lf.lfUnderline = TRUE;
> > + if (cf.dwEffects & cf.dwMask & CFM_STRIKEOUT)
> > + lf.lfStrikeOut = TRUE;
> > + if (cf.dwEffects & cf.dwMask & (CFM_SUBSCRIPT | CFM_SUPERSCRIPT))
> > + lf.lfHeight = (lf.lfHeight * 2) / 3;
> > + if (cf.dwMask & CFM_FACE)
> > + lf.lfPitchAndFamily = cf.bPitchAndFamily;
> > + if (cf.dwMask & CFM_CHARSET)
> > + lf.lfCharSet = cf.bCharSet;
> > + *hf = CreateFontIndirectW(&lf);
> > +}
> > +
> > +static LONG get_max_width(HDC hdc, LPCWSTR string, LONG avail_width, LONG *lines)
> > +{
> > + SCRIPT_ITEM buf[16], *items = buf;
> > + LONG items_passed = sizeof(buf) / sizeof(buf[0]), num_items;
> > + SCRIPT_CONTROL control = {LANG_USER_DEFAULT, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
> > + FALSE, FALSE, 0};
> > + SCRIPT_STATE state = {0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
> > + SCRIPT_CACHE script_cache = NULL;
> > + LONG max_glyphs = 1.5 * lstrlenW(string) + 16;
> > + LONG max_clusters = lstrlenW(string) * 2;
> > + WORD *clusters = HeapAlloc(GetProcessHeap(), 0, max_clusters * sizeof(WORD));
> > + WORD *glyphs = HeapAlloc(GetProcessHeap(), 0, max_glyphs *
> > + (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(LONG) + sizeof(GOFFSET)));
> > + SCRIPT_VISATTR *vis_attrs = (SCRIPT_VISATTR *)((char *)glyphs + max_glyphs * sizeof(WORD));
> > + GOFFSET *offsets = (GOFFSET *)((char *)glyphs + max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR)
> > + + sizeof(LONG)));
> > + LONG num_glyphs = 0;
> > + LONG *advances = (LONG *)((char *)glyphs + max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR)));
> > + LONG i, width = 0, max_width = 0;
> > +
> > + ScriptItemize(string, lstrlenW(string), items_passed, &control, &state, items, &num_items);
> > + ScriptShape(hdc, &script_cache, string, lstrlenW(string), max_glyphs, &items[0].a, glyphs,
> > + clusters, vis_attrs, &num_glyphs);
> > + ScriptPlace(hdc, &script_cache, glyphs, num_glyphs, vis_attrs, &items[0].a, advances, offsets,
> > + NULL);
> > +
> > + *lines = 1;
> > + for (i = 0; i < num_glyphs; i++)
> > + {
> > + width += advances[i];
> > + if (width >= avail_width)
> > + {
> > + (*lines)++;
> > + width -= advances[i];
> > + if (width > max_width)
> > + max_width = width;
> > + width = advances[i];
> > + }
> > + if (width > max_width)
> > + max_width = width;
> > + }
>
> Since we'll probably just use ascii characters for this test, you could
> avoid using uniscribe here and just use gdi32 directly.
>
> > + HeapFree(GetProcessHeap(), 0, clusters);
> > + HeapFree(GetProcessHeap(), 0, glyphs);
> > + return max_width;
> > +}
> > +
> > +#define CHECK_TXGETNATURALSIZE(res,width,height,expected_width,expected_height) \
> > + _check_txgetnaturalsize(res, width, height, expected_width, expected_height, __LINE__)
> > +static void _check_txgetnaturalsize(HRESULT res, LONG width, LONG height, LONG expected_width,
> > + LONG expected_height, int line)
> > +{
> > + ok_(__FILE__,line)(res == S_OK, "TxGetNaturalSize failed: 0x%08x.\n", res);
> > + ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1,
> > + "got wrong width: %d, expected: %d {+1}.\n", width, expected_width);
> > + ok_(__FILE__,line)(height == expected_height, "got wrong height: %d, expected: %d.\n",
> > + height, expected_height);
> > +}
> > +
> > static void test_TxGetNaturalSize(void)
> > {
> > ITextServices *txtserv;
> > ITextHost *host;
> > HRESULT result;
> > - BOOL ret;
> > -
> > - /* This value is used when calling TxGetNaturalSize. MSDN says
> > - that this is not supported however a null pointer cannot be
> > - used as it will cause a segmentation violation. The values in
> > - the structure being pointed to are required to be INT_MAX
> > - otherwise calculations can give wrong values. */
> > - const SIZEL psizelExtent = {INT_MAX,INT_MAX};
> > -
> > - static const WCHAR oneA[] = {'A',0};
> > -
> > - /* Results of measurements */
> > - LONG xdim, ydim;
> > -
> > - /* The device context to do the tests in */
> > + SIZEL psizelExtent = {-1,-1};
> > + static const WCHAR test_text[] = {'T','e','s','t','S','o','m','e','T','e','x','t',0};
> > + LONG width, height, expected_width, expected_height, lines;
> > HDC hdcDraw;
> > -
> > - /* Variables with the text metric information */
> > - INT charwidth_caps_text[26];
> > - TEXTMETRICA tmInfo_text;
> > + HWND hwnd;
> > + RECT rect;
> > + CHARFORMAT2W cf;
> > + LRESULT lresult;
> > + HFONT hf, old_hf;
> > + TEXTMETRICA tm;
> >
> > if (!init_texthost(&txtserv, &host))
> > return;
> >
> > - hdcDraw = GetDC(NULL);
> > - SaveDC(hdcDraw);
> > -
> > - /* Populate the metric strucs */
> > - SetMapMode(hdcDraw,MM_TEXT);
> > - GetTextMetricsA(hdcDraw, &tmInfo_text);
> > - SetLastError(0xdeadbeef);
> > - ret = GetCharWidth32A(hdcDraw,'A','Z',charwidth_caps_text);
> > - if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
> > - win_skip("GetCharWidth32 is not available\n");
> > - goto cleanup;
> > - }
> > -
> > - /* Make measurements in MM_TEXT */
> > + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
> > + 0, 0, 100, 100, 0, 0, 0, NULL);
> > + hdcDraw = GetDC(hwnd);
> > SetMapMode(hdcDraw,MM_TEXT);
> > - xdim = 0; ydim = 0;
> > -
> > - result = ITextServices_TxSetText(txtserv, oneA);
> > - ok(result == S_OK, "ITextServices_TxSetText failed (result = %x)\n", result);
> > - if (result != S_OK) {
> > - skip("Could not set text\n");
> > - goto cleanup;
> > - }
> > -
> > - SetLastError(0xdeadbeef);
> > - result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT,
> > - hdcDraw, NULL, NULL,
> > - TXTNS_FITTOCONTENT, &psizelExtent,
> > - &xdim, &ydim);
> > - todo_wine ok(result == S_OK || broken(result == E_FAIL), /* WINXP Arabic Language */
> > - "TxGetNaturalSize gave unexpected return value (result = %x)\n", result);
> > - if (result == S_OK) {
> > - todo_wine ok(ydim == tmInfo_text.tmHeight,
> > - "Height calculated incorrectly (expected %d, got %d)\n",
> > - tmInfo_text.tmHeight, ydim);
> > - /* The native DLL adds one pixel extra when calculating widths. */
> > - todo_wine ok(xdim >= charwidth_caps_text[0] && xdim <= charwidth_caps_text[0] + 1,
> > - "Width calculated incorrectly (expected %d {+1}, got %d)\n",
> > - charwidth_caps_text[0], xdim);
> > - } else
> > - skip("TxGetNaturalSize measurements not performed (xdim = %d, ydim = %d, result = %x, error = %x)\n",
> > - xdim, ydim, result, GetLastError());
> > -
> > -cleanup:
> > - RestoreDC(hdcDraw,1);
> > - ReleaseDC(NULL,hdcDraw);
> > + GetClientRect(hwnd, &rect);
> > +
> > + result = ITextServices_TxSetText(txtserv, test_text);
> > + ok(result == S_OK, "ITextServices_TxSetText failed: 0x%08x.\n", result);
> > +
> > + cf.cbSize = sizeof(cf);
> > + result = ITextServices_TxSendMessage(txtserv, EM_GETCHARFORMAT, SCF_DEFAULT, (LPARAM)&cf, &lresult);
> > + ok(result == S_OK, "ITextServices_TxSendMessage failed: 0x%08x.\n", result);
> > + hf_from_cf(&hf, cf);
> > +
> > + old_hf = SelectObject(hdcDraw, hf);
>
> How about doing this the other way around - create an hfont, fill out
> an appropriate cf and use that to set the character format of the
> text? I think that would end up being simpler.
>
>
> > + expected_width = get_max_width(hdcDraw, test_text, rect.right - rect.left, &lines);
> > + GetTextMetricsA(hdcDraw, &tm);
> > + expected_height = (tm.tmAscent + tm.tmDescent) * lines;
> > + SelectObject(hdcDraw, old_hf);
> > +
> > + psizelExtent.cx = -1; psizelExtent.cy = -1;
> > + width = rect.right - rect.left;
> > + height = 0;
> > + result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL,
> > + TXTNS_FITTOCONTENT, &psizelExtent, &width, &height);
> > + todo_wine CHECK_TXGETNATURALSIZE(result, width, height, expected_width, expected_height);
> > +
> > + ReleaseDC(hwnd, hdcDraw);
> > + DestroyWindow(hwnd);
> > ITextServices_Release(txtserv);
> > ITextHost_Release(host);
> > }
> > --
> > 2.15.1 (Apple Git-101)
> >
> >
> >
> >
>
>
--
Regards,
Jactry Zeng
More information about the wine-devel
mailing list