2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * a couple macros to fill a single pixel or a line
28 #define PUTPIXEL(x,y,BrushInst) \
29 ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
31 &BrushInst.BrushObject, \
34 ROP2_TO_MIX(Dc_Attr->jROP2));
36 #define PUTLINE(x1,y1,x2,y2,BrushInst) \
37 ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
39 &BrushInst.BrushObject, \
42 ROP2_TO_MIX(Dc_Attr->jROP2));
44 #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
45 #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
47 BOOL FASTCALL
IntFillEllipse( PDC dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
);
48 BOOL FASTCALL
IntDrawEllipse( PDC dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
, PGDIBRUSHOBJ PenBrushObj
);
49 BOOL FASTCALL
IntFillRoundRect( PDC dc
, INT Left
, INT Top
, INT Right
, INT Bottom
, INT Wellipse
, INT Hellipse
);
50 BOOL FASTCALL
IntDrawRoundRect( PDC dc
, INT Left
, INT Top
, INT Right
, INT Bottom
, INT Wellipse
, INT Hellipse
, PGDIBRUSHOBJ PenBrushObj
);
58 PGDIBRUSHOBJ PenBrushObj
, FillBrushObj
;
59 GDIBRUSHINST PenBrushInst
, FillBrushInst
;
60 BOOL ret
= FALSE
; // default to failure
65 ASSERT(dc
); // caller's responsibility to pass a valid dc
67 if ( NULL
== UnsafePoints
|| Count
< 2 )
69 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
73 Dc_Attr
= dc
->pDc_Attr
;
74 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
76 /* Convert to screen coordinates */
77 IntLPtoDP(dc
, UnsafePoints
, Count
);
78 for (CurrentPoint
= 0; CurrentPoint
< Count
; CurrentPoint
++)
80 UnsafePoints
[CurrentPoint
].x
+= dc
->ptlDCOrig
.x
;
81 UnsafePoints
[CurrentPoint
].y
+= dc
->ptlDCOrig
.y
;
83 // No need to have path here.
85 DestRect
.left
= UnsafePoints
[0].x
;
86 DestRect
.right
= UnsafePoints
[0].x
;
87 DestRect
.top
= UnsafePoints
[0].y
;
88 DestRect
.bottom
= UnsafePoints
[0].y
;
90 for (CurrentPoint
= 1; CurrentPoint
< Count
; ++CurrentPoint
)
92 DestRect
.left
= min(DestRect
.left
, UnsafePoints
[CurrentPoint
].x
);
93 DestRect
.right
= max(DestRect
.right
, UnsafePoints
[CurrentPoint
].x
);
94 DestRect
.top
= min(DestRect
.top
, UnsafePoints
[CurrentPoint
].y
);
95 DestRect
.bottom
= max(DestRect
.bottom
, UnsafePoints
[CurrentPoint
].y
);
98 /* Special locking order to avoid lock-ups */
99 FillBrushObj
= BRUSHOBJ_LockBrush(Dc_Attr
->hbrush
);
100 PenBrushObj
= PENOBJ_LockPen(Dc_Attr
->hpen
);
101 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
102 /* FIXME - BitmapObj can be NULL!!!! don't assert but handle this case gracefully! */
105 /* Now fill the polygon with the current brush. */
106 if (FillBrushObj
&& !(FillBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
108 IntGdiInitBrushInstance(&FillBrushInst
, FillBrushObj
, dc
->XlateBrush
);
109 ret
= FillPolygon ( dc
, BitmapObj
, &FillBrushInst
.BrushObject
, ROP2_TO_MIX(Dc_Attr
->jROP2
), UnsafePoints
, Count
, DestRect
);
112 BRUSHOBJ_UnlockBrush(FillBrushObj
);
114 // Draw the Polygon Edges with the current pen ( if not a NULL pen )
115 if (PenBrushObj
&& !(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
119 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
121 for (i
= 0; i
< Count
-1; i
++)
124 // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
125 // UnsafePoints[0].x, UnsafePoints[0].y,
126 // UnsafePoints[1].x, UnsafePoints[1].y );
128 ret
= IntEngLineTo(&BitmapObj
->SurfObj
,
130 &PenBrushInst
.BrushObject
,
131 UnsafePoints
[i
].x
, /* From */
133 UnsafePoints
[i
+1].x
, /* To */
136 ROP2_TO_MIX(Dc_Attr
->jROP2
)); /* MIX */
139 /* Close the polygon */
142 ret
= IntEngLineTo(&BitmapObj
->SurfObj
,
144 &PenBrushInst
.BrushObject
,
145 UnsafePoints
[Count
-1].x
, /* From */
146 UnsafePoints
[Count
-1].y
,
147 UnsafePoints
[0].x
, /* To */
150 ROP2_TO_MIX(Dc_Attr
->jROP2
)); /* MIX */
154 PENOBJ_UnlockPen(PenBrushObj
);
156 BITMAPOBJ_UnlockBitmap(BitmapObj
);
162 IntGdiPolyPolygon(DC
*dc
,
167 if (PATH_IsPathOpen(dc
->DcLevel
))
168 return PATH_PolyPolygon ( dc
, Points
, PolyCounts
, Count
);
172 if (!IntGdiPolygon ( dc
, Points
, *PolyCounts
))
174 Points
+=*PolyCounts
++;
181 /******************************************************************************/
190 * This function uses optimized Bresenham's ellipse algorithm. It draws
191 * four lines of the ellipse in one pass.
206 PGDIBRUSHOBJ PenBrushObj
;
208 LONG PenWidth
, PenOrigWidth
;
209 LONG RadiusX
, RadiusY
, CenterX
, CenterY
;
211 if ((Left
== Right
) || (Top
== Bottom
)) return TRUE
;
216 SetLastWin32Error(ERROR_INVALID_HANDLE
);
219 if (dc
->DC_Type
== DC_TYPE_INFO
)
222 /* Yes, Windows really returns TRUE in this case */
226 if (PATH_IsPathOpen(dc
->DcLevel
))
228 ret
= PATH_Ellipse(dc
, Left
, Top
, Right
, Bottom
);
235 INT tmp
= Right
; Right
= Left
; Left
= tmp
;
239 INT tmp
= Bottom
; Bottom
= Top
; Top
= tmp
;
242 Dc_Attr
= dc
->pDc_Attr
;
243 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
245 PenBrushObj
= PENOBJ_LockPen(Dc_Attr
->hpen
);
246 if (NULL
== PenBrushObj
)
248 DPRINT1("Ellipse Fail 1\n");
250 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
254 PenOrigWidth
= PenWidth
= PenBrushObj
->ptPenWidth
.x
;
255 if (PenBrushObj
->ulPenStyle
== PS_NULL
) PenWidth
= 0;
257 if (PenBrushObj
->ulPenStyle
== PS_INSIDEFRAME
)
259 if (2*PenWidth
> (Right
- Left
)) PenWidth
= (Right
-Left
+ 1)/2;
260 if (2*PenWidth
> (Bottom
- Top
)) PenWidth
= (Bottom
-Top
+ 1)/2;
261 Left
+= PenWidth
/ 2;
262 Right
-= (PenWidth
- 1) / 2;
264 Bottom
-= (PenWidth
- 1) / 2;
267 if (!PenWidth
) PenWidth
= 1;
268 PenBrushObj
->ptPenWidth
.x
= PenWidth
;
270 RectBounds
.left
= Left
;
271 RectBounds
.right
= Right
;
272 RectBounds
.top
= Top
;
273 RectBounds
.bottom
= Bottom
;
275 IntLPtoDP(dc
, (LPPOINT
)&RectBounds
, 2);
277 RectBounds
.left
+= dc
->ptlDCOrig
.x
;
278 RectBounds
.right
+= dc
->ptlDCOrig
.x
;
279 RectBounds
.top
+= dc
->ptlDCOrig
.y
;
280 RectBounds
.bottom
+= dc
->ptlDCOrig
.y
;
282 // Setup for dynamic width and height.
283 RadiusX
= max((RectBounds
.right
- RectBounds
.left
) / 2, 2); // Needs room
284 RadiusY
= max((RectBounds
.bottom
- RectBounds
.top
) / 2, 2);
285 CenterX
= (RectBounds
.right
+ RectBounds
.left
) / 2;
286 CenterY
= (RectBounds
.bottom
+ RectBounds
.top
) / 2;
288 DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
289 RectBounds
.left
,RectBounds
.top
,RectBounds
.right
,RectBounds
.bottom
);
291 DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
292 CenterX
- RadiusX
, CenterY
+ RadiusY
, RadiusX
*2, RadiusY
*2);
294 ret
= IntFillEllipse( dc
,
298 RadiusY
*2); // Height
300 ret
= IntDrawEllipse( dc
,
307 PenBrushObj
->ptPenWidth
.x
= PenOrigWidth
;
308 PENOBJ_UnlockPen(PenBrushObj
);
310 DPRINT("Ellipse Exit.\n");
316 //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
317 //even-numbered polygon sides on each scan line. That is, GDI fills the area between the
318 //first and second side, between the third and fourth side, and so on.
320 //WINDING Selects winding mode (fills any region with a nonzero winding value).
321 //When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
322 //This value is defined as the number of times a pen used to draw the polygon would go around the region.
323 //The direction of each edge of the polygon is important.
325 extern BOOL
FillPolygon(PDC dc
,
338 NtGdiPolyPolyDraw( IN HDC hDC
,
340 IN PULONG PolyCounts
,
346 LPINT SafePolyPoints
;
347 NTSTATUS Status
= STATUS_SUCCESS
;
349 INT nPoints
, nEmpty
, nInvalid
, i
;
351 if (iFunc
== GdiPolyPolyRgn
)
353 return (ULONG_PTR
) GdiCreatePolyPolygonRgn((CONST PPOINT
) Points
,
354 (CONST PINT
) PolyCounts
,
361 SetLastWin32Error(ERROR_INVALID_HANDLE
);
364 if (dc
->DC_Type
== DC_TYPE_INFO
)
367 /* Yes, Windows really returns TRUE in this case */
376 Count
* sizeof(POINT
),
378 ProbeForRead(PolyCounts
,
384 Status
= _SEH_GetExceptionCode();
388 if (!NT_SUCCESS(Status
))
391 SetLastNtError(Status
);
395 SafePolyPoints
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(INT
), TAG_SHAPE
);
399 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
405 /* pointers already probed! */
406 RtlCopyMemory(SafePolyPoints
,
408 Count
* sizeof(INT
));
412 Status
= _SEH_GetExceptionCode();
416 if (!NT_SUCCESS(Status
))
419 ExFreePool(SafePolyPoints
);
420 SetLastNtError(Status
);
423 /* validate poligons */
427 for (i
= 0; i
< Count
; i
++)
429 if (SafePolyPoints
[i
] == 0)
433 if (SafePolyPoints
[i
] == 1)
437 nPoints
+= SafePolyPoints
[i
];
442 /* if all polygon counts are zero, return without setting a last error code. */
443 ExFreePool(SafePolyPoints
);
448 /* if at least one poly count is 1, fail */
449 ExFreePool(SafePolyPoints
);
450 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
454 Safept
= ExAllocatePoolWithTag(PagedPool
, nPoints
* sizeof(POINT
), TAG_SHAPE
);
458 ExFreePool(SafePolyPoints
);
459 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
465 /* pointers already probed! */
466 RtlCopyMemory(Safept
,
468 nPoints
* sizeof(POINT
));
472 Status
= _SEH_GetExceptionCode();
476 if (!NT_SUCCESS(Status
))
479 ExFreePool(SafePolyPoints
);
481 SetLastNtError(Status
);
488 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
495 Ret
= IntGdiPolyPolygon(dc
, Safept
, SafePolyPoints
, Count
);
497 case GdiPolyPolyLine
:
498 Ret
= IntGdiPolyPolyline(dc
, Safept
, (LPDWORD
) SafePolyPoints
, Count
);
501 Ret
= IntGdiPolyBezier(dc
, Safept
, *PolyCounts
);
504 Ret
= IntGdiPolylineTo(dc
, Safept
, *PolyCounts
);
506 case GdiPolyBezierTo
:
507 Ret
= IntGdiPolyBezierTo(dc
, Safept
, *PolyCounts
);
510 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
513 ExFreePool(SafePolyPoints
);
517 return (ULONG_PTR
) Ret
;
529 BITMAPOBJ
*BitmapObj
= NULL
;
530 PGDIBRUSHOBJ PenBrushObj
= NULL
, FillBrushObj
= NULL
;
531 GDIBRUSHINST PenBrushInst
, FillBrushInst
;
532 BOOL ret
= FALSE
; // default to failure
537 ASSERT ( dc
); // caller's responsibility to set this up
539 Dc_Attr
= dc
->pDc_Attr
;
540 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
542 /* Do we rotate or shear? */
543 // if (!(dc->DcLevel.mxWorldToDevice.flAccel & MXACC_DIAGONAL))
544 if (dc
->DcLevel
.xformWorld2Vport
.eM12
!= 0. || dc
->DcLevel
.xformWorld2Vport
.eM21
!= 0.)
546 POINTL DestCoords
[4];
547 DestCoords
[0].x
= DestCoords
[3].x
= LeftRect
;
548 DestCoords
[0].y
= DestCoords
[1].y
= TopRect
;
549 DestCoords
[1].x
= DestCoords
[2].x
= RightRect
;
550 DestCoords
[2].y
= DestCoords
[3].y
= BottomRect
;
551 return IntGdiPolygon(dc
, DestCoords
, 4);
554 if ( PATH_IsPathOpen(dc
->DcLevel
) )
556 return PATH_Rectangle ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
);
559 DestRect
.left
= LeftRect
;
560 DestRect
.right
= RightRect
;
561 DestRect
.top
= TopRect
;
562 DestRect
.bottom
= BottomRect
;
564 IntLPtoDP(dc
, (LPPOINT
)&DestRect
, 2);
566 DestRect
.left
+= dc
->ptlDCOrig
.x
;
567 DestRect
.right
+= dc
->ptlDCOrig
.x
;
568 DestRect
.top
+= dc
->ptlDCOrig
.y
;
569 DestRect
.bottom
+= dc
->ptlDCOrig
.y
;
571 /* In GM_COMPATIBLE, don't include bottom and right edges */
572 if (IntGetGraphicsMode(dc
) == GM_COMPATIBLE
)
578 /* Special locking order to avoid lock-ups! */
579 FillBrushObj
= BRUSHOBJ_LockBrush(Dc_Attr
->hbrush
);
580 PenBrushObj
= PENOBJ_LockPen(Dc_Attr
->hpen
);
586 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
595 if (!(FillBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
597 IntGdiInitBrushInstance(&FillBrushInst
, FillBrushObj
, dc
->XlateBrush
);
598 ret
= IntEngBitBlt(&BitmapObj
->SurfObj
,
606 &FillBrushInst
.BrushObject
,
608 ROP3_TO_ROP4(PATCOPY
));
612 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
614 // Draw the rectangle with the current pen
616 ret
= TRUE
; // change default to success
618 if (!(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
620 Mix
= ROP2_TO_MIX(Dc_Attr
->jROP2
);
621 ret
= ret
&& IntEngLineTo(&BitmapObj
->SurfObj
,
623 &PenBrushInst
.BrushObject
,
624 DestRect
.left
, DestRect
.top
, DestRect
.right
, DestRect
.top
,
625 &DestRect
, // Bounding rectangle
628 ret
= ret
&& IntEngLineTo(&BitmapObj
->SurfObj
,
630 &PenBrushInst
.BrushObject
,
631 DestRect
.right
, DestRect
.top
, DestRect
.right
, DestRect
.bottom
,
632 &DestRect
, // Bounding rectangle
635 ret
= ret
&& IntEngLineTo(&BitmapObj
->SurfObj
,
637 &PenBrushInst
.BrushObject
,
638 DestRect
.right
, DestRect
.bottom
, DestRect
.left
, DestRect
.bottom
,
639 &DestRect
, // Bounding rectangle
642 ret
= ret
&& IntEngLineTo(&BitmapObj
->SurfObj
,
644 &PenBrushInst
.BrushObject
,
645 DestRect
.left
, DestRect
.bottom
, DestRect
.left
, DestRect
.top
,
646 &DestRect
, // Bounding rectangle
652 BRUSHOBJ_UnlockBrush(FillBrushObj
);
655 PENOBJ_UnlockPen(PenBrushObj
);
658 BITMAPOBJ_UnlockBitmap(BitmapObj
);
660 /* Move current position in DC?
661 MSDN: The current position is neither used nor updated by Rectangle. */
668 NtGdiRectangle(HDC hDC
,
675 BOOL ret
; // default to failure
680 SetLastWin32Error(ERROR_INVALID_HANDLE
);
683 if (dc
->DC_Type
== DC_TYPE_INFO
)
686 /* Yes, Windows really returns TRUE in this case */
690 ret
= IntRectangle ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
);
709 PGDIBRUSHOBJ PenBrushObj
;
711 LONG PenWidth
, PenOrigWidth
;
712 BOOL ret
= TRUE
; // default to success
714 ASSERT ( dc
); // caller's responsibility to set this up
716 if ( PATH_IsPathOpen(dc
->DcLevel
) )
717 return PATH_RoundRect ( dc
, Left
, Top
, Right
, Bottom
,
718 xCurveDiameter
, yCurveDiameter
);
720 if ((Left
== Right
) || (Top
== Bottom
)) return TRUE
;
722 xCurveDiameter
= max(abs( xCurveDiameter
), 1);
723 yCurveDiameter
= max(abs( yCurveDiameter
), 1);
727 INT tmp
= Right
; Right
= Left
; Left
= tmp
;
731 INT tmp
= Bottom
; Bottom
= Top
; Top
= tmp
;
734 Dc_Attr
= dc
->pDc_Attr
;
735 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
737 PenBrushObj
= PENOBJ_LockPen(Dc_Attr
->hpen
);
740 /* Nothing to do, as we don't have a bitmap */
741 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
745 PenOrigWidth
= PenWidth
= PenBrushObj
->ptPenWidth
.x
;
746 if (PenBrushObj
->ulPenStyle
== PS_NULL
) PenWidth
= 0;
748 if (PenBrushObj
->ulPenStyle
== PS_INSIDEFRAME
)
750 if (2*PenWidth
> (Right
- Left
)) PenWidth
= (Right
-Left
+ 1)/2;
751 if (2*PenWidth
> (Bottom
- Top
)) PenWidth
= (Bottom
-Top
+ 1)/2;
752 Left
+= PenWidth
/ 2;
753 Right
-= (PenWidth
- 1) / 2;
755 Bottom
-= (PenWidth
- 1) / 2;
758 if (!PenWidth
) PenWidth
= 1;
759 PenBrushObj
->ptPenWidth
.x
= PenWidth
;
761 RectBounds
.left
= Left
;
762 RectBounds
.top
= Top
;
763 RectBounds
.right
= Right
;
764 RectBounds
.bottom
= Bottom
;
766 IntLPtoDP(dc
, (LPPOINT
)&RectBounds
, 2);
768 RectBounds
.left
+= dc
->ptlDCOrig
.x
;
769 RectBounds
.top
+= dc
->ptlDCOrig
.y
;
770 RectBounds
.right
+= dc
->ptlDCOrig
.x
;
771 RectBounds
.bottom
+= dc
->ptlDCOrig
.y
;
773 ret
= IntFillRoundRect( dc
,
781 ret
= IntDrawRoundRect( dc
,
790 PenBrushObj
->ptPenWidth
.x
= PenOrigWidth
;
791 PENOBJ_UnlockPen(PenBrushObj
);
806 DC
*dc
= DC_LockDc(hDC
);
807 BOOL ret
= FALSE
; /* default to failure */
809 DPRINT("NtGdiRoundRect(0x%x,%i,%i,%i,%i,%i,%i)\n",hDC
,LeftRect
,TopRect
,RightRect
,BottomRect
,Width
,Height
);
812 DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
813 SetLastWin32Error(ERROR_INVALID_HANDLE
);
815 else if (dc
->DC_Type
== DC_TYPE_INFO
)
818 /* Yes, Windows really returns TRUE in this case */
823 ret
= IntRoundRect ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
, Width
, Height
);
839 BITMAPOBJ
*BitmapObj
;
846 HPALETTE hDestPalette
;
854 /* check parameters */
855 if (ulMode
& GRADIENT_FILL_TRIANGLE
)
857 PGRADIENT_TRIANGLE tr
= (PGRADIENT_TRIANGLE
)pMesh
;
859 for (i
= 0; i
< uMesh
; i
++, tr
++)
861 if (tr
->Vertex1
>= uVertex
||
862 tr
->Vertex2
>= uVertex
||
863 tr
->Vertex3
>= uVertex
)
865 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
872 PGRADIENT_RECT rc
= (PGRADIENT_RECT
)pMesh
;
873 for (i
= 0; i
< uMesh
; i
++, rc
++)
875 if (rc
->UpperLeft
>= uVertex
|| rc
->LowerRight
>= uVertex
)
877 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
883 /* calculate extent */
884 Extent
.left
= Extent
.right
= pVertex
->x
;
885 Extent
.top
= Extent
.bottom
= pVertex
->y
;
886 for (i
= 0; i
< uVertex
; i
++)
888 Extent
.left
= min(Extent
.left
, (pVertex
+ i
)->x
);
889 Extent
.right
= max(Extent
.right
, (pVertex
+ i
)->x
);
890 Extent
.top
= min(Extent
.top
, (pVertex
+ i
)->y
);
891 Extent
.bottom
= max(Extent
.bottom
, (pVertex
+ i
)->y
);
894 DitherOrg
.x
= dc
->ptlDCOrig
.x
;
895 DitherOrg
.y
= dc
->ptlDCOrig
.y
;
896 Extent
.left
+= DitherOrg
.x
;
897 Extent
.right
+= DitherOrg
.x
;
898 Extent
.top
+= DitherOrg
.y
;
899 Extent
.bottom
+= DitherOrg
.y
;
901 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
902 /* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */
905 hDestPalette
= BitmapObj
->hDIBPalette
;
906 if (!hDestPalette
) hDestPalette
= pPrimarySurface
->DevInfo
.hpalDefault
;
908 PalDestGDI
= PALETTE_LockPalette(hDestPalette
);
911 Mode
= PalDestGDI
->Mode
;
912 PALETTE_UnlockPalette(PalDestGDI
);
917 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(Mode
, PAL_RGB
, hDestPalette
, NULL
);
920 Ret
= IntEngGradientFill(&BitmapObj
->SurfObj
,
931 BITMAPOBJ_UnlockBitmap(BitmapObj
);
932 EngDeleteXlate(XlateObj
);
949 PTRIVERTEX SafeVertex
;
952 NTSTATUS Status
= STATUS_SUCCESS
;
957 SetLastWin32Error(ERROR_INVALID_HANDLE
);
960 if (dc
->DC_Type
== DC_TYPE_INFO
)
963 /* Yes, Windows really returns TRUE in this case */
966 if (!pVertex
|| !uVertex
|| !pMesh
|| !uMesh
)
969 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
975 case GRADIENT_FILL_RECT_H
:
976 case GRADIENT_FILL_RECT_V
:
977 SizeMesh
= uMesh
* sizeof(GRADIENT_RECT
);
979 case GRADIENT_FILL_TRIANGLE
:
980 SizeMesh
= uMesh
* sizeof(TRIVERTEX
);
984 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
990 ProbeForRead(pVertex
,
991 uVertex
* sizeof(TRIVERTEX
),
999 Status
= _SEH_GetExceptionCode();
1003 if (!NT_SUCCESS(Status
))
1006 SetLastWin32Error(Status
);
1010 if (!(SafeVertex
= ExAllocatePoolWithTag(PagedPool
, (uVertex
* sizeof(TRIVERTEX
)) + SizeMesh
, TAG_SHAPE
)))
1013 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1017 SafeMesh
= (PTRIVERTEX
)(SafeVertex
+ uVertex
);
1021 /* pointers were already probed! */
1022 RtlCopyMemory(SafeVertex
,
1024 uVertex
* sizeof(TRIVERTEX
));
1025 RtlCopyMemory(SafeMesh
,
1031 Status
= _SEH_GetExceptionCode();
1035 if (!NT_SUCCESS(Status
))
1038 ExFreePool(SafeVertex
);
1039 SetLastNtError(Status
);
1043 Ret
= IntGdiGradientFill(dc
, SafeVertex
, uVertex
, SafeMesh
, uMesh
, ulMode
);
1046 ExFreePool(SafeVertex
);
1058 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
1060 /* lie and say we succeded */