diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c index 56efb11dfd7..9133ae3bc5e 100644 --- a/dlls/d3dx9_36/font.c +++ b/dlls/d3dx9_36/font.c @@ -587,6 +587,7 @@ static const WCHAR *read_line(HDC hdc, const WCHAR *str, int *count, *count = 0; } } + TRACE("size.x %u, size.y %u, num_fit %u\n", size->cx, size->cy, num_fit); if (*count && str[i] == '\n') { @@ -599,14 +600,52 @@ static const WCHAR *read_line(HDC hdc, const WCHAR *str, int *count, return NULL; } +static void compute_rect(struct d3dx_font *font, const WCHAR *string, INT count, WCHAR *line, RECT *rect, DWORD format) +{ + unsigned int width, max_width = 0, y, lh; + SIZE size; + + TRACE("rect %s.\n", wine_dbgstr_rect(rect)); + + y = rect->top; + lh = font->metrics.tmHeight; + width = rect->right - rect->left; + while (string) + { + unsigned int line_len; + + string = read_line(font->hdc, string, &count, line, &line_len, width, format, &size); + if (size.cx > max_width) + max_width = size.cx; + y += lh; + TRACE("y %u\n", y); + if (!(format & DT_NOCLIP) && (y > rect->bottom)) + break; + } + if (format & DT_VCENTER) + { + rect->top = rect->top + (rect->bottom - y) / 2; + rect->bottom -= (rect->bottom - y) / 2; + } + else if (format & DT_BOTTOM) + { + rect->top += rect->bottom - y; + } + else + { + rect->bottom = y; + } + rect->right = rect->left + max_width; + TRACE("rect %s\n", wine_dbgstr_rect(rect)); +} + static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite, const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR color) { struct d3dx_font *font = impl_from_ID3DXFont(iface); - RECT calcrect, textrect = {0}; + RECT r = {0}, *orig_rect = rect; ID3DXSprite *target = sprite; int lh, x, y, width; - int max_width = 0; int ret = 0; WCHAR *line; SIZE size; @@ -629,46 +668,49 @@ static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite, if (format & DT_SINGLELINE) format &= ~DT_WORDBREAK; - if (!rect) - { - y = ID3DXFont_DrawTextW(iface, NULL, string, count, &textrect, format | DT_CALCRECT, 0); - - if (format & DT_CALCRECT) - return y; - } - else - { - textrect = *rect; - } - - calcrect = textrect; + line = heap_alloc(count * sizeof(*line)); + if (!line) + return 0; - if (format & (DT_VCENTER | DT_BOTTOM)) + if (!rect || format & (DT_CALCRECT | DT_VCENTER | DT_BOTTOM)) { - y = ID3DXFont_DrawTextW(iface, NULL, string, count, &calcrect, - (format & ~DT_BOTTOM & ~DT_VCENTER) | DT_CALCRECT, 0); + DWORD flags = format; - if (format & DT_VCENTER) + if (!rect) { - calcrect.top = textrect.top + (textrect.bottom - textrect.top - y) / 2; - calcrect.bottom = calcrect.top + y; + orig_rect = &r; + flags |= DT_NOCLIP; } - else if (format & DT_BOTTOM) + else + r = *rect; + + compute_rect(font, string, count, line, &r, flags); + + if (format & DT_CALCRECT) { - calcrect.top = textrect.bottom - y; + if (rect) + { + ret = r.bottom - rect->top; + *rect = r; + } + else + { + ret = r.bottom - r.top; + } + return ret; } + + rect = &r; } - x = calcrect.left; - y = calcrect.top; - width = calcrect.right - calcrect.left; + TRACE("rect %s\n", wine_dbgstr_rect(rect)); + x = rect->left; + y = rect->top; + width = rect->right - rect->left; + TRACE("y %u\n", y); lh = font->metrics.tmHeight; - line = heap_alloc(count * sizeof(*line)); - if (!line) - return 0; - if (!(format & DT_CALCRECT) && !sprite) { D3DXCreateSprite(font->device, &target); @@ -724,25 +766,14 @@ static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite *sprite, heap_free(results.lpCaretPos); heap_free(results.lpGlyphs); } - else if (size.cx > max_width) - { - max_width = size.cx; - } y += lh; - if (!(DT_NOCLIP & format) && (y > textrect.bottom)) + TRACE("y %u\n", y); + if (!(DT_NOCLIP & format) && (y > rect->bottom)) break; } - if (format & DT_CALCRECT) - { - *rect = calcrect; - - rect->bottom = y; - rect->right = rect->left + max_width; - } - - ret = y - textrect.top; + ret = y - orig_rect->top; cleanup: if (target != sprite)