Author: tkreuzer Date: Tue Oct 7 18:02:41 2008 New Revision: 36686
URL: http://svn.reactos.org/svn/reactos?rev=36686&view=rev Log: - rewrite NtGdiPolyPolyDraw, optimizing it and making it more windows compatible - Make PolyCounts ULONGs, not DWORDS or INTs. - Remove GdiCreatePolyPolygonRgn and use IntCreatePolyPolygonRgn instead to get rid of code-duplication. - IntGdiPolygon: rename UnsafePoints to Points
Modified: trunk/reactos/subsystems/win32/win32k/include/intgdi.h trunk/reactos/subsystems/win32/win32k/include/region.h trunk/reactos/subsystems/win32/win32k/objects/fillshap.c trunk/reactos/subsystems/win32/win32k/objects/line.c trunk/reactos/subsystems/win32/win32k/objects/path.c trunk/reactos/subsystems/win32/win32k/objects/region.c
Modified: trunk/reactos/subsystems/win32/win32k/include/intgdi.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/intgdi.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/intgdi.h [iso-8859-1] Tue Oct 7 18:02:41 2008 @@ -93,7 +93,7 @@ BOOL FASTCALL IntGdiPolyPolyline(DC *dc, LPPOINT pt, - LPDWORD PolyPoints, + PULONG PolyPoints, DWORD Count);
BOOL FASTCALL @@ -125,7 +125,7 @@ BOOL FASTCALL IntGdiPolyPolygon(DC *dc, LPPOINT Points, - LPINT PolyCounts, + PULONG PolyCounts, int Count);
BOOL FASTCALL IntGdiGradientFill(DC *dc,
Modified: trunk/reactos/subsystems/win32/win32k/include/region.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/region.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/region.h [iso-8859-1] Tue Oct 7 18:02:41 2008 @@ -43,7 +43,7 @@
INT STDCALL IntGdiGetRgnBox(HRGN, LPRECT); BOOL FASTCALL IntGdiPaintRgn(PDC, HRGN ); -HRGN FASTCALL GdiCreatePolyPolygonRgn(CONST PPOINT, CONST PINT, INT, INT ); +HRGN FASTCALL IntCreatePolyPolygonRgn(PPOINT, PULONG, INT, INT);
INT FASTCALL IntGdiCombineRgn(PROSRGNDATA, PROSRGNDATA, PROSRGNDATA, INT); INT FASTCALL REGION_Complexity(PROSRGNDATA);
Modified: trunk/reactos/subsystems/win32/win32k/objects/fillshap.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] Tue Oct 7 18:02:41 2008 @@ -51,7 +51,7 @@
BOOL FASTCALL IntGdiPolygon(PDC dc, - PPOINT UnsafePoints, + PPOINT Points, int Count) { BITMAPOBJ *BitmapObj; @@ -64,7 +64,7 @@
ASSERT(dc); // caller's responsibility to pass a valid dc
- if ( NULL == UnsafePoints || Count < 2 ) + if (!Points || Count < 2 ) { SetLastWin32Error(ERROR_INVALID_PARAMETER); return FALSE; @@ -74,25 +74,25 @@ if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* Convert to screen coordinates */ - IntLPtoDP(dc, UnsafePoints, Count); + IntLPtoDP(dc, Points, Count); for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++) { - UnsafePoints[CurrentPoint].x += dc->ptlDCOrig.x; - UnsafePoints[CurrentPoint].y += dc->ptlDCOrig.y; + Points[CurrentPoint].x += dc->ptlDCOrig.x; + Points[CurrentPoint].y += dc->ptlDCOrig.y; } // No need to have path here. { - DestRect.left = UnsafePoints[0].x; - DestRect.right = UnsafePoints[0].x; - DestRect.top = UnsafePoints[0].y; - DestRect.bottom = UnsafePoints[0].y; + DestRect.left = Points[0].x; + DestRect.right = Points[0].x; + DestRect.top = Points[0].y; + DestRect.bottom = Points[0].y;
for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) { - DestRect.left = min(DestRect.left, UnsafePoints[CurrentPoint].x); - DestRect.right = max(DestRect.right, UnsafePoints[CurrentPoint].x); - DestRect.top = min(DestRect.top, UnsafePoints[CurrentPoint].y); - DestRect.bottom = max(DestRect.bottom, UnsafePoints[CurrentPoint].y); + DestRect.left = min(DestRect.left, Points[CurrentPoint].x); + DestRect.right = max(DestRect.right, Points[CurrentPoint].x); + DestRect.top = min(DestRect.top, Points[CurrentPoint].y); + DestRect.bottom = max(DestRect.bottom, Points[CurrentPoint].y); }
/* Special locking order to avoid lock-ups */ @@ -106,7 +106,7 @@ if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)) { IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush); - ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), UnsafePoints, Count, DestRect ); + ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), Points, Count, DestRect ); } if (FillBrushObj) BRUSHOBJ_UnlockBrush(FillBrushObj); @@ -122,16 +122,16 @@ {
// DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", -// UnsafePoints[0].x, UnsafePoints[0].y, -// UnsafePoints[1].x, UnsafePoints[1].y ); +// Points[0].x, Points[0].y, +// Points[1].x, Points[1].y );
ret = IntEngLineTo(&BitmapObj->SurfObj, dc->CombinedClip, &PenBrushInst.BrushObject, - UnsafePoints[i].x, /* From */ - UnsafePoints[i].y, - UnsafePoints[i+1].x, /* To */ - UnsafePoints[i+1].y, + Points[i].x, /* From */ + Points[i].y, + Points[i+1].x, /* To */ + Points[i+1].y, &DestRect, ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ if (!ret) break; @@ -142,10 +142,10 @@ ret = IntEngLineTo(&BitmapObj->SurfObj, dc->CombinedClip, &PenBrushInst.BrushObject, - UnsafePoints[Count-1].x, /* From */ - UnsafePoints[Count-1].y, - UnsafePoints[0].x, /* To */ - UnsafePoints[0].y, + Points[Count-1].x, /* From */ + Points[Count-1].y, + Points[0].x, /* To */ + Points[0].y, &DestRect, ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ } @@ -161,11 +161,11 @@ BOOL FASTCALL IntGdiPolyPolygon(DC *dc, LPPOINT Points, - LPINT PolyCounts, + PULONG PolyCounts, int Count) { if (PATH_IsPathOpen(dc->DcLevel)) - return PATH_PolyPolygon ( dc, Points, PolyCounts, Count); + return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
while (--Count >=0) { @@ -336,185 +336,152 @@ ULONG_PTR STDCALL NtGdiPolyPolyDraw( IN HDC hDC, - IN PPOINT Points, - IN PULONG PolyCounts, + IN PPOINT UnsafePoints, + IN PULONG UnsafeCounts, IN ULONG Count, IN INT iFunc ) { DC *dc; - LPPOINT Safept; - LPINT SafePolyPoints; + PVOID pTemp; + LPPOINT SafePoints; + PULONG SafeCounts; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = TRUE; - INT nPoints, nEmpty, nInvalid, i; - - if (iFunc == GdiPolyPolyRgn) - { - return (ULONG_PTR) GdiCreatePolyPolygonRgn((CONST PPOINT) Points, - (CONST PINT) PolyCounts, - Count, - (INT) hDC); - } - dc = DC_LockDc(hDC); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - if (dc->DC_Type == DC_TYPE_INFO) - { - DC_UnlockDc(dc); - /* Yes, Windows really returns TRUE in this case */ - return TRUE; - } - - if (Count > 0) - { - _SEH_TRY - { - ProbeForRead(Points, - Count * sizeof(POINT), - 1); - ProbeForRead(PolyCounts, - Count * sizeof(INT), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - SetLastNtError(Status); - return FALSE; - } - - SafePolyPoints = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_SHAPE); - if (!SafePolyPoints) - { - DC_UnlockDc(dc); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - _SEH_TRY - { - /* pointers already probed! */ - RtlCopyMemory(SafePolyPoints, - PolyCounts, - Count * sizeof(INT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - SetLastNtError(Status); - return FALSE; - } - /* validate poligons */ - nPoints = 0; - nEmpty = 0; - nInvalid = 0; + INT nPoints = 0, nMaxPoints = 0, nInvalid = 0, i; + + if (!UnsafePoints || !UnsafeCounts || + Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn) + { + /* Windows doesn't set last error */ + return FALSE; + } + + _SEH_TRY + { + ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1); + ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1); + + /* Count points and validate poligons */ for (i = 0; i < Count; i++) { - if (SafePolyPoints[i] == 0) - { - nEmpty++; - } - if (SafePolyPoints[i] == 1) + if (UnsafeCounts[i] < 2) { nInvalid++; } - nPoints += SafePolyPoints[i]; + nPoints += UnsafeCounts[i]; + nMaxPoints = max(nMaxPoints, UnsafeCounts[i]); } - - if (nEmpty == Count) - { - /* if all polygon counts are zero, return without setting a last error code. */ - ExFreePool(SafePolyPoints); - return FALSE; - } - if (nInvalid != 0) - { - /* if at least one poly count is 1, fail */ - ExFreePool(SafePolyPoints); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - Safept = ExAllocatePoolWithTag(PagedPool, nPoints * sizeof(POINT), TAG_SHAPE); - if (!Safept) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - _SEH_TRY - { - /* pointers already probed! */ - RtlCopyMemory(Safept, - Points, - nPoints * sizeof(POINT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - ExFreePool(Safept); - SetLastNtError(Status); - return FALSE; - } - } - else + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + /* Windows doesn't set last error */ + return FALSE; + } + + if (nPoints == 0 || nPoints < nMaxPoints) + { + /* If all polygon counts are zero, or we have overflow, + return without setting a last error code. */ + return FALSE; + } + + if (nInvalid != 0) + { + /* If at least one poly count is 0 or 1, fail */ + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } + + /* Allocate one buffer for both counts and points */ + pTemp = ExAllocatePoolWithTag(PagedPool, + Count * sizeof(ULONG) + nPoints * sizeof(POINT), + TAG_SHAPE); + if (!pTemp) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + SafeCounts = pTemp; + SafePoints = (PVOID)(SafeCounts + Count); + + _SEH_TRY + { + /* Pointers already probed! */ + RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG)); + RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + ExFreePool(pTemp); + return FALSE; + } + + /* Special handling for GdiPolyPolyRgn */ + if (iFunc == GdiPolyPolyRgn) + { + HRGN hRgn; + hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC); + ExFreePool(pTemp); + return (ULONG_PTR)hRgn; + } + + dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + ExFreePool(pTemp); + return FALSE; + } + + if (dc->DC_Type == DC_TYPE_INFO) { DC_UnlockDc(dc); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - + ExFreePool(pTemp); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + /* Perform the actual work */ switch (iFunc) { case GdiPolyPolygon: - Ret = IntGdiPolyPolygon(dc, Safept, SafePolyPoints, Count); + Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count); break; case GdiPolyPolyLine: - Ret = IntGdiPolyPolyline(dc, Safept, (LPDWORD) SafePolyPoints, Count); + Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count); break; case GdiPolyBezier: - Ret = IntGdiPolyBezier(dc, Safept, *PolyCounts); + Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts); break; case GdiPolyLineTo: - Ret = IntGdiPolylineTo(dc, Safept, *PolyCounts); + Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts); break; case GdiPolyBezierTo: - Ret = IntGdiPolyBezierTo(dc, Safept, *PolyCounts); + Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts); break; default: SetLastWin32Error(ERROR_INVALID_PARAMETER); Ret = FALSE; } - ExFreePool(SafePolyPoints); - ExFreePool(Safept); + + /* Cleanup and return */ DC_UnlockDc(dc); - - return (ULONG_PTR) Ret; + ExFreePool(pTemp); + + return (ULONG_PTR)Ret; }
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] Tue Oct 7 18:02:41 2008 @@ -350,12 +350,12 @@ BOOL FASTCALL IntGdiPolyPolyline(DC *dc, LPPOINT pt, - LPDWORD PolyPoints, + PULONG PolyPoints, DWORD Count) { int i; LPPOINT pts; - LPDWORD pc; + PULONG pc; BOOL ret = FALSE; // default to failure pts = pt; pc = PolyPoints;
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] Tue Oct 7 18:02:41 2008 @@ -1028,7 +1028,6 @@ }
-HRGN FASTCALL IntCreatePolyPolygonRgn(POINT *Pts, INT *Count, INT nbpolygons,INT mode); /* PATH_PathToRegion * * Creates a region from the specified path using the specified polygon @@ -1042,7 +1041,7 @@ PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn ) { int numStrokes, iStroke, i; - INT *pNumPointsInStroke; + PULONG pNumPointsInStroke; HRGN hrgn = 0;
ASSERT(pPath!=NULL); @@ -1060,7 +1059,7 @@ numStrokes++;
/* Allocate memory for number-of-points-in-stroke array */ - pNumPointsInStroke=(int *)ExAllocatePoolWithTag(PagedPool, sizeof(int) * numStrokes, TAG_PATH); + pNumPointsInStroke = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * numStrokes, TAG_PATH); if(!pNumPointsInStroke) { SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
Modified: trunk/reactos/subsystems/win32/win32k/objects/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] Tue Oct 7 18:02:41 2008 @@ -3560,7 +3560,7 @@ */ static void FASTCALL REGION_CreateETandAET( - const INT *Count, + const ULONG *Count, INT nbpolygons, const POINT *pts, EdgeTable *ET, @@ -3657,7 +3657,7 @@ HRGN FASTCALL IntCreatePolyPolygonRgn( POINT *Pts, - INT *Count, + PULONG Count, INT nbpolygons, INT mode ) @@ -3680,6 +3680,8 @@ POINTBLOCK *tmpPtBlock; int numFullPtBlocks = 0; INT poly, total; + + if (mode == 0 || mode > 2) return 0;
if (!(region = REGION_AllocRgnWithHandle(nbpolygons))) return 0; @@ -3851,139 +3853,4 @@ return hrgn; }
- -HRGN -FASTCALL -GdiCreatePolyPolygonRgn( - CONST PPOINT pt, - CONST PINT PolyCounts, - INT Count, - INT PolyFillMode -) -{ - POINT *Safept; - INT *SafePolyCounts; - INT nPoints, nEmpty, nInvalid, i; - HRGN hRgn; - NTSTATUS Status = STATUS_SUCCESS; - - if (pt == NULL || PolyCounts == NULL || Count == 0 || - (PolyFillMode != WINDING && PolyFillMode != ALTERNATE)) - { - /* Windows doesn't set a last error here */ - return (HRGN)0; - } - - _SEH_TRY - { - ProbeForRead(PolyCounts, Count * sizeof(INT), 1); - /* just probe one point for now, we don't know the length of the array yet */ - ProbeForRead(pt, sizeof(POINT), 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return (HRGN)0; - } - - if (!(SafePolyCounts = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_REGION))) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return (HRGN)0; - } - - _SEH_TRY - { - /* pointers were already probed! */ - RtlCopyMemory(SafePolyCounts, - PolyCounts, - Count * sizeof(INT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - ExFreePool(SafePolyCounts); - SetLastNtError(Status); - return (HRGN)0; - } - - /* validate poligons */ - nPoints = 0; - nEmpty = 0; - nInvalid = 0; - for (i = 0; i < Count; i++) - { - if (SafePolyCounts[i] == 0) - { - nEmpty++; - } - if (SafePolyCounts[i] == 1) - { - nInvalid++; - } - nPoints += SafePolyCounts[i]; - } - - if (nEmpty == Count) - { - /* if all polygon counts are zero, return without setting a last error code. */ - ExFreePool(SafePolyCounts); - return (HRGN)0; - } - if (nInvalid != 0) - { - /* if at least one poly count is 1, fail */ - ExFreePool(SafePolyCounts); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return (HRGN)0; - } - - /* copy points */ - if (!(Safept = ExAllocatePoolWithTag(PagedPool, nPoints * sizeof(POINT), TAG_REGION))) - { - ExFreePool(SafePolyCounts); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return (HRGN)0; - } - - _SEH_TRY - { - ProbeForRead(pt, nPoints * sizeof(POINT), 1); - /* pointers were already probed! */ - RtlCopyMemory(Safept, - pt, - nPoints * sizeof(POINT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - if (!NT_SUCCESS(Status)) - { - ExFreePool(Safept); - ExFreePool(SafePolyCounts); - SetLastNtError(Status); - return (HRGN)0; - } - - /* now we're ready to calculate the region safely */ - hRgn = IntCreatePolyPolygonRgn(Safept, SafePolyCounts, Count, PolyFillMode); - - ExFreePool(Safept); - ExFreePool(SafePolyCounts); - return hRgn; -} - /* EOF */