mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[Win32k]
- Fix path support, now all wine path tests pass. - Need a PolyDraw test for non-path functions! The non-path code was synced ported, but still failed 16 path tests, then path was moved out. Purged missing patches from the last trunk freeze, tested with the program Area. - Sync Information: Evan Stade <estade@gmail.com> : Improved PolyDraw in path closed case. Added PATH_PolyDraw. svn path=/trunk/; revision=54210
This commit is contained in:
parent
6bbe25388c
commit
a87d86ea1a
3 changed files with 233 additions and 57 deletions
|
@ -55,6 +55,7 @@ BOOL FASTCALL PATH_LineTo (PDC dc, INT x, INT y);
|
|||
BOOL FASTCALL PATH_MoveTo (PDC dc);
|
||||
BOOL FASTCALL PATH_PolyBezier (PDC dc, const POINT *pts, DWORD cbPoints);
|
||||
BOOL FASTCALL PATH_PolyBezierTo (PDC dc, const POINT *pts, DWORD cbPoints);
|
||||
BOOL FASTCALL PATH_PolyDraw(PDC dc, const POINT *pts, const BYTE *types, DWORD cbPoints);
|
||||
BOOL FASTCALL PATH_Polygon (PDC dc, const POINT *pts, DWORD cbPoints);
|
||||
BOOL FASTCALL PATH_Polyline (PDC dc, const POINT *pts, DWORD cbPoints);
|
||||
BOOL FASTCALL PATH_PolylineTo (PDC dc, const POINT *pts, DWORD cbPoints);
|
||||
|
|
|
@ -417,73 +417,110 @@ NtGdiPolyDraw(
|
|||
IN ULONG cCount)
|
||||
{
|
||||
PDC dc;
|
||||
PPATH pPath;
|
||||
BOOL result = FALSE;
|
||||
POINT lastmove;
|
||||
unsigned int i;
|
||||
PDC_ATTR pdcattr;
|
||||
POINT *line_pts = NULL, *line_pts_old, *bzr_pts = NULL, bzr[4];
|
||||
INT i, num_pts, num_bzr_pts, space, space_old, size;
|
||||
BOOL result = FALSE;
|
||||
|
||||
dc = DC_LockDc(hdc);
|
||||
if (!dc) return FALSE;
|
||||
pdcattr = dc->pdcattr;
|
||||
|
||||
if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
|
||||
DC_vUpdateFillBrush(dc);
|
||||
|
||||
if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
|
||||
DC_vUpdateLineBrush(dc);
|
||||
|
||||
if (!cCount)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeArrayForRead(lppt, sizeof(POINT), cCount, sizeof(LONG));
|
||||
ProbeArrayForRead(lpbTypes, sizeof(BYTE), cCount, sizeof(BYTE));
|
||||
|
||||
/* check for each bezierto if there are two more points */
|
||||
for ( i = 0; i < cCount; i++ )
|
||||
if (PATH_IsPathOpen(dc->dclevel))
|
||||
{
|
||||
if ( lpbTypes[i] != PT_MOVETO &&
|
||||
lpbTypes[i] & PT_BEZIERTO )
|
||||
{
|
||||
if ( cCount < i+3 ) _SEH2_LEAVE;
|
||||
else i += 2;
|
||||
}
|
||||
result = PATH_PolyDraw(dc, (const POINT *)lppt, (const BYTE *)lpbTypes, cCount);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
/* if no moveto occurs, we will close the figure here */
|
||||
lastmove.x = pdcattr->ptlCurrent.x;
|
||||
lastmove.y = pdcattr->ptlCurrent.y;
|
||||
|
||||
/* now let's draw */
|
||||
for ( i = 0; i < cCount; i++ )
|
||||
/* check for valid point types */
|
||||
for (i = 0; i < cCount; i++)
|
||||
{
|
||||
if ( lpbTypes[i] == PT_MOVETO )
|
||||
{
|
||||
IntGdiMoveToEx( dc, lppt[i].x, lppt[i].y, NULL, FALSE );
|
||||
lastmove.x = pdcattr->ptlCurrent.x;
|
||||
lastmove.y = pdcattr->ptlCurrent.y;
|
||||
}
|
||||
else if ( lpbTypes[i] & PT_LINETO )
|
||||
IntGdiLineTo( dc, lppt[i].x, lppt[i].y );
|
||||
else if ( lpbTypes[i] & PT_BEZIERTO )
|
||||
{
|
||||
POINT pts[4];
|
||||
pts[0].x = pdcattr->ptlCurrent.x;
|
||||
pts[0].y = pdcattr->ptlCurrent.y;
|
||||
RtlCopyMemory(pts + 1, &lppt[i], sizeof(POINT) * 3);
|
||||
IntGdiPolyBezier(dc, pts, 4);
|
||||
i += 2;
|
||||
}
|
||||
else _SEH2_LEAVE;
|
||||
|
||||
if ( lpbTypes[i] & PT_CLOSEFIGURE )
|
||||
{
|
||||
if ( PATH_IsPathOpen(dc->dclevel) )
|
||||
{
|
||||
pPath = PATH_LockPath( dc->dclevel.hPath );
|
||||
if (pPath)
|
||||
{
|
||||
IntGdiCloseFigure( pPath );
|
||||
PATH_UnlockPath( pPath );
|
||||
}
|
||||
}
|
||||
else IntGdiLineTo( dc, lastmove.x, lastmove.y );
|
||||
}
|
||||
switch (lpbTypes[i])
|
||||
{
|
||||
case PT_MOVETO:
|
||||
case PT_LINETO | PT_CLOSEFIGURE:
|
||||
case PT_LINETO:
|
||||
break;
|
||||
case PT_BEZIERTO:
|
||||
if((i + 2 < cCount) && (lpbTypes[i + 1] == PT_BEZIERTO) &&
|
||||
((lpbTypes[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO))
|
||||
{
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
}
|
||||
|
||||
space = cCount + 300;
|
||||
line_pts = ExAllocatePoolWithTag(PagedPool, space * sizeof(POINT), TAG_SHAPE);
|
||||
num_pts = 1;
|
||||
|
||||
line_pts[0].x = pdcattr->ptlCurrent.x;
|
||||
line_pts[0].y = pdcattr->ptlCurrent.y;
|
||||
|
||||
for ( i = 0; i < cCount; i++ )
|
||||
{
|
||||
switch (lpbTypes[i])
|
||||
{
|
||||
case PT_MOVETO:
|
||||
if (num_pts >= 2) IntGdiPolyline( dc, line_pts, num_pts );
|
||||
num_pts = 0;
|
||||
line_pts[num_pts++] = lppt[i];
|
||||
break;
|
||||
case PT_LINETO:
|
||||
case (PT_LINETO | PT_CLOSEFIGURE):
|
||||
line_pts[num_pts++] = lppt[i];
|
||||
break;
|
||||
case PT_BEZIERTO:
|
||||
bzr[0].x = line_pts[num_pts - 1].x;
|
||||
bzr[0].y = line_pts[num_pts - 1].y;
|
||||
RtlCopyMemory( &bzr[1], &lppt[i], 3 * sizeof(POINT) );
|
||||
|
||||
if ((bzr_pts = GDI_Bezier( bzr, 4, &num_bzr_pts )))
|
||||
{
|
||||
size = num_pts + (cCount - i) + num_bzr_pts;
|
||||
if (space < size)
|
||||
{
|
||||
space_old = space;
|
||||
space = size * 2;
|
||||
line_pts_old = line_pts;
|
||||
line_pts = ExAllocatePoolWithTag(PagedPool, space * sizeof(POINT), TAG_SHAPE);
|
||||
if (!line_pts) _SEH2_LEAVE;
|
||||
RtlCopyMemory(line_pts, line_pts_old, space_old * sizeof(POINT));
|
||||
ExFreePoolWithTag(line_pts_old, TAG_SHAPE);
|
||||
}
|
||||
RtlCopyMemory( &line_pts[num_pts], &bzr_pts[1], (num_bzr_pts - 1) * sizeof(POINT) );
|
||||
num_pts += num_bzr_pts - 1;
|
||||
ExFreePoolWithTag(bzr_pts, TAG_BEZIER);
|
||||
}
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
if (lpbTypes[i] & PT_CLOSEFIGURE) line_pts[num_pts++] = line_pts[0];
|
||||
}
|
||||
|
||||
if (num_pts >= 2) IntGdiPolyline( dc, line_pts, num_pts );
|
||||
IntGdiMoveToEx( dc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL, TRUE );
|
||||
ExFreePoolWithTag(line_pts, TAG_SHAPE);
|
||||
result = TRUE;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
|
@ -497,8 +534,8 @@ NtGdiPolyDraw(
|
|||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL
|
||||
APIENTRY
|
||||
|
@ -508,8 +545,32 @@ NtGdiMoveTo(
|
|||
IN INT y,
|
||||
OUT OPTIONAL LPPOINT pptOut)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return FALSE;
|
||||
PDC dc;
|
||||
BOOL Ret;
|
||||
POINT Point;
|
||||
|
||||
dc = DC_LockDc(hdc);
|
||||
if (!dc) return FALSE;
|
||||
|
||||
Ret = IntGdiMoveToEx(dc, x, y, &Point, TRUE);
|
||||
|
||||
if (pptOut)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite( pptOut, sizeof(POINT), 1);
|
||||
RtlCopyMemory( pptOut, &Point, sizeof(POINT));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
SetLastNtError(_SEH2_GetExceptionCode());
|
||||
Ret = FALSE;
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -64,6 +64,18 @@ IntGdiCloseFigure(PPATH pPath)
|
|||
}
|
||||
}
|
||||
|
||||
/* MSDN: This fails if the device coordinates exceed 27 bits, or if the converted
|
||||
logical coordinates exceed 32 bits. */
|
||||
BOOL
|
||||
FASTCALL
|
||||
GdiPathDPtoLP(PDC pdc, PPOINT ppt, INT count)
|
||||
{
|
||||
XFORMOBJ xo;
|
||||
|
||||
XFORMOBJ_vInit(&xo, &pdc->dclevel.mxDeviceToWorld);
|
||||
return XFORMOBJ_bApplyXform(&xo, XF_LTOL, count, (PPOINTL)ppt, (PPOINTL)ppt);
|
||||
}
|
||||
|
||||
/* PATH_FillPath
|
||||
*
|
||||
*
|
||||
|
@ -720,6 +732,103 @@ PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
PATH_PolyDraw(PDC dc, const POINT *pts, const BYTE *types, DWORD cbPoints)
|
||||
{
|
||||
PPATH pPath;
|
||||
POINT lastmove, orig_pos;
|
||||
INT i;
|
||||
PDC_ATTR pdcattr;
|
||||
BOOL State = FALSE, Ret = FALSE;
|
||||
|
||||
pPath = PATH_LockPath( dc->dclevel.hPath );
|
||||
if (!pPath) return FALSE;
|
||||
|
||||
if ( pPath->state != PATH_Open )
|
||||
{
|
||||
PATH_UnlockPath( pPath );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pdcattr = dc->pdcattr;
|
||||
|
||||
lastmove.x = orig_pos.x = pdcattr->ptlCurrent.x;
|
||||
lastmove.y = orig_pos.y = pdcattr->ptlCurrent.y;
|
||||
|
||||
for (i = pPath->numEntriesUsed - 1; i >= 0; i--)
|
||||
{
|
||||
if (pPath->pFlags[i] == PT_MOVETO)
|
||||
{
|
||||
lastmove.x = pPath->pPoints[i].x;
|
||||
lastmove.y = pPath->pPoints[i].y;
|
||||
if (!GdiPathDPtoLP(dc, &lastmove, 1))
|
||||
{
|
||||
PATH_UnlockPath( pPath );
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cbPoints; i++)
|
||||
{
|
||||
if (types[i] == PT_MOVETO)
|
||||
{
|
||||
pPath->newStroke = TRUE;
|
||||
lastmove.x = pts[i].x;
|
||||
lastmove.y = pts[i].y;
|
||||
}
|
||||
else if((types[i] & ~PT_CLOSEFIGURE) == PT_LINETO)
|
||||
{
|
||||
PATH_LineTo(dc, pts[i].x, pts[i].y);
|
||||
}
|
||||
else if(types[i] == PT_BEZIERTO)
|
||||
{
|
||||
if (!((i + 2 < cbPoints) && (types[i + 1] == PT_BEZIERTO)
|
||||
&& ((types[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO)))
|
||||
goto err;
|
||||
PATH_PolyBezierTo(dc, &(pts[i]), 3);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
goto err;
|
||||
|
||||
pdcattr->ptlCurrent.x = pts[i].x;
|
||||
pdcattr->ptlCurrent.y = pts[i].y;
|
||||
State = TRUE;
|
||||
|
||||
if (types[i] & PT_CLOSEFIGURE)
|
||||
{
|
||||
pPath->pFlags[pPath->numEntriesUsed-1] |= PT_CLOSEFIGURE;
|
||||
pPath->newStroke = TRUE;
|
||||
pdcattr->ptlCurrent.x = lastmove.x;
|
||||
pdcattr->ptlCurrent.y = lastmove.y;
|
||||
State = TRUE;
|
||||
}
|
||||
}
|
||||
Ret = TRUE;
|
||||
goto Exit;
|
||||
|
||||
err:
|
||||
if ((pdcattr->ptlCurrent.x != orig_pos.x) || (pdcattr->ptlCurrent.y != orig_pos.y))
|
||||
{
|
||||
pPath->newStroke = TRUE;
|
||||
pdcattr->ptlCurrent.x = orig_pos.x;
|
||||
pdcattr->ptlCurrent.y = orig_pos.y;
|
||||
State = TRUE;
|
||||
}
|
||||
Exit:
|
||||
if (State) // State change?
|
||||
{
|
||||
pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
|
||||
CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
|
||||
pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
|
||||
}
|
||||
PATH_UnlockPath( pPath );
|
||||
return Ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
|
||||
|
@ -1467,7 +1576,7 @@ BOOL
|
|||
FASTCALL
|
||||
PATH_WidenPath(DC *dc)
|
||||
{
|
||||
INT i, j, numStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
|
||||
INT i, j, numStrokes, numOldStrokes, penWidth, penWidthIn, penWidthOut, size, penStyle;
|
||||
BOOL ret = FALSE;
|
||||
PPATH pPath, pNewPath, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath;
|
||||
EXTLOGPEN *elp;
|
||||
|
@ -1554,6 +1663,7 @@ PATH_WidenPath(DC *dc)
|
|||
{
|
||||
pStrokes[numStrokes - 1]->state = PATH_Closed;
|
||||
}
|
||||
numOldStrokes = numStrokes;
|
||||
numStrokes++;
|
||||
j = 0;
|
||||
if (numStrokes == 1)
|
||||
|
@ -1563,7 +1673,7 @@ PATH_WidenPath(DC *dc)
|
|||
pOldStrokes = pStrokes; // Save old pointer.
|
||||
pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
|
||||
if (!pStrokes) return FALSE;
|
||||
RtlCopyMemory(pStrokes, pOldStrokes, numStrokes * sizeof(PPATH));
|
||||
RtlCopyMemory(pStrokes, pOldStrokes, numOldStrokes * sizeof(PPATH));
|
||||
ExFreePoolWithTag(pOldStrokes, TAG_PATH); // Free old pointer.
|
||||
}
|
||||
if (!pStrokes) return FALSE;
|
||||
|
@ -2392,7 +2502,11 @@ NtGdiGetPath(
|
|||
memcpy(Types, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
|
||||
|
||||
/* Convert the points to logical coordinates */
|
||||
IntDPtoLP(dc, Points, pPath->numEntriesUsed);
|
||||
if (!GdiPathDPtoLP(dc, Points, pPath->numEntriesUsed))
|
||||
{
|
||||
EngSetLastError(ERROR_ARITHMETIC_OVERFLOW);
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
ret = pPath->numEntriesUsed;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue