Client side render fonts for XServers without the Render extension

using X11 core requests.
This commit is contained in:
Huw Davies 2002-11-14 22:31:34 +00:00 committed by Alexandre Julliard
parent 3f61afbbc8
commit 94705862d6
7 changed files with 768 additions and 226 deletions

View File

@ -60,6 +60,10 @@ Window root_window;
int dxgrab, usedga, usexvidmode;
int use_take_focus = 1;
int managed_mode = 1;
int client_side_with_core = 1;
int client_side_with_render = 1;
int client_side_antialias_with_core = 1;
int client_side_antialias_with_render = 1;
unsigned int X11DRV_server_startticks;
@ -252,6 +256,18 @@ static void setup_options(void)
if (!get_config_key( hkey, appkey, "Synchronous", buffer, sizeof(buffer) ))
synchronous = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "ClientSideWithCore", buffer, sizeof(buffer) ))
client_side_with_core = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "ClientSideWithRender", buffer, sizeof(buffer) ))
client_side_with_render = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithCore", buffer, sizeof(buffer) ))
client_side_antialias_with_core = IS_OPTION_TRUE( buffer[0] );
if (!get_config_key( hkey, appkey, "ClientSideAntiAliasWithRender", buffer, sizeof(buffer) ))
client_side_antialias_with_render = IS_OPTION_TRUE( buffer[0] );
if (appkey) RegCloseKey( appkey );
RegCloseKey( hkey );
}
@ -381,6 +397,8 @@ static void process_detach(void)
/* cleanup XVidMode */
X11DRV_XF86VM_Cleanup();
#endif
if(using_client_side_fonts)
X11DRV_XRender_Finalize();
/* FIXME: should detach all threads */
thread_detach();

View File

@ -1,7 +1,10 @@
/*
* Functions to use the XRender extension
*
* Copyright 2001 Huw D M Davies for CodeWeavers
* Copyright 2001, 2002 Huw D M Davies for CodeWeavers
*
* Some parts also:
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -31,7 +34,9 @@
#include "wine/unicode.h"
#include "wine/debug.h"
BOOL X11DRV_XRender_Installed = FALSE;
static BOOL X11DRV_XRender_Installed = FALSE;
int using_client_side_fonts = FALSE;
WINE_DEFAULT_DEBUG_CHANNEL(xrender);
#ifdef HAVE_X11_EXTENSIONS_XRENDER_H
@ -51,14 +56,18 @@ typedef struct
#define INITIAL_REALIZED_BUF_SIZE 128
typedef enum { AA_None, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR } AA_Type;
typedef struct
{
LFANDSIZE lfsz;
AA_Type aa;
GlyphSet glyphset;
XRenderPictFormat *font_format;
int nrealized;
BOOL *realized;
void **bitmaps;
XGlyphInfo *gis;
UINT count;
INT next;
} gsCacheEntry;
@ -125,10 +134,11 @@ void X11DRV_XRender_Init(void)
int error_base, event_base, i;
XRenderPictFormat pf;
if (!wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0)) return;
if (!wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0)) return;
xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0);
if(!xrender_handle) return;
if (client_side_with_render &&
wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
(xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0)))
{
#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
LOAD_FUNCPTR(XRenderAddGlyphs)
@ -168,11 +178,16 @@ LOAD_FUNCPTR(XRenderQueryExtension)
PictFormatDepth | PictFormatAlpha |
PictFormatAlphaMask, &pf, 0);
if(!mono_format) {
wine_tsx11_unlock();
ERR("mono_format == NULL?\n");
X11DRV_XRender_Installed = FALSE;
return;
}
}
wine_tsx11_unlock();
}
sym_not_found:
if(X11DRV_XRender_Installed || client_side_with_core)
{
glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
@ -183,15 +198,18 @@ LOAD_FUNCPTR(XRenderQueryExtension)
glyphsetCache[i].count = -1;
}
glyphsetCache[i-1].next = -1;
} else {
TRACE("Xrender is not available on this server\n");
}
wine_tsx11_unlock();
return;
using_client_side_fonts = 1;
sym_not_found:
wine_dlclose(xrender_handle, NULL, 0);
xrender_handle = NULL;
if(!X11DRV_XRender_Installed) {
TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
if(screen_depth <= 8 || !client_side_antialias_with_core)
antialias = 0;
} else {
if(screen_depth <= 8 || !client_side_antialias_with_render)
antialias = 0;
}
}
else TRACE("Using X11 core fonts\n");
}
static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
@ -241,6 +259,32 @@ static int LookupEntry(LFANDSIZE *plfsz)
return -1;
}
static void FreeEntry(int entry)
{
int i;
if(glyphsetCache[entry].glyphset) {
wine_tsx11_lock();
pXRenderFreeGlyphSet(gdi_display, glyphsetCache[entry].glyphset);
wine_tsx11_unlock();
glyphsetCache[entry].glyphset = 0;
}
if(glyphsetCache[entry].nrealized) {
HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].realized);
glyphsetCache[entry].realized = NULL;
if(glyphsetCache[entry].bitmaps) {
for(i = 0; i < glyphsetCache[entry].nrealized; i++)
if(glyphsetCache[entry].bitmaps[i])
HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].bitmaps[i]);
HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].bitmaps);
glyphsetCache[entry].bitmaps = NULL;
HeapFree(GetProcessHeap(), 0, glyphsetCache[entry].gis);
glyphsetCache[entry].gis = NULL;
}
glyphsetCache[entry].nrealized = 0;
}
}
static int AllocEntry(void)
{
int best = -1, prev_best = -1, i, prev_i = -1;
@ -268,15 +312,7 @@ static int AllocEntry(void)
if(best >= 0) {
TRACE("freeing unused glyphset at cache %d\n", best);
wine_tsx11_lock();
pXRenderFreeGlyphSet(gdi_display, glyphsetCache[best].glyphset);
wine_tsx11_unlock();
glyphsetCache[best].glyphset = 0;
if(glyphsetCache[best].nrealized) { /* do we really want to do this? */
HeapFree(GetProcessHeap(), 0, glyphsetCache[best].realized);
glyphsetCache[best].realized = NULL;
glyphsetCache[best].nrealized = 0;
}
FreeEntry(best);
glyphsetCache[best].count = 1;
if(prev_best >= 0) {
glyphsetCache[prev_best].next = glyphsetCache[best].next;
@ -322,14 +358,26 @@ static int GetCacheEntry(LFANDSIZE *plfsz)
entry->lfsz = *plfsz;
assert(entry->nrealized == 0);
if(antialias)
entry->aa = AA_Grey;
else
entry->aa = AA_None;
if(antialias) {
if(X11DRV_XRender_Installed) {
switch(entry->aa) {
case AA_Grey:
pf.depth = 8;
pf.direct.alphaMask = 0xff;
} else {
break;
default:
ERR("aa = %d - not implemented\n", entry->aa);
case AA_None:
pf.depth = 1;
pf.direct.alphaMask = 1;
break;
}
pf.type = PictTypeDirect;
pf.direct.alpha = 0;
@ -343,6 +391,7 @@ static int GetCacheEntry(LFANDSIZE *plfsz)
entry->glyphset = pXRenderCreateGlyphSet(gdi_display, entry->font_format);
wine_tsx11_unlock();
}
return ret;
}
@ -379,11 +428,12 @@ static void lfsz_calc_hash(LFANDSIZE *plfsz)
*/
void X11DRV_XRender_Finalize(void)
{
FIXME("Free cached glyphsets\n");
#if 0
if (xrender_handle) wine_dlclose(xrender_handle, NULL, 0);
xrender_handle = NULL;
#endif
int i;
EnterCriticalSection(&xrender_cs);
for(i = mru; i >= 0; i = glyphsetCache[i].next)
FreeEntry(i);
LeaveCriticalSection(&xrender_cs);
}
@ -445,15 +495,16 @@ void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
/***********************************************************************
* X11DRV_XRender_UpdateDrawable
*
* This gets called from X11DRV_SetDrawable and deletes the pict when the
* drawable changes. However at the moment we delete the pict at the end of
* every ExtTextOut so this is basically a NOP.
* This gets called from X11DRV_SetDrawable and X11DRV_SelectBitmap.
* It deletes the pict when the drawable changes.
*/
void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
{
if(physDev->xrender->pict) {
TRACE("freeing pict %08lx from dc %p\n", physDev->xrender->pict, physDev->dc);
TRACE("freeing pict %08lx from dc %p drawable %08lx\n", physDev->xrender->pict,
physDev->dc, physDev->drawable);
wine_tsx11_lock();
XFlush(gdi_display);
pXRenderFreePicture(gdi_display, physDev->xrender->pict);
wine_tsx11_unlock();
}
@ -475,7 +526,6 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
XGlyphInfo gi;
gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
UINT ggo_format = GGO_GLYPH_INDEX;
BOOL aa;
if(entry->nrealized <= glyph) {
entry->nrealized = (glyph / 128 + 1) * 128;
@ -483,14 +533,28 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
HEAP_ZERO_MEMORY,
entry->realized,
entry->nrealized * sizeof(BOOL));
if(entry->glyphset == 0) {
entry->bitmaps = HeapReAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
entry->bitmaps,
entry->nrealized * sizeof(entry->bitmaps[0]));
entry->gis = HeapReAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
entry->gis,
entry->nrealized * sizeof(entry->gis[0]));
}
}
if(entry->font_format->depth == 8) {
aa = TRUE;
switch(entry->aa) {
case AA_Grey:
ggo_format |= WINE_GGO_GRAY16_BITMAP;
} else {
aa = FALSE;
break;
default:
ERR("aa = %d - not implemented\n", entry->aa);
case AA_None:
ggo_format |= GGO_BITMAP;
break;
}
buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL,
@ -522,7 +586,7 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
char output[300];
unsigned char *line;
if(!aa) {
if(entry->aa == AA_None) {
pitch = ((gi.width + 31) / 32) * 4;
for(i = 0; i < gi.height; i++) {
line = buf + i * pitch;
@ -552,7 +616,8 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
}
}
if(!aa && BitmapBitOrder(gdi_display) != MSBFirst) {
if(entry->glyphset) {
if(entry->aa == AA_None && BitmapBitOrder(gdi_display) != MSBFirst) {
unsigned char *byte = buf, c;
int i = buflen;
@ -573,9 +638,258 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
buf, buflen);
wine_tsx11_unlock();
HeapFree(GetProcessHeap(), 0, buf);
} else {
entry->bitmaps[glyph] = buf;
memcpy(&entry->gis[glyph], &gi, sizeof(gi));
}
return TRUE;
}
static void SharpGlyphMono(X11DRV_PDEVICE *physDev, INT x, INT y,
void *bitmap, XGlyphInfo *gi)
{
unsigned char *srcLine = bitmap, *src;
unsigned char bits, bitsMask;
int width = gi->width;
int stride = ((width + 31) & ~31) >> 3;
int height = gi->height;
int w;
int xspan, lenspan;
TRACE("%d, %d\n", x, y);
x -= gi->x;
y -= gi->y;
while (height--)
{
src = srcLine;
srcLine += stride;
w = width;
bitsMask = 0x80; /* FreeType is always MSB first */
bits = *src++;
xspan = x;
while (w)
{
if (bits & bitsMask)
{
lenspan = 0;
do
{
lenspan++;
if (lenspan == w)
break;
bitsMask = bitsMask >> 1;
if (!bitsMask)
{
bits = *src++;
bitsMask = 0x80;
}
} while (bits & bitsMask);
XFillRectangle (gdi_display, physDev->drawable,
physDev->gc, xspan, y, lenspan, 1);
xspan += lenspan;
w -= lenspan;
}
else
{
do
{
w--;
xspan++;
if (!w)
break;
bitsMask = bitsMask >> 1;
if (!bitsMask)
{
bits = *src++;
bitsMask = 0x80;
}
} while (!(bits & bitsMask));
}
}
y++;
}
}
static void SharpGlyphGray(X11DRV_PDEVICE *physDev, INT x, INT y,
void *bitmap, XGlyphInfo *gi)
{
unsigned char *srcLine = bitmap, *src, bits;
int width = gi->width;
int stride = ((width + 3) & ~3);
int height = gi->height;
int w;
int xspan, lenspan;
x -= gi->x;
y -= gi->y;
while (height--)
{
src = srcLine;
srcLine += stride;
w = width;
bits = *src++;
xspan = x;
while (w)
{
if (bits >= 0x80)
{
lenspan = 0;
do
{
lenspan++;
if (lenspan == w)
break;
bits = *src++;
} while (bits >= 0x80);
XFillRectangle (gdi_display, physDev->drawable,
physDev->gc, xspan, y, lenspan, 1);
xspan += lenspan;
w -= lenspan;
}
else
{
do
{
w--;
xspan++;
if (!w)
break;
bits = *src++;
} while (bits < 0x80);
}
}
y++;
}
}
static void ExamineBitfield (DWORD mask, int *shift, int *len)
{
int s, l;
s = 0;
while ((mask & 1) == 0)
{
mask >>= 1;
s++;
}
l = 0;
while ((mask & 1) == 1)
{
mask >>= 1;
l++;
}
*shift = s;
*len = l;
}
static DWORD GetField (DWORD pixel, int shift, int len)
{
pixel = pixel & (((1 << (len)) - 1) << shift);
pixel = pixel << (32 - (shift + len)) >> 24;
while (len < 8)
{
pixel |= (pixel >> len);
len <<= 1;
}
return pixel;
}
static DWORD PutField (DWORD pixel, int shift, int len)
{
shift = shift - (8 - len);
if (len <= 8)
pixel &= (((1 << len) - 1) << (8 - len));
if (shift < 0)
pixel >>= -shift;
else
pixel <<= shift;
return pixel;
}
static void SmoothGlyphGray(XImage *image, int x, int y, void *bitmap, XGlyphInfo *gi,
COLORREF color)
{
int r_shift, r_len;
int g_shift, g_len;
int b_shift, b_len;
BYTE *maskLine, *mask, m;
int maskStride;
DWORD pixel;
int width, height;
int w, tx;
BYTE src_r, src_g, src_b;
src_r = GetRValue(color);
src_g = GetGValue(color);
src_b = GetBValue(color);
x -= gi->x;
y -= gi->y;
width = gi->width;
height = gi->height;
maskLine = (unsigned char *) bitmap;
maskStride = (width + 3) & ~3;
ExamineBitfield (image->red_mask, &r_shift, &r_len);
ExamineBitfield (image->green_mask, &g_shift, &g_len);
ExamineBitfield (image->blue_mask, &b_shift, &b_len);
for(; height--; y++)
{
mask = maskLine;
maskLine += maskStride;
w = width;
tx = x;
if(y < 0) continue;
if(y >= image->height) break;
for(; w--; tx++)
{
if(tx >= image->width) break;
m = *mask++;
if(tx < 0) continue;
if (m == 0xff)
{
pixel = (PutField ((src_r), r_shift, r_len) |
PutField ((src_g), g_shift, g_len) |
PutField ((src_b), b_shift, b_len));
XPutPixel (image, tx, y, pixel);
}
else if (m)
{
BYTE r, g, b;
pixel = XGetPixel (image, tx, y);
r = GetField(pixel, r_shift, r_len);
r = ((BYTE)~m * (WORD)r + (BYTE)m * (WORD)src_r) >> 8;
g = GetField(pixel, g_shift, g_len);
g = ((BYTE)~m * (WORD)g + (BYTE)m * (WORD)src_g) >> 8;
b = GetField(pixel, b_shift, b_len);
b = ((BYTE)~m * (WORD)b + (BYTE)m * (WORD)src_b) >> 8;
pixel = (PutField (r, r_shift, r_len) |
PutField (g, g_shift, g_len) |
PutField (b, b_shift, b_len));
XPutPixel (image, tx, y, pixel);
}
}
}
}
static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
{
return 1;
}
/***********************************************************************
* X11DRV_XRender_ExtTextOut
*/
@ -601,6 +915,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
BOOL retv = FALSE;
HDC hdc = physDev->hdc;
DC *dc = physDev->dc;
int textPixel, backgroundPixel;
INT *deltas = NULL;
INT char_extra;
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
lprect, debugstr_wn(wstr, count), count, lpDx);
@ -658,8 +975,21 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod, FALSE );
if(dc->bitsPerPixel == 1) {
if((dc->textColor & 0xffffff) == 0) {
textPixel = 0;
backgroundPixel = 1;
} else {
textPixel = 1;
backgroundPixel = 0;
}
} else {
textPixel = physDev->textPixel;
backgroundPixel = physDev->backgroundPixel;
}
if(flags & ETO_OPAQUE) {
TSXSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
TSXSetForeground( gdi_display, physDev->gc, backgroundPixel );
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + rc.left, physDev->org.y + rc.top,
rc.right - rc.left, rc.bottom - rc.top );
@ -678,10 +1008,26 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
TRACE("real x,y %d,%d\n", x, y);
if(lpDx) {
if((char_extra = GetTextCharacterExtra(physDev->hdc)) != 0) {
INT i;
SIZE tmpsz;
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
for(i = 0; i < count; i++) {
deltas[i] = char_extra;
if(lpDx)
deltas[i] += lpDx[i];
else {
GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
deltas[i] += tmpsz.cx;
}
}
} else if(lpDx)
deltas = (INT*)lpDx;
if(deltas) {
width = 0;
for(idx = 0; idx < count; idx++)
width += lpDx[idx];
width += deltas[idx];
} else {
if(!done_extents) {
GetTextExtentPointI(hdc, glyphs, count, &sz);
@ -747,6 +1093,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
IntersectVisRect16( HDC_16(dc->hSelf), lprect->left, lprect->top, lprect->right, lprect->bottom );
}
if(X11DRV_XRender_Installed) {
if(!physDev->xrender->pict) {
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
@ -761,7 +1108,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
TRACE("allocing pict = %lx dc = %p drawable = %08lx\n", physDev->xrender->pict, dc, physDev->drawable);
} else {
TRACE("using existing pict = %lx dc = %p\n", physDev->xrender->pict, dc);
TRACE("using existing pict = %lx dc = %p drawable = %08lx\n", physDev->xrender->pict, dc, physDev->drawable);
}
if ((data = X11DRV_GetRegionData( dc->hGCClipRgn, 0 )))
@ -773,12 +1120,13 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
wine_tsx11_unlock();
HeapFree( GetProcessHeap(), 0, data );
}
}
if(GetBkMode(hdc) != TRANSPARENT) {
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE))) {
if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom) {
TSXSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
TSXSetForeground( gdi_display, physDev->gc, backgroundPixel );
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y - tm.tmAscent,
width, tm.tmAscent + tm.tmDescent );
@ -786,6 +1134,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
}
}
if(X11DRV_XRender_Installed) {
/* Create a 1x1 pixmap to tile over the font mask */
if(!physDev->xrender->tile_xpm) {
XRenderPictureAttributes pa;
@ -832,8 +1181,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
/* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
*/
if((dc->bitsPerPixel == 1) && ((dc->textColor & 0xffffff) == 0))
if((dc->bitsPerPixel == 1) && (textPixel == 0))
render_op = PictOpOutReverse; /* This gives us 'black' text */
}
EnterCriticalSection(&xrender_cs);
entry = glyphsetCache + physDev->xrender->cache_index;
@ -848,8 +1198,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
TRACE("Writing %s at %ld,%ld\n", debugstr_wn(wstr,count),
physDev->org.x + x, physDev->org.y + y);
if(X11DRV_XRender_Installed) {
wine_tsx11_lock();
if(!lpDx)
if(!deltas)
pXRenderCompositeString16(gdi_display, render_op,
physDev->xrender->tile_pict,
physDev->xrender->pict,
@ -867,19 +1218,172 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
0, 0, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
glyphs + idx, 1);
offset += INTERNAL_XWSTODS(dc, lpDx[idx]);
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
}
}
wine_tsx11_unlock();
} else {
INT offset = 0, xoff = 0, yoff = 0;
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, textPixel );
if(entry->aa == AA_None) {
for(idx = 0; idx < count; idx++) {
SharpGlyphMono(physDev, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
entry->bitmaps[glyphs[idx]],
&entry->gis[glyphs[idx]]);
if(deltas) {
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += entry->gis[glyphs[idx]].xOff;
yoff += entry->gis[glyphs[idx]].yOff;
}
}
} else if(dc->bitsPerPixel == 1) {
for(idx = 0; idx < count; idx++) {
SharpGlyphGray(physDev, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
entry->bitmaps[glyphs[idx]],
&entry->gis[glyphs[idx]]);
if(deltas) {
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += entry->gis[glyphs[idx]].xOff;
yoff += entry->gis[glyphs[idx]].yOff;
}
}
} else {
XImage *image;
unsigned int w, h, dummy_uint;
Window dummy_window;
int dummy_int;
int image_x, image_y, image_off_x, image_off_y, image_w, image_h;
RECT extents = {0, 0, 0, 0};
POINT cur = {0, 0};
XGetGeometry(gdi_display, physDev->drawable, &dummy_window, &dummy_int, &dummy_int,
&w, &h, &dummy_uint, &dummy_uint);
TRACE("drawable %dx%d\n", w, h);
for(idx = 0; idx < count; idx++) {
if(extents.left > cur.x - entry->gis[glyphs[idx]].x)
extents.left = cur.x - entry->gis[glyphs[idx]].x;
if(extents.top > cur.y - entry->gis[glyphs[idx]].y)
extents.top = cur.y - entry->gis[glyphs[idx]].y;
if(extents.right < cur.x - entry->gis[glyphs[idx]].x + entry->gis[glyphs[idx]].width)
extents.right = cur.x - entry->gis[glyphs[idx]].x + entry->gis[glyphs[idx]].width;
if(extents.bottom < cur.y - entry->gis[glyphs[idx]].y + entry->gis[glyphs[idx]].height)
extents.bottom = cur.y - entry->gis[glyphs[idx]].y + entry->gis[glyphs[idx]].height;
if(deltas) {
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
cur.x = offset * cosEsc;
cur.y = offset * -sinEsc;
} else {
cur.x += entry->gis[glyphs[idx]].xOff;
cur.y += entry->gis[glyphs[idx]].yOff;
}
}
TRACE("glyph extents %d,%d - %d,%d drawable x,y %ld,%ld\n", extents.left, extents.top,
extents.right, extents.bottom, physDev->org.x + x, physDev->org.y + y);
if(physDev->org.x + x + extents.left >= 0) {
image_x = physDev->org.x + x + extents.left;
image_off_x = 0;
} else {
image_x = 0;
image_off_x = physDev->org.x + x + extents.left;
}
if(physDev->org.y + y + extents.top >= 0) {
image_y = physDev->org.y + y + extents.top;
image_off_y = 0;
} else {
image_y = 0;
image_off_y = physDev->org.y + y + extents.top;
}
if(physDev->org.x + x + extents.right < w)
image_w = physDev->org.x + x + extents.right - image_x;
else
image_w = w - image_x;
if(physDev->org.y + y + extents.bottom < h)
image_h = physDev->org.y + y + extents.bottom - image_y;
else
image_h = h - image_y;
if(image_w <= 0 || image_h <= 0) goto no_image;
X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
image = XGetImage(gdi_display, physDev->drawable,
image_x, image_y, image_w, image_h,
AllPlanes, ZPixmap);
X11DRV_check_error();
TRACE("XGetImage(%p, %x, %d, %d, %d, %d, %lx, %x) depth = %d rets %p\n",
gdi_display, (int)physDev->drawable, image_x, image_y,
image_w, image_h, AllPlanes, ZPixmap,
dc->bitsPerPixel, image);
if(!image) {
Pixmap xpm = XCreatePixmap(gdi_display, physDev->drawable, image_w, image_h,
dc->bitsPerPixel);
GC gc;
XGCValues gcv;
gcv.graphics_exposures = False;
gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
XCopyArea(gdi_display, physDev->drawable, xpm, gc, image_x, image_y,
image_w, image_h, 0, 0);
XFreeGC(gdi_display, gc);
X11DRV_expect_error(gdi_display, XRenderErrorHandler, NULL);
image = XGetImage(gdi_display, xpm, 0, 0, image_w, image_h, AllPlanes,
ZPixmap);
X11DRV_check_error();
XFreePixmap(gdi_display, xpm);
}
if(!image) goto no_image;
image->red_mask = visual->red_mask;
image->green_mask = visual->green_mask;
image->blue_mask = visual->blue_mask;
offset = xoff = yoff = 0;
for(idx = 0; idx < count; idx++) {
SmoothGlyphGray(image, xoff + image_off_x - extents.left,
yoff + image_off_y - extents.top,
entry->bitmaps[glyphs[idx]],
&entry->gis[glyphs[idx]],
dc->textColor);
if(deltas) {
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += entry->gis[glyphs[idx]].xOff;
yoff += entry->gis[glyphs[idx]].yOff;
}
}
XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
image_x, image_y, image_w, image_h);
XDestroyImage(image);
no_image:
}
wine_tsx11_unlock();
}
LeaveCriticalSection(&xrender_cs);
if(physDev->xrender->pict) {
pXRenderFreePicture(gdi_display, physDev->xrender->pict);
}
physDev->xrender->pict = 0;
wine_tsx11_unlock();
if(deltas && deltas != lpDx)
HeapFree(GetProcessHeap(), 0, deltas);
if (flags & ETO_CLIPPED)
RestoreVisRgn16( HDC_16(hdc) );

View File

@ -137,6 +137,18 @@ WINE REGISTRY Version 2
;; "XVideoPort" = "43"
; Run in synchronous mode (useful for debugging X11 problems)
;;"Synchronous" = "Y"
;
; Use the Render extension to render client side fonts (default "Y")
;;"ClientSideWithRender" = "Y"
; Fallback on X core requests to render client side fonts (default "Y")
;;"ClientSideWithCore" = "Y"
; Set both of the previous two to "N" in order to force X11 server side fonts
;
; Anti-alias fonts if using the Render extension (default "Y")
;;"ClientSideAntiAliasWithRender" = "Y"
; Anti-alias fonts if using core requests fallback (default "Y")
;;"ClientSideAntiAliasWithCore" = "Y"
;
[fonts]
;Read the Fonts topic in the Wine User Guide before adding aliases

View File

@ -80,6 +80,9 @@ HBITMAP X11DRV_SelectBitmap( X11DRV_PDEVICE *physDev, HBITMAP hbitmap )
if (!(bmp = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
if(physDev->xrender)
X11DRV_XRender_UpdateDrawable( physDev );
if (hbitmap == GetStockObject(DEFAULT_BITMAP))
physDev->drawable = BITMAP_stock_pixmap;
else

View File

@ -136,12 +136,13 @@ void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, const POINT *org,
{
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
if(physDev->xrender)
X11DRV_XRender_UpdateDrawable( physDev );
physDev->org = *org;
physDev->drawable = drawable;
physDev->drawable_org = *drawable_org;
TSXSetSubwindowMode( gdi_display, physDev->gc, mode );
if(physDev->xrender)
X11DRV_XRender_UpdateDrawable( physDev );
GDI_ReleaseObj( hdc );
}
}

View File

@ -3007,7 +3007,7 @@ void X11DRV_FONT_Init( int *log_pixels_x, int *log_pixels_y )
{
XFONT_GetPointResolution( log_pixels_x, log_pixels_y );
if(X11DRV_XRender_Installed)
if(using_client_side_fonts)
text_caps |= TC_VA_ABLE;
return;
@ -3263,7 +3263,7 @@ HFONT X11DRV_SelectFont( X11DRV_PDEVICE *physDev, HFONT hfont )
TRACE("dc->gdiFont = %p\n", dc->gdiFont);
if(dc->gdiFont && X11DRV_XRender_Installed) {
if(dc->gdiFont && using_client_side_fonts) {
X11DRV_XRender_SelectFont(physDev, hfont);
return FALSE;
}

View File

@ -212,7 +212,11 @@ extern const int X11DRV_XROPfunction[];
extern void _XInitImageFuncPtrs(XImage *);
extern BOOL X11DRV_XRender_Installed;
extern int client_side_with_core;
extern int client_side_with_render;
extern int client_side_antialias_with_core;
extern int client_side_antialias_with_render;
extern int using_client_side_fonts;
extern void X11DRV_XRender_Init(void);
extern void X11DRV_XRender_Finalize(void);
extern BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE*, HFONT);