Jacek Caban : gdi32: Support passing an array of chars to NtGdiGetCharWidthW.

Alexandre Julliard julliard at winehq.org
Thu Aug 26 15:22:31 CDT 2021


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Aug 26 13:45:15 2021 +0100

gdi32: Support passing an array of chars to NtGdiGetCharWidthW.

And use it for GetCharWidthA.

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/driver.c       |  3 ++-
 dlls/gdi32/font.c         | 29 ++++++++++++++++-------------
 dlls/gdi32/text.c         | 38 ++++++++++++--------------------------
 dlls/wineps.drv/builtin.c | 24 +++++++++++++-----------
 dlls/wineps.drv/psdrv.h   |  2 +-
 include/wine/gdi_driver.h |  4 ++--
 6 files changed, 46 insertions(+), 54 deletions(-)

diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index f370d088585..3d64eedc638 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -380,7 +380,8 @@ static BOOL CDECL nulldrv_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count
     return FALSE;
 }
 
-static BOOL CDECL nulldrv_GetCharWidth( PHYSDEV dev, UINT first, UINT last, INT *buffer )
+static BOOL CDECL nulldrv_GetCharWidth( PHYSDEV dev, UINT first, UINT count,
+                                        const WCHAR *chars, INT *buffer )
 {
     return FALSE;
 }
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index c88e69ef013..7e4d67af8ae 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3089,27 +3089,29 @@ static BOOL CDECL font_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count, W
 /*************************************************************
  * font_GetCharWidth
  */
-static BOOL CDECL font_GetCharWidth( PHYSDEV dev, UINT first, UINT last, INT *buffer )
+static BOOL CDECL font_GetCharWidth( PHYSDEV dev, UINT first, UINT count,
+                                     const WCHAR *chars, INT *buffer )
 {
     struct font_physdev *physdev = get_font_dev( dev );
+    UINT c, i;
     ABC abc;
-    UINT c;
 
     if (!physdev->font)
     {
         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
-        return dev->funcs->pGetCharWidth( dev, first, last, buffer );
+        return dev->funcs->pGetCharWidth( dev, first, count, chars, buffer );
     }
 
-    TRACE( "%p, %d, %d, %p\n", physdev->font, first, last, buffer );
+    TRACE( "%p, %d, %d, %p\n", physdev->font, first, count, buffer );
 
     EnterCriticalSection( &font_cs );
-    for (c = first; c <= last; c++)
+    for (i = 0; i < count; i++)
     {
+        c = chars ? chars[i] : i + first;
         if (get_glyph_outline( physdev->font, c, GGO_METRICS, NULL, &abc, 0, NULL, NULL ) == GDI_ERROR)
-            buffer[c - first] = 0;
+            buffer[i] = 0;
         else
-            buffer[c - first] = abc.abcA + abc.abcB + abc.abcC;
+            buffer[i] = abc.abcA + abc.abcB + abc.abcC;
     }
     LeaveCriticalSection( &font_cs );
     return TRUE;
@@ -4864,25 +4866,26 @@ static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT
 /***********************************************************************
  *           NtGdiGetCharWidthW    (win32u.@)
  */
-BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT firstChar, UINT lastChar, WCHAR *chars,
+BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT first, UINT last, WCHAR *chars,
                                 ULONG flags, void *buf )
 {
-    UINT i;
+    UINT i, count = last;
     BOOL ret;
     PHYSDEV dev;
     DC * dc = get_dc_ptr( hdc );
 
     if (!dc) return FALSE;
 
+    if (!chars) count = last - first + 1;
     dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
-    ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buf );
+    ret = dev->funcs->pGetCharWidth( dev, first, count, chars, buf );
 
     if (ret)
     {
         INT *buffer = buf;
         /* convert device units to logical */
-        for( i = firstChar; i <= lastChar; i++, buffer++ )
-            *buffer = width_to_LP( dc, *buffer );
+        for (i = 0; i < count; i++)
+            buffer[i] = width_to_LP( dc, buffer[i] );
     }
     release_dc_ptr( dc );
     return ret;
@@ -6479,7 +6482,7 @@ BOOL WINAPI GetCharWidthFloatW( HDC hdc, UINT first, UINT last, float *buffer )
     }
 
     dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
-    if ((ret = dev->funcs->pGetCharWidth( dev, first, last, ibuffer )))
+    if ((ret = dev->funcs->pGetCharWidth( dev, first, last - first + 1, NULL, ibuffer )))
     {
         float scale = fabs( dc->xformVport2World.eM11 ) / 16.0f;
         for (i = first; i <= last; ++i)
diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c
index 167aa5cc07d..0bb47f00c24 100644
--- a/dlls/gdi32/text.c
+++ b/dlls/gdi32/text.c
@@ -1580,12 +1580,13 @@ BOOL WINAPI GetCharWidth32W( HDC hdc, UINT first, UINT last, INT *buffer )
     return NtGdiGetCharWidthW( hdc, first, last, NULL, NTGDI_GETCHARWIDTH_INT, buffer );
 }
 
-static char *get_chars_by_range( HDC hdc, UINT first, UINT last, INT *byte_len )
+static WCHAR *get_chars_by_range( HDC hdc, UINT first, UINT last, INT *ret_len )
 {
     INT i, count = last - first + 1;
+    WCHAR *wstr;
+    char *str;
     UINT mbcp;
     UINT c;
-    LPSTR str;
 
     if (count <= 0)
         return NULL;
@@ -1628,8 +1629,9 @@ static char *get_chars_by_range( HDC hdc, UINT first, UINT last, INT *byte_len )
     }
     str[i] = '\0';
 
-    *byte_len = i;
-    return str;
+    wstr = text_mbtowc( hdc, str, i, ret_len, NULL );
+    HeapFree( GetProcessHeap(), 0, str );
+    return wstr;
 }
 
 /***********************************************************************
@@ -1638,28 +1640,12 @@ static char *get_chars_by_range( HDC hdc, UINT first, UINT last, INT *byte_len )
  */
 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT first, UINT last, INT *buffer )
 {
-    INT i, wlen;
-    LPSTR str;
-    LPWSTR wstr;
-    BOOL ret = TRUE;
-
-    str = get_chars_by_range( hdc, first, last, &i );
-    if (str == NULL)
-        return FALSE;
-
-    wstr = text_mbtowc( hdc, str, i, &wlen, NULL );
-
-    for(i = 0; i < wlen; i++)
-    {
-	if(!GetCharWidth32W( hdc, wstr[i], wstr[i], buffer ))
-	{
-	    ret = FALSE;
-	    break;
-	}
-	buffer++;
-    }
+    WCHAR *chars;
+    INT count;
+    BOOL ret;
 
-    HeapFree( GetProcessHeap(), 0, str );
-    HeapFree( GetProcessHeap(), 0, wstr );
+    if (!(chars = get_chars_by_range( hdc, first, last, &count ))) return FALSE;
+    ret = NtGdiGetCharWidthW( hdc, 0, count, chars, NTGDI_GETCHARWIDTH_INT, buffer );
+    HeapFree( GetProcessHeap(), 0, chars );
     return ret;
 }
diff --git a/dlls/wineps.drv/builtin.c b/dlls/wineps.drv/builtin.c
index 22397567aa4..11ba2154148 100644
--- a/dlls/wineps.drv/builtin.c
+++ b/dlls/wineps.drv/builtin.c
@@ -343,28 +343,30 @@ BOOL CDECL PSDRV_GetTextExtentExPoint(PHYSDEV dev, LPCWSTR str, INT count, LPINT
 /***********************************************************************
  *           PSDRV_GetCharWidth
  */
-BOOL CDECL PSDRV_GetCharWidth(PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer)
+BOOL CDECL PSDRV_GetCharWidth(PHYSDEV dev, UINT first, UINT count, const WCHAR *chars, INT *buffer)
 {
     PSDRV_PDEVICE *physDev = get_psdrv_dev( dev );
-    UINT    	    i;
+    UINT i, c;
 
     if (physDev->font.fontloc == Download)
     {
         dev = GET_NEXT_PHYSDEV( dev, pGetCharWidth );
-        return dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
+        return dev->funcs->pGetCharWidth( dev, first, count, chars, buffer );
     }
 
-    TRACE("U+%.4X U+%.4X\n", firstChar, lastChar);
+    TRACE("U+%.4X +%u\n", first, count);
 
-    if (lastChar > 0xffff || firstChar > lastChar)
+    for (i = 0; i < count; ++i)
     {
-    	SetLastError(ERROR_INVALID_PARAMETER);
-    	return FALSE;
-    }
+        c = chars ? chars[i] : first + i;
 
-    for (i = firstChar; i <= lastChar; ++i)
-    {
-        *buffer = floor( PSDRV_UVMetrics(i, physDev->font.fontinfo.Builtin.afm)->WX
+        if (c > 0xffff)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+
+        *buffer = floor( PSDRV_UVMetrics(c, physDev->font.fontinfo.Builtin.afm)->WX
                          * physDev->font.fontinfo.Builtin.scale + 0.5 );
 	TRACE("U+%.4X: %i\n", i, *buffer);
 	++buffer;
diff --git a/dlls/wineps.drv/psdrv.h b/dlls/wineps.drv/psdrv.h
index 84828a5c9ce..db7c6e37f7c 100644
--- a/dlls/wineps.drv/psdrv.h
+++ b/dlls/wineps.drv/psdrv.h
@@ -439,7 +439,7 @@ extern INT CDECL PSDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID
 extern BOOL CDECL PSDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
                                     const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx ) DECLSPEC_HIDDEN;
 extern BOOL CDECL PSDRV_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
-extern BOOL CDECL PSDRV_GetCharWidth(PHYSDEV dev, UINT firstChar, UINT lastChar, LPINT buffer) DECLSPEC_HIDDEN;
+extern BOOL CDECL PSDRV_GetCharWidth(PHYSDEV dev, UINT first, UINT count, const WCHAR *chars, INT *buffer) DECLSPEC_HIDDEN;
 extern BOOL CDECL PSDRV_GetTextExtentExPoint(PHYSDEV dev, LPCWSTR str, INT count, LPINT alpDx) DECLSPEC_HIDDEN;
 extern BOOL CDECL PSDRV_GetTextMetrics(PHYSDEV dev, TEXTMETRICW *metrics) DECLSPEC_HIDDEN;
 extern BOOL CDECL PSDRV_LineTo(PHYSDEV dev, INT x, INT y) DECLSPEC_HIDDEN;
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h
index 5ca84ccf56c..6db6cf94b70 100644
--- a/include/wine/gdi_driver.h
+++ b/include/wine/gdi_driver.h
@@ -99,7 +99,7 @@ struct gdi_dc_funcs
     UINT     (CDECL *pGetBoundsRect)(PHYSDEV,RECT*,UINT);
     BOOL     (CDECL *pGetCharABCWidths)(PHYSDEV,UINT,UINT,LPABC);
     BOOL     (CDECL *pGetCharABCWidthsI)(PHYSDEV,UINT,UINT,WORD*,LPABC);
-    BOOL     (CDECL *pGetCharWidth)(PHYSDEV,UINT,UINT,LPINT);
+    BOOL     (CDECL *pGetCharWidth)(PHYSDEV,UINT,UINT,const WCHAR*,LPINT);
     BOOL     (CDECL *pGetCharWidthInfo)(PHYSDEV,void*);
     INT      (CDECL *pGetDeviceCaps)(PHYSDEV,INT);
     BOOL     (CDECL *pGetDeviceGammaRamp)(PHYSDEV,LPVOID);
@@ -169,7 +169,7 @@ struct gdi_dc_funcs
 };
 
 /* increment this when you change the DC function table */
-#define WINE_GDI_DRIVER_VERSION 64
+#define WINE_GDI_DRIVER_VERSION 65
 
 #define GDI_PRIORITY_NULL_DRV        0  /* null driver */
 #define GDI_PRIORITY_FONT_DRV      100  /* any font driver */




More information about the wine-cvs mailing list