From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com --- dlls/gdi32/font.c | 45 +++-------------------- dlls/gdi32/text.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ include/ntgdi.h | 6 ++- 3 files changed, 103 insertions(+), 41 deletions(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index cdd3ca24034..c88e69ef013 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -4862,11 +4862,10 @@ static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT }
/*********************************************************************** - * GetCharWidthW (GDI32.@) - * GetCharWidth32W (GDI32.@) + * NtGdiGetCharWidthW (win32u.@) */ -BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar, - LPINT buffer ) +BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT firstChar, UINT lastChar, WCHAR *chars, + ULONG flags, void *buf ) { UINT i; BOOL ret; @@ -4876,10 +4875,11 @@ BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar, if (!dc) return FALSE;
dev = GET_DC_PHYSDEV( dc, pGetCharWidth ); - ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer ); + ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buf );
if (ret) { + INT *buffer = buf; /* convert device units to logical */ for( i = firstChar; i <= lastChar; i++, buffer++ ) *buffer = width_to_LP( dc, *buffer ); @@ -4889,41 +4889,6 @@ BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar, }
-/*********************************************************************** - * GetCharWidthA (GDI32.@) - * GetCharWidth32A (GDI32.@) - */ -BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar, - LPINT buffer ) -{ - INT i, wlen; - LPSTR str; - LPWSTR wstr; - BOOL ret = TRUE; - - str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i); - if(str == NULL) - return FALSE; - - wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL); - - for(i = 0; i < wlen; i++) - { - if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer)) - { - ret = FALSE; - break; - } - buffer++; - } - - HeapFree(GetProcessHeap(), 0, str); - HeapFree(GetProcessHeap(), 0, wstr); - - return ret; -} - - /* helper for nulldrv_ExtTextOut */ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT flags, UINT aa_flags, GLYPHMETRICS *metrics, struct gdi_image_bits *image ) diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c index acc796fce30..167aa5cc07d 100644 --- a/dlls/gdi32/text.c +++ b/dlls/gdi32/text.c @@ -1570,3 +1570,96 @@ UINT WINAPI GetOutlineTextMetricsW( HDC hdc, UINT size, OUTLINETEXTMETRICW *otm { return NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 ); } + +/*********************************************************************** + * GetCharWidthW (GDI32.@) + * GetCharWidth32W (GDI32.@) + */ +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 ) +{ + INT i, count = last - first + 1; + UINT mbcp; + UINT c; + LPSTR str; + + if (count <= 0) + return NULL; + + mbcp = GdiGetCodePage( hdc ); + switch (mbcp) + { + case 932: + case 936: + case 949: + case 950: + case 1361: + if (last > 0xffff) + return NULL; + if ((first ^ last) > 0xff) + return NULL; + break; + default: + if (last > 0xff) + return NULL; + mbcp = 0; + break; + } + + if (!(str = HeapAlloc( GetProcessHeap(), 0, count * 2 + 1 ))) + return NULL; + + for (i = 0, c = first; c <= last; i++, c++) + { + if (mbcp) { + if (c > 0xff) + str[i++] = (BYTE)(c >> 8); + if (c <= 0xff && IsDBCSLeadByteEx( mbcp, c )) + str[i] = 0x1f; /* FIXME: use default character */ + else + str[i] = (BYTE)c; + } + else + str[i] = (BYTE)c; + } + str[i] = '\0'; + + *byte_len = i; + return str; +} + +/*********************************************************************** + * GetCharWidthA (GDI32.@) + * GetCharWidth32A (GDI32.@) + */ +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++; + } + + HeapFree( GetProcessHeap(), 0, str ); + HeapFree( GetProcessHeap(), 0, wstr ); + return ret; +} diff --git a/include/ntgdi.h b/include/ntgdi.h index 66611b38fb0..7e75b944e85 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -123,6 +123,9 @@ enum NtGdiSetDIBColorTable, };
+#define NTGDI_GETCHARWIDTH_INT 0x02 +#define NTGDI_GETCHARWIDTH_INDICES 0x08 + #define MWT_SET 4
/* structs not compatible with native Windows */ @@ -227,7 +230,8 @@ INT WINAPI NtGdiGetAppClipBox( HDC hdc, RECT *rect ); BOOL WINAPI NtGdiGetBitmapDimension( HBITMAP bitmap, SIZE *size ); UINT WINAPI NtGdiGetBoundsRect( HDC hdc, RECT *rect, UINT flags ); BOOL WINAPI NtGdiGetCharABCWidthsW( HDC hdc, UINT first_char, UINT last_char, ABC *abc ); -BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT first_char, UINT last_char, INT *buffer ); +BOOL WINAPI NtGdiGetCharWidthW( HDC hdc, UINT first_char, UINT last_char, WCHAR *chars, + ULONG flags, void *buffer ); BOOL WINAPI NtGdiGetDCDword( HDC hdc, UINT method, DWORD *result ); BOOL WINAPI NtGdiGetDCPoint( HDC hdc, UINT method, POINT *result ); INT WINAPI NtGdiGetDeviceCaps( HDC hdc, INT cap );