Author: jimtabor Date: Thu Oct 20 12:02:15 2011 New Revision: 54210
URL: http://svn.reactos.org/svn/reactos?rev=54210&view=rev Log: [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.
Modified: trunk/reactos/subsystems/win32/win32k/include/path.h trunk/reactos/subsystems/win32/win32k/objects/line.c trunk/reactos/subsystems/win32/win32k/objects/path.c
Modified: trunk/reactos/subsystems/win32/win32k/include/path.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/path.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/path.h [iso-8859-1] Thu Oct 20 12:02:15 2011 @@ -55,6 +55,7 @@ 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);
Modified: trunk/reactos/subsystems/win32/win32k/objects/line.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/line.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/line.c [iso-8859-1] Thu Oct 20 12:02:15 2011 @@ -417,73 +417,110 @@ IN ULONG cCount) { PDC dc; - PPATH pPath; + 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; - POINT lastmove; - unsigned int i; - PDC_ATTR pdcattr;
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 */ + if (PATH_IsPathOpen(dc->dclevel)) + { + result = PATH_PolyDraw(dc, (const POINT *)lppt, (const BYTE *)lpbTypes, cCount); + _SEH2_LEAVE; + } + + /* check for valid point types */ + for (i = 0; i < cCount; i++) + { + 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++ ) { - if ( lpbTypes[i] != PT_MOVETO && - lpbTypes[i] & PT_BEZIERTO ) - { - if ( cCount < i+3 ) _SEH2_LEAVE; - else i += 2; - } - } - - /* 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++ ) - { - 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: + 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 @@ return result; }
- /* - * @unimplemented +/* + * @implemented */ BOOL APIENTRY @@ -508,8 +545,32 @@ 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 */
Modified: trunk/reactos/subsystems/win32/win32k/objects/path.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/path.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/path.c [iso-8859-1] Thu Oct 20 12:02:15 2011 @@ -62,6 +62,18 @@ pPath->pFlags[pPath->numEntriesUsed-1]|=PT_CLOSEFIGURE; pPath->newStroke=TRUE; } +} + +/* 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 @@ -722,6 +734,103 @@
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 ) { POINT pt; @@ -1467,7 +1576,7 @@ 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 @@ { pStrokes[numStrokes - 1]->state = PATH_Closed; } + numOldStrokes = numStrokes; numStrokes++; j = 0; if (numStrokes == 1) @@ -1563,7 +1673,7 @@ 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 @@ 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; }