gdi32, winex11: Add support for subpixel font rendering.

This commit is contained in:
ByeongSik Jeon 2008-12-10 23:50:44 +09:00 committed by Alexandre Julliard
parent 33f6b46fd2
commit 028617b90b
6 changed files with 219 additions and 18 deletions

1
configure vendored
View File

@ -14591,6 +14591,7 @@ for ac_header in ft2build.h \
freetype/ftoutln.h \ freetype/ftoutln.h \
freetype/ftwinfnt.h \ freetype/ftwinfnt.h \
freetype/ftmodapi.h \ freetype/ftmodapi.h \
freetype/ftlcdfil.h \
freetype/internal/sfnt.h freetype/internal/sfnt.h
do do
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`

View File

@ -1040,6 +1040,7 @@ then
freetype/ftoutln.h \ freetype/ftoutln.h \
freetype/ftwinfnt.h \ freetype/ftwinfnt.h \
freetype/ftmodapi.h \ freetype/ftmodapi.h \
freetype/ftlcdfil.h \
freetype/internal/sfnt.h,,, freetype/internal/sfnt.h,,,
[#ifdef HAVE_FT2BUILD_H [#ifdef HAVE_FT2BUILD_H
# include <ft2build.h> # include <ft2build.h>

View File

@ -132,6 +132,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(font);
#ifdef HAVE_FREETYPE_FTMODAPI_H #ifdef HAVE_FREETYPE_FTMODAPI_H
#include <freetype/ftmodapi.h> #include <freetype/ftmodapi.h>
#endif #endif
#ifdef HAVE_FREETYPE_FTLCDFIL_H
#include <freetype/ftlcdfil.h>
#endif
#ifndef HAVE_FT_TRUETYPEENGINETYPE #ifndef HAVE_FT_TRUETYPEENGINETYPE
typedef enum typedef enum
@ -179,7 +182,9 @@ MAKE_FUNCPTR(FT_Select_Charmap);
MAKE_FUNCPTR(FT_Set_Charmap); MAKE_FUNCPTR(FT_Set_Charmap);
MAKE_FUNCPTR(FT_Set_Pixel_Sizes); MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
MAKE_FUNCPTR(FT_Vector_Transform); MAKE_FUNCPTR(FT_Vector_Transform);
MAKE_FUNCPTR(FT_Render_Glyph);
static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*); static void (*pFT_Library_Version)(FT_Library,FT_Int*,FT_Int*,FT_Int*);
static FT_Error (*pFT_Library_SetLcdFilter)(FT_Library, FT_LcdFilter);
static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*); static FT_Error (*pFT_Load_Sfnt_Table)(FT_Face,FT_ULong,FT_Long,FT_Byte*,FT_ULong*);
static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*); static FT_ULong (*pFT_Get_First_Char)(FT_Face,FT_UInt*);
static FT_ULong (*pFT_Get_Next_Char)(FT_Face,FT_ULong,FT_UInt*); static FT_ULong (*pFT_Get_Next_Char)(FT_Face,FT_ULong,FT_UInt*);
@ -2481,10 +2486,12 @@ static BOOL init_freetype(void)
LOAD_FUNCPTR(FT_Set_Charmap) LOAD_FUNCPTR(FT_Set_Charmap)
LOAD_FUNCPTR(FT_Set_Pixel_Sizes) LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
LOAD_FUNCPTR(FT_Vector_Transform) LOAD_FUNCPTR(FT_Vector_Transform)
LOAD_FUNCPTR(FT_Render_Glyph)
#undef LOAD_FUNCPTR #undef LOAD_FUNCPTR
/* Don't warn if these ones are missing */ /* Don't warn if these ones are missing */
pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0); pFT_Library_Version = wine_dlsym(ft_handle, "FT_Library_Version", NULL, 0);
pFT_Library_SetLcdFilter = wine_dlsym(ft_handle, "FT_Library_SetLcdFilter", NULL, 0);
pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0); pFT_Load_Sfnt_Table = wine_dlsym(ft_handle, "FT_Load_Sfnt_Table", NULL, 0);
pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0); pFT_Get_First_Char = wine_dlsym(ft_handle, "FT_Get_First_Char", NULL, 0);
pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0); pFT_Get_Next_Char = wine_dlsym(ft_handle, "FT_Get_Next_Char", NULL, 0);
@ -4491,8 +4498,12 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
needsTransform = TRUE; needsTransform = TRUE;
} }
if (needsTransform || (format != GGO_METRICS && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP)) if (needsTransform || (format == GGO_NATIVE || format == GGO_BEZIER ||
format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
format == GGO_GRAY8_BITMAP))
{
load_flags |= FT_LOAD_NO_BITMAP; load_flags |= FT_LOAD_NO_BITMAP;
}
err = pFT_Load_Glyph(ft_face, glyph_index, load_flags); err = pFT_Load_Glyph(ft_face, glyph_index, load_flags);
@ -4563,7 +4574,9 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
wine_dbgstr_point(&lpgm->gmptGlyphOrigin), wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
lpgm->gmCellIncX, lpgm->gmCellIncY); lpgm->gmCellIncX, lpgm->gmCellIncY);
if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP ||
format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP ||
format == WINE_GGO_VRGB_BITMAP || format == WINE_GGO_VBGR_BITMAP ) &&
(!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */ (!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */
{ {
FONT_GM(font,original_index)->gm = *lpgm; FONT_GM(font,original_index)->gm = *lpgm;
@ -4579,7 +4592,11 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
return 1; /* FIXME */ return 1; /* FIXME */
} }
if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) { if(ft_face->glyph->format != ft_glyph_format_outline &&
(needsTransform || format == GGO_NATIVE || format == GGO_BEZIER ||
format == GGO_GRAY2_BITMAP || format == GGO_GRAY4_BITMAP ||
format == GGO_GRAY8_BITMAP))
{
TRACE("loaded a bitmap\n"); TRACE("loaded a bitmap\n");
LeaveCriticalSection( &freetype_cs ); LeaveCriticalSection( &freetype_cs );
return GDI_ERROR; return GDI_ERROR;
@ -4714,6 +4731,112 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format,
break; break;
} }
case WINE_GGO_HRGB_BITMAP:
case WINE_GGO_HBGR_BITMAP:
case WINE_GGO_VRGB_BITMAP:
case WINE_GGO_VBGR_BITMAP:
{
width = lpgm->gmBlackBoxX;
height = lpgm->gmBlackBoxY;
pitch = width * 4;
needed = pitch * height;
if (!buf || !buflen) break;
memset(buf, 0, buflen);
switch (ft_face->glyph->format)
{
case FT_GLYPH_FORMAT_BITMAP:
{
BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf;
INT src_pitch = ft_face->glyph->bitmap.pitch;
INT x;
while ( height-- )
{
for (x = 0; x < width; x++)
{
if ( src[x / 8] & (1 << ( (7 - (x % 8)))) )
((unsigned int *)dst)[x] = ~0u;
}
src += src_pitch;
dst += pitch;
}
break;
}
case FT_GLYPH_FORMAT_OUTLINE:
{
unsigned int *dst = (unsigned int *) buf;
BYTE *src;
INT x, src_pitch, rgb_interval, hmul, vmul;
BOOL rgb = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP);
FT_LcdFilter lcdfilter = FT_LCD_FILTER_DEFAULT;
FT_Render_Mode render_mode =
(format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)?
FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V;
if ( needsTransform )
pFT_Outline_Transform (&ft_face->glyph->outline, &transMat);
pFT_Outline_Translate (&ft_face->glyph->outline, -left, -bottom );
if ( pFT_Library_SetLcdFilter )
pFT_Library_SetLcdFilter( library, lcdfilter );
pFT_Render_Glyph (ft_face->glyph, render_mode);
src = ft_face->glyph->bitmap.buffer;
src_pitch = ft_face->glyph->bitmap.pitch;
if ( render_mode == FT_RENDER_MODE_LCD)
{
rgb_interval = 1;
hmul = 3;
vmul = 1;
}
else
{
rgb_interval = src_pitch;
hmul = 1;
vmul = 3;
}
if ( lcdfilter == FT_LCD_FILTER_DEFAULT || lcdfilter == FT_LCD_FILTER_LIGHT )
src += rgb_interval * 3;
while ( height-- )
{
for ( x = 0; x < width; x++ )
{
if ( rgb )
{
dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 0] << 16) |
((unsigned int)src[hmul * x + rgb_interval * 1] << 8) |
((unsigned int)src[hmul * x + rgb_interval * 2] << 0) |
((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
}
else
{
dst[x] = ((unsigned int)src[hmul * x + rgb_interval * 2] << 16) |
((unsigned int)src[hmul * x + rgb_interval * 1] << 8) |
((unsigned int)src[hmul * x + rgb_interval * 0] << 0) |
((unsigned int)src[hmul * x + rgb_interval * 1] << 24) ;
}
}
src += src_pitch * vmul;
dst += pitch / 4;
}
break;
}
default:
FIXME ("loaded glyph format %x\n", ft_face->glyph->format);
LeaveCriticalSection ( &freetype_cs );
return GDI_ERROR;
}
break;
}
case GGO_NATIVE: case GGO_NATIVE:
{ {
int contour, point = 0, first_pt; int contour, point = 0, first_pt;
@ -5792,12 +5915,24 @@ static BOOL is_hinting_enabled(void)
return FALSE; return FALSE;
} }
static BOOL is_subpixel_rendering_enabled( void )
{
if ( !pFT_Library_SetLcdFilter )
return FALSE;
if ( pFT_Library_SetLcdFilter ( NULL, 0 ) == FT_Err_Unimplemented_Feature )
return FALSE;
return TRUE;
}
/************************************************************************* /*************************************************************************
* GetRasterizerCaps (GDI32.@) * GetRasterizerCaps (GDI32.@)
*/ */
BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes) BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
{ {
static int hinting = -1; static int hinting = -1;
static int subpixel = -1;
if(hinting == -1) if(hinting == -1)
{ {
@ -5805,8 +5940,16 @@ BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
TRACE("hinting is %senabled\n", hinting ? "" : "NOT "); TRACE("hinting is %senabled\n", hinting ? "" : "NOT ");
} }
if ( subpixel == -1 )
{
subpixel = is_subpixel_rendering_enabled();
TRACE("subpixel rendering is %senabled\n", subpixel ? "" : "NOT ");
}
lprs->nSize = sizeof(RASTERIZER_STATUS); lprs->nSize = sizeof(RASTERIZER_STATUS);
lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0); lprs->wFlags = TT_AVAILABLE | TT_ENABLED | (hinting ? WINE_TT_HINTER_ENABLED : 0);
if ( subpixel )
lprs->wFlags |= WINE_TT_SUBPIXEL_RENDERING_ENABLED;
lprs->nLanguageID = 0; lprs->nLanguageID = 0;
return TRUE; return TRUE;
} }

View File

@ -142,8 +142,10 @@ static CRITICAL_SECTION xrender_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
#define get_be_word(x) (x) #define get_be_word(x) (x)
#define NATIVE_BYTE_ORDER MSBFirst
#else #else
#define get_be_word(x) RtlUshortByteSwap(x) #define get_be_word(x) RtlUshortByteSwap(x)
#define NATIVE_BYTE_ORDER LSBFirst
#endif #endif
/*********************************************************************** /***********************************************************************
@ -456,6 +458,7 @@ static int GetCacheEntry(X11DRV_PDEVICE *physDev, LFANDSIZE *plfsz)
gsCacheEntry *entry; gsCacheEntry *entry;
WORD flags; WORD flags;
static int hinter = -1; static int hinter = -1;
static int subpixel = -1;
if((ret = LookupEntry(plfsz)) != -1) return ret; if((ret = LookupEntry(plfsz)) != -1) return ret;
@ -468,13 +471,24 @@ static int GetCacheEntry(X11DRV_PDEVICE *physDev, LFANDSIZE *plfsz)
if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY) if(antialias && plfsz->lf.lfQuality != NONANTIALIASED_QUALITY)
{ {
if(hinter == -1) if(hinter == -1 || subpixel == -1)
{ {
RASTERIZER_STATUS status; RASTERIZER_STATUS status;
GetRasterizerCaps(&status, sizeof(status)); GetRasterizerCaps(&status, sizeof(status));
hinter = status.wFlags & WINE_TT_HINTER_ENABLED; hinter = status.wFlags & WINE_TT_HINTER_ENABLED;
subpixel = status.wFlags & WINE_TT_SUBPIXEL_RENDERING_ENABLED;
} }
if(!hinter || !get_gasp_flags(physDev, &flags) || flags & GASP_DOGRAY)
/* FIXME: Use the following registry information
[HKEY_CURRENT_USER\Control Panel\Desktop]
"FontSmoothing"="2" ; 0=>Off, 2=>On
"FontSmoothingType"=dword:00000002 ; 1=>Standard, 2=>Cleartype
"FontSmoothingOrientation"=dword:00000001 ; 0=>BGR, 1=>RGB
"FontSmoothingGamma"=dword:00000578
*/
if ( subpixel && X11DRV_XRender_Installed)
entry->aa_default = AA_RGB;
else if(!hinter || !get_gasp_flags(physDev, &flags) || flags & GASP_DOGRAY)
entry->aa_default = AA_Grey; entry->aa_default = AA_Grey;
else else
entry->aa_default = AA_None; entry->aa_default = AA_None;
@ -610,12 +624,25 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
gsCacheEntryFormat *formatEntry; gsCacheEntryFormat *formatEntry;
UINT ggo_format = GGO_GLYPH_INDEX; UINT ggo_format = GGO_GLYPH_INDEX;
XRenderPictFormat pf; XRenderPictFormat pf;
unsigned long pf_mask;
static const char zero[4]; static const char zero[4];
switch(format) { switch(format) {
case AA_Grey: case AA_Grey:
ggo_format |= WINE_GGO_GRAY16_BITMAP; ggo_format |= WINE_GGO_GRAY16_BITMAP;
break; break;
case AA_RGB:
ggo_format |= WINE_GGO_HRGB_BITMAP;
break;
case AA_BGR:
ggo_format |= WINE_GGO_HBGR_BITMAP;
break;
case AA_VRGB:
ggo_format |= WINE_GGO_VRGB_BITMAP;
break;
case AA_VBGR:
ggo_format |= WINE_GGO_VBGR_BITMAP;
break;
default: default:
ERR("aa = %d - not implemented\n", format); ERR("aa = %d - not implemented\n", format);
@ -630,8 +657,7 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
if(format != AA_None) { if(format != AA_None) {
format = AA_None; format = AA_None;
entry->aa_default = AA_None; entry->aa_default = AA_None;
ggo_format &= ~WINE_GGO_GRAY16_BITMAP; ggo_format = GGO_GLYPH_INDEX | GGO_BITMAP;
ggo_format |= GGO_BITMAP;
buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL, buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL,
NULL); NULL);
} }
@ -689,29 +715,45 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) { if(formatEntry->glyphset == 0 && X11DRV_XRender_Installed) {
switch(format) { switch(format) {
case AA_Grey: case AA_Grey:
pf_mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask,
pf.type = PictTypeDirect;
pf.depth = 8; pf.depth = 8;
pf.direct.alpha = 0;
pf.direct.alphaMask = 0xff;
break;
case AA_RGB:
case AA_BGR:
case AA_VRGB:
case AA_VBGR:
pf_mask = PictFormatType | PictFormatDepth | PictFormatRed | PictFormatRedMask |
PictFormatGreen | PictFormatGreenMask | PictFormatBlue |
PictFormatBlueMask | PictFormatAlpha | PictFormatAlphaMask;
pf.type = PictTypeDirect;
pf.depth = 32;
pf.direct.red = 16;
pf.direct.redMask = 0xff;
pf.direct.green = 8;
pf.direct.greenMask = 0xff;
pf.direct.blue = 0;
pf.direct.blueMask = 0xff;
pf.direct.alpha = 24;
pf.direct.alphaMask = 0xff; pf.direct.alphaMask = 0xff;
break; break;
default: default:
ERR("aa = %d - not implemented\n", format); ERR("aa = %d - not implemented\n", format);
case AA_None: case AA_None:
pf_mask = PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask,
pf.type = PictTypeDirect;
pf.depth = 1; pf.depth = 1;
pf.direct.alpha = 0;
pf.direct.alphaMask = 1; pf.direct.alphaMask = 1;
break; break;
} }
pf.type = PictTypeDirect;
pf.direct.alpha = 0;
wine_tsx11_lock(); wine_tsx11_lock();
formatEntry->font_format = pXRenderFindFormat(gdi_display, formatEntry->font_format = pXRenderFindFormat(gdi_display, pf_mask, &pf, 0);
PictFormatType |
PictFormatDepth |
PictFormatAlpha |
PictFormatAlphaMask,
&pf, 0);
formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format); formatEntry->glyphset = pXRenderCreateGlyphSet(gdi_display, formatEntry->font_format);
wine_tsx11_unlock(); wine_tsx11_unlock();
} }
@ -783,6 +825,12 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph, AA_Type format)
*byte++ = c; *byte++ = c;
} }
} }
else if ( format != AA_Grey &&
ImageByteOrder (gdi_display) != NATIVE_BYTE_ORDER)
{
unsigned int i, *data = (unsigned int *)buf;
for (i = buflen / sizeof(int); i; i--, data++) *data = RtlUlongByteSwap(*data);
}
gid = glyph; gid = glyph;
/* /*

View File

@ -117,6 +117,9 @@
/* Define to 1 if you have the <freetype/ftglyph.h> header file. */ /* Define to 1 if you have the <freetype/ftglyph.h> header file. */
#undef HAVE_FREETYPE_FTGLYPH_H #undef HAVE_FREETYPE_FTGLYPH_H
/* Define to 1 if you have the <freetype/ftlcdfil.h> header file. */
#undef HAVE_FREETYPE_FTLCDFIL_H
/* Define to 1 if you have the <freetype/ftmodapi.h> header file. */ /* Define to 1 if you have the <freetype/ftmodapi.h> header file. */
#undef HAVE_FREETYPE_FTMODAPI_H #undef HAVE_FREETYPE_FTMODAPI_H

View File

@ -1297,7 +1297,11 @@ typedef struct
#define GGO_UNHINTED 0x100 #define GGO_UNHINTED 0x100
#ifdef __WINESRC__ #ifdef __WINESRC__
#define WINE_GGO_GRAY16_BITMAP 0x7f #define WINE_GGO_GRAY16_BITMAP 0x10
#define WINE_GGO_HRGB_BITMAP 0x11
#define WINE_GGO_HBGR_BITMAP 0x12
#define WINE_GGO_VRGB_BITMAP 0x13
#define WINE_GGO_VBGR_BITMAP 0x14
#endif #endif
typedef struct typedef struct
@ -1424,6 +1428,7 @@ typedef struct
#define TT_ENABLED 0x0002 #define TT_ENABLED 0x0002
#ifdef __WINESRC__ #ifdef __WINESRC__
#define WINE_TT_SUBPIXEL_RENDERING_ENABLED 0x4000
#define WINE_TT_HINTER_ENABLED 0x8000 #define WINE_TT_HINTER_ENABLED 0x8000
#endif #endif