diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 220760b6bdf..6c88b4d461f 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -651,6 +651,11 @@ static HBRUSH CDECL nulldrv_SelectBrush( PHYSDEV dev, HBRUSH brush, const struct return brush; } +static HFONT CDECL nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *aa_flags ) +{ + return font; +} + static HPALETTE CDECL nulldrv_SelectPalette( PHYSDEV dev, HPALETTE palette, BOOL bkgnd ) { return palette; diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 9c57870e2a1..cf27f6063ee 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -60,6 +60,10 @@ static const struct font_backend_funcs *font_funcs; static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} }; +static UINT font_smoothing = GGO_BITMAP; +static UINT subpixel_orientation = GGO_GRAY4_BITMAP; +static BOOL antialias_fakes = TRUE; + /* Device -> World size conversion */ /* Performs a device to world transformation on the specified width (which @@ -1636,6 +1640,7 @@ static void release_gdi_font( struct gdi_font *font ) TRACE( "font %p\n", font ); /* add it to the unused list */ + EnterCriticalSection( &font_cs ); list_add_head( &unused_gdi_font_list, &font->unused_entry ); if (unused_font_count > UNUSED_CACHE_SIZE) { @@ -1644,9 +1649,9 @@ static void release_gdi_font( struct gdi_font *font ) list_remove( &font->entry ); list_remove( &font->unused_entry ); free_gdi_font( font ); - return; } - unused_font_count++; + else unused_font_count++; + LeaveCriticalSection( &font_cs ); } static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl, int dpi) @@ -2929,27 +2934,46 @@ static BOOL CDECL font_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics ) */ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) { - UINT default_aa_flags = *aa_flags; struct font_physdev *physdev = get_font_dev( dev ); - struct gdi_font *prev = physdev->font; + struct gdi_font *font = NULL, *prev = physdev->font; DC *dc = get_physdev_dc( dev ); - if (!default_aa_flags) - { - PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont ); - next->funcs->pSelectFont( next, hfont, &default_aa_flags ); - } - if (hfont) { + LOGFONTW lf; + + GetObjectW( hfont, sizeof(lf), &lf ); + switch (lf.lfQuality) + { + case NONANTIALIASED_QUALITY: + if (!*aa_flags) *aa_flags = GGO_BITMAP; + break; + case ANTIALIASED_QUALITY: + if (!*aa_flags) *aa_flags = GGO_GRAY4_BITMAP; + break; + } + EnterCriticalSection( &font_cs ); - physdev->font = font_funcs->pSelectFont( dc, hfont, aa_flags, default_aa_flags ); + + font = font_funcs->pSelectFont( dc, hfont ); + if (font && !*aa_flags) + { + *aa_flags = font->aa_flags; + if (!*aa_flags) + { + if (lf.lfQuality == CLEARTYPE_QUALITY || lf.lfQuality == CLEARTYPE_NATURAL_QUALITY) + *aa_flags = subpixel_orientation; + else + *aa_flags = font_smoothing; + } + *aa_flags = font_funcs->get_aa_flags( font, *aa_flags, antialias_fakes ); + } + TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags ); LeaveCriticalSection( &font_cs ); } - else physdev->font = NULL; /* notification that the font has been changed by another driver */ - + physdev->font = font; if (prev) release_gdi_font( prev ); - return physdev->font ? hfont : 0; + return font ? hfont : 0; } @@ -3089,6 +3113,68 @@ const struct gdi_dc_funcs font_driver = GDI_PRIORITY_FONT_DRV /* priority */ }; +static DWORD get_key_value( HKEY key, const WCHAR *name, DWORD *value ) +{ + WCHAR buf[12]; + DWORD count = sizeof(buf), type, err; + + err = RegQueryValueExW( key, name, NULL, &type, (BYTE *)buf, &count ); + if (!err) + { + if (type == REG_DWORD) memcpy( value, buf, sizeof(*value) ); + else *value = atoiW( buf ); + } + return err; +} + +static void init_font_options(void) +{ + static const WCHAR antialias_fake_bold_or_italic[] = { 'A','n','t','i','a','l','i','a','s','F','a','k','e', + 'B','o','l','d','O','r','I','t','a','l','i','c',0 }; + static const WCHAR true_options[] = { 'y','Y','t','T','1',0 }; + static const WCHAR desktopW[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\', + 'D','e','s','k','t','o','p',0 }; + static const WCHAR smoothing[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',0}; + static const WCHAR smoothing_type[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0}; + static const WCHAR smoothing_orientation[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g', + 'O','r','i','e','n','t','a','t','i','o','n',0}; + HKEY key; + DWORD type, size, val; + WCHAR buffer[20]; + + size = sizeof(buffer); + if (!RegQueryValueExW( wine_fonts_key, antialias_fake_bold_or_italic, NULL, + &type, (BYTE *)buffer, &size) && type == REG_SZ && size >= 1) + { + antialias_fakes = (strchrW(true_options, buffer[0]) != NULL); + } + + if (!RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key )) + { + /* FIXME: handle vertical orientations even though Windows doesn't */ + if (!get_key_value( key, smoothing_orientation, &val )) + { + switch (val) + { + case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */ + subpixel_orientation = WINE_GGO_HBGR_BITMAP; + break; + case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */ + subpixel_orientation = WINE_GGO_HRGB_BITMAP; + break; + } + } + if (!get_key_value( key, smoothing, &val ) && val /* enabled */) + { + if (!get_key_value( key, smoothing_type, &val ) && val == 2 /* FE_FONTSMOOTHINGCLEARTYPE */) + font_smoothing = subpixel_orientation; + else + font_smoothing = GGO_GRAY4_BITMAP; + } + RegCloseKey( key ); + } +} + /*********************************************************************** * font_init */ @@ -3098,6 +3184,7 @@ void font_init(void) KEY_ALL_ACCESS, NULL, &wine_fonts_key, NULL )) return; + init_font_options(); update_codepage(); WineEngInit( &font_funcs ); load_gdi_font_subst(); @@ -3206,54 +3293,6 @@ static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRIC memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE)); } -static DWORD get_key_value( HKEY key, const WCHAR *name, DWORD *value ) -{ - WCHAR buf[12]; - DWORD count = sizeof(buf), type, err; - - err = RegQueryValueExW( key, name, NULL, &type, (BYTE *)buf, &count ); - if (!err) - { - if (type == REG_DWORD) memcpy( value, buf, sizeof(*value) ); - else *value = atoiW( buf ); - } - return err; -} - -static UINT get_subpixel_orientation( HKEY key ) -{ - static const WCHAR smoothing_orientation[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g', - 'O','r','i','e','n','t','a','t','i','o','n',0}; - DWORD orient; - - /* FIXME: handle vertical orientations even though Windows doesn't */ - if (get_key_value( key, smoothing_orientation, &orient )) return GGO_GRAY4_BITMAP; - - switch (orient) - { - case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */ - return WINE_GGO_HBGR_BITMAP; - case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */ - return WINE_GGO_HRGB_BITMAP; - } - return GGO_GRAY4_BITMAP; -} - -static UINT get_default_smoothing( HKEY key ) -{ - static const WCHAR smoothing[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',0}; - static const WCHAR smoothing_type[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0}; - DWORD enabled, type; - - if (get_key_value( key, smoothing, &enabled )) return 0; - if (!enabled) return GGO_BITMAP; - - if (!get_key_value( key, smoothing_type, &type ) && type == 2 /* FE_FONTSMOOTHINGCLEARTYPE */) - return get_subpixel_orientation( key ); - - return GGO_GRAY4_BITMAP; -} - /* compute positions for text rendering, in device coords */ static BOOL get_char_positions( DC *dc, const WCHAR *str, INT count, INT *dx, SIZE *size ) { @@ -3808,52 +3847,6 @@ static BOOL FONT_DeleteObject( HGDIOBJ handle ) } -/*********************************************************************** - * nulldrv_SelectFont - */ -HFONT CDECL nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *aa_flags ) -{ - static const WCHAR desktopW[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\', - 'D','e','s','k','t','o','p',0 }; - static int orientation = -1, smoothing = -1; - LOGFONTW lf; - HKEY key; - - if (*aa_flags) return 0; - - GetObjectW( font, sizeof(lf), &lf ); - switch (lf.lfQuality) - { - case NONANTIALIASED_QUALITY: - *aa_flags = GGO_BITMAP; - break; - case ANTIALIASED_QUALITY: - *aa_flags = GGO_GRAY4_BITMAP; - break; - case CLEARTYPE_QUALITY: - case CLEARTYPE_NATURAL_QUALITY: - if (orientation == -1) - { - if (RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key )) break; - orientation = get_subpixel_orientation( key ); - RegCloseKey( key ); - } - *aa_flags = orientation; - break; - default: - if (smoothing == -1) - { - if (RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key )) break; - smoothing = get_default_smoothing( key ); - RegCloseKey( key ); - } - *aa_flags = smoothing; - break; - } - return 0; -} - - /*********************************************************************** * FONT_EnumInstance * diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 6c89ec783d9..ea76e90a7f8 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -323,7 +323,6 @@ static struct list mappings_list = LIST_INIT( mappings_list ); static UINT default_aa_flags; static HKEY hkey_font_cache; -static BOOL antialias_fakes = TRUE; static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'}; @@ -2248,7 +2247,6 @@ static void reorder_font_list(void) */ BOOL WineEngInit( const struct font_backend_funcs **funcs ) { - HKEY hkey; DWORD disposition; HANDLE font_mutex; @@ -2260,23 +2258,6 @@ BOOL WineEngInit( const struct font_backend_funcs **funcs ) *funcs = &font_funcs; - if (!RegOpenKeyExW(HKEY_CURRENT_USER, wine_fonts_key, 0, KEY_READ, &hkey)) - { - static const WCHAR antialias_fake_bold_or_italic[] = { 'A','n','t','i','a','l','i','a','s','F','a','k','e', - 'B','o','l','d','O','r','I','t','a','l','i','c',0 }; - static const WCHAR true_options[] = { 'y','Y','t','T','1',0 }; - DWORD type, size; - WCHAR buffer[20]; - - size = sizeof(buffer); - if (!RegQueryValueExW(hkey, antialias_fake_bold_or_italic, NULL, &type, (BYTE*)buffer, &size) && - type == REG_SZ && size >= 1) - { - antialias_fakes = (strchrW(true_options, buffer[0]) != NULL); - } - RegCloseKey(hkey); - } - if((font_mutex = CreateMutexW(NULL, FALSE, font_mutex_nameW)) == NULL) { ERR("Failed to create font mutex\n"); @@ -2972,8 +2953,7 @@ static BOOL CDECL freetype_load_font( struct gdi_font *font ) /************************************************************* * freetype_SelectFont */ -static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *aa_flags, - UINT default_aa_flags ) +static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont ) { struct gdi_font *font; Face *face, *best, *best_bitmap; @@ -3032,7 +3012,7 @@ static struct gdi_font * CDECL freetype_SelectFont( DC *dc, HFONT hfont, UINT *a /* check the cache first */ if ((font = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) { TRACE("returning cached gdiFont(%p) for hFont %p\n", font, hfont); - goto done; + return font; } /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to @@ -3295,8 +3275,7 @@ found_face: if((cachedfont = find_cached_gdi_font( &lf, &dcmat, can_use_bitmap ))) { TRACE("Found cached font after non-scalable matrix rescale!\n"); free_gdi_font( font ); - font = cachedfont; - goto done; + return cachedfont; } if (height != 0) height = diff; @@ -3326,50 +3305,40 @@ found_face: TRACE("caching: gdiFont=%p hfont=%p\n", font, hfont); cache_gdi_font( font ); -done: - if (font) - { - switch (lf.lfQuality) - { - case NONANTIALIASED_QUALITY: - case ANTIALIASED_QUALITY: - if (!*aa_flags) *aa_flags = default_aa_flags; - break; - case CLEARTYPE_QUALITY: - case CLEARTYPE_NATURAL_QUALITY: - default: - if (!*aa_flags) *aa_flags = font->aa_flags; - if (!*aa_flags) *aa_flags = default_aa_flags; + return font; +} - /* fixup the antialiasing flags for that font */ - switch (*aa_flags) +/************************************************************* + * freetype_get_aa_flags + */ +static UINT CDECL freetype_get_aa_flags( struct gdi_font *font, UINT aa_flags, BOOL antialias_fakes ) +{ + /* fixup the antialiasing flags for that font */ + switch (aa_flags) + { + case WINE_GGO_HRGB_BITMAP: + case WINE_GGO_HBGR_BITMAP: + case WINE_GGO_VRGB_BITMAP: + case WINE_GGO_VBGR_BITMAP: + if (is_subpixel_rendering_enabled()) break; + aa_flags = GGO_GRAY4_BITMAP; + /* fall through */ + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + case WINE_GGO_GRAY16_BITMAP: + if ((!antialias_fakes || (!font->fake_bold && !font->fake_italic)) && is_hinting_enabled()) + { + WORD gasp_flags; + if (get_gasp_flags( font, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY)) { - case WINE_GGO_HRGB_BITMAP: - case WINE_GGO_HBGR_BITMAP: - case WINE_GGO_VRGB_BITMAP: - case WINE_GGO_VBGR_BITMAP: - if (is_subpixel_rendering_enabled()) break; - *aa_flags = GGO_GRAY4_BITMAP; - /* fall through */ - case GGO_GRAY2_BITMAP: - case GGO_GRAY4_BITMAP: - case GGO_GRAY8_BITMAP: - case WINE_GGO_GRAY16_BITMAP: - if ((!antialias_fakes || (!font->fake_bold && !font->fake_italic)) && is_hinting_enabled()) - { - WORD gasp_flags; - if (get_gasp_flags( font, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY)) - { - TRACE( "font %s %d aa disabled by GASP\n", - debugstr_w(lf.lfFaceName), lf.lfHeight ); - *aa_flags = GGO_BITMAP; - } - } + TRACE( "font %s %d aa disabled by GASP\n", + debugstr_w(font->lf.lfFaceName), font->lf.lfHeight ); + aa_flags = GGO_BITMAP; } } - TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags ); } - return font; + return aa_flags; } static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) @@ -5131,6 +5100,7 @@ static const struct font_backend_funcs font_funcs = freetype_remove_font, freetype_load_font, freetype_get_font_data, + freetype_get_aa_flags, freetype_get_glyph_index, freetype_get_default_glyph, freetype_get_glyph_outline, diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 516f38b11c4..2d1d74e902b 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -425,7 +425,7 @@ struct gdi_font struct font_backend_funcs { - struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont, UINT *aa_flags, UINT default_aa_flags ); + struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont ); INT (CDECL *add_font)( const WCHAR *file, DWORD flags ); INT (CDECL *add_mem_font)( void *ptr, SIZE_T size, DWORD flags ); @@ -434,6 +434,7 @@ struct font_backend_funcs BOOL (CDECL *load_font)( struct gdi_font *gdi_font ); DWORD (CDECL *get_font_data)( struct gdi_font *gdi_font, DWORD table, DWORD offset, void *buf, DWORD count ); + UINT (CDECL *get_aa_flags)( struct gdi_font *font, UINT aa_flags, BOOL antialias_fakes ); BOOL (CDECL *get_glyph_index)( struct gdi_font *gdi_font, UINT *glyph, BOOL use_encoding ); UINT (CDECL *get_default_glyph)( struct gdi_font *gdi_font ); DWORD (CDECL *get_glyph_outline)( struct gdi_font *font, UINT glyph, UINT format, @@ -644,7 +645,6 @@ extern INT CDECL nulldrv_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL CDECL nulldrv_ScaleViewportExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN; extern BOOL CDECL nulldrv_ScaleWindowExtEx( PHYSDEV dev, INT x_num, INT x_denom, INT y_num, INT y_denom, SIZE *size ) DECLSPEC_HIDDEN; extern BOOL CDECL nulldrv_SelectClipPath( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; -extern HFONT CDECL nulldrv_SelectFont( PHYSDEV dev, HFONT font, UINT *ggo_flags ) DECLSPEC_HIDDEN; extern INT CDECL nulldrv_SetDIBitsToDevice( PHYSDEV dev, INT x_dst, INT y_dst, DWORD width, DWORD height, INT x_src, INT y_src, UINT start, UINT lines, const void *bits, BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN;