* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
-/*
- * a couple macros to fill a single pixel or a line
- */
-#define PUTPIXEL(x,y,BrushInst) \
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
- dc->CombinedClip, \
- &BrushInst.BrushObject, \
- x, y, (x)+1, y, \
- &RectBounds, \
- ROP2_TO_MIX(Dc_Attr->jROP2));
-
-#define PUTLINE(x1,y1,x2,y2,BrushInst) \
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
- dc->CombinedClip, \
- &BrushInst.BrushObject, \
- x1, y1, x2, y2, \
- &RectBounds, \
- ROP2_TO_MIX(Dc_Attr->jROP2));
-
#define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
#define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
-BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height);
-BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ PenBrushObj);
+BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush);
+BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush);
+BOOL FASTCALL IntFillRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrush);
+BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PBRUSH pbrush);
BOOL FASTCALL
IntGdiPolygon(PDC dc,
- PPOINT UnsafePoints,
+ PPOINT Points,
int Count)
{
- BITMAPOBJ *BitmapObj;
- PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
- GDIBRUSHINST PenBrushInst, FillBrushInst;
+ SURFACE *psurf;
+ PBRUSH pbrLine, pbrFill;
BOOL ret = FALSE; // default to failure
RECTL DestRect;
int CurrentPoint;
- PDC_ATTR Dc_Attr;
+ PDC_ATTR pdcattr;
+ POINTL BrushOrigin;
+// int Left;
+// int Top;
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;
}
- Dc_Attr = dc->pDc_Attr;
- if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+/*
+ //Find start x, y
+ Left = Points[0].x;
+ Top = Points[0].y;
+ for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
+ Left = min(Left, Points[CurrentPoint].x);
+ Top = min(Top, Points[CurrentPoint].y);
+ }
+*/
- BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
- /* FIXME - BitmapObj can be NULL!!!! don't assert but handle this case gracefully! */
- ASSERT(BitmapObj);
+ pdcattr = dc->pdcattr;
/* 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);
}
- /* Now fill the polygon with the current brush. */
- FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
- if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
+
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
+ /* Special locking order to avoid lock-ups */
+ pbrFill = dc->dclevel.pbrFill;
+ pbrLine = dc->dclevel.pbrLine;
+ psurf = dc->dclevel.pSurface;
+ /* FIXME - psurf can be NULL!!!! don't assert but handle this case gracefully! */
+ ASSERT(psurf);
+
+ /* Now fill the polygon with the current fill brush. */
+ if (!(pbrFill->flAttrs & GDIBRUSH_IS_NULL))
{
- IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
- ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), UnsafePoints, Count, DestRect );
+ BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
+ BrushOrigin.x += dc->ptlDCOrig.x;
+ BrushOrigin.y += dc->ptlDCOrig.y;
+ ret = IntFillPolygon (dc,
+ psurf,
+ &dc->eboFill.BrushObject,
+ Points,
+ Count,
+ DestRect,
+ &BrushOrigin);
}
- BRUSHOBJ_UnlockBrush(FillBrushObj);
- /* get BRUSHOBJ from current pen. */
- PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
// Draw the Polygon Edges with the current pen ( if not a NULL pen )
- if (PenBrushObj && !(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+ if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
{
int i;
- IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-
for (i = 0; i < Count-1; i++)
{
// DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
-// UnsafePoints[0].x, UnsafePoints[0].y,
-// UnsafePoints[1].x, UnsafePoints[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[0].x, Points[0].y,
+// Points[1].x, Points[1].y );
+
+ ret = IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ Points[i].x, /* From */
+ Points[i].y,
+ Points[i+1].x, /* To */
+ Points[i+1].y,
&DestRect,
- ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
+ ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
if (!ret) break;
}
/* Close the polygon */
if (ret)
{
- ret = IntEngLineTo(&BitmapObj->SurfObj,
- dc->CombinedClip,
- &PenBrushInst.BrushObject,
- UnsafePoints[Count-1].x, /* From */
- UnsafePoints[Count-1].y,
- UnsafePoints[0].x, /* To */
- UnsafePoints[0].y,
+ ret = IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ Points[Count-1].x, /* From */
+ Points[Count-1].y,
+ Points[0].x, /* To */
+ Points[0].y,
&DestRect,
- ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
+ ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
}
}
- PENOBJ_UnlockPen(PenBrushObj);
}
- BITMAPOBJ_UnlockBitmap(BitmapObj);
return ret;
}
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);
+ if (PATH_IsPathOpen(dc->dclevel))
+ return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
while (--Count >=0)
{
*
*/
-BOOL STDCALL
+BOOL APIENTRY
NtGdiEllipse(
HDC hDC,
int Left,
int Bottom)
{
PDC dc;
- PDC_ATTR Dc_Attr;
+ PDC_ATTR pdcattr;
RECTL RectBounds;
- PGDIBRUSHOBJ PenBrushObj;
+ PBRUSH pbrush;
BOOL ret = TRUE;
LONG PenWidth, PenOrigWidth;
LONG RadiusX, RadiusY, CenterX, CenterY;
+ PBRUSH pFillBrushObj;
+ BRUSH tmpFillBrushObj;
if ((Left == Right) || (Top == Bottom)) return TRUE;
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- if (dc->DC_Type == DC_TYPE_INFO)
+ if (dc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
- if (PATH_IsPathOpen(dc->DcLevel))
+ if (PATH_IsPathOpen(dc->dclevel))
{
ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
DC_UnlockDc(dc);
INT tmp = Bottom; Bottom = Top; Top = tmp;
}
- Dc_Attr = dc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+ pdcattr = dc->pdcattr;
+
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
- PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
- if (NULL == PenBrushObj)
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
+
+ pbrush = PEN_LockPen(pdcattr->hpen);
+ if (!pbrush)
{
DPRINT1("Ellipse Fail 1\n");
DC_UnlockDc(dc);
return FALSE;
}
- PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
- if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
+ PenOrigWidth = PenWidth = pbrush->ptPenWidth.x;
+ if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0;
- if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
+ if (pbrush->ulPenStyle == PS_INSIDEFRAME)
{
if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
}
if (!PenWidth) PenWidth = 1;
- PenBrushObj->ptPenWidth.x = PenWidth;
+ pbrush->ptPenWidth.x = PenWidth;
RectBounds.left = Left;
RectBounds.right = Right;
DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
- ret = IntFillEllipse( dc,
- CenterX - RadiusX,
- CenterY - RadiusY,
- RadiusX*2, // Width
- RadiusY*2); // Height
+ pFillBrushObj = BRUSH_LockBrush(pdcattr->hbrush);
+ if (NULL == pFillBrushObj)
+ {
+ DPRINT1("FillEllipse Fail\n");
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ ret = FALSE;
+ }
+ else
+ {
+ RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj));
+// tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
+// tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
+ tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
+ tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;
+ ret = IntFillEllipse( dc,
+ CenterX - RadiusX,
+ CenterY - RadiusY,
+ RadiusX*2, // Width
+ RadiusY*2, // Height
+ &tmpFillBrushObj);
+ BRUSH_UnlockBrush(pFillBrushObj);
+ }
+
if (ret)
ret = IntDrawEllipse( dc,
CenterX - RadiusX,
CenterY - RadiusY,
RadiusX*2, // Width
RadiusY*2, // Height
- PenBrushObj);
+ pbrush);
- PenBrushObj->ptPenWidth.x = PenOrigWidth;
- PENOBJ_UnlockPen(PenBrushObj);
+ pbrush->ptPenWidth.x = PenOrigWidth;
+ PEN_UnlockPen(pbrush);
DC_UnlockDc(dc);
DPRINT("Ellipse Exit.\n");
return ret;
ULONG_PTR
-STDCALL
+APIENTRY
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;
+ INT nPoints = 0, nMaxPoints = 0, nInvalid = 0, i;
- if (iFunc == GdiPolyPolyRgn)
+ if (!UnsafePoints || !UnsafeCounts ||
+ Count == 0 || iFunc == 0 || 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);
+ /* Windows doesn't set last error */
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)
+ _SEH2_TRY
{
- _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;
- }
+ ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
+ ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
- 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;
+ /* 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]);
}
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
- 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;
- }
+ if (!NT_SUCCESS(Status))
+ {
+ /* Windows doesn't set last error */
+ return FALSE;
+ }
- Safept = ExAllocatePoolWithTag(PagedPool, nPoints * sizeof(POINT), TAG_SHAPE);
- if (!Safept)
- {
- DC_UnlockDc(dc);
- ExFreePool(SafePolyPoints);
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- 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;
+ }
- _SEH_TRY
- {
- /* pointers already probed! */
- RtlCopyMemory(Safept,
- Points,
- nPoints * sizeof(POINT));
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
+ if (nInvalid != 0)
+ {
+ /* If at least one poly count is 0 or 1, fail */
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
- if (!NT_SUCCESS(Status))
- {
- DC_UnlockDc(dc);
- ExFreePool(SafePolyPoints);
- ExFreePool(Safept);
- SetLastNtError(Status);
- 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;
}
- else
+
+ SafeCounts = pTemp;
+ SafePoints = (PVOID)(SafeCounts + Count);
+
+ _SEH2_TRY
{
- DC_UnlockDc(dc);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ /* Pointers already probed! */
+ RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG));
+ RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(pTemp, TAG_SHAPE);
+ return FALSE;
+ }
+
+ /* Special handling for GdiPolyPolyRgn */
+ if (iFunc == GdiPolyPolyRgn)
+ {
+ HRGN hRgn;
+ hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC);
+ ExFreePoolWithTag(pTemp, TAG_SHAPE);
+ return (ULONG_PTR)hRgn;
+ }
+
+ dc = DC_LockDc(hDC);
+ if (!dc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ ExFreePool(pTemp);
return FALSE;
}
+ if (dc->dctype == DC_TYPE_INFO)
+ {
+ DC_UnlockDc(dc);
+ 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);
+ ExFreePool(pTemp);
- return (ULONG_PTR) Ret;
+ return (ULONG_PTR)Ret;
}
int RightRect,
int BottomRect)
{
- BITMAPOBJ *BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
- PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
- GDIBRUSHINST PenBrushInst, FillBrushInst;
+ SURFACE *psurf = NULL;
+ PBRUSH pbrLine, pbrFill;
BOOL ret = FALSE; // default to failure
RECTL DestRect;
MIX Mix;
- PDC_ATTR Dc_Attr;
+ PDC_ATTR pdcattr;
+ POINTL BrushOrigin;
ASSERT ( dc ); // caller's responsibility to set this up
- /* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */
- ASSERT ( BitmapObj );
- Dc_Attr = dc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+ pdcattr = dc->pdcattr;
- if ( PATH_IsPathOpen(dc->DcLevel) )
+ /* Do we rotate or shear? */
+ if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
{
- ret = PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
+
+ POINTL DestCoords[4];
+ ULONG PolyCounts = 4;
+ DestCoords[0].x = DestCoords[3].x = LeftRect;
+ DestCoords[0].y = DestCoords[1].y = TopRect;
+ DestCoords[1].x = DestCoords[2].x = RightRect;
+ DestCoords[2].y = DestCoords[3].y = BottomRect;
+ // Use IntGdiPolyPolygon so to support PATH.
+ return IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
}
- else
+ // Rectangle Path only.
+ if ( PATH_IsPathOpen(dc->dclevel) )
{
- LeftRect += dc->ptlDCOrig.x;
- RightRect += dc->ptlDCOrig.x - 1;
- TopRect += dc->ptlDCOrig.y;
- BottomRect += dc->ptlDCOrig.y - 1;
-
- DestRect.left = LeftRect;
- DestRect.right = RightRect;
- DestRect.top = TopRect;
- DestRect.bottom = BottomRect;
+ return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
+ }
- FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
+ DestRect.left = LeftRect;
+ DestRect.right = RightRect;
+ DestRect.top = TopRect;
+ DestRect.bottom = BottomRect;
- if ( FillBrushObj )
- {
- if (!(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
- {
- IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
- ret = IntEngBitBlt(&BitmapObj->SurfObj,
- NULL,
- NULL,
- dc->CombinedClip,
- NULL,
- &DestRect,
- NULL,
- NULL,
- &FillBrushInst.BrushObject,
- NULL,
- ROP3_TO_ROP4(PATCOPY));
- }
- }
+ IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
- BRUSHOBJ_UnlockBrush(FillBrushObj);
+ DestRect.left += dc->ptlDCOrig.x;
+ DestRect.right += dc->ptlDCOrig.x;
+ DestRect.top += dc->ptlDCOrig.y;
+ DestRect.bottom += dc->ptlDCOrig.y;
- /* get BRUSHOBJ from current pen. */
- PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
- if (PenBrushObj == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- return FALSE;
- }
+ /* In GM_COMPATIBLE, don't include bottom and right edges */
+ if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
+ {
+ DestRect.right--;
+ DestRect.bottom--;
+ }
- IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
- // Draw the rectangle with the current pen
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
- ret = TRUE; // change default to success
+ pbrFill = dc->dclevel.pbrFill;
+ pbrLine = dc->dclevel.pbrLine;
+ if (!pbrLine)
+ {
+ ret = FALSE;
+ goto cleanup;
+ }
+ psurf = dc->dclevel.pSurface;
+ if (!psurf)
+ {
+ ret = FALSE;
+ goto cleanup;
+ }
- if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+ if (pbrFill)
+ {
+ if (!(pbrFill->flAttrs & GDIBRUSH_IS_NULL))
{
- Mix = ROP2_TO_MIX(Dc_Attr->jROP2);
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
- dc->CombinedClip,
- &PenBrushInst.BrushObject,
- LeftRect, TopRect, RightRect, TopRect,
- &DestRect, // Bounding rectangle
- Mix);
-
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
- dc->CombinedClip,
- &PenBrushInst.BrushObject,
- RightRect, TopRect, RightRect, BottomRect,
- &DestRect, // Bounding rectangle
- Mix);
-
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
- dc->CombinedClip,
- &PenBrushInst.BrushObject,
- RightRect, BottomRect, LeftRect, BottomRect,
- &DestRect, // Bounding rectangle
- Mix);
-
- ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
- dc->CombinedClip,
- &PenBrushInst.BrushObject,
- LeftRect, BottomRect, LeftRect, TopRect,
- &DestRect, // Bounding rectangle
- Mix);
+ BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
+ BrushOrigin.x += dc->ptlDCOrig.x;
+ BrushOrigin.y += dc->ptlDCOrig.y;
+ ret = IntEngBitBlt(&psurf->SurfObj,
+ NULL,
+ NULL,
+ dc->rosdc.CombinedClip,
+ NULL,
+ &DestRect,
+ NULL,
+ NULL,
+ &dc->eboFill.BrushObject,
+ &BrushOrigin,
+ ROP3_TO_ROP4(PATCOPY));
}
-
- PENOBJ_UnlockPen(PenBrushObj);
}
- BITMAPOBJ_UnlockBitmap(BitmapObj);
+ // Draw the rectangle with the current pen
+
+ ret = TRUE; // change default to success
+
+ if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
+ {
+ Mix = ROP2_TO_MIX(pdcattr->jROP2);
+ ret = ret && IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ DestRect.left, DestRect.top, DestRect.right, DestRect.top,
+ &DestRect, // Bounding rectangle
+ Mix);
+
+ ret = ret && IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ DestRect.right, DestRect.top, DestRect.right, DestRect.bottom,
+ &DestRect, // Bounding rectangle
+ Mix);
+
+ ret = ret && IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom,
+ &DestRect, // Bounding rectangle
+ Mix);
+
+ ret = ret && IntEngLineTo(&psurf->SurfObj,
+ dc->rosdc.CombinedClip,
+ &dc->eboLine.BrushObject,
+ DestRect.left, DestRect.bottom, DestRect.left, DestRect.top,
+ &DestRect, // Bounding rectangle
+ Mix);
+ }
+cleanup:
/* Move current position in DC?
MSDN: The current position is neither used nor updated by Rectangle. */
- return TRUE;
+ return ret;
}
BOOL
-STDCALL
+APIENTRY
NtGdiRectangle(HDC hDC,
int LeftRect,
int TopRect,
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
- if (dc->DC_Type == DC_TYPE_INFO)
+ if (dc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
FASTCALL
IntRoundRect(
PDC dc,
- int left,
- int top,
- int right,
- int bottom,
+ int Left,
+ int Top,
+ int Right,
+ int Bottom,
int xCurveDiameter,
int yCurveDiameter)
{
- PDC_ATTR Dc_Attr;
- BITMAPOBJ *BitmapObj;
- PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
- GDIBRUSHINST FillBrushInst, PenBrushInst;
- RECTL RectBounds;
- int potential_steps;
- int i, col, row, width, height, x1, x1start, x2, x2start, y1, y2;
- int xradius, yradius;
- //float aspect_square;
- long a_square, b_square,
- two_a_square, two_b_square,
- four_a_square, four_b_square,
- d, dinc, ddec;
- BOOL first,
- ret = TRUE; // default to success
+ PDC_ATTR pdcattr;
+ PBRUSH pbrushLine, pbrushFill;
+ RECTL RectBounds;
+ LONG PenWidth, PenOrigWidth;
+ BOOL ret = TRUE; // default to success
+ BRUSH brushTemp;
ASSERT ( dc ); // caller's responsibility to set this up
- if ( PATH_IsPathOpen(dc->DcLevel) )
- return PATH_RoundRect ( dc, left, top, right, bottom,
+ if ( PATH_IsPathOpen(dc->dclevel) )
+ return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
xCurveDiameter, yCurveDiameter );
- Dc_Attr = dc->pDc_Attr;
- if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
- xradius = xCurveDiameter >> 1;
- yradius = yCurveDiameter >> 1;
-
- left += dc->ptlDCOrig.x;
- right += dc->ptlDCOrig.x;
- top += dc->ptlDCOrig.y;
- bottom += dc->ptlDCOrig.y;
+ if ((Left == Right) || (Top == Bottom)) return TRUE;
- RectBounds.left = left;
- RectBounds.right = right;
- RectBounds.top = top;
- RectBounds.bottom = bottom;
+ xCurveDiameter = max(abs( xCurveDiameter ), 1);
+ yCurveDiameter = max(abs( yCurveDiameter ), 1);
- BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
- if (!BitmapObj)
+ if (Right < Left)
{
- /* Nothing to do, as we don't have a bitmap */
- SetLastWin32Error(ERROR_INTERNAL_ERROR);
- return FALSE;
+ INT tmp = Right; Right = Left; Left = tmp;
}
-
- FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
- if (FillBrushObj)
+ if (Bottom < Top)
{
- if (FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)
- {
- /* make null brush check simpler... */
- BRUSHOBJ_UnlockBrush(FillBrushObj);
- FillBrushObj = NULL;
- }
- else
- {
- IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
- }
+ INT tmp = Bottom; Bottom = Top; Top = tmp;
}
- PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
- if (PenBrushObj)
- {
- if (PenBrushObj->flAttrs & GDIBRUSH_IS_NULL)
- {
- /* make null pen check simpler... */
- PENOBJ_UnlockPen(PenBrushObj);
- PenBrushObj = NULL;
- }
- else
- {
- IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
- }
- }
+ pdcattr = dc->pdcattr;
- right--;
- bottom--;
-
- width = right - left;
- height = bottom - top;
-
- if ( (xradius<<1) > width )
- xradius = width >> 1;
- if ( (yradius<<1) > height )
- yradius = height >> 1;
-
- b_square = yradius * yradius;
- a_square = xradius * xradius;
- row = yradius;
- col = 0;
- two_a_square = a_square << 1;
- four_a_square = a_square << 2;
- four_b_square = b_square << 2;
- two_b_square = b_square << 1;
- d = two_a_square * ((row - 1) * (row))
- + a_square
- + two_b_square * (1 - a_square);
-
- x1 = left+xradius;
- x2 = right-xradius;
- y1 = top;
- y2 = bottom;
-
- x1start = x1;
- x2start = x2;
-
- dinc = two_b_square*3; /* two_b_square * (3 + (col << 1)); */
- ddec = four_a_square * row;
-
- first = TRUE;
- for ( ;; )
- {
- if ( d >= 0 )
- {
- if ( FillBrushObj )
- PUTLINE ( x1, y1, x2, y1, FillBrushInst );
- if ( first )
- {
- if ( PenBrushObj )
- {
- if ( x1start > x1 )
- {
- PUTLINE ( x1, y1, x1start, y1, PenBrushInst );
- PUTLINE ( x2start+1, y2, x2+1, y2, PenBrushInst );
- }
- else
- {
- PUTPIXEL ( x1, y1, PenBrushInst );
- PUTPIXEL ( x2, y2, PenBrushInst );
- }
- }
- first = FALSE;
- }
- else
- {
- if ( FillBrushObj )
- PUTLINE ( x1, y2, x2, y2, FillBrushInst );
- if ( PenBrushObj )
- {
- if ( x1start >= x1 )
- {
- PUTLINE ( x1, y1, x1start+1, y1, PenBrushInst );
- PUTLINE ( x2start, y2, x2+1, y2, PenBrushInst );
- }
- else
- {
- PUTPIXEL ( x1, y1, PenBrushInst );
- PUTPIXEL ( x2, y2, PenBrushInst );
- }
- }
- }
- if ( PenBrushObj )
- {
- if ( x1start > x1 )
- {
- PUTLINE ( x1, y2, x1start+1, y2, PenBrushInst );
- PUTLINE ( x2start, y1, x2+1, y1, PenBrushInst );
- }
- else
- {
- PUTPIXEL ( x1, y2, PenBrushInst );
- PUTPIXEL ( x2, y1, PenBrushInst );
- }
- }
- x1start = x1-1;
- x2start = x2+1;
- row--, y1++, y2--, ddec -= four_a_square;
- d -= ddec;
- }
+ if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
- potential_steps = ( a_square * row ) / b_square - col + 1;
- while ( d < 0 && potential_steps-- )
- {
- d += dinc; /* two_b_square * (3 + (col << 1)); */
- col++, x1--, x2++, dinc += four_b_square;
- }
+ if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+ DC_vUpdateLineBrush(dc);
- if ( a_square * row <= b_square * col )
- break;
- };
+ pbrushLine = PEN_LockPen(pdcattr->hpen);
+ if (!pbrushLine)
+ {
+ /* Nothing to do, as we don't have a bitmap */
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ return FALSE;
+ }
- d = two_b_square * (col + 1) * col
- + two_a_square * (row * (row - 2) + 1)
- + (1 - two_a_square) * b_square;
- dinc = ddec; /* four_b_square * col; */
- ddec = two_a_square * ((row << 1) - 3);
+ PenOrigWidth = PenWidth = pbrushLine->ptPenWidth.x;
+ if (pbrushLine->ulPenStyle == PS_NULL) PenWidth = 0;
- while ( row )
+ if (pbrushLine->ulPenStyle == PS_INSIDEFRAME)
{
- if ( FillBrushObj )
- {
- PUTLINE ( x1, y1, x2, y1, FillBrushInst );
- PUTLINE ( x1, y2, x2, y2, FillBrushInst );
- }
- if ( PenBrushObj )
- {
- PUTPIXEL ( x2, y1, PenBrushInst );
- PUTPIXEL ( x1, y2, PenBrushInst );
- PUTPIXEL ( x2, y2, PenBrushInst );
- PUTPIXEL ( x1, y1, PenBrushInst );
- }
+ if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
+ if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
+ Left += PenWidth / 2;
+ Right -= (PenWidth - 1) / 2;
+ Top += PenWidth / 2;
+ Bottom -= (PenWidth - 1) / 2;
+ }
- if ( d <= 0 )
- {
- col++, x1--, x2++, dinc += four_b_square;
- d += dinc; //four_b_square * col;
- }
+ if (!PenWidth) PenWidth = 1;
+ pbrushLine->ptPenWidth.x = PenWidth;
- row--, y1++, y2--, ddec -= four_a_square;
- d -= ddec; //two_a_square * ((row << 1) - 3);
- }
+ RectBounds.left = Left;
+ RectBounds.top = Top;
+ RectBounds.right = Right;
+ RectBounds.bottom = Bottom;
- if ( FillBrushObj )
- {
- PUTLINE ( left, y1, right, y1, FillBrushInst );
- PUTLINE ( left, y2, right, y2, FillBrushInst );
- }
- if ( PenBrushObj )
- {
- if ( x1 > (left+1) )
- {
- PUTLINE ( left, y1, x1, y1, PenBrushInst );
- PUTLINE ( x2+1, y1, right, y1, PenBrushInst );
- PUTLINE ( left+1, y2, x1, y2, PenBrushInst );
- PUTLINE ( x2+1, y2, right+1, y2, PenBrushInst );
- }
- else
- {
- PUTPIXEL ( left, y1, PenBrushInst );
- PUTPIXEL ( right, y2, PenBrushInst );
- }
- }
+ IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
- x1 = left+xradius;
- x2 = right-xradius;
- y1 = top+yradius;
- y2 = bottom-yradius;
+ RectBounds.left += dc->ptlDCOrig.x;
+ RectBounds.top += dc->ptlDCOrig.y;
+ RectBounds.right += dc->ptlDCOrig.x;
+ RectBounds.bottom += dc->ptlDCOrig.y;
- if ( FillBrushObj )
+ pbrushFill = BRUSH_LockBrush(pdcattr->hbrush);
+ if (NULL == pbrushFill)
{
- for ( i = y1+1; i < y2; i++ )
- PUTLINE ( left, i, right, i, FillBrushInst );
- }
-
- if ( PenBrushObj )
+ DPRINT1("FillRound Fail\n");
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ ret = FALSE;
+ }
+ else
{
- PUTLINE ( x1, top, x2, top, PenBrushInst );
- PUTLINE ( right, y1, right, y2, PenBrushInst );
- PUTLINE ( x2, bottom, x1, bottom, PenBrushInst );
- PUTLINE ( left, y2, left, y1, PenBrushInst );
+ RtlCopyMemory(&brushTemp, pbrushFill, sizeof(brushTemp));
+ brushTemp.ptOrigin.x += RectBounds.left - Left;
+ brushTemp.ptOrigin.y += RectBounds.top - Top;
+ ret = IntFillRoundRect( dc,
+ RectBounds.left,
+ RectBounds.top,
+ RectBounds.right,
+ RectBounds.bottom,
+ xCurveDiameter,
+ yCurveDiameter,
+ &brushTemp);
+ BRUSH_UnlockBrush(pbrushFill);
}
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- if (PenBrushObj != NULL)
- PENOBJ_UnlockPen(PenBrushObj);
- if (FillBrushObj != NULL)
- BRUSHOBJ_UnlockBrush(FillBrushObj);
-
+ if (ret)
+ ret = IntDrawRoundRect( dc,
+ RectBounds.left,
+ RectBounds.top,
+ RectBounds.right,
+ RectBounds.bottom,
+ xCurveDiameter,
+ yCurveDiameter,
+ pbrushLine);
+
+ pbrushLine->ptPenWidth.x = PenOrigWidth;
+ PEN_UnlockPen(pbrushLine);
return ret;
}
BOOL
-STDCALL
+APIENTRY
NtGdiRoundRect(
HDC hDC,
int LeftRect,
DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
SetLastWin32Error(ERROR_INVALID_HANDLE);
}
- else if (dc->DC_Type == DC_TYPE_INFO)
+ else if (dc->dctype == DC_TYPE_INFO)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return ret;
}
-BOOL FASTCALL
-IntGdiGradientFill(
- DC *dc,
+BOOL
+NTAPI
+GreGradientFill(
+ HDC hdc,
PTRIVERTEX pVertex,
- ULONG uVertex,
+ ULONG nVertex,
PVOID pMesh,
- ULONG uMesh,
+ ULONG nMesh,
ULONG ulMode)
{
- BITMAPOBJ *BitmapObj;
- PPALGDI PalDestGDI;
- XLATEOBJ *XlateObj;
- RECTL Extent;
- POINTL DitherOrg;
- ULONG Mode, i;
- BOOL Ret;
+ PDC pdc;
+ SURFACE *psurf;
+ PPALETTE ppal;
+ EXLATEOBJ exlo;
+ RECTL rclExtent;
+ POINTL ptlDitherOrg;
+ ULONG i;
+ BOOL bRet;
HPALETTE hDestPalette;
- ASSERT(dc);
- ASSERT(pVertex);
- ASSERT(uVertex);
- ASSERT(pMesh);
- ASSERT(uMesh);
-
- /* check parameters */
- if (ulMode & GRADIENT_FILL_TRIANGLE)
+ /* Check parameters */
+ if (ulMode == GRADIENT_FILL_TRIANGLE)
{
- PGRADIENT_TRIANGLE tr = (PGRADIENT_TRIANGLE)pMesh;
+ PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
- for (i = 0; i < uMesh; i++, tr++)
+ for (i = 0; i < nMesh; i++, pTriangle++)
{
- if (tr->Vertex1 >= uVertex ||
- tr->Vertex2 >= uVertex ||
- tr->Vertex3 >= uVertex)
+ if (pTriangle->Vertex1 >= nVertex ||
+ pTriangle->Vertex2 >= nVertex ||
+ pTriangle->Vertex3 >= nVertex)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
else
{
- PGRADIENT_RECT rc = (PGRADIENT_RECT)pMesh;
- for (i = 0; i < uMesh; i++, rc++)
+ PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh;
+ for (i = 0; i < nMesh; i++, pRect++)
{
- if (rc->UpperLeft >= uVertex || rc->LowerRight >= uVertex)
+ if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
- /* calculate extent */
- Extent.left = Extent.right = pVertex->x;
- Extent.top = Extent.bottom = pVertex->y;
- for (i = 0; i < uVertex; i++)
+ /* Lock the output DC */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
{
- Extent.left = min(Extent.left, (pVertex + i)->x);
- Extent.right = max(Extent.right, (pVertex + i)->x);
- Extent.top = min(Extent.top, (pVertex + i)->y);
- Extent.bottom = max(Extent.bottom, (pVertex + i)->y);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
}
- DitherOrg.x = dc->ptlDCOrig.x;
- DitherOrg.y = dc->ptlDCOrig.y;
- Extent.left += DitherOrg.x;
- Extent.right += DitherOrg.x;
- Extent.top += DitherOrg.y;
- Extent.bottom += DitherOrg.y;
-
- BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
- /* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */
- ASSERT(BitmapObj);
+ if (pdc->dctype == DC_TYPE_INFO)
+ {
+ DC_UnlockDc(pdc);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
+ }
- hDestPalette = BitmapObj->hDIBPalette;
- if (!hDestPalette) hDestPalette = pPrimarySurface->DevInfo.hpalDefault;
+ psurf = pdc->dclevel.pSurface;
+ if (!psurf)
+ {
+ /* Memory DC with no surface selected */
+ DC_UnlockDc(pdc);
+ return TRUE; // CHECKME
+ }
- PalDestGDI = PALETTE_LockPalette(hDestPalette);
- if (PalDestGDI)
+ /* calculate extent */
+ rclExtent.left = rclExtent.right = pVertex->x;
+ rclExtent.top = rclExtent.bottom = pVertex->y;
+ for (i = 0; i < nVertex; i++)
{
- Mode = PalDestGDI->Mode;
- PALETTE_UnlockPalette(PalDestGDI);
+ rclExtent.left = min(rclExtent.left, (pVertex + i)->x);
+ rclExtent.right = max(rclExtent.right, (pVertex + i)->x);
+ rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
+ rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
}
- else
- Mode = PAL_RGB;
- XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, hDestPalette, NULL);
- ASSERT(XlateObj);
+ IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
+ rclExtent.left += pdc->ptlDCOrig.x;
+ rclExtent.right += pdc->ptlDCOrig.x;
+ rclExtent.top += pdc->ptlDCOrig.y;
+ rclExtent.bottom += pdc->ptlDCOrig.y;
- Ret = IntEngGradientFill(&BitmapObj->SurfObj,
- dc->CombinedClip,
- XlateObj,
- pVertex,
- uVertex,
- pMesh,
- uMesh,
- &Extent,
- &DitherOrg,
- ulMode);
+ ptlDitherOrg.x = ptlDitherOrg.y = 0;
+ IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
+ ptlDitherOrg.x += pdc->ptlDCOrig.x;
+ ptlDitherOrg.y += pdc->ptlDCOrig.y;
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- EngDeleteXlate(XlateObj);
+ hDestPalette = psurf->hDIBPalette;
+ if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
- return Ret;
+ ppal = PALETTE_LockPalette(hDestPalette);
+ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0, 0);
+
+ ASSERT(pdc->rosdc.CombinedClip);
+
+ bRet = IntEngGradientFill(&psurf->SurfObj,
+ pdc->rosdc.CombinedClip,
+ &exlo.xlo,
+ pVertex,
+ nVertex,
+ pMesh,
+ nMesh,
+ &rclExtent,
+ &ptlDitherOrg,
+ ulMode);
+
+ EXLATEOBJ_vCleanup(&exlo);
+
+ if (ppal)
+ PALETTE_UnlockPalette(ppal);
+
+ DC_UnlockDc(pdc);
+
+ return bRet;
}
BOOL
-STDCALL
+APIENTRY
NtGdiGradientFill(
HDC hdc,
PTRIVERTEX pVertex,
- ULONG uVertex,
+ ULONG nVertex,
PVOID pMesh,
- ULONG uMesh,
+ ULONG nMesh,
ULONG ulMode)
{
- DC *dc;
- BOOL Ret;
+ BOOL bRet;
PTRIVERTEX SafeVertex;
PVOID SafeMesh;
- ULONG SizeMesh;
- NTSTATUS Status = STATUS_SUCCESS;
+ ULONG cbVertex, cbMesh;
- dc = DC_LockDc(hdc);
- if (!dc)
+ /* Validate parameters */
+ if (!pVertex || !nVertex || !pMesh || !nMesh)
{
- 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 (!pVertex || !uVertex || !pMesh || !uMesh)
- {
- DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
{
case GRADIENT_FILL_RECT_H:
case GRADIENT_FILL_RECT_V:
- SizeMesh = uMesh * sizeof(GRADIENT_RECT);
+ cbMesh = nMesh * sizeof(GRADIENT_RECT);
break;
case GRADIENT_FILL_TRIANGLE:
- SizeMesh = uMesh * sizeof(TRIVERTEX);
+ cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE);
break;
default:
- DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
- _SEH_TRY
+ cbVertex = nVertex * sizeof(TRIVERTEX);
+ if (cbVertex + cbMesh <= cbVertex)
{
- ProbeForRead(pVertex,
- uVertex * sizeof(TRIVERTEX),
- 1);
- ProbeForRead(pMesh,
- SizeMesh,
- 1);
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- if (!NT_SUCCESS(Status))
- {
- DC_UnlockDc(dc);
- SetLastWin32Error(Status);
+ /* Overflow */
return FALSE;
}
- if (!(SafeVertex = ExAllocatePoolWithTag(PagedPool, (uVertex * sizeof(TRIVERTEX)) + SizeMesh, TAG_SHAPE)))
+ /* Allocate a kernel mode buffer */
+ SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
+ if (!SafeVertex)
{
- DC_UnlockDc(dc);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- SafeMesh = (PTRIVERTEX)(SafeVertex + uVertex);
+ SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex);
- _SEH_TRY
+ /* Copy the parameters to kernel mode */
+ _SEH2_TRY
{
- /* pointers were already probed! */
- RtlCopyMemory(SafeVertex,
- pVertex,
- uVertex * sizeof(TRIVERTEX));
- RtlCopyMemory(SafeMesh,
- pMesh,
- SizeMesh);
+ ProbeForRead(pVertex, cbVertex, 1);
+ ProbeForRead(pMesh, cbMesh, 1);
+ RtlCopyMemory(SafeVertex, pVertex, cbVertex);
+ RtlCopyMemory(SafeMesh, pMesh, cbMesh);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- Status = _SEH_GetExceptionCode();
+ ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(return FALSE;)
}
- _SEH_END;
+ _SEH2_END;
- if (!NT_SUCCESS(Status))
- {
- DC_UnlockDc(dc);
- ExFreePool(SafeVertex);
- SetLastNtError(Status);
- return FALSE;
- }
-
- Ret = IntGdiGradientFill(dc, SafeVertex, uVertex, SafeMesh, uMesh, ulMode);
+ /* Call the internal function */
+ bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode);
- DC_UnlockDc(dc);
- ExFreePool(SafeVertex);
- return Ret;
+ /* Cleanup and return result */
+ ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
+ return bRet;
}
-BOOL STDCALL
+BOOL APIENTRY
NtGdiExtFloodFill(
HDC hDC,
INT XStart,
COLORREF Color,
UINT FillType)
{
- DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
+ PDC dc;
+ PDC_ATTR pdcattr;
+ SURFACE *psurf = NULL;
+ HPALETTE hpal;
+ PPALETTE ppal;
+ EXLATEOBJ exlo;
+ BOOL Ret = FALSE;
+ RECTL DestRect;
+ POINTL Pt;
+ ULONG ConvColor;
- /* lie and say we succeded */
- return TRUE;
+ dc = DC_LockDc(hDC);
+ if (!dc)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (dc->dctype == DC_TYPE_INFO)
+ {
+ DC_UnlockDc(dc);
+ /* Yes, Windows really returns TRUE in this case */
+ return TRUE;
+ }
+
+ 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);
+
+ Pt.x = XStart;
+ Pt.y = YStart;
+ IntLPtoDP(dc, (LPPOINT)&Pt, 1);
+
+ Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y);
+ if (Ret)
+ IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect);
+ else
+ goto cleanup;
+
+ psurf = dc->dclevel.pSurface;
+ if (!psurf)
+ {
+ Ret = FALSE;
+ goto cleanup;
+ }
+
+ hpal = dc->dclevel.pSurface->hDIBPalette;
+ if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
+ ppal = PALETTE_ShareLockPalette(hpal);
+
+ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0xffffff, 0);
+
+ /* Only solid fills supported for now
+ * How to support pattern brushes and non standard surfaces (not offering dib functions):
+ * Version a (most likely slow): call DrvPatBlt for every pixel
+ * Version b: create a flood mask and let MaskBlt blit a masked brush */
+ ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
+ Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
+
+ EXLATEOBJ_vCleanup(&exlo);
+ PALETTE_ShareUnlockPalette(ppal);
+
+cleanup:
+ DC_UnlockDc(dc);
+ return Ret;
}
/* EOF */