Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
6f7fc504
Commit
6f7fc504
authored
Jan 29, 2002
by
Huw D M Davies
Committed by
Alexandre Julliard
Jan 29, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Uses Xrender extension to allow client side font rendering.
Adds nice things like anti-aliased text.
parent
74e4d21e
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
873 additions
and
4 deletions
+873
-4
Makefile.in
dlls/x11drv/Makefile.in
+1
-0
x11drv.spec
dlls/x11drv/x11drv.spec
+1
-1
xrender.c
dlls/x11drv/xrender.c
+826
-0
clipping.c
graphics/x11drv/clipping.c
+2
-0
init.c
graphics/x11drv/init.c
+6
-0
text.c
graphics/x11drv/text.c
+7
-1
xfont.c
graphics/x11drv/xfont.c
+17
-2
x11drv.h
include/x11drv.h
+13
-0
No files found.
dlls/x11drv/Makefile.in
View file @
6f7fc504
...
...
@@ -15,6 +15,7 @@ C_SRCS = \
winpos.c
\
x11ddraw.c
\
x11drv_main.c
\
xrender.c
\
xvidmode.c
PROGRAMS
=
\
...
...
dlls/x11drv/x11drv.spec
View file @
6f7fc504
...
...
@@ -9,7 +9,7 @@ import kernel32.dll
import ntdll.dll
debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
key keyboard opengl palette text win x11drv)
key keyboard opengl palette text win x11drv
xrender
)
# GDI driver
...
...
dlls/x11drv/xrender.c
0 → 100644
View file @
6f7fc504
/*
* Functions to use the XRender extension
*
* Copyright 2001 Huw D M Davies for CodeWeavers
*/
#include "config.h"
#include "winnt.h"
#include "x11drv.h"
#include "bitmap.h"
#include "debugtools.h"
#include "region.h"
#include <string.h>
#include <stdlib.h>
#include "wine/unicode.h"
#include <assert.h>
BOOL
X11DRV_XRender_Installed
=
FALSE
;
DEFAULT_DEBUG_CHANNEL
(
xrender
);
#ifdef HAVE_LIBXRENDER
#include "ts_xlib.h"
#include "ts_xrender.h"
static
XRenderPictFormat
*
screen_format
;
/* format of screen */
static
XRenderPictFormat
*
mono_format
;
/* format of mono bitmap */
typedef
struct
{
LOGFONTW
lf
;
XFORM
xform
;
/* this is dum as we don't care about offsets */
DWORD
hash
;
}
LFANDSIZE
;
#define INITIAL_REALIZED_BUF_SIZE 128
typedef
struct
{
LFANDSIZE
lfsz
;
GlyphSet
glyphset
;
XRenderPictFormat
*
font_format
;
int
nrealized
;
BOOL
*
realized
;
UINT
count
;
INT
next
;
}
gsCacheEntry
;
struct
tagXRENDERINFO
{
gsCacheEntry
*
cacheEntry
;
Picture
pict
;
Picture
tile_pict
;
Pixmap
tile_xpm
;
COLORREF
lastTextColor
;
};
static
gsCacheEntry
*
glyphsetCache
=
NULL
;
static
DWORD
glyphsetCacheSize
=
0
;
static
INT
lastfree
=
-
1
;
static
INT
mru
=
-
1
;
#define INIT_CACHE_SIZE 10
static
int
antialias
=
1
;
/***********************************************************************
* X11DRV_XRender_Init
*
* Let's see if our XServer has the extension available
*
*/
void
X11DRV_XRender_Init
(
void
)
{
int
error_base
,
event_base
,
i
;
XRenderPictFormat
pf
;
if
(
TSXRenderQueryExtension
(
gdi_display
,
&
event_base
,
&
error_base
))
{
X11DRV_XRender_Installed
=
TRUE
;
TRACE
(
"Xrender is up and running error_base = %d
\n
"
,
error_base
);
screen_format
=
TSXRenderFindVisualFormat
(
gdi_display
,
visual
);
pf
.
type
=
PictTypeDirect
;
pf
.
depth
=
1
;
pf
.
direct
.
alpha
=
0
;
pf
.
direct
.
alphaMask
=
1
;
mono_format
=
TSXRenderFindFormat
(
gdi_display
,
PictFormatType
|
PictFormatDepth
|
PictFormatAlpha
|
PictFormatAlphaMask
,
&
pf
,
0
);
glyphsetCache
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
glyphsetCache
)
*
INIT_CACHE_SIZE
);
glyphsetCacheSize
=
INIT_CACHE_SIZE
;
lastfree
=
0
;
for
(
i
=
0
;
i
<
INIT_CACHE_SIZE
;
i
++
)
{
glyphsetCache
[
i
].
next
=
i
+
1
;
glyphsetCache
[
i
].
count
=
-
1
;
}
glyphsetCache
[
i
-
1
].
next
=
-
1
;
}
else
{
TRACE
(
"Xrender is not available on this server
\n
"
);
}
return
;
}
static
BOOL
fontcmp
(
LFANDSIZE
*
p1
,
LFANDSIZE
*
p2
)
{
if
(
p1
->
hash
!=
p2
->
hash
)
return
TRUE
;
if
(
memcmp
(
&
p1
->
xform
,
&
p2
->
xform
,
sizeof
(
p1
->
xform
)))
return
TRUE
;
if
(
memcmp
(
&
p1
->
lf
,
&
p2
->
lf
,
offsetof
(
LOGFONTW
,
lfFaceName
)))
return
TRUE
;
return
strcmpW
(
p1
->
lf
.
lfFaceName
,
p2
->
lf
.
lfFaceName
);
}
static
void
walk_cache
(
void
)
{
int
i
;
for
(
i
=
mru
;
i
>=
0
;
i
=
glyphsetCache
[
i
].
next
)
TRACE
(
"item %d
\n
"
,
i
);
}
static
gsCacheEntry
*
LookupEntry
(
LFANDSIZE
*
plfsz
)
{
int
i
,
prev_i
=
-
1
;
for
(
i
=
mru
;
i
>=
0
;
i
=
glyphsetCache
[
i
].
next
)
{
TRACE
(
"%d
\n
"
,
i
);
if
(
glyphsetCache
[
i
].
count
==
-
1
)
{
/* reached free list so stop */
i
=
-
1
;
break
;
}
if
(
!
fontcmp
(
&
glyphsetCache
[
i
].
lfsz
,
plfsz
))
{
glyphsetCache
[
i
].
count
++
;
if
(
prev_i
>=
0
)
{
glyphsetCache
[
prev_i
].
next
=
glyphsetCache
[
i
].
next
;
glyphsetCache
[
i
].
next
=
mru
;
mru
=
i
;
}
TRACE
(
"found font in cache %d
\n
"
,
i
);
return
glyphsetCache
+
i
;
}
prev_i
=
i
;
}
TRACE
(
"font not in cache
\n
"
);
return
NULL
;
}
static
gsCacheEntry
*
AllocEntry
(
void
)
{
int
best
=
-
1
,
prev_best
=
-
1
,
i
,
prev_i
=
-
1
;
if
(
lastfree
>=
0
)
{
assert
(
glyphsetCache
[
lastfree
].
count
==
-
1
);
glyphsetCache
[
lastfree
].
count
=
1
;
best
=
lastfree
;
lastfree
=
glyphsetCache
[
lastfree
].
next
;
assert
(
best
!=
mru
);
glyphsetCache
[
best
].
next
=
mru
;
mru
=
best
;
TRACE
(
"empty space at %d, next lastfree = %d
\n
"
,
mru
,
lastfree
);
return
glyphsetCache
+
mru
;
}
for
(
i
=
mru
;
i
>=
0
;
i
=
glyphsetCache
[
i
].
next
)
{
if
(
glyphsetCache
[
i
].
count
==
0
)
{
best
=
i
;
prev_best
=
prev_i
;
}
prev_i
=
i
;
}
if
(
best
>=
0
)
{
TRACE
(
"freeing unused glyphset at cache %d
\n
"
,
best
);
TSXRenderFreeGlyphSet
(
gdi_display
,
glyphsetCache
[
best
].
glyphset
);
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
;
if
(
prev_best
>=
0
)
{
glyphsetCache
[
prev_best
].
next
=
glyphsetCache
[
best
].
next
;
glyphsetCache
[
best
].
next
=
mru
;
mru
=
best
;
}
else
{
assert
(
mru
==
best
);
}
return
glyphsetCache
+
mru
;
}
TRACE
(
"Growing cache
\n
"
);
glyphsetCache
=
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
glyphsetCache
,
(
glyphsetCacheSize
+
INIT_CACHE_SIZE
)
*
sizeof
(
*
glyphsetCache
));
for
(
best
=
i
=
glyphsetCacheSize
;
i
<
glyphsetCacheSize
+
INIT_CACHE_SIZE
;
i
++
)
{
glyphsetCache
[
i
].
next
=
i
+
1
;
glyphsetCache
[
i
].
count
=
-
1
;
}
glyphsetCache
[
i
-
1
].
next
=
-
1
;
glyphsetCacheSize
+=
INIT_CACHE_SIZE
;
lastfree
=
glyphsetCache
[
best
].
next
;
glyphsetCache
[
best
].
count
=
1
;
glyphsetCache
[
best
].
next
=
mru
;
mru
=
best
;
TRACE
(
"new free cache slot at %d
\n
"
,
mru
);
return
glyphsetCache
+
mru
;
}
static
gsCacheEntry
*
GetCacheEntry
(
LFANDSIZE
*
plfsz
)
{
XRenderPictFormat
pf
;
gsCacheEntry
*
ret
;
if
((
ret
=
LookupEntry
(
plfsz
))
!=
NULL
)
return
ret
;
ret
=
AllocEntry
();
ret
->
lfsz
=
*
plfsz
;
assert
(
ret
->
nrealized
==
0
);
if
(
antialias
&&
abs
(
plfsz
->
lf
.
lfHeight
)
>
16
)
{
pf
.
depth
=
8
;
pf
.
direct
.
alphaMask
=
0xff
;
}
else
{
pf
.
depth
=
1
;
pf
.
direct
.
alphaMask
=
1
;
}
pf
.
type
=
PictTypeDirect
;
pf
.
direct
.
alpha
=
0
;
ret
->
font_format
=
TSXRenderFindFormat
(
gdi_display
,
PictFormatType
|
PictFormatDepth
|
PictFormatAlpha
|
PictFormatAlphaMask
,
&
pf
,
0
);
ret
->
glyphset
=
TSXRenderCreateGlyphSet
(
gdi_display
,
ret
->
font_format
);
return
ret
;
}
static
void
dec_ref_cache
(
gsCacheEntry
*
entry
)
{
TRACE
(
"dec'ing entry %d to %d
\n
"
,
entry
-
glyphsetCache
,
entry
->
count
-
1
);
assert
(
entry
->
count
>
0
);
entry
->
count
--
;
}
static
void
lfsz_calc_hash
(
LFANDSIZE
*
plfsz
)
{
DWORD
hash
=
0
,
*
ptr
;
int
i
;
for
(
ptr
=
(
DWORD
*
)
&
plfsz
->
xform
;
ptr
<
(
DWORD
*
)(
&
plfsz
->
xform
+
1
);
ptr
++
)
hash
^=
*
ptr
;
for
(
i
=
0
,
ptr
=
(
DWORD
*
)
&
plfsz
->
lf
;
i
<
7
;
i
++
,
ptr
++
)
hash
^=
*
ptr
;
for
(
i
=
0
,
ptr
=
(
DWORD
*
)
&
plfsz
->
lf
.
lfFaceName
;
i
<
LF_FACESIZE
/
2
;
i
++
,
ptr
++
)
{
WCHAR
*
pwc
=
(
WCHAR
*
)
ptr
;
if
(
!*
pwc
)
break
;
hash
^=
*
ptr
;
pwc
++
;
if
(
!*
pwc
)
break
;
}
plfsz
->
hash
=
hash
;
return
;
}
/***********************************************************************
* X11DRV_XRender_Finalize
*/
void
X11DRV_XRender_Finalize
(
void
)
{
FIXME
(
"Free cached glyphsets
\n
"
);
return
;
}
/***********************************************************************
* X11DRV_XRender_SelectFont
*/
BOOL
X11DRV_XRender_SelectFont
(
DC
*
dc
,
HFONT
hfont
)
{
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
LFANDSIZE
lfsz
;
GetObjectW
(
hfont
,
sizeof
(
lfsz
.
lf
),
&
lfsz
.
lf
);
TRACE
(
"h=%ld w=%ld weight=%ld it=%d charset=%d name=%s
\n
"
,
lfsz
.
lf
.
lfHeight
,
lfsz
.
lf
.
lfWidth
,
lfsz
.
lf
.
lfWeight
,
lfsz
.
lf
.
lfItalic
,
lfsz
.
lf
.
lfCharSet
,
debugstr_w
(
lfsz
.
lf
.
lfFaceName
));
lfsz
.
xform
=
dc
->
xformWorld2Vport
;
lfsz_calc_hash
(
&
lfsz
);
if
(
!
physDev
->
xrender
)
physDev
->
xrender
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
physDev
->
xrender
));
else
if
(
physDev
->
xrender
->
cacheEntry
)
dec_ref_cache
(
physDev
->
xrender
->
cacheEntry
);
physDev
->
xrender
->
cacheEntry
=
GetCacheEntry
(
&
lfsz
);
return
0
;
}
/***********************************************************************
* X11DRV_XRender_DeleteDC
*/
void
X11DRV_XRender_DeleteDC
(
DC
*
dc
)
{
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
if
(
physDev
->
xrender
->
tile_pict
)
TSXRenderFreePicture
(
gdi_display
,
physDev
->
xrender
->
tile_pict
);
if
(
physDev
->
xrender
->
tile_xpm
)
TSXFreePixmap
(
gdi_display
,
physDev
->
xrender
->
tile_xpm
);
if
(
physDev
->
xrender
->
pict
)
{
TRACE
(
"freeing pict = %lx dc = %p
\n
"
,
physDev
->
xrender
->
pict
,
dc
);
TSXRenderFreePicture
(
gdi_display
,
physDev
->
xrender
->
pict
);
}
if
(
physDev
->
xrender
->
cacheEntry
)
dec_ref_cache
(
physDev
->
xrender
->
cacheEntry
);
HeapFree
(
GetProcessHeap
(),
0
,
physDev
->
xrender
);
physDev
->
xrender
=
NULL
;
return
;
}
/***********************************************************************
* 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.
*/
void
X11DRV_XRender_UpdateDrawable
(
DC
*
dc
)
{
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
if
(
physDev
->
xrender
->
pict
)
{
TRACE
(
"freeing pict %08lx from dc %p
\n
"
,
physDev
->
xrender
->
pict
,
dc
);
TSXRenderFreePicture
(
gdi_display
,
physDev
->
xrender
->
pict
);
}
physDev
->
xrender
->
pict
=
0
;
return
;
}
static
BOOL
UploadGlyph
(
DC
*
dc
,
WCHAR
glyph
)
{
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
int
buflen
;
char
*
buf
;
Glyph
gid
;
GLYPHMETRICS
gm
;
XGlyphInfo
gi
;
gsCacheEntry
*
entry
=
physDev
->
xrender
->
cacheEntry
;
UINT
ggo_format
;
BOOL
aa
;
if
(
entry
->
nrealized
<=
glyph
)
{
entry
->
nrealized
=
(
glyph
/
128
+
1
)
*
128
;
entry
->
realized
=
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
entry
->
realized
,
entry
->
nrealized
*
sizeof
(
BOOL
));
}
entry
->
realized
[
glyph
]
=
TRUE
;
if
(
entry
->
font_format
->
depth
==
8
)
{
aa
=
TRUE
;
ggo_format
=
WINE_GGO_GRAY16_BITMAP
;
}
else
{
aa
=
FALSE
;
ggo_format
=
GGO_BITMAP
;
}
buflen
=
GetGlyphOutlineW
(
dc
->
hSelf
,
glyph
,
ggo_format
,
&
gm
,
0
,
NULL
,
NULL
);
if
(
buflen
==
GDI_ERROR
)
return
FALSE
;
buf
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
buflen
);
GetGlyphOutlineW
(
dc
->
hSelf
,
glyph
,
ggo_format
,
&
gm
,
buflen
,
buf
,
NULL
);
TRACE
(
"buflen = %d. Got metrics: %dx%d adv=%d,%d origin=%ld,%ld
\n
"
,
buflen
,
gm
.
gmBlackBoxX
,
gm
.
gmBlackBoxY
,
gm
.
gmCellIncX
,
gm
.
gmCellIncY
,
gm
.
gmptGlyphOrigin
.
x
,
gm
.
gmptGlyphOrigin
.
y
);
gi
.
width
=
gm
.
gmBlackBoxX
;
gi
.
height
=
gm
.
gmBlackBoxY
;
gi
.
x
=
-
gm
.
gmptGlyphOrigin
.
x
;
gi
.
y
=
gm
.
gmptGlyphOrigin
.
y
;
gi
.
xOff
=
gm
.
gmCellIncX
;
gi
.
yOff
=
gm
.
gmCellIncY
;
if
(
TRACE_ON
(
xrender
))
{
int
pitch
,
i
,
j
;
char
output
[
300
];
unsigned
char
*
line
;
if
(
!
aa
)
{
pitch
=
((
gi
.
width
+
31
)
/
32
)
*
4
;
for
(
i
=
0
;
i
<
gi
.
height
;
i
++
)
{
line
=
buf
+
i
*
pitch
;
output
[
0
]
=
'\0'
;
for
(
j
=
0
;
j
<
pitch
*
8
;
j
++
)
{
strcat
(
output
,
(
line
[
j
/
8
]
&
(
1
<<
(
7
-
(
j
%
8
))))
?
"#"
:
" "
);
}
strcat
(
output
,
"
\n
"
);
TRACE
(
output
);
}
}
else
{
char
blks
[]
=
" .:;!o*#"
;
char
str
[
2
];
str
[
1
]
=
'\0'
;
pitch
=
((
gi
.
width
+
3
)
/
4
)
*
4
;
for
(
i
=
0
;
i
<
gi
.
height
;
i
++
)
{
line
=
buf
+
i
*
pitch
;
output
[
0
]
=
'\0'
;
for
(
j
=
0
;
j
<
pitch
;
j
++
)
{
str
[
0
]
=
blks
[
line
[
j
]
>>
5
];
strcat
(
output
,
str
);
}
strcat
(
output
,
"
\n
"
);
TRACE
(
output
);
}
}
}
if
(
!
aa
&&
BitmapBitOrder
(
gdi_display
)
!=
MSBFirst
)
{
unsigned
char
*
byte
=
buf
,
c
;
int
i
=
buflen
;
while
(
i
--
)
{
c
=
*
byte
;
/* magic to flip bit order */
c
=
((
c
<<
1
)
&
0xaa
)
|
((
c
>>
1
)
&
0x55
);
c
=
((
c
<<
2
)
&
0xcc
)
|
((
c
>>
2
)
&
0x33
);
c
=
((
c
<<
4
)
&
0xf0
)
|
((
c
>>
4
)
&
0x0f
);
*
byte
++
=
c
;
}
}
gid
=
glyph
;
TSXRenderAddGlyphs
(
gdi_display
,
entry
->
glyphset
,
&
gid
,
&
gi
,
1
,
buf
,
buflen
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
return
TRUE
;
}
/***********************************************************************
* X11DRV_XRender_ExtTextOut
*/
BOOL
X11DRV_XRender_ExtTextOut
(
DC
*
dc
,
INT
x
,
INT
y
,
UINT
flags
,
const
RECT
*
lprect
,
LPCWSTR
wstr
,
UINT
count
,
const
INT
*
lpDx
)
{
XRenderColor
col
;
int
idx
;
TEXTMETRICW
tm
;
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
RGNOBJ
*
obj
;
XRectangle
*
pXrect
;
SIZE
sz
;
RECT
rc
;
BOOL
done_extents
=
FALSE
;
INT
width
,
xwidth
,
ywidth
;
double
cosEsc
,
sinEsc
;
XGCValues
xgcval
;
LOGFONTW
lf
;
int
render_op
=
PictOpOver
;
TRACE
(
"%04x, %d, %d, %08x, %p, %s, %d, %p)
\n
"
,
dc
->
hSelf
,
x
,
y
,
flags
,
lprect
,
debugstr_wn
(
wstr
,
count
),
count
,
lpDx
);
if
(
lprect
)
TRACE
(
"rect: %d,%d - %d,%d
\n
"
,
lprect
->
left
,
lprect
->
top
,
lprect
->
right
,
lprect
->
bottom
);
TRACE
(
"align = %x bkmode = %x mapmode = %x
\n
"
,
dc
->
textAlign
,
dc
->
backgroundMode
,
dc
->
MapMode
);
if
(
dc
->
textAlign
&
TA_UPDATECP
)
{
x
=
dc
->
CursPosX
;
y
=
dc
->
CursPosY
;
}
GetObjectW
(
GetCurrentObject
(
dc
->
hSelf
,
OBJ_FONT
),
sizeof
(
lf
),
&
lf
);
if
(
lf
.
lfEscapement
!=
0
)
{
cosEsc
=
cos
(
lf
.
lfEscapement
*
M_PI
/
1800
);
sinEsc
=
sin
(
lf
.
lfEscapement
*
M_PI
/
1800
);
}
else
{
cosEsc
=
1
;
sinEsc
=
0
;
}
if
(
flags
&
(
ETO_CLIPPED
|
ETO_OPAQUE
))
{
if
(
!
lprect
)
{
if
(
flags
&
ETO_CLIPPED
)
return
FALSE
;
GetTextExtentPointW
(
dc
->
hSelf
,
wstr
,
count
,
&
sz
);
done_extents
=
TRUE
;
rc
.
left
=
x
;
rc
.
top
=
y
;
rc
.
right
=
x
+
sz
.
cx
;
rc
.
bottom
=
y
+
sz
.
cy
;
}
else
{
rc
=
*
lprect
;
}
rc
.
left
=
INTERNAL_XWPTODP
(
dc
,
rc
.
left
,
rc
.
top
);
rc
.
top
=
INTERNAL_YWPTODP
(
dc
,
rc
.
left
,
rc
.
top
);
rc
.
right
=
INTERNAL_XWPTODP
(
dc
,
rc
.
right
,
rc
.
bottom
);
rc
.
bottom
=
INTERNAL_YWPTODP
(
dc
,
rc
.
right
,
rc
.
bottom
);
if
(
rc
.
left
>
rc
.
right
)
{
INT
tmp
=
rc
.
left
;
rc
.
left
=
rc
.
right
;
rc
.
right
=
tmp
;}
if
(
rc
.
top
>
rc
.
bottom
)
{
INT
tmp
=
rc
.
top
;
rc
.
top
=
rc
.
bottom
;
rc
.
bottom
=
tmp
;}
}
xgcval
.
function
=
GXcopy
;
xgcval
.
background
=
physDev
->
backgroundPixel
;
xgcval
.
fill_style
=
FillSolid
;
TSXChangeGC
(
gdi_display
,
physDev
->
gc
,
GCFunction
|
GCBackground
|
GCFillStyle
,
&
xgcval
);
X11DRV_LockDIBSection
(
dc
,
DIB_Status_GdiMod
,
FALSE
);
if
(
flags
&
ETO_OPAQUE
)
{
TSXSetForeground
(
gdi_display
,
physDev
->
gc
,
physDev
->
backgroundPixel
);
TSXFillRectangle
(
gdi_display
,
physDev
->
drawable
,
physDev
->
gc
,
dc
->
DCOrgX
+
rc
.
left
,
dc
->
DCOrgY
+
rc
.
top
,
rc
.
right
-
rc
.
left
,
rc
.
bottom
-
rc
.
top
);
}
if
(
count
==
0
)
{
X11DRV_UnlockDIBSection
(
dc
,
TRUE
);
return
TRUE
;
}
x
=
INTERNAL_XWPTODP
(
dc
,
x
,
y
);
y
=
INTERNAL_YWPTODP
(
dc
,
x
,
y
);
TRACE
(
"real x,y %d,%d
\n
"
,
x
,
y
);
if
(
lpDx
)
{
width
=
0
;
for
(
idx
=
0
;
idx
<
count
;
idx
++
)
width
+=
lpDx
[
idx
];
}
else
{
if
(
!
done_extents
)
{
GetTextExtentPointW
(
dc
->
hSelf
,
wstr
,
count
,
&
sz
);
done_extents
=
TRUE
;
}
width
=
sz
.
cx
;
}
width
=
INTERNAL_XWSTODS
(
dc
,
width
);
xwidth
=
width
*
cosEsc
;
ywidth
=
width
*
sinEsc
;
GetTextMetricsW
(
dc
->
hSelf
,
&
tm
);
switch
(
dc
->
textAlign
&
(
TA_LEFT
|
TA_RIGHT
|
TA_CENTER
)
)
{
case
TA_LEFT
:
if
(
dc
->
textAlign
&
TA_UPDATECP
)
{
dc
->
CursPosX
=
INTERNAL_XDPTOWP
(
dc
,
x
+
xwidth
,
y
-
ywidth
);
dc
->
CursPosY
=
INTERNAL_YDPTOWP
(
dc
,
x
+
xwidth
,
y
-
ywidth
);
}
break
;
case
TA_CENTER
:
x
-=
xwidth
/
2
;
y
+=
ywidth
/
2
;
break
;
case
TA_RIGHT
:
x
-=
xwidth
;
y
+=
ywidth
;
if
(
dc
->
textAlign
&
TA_UPDATECP
)
{
dc
->
CursPosX
=
INTERNAL_XDPTOWP
(
dc
,
x
+
xwidth
,
y
-
ywidth
);
dc
->
CursPosY
=
INTERNAL_YDPTOWP
(
dc
,
x
+
xwidth
,
y
-
ywidth
);
}
break
;
}
switch
(
dc
->
textAlign
&
(
TA_TOP
|
TA_BOTTOM
|
TA_BASELINE
)
)
{
case
TA_TOP
:
y
+=
tm
.
tmAscent
*
cosEsc
;
x
+=
tm
.
tmAscent
*
sinEsc
;
break
;
case
TA_BOTTOM
:
y
-=
tm
.
tmDescent
*
cosEsc
;
x
-=
tm
.
tmDescent
*
sinEsc
;
break
;
case
TA_BASELINE
:
break
;
}
if
(
flags
&
ETO_CLIPPED
)
{
SaveVisRgn16
(
dc
->
hSelf
);
CLIPPING_IntersectVisRect
(
dc
,
rc
.
left
,
rc
.
top
,
rc
.
right
,
rc
.
bottom
,
FALSE
);
}
if
(
!
physDev
->
xrender
->
pict
)
{
XRenderPictureAttributes
pa
;
pa
.
subwindow_mode
=
IncludeInferiors
;
physDev
->
xrender
->
pict
=
TSXRenderCreatePicture
(
gdi_display
,
physDev
->
drawable
,
(
dc
->
bitsPerPixel
==
1
)
?
mono_format
:
screen_format
,
CPSubwindowMode
,
&
pa
);
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
);
}
obj
=
(
RGNOBJ
*
)
GDI_GetObjPtr
(
dc
->
hGCClipRgn
,
REGION_MAGIC
);
if
(
!
obj
)
{
ERR
(
"Rgn is 0. Please report this.
\n
"
);
return
FALSE
;
}
if
(
obj
->
rgn
->
numRects
>
0
)
{
XRectangle
*
pXr
;
RECT
*
pRect
=
obj
->
rgn
->
rects
;
RECT
*
pEndRect
=
obj
->
rgn
->
rects
+
obj
->
rgn
->
numRects
;
pXrect
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
pXrect
)
*
obj
->
rgn
->
numRects
);
if
(
!
pXrect
)
{
WARN
(
"Can't alloc buffer
\n
"
);
GDI_ReleaseObj
(
dc
->
hGCClipRgn
);
return
FALSE
;
}
for
(
pXr
=
pXrect
;
pRect
<
pEndRect
;
pRect
++
,
pXr
++
)
{
pXr
->
x
=
pRect
->
left
;
pXr
->
y
=
pRect
->
top
;
pXr
->
width
=
pRect
->
right
-
pRect
->
left
;
pXr
->
height
=
pRect
->
bottom
-
pRect
->
top
;
TRACE
(
"Adding clip rect %d,%d - %d,%d
\n
"
,
pRect
->
left
,
pRect
->
top
,
pRect
->
right
,
pRect
->
bottom
);
}
}
else
{
TRACE
(
"no clip rgn
\n
"
);
pXrect
=
NULL
;
}
TSXRenderSetPictureClipRectangles
(
gdi_display
,
physDev
->
xrender
->
pict
,
0
,
0
,
pXrect
,
obj
->
rgn
->
numRects
);
if
(
pXrect
)
HeapFree
(
GetProcessHeap
(),
0
,
pXrect
);
GDI_ReleaseObj
(
dc
->
hGCClipRgn
);
if
(
dc
->
backgroundMode
!=
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
);
TSXFillRectangle
(
gdi_display
,
physDev
->
drawable
,
physDev
->
gc
,
dc
->
DCOrgX
+
x
,
dc
->
DCOrgY
+
y
-
tm
.
tmAscent
,
width
,
tm
.
tmAscent
+
tm
.
tmDescent
);
}
}
}
/* Create a 1x1 pixmap to tile over the font mask */
if
(
!
physDev
->
xrender
->
tile_xpm
)
{
XRenderPictureAttributes
pa
;
XRenderPictFormat
*
format
=
(
dc
->
bitsPerPixel
==
1
)
?
mono_format
:
screen_format
;
physDev
->
xrender
->
tile_xpm
=
TSXCreatePixmap
(
gdi_display
,
physDev
->
drawable
,
1
,
1
,
format
->
depth
);
pa
.
repeat
=
True
;
physDev
->
xrender
->
tile_pict
=
TSXRenderCreatePicture
(
gdi_display
,
physDev
->
xrender
->
tile_xpm
,
format
,
CPRepeat
,
&
pa
);
TRACE
(
"Created pixmap of depth %d
\n
"
,
format
->
depth
);
/* init lastTextColor to something different from dc->textColor */
physDev
->
xrender
->
lastTextColor
=
~
dc
->
textColor
;
}
if
(
dc
->
textColor
!=
physDev
->
xrender
->
lastTextColor
)
{
if
(
dc
->
bitsPerPixel
!=
1
)
{
/* Map 0 -- 0xff onto 0 -- 0xffff */
col
.
red
=
GetRValue
(
dc
->
textColor
);
col
.
red
|=
col
.
red
<<
8
;
col
.
green
=
GetGValue
(
dc
->
textColor
);
col
.
green
|=
col
.
green
<<
8
;
col
.
blue
=
GetBValue
(
dc
->
textColor
);
col
.
blue
|=
col
.
blue
<<
8
;
col
.
alpha
=
0x0
;
}
else
{
/* for a 1bpp bitmap we always need a 1 in the tile */
col
.
red
=
col
.
green
=
col
.
blue
=
0
;
col
.
alpha
=
0xffff
;
}
TSXRenderFillRectangle
(
gdi_display
,
PictOpSrc
,
physDev
->
xrender
->
tile_pict
,
&
col
,
0
,
0
,
1
,
1
);
physDev
->
xrender
->
lastTextColor
=
dc
->
textColor
;
}
/* FIXME the mapping of Text/BkColor onto 1 or 0 needs investigation.
*/
if
((
dc
->
bitsPerPixel
==
1
)
&&
((
dc
->
textColor
&
0xffffff
)
==
0
))
render_op
=
PictOpOutReverse
;
/* This gives us 'black' text */
for
(
idx
=
0
;
idx
<
count
;
idx
++
)
{
if
(
wstr
[
idx
]
>=
physDev
->
xrender
->
cacheEntry
->
nrealized
||
physDev
->
xrender
->
cacheEntry
->
realized
[
wstr
[
idx
]]
==
FALSE
)
{
UploadGlyph
(
dc
,
wstr
[
idx
]);
}
}
TRACE
(
"Writing %s at %d,%d
\n
"
,
debugstr_wn
(
wstr
,
count
),
dc
->
DCOrgX
+
x
,
dc
->
DCOrgY
+
y
);
if
(
!
lpDx
)
TSXRenderCompositeString16
(
gdi_display
,
render_op
,
physDev
->
xrender
->
tile_pict
,
physDev
->
xrender
->
pict
,
physDev
->
xrender
->
cacheEntry
->
font_format
,
physDev
->
xrender
->
cacheEntry
->
glyphset
,
0
,
0
,
dc
->
DCOrgX
+
x
,
dc
->
DCOrgY
+
y
,
wstr
,
count
);
else
{
INT
offset
=
0
,
xoff
=
0
,
yoff
=
0
;
for
(
idx
=
0
;
idx
<
count
;
idx
++
)
{
TSXRenderCompositeString16
(
gdi_display
,
render_op
,
physDev
->
xrender
->
tile_pict
,
physDev
->
xrender
->
pict
,
physDev
->
xrender
->
cacheEntry
->
font_format
,
physDev
->
xrender
->
cacheEntry
->
glyphset
,
0
,
0
,
dc
->
DCOrgX
+
x
+
xoff
,
dc
->
DCOrgY
+
y
+
yoff
,
wstr
+
idx
,
1
);
offset
+=
INTERNAL_XWSTODS
(
dc
,
lpDx
[
idx
]);
xoff
=
offset
*
cosEsc
;
yoff
=
offset
*
sinEsc
;
}
}
if
(
physDev
->
xrender
->
pict
)
{
TSXRenderFreePicture
(
gdi_display
,
physDev
->
xrender
->
pict
);
}
physDev
->
xrender
->
pict
=
0
;
if
(
flags
&
ETO_CLIPPED
)
RestoreVisRgn16
(
dc
->
hSelf
);
X11DRV_UnlockDIBSection
(
dc
,
TRUE
);
return
TRUE
;
}
#else
/* #ifdef HAVE_LIBXRENDER */
void
X11DRV_XRender_Init
(
void
)
{
TRACE
(
"XRender support not compiled in.
\n
"
);
return
;
}
void
X11DRV_XRender_Finalize
(
void
)
{
assert
(
0
);
return
;
}
BOOL
X11DRV_XRender_SelectFont
(
DC
*
dc
,
HFONT
hfont
)
{
assert
(
0
);
return
FALSE
;
}
void
X11DRV_XRender_DeleteDC
(
DC
*
dc
)
{
assert
(
0
);
return
;
}
BOOL
X11DRV_XRender_ExtTextOut
(
DC
*
dc
,
INT
x
,
INT
y
,
UINT
flags
,
const
RECT
*
lprect
,
LPCWSTR
wstr
,
UINT
count
,
const
INT
*
lpDx
)
{
assert
(
0
);
return
FALSE
;
}
void
X11DRV_XRender_UpdateDrawable
(
DC
*
dc
)
{
assert
(
0
);
return
;
}
#endif
graphics/x11drv/clipping.c
View file @
6f7fc504
...
...
@@ -99,6 +99,8 @@ void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int or
dc
->
DCOrgY
=
org_y
;
physDev
->
drawable
=
drawable
;
TSXSetSubwindowMode
(
gdi_display
,
physDev
->
gc
,
mode
);
if
(
physDev
->
xrender
)
X11DRV_XRender_UpdateDrawable
(
dc
);
GDI_ReleaseObj
(
hdc
);
}
}
...
...
graphics/x11drv/init.c
View file @
6f7fc504
...
...
@@ -66,6 +66,9 @@ BOOL X11DRV_GDI_Initialize( Display *display )
if
(
!
X11DRV_BITMAP_Init
())
return
FALSE
;
/* Initialize XRender */
X11DRV_XRender_Init
();
/* Initialize fonts and text caps */
log_pixels_x
=
MulDiv
(
WidthOfScreen
(
screen
),
254
,
WidthMMOfScreen
(
screen
)
*
10
);
...
...
@@ -157,6 +160,9 @@ BOOL X11DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
BOOL
X11DRV_DeleteDC
(
DC
*
dc
)
{
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
if
(
physDev
->
xrender
)
X11DRV_XRender_DeleteDC
(
dc
);
wine_tsx11_lock
();
XFreeGC
(
gdi_display
,
physDev
->
gc
);
while
(
physDev
->
used_visuals
--
>
0
)
...
...
graphics/x11drv/text.c
View file @
6f7fc504
...
...
@@ -46,11 +46,17 @@ X11DRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
BOOL
dibUpdateFlag
=
FALSE
;
BOOL
result
=
TRUE
;
if
(
dc
->
gdiFont
)
return
X11DRV_XRender_ExtTextOut
(
dc
,
x
,
y
,
flags
,
lprect
,
wstr
,
count
,
lpDx
);
if
(
!
X11DRV_SetupGCForText
(
dc
))
return
TRUE
;
pfo
=
XFONT_GetFontObject
(
physDev
->
font
);
font
=
pfo
->
fs
;
if
(
pfo
->
lf
.
lfEscapement
&&
pfo
->
lpX11Trans
)
rotated
=
TRUE
;
dfBreakChar
=
(
char
)
pfo
->
fi
->
df
.
dfBreakChar
;
...
...
graphics/x11drv/xfont.c
View file @
6f7fc504
...
...
@@ -206,6 +206,10 @@ static const SuffixCharset sufch_iso10646[] = {
{
"1"
,
DEFAULT_CHARSET
,
0
,
X11DRV_CPTABLE_UNICODE
},
{
NULL
,
DEFAULT_CHARSET
,
0
,
X11DRV_CPTABLE_UNICODE
}};
static
const
SuffixCharset
sufch_dec
[]
=
{
{
"dectech"
,
SYMBOL_CHARSET
,
CP_SYMBOL
,
X11DRV_CPTABLE_SBCS
},
{
NULL
,
0
,
0
,
X11DRV_CPTABLE_SBCS
}};
/* Each of these must be matched explicitly */
static
const
SuffixCharset
sufch_any
[]
=
{
{
"fontspecific"
,
SYMBOL_CHARSET
,
CP_SYMBOL
,
X11DRV_CPTABLE_SBCS
},
...
...
@@ -244,6 +248,7 @@ static fontEncodingTemplate __fETTable[] = {
{
"unicode"
,
sufch_unicode
,
&
__fETTable
[
19
]},
{
"iso10646"
,
sufch_iso10646
,
&
__fETTable
[
20
]},
{
"cp"
,
sufch_windows
,
&
__fETTable
[
21
]},
{
"dec"
,
sufch_dec
,
&
__fETTable
[
22
]},
/* NULL prefix matches anything so put it last */
{
NULL
,
sufch_any
,
NULL
},
};
...
...
@@ -2919,6 +2924,10 @@ int X11DRV_FONT_Init( int *log_pixels_x, int *log_pixels_y )
RAW_ASCENT
=
TSXInternAtom
(
gdi_display
,
"RAW_ASCENT"
,
TRUE
);
RAW_DESCENT
=
TSXInternAtom
(
gdi_display
,
"RAW_DESCENT"
,
TRUE
);
if
(
X11DRV_XRender_Installed
)
XTextCaps
|=
TC_VA_ABLE
;
return
XTextCaps
;
}
...
...
@@ -3166,10 +3175,16 @@ HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont )
LOGFONT16
lf
;
X11DRV_PDEVICE
*
physDev
=
(
X11DRV_PDEVICE
*
)
dc
->
physDev
;
TRACE
(
"dc=%p, hfont=%04x
\n
"
,
dc
,
hfont
);
if
(
!
GetObjectW
(
hfont
,
sizeof
(
logfont
),
&
logfont
))
return
GDI_ERROR
;
/* If we want to use a gdi font, we should check for XRender extension
and return FALSE here */
TRACE
(
"dc->gdiFont = %p
\n
"
,
dc
->
gdiFont
);
if
(
dc
->
gdiFont
&&
X11DRV_XRender_Installed
)
{
X11DRV_XRender_SelectFont
(
dc
,
hfont
);
return
FALSE
;
}
EnterCriticalSection
(
&
crtsc_fonts_X11
);
...
...
include/x11drv.h
View file @
6f7fc504
...
...
@@ -58,6 +58,8 @@ typedef struct
/* X physical font */
typedef
UINT
X_PHYSFONT
;
typedef
struct
tagXRENDERINFO
*
XRENDERINFO
;
/* X physical device */
typedef
struct
{
...
...
@@ -72,6 +74,7 @@ typedef struct
XVisualInfo
*
visuals
[
MAX_PIXELFORMATS
];
int
used_visuals
;
int
current_pf
;
XRENDERINFO
xrender
;
}
X11DRV_PDEVICE
;
...
...
@@ -196,6 +199,16 @@ extern const int X11DRV_XROPfunction[];
extern
void
_XInitImageFuncPtrs
(
XImage
*
);
extern
BOOL
X11DRV_XRender_Installed
;
extern
void
X11DRV_XRender_Init
(
void
);
extern
void
X11DRV_XRender_Finalize
(
void
);
extern
BOOL
X11DRV_XRender_SelectFont
(
struct
tagDC
*
,
HFONT
);
extern
void
X11DRV_XRender_DeleteDC
(
struct
tagDC
*
);
extern
BOOL
X11DRV_XRender_ExtTextOut
(
DC
*
dc
,
INT
x
,
INT
y
,
UINT
flags
,
const
RECT
*
lprect
,
LPCWSTR
wstr
,
UINT
count
,
const
INT
*
lpDx
);
extern
void
X11DRV_XRender_UpdateDrawable
(
DC
*
dc
);
/* exported dib functions for now */
/* Additional info for DIB section objects */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment