Signed-off-by: Jactry Zeng jzeng@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); }
On Tue, May 29, 2018 at 12:12:06PM +0800, Jactry Zeng wrote:
Signed-off-by: Jactry Zeng jzeng@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)
Thanks! I sent another try. Huw Davies huw@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@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)