gdi32: Revert 1440eb5a35dc95dea1836d9035b51e2b15d83703 and add the
test showing that the change was wrong
Dmitry Timoshkov
dmitry at codeweavers.com
Thu Feb 15 01:52:33 CST 2007
Hello,
this patch should fix the bug #7379.
Changelog:
gdi32: Revert 1440eb5a35dc95dea1836d9035b51e2b15d83703 and add the test showing
that the change was wrong.
---
dlls/gdi32/font.c | 79 ++++++++++++++++++++++++-------
dlls/gdi32/tests/font.c | 121 +++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 179 insertions(+), 21 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index ee57ba8..876e49a 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -342,17 +342,59 @@ static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRIC
/***********************************************************************
* FONT_mbtowc
*
- * Returns a Unicode translation of str. If count is -1 then str is
- * assumed to be '\0' terminated, otherwise it contains the number of
- * bytes to convert. If plenW is non-NULL, on return it will point to
- * the number of WCHARs that have been written. The caller should free
- * the returned LPWSTR from the process heap itself.
+ * Returns a Unicode translation of str using the charset of the
+ * currently selected font in hdc. If count is -1 then str is assumed
+ * to be '\0' terminated, otherwise it contains the number of bytes to
+ * convert. If plenW is non-NULL, on return it will point to the
+ * 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;
INT lenW;
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);
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);
TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
if(plenW) *plenW = lenW;
+ if(pCP) *pCP = cp;
return strW;
}
@@ -1021,7 +1064,7 @@ BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
{
BOOL ret = FALSE;
INT wlen;
- LPWSTR p = FONT_mbtowc(str, count, &wlen);
+ LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
if (p) {
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))))
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);
if (walpDx)
{
@@ -1663,7 +1706,7 @@ BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
for(i = 0; i < count; 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++)
{
@@ -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 )
{
INT wlen;
+ UINT codepage;
LPWSTR p;
BOOL ret;
LPINT lpDxW = NULL;
@@ -1698,14 +1742,14 @@ BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
if (flags & ETO_GLYPH_INDEX)
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) {
unsigned int i = 0, j = 0;
lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
while(i < count) {
- if(IsDBCSLeadByte(str[i])) {
+ if(IsDBCSLeadByteEx(codepage, str[i])) {
lpDxW[j++] = lpDx[i] + lpDx[i+1];
i = i + 2;
} else {
@@ -2310,7 +2354,7 @@ BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
for(i = 0; i < count; 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++)
{
@@ -2448,7 +2492,7 @@ DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
len = 1;
mbchs[0] = (uChar & 0xff);
}
- p = FONT_mbtowc(mbchs, len, NULL);
+ p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
c = p[0];
} else
c = uChar;
@@ -2754,7 +2798,7 @@ DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
TRACE("(%p, %s, %d, %p, 0x%x)\n",
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);
HeapFree(GetProcessHeap(), 0, lpstrW);
@@ -2799,6 +2843,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
INT uCountW;
GCP_RESULTSW resultsW;
DWORD ret;
+ UINT font_cp;
TRACE("%s, %d, %d, 0x%08x\n",
debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
@@ -2806,7 +2851,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
/* both structs are equal in size */
memcpy(&resultsW, lpResults, sizeof(resultsW));
- lpStringW = FONT_mbtowc(lpString, uCount, &uCountW);
+ lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
if(lpResults->lpOutString)
resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
@@ -2816,7 +2861,7 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
lpResults->nMaxFit = resultsW.nMaxFit;
if(lpResults->lpOutString) {
- WideCharToMultiByte(CP_ACP, 0, resultsW.lpOutString, uCountW,
+ WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
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++)
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++)
{
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 670ec36..5dddf3a 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -26,9 +26,13 @@
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
+#include "winnls.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)
{
return 0;
@@ -432,7 +436,7 @@ static void test_text_extents(void)
GetTextExtentExPointW(hdc, wt, 1, 1, &fit1, &fit2, &sz1);
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);
DeleteObject(hfont);
ReleaseDC(0, hdc);
@@ -615,7 +619,7 @@ static void test_GetKerningPairs(void)
GetKerningPairsW(hdc, 0, NULL);
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);
return;
}
@@ -740,14 +744,14 @@ static void test_GetOutlineTextMetrics(void)
HDC hdc;
DWORD ret, otm_size;
- hdc = GetDC(0);
-
if (!is_font_installed("Arial"))
{
skip("Arial is not installed\n");
return;
}
+ hdc = GetDC(0);
+
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = -13;
@@ -817,6 +821,114 @@ static void test_GetOutlineTextMetrics(void)
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)
{
test_logfont();
@@ -828,4 +940,5 @@ START_TEST(font)
test_GetGlyphIndices();
test_GetKerningPairs();
test_GetOutlineTextMetrics();
+ test_font_charset();
}
--
1.4.4.4
More information about the wine-patches
mailing list