[PATCH] user32: Fix using DrawTextEx() to calculate rect with flag DT_BOTTOM.

Zhiyi Zhang zzhang at codeweavers.com
Tue Apr 17 09:25:38 CDT 2018


Fix using DrawTextEx to calculate text rect with DT_BOTTOM flag set
returns zero for text height.

Signed-off-by: Zhiyi Zhang <zzhang at 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;
  }
   /***********************************************************************
-- 
2.16.3





More information about the wine-devel mailing list