- Add path support for ExtTextOut.

svn path=/trunk/; revision=37345
This commit is contained in:
James Tabor 2008-11-13 22:38:16 +00:00
parent 3ab3cebe76
commit 122723ef7d
3 changed files with 269 additions and 19 deletions

View file

@ -67,6 +67,7 @@ BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts,
BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2);
BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height);
BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, HRGN *pHrgn);
BOOL FASTCALL PATH_ExtTextOut(PDC dc,INT x,INT y,UINT flags,const RECT *lprc,LPCWSTR str,UINT count,const INT *dx);
VOID FASTCALL IntGdiCloseFigure(PPATH pPath);
BOOL FASTCALL PATH_Delete(HPATH hPath);

View file

@ -3162,24 +3162,11 @@ NtGdiExtTextOutW(
Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR));
if (! NT_SUCCESS(Status))
{
goto fail;
goto fail;
}
}
String = SafeString;
if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
{
// At least one of the two flags were specified. Copy lprc. Once.
Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
if (!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
}
if (NULL != UnsafeDx && Count > 0)
{
Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
@ -3188,12 +3175,40 @@ NtGdiExtTextOutW(
goto fail;
}
Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT));
if (! NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
goto fail;
}
}
if (lprc)
{
Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
if (!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
goto fail;
}
}
if (PATH_IsPathOpen(dc->DcLevel))
{
if (!PATH_ExtTextOut( dc,
XStart,
YStart,
fuOptions,
(const RECT *)&SpecifiedDestRect,
SafeString,
Count,
(const INT *)Dx)) goto fail;
goto good;
}
if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
{
IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
}
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if ( !BitmapObj )
{
@ -3636,13 +3651,14 @@ NtGdiExtTextOutW(
}
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
good:
if (NULL != SafeString)
{
ExFreePool((void*)SafeString);
ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
}
if (NULL != Dx)
{
ExFreePool(Dx);
ExFreePoolWithTag(Dx, TAG_GDITEXT);
}
DC_UnlockDc( dc );
@ -3669,11 +3685,11 @@ fail:
}
if (NULL != SafeString)
{
ExFreePool((void*)SafeString);
ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
}
if (NULL != Dx)
{
ExFreePool(Dx);
ExFreePoolWithTag(Dx, TAG_GDITEXT);
}
DC_UnlockDc(dc);

View file

@ -1854,6 +1854,239 @@ PATH_WidenPath(DC *dc)
return ret;
}
static inline INT int_from_fixed(FIXED f)
{
return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
}
/**********************************************************************
* PATH_BezierTo
*
* internally used by PATH_add_outline
*/
static
VOID
FASTCALL
PATH_BezierTo(PPATH pPath, POINT *lppt, INT n)
{
if (n < 2) return;
if (n == 2)
{
PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
}
else if (n == 3)
{
PATH_AddEntry(pPath, &lppt[0], PT_BEZIERTO);
PATH_AddEntry(pPath, &lppt[1], PT_BEZIERTO);
PATH_AddEntry(pPath, &lppt[2], PT_BEZIERTO);
}
else
{
POINT pt[3];
INT i = 0;
pt[2] = lppt[0];
n--;
while (n > 2)
{
pt[0] = pt[2];
pt[1] = lppt[i+1];
pt[2].x = (lppt[i+2].x + lppt[i+1].x) / 2;
pt[2].y = (lppt[i+2].y + lppt[i+1].y) / 2;
PATH_BezierTo(pPath, pt, 3);
n--;
i++;
}
pt[0] = pt[2];
pt[1] = lppt[i+1];
pt[2] = lppt[i+2];
PATH_BezierTo(pPath, pt, 3);
}
}
static
BOOL
FASTCALL
PATH_add_outline(PDC dc, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
{
PPATH pPath;
TTPOLYGONHEADER *start;
POINT pt;
start = header;
pPath = PATH_LockPath(dc->DcLevel.hPath);
{
return FALSE;
}
while ((char *)header < (char *)start + size)
{
TTPOLYCURVE *curve;
if (header->dwType != TT_POLYGON_TYPE)
{
DPRINT1("Unknown header type %d\n", header->dwType);
return FALSE;
}
pt.x = x + int_from_fixed(header->pfxStart.x);
pt.y = y - int_from_fixed(header->pfxStart.y);
IntLPtoDP(dc, &pt, 1);
PATH_AddEntry(pPath, &pt, PT_MOVETO);
curve = (TTPOLYCURVE *)(header + 1);
while ((char *)curve < (char *)header + header->cb)
{
/*DPRINT1("curve->wType %d\n", curve->wType);*/
switch(curve->wType)
{
case TT_PRIM_LINE:
{
WORD i;
for (i = 0; i < curve->cpfx; i++)
{
pt.x = x + int_from_fixed(curve->apfx[i].x);
pt.y = y - int_from_fixed(curve->apfx[i].y);
IntLPtoDP(dc, &pt, 1);
PATH_AddEntry(pPath, &pt, PT_LINETO);
}
break;
}
case TT_PRIM_QSPLINE:
case TT_PRIM_CSPLINE:
{
WORD i;
POINTFX ptfx;
POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH);
if (!pts) return FALSE;
ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
pts[0].x = x + int_from_fixed(ptfx.x);
pts[0].y = y - int_from_fixed(ptfx.y);
IntLPtoDP(dc, &pts[0], 1);
for (i = 0; i < curve->cpfx; i++)
{
pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
IntLPtoDP(dc, &pts[i + 1], 1);
}
PATH_BezierTo(pPath, pts, curve->cpfx + 1);
ExFreePoolWithTag(pts, TAG_PATH);
break;
}
default:
DPRINT1("Unknown curve type %04x\n", curve->wType);
return FALSE;
}
curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
}
header = (TTPOLYGONHEADER *)((char *)header + header->cb);
}
IntGdiCloseFigure( pPath );
PATH_UnlockPath( pPath );
return TRUE;
}
/**********************************************************************
* PATH_ExtTextOut
*/
BOOL
FASTCALL
PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECT *lprc,
LPCWSTR str, UINT count, const INT *dx)
{
unsigned int idx;
double cosEsc, sinEsc;
PDC_ATTR Dc_Attr;
PTEXTOBJ TextObj;
LOGFONTW lf;
POINTL org;
INT offset = 0, xoff = 0, yoff = 0;
if (!count) return TRUE;
Dc_Attr = dc->pDc_Attr;
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
TextObj = RealizeFontInit( Dc_Attr->hlfntNew);
if ( !TextObj ) return FALSE;
FontGetObject( TextObj, 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;
}
IntGdiGetDCOrg(dc, &org);
for (idx = 0; idx < count; idx++)
{
GLYPHMETRICS gm;
DWORD dwSize;
void *outline;
dwSize = ftGdiGetGlyphOutline( dc,
str[idx],
GGO_GLYPH_INDEX | GGO_NATIVE,
&gm,
0,
NULL,
NULL,
TRUE);
if (!dwSize) return FALSE;
outline = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_PATH);
if (!outline) return FALSE;
ftGdiGetGlyphOutline( dc,
str[idx],
GGO_GLYPH_INDEX | GGO_NATIVE,
&gm,
dwSize,
outline,
NULL,
TRUE);
PATH_add_outline(dc, org.x + x + xoff, org.x + y + yoff, outline, dwSize);
ExFreePoolWithTag(outline, TAG_PATH);
if (dx)
{
offset += dx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
}
else
{
xoff += gm.gmCellIncX;
yoff += gm.gmCellIncY;
}
}
return TRUE;
}
/***********************************************************************