- 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:
James Tabor 2011-10-20 12:02:15 +00:00
parent 6bbe25388c
commit a87d86ea1a
3 changed files with 233 additions and 57 deletions

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}