gdi32: Fix for GetTextExtentExPointW() and ExtTextOutW().

This commit is contained in:
Pedro Araujo Chaves Jr 2007-02-08 13:12:08 -02:00 committed by Alexandre Julliard
parent 5c398c571f
commit 2051bcccca
2 changed files with 169 additions and 8 deletions

View File

@ -1231,6 +1231,7 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
LPINT dxs = NULL;
DC *dc;
BOOL ret = FALSE;
TEXTMETRICW tm;
TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
@ -1238,6 +1239,8 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
if (! dc)
return FALSE;
GetTextMetricsW(hdc, &tm);
/* If we need to calculate nFit, then we need the partial extents even if
the user hasn't provided us with an array. */
if (lpnFit)
@ -1263,22 +1266,49 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
/* Perform device size to world size transformations. */
if (ret)
{
INT extra = dc->charExtra, breakRem = dc->breakRem;
INT extra = dc->charExtra,
breakExtra = dc->breakExtra,
breakRem = dc->breakRem,
i;
if (dxs)
{
INT i;
for (i = 0; i < count; ++i)
{
dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
dxs[i] += (i+1) * extra + breakRem;
dxs[i] += (i+1) * extra;
if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
{
dxs[i] += breakExtra;
if (breakRem > 0)
{
breakRem--;
dxs[i]++;
}
}
if (dxs[i] <= maxExt)
++nFit;
}
breakRem = dc->breakRem;
}
size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
size->cx += count * extra + breakRem;
if (!dxs && count > 1 && (breakExtra || breakRem))
{
for (i = 0; i < count; i++)
{
if (str[i] == tm.tmBreakChar)
{
size->cx += breakExtra;
if (breakRem > 0)
{
breakRem--;
(size->cx)++;
}
}
}
}
}
if (lpnFit)
@ -1812,12 +1842,15 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
SIZE sz;
RECT rc;
BOOL done_extents = FALSE;
INT width, xwidth = 0, ywidth = 0;
INT width = 0, xwidth = 0, ywidth = 0;
DWORD type;
DC * dc = DC_GetDCUpdate( hdc );
INT breakRem;
if (!dc) return FALSE;
breakRem = dc->breakRem;
if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
@ -1927,8 +1960,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
y = pt.y;
char_extra = GetTextCharacterExtra(hdc);
width = 0;
if(char_extra || dc->breakExtra || lpDx)
if(char_extra || dc->breakExtra || breakRem || lpDx)
{
UINT i;
SIZE tmpsz;
@ -1949,9 +1981,14 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
deltas[i] = tmpsz.cx;
}
if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
{
deltas[i] = deltas[i] + dc->breakExtra;
if (breakRem > 0)
{
breakRem--;
deltas[i]++;
}
}
deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
width += deltas[i];

View File

@ -887,6 +887,129 @@ static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count
return TRUE;
}
static void testJustification(HDC hdc, PSTR str, RECT *clientArea)
{
INT x, y,
breakCount,
outputWidth = 0, /* to test TabbedTextOut() */
justifiedWidth = 0, /* to test GetTextExtentExPointW() */
areaWidth = clientArea->right - clientArea->left,
nErrors = 0, e;
BOOL lastExtent = FALSE;
PSTR pFirstChar, pLastChar;
SIZE size;
TEXTMETRICA tm;
struct err
{
char extent[100];
int GetTextExtentExPointWWidth;
int TabbedTextOutWidth;
} error[10];
GetTextMetricsA(hdc, &tm);
y = clientArea->top;
do {
breakCount = 0;
while (*str == tm.tmBreakChar) str++; /* skip leading break chars */
pFirstChar = str;
do {
pLastChar = str;
/* if not at the end of the string, ... */
if (*str == '\0') break;
/* ... add the next word to the current extent */
while (*str != '\0' && *str++ != tm.tmBreakChar);
breakCount++;
SetTextJustification(hdc, 0, 0);
GetTextExtentPoint32(hdc, pFirstChar, str - pFirstChar - 1, &size);
} while ((int) size.cx < areaWidth);
/* ignore trailing break chars */
breakCount--;
while (*(pLastChar - 1) == tm.tmBreakChar)
{
pLastChar--;
breakCount--;
}
if (*str == '\0' || breakCount <= 0) pLastChar = str;
SetTextJustification(hdc, 0, 0);
GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
/* do not justify the last extent */
if (*str != '\0' && breakCount > 0)
{
SetTextJustification(hdc, areaWidth - size.cx, breakCount);
GetTextExtentPoint32(hdc, pFirstChar, pLastChar - pFirstChar, &size);
justifiedWidth = size.cx;
}
else lastExtent = TRUE;
x = clientArea->left;
outputWidth = LOWORD(TabbedTextOut(
hdc, x, y, pFirstChar, pLastChar - pFirstChar,
0, NULL, 0));
/* catch errors and report them */
if (!lastExtent && ((outputWidth != areaWidth) || (justifiedWidth != areaWidth)))
{
memset(error[nErrors].extent, 0, 100);
memcpy(error[nErrors].extent, pFirstChar, pLastChar - pFirstChar);
error[nErrors].TabbedTextOutWidth = outputWidth;
error[nErrors].GetTextExtentExPointWWidth = justifiedWidth;
nErrors++;
}
y += size.cy;
str = pLastChar;
} while (*str && y < clientArea->bottom);
for (e = 0; e < nErrors; e++)
{
ok(error[e].TabbedTextOutWidth == areaWidth,
"The output text (\"%s\") width should be %d, not %d.\n",
error[e].extent, areaWidth, error[e].TabbedTextOutWidth);
/* The width returned by GetTextExtentPoint32() is exactly the same
returned by GetTextExtentExPointW() - see dlls/gdi32/font.c */
ok(error[e].GetTextExtentExPointWWidth == areaWidth,
"GetTextExtentPointW() for \"%s\" should have returned a width of %d, not %d.\n",
error[e].extent, areaWidth, error[e].GetTextExtentExPointWWidth);
}
}
static void test_SetTextJustification(void)
{
HDC hdc = GetDC(0);
RECT clientArea = {0, 0, 400, 400};
LOGFONTA lf;
HFONT hfont;
static char testText[] =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
"nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in "
"reprehenderit in voluptate velit esse cillum dolore eu fugiat "
"nulla pariatur. Excepteur sint occaecat cupidatat non proident, "
"sunt in culpa qui officia deserunt mollit anim id est laborum.";
memset(&lf, 0, sizeof lf);
lf.lfCharSet = ANSI_CHARSET;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfWeight = FW_DONTCARE;
lf.lfHeight = 20;
lf.lfQuality = DEFAULT_QUALITY;
lstrcpyA(lf.lfFaceName, "Times New Roman");
hfont = create_font("Times New Roman", &lf);
SelectObject(hdc, hfont);
testJustification(hdc, testText, &clientArea);
DeleteObject(hfont);
ReleaseDC(0, hdc);
}
static void test_font_charset(void)
{
static struct charset_data
@ -940,5 +1063,6 @@ START_TEST(font)
test_GetGlyphIndices();
test_GetKerningPairs();
test_GetOutlineTextMetrics();
test_SetTextJustification();
test_font_charset();
}