mirror of
https://github.com/reactos/reactos.git
synced 2024-08-02 17:40:58 +00:00
- Add path support for ExtTextOut.
svn path=/trunk/; revision=37345
This commit is contained in:
parent
3ab3cebe76
commit
122723ef7d
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in a new issue