gdi32: Add support for ETO_PDY and improve world transform support.

This commit is contained in:
Huw Davies 2010-05-06 14:05:39 +01:00 committed by Alexandre Julliard
parent 4733bd8162
commit d92ed5bd07
4 changed files with 166 additions and 123 deletions

View file

@ -1663,11 +1663,11 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
TEXTMETRICW tm;
LOGFONTW lf;
double cosEsc, sinEsc;
INT *deltas = NULL, char_extra;
INT char_extra;
SIZE sz;
RECT rc;
BOOL done_extents = FALSE;
INT width = 0, xwidth = 0, ywidth = 0;
POINT *deltas = NULL, width = {0, 0};
DWORD type;
DC * dc = get_dc_ptr( hdc );
INT breakRem;
@ -1677,9 +1677,9 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
breakRem = dc->breakRem;
if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
{
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
quietfixme = 1;
}
if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
@ -1793,13 +1793,25 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
{
UINT i;
SIZE tmpsz;
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
POINT total = {0, 0}, desired[2];
deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
for(i = 0; i < count; i++)
{
if(lpDx && (flags & ETO_PDY))
deltas[i] = lpDx[i*2] + char_extra;
else if(lpDx)
deltas[i] = lpDx[i] + char_extra;
if(lpDx)
{
if(flags & ETO_PDY)
{
deltas[i].x = lpDx[i * 2] + char_extra;
deltas[i].y = -lpDx[i * 2 + 1];
}
else
{
deltas[i].x = lpDx[i] + char_extra;
deltas[i].y = 0;
}
}
else
{
if(flags & ETO_GLYPH_INDEX)
@ -1807,21 +1819,37 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
else
GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
deltas[i] = tmpsz.cx;
deltas[i].x = tmpsz.cx;
deltas[i].y = 0;
}
if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
{
deltas[i] = deltas[i] + dc->breakExtra;
deltas[i].x = deltas[i].x + dc->breakExtra;
if (breakRem > 0)
{
breakRem--;
deltas[i]++;
deltas[i].x++;
}
}
deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
width += deltas[i];
total.x += deltas[i].x;
total.y += deltas[i].y;
desired[0].x = desired[0].y = 0;
desired[1].x = cosEsc * total.x + sinEsc * total.y;
desired[1].y = -sinEsc * total.x + cosEsc * total.y;
LPtoDP(hdc, desired, 2);
desired[1].x -= desired[0].x;
desired[1].y -= desired[0].y;
deltas[i].x = desired[1].x - width.x;
deltas[i].y = desired[1].y - width.y;
width = desired[1];
}
flags |= ETO_PDY;
}
else
{
@ -1833,10 +1861,9 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
GetTextExtentPointW(hdc, reordered_str, count, &sz);
done_extents = TRUE;
}
width = INTERNAL_XWSTODS(dc, sz.cx);
width.x = INTERNAL_XWSTODS(dc, sz.cx);
width.y = 0;
}
xwidth = width * cosEsc;
ywidth = width * sinEsc;
tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
@ -1845,21 +1872,21 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
case TA_LEFT:
if (align & TA_UPDATECP)
{
pt.x = x + xwidth;
pt.y = y - ywidth;
pt.x = x + width.x;
pt.y = y - width.y;
DPtoLP(hdc, &pt, 1);
MoveToEx(hdc, pt.x, pt.y, NULL);
}
break;
case TA_CENTER:
x -= xwidth / 2;
y += ywidth / 2;
x -= width.x / 2;
y += width.y / 2;
break;
case TA_RIGHT:
x -= xwidth;
y += ywidth;
x -= width.x;
y += width.y;
if (align & TA_UPDATECP)
{
pt.x = x;
@ -1890,12 +1917,12 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
{
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.x >= rc.right ||
y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
{
RECT rc;
rc.left = x;
rc.right = x + width;
rc.right = x + width.x;
rc.top = y - tm.tmAscent;
rc.bottom = y + tm.tmDescent;
dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
@ -1907,7 +1934,8 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
{
HFONT orig_font = dc->hFont, cur_font;
UINT glyph;
INT span = 0, *offsets = NULL;
INT span = 0;
POINT *offsets = NULL;
unsigned int i;
glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
@ -1920,32 +1948,37 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
{
unsigned int j;
offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
offsets[0] = 0;
offsets[0].x = offsets[0].y = 0;
if(!deltas)
{
SIZE tmpsz;
for(j = 1; j < count; j++)
{
GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
offsets[j].x = offsets[j - 1].x + INTERNAL_XWSTODS(dc, tmpsz.cx);
offsets[j].y = 0;
}
}
else
{
for(j = 1; j < count; j++)
offsets[j] = offsets[j-1] + deltas[j];
{
offsets[j].x = offsets[j - 1].x + deltas[j].x;
offsets[j].y = offsets[j - 1].y + deltas[j].y;
}
}
}
if(span)
{
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
ret = PATH_ExtTextOut(dc, x + offsets[i - span].x, y + offsets[i - span].y,
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + i - span : NULL);
glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
else
dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + i - span : NULL);
dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span].x, y + offsets[i - span].y,
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? (INT*)(deltas + (i - span)) : NULL);
span = 0;
}
SelectObject(hdc, cur_font);
@ -1955,15 +1988,15 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
if(i == count - 1)
{
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
y - (offsets ? offsets[count - span] * sinEsc : 0),
ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span].x : 0),
y + (offsets ? offsets[count - span].y : 0),
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + count - span : NULL);
glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
else
ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
y - (offsets ? offsets[count - span] * sinEsc : 0),
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + count - span : NULL);
ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span].x : 0),
y + (offsets ? offsets[count - span].y : 0),
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? (INT*)(deltas + (count - span)) : NULL);
SelectObject(hdc, orig_font);
HeapFree(GetProcessHeap(), 0, offsets);
}
@ -1980,10 +2013,10 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
glyphs ? glyphs : reordered_str, count, deltas);
glyphs ? glyphs : reordered_str, count, (INT*)deltas);
else
ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
glyphs ? glyphs : reordered_str, count, deltas);
glyphs ? glyphs : reordered_str, count, (INT*)deltas);
}
done:
@ -2033,8 +2066,8 @@ done:
{
pts[0].x = x - underlinePos * sinEsc;
pts[0].y = y - underlinePos * cosEsc;
pts[1].x = x + xwidth - underlinePos * sinEsc;
pts[1].y = y - ywidth - underlinePos * cosEsc;
pts[1].x = x + width.x - underlinePos * sinEsc;
pts[1].y = y - width.y - underlinePos * cosEsc;
pts[2].x = pts[1].x + underlineWidth * sinEsc;
pts[2].y = pts[1].y + underlineWidth * cosEsc;
pts[3].x = pts[0].x + underlineWidth * sinEsc;
@ -2049,8 +2082,8 @@ done:
{
pts[0].x = x - strikeoutPos * sinEsc;
pts[0].y = y - strikeoutPos * cosEsc;
pts[1].x = x + xwidth - strikeoutPos * sinEsc;
pts[1].y = y - ywidth - strikeoutPos * cosEsc;
pts[1].x = x + width.x - strikeoutPos * sinEsc;
pts[1].y = y - width.y - strikeoutPos * cosEsc;
pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
@ -2076,8 +2109,8 @@ done:
hpen = SelectObject(hdc, hpen);
pts[0].x = x;
pts[0].y = y;
pts[1].x = x + xwidth;
pts[1].y = y - ywidth;
pts[1].x = x + width.x;
pts[1].y = y - width.y;
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);
@ -2091,8 +2124,8 @@ done:
hpen = SelectObject(hdc, hpen);
pts[0].x = x;
pts[0].y = y;
pts[1].x = x + xwidth;
pts[1].y = y - ywidth;
pts[1].x = x + width.x;
pts[1].y = y - width.y;
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);

View file

@ -1423,28 +1423,14 @@ BOOL PATH_ExtTextOut(DC *dc, INT x, INT y, UINT flags, const RECT *lprc,
LPCWSTR str, UINT count, const INT *dx)
{
unsigned int idx;
double cosEsc, sinEsc;
LOGFONTW lf;
HDC hdc = dc->hSelf;
INT offset = 0, xoff = 0, yoff = 0;
POINT offset = {0, 0};
TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
wine_dbgstr_rect(lprc), debugstr_wn(str, count), count, dx);
if (!count) return TRUE;
GetObjectW(GetCurrentObject(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
{
cosEsc = 1;
sinEsc = 0;
}
for (idx = 0; idx < count; idx++)
{
static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
@ -1463,21 +1449,25 @@ BOOL PATH_ExtTextOut(DC *dc, INT x, INT y, UINT flags, const RECT *lprc,
GetGlyphOutlineW(hdc, str[idx], GGO_GLYPH_INDEX | GGO_NATIVE, &gm, dwSize, outline, &identity);
PATH_add_outline(dc, x + xoff, y + yoff, outline, dwSize);
PATH_add_outline(dc, x + offset.x, y + offset.y, outline, dwSize);
HeapFree(GetProcessHeap(), 0, outline);
}
if (dx)
{
offset += dx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
if(flags & ETO_PDY)
{
offset.x += dx[idx * 2];
offset.y += dx[idx * 2 + 1];
}
else
offset.x += dx[idx];
}
else
{
xoff += gm.gmCellIncX;
yoff += gm.gmCellIncY;
offset.x += gm.gmCellIncX;
offset.y += gm.gmCellIncY;
}
}
return TRUE;

View file

@ -112,18 +112,21 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, LPCWSTR
}
else {
UINT i;
float dx = 0.0, dy = 0.0;
float cos_theta = cos(physDev->font.escapement * M_PI / 1800.0);
float sin_theta = sin(physDev->font.escapement * M_PI / 1800.0);
POINT offset = {0, 0};
for(i = 0; i < count-1; 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 += lpDx[i] * cos_theta;
dy -= lpDx[i] * sin_theta;
PSDRV_WriteMoveTo(physDev, x + dx, y + dy);
if(flags & ETO_PDY)
{
offset.x += lpDx[i * 2];
offset.y += lpDx[i * 2 + 1];
}
else
offset.x += lpDx[i];
PSDRV_WriteMoveTo(physDev, x + offset.x, y + offset.y);
}
if(physDev->font.fontloc == Download)
PSDRV_WriteDownloadGlyphShow(physDev, glyphs + i, 1);

View file

@ -1626,8 +1626,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
AA_Type aa_type = AA_None;
DIBSECTION bmp;
unsigned int idx;
double cosEsc, sinEsc;
LOGFONTW lf;
const WineXRenderFormat *dst_format = get_xrender_format_from_color_shifts(physDev->depth, physDev->color_shifts);
Picture tile_pict = 0;
@ -1678,16 +1676,6 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
goto done_unlock;
}
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 {
cosEsc = 1;
sinEsc = 0;
}
if (flags & ETO_CLIPPED)
{
HRGN clip_region;
@ -1731,7 +1719,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if(X11DRV_XRender_Installed)
{
XGlyphElt16 *elts = HeapAlloc(GetProcessHeap(), 0, sizeof(XGlyphElt16) * count);
INT offset = 0;
POINT offset = {0, 0};
POINT desired, current;
int render_op = PictOpOver;
Picture pict = get_xrender_picture(physDev);
@ -1769,9 +1757,15 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
}
else
{
offset += lpDx[idx];
desired.x = physDev->dc_rect.left + x + offset * cosEsc;
desired.y = physDev->dc_rect.top + y - offset * sinEsc;
if(flags & ETO_PDY)
{
offset.x += lpDx[idx * 2];
offset.y += lpDx[idx * 2 + 1];
}
else
offset.x += lpDx[idx];
desired.x = physDev->dc_rect.left + x + offset.x;
desired.y = physDev->dc_rect.top + y + offset.y;
}
}
wine_tsx11_lock();
@ -1785,7 +1779,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
wine_tsx11_unlock();
HeapFree(GetProcessHeap(), 0, elts);
} else {
INT offset = 0, xoff = 0, yoff = 0;
POINT offset = {0, 0};
wine_tsx11_lock();
XSetForeground( gdi_display, physDev->gc, textPixel );
@ -1799,17 +1793,25 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
sharp_glyph_fn = SharpGlyphGray;
for(idx = 0; idx < count; idx++) {
sharp_glyph_fn(physDev, physDev->dc_rect.left + x + xoff,
physDev->dc_rect.top + y + yoff,
sharp_glyph_fn(physDev,
physDev->dc_rect.left + x + offset.x,
physDev->dc_rect.top + y + offset.y,
formatEntry->bitmaps[wstr[idx]],
&formatEntry->gis[wstr[idx]]);
if(lpDx) {
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += formatEntry->gis[wstr[idx]].xOff;
yoff += formatEntry->gis[wstr[idx]].yOff;
if(lpDx)
{
if(flags & ETO_PDY)
{
offset.x += lpDx[idx * 2];
offset.y += lpDx[idx * 2 + 1];
}
else
offset.x += lpDx[idx];
}
else
{
offset.x += formatEntry->gis[wstr[idx]].xOff;
offset.y += formatEntry->gis[wstr[idx]].yOff;
}
}
} else {
@ -1831,13 +1833,21 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
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[wstr[idx]].xOff;
cur.y += formatEntry->gis[wstr[idx]].yOff;
if(lpDx)
{
if(flags & ETO_PDY)
{
cur.x += lpDx[idx * 2];
cur.y += lpDx[idx * 2 + 1];
}
else
cur.x += lpDx[idx];
}
else
{
cur.x += formatEntry->gis[wstr[idx]].xOff;
cur.y += formatEntry->gis[wstr[idx]].yOff;
}
}
TRACE("glyph extents %d,%d - %d,%d drawable x,y %d,%d\n", extents.left, extents.top,
@ -1901,21 +1911,28 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
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,
SmoothGlyphGray(image,
offset.x + image_off_x - extents.left,
offset.y + image_off_y - extents.top,
formatEntry->bitmaps[wstr[idx]],
&formatEntry->gis[wstr[idx]],
physDev->textPixel);
if(lpDx) {
offset += lpDx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
} else {
xoff += formatEntry->gis[wstr[idx]].xOff;
yoff += formatEntry->gis[wstr[idx]].yOff;
}
if(lpDx)
{
if(flags & ETO_PDY)
{
offset.x += lpDx[idx * 2];
offset.y += lpDx[idx * 2 + 1];
}
else
offset.x += lpDx[idx];
}
else
{
offset.x += formatEntry->gis[wstr[idx]].xOff;
offset.y += formatEntry->gis[wstr[idx]].yOff;
}
}
XPutImage(gdi_display, physDev->drawable, physDev->gc, image, 0, 0,
image_x, image_y, image_w, image_h);