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 dxgrab, usedga, usexvidmode;
|
||||||
int use_take_focus = 1;
|
int use_take_focus = 1;
|
||||||
int managed_mode = 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;
|
unsigned int X11DRV_server_startticks;
|
||||||
|
|
||||||
@ -252,6 +256,18 @@ static void setup_options(void)
|
|||||||
if (!get_config_key( hkey, appkey, "Synchronous", buffer, sizeof(buffer) ))
|
if (!get_config_key( hkey, appkey, "Synchronous", buffer, sizeof(buffer) ))
|
||||||
synchronous = IS_OPTION_TRUE( buffer[0] );
|
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 );
|
if (appkey) RegCloseKey( appkey );
|
||||||
RegCloseKey( hkey );
|
RegCloseKey( hkey );
|
||||||
}
|
}
|
||||||
@ -381,6 +397,8 @@ static void process_detach(void)
|
|||||||
/* cleanup XVidMode */
|
/* cleanup XVidMode */
|
||||||
X11DRV_XF86VM_Cleanup();
|
X11DRV_XF86VM_Cleanup();
|
||||||
#endif
|
#endif
|
||||||
|
if(using_client_side_fonts)
|
||||||
|
X11DRV_XRender_Finalize();
|
||||||
|
|
||||||
/* FIXME: should detach all threads */
|
/* FIXME: should detach all threads */
|
||||||
thread_detach();
|
thread_detach();
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Functions to use the XRender extension
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -31,7 +34,9 @@
|
|||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.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);
|
WINE_DEFAULT_DEBUG_CHANNEL(xrender);
|
||||||
|
|
||||||
#ifdef HAVE_X11_EXTENSIONS_XRENDER_H
|
#ifdef HAVE_X11_EXTENSIONS_XRENDER_H
|
||||||
@ -51,14 +56,18 @@ typedef struct
|
|||||||
|
|
||||||
#define INITIAL_REALIZED_BUF_SIZE 128
|
#define INITIAL_REALIZED_BUF_SIZE 128
|
||||||
|
|
||||||
|
typedef enum { AA_None, AA_Grey, AA_RGB, AA_BGR, AA_VRGB, AA_VBGR } AA_Type;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
LFANDSIZE lfsz;
|
LFANDSIZE lfsz;
|
||||||
|
AA_Type aa;
|
||||||
GlyphSet glyphset;
|
GlyphSet glyphset;
|
||||||
XRenderPictFormat *font_format;
|
XRenderPictFormat *font_format;
|
||||||
int nrealized;
|
int nrealized;
|
||||||
BOOL *realized;
|
BOOL *realized;
|
||||||
|
void **bitmaps;
|
||||||
|
XGlyphInfo *gis;
|
||||||
UINT count;
|
UINT count;
|
||||||
INT next;
|
INT next;
|
||||||
} gsCacheEntry;
|
} gsCacheEntry;
|
||||||
@ -125,10 +134,11 @@ void X11DRV_XRender_Init(void)
|
|||||||
int error_base, event_base, i;
|
int error_base, event_base, i;
|
||||||
XRenderPictFormat pf;
|
XRenderPictFormat pf;
|
||||||
|
|
||||||
if (!wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0)) return;
|
if (client_side_with_render &&
|
||||||
if (!wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0)) return;
|
wine_dlopen(SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
|
||||||
xrender_handle = wine_dlopen(SONAME_LIBXRENDER, RTLD_NOW, NULL, 0);
|
wine_dlopen(SONAME_LIBXEXT, RTLD_NOW|RTLD_GLOBAL, NULL, 0) &&
|
||||||
if(!xrender_handle) return;
|
(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;
|
#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
|
||||||
LOAD_FUNCPTR(XRenderAddGlyphs)
|
LOAD_FUNCPTR(XRenderAddGlyphs)
|
||||||
@ -168,11 +178,16 @@ LOAD_FUNCPTR(XRenderQueryExtension)
|
|||||||
PictFormatDepth | PictFormatAlpha |
|
PictFormatDepth | PictFormatAlpha |
|
||||||
PictFormatAlphaMask, &pf, 0);
|
PictFormatAlphaMask, &pf, 0);
|
||||||
if(!mono_format) {
|
if(!mono_format) {
|
||||||
wine_tsx11_unlock();
|
|
||||||
ERR("mono_format == NULL?\n");
|
ERR("mono_format == NULL?\n");
|
||||||
X11DRV_XRender_Installed = FALSE;
|
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,
|
glyphsetCache = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||||
sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
|
sizeof(*glyphsetCache) * INIT_CACHE_SIZE);
|
||||||
|
|
||||||
@ -183,15 +198,18 @@ LOAD_FUNCPTR(XRenderQueryExtension)
|
|||||||
glyphsetCache[i].count = -1;
|
glyphsetCache[i].count = -1;
|
||||||
}
|
}
|
||||||
glyphsetCache[i-1].next = -1;
|
glyphsetCache[i-1].next = -1;
|
||||||
} else {
|
using_client_side_fonts = 1;
|
||||||
TRACE("Xrender is not available on this server\n");
|
|
||||||
}
|
|
||||||
wine_tsx11_unlock();
|
|
||||||
return;
|
|
||||||
|
|
||||||
sym_not_found:
|
if(!X11DRV_XRender_Installed) {
|
||||||
wine_dlclose(xrender_handle, NULL, 0);
|
TRACE("Xrender is not available on your XServer, client side rendering with the core protocol instead.\n");
|
||||||
xrender_handle = NULL;
|
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)
|
static BOOL fontcmp(LFANDSIZE *p1, LFANDSIZE *p2)
|
||||||
@ -241,6 +259,32 @@ static int LookupEntry(LFANDSIZE *plfsz)
|
|||||||
return -1;
|
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)
|
static int AllocEntry(void)
|
||||||
{
|
{
|
||||||
int best = -1, prev_best = -1, i, prev_i = -1;
|
int best = -1, prev_best = -1, i, prev_i = -1;
|
||||||
@ -268,15 +312,7 @@ static int AllocEntry(void)
|
|||||||
|
|
||||||
if(best >= 0) {
|
if(best >= 0) {
|
||||||
TRACE("freeing unused glyphset at cache %d\n", best);
|
TRACE("freeing unused glyphset at cache %d\n", best);
|
||||||
wine_tsx11_lock();
|
FreeEntry(best);
|
||||||
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;
|
|
||||||
}
|
|
||||||
glyphsetCache[best].count = 1;
|
glyphsetCache[best].count = 1;
|
||||||
if(prev_best >= 0) {
|
if(prev_best >= 0) {
|
||||||
glyphsetCache[prev_best].next = glyphsetCache[best].next;
|
glyphsetCache[prev_best].next = glyphsetCache[best].next;
|
||||||
@ -322,14 +358,26 @@ static int GetCacheEntry(LFANDSIZE *plfsz)
|
|||||||
entry->lfsz = *plfsz;
|
entry->lfsz = *plfsz;
|
||||||
assert(entry->nrealized == 0);
|
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.depth = 8;
|
||||||
pf.direct.alphaMask = 0xff;
|
pf.direct.alphaMask = 0xff;
|
||||||
} else {
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERR("aa = %d - not implemented\n", entry->aa);
|
||||||
|
case AA_None:
|
||||||
pf.depth = 1;
|
pf.depth = 1;
|
||||||
pf.direct.alphaMask = 1;
|
pf.direct.alphaMask = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pf.type = PictTypeDirect;
|
pf.type = PictTypeDirect;
|
||||||
pf.direct.alpha = 0;
|
pf.direct.alpha = 0;
|
||||||
|
|
||||||
@ -343,6 +391,7 @@ static int GetCacheEntry(LFANDSIZE *plfsz)
|
|||||||
|
|
||||||
entry->glyphset = pXRenderCreateGlyphSet(gdi_display, entry->font_format);
|
entry->glyphset = pXRenderCreateGlyphSet(gdi_display, entry->font_format);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,11 +428,12 @@ static void lfsz_calc_hash(LFANDSIZE *plfsz)
|
|||||||
*/
|
*/
|
||||||
void X11DRV_XRender_Finalize(void)
|
void X11DRV_XRender_Finalize(void)
|
||||||
{
|
{
|
||||||
FIXME("Free cached glyphsets\n");
|
int i;
|
||||||
#if 0
|
|
||||||
if (xrender_handle) wine_dlclose(xrender_handle, NULL, 0);
|
EnterCriticalSection(&xrender_cs);
|
||||||
xrender_handle = NULL;
|
for(i = mru; i >= 0; i = glyphsetCache[i].next)
|
||||||
#endif
|
FreeEntry(i);
|
||||||
|
LeaveCriticalSection(&xrender_cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -445,15 +495,16 @@ void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE *physDev)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* X11DRV_XRender_UpdateDrawable
|
* X11DRV_XRender_UpdateDrawable
|
||||||
*
|
*
|
||||||
* This gets called from X11DRV_SetDrawable and deletes the pict when the
|
* This gets called from X11DRV_SetDrawable and X11DRV_SelectBitmap.
|
||||||
* drawable changes. However at the moment we delete the pict at the end of
|
* It deletes the pict when the drawable changes.
|
||||||
* every ExtTextOut so this is basically a NOP.
|
|
||||||
*/
|
*/
|
||||||
void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
|
void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev)
|
||||||
{
|
{
|
||||||
if(physDev->xrender->pict) {
|
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();
|
wine_tsx11_lock();
|
||||||
|
XFlush(gdi_display);
|
||||||
pXRenderFreePicture(gdi_display, physDev->xrender->pict);
|
pXRenderFreePicture(gdi_display, physDev->xrender->pict);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
}
|
}
|
||||||
@ -475,7 +526,6 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
|
|||||||
XGlyphInfo gi;
|
XGlyphInfo gi;
|
||||||
gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
|
gsCacheEntry *entry = glyphsetCache + physDev->xrender->cache_index;
|
||||||
UINT ggo_format = GGO_GLYPH_INDEX;
|
UINT ggo_format = GGO_GLYPH_INDEX;
|
||||||
BOOL aa;
|
|
||||||
|
|
||||||
if(entry->nrealized <= glyph) {
|
if(entry->nrealized <= glyph) {
|
||||||
entry->nrealized = (glyph / 128 + 1) * 128;
|
entry->nrealized = (glyph / 128 + 1) * 128;
|
||||||
@ -483,14 +533,28 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
|
|||||||
HEAP_ZERO_MEMORY,
|
HEAP_ZERO_MEMORY,
|
||||||
entry->realized,
|
entry->realized,
|
||||||
entry->nrealized * sizeof(BOOL));
|
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) {
|
switch(entry->aa) {
|
||||||
aa = TRUE;
|
case AA_Grey:
|
||||||
ggo_format |= WINE_GGO_GRAY16_BITMAP;
|
ggo_format |= WINE_GGO_GRAY16_BITMAP;
|
||||||
} else {
|
break;
|
||||||
aa = FALSE;
|
|
||||||
|
default:
|
||||||
|
ERR("aa = %d - not implemented\n", entry->aa);
|
||||||
|
case AA_None:
|
||||||
ggo_format |= GGO_BITMAP;
|
ggo_format |= GGO_BITMAP;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buflen = GetGlyphOutlineW(physDev->hdc, glyph, ggo_format, &gm, 0, NULL,
|
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];
|
char output[300];
|
||||||
unsigned char *line;
|
unsigned char *line;
|
||||||
|
|
||||||
if(!aa) {
|
if(entry->aa == AA_None) {
|
||||||
pitch = ((gi.width + 31) / 32) * 4;
|
pitch = ((gi.width + 31) / 32) * 4;
|
||||||
for(i = 0; i < gi.height; i++) {
|
for(i = 0; i < gi.height; i++) {
|
||||||
line = buf + i * pitch;
|
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;
|
unsigned char *byte = buf, c;
|
||||||
int i = buflen;
|
int i = buflen;
|
||||||
|
|
||||||
@ -573,9 +638,258 @@ static BOOL UploadGlyph(X11DRV_PDEVICE *physDev, int glyph)
|
|||||||
buf, buflen);
|
buf, buflen);
|
||||||
wine_tsx11_unlock();
|
wine_tsx11_unlock();
|
||||||
HeapFree(GetProcessHeap(), 0, buf);
|
HeapFree(GetProcessHeap(), 0, buf);
|
||||||
|
} else {
|
||||||
|
entry->bitmaps[glyph] = buf;
|
||||||
|
memcpy(&entry->gis[glyph], &gi, sizeof(gi));
|
||||||
|
}
|
||||||
return TRUE;
|
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
|
* X11DRV_XRender_ExtTextOut
|
||||||
*/
|
*/
|
||||||
@ -601,6 +915,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
|
|||||||
BOOL retv = FALSE;
|
BOOL retv = FALSE;
|
||||||
HDC hdc = physDev->hdc;
|
HDC hdc = physDev->hdc;
|
||||||
DC *dc = physDev->dc;
|
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,
|
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
|
||||||
lprect, debugstr_wn(wstr, count), count, lpDx);
|
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 );
|
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) {
|
if(flags & ETO_OPAQUE) {
|
||||||
TSXSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
|
TSXSetForeground( gdi_display, physDev->gc, backgroundPixel );
|
||||||
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
|
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
|
||||||
physDev->org.x + rc.left, physDev->org.y + rc.top,
|
physDev->org.x + rc.left, physDev->org.y + rc.top,
|
||||||
rc.right - rc.left, rc.bottom - 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);
|
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;
|
width = 0;
|
||||||
for(idx = 0; idx < count; idx++)
|
for(idx = 0; idx < count; idx++)
|
||||||
width += lpDx[idx];
|
width += deltas[idx];
|
||||||
} else {
|
} else {
|
||||||
if(!done_extents) {
|
if(!done_extents) {
|
||||||
GetTextExtentPointI(hdc, glyphs, count, &sz);
|
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 );
|
IntersectVisRect16( HDC_16(dc->hSelf), lprect->left, lprect->top, lprect->right, lprect->bottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(X11DRV_XRender_Installed) {
|
||||||
if(!physDev->xrender->pict) {
|
if(!physDev->xrender->pict) {
|
||||||
XRenderPictureAttributes pa;
|
XRenderPictureAttributes pa;
|
||||||
pa.subwindow_mode = IncludeInferiors;
|
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);
|
TRACE("allocing pict = %lx dc = %p drawable = %08lx\n", physDev->xrender->pict, dc, physDev->drawable);
|
||||||
} else {
|
} 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 )))
|
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();
|
wine_tsx11_unlock();
|
||||||
HeapFree( GetProcessHeap(), 0, data );
|
HeapFree( GetProcessHeap(), 0, data );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(GetBkMode(hdc) != TRANSPARENT) {
|
if(GetBkMode(hdc) != TRANSPARENT) {
|
||||||
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE))) {
|
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE))) {
|
||||||
if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
|
if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
|
||||||
y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom) {
|
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,
|
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
|
||||||
physDev->org.x + x, physDev->org.y + y - tm.tmAscent,
|
physDev->org.x + x, physDev->org.y + y - tm.tmAscent,
|
||||||
width, tm.tmAscent + tm.tmDescent );
|
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 */
|
/* Create a 1x1 pixmap to tile over the font mask */
|
||||||
if(!physDev->xrender->tile_xpm) {
|
if(!physDev->xrender->tile_xpm) {
|
||||||
XRenderPictureAttributes pa;
|
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.
|
/* 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 */
|
render_op = PictOpOutReverse; /* This gives us 'black' text */
|
||||||
|
}
|
||||||
|
|
||||||
EnterCriticalSection(&xrender_cs);
|
EnterCriticalSection(&xrender_cs);
|
||||||
entry = glyphsetCache + physDev->xrender->cache_index;
|
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),
|
TRACE("Writing %s at %ld,%ld\n", debugstr_wn(wstr,count),
|
||||||
physDev->org.x + x, physDev->org.y + y);
|
physDev->org.x + x, physDev->org.y + y);
|
||||||
|
|
||||||
|
if(X11DRV_XRender_Installed) {
|
||||||
wine_tsx11_lock();
|
wine_tsx11_lock();
|
||||||
if(!lpDx)
|
if(!deltas)
|
||||||
pXRenderCompositeString16(gdi_display, render_op,
|
pXRenderCompositeString16(gdi_display, render_op,
|
||||||
physDev->xrender->tile_pict,
|
physDev->xrender->tile_pict,
|
||||||
physDev->xrender->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,
|
0, 0, physDev->org.x + x + xoff,
|
||||||
physDev->org.y + y + yoff,
|
physDev->org.y + y + yoff,
|
||||||
glyphs + idx, 1);
|
glyphs + idx, 1);
|
||||||
offset += INTERNAL_XWSTODS(dc, lpDx[idx]);
|
offset += INTERNAL_XWSTODS(dc, deltas[idx]);
|
||||||
xoff = offset * cosEsc;
|
xoff = offset * cosEsc;
|
||||||
yoff = offset * -sinEsc;
|
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);
|
LeaveCriticalSection(&xrender_cs);
|
||||||
|
|
||||||
if(physDev->xrender->pict) {
|
if(deltas && deltas != lpDx)
|
||||||
pXRenderFreePicture(gdi_display, physDev->xrender->pict);
|
HeapFree(GetProcessHeap(), 0, deltas);
|
||||||
}
|
|
||||||
physDev->xrender->pict = 0;
|
|
||||||
wine_tsx11_unlock();
|
|
||||||
|
|
||||||
if (flags & ETO_CLIPPED)
|
if (flags & ETO_CLIPPED)
|
||||||
RestoreVisRgn16( HDC_16(hdc) );
|
RestoreVisRgn16( HDC_16(hdc) );
|
||||||
|
@ -137,6 +137,18 @@ WINE REGISTRY Version 2
|
|||||||
;; "XVideoPort" = "43"
|
;; "XVideoPort" = "43"
|
||||||
; Run in synchronous mode (useful for debugging X11 problems)
|
; Run in synchronous mode (useful for debugging X11 problems)
|
||||||
;;"Synchronous" = "Y"
|
;;"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]
|
[fonts]
|
||||||
;Read the Fonts topic in the Wine User Guide before adding aliases
|
;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 (!(bmp = GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
|
||||||
|
|
||||||
|
if(physDev->xrender)
|
||||||
|
X11DRV_XRender_UpdateDrawable( physDev );
|
||||||
|
|
||||||
if (hbitmap == GetStockObject(DEFAULT_BITMAP))
|
if (hbitmap == GetStockObject(DEFAULT_BITMAP))
|
||||||
physDev->drawable = BITMAP_stock_pixmap;
|
physDev->drawable = BITMAP_stock_pixmap;
|
||||||
else
|
else
|
||||||
|
@ -136,12 +136,13 @@ void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, const POINT *org,
|
|||||||
{
|
{
|
||||||
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
|
X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
|
||||||
|
|
||||||
|
if(physDev->xrender)
|
||||||
|
X11DRV_XRender_UpdateDrawable( physDev );
|
||||||
|
|
||||||
physDev->org = *org;
|
physDev->org = *org;
|
||||||
physDev->drawable = drawable;
|
physDev->drawable = drawable;
|
||||||
physDev->drawable_org = *drawable_org;
|
physDev->drawable_org = *drawable_org;
|
||||||
TSXSetSubwindowMode( gdi_display, physDev->gc, mode );
|
TSXSetSubwindowMode( gdi_display, physDev->gc, mode );
|
||||||
if(physDev->xrender)
|
|
||||||
X11DRV_XRender_UpdateDrawable( physDev );
|
|
||||||
GDI_ReleaseObj( hdc );
|
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 );
|
XFONT_GetPointResolution( log_pixels_x, log_pixels_y );
|
||||||
|
|
||||||
if(X11DRV_XRender_Installed)
|
if(using_client_side_fonts)
|
||||||
text_caps |= TC_VA_ABLE;
|
text_caps |= TC_VA_ABLE;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -3263,7 +3263,7 @@ HFONT X11DRV_SelectFont( X11DRV_PDEVICE *physDev, HFONT hfont )
|
|||||||
|
|
||||||
TRACE("dc->gdiFont = %p\n", dc->gdiFont);
|
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);
|
X11DRV_XRender_SelectFont(physDev, hfont);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,11 @@ extern const int X11DRV_XROPfunction[];
|
|||||||
|
|
||||||
extern void _XInitImageFuncPtrs(XImage *);
|
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_Init(void);
|
||||||
extern void X11DRV_XRender_Finalize(void);
|
extern void X11DRV_XRender_Finalize(void);
|
||||||
extern BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE*, HFONT);
|
extern BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE*, HFONT);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user