Signed-off-by: Jactry Zeng <jzeng(a)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;
+ }
+ 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);
+ 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)