[PATCH v2 1/5] d3dx9: Handle vertical alignment in ID3DXFont_DrawText.
Matteo Bruni
matteo.mystral at gmail.com
Tue Mar 24 08:08:53 CDT 2020
I spent a bunch of time tinkering with this, mostly to understand what
the tests check and thus the expected behavior. I came up with the
attached patch, based on top of this one: it isn't necessarily an
improvement, although it does get rid of the recursion (which I don't
like). I left all the debug traces in, it isn't a clean patch by any
means, but I think it shows a possible direction for the
implementation.
I haven't checked that it still works (or even that it still makes
sense) with the other patches in the series.
-------------- next part --------------
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)
More information about the wine-devel
mailing list