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