Client side render fonts for XServers without the Render extension
using X11 core requests.
This commit is contained in:
parent
3f61afbbc8
commit
94705862d6
@ -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();
|
||||
|
@ -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) );
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user