gdi32: Revert 1440eb5a35 and add the test showing that the change was wrong.

This commit is contained in:
Dmitry Timoshkov 2007-02-15 15:52:33 +08:00 committed by Alexandre Julliard
parent 2aa8463a94
commit 37591409b2
2 changed files with 179 additions and 21 deletions

View File

@ -342,17 +342,59 @@ static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRIC
/*********************************************************************** /***********************************************************************
* FONT_mbtowc * FONT_mbtowc
* *
* Returns a Unicode translation of str. If count is -1 then str is * Returns a Unicode translation of str using the charset of the
* assumed to be '\0' terminated, otherwise it contains the number of * currently selected font in hdc. If count is -1 then str is assumed
* bytes to convert. If plenW is non-NULL, on return it will point to * to be '\0' terminated, otherwise it contains the number of bytes to
* the number of WCHARs that have been written. The caller should free * convert. If plenW is non-NULL, on return it will point to the
* the returned LPWSTR from the process heap itself. * number of WCHARs that have been written. If pCP is non-NULL, on
* return it will point to the codepage used in the conversion. The
* caller should free the returned LPWSTR from the process heap
* itself.
*/ */
static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW) static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
{ {
UINT cp = CP_ACP; UINT cp = CP_ACP;
INT lenW; INT lenW;
LPWSTR strW; LPWSTR strW;
CHARSETINFO csi;
int charset = GetTextCharset(hdc);
/* Hmm, nicely designed api this one! */
if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
cp = csi.ciACP;
else {
switch(charset) {
case OEM_CHARSET:
cp = GetOEMCP();
break;
case DEFAULT_CHARSET:
cp = GetACP();
break;
case VISCII_CHARSET:
case TCVN_CHARSET:
case KOI8_CHARSET:
case ISO3_CHARSET:
case ISO4_CHARSET:
case ISO10_CHARSET:
case CELTIC_CHARSET:
/* FIXME: These have no place here, but because x11drv
enumerates fonts with these (made up) charsets some apps
might use them and then the FIXME below would become
annoying. Now we could pick the intended codepage for
each of these, but since it's broken anyway we'll just
use CP_ACP and hope it'll go away...
*/
cp = CP_ACP;
break;
default:
FIXME("Can't find codepage for charset %d\n", charset);
break;
}
}
TRACE("charset %d => cp %d\n", charset, cp);
if(count == -1) count = strlen(str); if(count == -1) count = strlen(str);
lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0); lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
@ -360,6 +402,7 @@ static LPWSTR FONT_mbtowc(LPCSTR str, INT count, INT *plenW)
MultiByteToWideChar(cp, 0, str, count, strW, lenW); MultiByteToWideChar(cp, 0, str, count, strW, lenW);
TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW)); TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
if(plenW) *plenW = lenW; if(plenW) *plenW = lenW;
if(pCP) *pCP = cp;
return strW; return strW;
} }
@ -1021,7 +1064,7 @@ BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
INT wlen; INT wlen;
LPWSTR p = FONT_mbtowc(str, count, &wlen); LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
if (p) { if (p) {
ret = GetTextExtentPoint32W( hdc, p, wlen, size ); ret = GetTextExtentPoint32W( hdc, p, wlen, size );
@ -1130,7 +1173,7 @@ BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT)))) NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
return FALSE; return FALSE;
p = FONT_mbtowc(str, count, &wlen); p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size); ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
if (walpDx) if (walpDx)
{ {
@ -1663,7 +1706,7 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
for(i = 0; i < count; i++) for(i = 0; i < count; i++)
str[i] = (BYTE)(firstChar + i); str[i] = (BYTE)(firstChar + i);
wstr = FONT_mbtowc(str, count, &wlen); wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
for(i = 0; i < wlen; i++) for(i = 0; i < wlen; i++)
{ {
@ -1691,6 +1734,7 @@ BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx ) const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
{ {
INT wlen; INT wlen;
UINT codepage;
LPWSTR p; LPWSTR p;
BOOL ret; BOOL ret;
LPINT lpDxW = NULL; LPINT lpDxW = NULL;
@ -1698,14 +1742,14 @@ BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
if (flags & ETO_GLYPH_INDEX) if (flags & ETO_GLYPH_INDEX)
return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx ); return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
p = FONT_mbtowc(str, count, &wlen); p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
if (lpDx) { if (lpDx) {
unsigned int i = 0, j = 0; unsigned int i = 0, j = 0;
lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT)); lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
while(i < count) { while(i < count) {
if(IsDBCSLeadByte(str[i])) { if(IsDBCSLeadByteEx(codepage, str[i])) {
lpDxW[j++] = lpDx[i] + lpDx[i+1]; lpDxW[j++] = lpDx[i] + lpDx[i+1];
i = i + 2; i = i + 2;
} else { } else {
@ -2310,7 +2354,7 @@ BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
for(i = 0; i < count; i++) for(i = 0; i < count; i++)
str[i] = (BYTE)(firstChar + i); str[i] = (BYTE)(firstChar + i);
wstr = FONT_mbtowc(str, count, &wlen); wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
for(i = 0; i < wlen; i++) for(i = 0; i < wlen; i++)
{ {
@ -2448,7 +2492,7 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
len = 1; len = 1;
mbchs[0] = (uChar & 0xff); mbchs[0] = (uChar & 0xff);
} }
p = FONT_mbtowc(mbchs, len, NULL); p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
c = p[0]; c = p[0];
} else } else
c = uChar; c = uChar;
@ -2754,7 +2798,7 @@ DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
TRACE("(%p, %s, %d, %p, 0x%x)\n", TRACE("(%p, %s, %d, %p, 0x%x)\n",
hdc, debugstr_an(lpstr, count), count, pgi, flags); hdc, debugstr_an(lpstr, count), count, pgi, flags);
lpstrW = FONT_mbtowc(lpstr, count, &countW); lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags); ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
HeapFree(GetProcessHeap(), 0, lpstrW); HeapFree(GetProcessHeap(), 0, lpstrW);
@ -2799,6 +2843,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
INT uCountW; INT uCountW;
GCP_RESULTSW resultsW; GCP_RESULTSW resultsW;
DWORD ret; DWORD ret;
UINT font_cp;
TRACE("%s, %d, %d, 0x%08x\n", TRACE("%s, %d, %d, 0x%08x\n",
debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags); debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
@ -2806,7 +2851,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
/* both structs are equal in size */ /* both structs are equal in size */
memcpy(&resultsW, lpResults, sizeof(resultsW)); memcpy(&resultsW, lpResults, sizeof(resultsW));
lpStringW = FONT_mbtowc(lpString, uCount, &uCountW); lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
if(lpResults->lpOutString) if(lpResults->lpOutString)
resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW); resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
@ -2816,7 +2861,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
lpResults->nMaxFit = resultsW.nMaxFit; lpResults->nMaxFit = resultsW.nMaxFit;
if(lpResults->lpOutString) { if(lpResults->lpOutString) {
WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW, WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
lpResults->lpOutString, uCount, NULL, NULL ); lpResults->lpOutString, uCount, NULL, NULL );
} }
@ -2946,7 +2991,7 @@ BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT a
for(i = 0; i < count; i++) for(i = 0; i < count; i++)
str[i] = (BYTE)(first + i); str[i] = (BYTE)(first + i);
wstr = FONT_mbtowc(str, count, &wlen); wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
for (i = 0; i < wlen; i++) for (i = 0; i < wlen; i++)
{ {

View File

@ -26,9 +26,13 @@
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
#include "winuser.h" #include "winuser.h"
#include "winnls.h"
#include "wine/test.h" #include "wine/test.h"
DWORD (WINAPI *pGetGlyphIndicesA)(HDC hdc, LPCSTR lpstr, INT count, LPWORD pgi, DWORD flags);
DWORD (WINAPI *pGetGlyphIndicesW)(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags);
static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
{ {
return 0; return 0;
@ -432,7 +436,7 @@ static void test_text_extents(void)
GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1); GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{ {
trace("Skipping remainder of text extents test on a Win9x platform\n"); skip("Skipping remainder of text extents test on a Win9x platform\n");
hfont = SelectObject(hdc, hfont); hfont = SelectObject(hdc, hfont);
DeleteObject(hfont); DeleteObject(hfont);
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
@ -615,7 +619,7 @@ static void test_GetKerningPairs(void)
GetKerningPairsW(hdc, 0, NULL); GetKerningPairsW(hdc, 0, NULL);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{ {
trace("Skipping the GetKerningPairs test on a Win9x platform\n"); skip("Skipping the GetKerningPairs test on a Win9x platform\n");
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
return; return;
} }
@ -740,14 +744,14 @@ static void test_GetOutlineTextMetrics(void)
HDC hdc; HDC hdc;
DWORD ret, otm_size; DWORD ret, otm_size;
hdc = GetDC(0);
if (!is_font_installed("Arial")) if (!is_font_installed("Arial"))
{ {
skip("Arial is not installed\n"); skip("Arial is not installed\n");
return; return;
} }
hdc = GetDC(0);
memset(&lf, 0, sizeof(lf)); memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial"); strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = -13; lf.lfHeight = -13;
@ -817,6 +821,114 @@ static void test_GetOutlineTextMetrics(void)
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
} }
static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count, BOOL unicode)
{
HDC hdc;
LOGFONTA lf;
HFONT hfont, hfont_old;
CHARSETINFO csi;
INT cs;
DWORD i, ret;
assert(count <= 128);
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = charset;
lf.lfHeight = 10;
lstrcpyA(lf.lfFaceName, "Arial");
SetLastError(0xdeadbeef);
hfont = CreateFontIndirectA(&lf);
ok(hfont != 0, "CreateFontIndirectA error %u\n", GetLastError());
hdc = GetDC(0);
hfont_old = SelectObject(hdc, hfont);
cs = GetTextCharset(hdc);
ok(cs == charset, "expected %d, got %d\n", charset, cs);
if (!TranslateCharsetInfo((DWORD *)cs, &csi, TCI_SRCCHARSET))
{
trace("Can't find codepage for charset %d\n", cs);
ReleaseDC(0, hdc);
return FALSE;
}
ok(csi.ciACP == code_page, "expected %d, got %d\n", code_page, csi.ciACP);
if (unicode)
{
char ansi_buf[128];
WCHAR unicode_buf[128];
for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
MultiByteToWideChar(code_page, 0, ansi_buf, count, unicode_buf, count);
SetLastError(0xdeadbeef);
ret = pGetGlyphIndicesW(hdc, unicode_buf, count, idx, 0);
ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
}
else
{
char ansi_buf[128];
for (i = 0; i < count; i++) ansi_buf[i] = (BYTE)(i + 128);
SetLastError(0xdeadbeef);
ret = pGetGlyphIndicesA(hdc, ansi_buf, count, idx, 0);
ok(ret == count, "GetGlyphIndicesA error %u\n", GetLastError());
}
SelectObject(hdc, hfont_old);
DeleteObject(hfont);
ReleaseDC(0, hdc);
return TRUE;
}
static void test_font_charset(void)
{
static struct charset_data
{
INT charset;
UINT code_page;
WORD font_idxA[128], font_idxW[128];
} cd[] =
{
{ ANSI_CHARSET, 1252 },
{ SYMBOL_CHARSET, CP_SYMBOL },
{ RUSSIAN_CHARSET, 1251 }
};
int i;
pGetGlyphIndicesA = (void *)GetProcAddress(GetModuleHandle("gdi32.dll"), "GetGlyphIndicesA");
pGetGlyphIndicesW = (void *)GetProcAddress(GetModuleHandle("gdi32.dll"), "GetGlyphIndicesW");
if (!pGetGlyphIndicesA || !pGetGlyphIndicesW)
{
skip("Skipping the font charset test on a Win9x platform\n");
return;
}
if (!is_font_installed("Arial"))
{
skip("Arial is not installed\n");
return;
}
for (i = 0; i < sizeof(cd)/sizeof(cd[0]); i++)
{
get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxA, 128, FALSE);
get_glyph_indices(cd[i].charset, cd[i].code_page, cd[i].font_idxW, 128, TRUE);
ok(!memcmp(cd[i].font_idxA, cd[i].font_idxW, 128), "%d: indices don't match\n", i);
}
ok(memcmp(cd[0].font_idxW, cd[1].font_idxW, 128*sizeof(WORD)), "0 vs 1: indices shouldn't match\n");
ok(memcmp(cd[0].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "0 vs 2: indices shouldn't match\n");
ok(memcmp(cd[1].font_idxW, cd[2].font_idxW, 128*sizeof(WORD)), "1 vs 2: indices shouldn't match\n");
}
START_TEST(font) START_TEST(font)
{ {
test_logfont(); test_logfont();
@ -828,4 +940,5 @@ START_TEST(font)
test_GetGlyphIndices(); test_GetGlyphIndices();
test_GetKerningPairs(); test_GetKerningPairs();
test_GetOutlineTextMetrics(); test_GetOutlineTextMetrics();
test_font_charset();
} }