From 865be24a2516518250badb5325220eacff2a126f Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 1 Sep 2021 14:08:27 +0200 Subject: [PATCH] gdi32: Use NtGdiEnumFonts for EnumFontFamiliesExW. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/font.c | 100 +++++++++++++++++++++------------------------- dlls/gdi32/text.c | 43 ++++++++++++++++++++ include/ntgdi.h | 9 +++++ 3 files changed, 98 insertions(+), 54 deletions(-) diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 5e9cefa0c7d..ef57c4f9e49 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -196,15 +196,6 @@ typedef struct LOGFONTW logfont; } FONTOBJ; -struct font_enum -{ - LPLOGFONTW lpLogFontParam; - FONTENUMPROCW lpEnumFunc; - LPARAM lpData; - HDC hdc; - INT retval; -}; - /* * For TranslateCharsetInfo */ @@ -4315,64 +4306,65 @@ static BOOL FONT_DeleteObject( HGDIOBJ handle ) } -/*********************************************************************** - * FONT_EnumInstance - * - * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW. - * We have to use other types because of the FONTENUMPROCW definition. - */ -static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm, - DWORD fType, LPARAM lp ) +struct font_enum { - struct font_enum *pfe = (struct font_enum *)lp; - INT ret = 1; + HDC hdc; + struct font_enum_entry *buf; + ULONG size; + ULONG count; + ULONG charset; +}; - /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */ - if ((!pfe->lpLogFontParam || - pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || - pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) && - (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) ) +static INT WINAPI font_enum_proc( const LOGFONTW *lf, const TEXTMETRICW *tm, + DWORD type, LPARAM lp ) +{ + struct font_enum *fe = (struct font_enum *)lp; + + if (fe->charset != DEFAULT_CHARSET && lf->lfCharSet != fe->charset) return 1; + if ((type & RASTER_FONTTYPE) && !(NtGdiGetDeviceCaps( fe->hdc, TEXTCAPS ) & TC_RA_ABLE)) + return 1; + + if (fe->buf && fe->count < fe->size) { - ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData ); - pfe->retval = ret; + fe->buf[fe->count].type = type; + fe->buf[fe->count].lf = *(const ENUMLOGFONTEXW *)lf; + fe->buf[fe->count].tm = *(const NEWTEXTMETRICEXW *)tm; } - return ret; + fe->count++; + return 1; } /*********************************************************************** - * FONT_EnumFontFamiliesEx + * NtGdiEnumFonts (win32u.@) */ -static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc, - LPARAM lParam ) +BOOL WINAPI NtGdiEnumFonts( HDC hdc, ULONG type, ULONG win32_compat, ULONG face_name_len, + const WCHAR *face_name, ULONG charset, ULONG *count, void *buf ) { - INT ret = 0; - DC *dc = get_dc_ptr( hDC ); struct font_enum fe; + PHYSDEV physdev; + LOGFONTW lf; + BOOL ret; + DC *dc; - if (dc) - { - PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts ); + if (!(dc = get_dc_ptr( hdc ))) return 0; - if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet); - fe.lpLogFontParam = plf; - fe.lpEnumFunc = efproc; - fe.lpData = lParam; - fe.hdc = hDC; - fe.retval = 1; - ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe ); - release_dc_ptr( dc ); - } - return ret ? fe.retval : 0; -} + memset( &lf, 0, sizeof(lf) ); + lf.lfCharSet = charset; + if (face_name_len) memcpy( lf.lfFaceName, face_name, face_name_len * sizeof(WCHAR) ); -/*********************************************************************** - * EnumFontFamiliesExW (GDI32.@) - */ -INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf, - FONTENUMPROCW efproc, - LPARAM lParam, DWORD dwFlags ) -{ - return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam ); + fe.hdc = hdc; + fe.buf = buf; + fe.size = *count / sizeof(*fe.buf); + fe.count = 0; + fe.charset = charset; + + physdev = GET_DC_PHYSDEV( dc, pEnumFonts ); + ret = physdev->funcs->pEnumFonts( physdev, &lf, font_enum_proc, (LPARAM)&fe ); + if (ret && buf) ret = fe.count <= fe.size; + *count = fe.count * sizeof(*fe.buf); + + release_dc_ptr( dc ); + return ret; } diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c index d500a19a65a..8cc6ec25353 100644 --- a/dlls/gdi32/text.c +++ b/dlls/gdi32/text.c @@ -2037,6 +2037,49 @@ BOOL WINAPI GdiRealizationInfo( HDC hdc, struct realization_info *info ) return TRUE; } +/*********************************************************************** + * EnumFontFamiliesExW (GDI32.@) + */ +INT WINAPI EnumFontFamiliesExW( HDC hdc, LOGFONTW *lf, FONTENUMPROCW efproc, + LPARAM lparam, DWORD flags ) +{ + struct font_enum_entry buf[32], *entries = buf; + const WCHAR *face_name = NULL; + DWORD charset, face_name_len = 0; + ULONG count, i; + INT ret = 1; + + if (lf) + { + if (lf->lfFaceName[0]) + { + face_name = lf->lfFaceName; + face_name_len = lstrlenW( face_name ); + } + charset = lf->lfCharSet; + } + else charset = DEFAULT_CHARSET; + + count = sizeof(buf); + if (!NtGdiEnumFonts( hdc, 0, 0, face_name_len, face_name, charset, &count, buf ) && + count <= sizeof(buf)) + return 0; + if (count > sizeof(buf)) + { + if (!(entries = HeapAlloc( GetProcessHeap(), 0, count ))) return 0; + ret = NtGdiEnumFonts( hdc, 0, 0, face_name_len, face_name, charset, &count, entries ); + } + count /= sizeof(*entries); + for (i = 0; ret && i < count; i++) + { + ret = efproc( (const LOGFONTW *)&entries[i].lf, (const TEXTMETRICW *)&entries[i].tm, + entries[i].type, lparam ); + } + + if (entries != buf) HeapFree( GetProcessHeap(), 0, entries ); + return ret; +} + struct enum_proc_paramsWtoA { LPARAM lparam; diff --git a/include/ntgdi.h b/include/ntgdi.h index f03b12a09ae..a3cf54d785a 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -171,6 +171,13 @@ typedef struct DC_ATTR void *emf; } DC_ATTR; +struct font_enum_entry +{ + DWORD type; + ENUMLOGFONTEXW lf; + NEWTEXTMETRICEXW tm; +}; + #endif /* __WINESRC__ */ struct font_realization_info @@ -259,6 +266,8 @@ HRGN WINAPI NtGdiExtCreateRegion( const XFORM *xform, DWORD count, const RGN INT WINAPI NtGdiExtGetObjectW( HGDIOBJ handle, INT count, void *buffer ); INT WINAPI NtGdiExtSelectClipRgn( HDC hdc, HRGN region, INT mode ); BOOL WINAPI NtGdiFillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush ); +BOOL WINAPI NtGdiEnumFonts( HDC hdc, ULONG type, ULONG win32_compat, ULONG face_name_len, + const WCHAR *face_name, ULONG charset, ULONG *count, void *buf ); INT WINAPI NtGdiExtEscape( HDC hdc, WCHAR *driver, INT driver_id, INT escape, INT input_size, const char *input, INT output_size, char *output ); BOOL WINAPI NtGdiExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, UINT type );