Jacek Caban : gdi32: Use local helpers for Unicode conversion in Unix lib.

Alexandre Julliard julliard at winehq.org
Mon Oct 4 15:42:19 CDT 2021


Module: wine
Branch: master
Commit: 763d8aa1cd41687213284cb1a5b6696066c6338a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=763d8aa1cd41687213284cb1a5b6696066c6338a

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Oct  4 15:03:20 2021 +0100

gdi32: Use local helpers for Unicode conversion in Unix lib.

Based on ntdll.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/font.c           | 99 +++++++++++++++++++++++++++++++++++++++++++--
 dlls/gdi32/freetype.c       | 10 ++---
 dlls/gdi32/win32u_private.h |  5 +++
 3 files changed, 106 insertions(+), 8 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 0b32a94f7fe..c6bc3a716be 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3200,6 +3200,7 @@ static UINT get_glyph_index_symbol( struct gdi_font *font, UINT glyph )
 CPTABLEINFO *get_cptable( WORD cp )
 {
     static CPTABLEINFO tables[100];
+    CPTABLEINFO *info;
     unsigned int i;
     USHORT *ptr;
     SIZE_T size;
@@ -3207,9 +3208,101 @@ CPTABLEINFO *get_cptable( WORD cp )
     for (i = 0; i < ARRAY_SIZE(tables) && tables[i].CodePage; i++)
         if (tables[i].CodePage == cp) return &tables[i];
     if (NtGetNlsSectionPtr( 11, cp, NULL, (void **)&ptr, &size )) return NULL;
-    if (i == ARRAY_SIZE(tables)) ERR( "too many code pages\n" );
-    RtlInitCodePageTable( ptr, &tables[i] );
-    return &tables[i];
+    if (i == ARRAY_SIZE(tables))
+    {
+        ERR( "too many code pages\n" );
+        return NULL;
+    }
+
+    info = &tables[i];
+    info->CodePage             = ptr[1];
+    info->MaximumCharacterSize = ptr[2];
+    info->DefaultChar          = ptr[3];
+    info->UniDefaultChar       = ptr[4];
+    info->TransDefaultChar     = ptr[5];
+    info->TransUniDefaultChar  = ptr[6];
+    memcpy( info->LeadByte, ptr + 7, sizeof(info->LeadByte) );
+    ptr += ptr[0];
+
+    info->WideCharTable = ptr + ptr[0] + 1;
+    info->MultiByteTable = ++ptr;
+    ptr += 256;
+    if (*ptr++) ptr += 256;  /* glyph table */
+    info->DBCSRanges = ptr;
+    if (*ptr)  /* dbcs ranges */
+    {
+        info->DBCSCodePage = 1;
+        info->DBCSOffsets  = ptr + 1;
+    }
+    else
+    {
+        info->DBCSCodePage = 0;
+        info->DBCSOffsets  = NULL;
+    }
+
+    return info;
+}
+
+DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src, DWORD srclen )
+{
+    DWORD i, ret;
+
+    if (!info && !(info = get_cptable( get_acp() ))) return 0;
+
+    srclen /= sizeof(WCHAR);
+    if (info->DBCSCodePage)
+    {
+        WCHAR *uni2cp = info->WideCharTable;
+
+        for (i = dstlen; srclen && i; i--, srclen--, src++)
+        {
+            if (uni2cp[*src] & 0xff00)
+            {
+                if (i == 1) break;  /* do not output a partial char */
+                i--;
+                *dst++ = uni2cp[*src] >> 8;
+            }
+            *dst++ = (char)uni2cp[*src];
+        }
+        ret = dstlen - i;
+    }
+    else
+    {
+        char *uni2cp = info->WideCharTable;
+        ret = min( srclen, dstlen );
+        for (i = 0; i < ret; i++) dst[i] = uni2cp[src[i]];
+    }
+    return ret;
+}
+
+DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src, DWORD srclen )
+{
+    DWORD i, ret;
+
+    if (!info && !(info = get_cptable( get_acp() ))) return 0;
+
+    dstlen /= sizeof(WCHAR);
+    if (info->DBCSOffsets)
+    {
+        for (i = dstlen; srclen && i; i--, srclen--, src++, dst++)
+        {
+            USHORT off = info->DBCSOffsets[(unsigned char)*src];
+            if (off && srclen > 1)
+            {
+                src++;
+                srclen--;
+                *dst = info->DBCSOffsets[off + (unsigned char)*src];
+            }
+            else *dst = info->MultiByteTable[(unsigned char)*src];
+        }
+        ret = dstlen - i;
+    }
+    else
+    {
+        ret = min( srclen, dstlen );
+        for (i = 0; i < ret; i++) dst[i] = info->MultiByteTable[(unsigned char)src[i]];
+    }
+    return ret * sizeof(WCHAR);
 }
 
 static BOOL wc_to_index( UINT cp, WCHAR wc, unsigned char *dst, BOOL allow_default )
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 44d5dc26cff..04b24b7f570 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -602,7 +602,7 @@ static WCHAR *towstr(const char *str)
 {
     DWORD len = strlen(str) + 1;
     WCHAR *wstr = malloc( len * sizeof(WCHAR) );
-    RtlMultiByteToUnicodeN( wstr, len * sizeof(WCHAR), &len, str, len );
+    win32u_mbtowc( NULL, wstr, len * sizeof(WCHAR), str, len );
     return wstr;
 }
 
@@ -805,8 +805,8 @@ static WCHAR *copy_name_table_string( const FT_SfntName *name )
     case TT_PLATFORM_MACINTOSH:
         if (!(cp = get_mac_code_page( name ))) return NULL;
         ret = malloc( (name->string_len + 1) * sizeof(WCHAR) );
-        RtlCustomCPToUnicodeN( cp, ret, name->string_len * sizeof(WCHAR), &i,
-                               (char *)name->string, name->string_len );
+        i = win32u_mbtowc( cp, ret, name->string_len * sizeof(WCHAR),
+                           (char *)name->string, name->string_len );
         ret[i / sizeof(WCHAR)] = 0;
         return ret;
     }
@@ -1165,7 +1165,7 @@ static WCHAR *decode_opentype_name( struct opentype_name *name )
     {
         CPTABLEINFO *cptable = get_cptable( name->codepage );
         if (!cptable) return NULL;
-        RtlCustomCPToUnicodeN( cptable, buffer, sizeof(buffer), &len, name->bytes, name->length );
+        len = win32u_mbtowc( cptable, buffer, sizeof(buffer), name->bytes, name->length );
         len /= sizeof(WCHAR);
     }
 
@@ -2577,7 +2577,7 @@ static BOOL CDECL freetype_get_glyph_index( struct gdi_font *font, UINT *glyph,
             DWORD len;
             char ch;
 
-            RtlUnicodeToMultiByteN( &ch, 1, &len, &wc, sizeof(wc) );
+            len = win32u_wctomb( NULL, &ch, 1, &wc, sizeof(wc) );
             if (len) *glyph = get_glyph_index_symbol( font, (unsigned char)ch );
         }
         return TRUE;
diff --git a/dlls/gdi32/win32u_private.h b/dlls/gdi32/win32u_private.h
index d986bf339c3..f867c556bff 100644
--- a/dlls/gdi32/win32u_private.h
+++ b/dlls/gdi32/win32u_private.h
@@ -395,4 +395,9 @@ static inline LONG win32u_wcstol( LPCWSTR s, LPWSTR *end, INT base )
 #define wcsrchr(s,c)    win32u_wcsrchr(s,c)
 #define wcstol(s,e,b)   win32u_wcstol(s,e,b)
 
+DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src,
+                     DWORD srclen ) DECLSPEC_HIDDEN;
+DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src,
+                     DWORD srclen ) DECLSPEC_HIDDEN;
+
 #endif /* __WINE_WIN32U_PRIVATE */




More information about the wine-cvs mailing list