Fix using DrawTextEx to calculate text rect with DT_BOTTOM flag set returns zero for text height.
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/user32/tests/text.c | 12 ++++++++++++ dlls/user32/text.c | 46 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/tests/text.c b/dlls/user32/tests/text.c index 3cc9571521..e07bb2f168 100644 --- a/dlls/user32/tests/text.c +++ b/dlls/user32/tests/text.c @@ -28,6 +28,8 @@ #include "winerror.h" #include "winnls.h" +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + #define MODIFIED(rect) (rect.left == 10 && rect.right != 100 && rect.top == 10 && rect.bottom != 100) #define EMPTY(rect) (rect.left == rect.right && rect.bottom == rect.top) @@ -46,11 +48,13 @@ static void test_DrawTextCalcRect(void) static CHAR wordbreak_text[] = "line1 line2"; static WCHAR wordbreak_textW[] = {'l','i','n','e','1',' ','l','i','n','e','2',0}; static char tabstring[] = "one\ttwo"; + static DWORD alignments[] = {DT_TOP, DT_LEFT, DT_CENTER, DT_RIGHT, DT_VCENTER, DT_BOTTOM}; INT textlen, textheight, heightcheck; RECT rect = { 0, 0, 100, 0 }, rect2; BOOL ret; DRAWTEXTPARAMS dtp; BOOL conform_xp = TRUE; + INT i; /* Initialization */ hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, @@ -586,6 +590,14 @@ static void test_DrawTextCalcRect(void) ok(rect.top == rect2.top, "unexpected value %d, got %d\n", rect.top, rect2.top); ok(rect.bottom == rect2.bottom , "unexpected value %d, got %d\n", rect.bottom, rect2.bottom); + for (i = 0; i < ARRAY_SIZE(alignments); i++) + { + SetRectEmpty(&rect); + textheight = DrawTextA(hdc, tabstring, -1, &rect, DT_NOCLIP | DT_CALCRECT | DT_SINGLELINE | alignments[i]); + ok(textheight > 0, "Alignment 0x%08x got unexpected textheight %d\n", alignments[i], textheight); + ok(rect.right - rect.left > 0, "Alignment 0x%08x got unexpected rect width %d\n", alignments[i], + rect.right - rect.left); + } SelectObject(hdc, hOldFont); ret = DeleteObject(hFont); diff --git a/dlls/user32/text.c b/dlls/user32/text.c index 0b5bd47461..f0a882c343 100644 --- a/dlls/user32/text.c +++ b/dlls/user32/text.c @@ -808,7 +808,6 @@ static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count, return NULL; } - /*********************************************************************** * TEXT_DrawUnderscore * @@ -874,17 +873,17 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, WCHAR *retstr, *p_retstr; size_t size_retstr; WCHAR line[MAX_BUFFER]; - int len, lh, count=i_count; + int len, lh, count = i_count, old_count, line_count = 0; TEXTMETRICW tm; int lmargin = 0, rmargin = 0; int x = rect->left, y = rect->top; int width = rect->right - rect->left; - int max_width = 0; + int max_width = 0, max_height = 0; int last_line; int tabwidth /* to keep gcc happy */ = 0; int prefix_offset; ellipsis_data ellip; - BOOL invert_y=FALSE; + BOOL invert_y = FALSE, is_fist_line = TRUE; TRACE("%s, %d, [%s] %08x\n", debugstr_wn (str, count), count, wine_dbgstr_rect(rect), flags); @@ -968,6 +967,29 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, } p_retstr = retstr; + old_count = count; + do + { + len = ARRAY_SIZE(line); + if (invert_y) + last_line = !(flags & DT_NOCLIP) && y - ((flags & DT_EDITCONTROL) ? 2 * lh - 1 : lh) < rect->bottom; + else + last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2 * lh - 1 : lh) > rect->bottom; + strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, &p_retstr, tabwidth, + &prefix_offset, &ellip); + + if (invert_y) + y -= lh; + else + y += lh; + + line_count++; + } while (strPtr && !last_line); + max_height = line_count * lh; + + strPtr = str; + count = old_count; + y = rect->top; do { len = ARRAY_SIZE(line); @@ -981,11 +1003,15 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, size.cx) / 2; else if (flags & DT_RIGHT) x = rect->right - size.cx; - if (flags & DT_SINGLELINE) - { - if (flags & DT_VCENTER) y = rect->top + - (rect->bottom - rect->top) / 2 - size.cy / 2; - else if (flags & DT_BOTTOM) y = rect->bottom - size.cy; + if (is_fist_line) + { + if (flags & DT_VCENTER) + y = invert_y ? rect->top - (rect->bottom - rect->top) / 2 + max_height / 2 + : rect->top + (rect->bottom - rect->top) / 2 - max_height / 2; + else if (flags & DT_BOTTOM) + y = invert_y ? rect->bottom + max_height : rect->bottom - max_height; + + is_fist_line = FALSE; } if (!(flags & DT_CALCRECT)) @@ -1071,7 +1097,7 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, memcpy (str, retstr, size_retstr); HeapFree (GetProcessHeap(), 0, retstr); } - return y - rect->top; + return invert_y ? -max_height : max_height; } /***********************************************************************