Commit 3433676f authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Move a bunch of common code from the drivers into gdi.

parent 86892164
......@@ -78,7 +78,7 @@ extern BOOL EMFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color,
extern INT EMFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode );
extern BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y,
UINT flags, const RECT *lprect, LPCWSTR str,
UINT count, const INT *lpDx, INT breakExtra );
UINT count, const INT *lpDx );
extern BOOL EMFDRV_FillPath( PHYSDEV dev );
extern BOOL EMFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush );
extern BOOL EMFDRV_FlattenPath( PHYSDEV dev );
......
......@@ -710,7 +710,7 @@ EMFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
*/
BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR str, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
EMREXTTEXTOUTW *pemr;
DWORD nSize;
......
......@@ -68,6 +68,25 @@ static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
return GDI_ROUND(floatHeight);
}
static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
{
POINT pt[2];
pt[0].x = pt[0].y = 0;
pt[1].x = width;
pt[1].y = 0;
LPtoDP(dc->hSelf, pt, 2);
return pt[1].x - pt[0].x;
}
static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
{
POINT pt[2];
pt[0].x = pt[0].y = 0;
pt[1].x = 0;
pt[1].y = height;
LPtoDP(dc->hSelf, pt, 2);
return pt[1].y - pt[0].y;
}
static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
......@@ -1718,39 +1737,320 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
{
BOOL ret = FALSE;
LPWSTR reordered_string = (LPWSTR)str;
LPWSTR reordered_str = (LPWSTR)str;
const WORD *glyphs = NULL;
UINT align = GetTextAlign( hdc );
POINT pt;
TEXTMETRICW tm;
LOGFONTW lf;
double cosEsc, sinEsc;
INT *deltas = NULL, char_extra;
SIZE sz;
RECT rc;
BOOL done_extents = FALSE;
INT width, xwidth, ywidth;
DWORD type;
DC * dc = DC_GetDCUpdate( hdc );
if (dc)
if (!dc) return FALSE;
if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
if(PATH_IsPathOpen(dc->path))
{
FIXME("called on an open path\n");
GDI_ReleaseObj( hdc );
return ret;
}
if(!dc->funcs->pExtTextOut)
{
GDI_ReleaseObj( hdc );
return ret;
}
type = GetObjectType(hdc);
if(type == OBJ_METADC || type == OBJ_ENHMETADC)
{
ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
GDI_ReleaseObj( hdc );
return ret;
}
if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
{
reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
BIDI_Reorder( str, count, GCP_REORDER,
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
reordered_str, count, NULL );
flags |= ETO_IGNORELANGUAGE;
}
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
lprect, debugstr_wn(str, count), count, lpDx);
if(flags & ETO_GLYPH_INDEX)
glyphs = (const WORD*)reordered_str;
else if(dc->gdiFont)
{
if (flags&(ETO_NUMERICSLOCAL|ETO_NUMERICSLATIN|ETO_PDY))
FIXME("flags ETO_NUMERICSLOCAL|ETO_NUMERICSLATIN|ETO_PDY unimplemented\n");
glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
GetGlyphIndicesW(hdc, reordered_str, count, (WORD*)glyphs, 0);
flags |= ETO_GLYPH_INDEX;
}
if(lprect)
TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
lprect->bottom);
TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
if(align & TA_UPDATECP)
{
GetCurrentPositionEx( hdc, &pt );
x = pt.x;
y = pt.y;
}
GetTextMetricsW(hdc, &tm);
GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
if(PATH_IsPathOpen(dc->path))
FIXME("called on an open path\n");
else if(dc->funcs->pExtTextOut)
if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
lf.lfEscapement = 0;
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) goto done;
if(flags & ETO_GLYPH_INDEX)
GetTextExtentPointI(hdc, glyphs, count, &sz);
else
GetTextExtentPointW(hdc, reordered_str, count, &sz);
done_extents = TRUE;
rc.left = x;
rc.top = y;
rc.right = x + sz.cx;
rc.bottom = y + sz.cy;
}
else
{
if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
rc = *lprect;
}
LPtoDP(hdc, (POINT*)&rc, 2);
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;}
}
if(flags & ETO_OPAQUE)
dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
if(count == 0)
goto done;
pt.x = x;
pt.y = y;
LPtoDP(hdc, &pt, 1);
x = pt.x;
y = pt.y;
char_extra = GetTextCharacterExtra(hdc);
width = 0;
if(char_extra || dc->breakExtra || lpDx)
{
UINT i;
SIZE tmpsz;
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
for(i = 0; i < count; i++)
{
if(lpDx)
deltas[i] = lpDx[i] + char_extra;
else
{
/* The caller did not specify that language processing was already done.
*/
reordered_string = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
if(flags & ETO_GLYPH_INDEX)
GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
else
GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
BIDI_Reorder( str, count, GCP_REORDER,
((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
reordered_string, count, NULL );
deltas[i] = tmpsz.cx;
}
if (dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
{
deltas[i] = deltas[i] + dc->breakExtra;
}
deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
width += deltas[i];
}
}
else
{
if(!done_extents)
{
if(flags & ETO_GLYPH_INDEX)
GetTextExtentPointI(hdc, glyphs, count, &sz);
else
GetTextExtentPointW(hdc, reordered_str, count, &sz);
done_extents = TRUE;
}
width = INTERNAL_XWSTODS(dc, sz.cx);
}
xwidth = width * cosEsc;
ywidth = width * sinEsc;
tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
{
case TA_LEFT:
if (align & TA_UPDATECP)
{
pt.x = x + xwidth;
pt.y = y - ywidth;
DPtoLP(hdc, &pt, 1);
MoveToEx(hdc, pt.x, pt.y, NULL);
}
break;
case TA_CENTER:
x -= xwidth / 2;
y += ywidth / 2;
break;
flags |= ETO_IGNORELANGUAGE;
case TA_RIGHT:
x -= xwidth;
y += ywidth;
if (align & TA_UPDATECP)
{
pt.x = x;
pt.y = y;
DPtoLP(hdc, &pt, 1);
MoveToEx(hdc, pt.x, pt.y, NULL);
}
break;
}
switch( align & (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(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)
{
RECT rc;
rc.left = x;
rc.right = x + width;
rc.top = y - tm.tmAscent;
rc.bottom = y + tm.tmDescent;
dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
}
ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,reordered_string,count,
lpDx,dc->breakExtra);
}
}
if(reordered_string != str)
HeapFree(GetProcessHeap(), 0, reordered_string);
ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
(flags & ETO_GLYPH_INDEX) ? glyphs: reordered_str, count, deltas);
if (lf.lfUnderline || lf.lfStrikeOut)
{
int underlinePos, strikeoutPos;
int underlineWidth, strikeoutWidth;
UINT nMetricsSize = GetOutlineTextMetricsW(hdc, 0, NULL);
OUTLINETEXTMETRICW* otm = NULL;
if(!nMetricsSize)
{
TEXTMETRICW tm;
GetTextMetricsW(hdc, &tm);
underlinePos = 0;
underlineWidth = tm.tmAscent / 20 + 1;
strikeoutPos = tm.tmAscent / 2;
strikeoutWidth = underlineWidth;
}
else
{
otm = HeapAlloc(GetProcessHeap(), 0, nMetricsSize);
if (!otm) goto done;
GetOutlineTextMetricsW(hdc, nMetricsSize, otm);
underlinePos = otm->otmsUnderscorePosition;
underlineWidth = otm->otmsUnderscoreSize;
strikeoutPos = otm->otmsStrikeoutPosition;
strikeoutWidth = otm->otmsStrikeoutSize;
}
if(lf.lfUnderline)
{
POINT pts[2], oldpt;
HPEN hpen = CreatePen(PS_SOLID, underlineWidth, dc->textColor);
hpen = SelectObject(hdc, hpen);
pts[0].x = x;
pts[0].y = y;
pts[1].x = x + xwidth;
pts[1].y = y - ywidth;
DPtoLP(hdc, pts, 2);
MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
DeleteObject(SelectObject(hdc, hpen));
}
if(lf.lfStrikeOut)
{
POINT pts[2], oldpt;
HPEN hpen = CreatePen(PS_SOLID, strikeoutWidth, dc->textColor);
hpen = SelectObject(hdc, hpen);
pts[0].x = x;
pts[0].y = y;
pts[1].x = x + xwidth;
pts[1].y = y - ywidth;
DPtoLP(hdc, pts, 2);
MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
DeleteObject(SelectObject(hdc, hpen));
}
GDI_ReleaseObj( hdc );
}
done:
HeapFree(GetProcessHeap(), 0, deltas);
if(glyphs && glyphs != reordered_str)
HeapFree(GetProcessHeap(), 0, (WORD*)glyphs);
if(reordered_str != str)
HeapFree(GetProcessHeap(), 0, reordered_str);
GDI_ReleaseObj( hdc );
return ret;
}
......
......@@ -82,7 +82,7 @@ typedef struct tagDC_FUNCS
INT (*pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID);
BOOL (*pExtFloodFill)(PHYSDEV,INT,INT,COLORREF,UINT);
INT (*pExtSelectClipRgn)(PHYSDEV,HRGN,INT);
BOOL (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*,INT);
BOOL (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
BOOL (*pFillPath)(PHYSDEV);
BOOL (*pFillRgn)(PHYSDEV,HRGN,HBRUSH);
BOOL (*pFlattenPath)(PHYSDEV);
......
......@@ -84,7 +84,7 @@ extern BOOL MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT
extern INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode );
extern BOOL MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y,
UINT flags, const RECT *lprect, LPCWSTR str,
UINT count, const INT *lpDx, INT breakExtra );
UINT count, const INT *lpDx );
extern BOOL MFDRV_FillPath( PHYSDEV dev );
extern BOOL MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush );
extern BOOL MFDRV_FlattenPath( PHYSDEV dev );
......
......@@ -74,7 +74,7 @@ static BOOL MFDRV_MetaExtTextOut( PHYSDEV dev, short x, short y, UINT16 flags,
BOOL
MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR str, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
RECT16 rect16;
LPINT16 lpdx16 = NULL;
......
......@@ -338,14 +338,12 @@ BOOL TTYDRV_DC_StretchBlt(TTYDRV_PDEVICE *physDevDst, INT xDst, INT yDst,
*/
BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lpRect, LPCWSTR str, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
#ifdef WINE_CURSES
INT row, col;
LPSTR ascii;
DWORD len;
POINT pt;
UINT text_align = GetTextAlign( physDev->hdc );
TRACE("(%p, %d, %d, 0x%08x, %p, %s, %d, %p)\n",
physDev->hdc, x, y, flags, lpRect, debugstr_wn(str, count), count, lpDx);
......@@ -353,14 +351,8 @@ BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
if(!physDev->window)
return FALSE;
pt.x = x;
pt.y = y;
/* FIXME: Is this really correct? */
if(text_align & TA_UPDATECP) GetCurrentPositionEx( physDev->hdc, &pt );
LPtoDP( physDev->hdc, &pt, 1 );
row = (physDev->org.y + pt.y) / physDev->cellHeight;
col = (physDev->org.x + pt.x) / physDev->cellWidth;
row = (physDev->org.y + y) / physDev->cellHeight;
col = (physDev->org.x + x) / physDev->cellWidth;
len = WideCharToMultiByte( CP_ACP, 0, str, count, NULL, 0, NULL, NULL );
ascii = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, str, count, ascii, len, NULL, NULL );
......@@ -368,14 +360,6 @@ BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
HeapFree( GetProcessHeap(), 0, ascii );
wrefresh(physDev->window);
if(text_align & TA_UPDATECP)
{
pt.x += count * physDev->cellWidth;
pt.y += physDev->cellHeight;
DPtoLP( physDev->hdc, &pt, 1 );
MoveToEx( physDev->hdc, pt.x, pt.y, NULL );
}
return TRUE;
#else /* defined(WINE_CURSES) */
FIXME("(%p, %d, %d, 0x%08x, %p, %s, %d, %p): stub\n",
......
......@@ -76,7 +76,7 @@ extern BOOL TTYDRV_DC_BitBlt(TTYDRV_PDEVICE *physDevDst, INT xDst, INT yDst, INT
extern BOOL TTYDRV_DC_Chord(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend);
extern BOOL TTYDRV_DC_Ellipse(TTYDRV_PDEVICE *physDev, INT left, INT top, INT right, INT bottom);
extern BOOL TTYDRV_DC_ExtFloodFill(TTYDRV_PDEVICE *physDev, INT x, INT y, COLORREF color, UINT fillType);
extern BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags, const RECT *lpRect, LPCWSTR str, UINT count, const INT *lpDx, INT breakExtra);
extern BOOL TTYDRV_DC_ExtTextOut(TTYDRV_PDEVICE *physDev, INT x, INT y, UINT flags, const RECT *lpRect, LPCWSTR str, UINT count, const INT *lpDx);
extern BOOL TTYDRV_DC_GetCharWidth(TTYDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar, LPINT buffer);
extern COLORREF TTYDRV_DC_GetPixel(TTYDRV_PDEVICE *physDev, INT x, INT y);
......
......@@ -8,7 +8,7 @@
@ cdecl Ellipse(ptr long long long long) TTYDRV_DC_Ellipse
@ cdecl ExtEscape(ptr long long ptr long ptr) TTYDRV_ExtEscape
@ cdecl ExtFloodFill(ptr long long long long) TTYDRV_DC_ExtFloodFill
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr long) TTYDRV_DC_ExtTextOut
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) TTYDRV_DC_ExtTextOut
@ cdecl GetBitmapBits(long ptr long) TTYDRV_GetBitmapBits
@ cdecl GetCharWidth(ptr long long ptr) TTYDRV_DC_GetCharWidth
@ cdecl GetDCOrgEx(ptr ptr) TTYDRV_GetDCOrgEx
......
......@@ -469,7 +469,7 @@ extern INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev );
extern INT PSDRV_EndPage( PSDRV_PDEVICE *physDev );
extern BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR str, UINT count,
const INT *lpDx, INT breakExtra );
const INT *lpDx );
extern BOOL PSDRV_GetCharWidth( PSDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar,
LPINT buffer );
extern BOOL PSDRV_GetTextExtentPoint( PSDRV_PDEVICE *physDev, LPCWSTR str, INT count,
......
......@@ -40,12 +40,11 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
*/
BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR str, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
BOOL bResult = TRUE;
BOOL bClipped = FALSE;
BOOL bOpaque = FALSE;
RECT rect;
TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x, y,
flags, debugstr_wn(str, count), count, lpDx);
......@@ -58,11 +57,9 @@ BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
/* set clipping and/or draw background */
if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL))
{
rect = *lprect;
LPtoDP( physDev->hdc, (POINT *)&rect, 2 );
PSDRV_WriteGSave(physDev);
PSDRV_WriteRectangle(physDev, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top);
PSDRV_WriteRectangle(physDev, lprect->left, lprect->top, lprect->right - lprect->left,
lprect->bottom - lprect->top);
if (flags & ETO_OPAQUE)
{
......@@ -97,14 +94,7 @@ BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, LPCWSTR str,
UINT count, BOOL bDrawBackground, const INT *lpDx)
{
SIZE sz;
TEXTMETRICW tm;
POINT pt;
INT ascent, descent;
WORD *glyphs = NULL;
UINT align = GetTextAlign( physDev->hdc );
INT char_extra;
INT *deltas = NULL;
double cosEsc, sinEsc;
LOGFONTW lf;
......@@ -120,127 +110,12 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, LPCWSTR
sinEsc = 0;
}
if(physDev->font.fontloc == Download) {
if(flags & ETO_GLYPH_INDEX)
glyphs = (LPWORD)str;
else {
glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
GetGlyphIndicesW(physDev->hdc, str, count, glyphs, 0);
}
}
pt.x = x;
pt.y = y;
if(align & TA_UPDATECP) GetCurrentPositionEx( physDev->hdc, &pt );
LPtoDP(physDev->hdc, &pt, 1);
x = pt.x;
y = pt.y;
if(physDev->font.fontloc == Download)
GetTextExtentPointI(physDev->hdc, glyphs, count, &sz);
else
GetTextExtentPoint32W(physDev->hdc, str, count, &sz);
if((char_extra = GetTextCharacterExtra(physDev->hdc)) != 0) {
UINT i;
SIZE tmpsz;
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
for(i = 0; i < count; i++) {
if(lpDx)
deltas[i] = lpDx[i] + char_extra;
else {
if(physDev->font.fontloc == Download)
GetTextExtentPointI(physDev->hdc, glyphs + i, 1, &tmpsz);
else
GetTextExtentPoint32W(physDev->hdc, str + i, 1, &tmpsz);
deltas[i] = tmpsz.cx;
}
}
} else if(lpDx)
deltas = (INT*)lpDx;
if(deltas) {
SIZE tmpsz;
UINT i;
/* Get the width of the last char and add on all the offsets */
if(physDev->font.fontloc == Download)
GetTextExtentPointI(physDev->hdc, glyphs + count - 1, 1, &tmpsz);
else
GetTextExtentPoint32W(physDev->hdc, str + count - 1, 1, &tmpsz);
for(i = 0; i < count-1; i++)
tmpsz.cx += deltas[i];
sz.cx = tmpsz.cx; /* sz.cy remains untouched */
}
sz.cx = PSDRV_XWStoDS(physDev, sz.cx);
sz.cy = PSDRV_YWStoDS(physDev, sz.cy);
GetTextMetricsW(physDev->hdc, &tm);
ascent = abs(PSDRV_YWStoDS(physDev, tm.tmAscent));
descent = abs(PSDRV_YWStoDS(physDev, tm.tmDescent));
TRACE("textAlign = %x\n", align);
switch(align & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
case TA_LEFT:
if(align & TA_UPDATECP)
{
POINT pt;
pt.x = x + sz.cx * cosEsc;
pt.y = y - sz.cx * sinEsc;
DPtoLP( physDev->hdc, &pt, 1 );
MoveToEx( physDev->hdc, pt.x, pt.y, NULL );
}
break;
case TA_CENTER:
x -= sz.cx * cosEsc / 2;
y += sz.cx * sinEsc / 2;
break;
case TA_RIGHT:
x -= sz.cx * cosEsc;
y += sz.cx * sinEsc;
if(align & TA_UPDATECP)
{
POINT pt;
pt.x = x;
pt.y = y;
DPtoLP( physDev->hdc, &pt, 1 );
MoveToEx( physDev->hdc, pt.x, pt.y, NULL );
}
break;
}
switch(align & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
case TA_TOP:
y += ascent * cosEsc;
x += ascent * sinEsc;
break;
case TA_BASELINE:
break;
case TA_BOTTOM:
y -= descent * cosEsc;
x -= descent * sinEsc;
break;
}
if ((GetBkMode( physDev->hdc ) != TRANSPARENT) && bDrawBackground)
{
PSDRV_WriteGSave(physDev);
PSDRV_WriteNewPath(physDev);
PSDRV_WriteRectangle(physDev, x, y - ascent, sz.cx,
ascent + descent);
PSDRV_WriteSetColor(physDev, &physDev->bkColor);
PSDRV_WriteFill(physDev);
PSDRV_WriteGRestore(physDev);
}
glyphs = (LPWORD)str;
PSDRV_WriteMoveTo(physDev, x, y);
if(!deltas) {
if(!lpDx) {
if(physDev->font.fontloc == Download)
PSDRV_WriteDownloadGlyphShow(physDev, glyphs, count);
else
......@@ -252,87 +127,20 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, LPCWSTR
float cos_theta = cos(physDev->font.escapement * M_PI / 1800.0);
float sin_theta = sin(physDev->font.escapement * M_PI / 1800.0);
for(i = 0; i < count-1; i++) {
TRACE("lpDx[%d] = %d\n", i, deltas[i]);
TRACE("lpDx[%d] = %d\n", i, lpDx[i]);
if(physDev->font.fontloc == Download)
PSDRV_WriteDownloadGlyphShow(physDev, glyphs + i, 1);
else
PSDRV_WriteBuiltinGlyphShow(physDev, str + i, 1);
dx += deltas[i] * cos_theta;
dy -= deltas[i] * sin_theta;
PSDRV_WriteMoveTo(physDev, x + PSDRV_XWStoDS(physDev, dx),
y + PSDRV_YWStoDS(physDev, dy));
dx += lpDx[i] * cos_theta;
dy -= lpDx[i] * sin_theta;
PSDRV_WriteMoveTo(physDev, x + dx, y + dy);
}
if(physDev->font.fontloc == Download)
PSDRV_WriteDownloadGlyphShow(physDev, glyphs + i, 1);
else
PSDRV_WriteBuiltinGlyphShow(physDev, str + i, 1);
if(deltas != lpDx)
HeapFree(GetProcessHeap(), 0, deltas);
}
/*
* Underline and strikeout attributes.
*/
if ((tm.tmUnderlined) || (tm.tmStruckOut)) {
/* Get the thickness and the position for the underline attribute */
/* We'll use the same thickness for the strikeout attribute */
INT escapement = physDev->font.escapement;
/* Do the underline */
if (tm.tmUnderlined) {
PSDRV_WriteNewPath(physDev); /* will be closed by WriteRectangle */
if (escapement != 0) /* rotated text */
{
PSDRV_WriteGSave(physDev); /* save the graphics state */
PSDRV_WriteMoveTo(physDev, x, y); /* move to the start */
/* temporarily rotate the coord system */
PSDRV_WriteRotate(physDev, -escapement/10);
/* draw the underline relative to the starting point */
PSDRV_WriteRRectangle(physDev, 0, -physDev->font.underlinePosition,
sz.cx, physDev->font.underlineThickness);
}
else
PSDRV_WriteRectangle(physDev, x, y - physDev->font.underlinePosition,
sz.cx, physDev->font.underlineThickness);
PSDRV_WriteFill(physDev);
if (escapement != 0) /* rotated text */
PSDRV_WriteGRestore(physDev); /* restore the graphics state */
}
/* Do the strikeout */
if (tm.tmStruckOut) {
PSDRV_WriteNewPath(physDev); /* will be closed by WriteRectangle */
if (escapement != 0) /* rotated text */
{
PSDRV_WriteGSave(physDev); /* save the graphics state */
PSDRV_WriteMoveTo(physDev, x, y); /* move to the start */
/* temporarily rotate the coord system */
PSDRV_WriteRotate(physDev, -escapement/10);
/* draw the line relative to the starting point */
PSDRV_WriteRRectangle(physDev, 0, -physDev->font.strikeoutPosition,
sz.cx, physDev->font.strikeoutThickness);
}
else
PSDRV_WriteRectangle(physDev, x, y - physDev->font.strikeoutPosition,
sz.cx, physDev->font.strikeoutThickness);
PSDRV_WriteFill(physDev);
if (escapement != 0) /* rotated text */
PSDRV_WriteGRestore(physDev); /* restore the graphics state */
}
}
if(glyphs && glyphs != str) HeapFree(GetProcessHeap(), 0, glyphs);
return TRUE;
}
......@@ -11,7 +11,7 @@
@ cdecl EnumDeviceFonts(ptr ptr ptr long) PSDRV_EnumDeviceFonts
@ cdecl ExtDeviceMode(ptr long ptr ptr ptr ptr ptr long) PSDRV_ExtDeviceMode
@ cdecl ExtEscape(ptr long long ptr long ptr) PSDRV_ExtEscape
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr long) PSDRV_ExtTextOut
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) PSDRV_ExtTextOut
@ cdecl GetCharWidth(ptr long long ptr) PSDRV_GetCharWidth
@ cdecl GetDeviceCaps(ptr long) PSDRV_GetDeviceCaps
@ cdecl GetTextExtentPoint(ptr ptr long ptr) PSDRV_GetTextExtentPoint
......
......@@ -42,93 +42,36 @@ WINE_DEFAULT_DEBUG_CHANNEL(text);
BOOL
X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR wstr, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
unsigned int i;
fontObject* pfo;
INT width, ascent, descent, xwidth, ywidth;
XFontStruct* font;
RECT rect;
char dfBreakChar, lfUnderline, lfStrikeOut;
BOOL rotated = FALSE;
XChar2b *str2b = NULL;
BOOL dibUpdateFlag = FALSE;
BOOL result = TRUE;
HRGN saved_region = 0;
POINT pt;
UINT align;
INT charExtra;
if(physDev->has_gdi_font)
return X11DRV_XRender_ExtTextOut(physDev, x, y, flags, lprect, wstr, count, lpDx, breakExtra);
return X11DRV_XRender_ExtTextOut(physDev, x, y, flags, lprect, wstr, count, lpDx);
if (!X11DRV_SetupGCForText( physDev )) return TRUE;
align = GetTextAlign( physDev->hdc );
charExtra = GetTextCharacterExtra( physDev->hdc );
pfo = XFONT_GetFontObject( physDev->font );
font = pfo->fs;
if (pfo->lf.lfEscapement && pfo->lpX11Trans)
rotated = TRUE;
dfBreakChar = (char)pfo->fi->df.dfBreakChar;
lfUnderline = (pfo->fo_flags & FO_SYNTH_UNDERLINE) ? 1 : 0;
lfStrikeOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT) ? 1 : 0;
TRACE("hdc=%p df=%04x %d,%d %s, %d flags=%d lpDx=%p\n",
physDev->hdc, (UINT16)(physDev->font), x, y,
debugstr_wn (wstr, count), count, flags, lpDx);
/* some strings sent here end in a newline for whatever reason. I have no
clue what the right treatment should be in general, but ignoring
terminating newlines seems ok. MW, April 1998. */
if (count > 0 && wstr[count - 1] == '\n') count--;
if (lprect != NULL) TRACE("\trect=(%ld,%ld - %ld,%ld)\n",
lprect->left, lprect->top,
lprect->right, lprect->bottom );
/* Setup coordinates */
if (align & TA_UPDATECP)
{
GetCurrentPositionEx( physDev->hdc, &pt );
x = pt.x;
y = pt.y;
}
if (flags & (ETO_OPAQUE | ETO_CLIPPED)) /* there's a rectangle */
{
if (!lprect) /* not always */
{
SIZE sz;
if (flags & ETO_CLIPPED) /* Can't clip with no rectangle */
return FALSE;
if (!X11DRV_GetTextExtentPoint( physDev, wstr, count, &sz ))
return FALSE;
rect.left = x;
rect.right = x + sz.cx;
rect.top = y;
rect.bottom = y + sz.cy;
}
else
{
rect = *lprect;
}
LPtoDP(physDev->hdc, (POINT*)&rect, 2);
if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
}
pt.x = x;
pt.y = y;
LPtoDP(physDev->hdc, &pt, 1);
x = pt.x;
y = pt.y;
TRACE("\treal coord: x=%i, y=%i, rect=(%ld,%ld - %ld,%ld)\n",
x, y, rect.left, rect.top, rect.right, rect.bottom);
/* Draw the rectangle */
......@@ -145,83 +88,14 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
}
if (!count) goto END; /* Nothing more to do */
/* Compute text starting position */
if (lpDx) /* have explicit character cell x offsets in logical coordinates */
{
for (i = width = 0; i < count; i++) width += lpDx[i];
width = X11DRV_XWStoDS(physDev, width);
}
else
{
SIZE sz;
if (!X11DRV_GetTextExtentPoint( physDev, wstr, count, &sz ))
{
result = FALSE;
goto END;
}
width = X11DRV_XWStoDS(physDev, sz.cx);
}
ascent = pfo->lpX11Trans ? pfo->lpX11Trans->ascent : font->ascent;
descent = pfo->lpX11Trans ? pfo->lpX11Trans->descent : font->descent;
xwidth = pfo->lpX11Trans ? width * pfo->lpX11Trans->a /
pfo->lpX11Trans->pixelsize : width;
ywidth = pfo->lpX11Trans ? width * pfo->lpX11Trans->b /
pfo->lpX11Trans->pixelsize : 0;
switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
{
case TA_LEFT:
if (align & TA_UPDATECP) {
pt.x = x + xwidth;
pt.y = y - ywidth;
DPtoLP(physDev->hdc, &pt, 1);
MoveToEx(physDev->hdc, pt.x, pt.y, NULL);
}
break;
case TA_RIGHT:
x -= xwidth;
y += ywidth;
if (align & TA_UPDATECP) {
pt.x = x;
pt.y = y;
DPtoLP(physDev->hdc, &pt, 1);
MoveToEx(physDev->hdc, pt.x, pt.y, NULL);
}
break;
case TA_CENTER:
x -= xwidth / 2;
y += ywidth / 2;
break;
}
switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
{
case TA_TOP:
x -= pfo->lpX11Trans ? ascent * pfo->lpX11Trans->c /
pfo->lpX11Trans->pixelsize : 0;
y += pfo->lpX11Trans ? ascent * pfo->lpX11Trans->d /
pfo->lpX11Trans->pixelsize : ascent;
break;
case TA_BOTTOM:
x += pfo->lpX11Trans ? descent * pfo->lpX11Trans->c /
pfo->lpX11Trans->pixelsize : 0;
y -= pfo->lpX11Trans ? descent * pfo->lpX11Trans->d /
pfo->lpX11Trans->pixelsize : descent;
break;
case TA_BASELINE:
break;
}
/* Set the clip region */
if (flags & ETO_CLIPPED)
{
HRGN clip_region;
RECT clip_rect = *lprect;
LPtoDP( physDev->hdc, (POINT *)&clip_rect, 2 );
clip_region = CreateRectRgnIndirect( &clip_rect );
clip_region = CreateRectRgnIndirect( lprect );
/* make a copy of the current device region */
saved_region = CreateRectRgn( 0, 0, 0, 0 );
CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
......@@ -237,28 +111,6 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
dibUpdateFlag = TRUE;
}
if (GetBkMode( physDev->hdc ) != TRANSPARENT)
{
/* If rectangle is opaque and clipped, do nothing */
if (!(flags & ETO_CLIPPED) || !(flags & ETO_OPAQUE))
{
/* Only draw if rectangle is not opaque or if some */
/* text is outside the rectangle */
if (!(flags & ETO_OPAQUE) ||
(x < rect.left) ||
(x + width >= rect.right) ||
(y - ascent < rect.top) ||
(y + descent >= rect.bottom))
{
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel );
XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y - ascent,
width, ascent + descent );
wine_tsx11_unlock();
}
}
}
/* Draw the text (count > 0 verified) */
if (!(str2b = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, wstr, count )))
......@@ -269,154 +121,67 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
wine_tsx11_unlock();
if(!rotated)
{
if (!charExtra && !breakExtra && !lpDx)
{
X11DRV_cptable[pfo->fi->cptable].pDrawString(
pfo, gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y, str2b, count );
}
else /* Now the fun begins... */
{
XTextItem16 *items, *pitem;
int delta;
/* allocate max items */
pitem = items = HeapAlloc( GetProcessHeap(), 0,
count * sizeof(XTextItem16) );
if(items == NULL) goto FAIL;
delta = i = 0;
if( lpDx ) /* explicit character widths */
{
long ve_we;
unsigned short err = 0;
ve_we = X11DRV_XWStoDS( physDev, 0x10000 );
while (i < count)
{
/* initialize text item with accumulated delta */
long sum;
long fSum;
sum = 0;
pitem->chars = str2b + i;
pitem->delta = delta;
pitem->nchars = 0;
pitem->font = None;
delta = 0;
/* add characters to the same XTextItem
* until new delta becomes non-zero */
do
{
sum += lpDx[i];
fSum = sum*ve_we+err;
delta = (short)HIWORD(fSum)
- X11DRV_cptable[pfo->fi->cptable].pTextWidth(
pfo, pitem->chars, pitem->nchars+1);
pitem->nchars++;
} while ((++i < count) && !delta);
pitem++;
err = LOWORD(fSum);
}
}
else /* charExtra or breakExtra */
{
while (i < count)
if (!lpDx)
{
X11DRV_cptable[pfo->fi->cptable].pDrawString(
pfo, gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y, str2b, count );
}
else
{
XTextItem16 *items, *pitem;
pitem = items = HeapAlloc( GetProcessHeap(), 0,
count * sizeof(XTextItem16) );
if(items == NULL) goto FAIL;
for(i = 0; i < count; i++)
{
pitem->chars = str2b + i;
pitem->delta = delta;
pitem->nchars = 0;
pitem->font = None;
delta = 0;
do
{
delta += charExtra;
if (str2b[i].byte2 == (char)dfBreakChar)
delta += breakExtra;
pitem->nchars++;
} while ((++i < count) && !delta);
pitem++;
pitem->chars = str2b + i;
pitem->delta = lpDx[i];
pitem->nchars = 1;
pitem->font = None;
pitem++;
}
}
X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display,
physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y, items, pitem - items );
HeapFree( GetProcessHeap(), 0, items );
}
X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display,
physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y, items, pitem - items );
HeapFree( GetProcessHeap(), 0, items );
}
}
else /* rotated */
{
/* have to render character by character. */
double offset = 0.0;
int i;
for (i=0; i<count; i++)
{
int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8)
- font->min_char_or_byte2;
int x_i = IROUND((double) (physDev->org.x + x) + offset *
pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize );
int y_i = IROUND((double) (physDev->org.y + y) - offset *
pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize );
X11DRV_cptable[pfo->fi->cptable].pDrawString(
pfo, gdi_display, physDev->drawable, physDev->gc,
x_i, y_i, &str2b[i], 1);
if (lpDx)
{
offset += X11DRV_XWStoDS(physDev, lpDx[i]);
}
else
{
offset += (double) (font->per_char ?
font->per_char[char_metric_offset].attributes:
font->min_bounds.attributes)
* pfo->lpX11Trans->pixelsize / 1000.0;
offset += charExtra;
if (str2b[i].byte2 == (char)dfBreakChar)
offset += breakExtra;
}
}
}
HeapFree( GetProcessHeap(), 0, str2b );
/* Draw underline and strike-out if needed */
/* have to render character by character. */
double offset = 0.0;
int i;
wine_tsx11_lock();
if (lfUnderline)
{
long linePos, lineWidth;
if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
linePos = descent - 1;
if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
lineWidth = 0;
else if (lineWidth == 1) lineWidth = 0;
XSetLineAttributes( gdi_display, physDev->gc, lineWidth,
LineSolid, CapRound, JoinBevel );
XDrawLine( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y + linePos,
physDev->org.x + x + width, physDev->org.y + y + linePos );
}
if (lfStrikeOut)
{
long lineAscent, lineDescent;
if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
lineAscent = ascent / 2;
if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
lineDescent = -lineAscent * 2 / 3;
XSetLineAttributes( gdi_display, physDev->gc, lineAscent + lineDescent,
LineSolid, CapRound, JoinBevel );
XDrawLine( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y - lineAscent,
physDev->org.x + x + width, physDev->org.y + y - lineAscent );
for (i=0; i<count; i++)
{
int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8)
- font->min_char_or_byte2;
int x_i = IROUND((double) (physDev->org.x + x) + offset *
pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize );
int y_i = IROUND((double) (physDev->org.y + y) - offset *
pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize );
X11DRV_cptable[pfo->fi->cptable].pDrawString(
pfo, gdi_display, physDev->drawable, physDev->gc,
x_i, y_i, &str2b[i], 1);
if (lpDx)
{
offset += lpDx[i];
}
else
{
offset += (double) (font->per_char ?
font->per_char[char_metric_offset].attributes:
font->min_bounds.attributes)
* pfo->lpX11Trans->pixelsize / 1000.0;
}
}
}
wine_tsx11_unlock();
HeapFree( GetProcessHeap(), 0, str2b );
if (flags & ETO_CLIPPED)
{
......
......@@ -15,7 +15,7 @@
@ cdecl EnumDeviceFonts(ptr ptr ptr long) X11DRV_EnumDeviceFonts
@ cdecl ExtEscape(ptr long long ptr long ptr) X11DRV_ExtEscape
@ cdecl ExtFloodFill(ptr long long long long) X11DRV_ExtFloodFill
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr long) X11DRV_ExtTextOut
@ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) X11DRV_ExtTextOut
@ cdecl GetBitmapBits(long ptr long) X11DRV_GetBitmapBits
@ cdecl GetCharWidth(ptr long long ptr) X11DRV_GetCharWidth
@ cdecl GetDCOrgEx(ptr ptr) X11DRV_GetDCOrgEx
......
......@@ -211,7 +211,7 @@ extern BOOL X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y,
COLORREF color, UINT fillType );
extern BOOL X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y,
UINT flags, const RECT *lprect,
LPCWSTR str, UINT count, const INT *lpDx, INT breakExtra );
LPCWSTR str, UINT count, const INT *lpDx );
extern LONG X11DRV_SetBitmapBits( HBITMAP hbitmap, const void *bits, LONG count );
extern void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN vis_rgn, HRGN clip_rgn );
extern INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest,
......@@ -271,7 +271,7 @@ extern BOOL X11DRV_XRender_SelectFont(X11DRV_PDEVICE*, HFONT);
extern void X11DRV_XRender_DeleteDC(X11DRV_PDEVICE*);
extern BOOL X11DRV_XRender_ExtTextOut(X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR wstr,
UINT count, const INT *lpDx, INT breakExtra);
UINT count, const INT *lpDx);
extern void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev);
extern XVisualInfo *X11DRV_setup_opengl_visual(Display *display);
......
......@@ -1004,33 +1004,24 @@ static int XRenderErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
*/
BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
const RECT *lprect, LPCWSTR wstr, UINT count,
const INT *lpDx, INT breakExtra )
const INT *lpDx )
{
XRenderColor col;
unsigned int idx;
TEXTMETRICW tm;
RGNDATA *data;
SIZE sz;
RECT rc;
BOOL done_extents = FALSE;
INT width, xwidth, ywidth;
double cosEsc, sinEsc;
XGCValues xgcval;
LOGFONTW lf;
int render_op = PictOpOver;
const WORD *glyphs;
POINT pt;
gsCacheEntry *entry;
gsCacheEntryFormat *formatEntry;
BOOL retv = FALSE;
HDC hdc = physDev->hdc;
int textPixel, backgroundPixel;
INT *deltas = NULL, char_extra;
HRGN saved_region = 0;
UINT align = GetTextAlign( hdc );
BOOL disable_antialias = FALSE;
AA_Type antialias = AA_None;
DIBSECTION bmp;
unsigned int idx;
double cosEsc, sinEsc;
LOGFONTW lf;
/* Do we need to disable antialiasing because of palette mode? */
if( !physDev->bitmap || GetObjectW( physDev->bitmap->hbitmap, sizeof(bmp), &bmp ) != sizeof(bmp) ) {
......@@ -1041,61 +1032,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
disable_antialias = TRUE;
}
TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
lprect, debugstr_wn(wstr, count), count, lpDx);
if(flags & ETO_GLYPH_INDEX)
glyphs = (const WORD*)wstr;
else {
glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
GetGlyphIndicesW(hdc, wstr, count, (WORD*)glyphs, 0);
}
if(lprect)
TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
lprect->bottom);
TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
if(align & TA_UPDATECP)
{
GetCurrentPositionEx( hdc, &pt );
x = pt.x;
y = pt.y;
}
GetTextMetricsW(hdc, &tm);
GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
lf.lfEscapement = 0;
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) goto done;
GetTextExtentPointI(hdc, glyphs, count, &sz);
done_extents = TRUE;
rc.left = x;
rc.top = y;
rc.right = x + sz.cx;
rc.bottom = y + sz.cy;
} else {
rc = *lprect;
}
LPtoDP(hdc, (POINT*)&rc, 2);
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;
......@@ -1118,114 +1054,37 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
backgroundPixel = physDev->backgroundPixel;
}
if(flags & ETO_OPAQUE) {
if(flags & ETO_OPAQUE)
{
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, backgroundPixel );
XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + rc.left, physDev->org.y + rc.top,
rc.right - rc.left, rc.bottom - rc.top );
physDev->org.x + lprect->left, physDev->org.y + lprect->top,
lprect->right - lprect->left, lprect->bottom - lprect->top );
wine_tsx11_unlock();
}
if(count == 0) {
retv = TRUE;
if(count == 0)
{
retv = TRUE;
goto done_unlock;
}
pt.x = x;
pt.y = y;
LPtoDP(hdc, &pt, 1);
x = pt.x;
y = pt.y;
TRACE("real x,y %d,%d\n", x, y);
char_extra = GetTextCharacterExtra(hdc);
if(char_extra || breakExtra) {
UINT i;
SIZE tmpsz;
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
for(i = 0; i < count; i++) {
if(lpDx)
deltas[i] = lpDx[i] + char_extra;
else {
GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
deltas[i] = tmpsz.cx;
}
if (breakExtra && wstr[i] == tm.tmBreakChar) {
deltas[i] = deltas[i] + breakExtra;
}
}
} else if(lpDx)
deltas = (INT*)lpDx;
if(deltas) {
width = 0;
for(idx = 0; idx < count; idx++)
width += deltas[idx];
GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf);
if(lf.lfEscapement != 0) {
cosEsc = cos(lf.lfEscapement * M_PI / 1800);
sinEsc = sin(lf.lfEscapement * M_PI / 1800);
} else {
if(!done_extents) {
GetTextExtentPointI(hdc, glyphs, count, &sz);
done_extents = TRUE;
}
width = sz.cx;
}
width = X11DRV_XWStoDS(physDev, width);
xwidth = width * cosEsc;
ywidth = width * sinEsc;
tm.tmAscent = abs(X11DRV_YWStoDS(physDev, tm.tmAscent));
tm.tmDescent = abs(X11DRV_YWStoDS(physDev, tm.tmDescent));
switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) ) {
case TA_LEFT:
if (align & TA_UPDATECP) {
pt.x = x + xwidth;
pt.y = y - ywidth;
DPtoLP(hdc, &pt, 1);
MoveToEx(hdc, pt.x, pt.y, NULL);
}
break;
case TA_CENTER:
x -= xwidth / 2;
y += ywidth / 2;
break;
case TA_RIGHT:
x -= xwidth;
y += ywidth;
if (align & TA_UPDATECP) {
pt.x = x;
pt.y = y;
DPtoLP(hdc, &pt, 1);
MoveToEx(hdc, pt.x, pt.y, NULL);
}
break;
}
switch( align & (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;
cosEsc = 1;
sinEsc = 0;
}
if (flags & ETO_CLIPPED)
{
HRGN clip_region;
RECT clip_rect = *lprect;
LPtoDP( hdc, (POINT *)&clip_rect, 2 );
clip_region = CreateRectRgnIndirect( &clip_rect );
clip_region = CreateRectRgnIndirect( lprect );
/* make a copy of the current device region */
saved_region = CreateRectRgn( 0, 0, 0, 0 );
CombineRgn( saved_region, physDev->region, 0, RGN_COPY );
......@@ -1264,20 +1123,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
}
}
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) {
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, backgroundPixel );
XFillRectangle( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x, physDev->org.y + y - tm.tmAscent,
width, tm.tmAscent + tm.tmDescent );
wine_tsx11_unlock();
}
}
}
if(X11DRV_XRender_Installed) {
/* Create a 1x1 pixmap to tile over the font mask */
if(!physDev->xrender->tile_xpm) {
......@@ -1345,10 +1190,10 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
for(idx = 0; idx < count; idx++) {
if( !formatEntry ) {
UploadGlyph(physDev, glyphs[idx], antialias);
UploadGlyph(physDev, wstr[idx], antialias);
formatEntry = entry->format[antialias];
} else if( glyphs[idx] >= formatEntry->nrealized || formatEntry->realized[glyphs[idx]] == FALSE) {
UploadGlyph(physDev, glyphs[idx], antialias);
} else if( wstr[idx] >= formatEntry->nrealized || formatEntry->realized[wstr[idx]] == FALSE) {
UploadGlyph(physDev, wstr[idx], antialias);
}
}
assert(formatEntry);
......@@ -1358,14 +1203,13 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if(X11DRV_XRender_Installed) {
wine_tsx11_lock();
if(!deltas)
if(!lpDx)
pXRenderCompositeString16(gdi_display, render_op,
physDev->xrender->tile_pict,
physDev->xrender->pict,
formatEntry->font_format, formatEntry->glyphset,
0, 0, physDev->org.x + x, physDev->org.y + y,
glyphs, count);
wstr, count);
else {
INT offset = 0, xoff = 0, yoff = 0;
for(idx = 0; idx < count; idx++) {
......@@ -1375,8 +1219,8 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
formatEntry->font_format, formatEntry->glyphset,
0, 0, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
glyphs + idx, 1);
offset += X11DRV_XWStoDS(physDev, deltas[idx]);
wstr + idx, 1);
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
}
......@@ -1392,32 +1236,30 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
for(idx = 0; idx < count; idx++) {
SharpGlyphMono(physDev, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
formatEntry->bitmaps[glyphs[idx]],
&formatEntry->gis[glyphs[idx]]);
if(deltas) {
offset += X11DRV_XWStoDS(physDev, deltas[idx]);
formatEntry->bitmaps[wstr[idx]],
&formatEntry->gis[wstr[idx]]);
if(lpDx) {
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += formatEntry->gis[glyphs[idx]].xOff;
yoff += formatEntry->gis[glyphs[idx]].yOff;
xoff += formatEntry->gis[wstr[idx]].xOff;
yoff += formatEntry->gis[wstr[idx]].yOff;
}
}
} else if(physDev->depth == 1) {
for(idx = 0; idx < count; idx++) {
SharpGlyphGray(physDev, physDev->org.x + x + xoff,
physDev->org.y + y + yoff,
formatEntry->bitmaps[glyphs[idx]],
&formatEntry->gis[glyphs[idx]]);
if(deltas) {
offset += X11DRV_XWStoDS(physDev, deltas[idx]);
formatEntry->bitmaps[wstr[idx]],
&formatEntry->gis[wstr[idx]]);
if(lpDx) {
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += formatEntry->gis[glyphs[idx]].xOff;
yoff += formatEntry->gis[glyphs[idx]].yOff;
xoff += formatEntry->gis[wstr[idx]].xOff;
yoff += formatEntry->gis[wstr[idx]].yOff;
}
}
......@@ -1436,21 +1278,21 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
TRACE("drawable %dx%d\n", w, h);
for(idx = 0; idx < count; idx++) {
if(extents.left > cur.x - formatEntry->gis[glyphs[idx]].x)
extents.left = cur.x - formatEntry->gis[glyphs[idx]].x;
if(extents.top > cur.y - formatEntry->gis[glyphs[idx]].y)
extents.top = cur.y - formatEntry->gis[glyphs[idx]].y;
if(extents.right < cur.x - formatEntry->gis[glyphs[idx]].x + formatEntry->gis[glyphs[idx]].width)
extents.right = cur.x - formatEntry->gis[glyphs[idx]].x + formatEntry->gis[glyphs[idx]].width;
if(extents.bottom < cur.y - formatEntry->gis[glyphs[idx]].y + formatEntry->gis[glyphs[idx]].height)
extents.bottom = cur.y - formatEntry->gis[glyphs[idx]].y + formatEntry->gis[glyphs[idx]].height;
if(deltas) {
offset += X11DRV_XWStoDS(physDev, deltas[idx]);
if(extents.left > cur.x - formatEntry->gis[wstr[idx]].x)
extents.left = cur.x - formatEntry->gis[wstr[idx]].x;
if(extents.top > cur.y - formatEntry->gis[wstr[idx]].y)
extents.top = cur.y - formatEntry->gis[wstr[idx]].y;
if(extents.right < cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width)
extents.right = cur.x - formatEntry->gis[wstr[idx]].x + formatEntry->gis[wstr[idx]].width;
if(extents.bottom < cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height)
extents.bottom = cur.y - formatEntry->gis[wstr[idx]].y + formatEntry->gis[wstr[idx]].height;
if(lpDx) {
offset += lpDx[idx];
cur.x = offset * cosEsc;
cur.y = offset * -sinEsc;
} else {
cur.x += formatEntry->gis[glyphs[idx]].xOff;
cur.y += formatEntry->gis[glyphs[idx]].yOff;
cur.x += formatEntry->gis[wstr[idx]].xOff;
cur.y += formatEntry->gis[wstr[idx]].yOff;
}
}
TRACE("glyph extents %ld,%ld - %ld,%ld drawable x,y %ld,%ld\n", extents.left, extents.top,
......@@ -1518,18 +1360,17 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
for(idx = 0; idx < count; idx++) {
SmoothGlyphGray(image, xoff + image_off_x - extents.left,
yoff + image_off_y - extents.top,
formatEntry->bitmaps[glyphs[idx]],
&formatEntry->gis[glyphs[idx]],
formatEntry->bitmaps[wstr[idx]],
&formatEntry->gis[wstr[idx]],
physDev->textPixel);
if(deltas) {
offset += X11DRV_XWStoDS(physDev, deltas[idx]);
if(lpDx) {
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += formatEntry->gis[glyphs[idx]].xOff;
yoff += formatEntry->gis[glyphs[idx]].yOff;
xoff += formatEntry->gis[wstr[idx]].xOff;
yoff += formatEntry->gis[wstr[idx]].yOff;
}
}
XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
image_x, image_y, image_w, image_h);
......@@ -1540,63 +1381,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
}
LeaveCriticalSection(&xrender_cs);
if (lf.lfUnderline || lf.lfStrikeOut) {
int underlinePos, strikeoutPos;
int underlineWidth, strikeoutWidth;
UINT nMetricsSize = GetOutlineTextMetricsW(hdc, 0, NULL);
OUTLINETEXTMETRICW* otm = NULL;
if(!nMetricsSize) {
underlinePos = 0;
underlineWidth = tm.tmAscent / 20 + 1;
strikeoutPos = tm.tmAscent / 2;
strikeoutWidth = underlineWidth;
} else {
otm = HeapAlloc(GetProcessHeap(), 0, nMetricsSize);
if (!otm) goto done_unlock;
GetOutlineTextMetricsW(hdc, nMetricsSize, otm);
underlinePos = otm->otmsUnderscorePosition;
underlineWidth = otm->otmsUnderscoreSize;
strikeoutPos = otm->otmsStrikeoutPosition;
strikeoutWidth = otm->otmsStrikeoutSize;
}
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, physDev->textPixel );
if (lf.lfUnderline) {
underlinePos = X11DRV_YWStoDS(physDev, underlinePos);
underlineWidth = X11DRV_YWStoDS(physDev, underlineWidth);
XSetLineAttributes( gdi_display, physDev->gc, underlineWidth,
LineSolid, CapProjecting, JoinBevel );
XDrawLine( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x - underlinePos * sinEsc,
physDev->org.y + y - underlinePos * cosEsc,
physDev->org.x + x + width * cosEsc - underlinePos * sinEsc,
physDev->org.y + y - width * sinEsc - underlinePos * cosEsc );
}
if (lf.lfStrikeOut) {
strikeoutPos = X11DRV_YWStoDS(physDev, strikeoutPos);
strikeoutWidth = X11DRV_YWStoDS(physDev, strikeoutWidth);
XSetLineAttributes( gdi_display, physDev->gc, strikeoutWidth,
LineSolid, CapProjecting, JoinBevel );
XDrawLine( gdi_display, physDev->drawable, physDev->gc,
physDev->org.x + x - strikeoutPos * sinEsc,
physDev->org.y + y - strikeoutPos * cosEsc,
physDev->org.x + x + width * cosEsc - strikeoutPos * sinEsc,
physDev->org.y + y - width * sinEsc - strikeoutPos * cosEsc);
}
wine_tsx11_unlock();
HeapFree(GetProcessHeap(), 0, otm);
}
if(deltas && deltas != lpDx)
HeapFree(GetProcessHeap(), 0, deltas);
if (flags & ETO_CLIPPED)
{
/* restore the device region */
......@@ -1608,8 +1392,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
done_unlock:
X11DRV_UnlockDIBSection( physDev, TRUE );
done:
if(glyphs != wstr) HeapFree(GetProcessHeap(), 0, (WORD*)glyphs);
return retv;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment