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

Huw Davies huw at codeweavers.com
Wed Apr 18 02:29:59 CDT 2018


On 17 Apr 2018, at 16:55, Zhiyi Zhang <zzhang at codeweavers.com> wrote:
> diff --git a/dlls/user32/text.c b/dlls/user32/text.c
> index 0b5bd47461..6843386e22 100644
> --- a/dlls/user32/text.c
> +++ b/dlls/user32/text.c
> @@ -874,17 +874,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;

You probably meant is_first_line.

>     TRACE("%s, %d, [%s] %08x\n", debugstr_wn (str, count), count,
>         wine_dbgstr_rect(rect), flags);
> @@ -968,6 +968,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 +1004,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 +1098,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;
> }

It may require some restructuring of the original code, but
there will be a better way of doing this.

Huw.




More information about the wine-devel mailing list