xref: /reactos/win32ss/gdi/ntgdi/fillshap.c (revision 4a17d4b0)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS win32 kernel mode subsystem
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            win32ss/gdi/ntgdi/fillshap.c
5c2c66affSColin Finck  * PURPOSE:         fillshap
6c2c66affSColin Finck  * PROGRAMMER:
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include <win32k.h>
10c2c66affSColin Finck 
11c2c66affSColin Finck #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck 
14c2c66affSColin Finck #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
15c2c66affSColin Finck #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
16c2c66affSColin Finck 
17c2c66affSColin Finck BOOL FASTCALL
IntGdiPolygon(PDC dc,PPOINT Points,int Count)18c2c66affSColin Finck IntGdiPolygon(PDC    dc,
19c2c66affSColin Finck               PPOINT Points,
20c2c66affSColin Finck               int    Count)
21c2c66affSColin Finck {
22c2c66affSColin Finck     SURFACE *psurf;
23c2c66affSColin Finck     PBRUSH pbrLine, pbrFill;
24c2c66affSColin Finck     BOOL ret = FALSE; // Default to failure
25c2c66affSColin Finck     RECTL DestRect;
26*6358c4acSKatayama Hirofumi MZ     INT i, CurrentPoint;
27c2c66affSColin Finck     PDC_ATTR pdcattr;
28c2c66affSColin Finck     POINTL BrushOrigin;
29*6358c4acSKatayama Hirofumi MZ     PPATH pPath;
30c2c66affSColin Finck //    int Left;
31c2c66affSColin Finck //    int Top;
32c2c66affSColin Finck 
33c2c66affSColin Finck     ASSERT(dc); // Caller's responsibility to pass a valid dc
34c2c66affSColin Finck 
35c2c66affSColin Finck     if (!Points || Count < 2 )
36c2c66affSColin Finck     {
37c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
38c2c66affSColin Finck         return FALSE;
39c2c66affSColin Finck     }
40c2c66affSColin Finck 
41c2c66affSColin Finck /*
42c2c66affSColin Finck     // Find start x, y
43c2c66affSColin Finck     Left = Points[0].x;
44c2c66affSColin Finck     Top  = Points[0].y;
45c2c66affSColin Finck     for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
46c2c66affSColin Finck       Left = min(Left, Points[CurrentPoint].x);
47c2c66affSColin Finck       Top  = min(Top, Points[CurrentPoint].y);
48c2c66affSColin Finck     }
49c2c66affSColin Finck */
50c2c66affSColin Finck 
51c2c66affSColin Finck     pdcattr = dc->pdcattr;
52c2c66affSColin Finck 
53c2c66affSColin Finck     /* Convert to screen coordinates */
54c2c66affSColin Finck     IntLPtoDP(dc, Points, Count);
55c2c66affSColin Finck     for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
56c2c66affSColin Finck     {
57c2c66affSColin Finck         Points[CurrentPoint].x += dc->ptlDCOrig.x;
58c2c66affSColin Finck         Points[CurrentPoint].y += dc->ptlDCOrig.y;
59c2c66affSColin Finck     }
60c2c66affSColin Finck     // No need to have path here.
61c2c66affSColin Finck     {
62c2c66affSColin Finck         DestRect.left   = Points[0].x;
63c2c66affSColin Finck         DestRect.right  = Points[0].x;
64c2c66affSColin Finck         DestRect.top    = Points[0].y;
65c2c66affSColin Finck         DestRect.bottom = Points[0].y;
66c2c66affSColin Finck 
67c2c66affSColin Finck         for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
68c2c66affSColin Finck         {
69c2c66affSColin Finck             DestRect.left     = min(DestRect.left, Points[CurrentPoint].x);
70c2c66affSColin Finck             DestRect.right    = max(DestRect.right, Points[CurrentPoint].x);
71c2c66affSColin Finck             DestRect.top      = min(DestRect.top, Points[CurrentPoint].y);
72c2c66affSColin Finck             DestRect.bottom   = max(DestRect.bottom, Points[CurrentPoint].y);
73c2c66affSColin Finck         }
74c2c66affSColin Finck 
75c2c66affSColin Finck         if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
76c2c66affSColin Finck             DC_vUpdateFillBrush(dc);
77c2c66affSColin Finck 
78c2c66affSColin Finck         if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
79c2c66affSColin Finck             DC_vUpdateLineBrush(dc);
80c2c66affSColin Finck 
81c2c66affSColin Finck         /* Special locking order to avoid lock-ups */
82c2c66affSColin Finck         pbrFill = dc->dclevel.pbrFill;
83c2c66affSColin Finck         pbrLine = dc->dclevel.pbrLine;
84c2c66affSColin Finck         psurf = dc->dclevel.pSurface;
85c2c66affSColin Finck         if (psurf == NULL)
86c2c66affSColin Finck         {
87c2c66affSColin Finck             /* Memory DC without a bitmap selected, nothing to do. */
88c2c66affSColin Finck             return TRUE;
89c2c66affSColin Finck         }
90c2c66affSColin Finck 
91c2c66affSColin Finck         /* Now fill the polygon with the current fill brush. */
92c2c66affSColin Finck         if (!(pbrFill->flAttrs & BR_IS_NULL))
93c2c66affSColin Finck         {
94c2c66affSColin Finck             BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
95c2c66affSColin Finck             BrushOrigin.x += dc->ptlDCOrig.x;
96c2c66affSColin Finck             BrushOrigin.y += dc->ptlDCOrig.y;
97c2c66affSColin Finck             ret = IntFillPolygon (dc,
98c2c66affSColin Finck                                   psurf,
99c2c66affSColin Finck                                   &dc->eboFill.BrushObject,
100c2c66affSColin Finck                                   Points,
101c2c66affSColin Finck                                   Count,
102c2c66affSColin Finck                                   DestRect,
103c2c66affSColin Finck                                   &BrushOrigin);
104c2c66affSColin Finck         }
105c2c66affSColin Finck 
106c2c66affSColin Finck         // Draw the Polygon Edges with the current pen ( if not a NULL pen )
107c2c66affSColin Finck         if (!(pbrLine->flAttrs & BR_IS_NULL))
108c2c66affSColin Finck         {
109*6358c4acSKatayama Hirofumi MZ             if (IntIsEffectiveWidePen(pbrLine))
110*6358c4acSKatayama Hirofumi MZ             {
111*6358c4acSKatayama Hirofumi MZ                 /* Clear the path */
112*6358c4acSKatayama Hirofumi MZ                 PATH_Delete(dc->dclevel.hPath);
113*6358c4acSKatayama Hirofumi MZ                 dc->dclevel.hPath = NULL;
114c2c66affSColin Finck 
115*6358c4acSKatayama Hirofumi MZ                 /* Begin a path */
116*6358c4acSKatayama Hirofumi MZ                 pPath = PATH_CreatePath(Count + 1);
117*6358c4acSKatayama Hirofumi MZ                 dc->dclevel.flPath |= DCPATH_ACTIVE;
118*6358c4acSKatayama Hirofumi MZ                 dc->dclevel.hPath = pPath->BaseObject.hHmgr;
119*6358c4acSKatayama Hirofumi MZ                 pPath->pos = Points[0];
120*6358c4acSKatayama Hirofumi MZ                 IntLPtoDP(dc, &pPath->pos, 1);
121*6358c4acSKatayama Hirofumi MZ 
122*6358c4acSKatayama Hirofumi MZ                 PATH_MoveTo(dc, pPath);
123*6358c4acSKatayama Hirofumi MZ                 for (i = 1; i < Count; ++i)
124*6358c4acSKatayama Hirofumi MZ                 {
125*6358c4acSKatayama Hirofumi MZ                     PATH_LineTo(dc, Points[i].x, Points[i].y);
126*6358c4acSKatayama Hirofumi MZ                 }
127*6358c4acSKatayama Hirofumi MZ                 PATH_LineTo(dc, Points[0].x, Points[0].y);
128*6358c4acSKatayama Hirofumi MZ 
129*6358c4acSKatayama Hirofumi MZ                 /* Close the path */
130*6358c4acSKatayama Hirofumi MZ                 pPath->state = PATH_Closed;
131*6358c4acSKatayama Hirofumi MZ                 dc->dclevel.flPath &= ~DCPATH_ACTIVE;
132*6358c4acSKatayama Hirofumi MZ 
133*6358c4acSKatayama Hirofumi MZ                 /* Actually stroke a path */
134*6358c4acSKatayama Hirofumi MZ                 ret = PATH_StrokePath(dc, pPath);
135*6358c4acSKatayama Hirofumi MZ 
136*6358c4acSKatayama Hirofumi MZ                 /* Clear the path */
137*6358c4acSKatayama Hirofumi MZ                 PATH_UnlockPath(pPath);
138*6358c4acSKatayama Hirofumi MZ                 PATH_Delete(dc->dclevel.hPath);
139*6358c4acSKatayama Hirofumi MZ                 dc->dclevel.hPath = NULL;
140*6358c4acSKatayama Hirofumi MZ             }
141*6358c4acSKatayama Hirofumi MZ             else
142*6358c4acSKatayama Hirofumi MZ             {
143c2c66affSColin Finck                 for (i = 0; i < Count-1; i++)
144c2c66affSColin Finck                 {
145c2c66affSColin Finck // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
146c2c66affSColin Finck //                                 Points[0].x, Points[0].y,
147c2c66affSColin Finck //                                 Points[1].x, Points[1].y );
148c2c66affSColin Finck 
149c2c66affSColin Finck                     ret = IntEngLineTo(&psurf->SurfObj,
150c2c66affSColin Finck                                        (CLIPOBJ *)&dc->co,
151c2c66affSColin Finck                                        &dc->eboLine.BrushObject,
152c2c66affSColin Finck                                        Points[i].x,          /* From */
153c2c66affSColin Finck                                        Points[i].y,
154c2c66affSColin Finck                                        Points[i+1].x,        /* To */
155c2c66affSColin Finck                                        Points[i+1].y,
156c2c66affSColin Finck                                        &DestRect,
157c2c66affSColin Finck                                        ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
158c2c66affSColin Finck                     if (!ret) break;
159c2c66affSColin Finck                 }
160c2c66affSColin Finck                 /* Close the polygon */
161c2c66affSColin Finck                 if (ret)
162c2c66affSColin Finck                 {
163c2c66affSColin Finck                     ret = IntEngLineTo(&psurf->SurfObj,
164c2c66affSColin Finck                                        (CLIPOBJ *)&dc->co,
165c2c66affSColin Finck                                        &dc->eboLine.BrushObject,
166c2c66affSColin Finck                                        Points[Count-1].x, /* From */
167c2c66affSColin Finck                                        Points[Count-1].y,
168c2c66affSColin Finck                                        Points[0].x,       /* To */
169c2c66affSColin Finck                                        Points[0].y,
170c2c66affSColin Finck                                        &DestRect,
171c2c66affSColin Finck                                        ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
172c2c66affSColin Finck                 }
173c2c66affSColin Finck             }
174c2c66affSColin Finck         }
175*6358c4acSKatayama Hirofumi MZ     }
176c2c66affSColin Finck 
177c2c66affSColin Finck     return ret;
178c2c66affSColin Finck }
179c2c66affSColin Finck 
180c2c66affSColin Finck BOOL FASTCALL
IntGdiPolyPolygon(DC * dc,LPPOINT Points,PULONG PolyCounts,int Count)181c2c66affSColin Finck IntGdiPolyPolygon(DC      *dc,
182c2c66affSColin Finck                   LPPOINT Points,
183c2c66affSColin Finck                   PULONG  PolyCounts,
184c2c66affSColin Finck                   int     Count)
185c2c66affSColin Finck {
186c2c66affSColin Finck     if (PATH_IsPathOpen(dc->dclevel))
187c2c66affSColin Finck         return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
188c2c66affSColin Finck 
189c2c66affSColin Finck     while (--Count >=0)
190c2c66affSColin Finck     {
191c2c66affSColin Finck         if (!IntGdiPolygon ( dc, Points, *PolyCounts ))
192c2c66affSColin Finck             return FALSE;
193c2c66affSColin Finck         Points+=*PolyCounts++;
194c2c66affSColin Finck     }
195c2c66affSColin Finck     return TRUE;
196c2c66affSColin Finck }
197c2c66affSColin Finck 
198c2c66affSColin Finck BOOL FASTCALL
IntPolygon(HDC hdc,POINT * Point,int Count)199c2c66affSColin Finck IntPolygon(HDC hdc, POINT *Point, int Count)
200c2c66affSColin Finck {
201c2c66affSColin Finck     BOOL bResult;
202c2c66affSColin Finck     PDC pdc;
203c2c66affSColin Finck 
204c2c66affSColin Finck     pdc = DC_LockDc(hdc);
205c2c66affSColin Finck     if (pdc == NULL)
206c2c66affSColin Finck     {
207c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
208c2c66affSColin Finck         return FALSE;
209c2c66affSColin Finck     }
210c2c66affSColin Finck 
211c2c66affSColin Finck     bResult = IntGdiPolygon(pdc, Point, Count);
212c2c66affSColin Finck 
213c2c66affSColin Finck     DC_UnlockDc(pdc);
214c2c66affSColin Finck     return bResult;
215c2c66affSColin Finck }
216c2c66affSColin Finck 
217c2c66affSColin Finck 
218c2c66affSColin Finck /******************************************************************************/
219c2c66affSColin Finck 
220c2c66affSColin Finck /*
221c2c66affSColin Finck  * NtGdiEllipse
222c2c66affSColin Finck  *
223c2c66affSColin Finck  * Author
224c2c66affSColin Finck  *    Filip Navara
225c2c66affSColin Finck  *
226c2c66affSColin Finck  * Remarks
227c2c66affSColin Finck  *    This function uses optimized Bresenham's ellipse algorithm. It draws
228c2c66affSColin Finck  *    four lines of the ellipse in one pass.
229c2c66affSColin Finck  *
230c2c66affSColin Finck  */
231c2c66affSColin Finck 
232c2c66affSColin Finck BOOL APIENTRY
NtGdiEllipse(HDC hDC,int Left,int Top,int Right,int Bottom)233c2c66affSColin Finck NtGdiEllipse(
234c2c66affSColin Finck     HDC hDC,
235c2c66affSColin Finck     int Left,
236c2c66affSColin Finck     int Top,
237c2c66affSColin Finck     int Right,
238c2c66affSColin Finck     int Bottom)
239c2c66affSColin Finck {
240c2c66affSColin Finck     PDC dc;
241c2c66affSColin Finck     PDC_ATTR pdcattr;
242c2c66affSColin Finck     RECTL RectBounds;
243c2c66affSColin Finck     PBRUSH pbrush;
244c2c66affSColin Finck     BOOL ret = TRUE;
245c2c66affSColin Finck     LONG PenWidth, PenOrigWidth;
246c2c66affSColin Finck     LONG RadiusX, RadiusY, CenterX, CenterY;
247c2c66affSColin Finck     PBRUSH pFillBrushObj;
248c2c66affSColin Finck     BRUSH tmpFillBrushObj;
249c2c66affSColin Finck 
250c2c66affSColin Finck     dc = DC_LockDc(hDC);
251c2c66affSColin Finck     if (dc == NULL)
252c2c66affSColin Finck     {
253c2c66affSColin Finck        EngSetLastError(ERROR_INVALID_HANDLE);
254c2c66affSColin Finck        return FALSE;
255c2c66affSColin Finck     }
256c2c66affSColin Finck 
257c2c66affSColin Finck     if (PATH_IsPathOpen(dc->dclevel))
258c2c66affSColin Finck     {
259c2c66affSColin Finck         ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
260c2c66affSColin Finck         DC_UnlockDc(dc);
261c2c66affSColin Finck         return ret;
262c2c66affSColin Finck     }
263c2c66affSColin Finck 
264c2c66affSColin Finck     ////
265c2c66affSColin Finck     //// Could this use PATH_CheckCorners ?
266c2c66affSColin Finck     ////
267c2c66affSColin Finck     if ((Left == Right) || (Top == Bottom))
268c2c66affSColin Finck     {
269c2c66affSColin Finck        DC_UnlockDc(dc);
270c2c66affSColin Finck        return TRUE;
271c2c66affSColin Finck     }
272c2c66affSColin Finck 
273c2c66affSColin Finck     if (Right < Left)
274c2c66affSColin Finck     {
275c2c66affSColin Finck        INT tmp = Right; Right = Left; Left = tmp;
276c2c66affSColin Finck     }
277c2c66affSColin Finck     if (Bottom < Top)
278c2c66affSColin Finck     {
279c2c66affSColin Finck        INT tmp = Bottom; Bottom = Top; Top = tmp;
280c2c66affSColin Finck     }
281c2c66affSColin Finck     ////
282c2c66affSColin Finck 
283c2c66affSColin Finck     pdcattr = dc->pdcattr;
284c2c66affSColin Finck 
285c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
286c2c66affSColin Finck         DC_vUpdateFillBrush(dc);
287c2c66affSColin Finck 
288c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
289c2c66affSColin Finck         DC_vUpdateLineBrush(dc);
290c2c66affSColin Finck 
291c2c66affSColin Finck     pbrush = PEN_ShareLockPen(pdcattr->hpen);
292c2c66affSColin Finck     if (!pbrush)
293c2c66affSColin Finck     {
294c2c66affSColin Finck         DPRINT1("Ellipse Fail 1\n");
295c2c66affSColin Finck         DC_UnlockDc(dc);
296c2c66affSColin Finck         EngSetLastError(ERROR_INTERNAL_ERROR);
297c2c66affSColin Finck         return FALSE;
298c2c66affSColin Finck     }
299c2c66affSColin Finck 
300c2c66affSColin Finck     PenOrigWidth = PenWidth = pbrush->lWidth;
301c2c66affSColin Finck     if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0;
302c2c66affSColin Finck 
303c2c66affSColin Finck     if (pbrush->ulPenStyle == PS_INSIDEFRAME)
304c2c66affSColin Finck     {
305c2c66affSColin Finck        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
306c2c66affSColin Finck        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
307c2c66affSColin Finck        Left   += PenWidth / 2;
308c2c66affSColin Finck        Right  -= (PenWidth - 1) / 2;
309c2c66affSColin Finck        Top    += PenWidth / 2;
310c2c66affSColin Finck        Bottom -= (PenWidth - 1) / 2;
311c2c66affSColin Finck     }
312c2c66affSColin Finck 
313c2c66affSColin Finck     if (!PenWidth) PenWidth = 1;
314c2c66affSColin Finck     pbrush->lWidth = PenWidth;
315c2c66affSColin Finck 
316c2c66affSColin Finck     RectBounds.left   = Left;
317c2c66affSColin Finck     RectBounds.right  = Right;
318c2c66affSColin Finck     RectBounds.top    = Top;
319c2c66affSColin Finck     RectBounds.bottom = Bottom;
320c2c66affSColin Finck 
321c2c66affSColin Finck     IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
322c2c66affSColin Finck 
323c2c66affSColin Finck     RectBounds.left += dc->ptlDCOrig.x;
324c2c66affSColin Finck     RectBounds.right += dc->ptlDCOrig.x;
325c2c66affSColin Finck     RectBounds.top += dc->ptlDCOrig.y;
326c2c66affSColin Finck     RectBounds.bottom += dc->ptlDCOrig.y;
327c2c66affSColin Finck 
328c2c66affSColin Finck     // Setup for dynamic width and height.
329c2c66affSColin Finck     RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room
330c2c66affSColin Finck     RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2);
331c2c66affSColin Finck     CenterX = (RectBounds.right + RectBounds.left) / 2;
332c2c66affSColin Finck     CenterY = (RectBounds.bottom + RectBounds.top) / 2;
333c2c66affSColin Finck 
334c2c66affSColin Finck     DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
335c2c66affSColin Finck                RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
336c2c66affSColin Finck 
337c2c66affSColin Finck     DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
338c2c66affSColin Finck                CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
339c2c66affSColin Finck 
340c2c66affSColin Finck     pFillBrushObj = BRUSH_ShareLockBrush(pdcattr->hbrush);
341c2c66affSColin Finck     if (NULL == pFillBrushObj)
342c2c66affSColin Finck     {
343c2c66affSColin Finck         DPRINT1("FillEllipse Fail\n");
344c2c66affSColin Finck         EngSetLastError(ERROR_INTERNAL_ERROR);
345c2c66affSColin Finck         ret = FALSE;
346c2c66affSColin Finck     }
347c2c66affSColin Finck     else
348c2c66affSColin Finck     {
349c2c66affSColin Finck         RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj));
350c2c66affSColin Finck         //tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
351c2c66affSColin Finck         //tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
352c2c66affSColin Finck         tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
353c2c66affSColin Finck         tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;
354c2c66affSColin Finck 
355c2c66affSColin Finck         DC_vPrepareDCsForBlit(dc, &RectBounds, NULL, NULL);
356c2c66affSColin Finck 
357c2c66affSColin Finck         ret = IntFillEllipse( dc,
358c2c66affSColin Finck                               CenterX - RadiusX,
359c2c66affSColin Finck                               CenterY - RadiusY,
360c2c66affSColin Finck                               RadiusX*2, // Width
361c2c66affSColin Finck                               RadiusY*2, // Height
362c2c66affSColin Finck                               &tmpFillBrushObj);
363c2c66affSColin Finck         BRUSH_ShareUnlockBrush(pFillBrushObj);
364c2c66affSColin Finck 
365c2c66affSColin Finck         if (ret)
366c2c66affSColin Finck         {
367c2c66affSColin Finck            ret = IntDrawEllipse( dc,
368c2c66affSColin Finck                                  CenterX - RadiusX,
369c2c66affSColin Finck                                  CenterY - RadiusY,
370c2c66affSColin Finck                                  RadiusX*2, // Width
371c2c66affSColin Finck                                  RadiusY*2, // Height
372c2c66affSColin Finck                                  pbrush);
373c2c66affSColin Finck         }
374c2c66affSColin Finck 
375c2c66affSColin Finck         DC_vFinishBlit(dc, NULL);
376c2c66affSColin Finck     }
377c2c66affSColin Finck 
378c2c66affSColin Finck     pbrush->lWidth = PenOrigWidth;
379c2c66affSColin Finck     PEN_ShareUnlockPen(pbrush);
380c2c66affSColin Finck     DC_UnlockDc(dc);
381c2c66affSColin Finck     DPRINT("Ellipse Exit.\n");
382c2c66affSColin Finck     return ret;
383c2c66affSColin Finck }
384c2c66affSColin Finck 
385c2c66affSColin Finck #if 0
386c2c66affSColin Finck 
387c2c66affSColin Finck // When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
388c2c66affSColin Finck // even-numbered polygon sides on each scan line. That is, GDI fills the area between the
389c2c66affSColin Finck // first and second side, between the third and fourth side, and so on.
390c2c66affSColin Finck 
391c2c66affSColin Finck // WINDING Selects winding mode (fills any region with a nonzero winding value).
392c2c66affSColin Finck // When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
393c2c66affSColin Finck // This value is defined as the number of times a pen used to draw the polygon would go around the region.
394c2c66affSColin Finck // The direction of each edge of the polygon is important.
395c2c66affSColin Finck 
396c2c66affSColin Finck extern BOOL FillPolygon(PDC dc,
397c2c66affSColin Finck                             SURFOBJ *SurfObj,
398c2c66affSColin Finck                             PBRUSHOBJ BrushObj,
399c2c66affSColin Finck                             MIX RopMode,
400c2c66affSColin Finck                             CONST PPOINT Points,
401c2c66affSColin Finck                             int Count,
402c2c66affSColin Finck                             RECTL BoundRect);
403c2c66affSColin Finck 
404c2c66affSColin Finck #endif
405c2c66affSColin Finck 
406c2c66affSColin Finck 
407c2c66affSColin Finck ULONG_PTR
408c2c66affSColin Finck APIENTRY
NtGdiPolyPolyDraw(IN HDC hDC,IN PPOINT UnsafePoints,IN PULONG UnsafeCounts,IN ULONG Count,IN INT iFunc)409c2c66affSColin Finck NtGdiPolyPolyDraw( IN HDC hDC,
410c2c66affSColin Finck                    IN PPOINT UnsafePoints,
411c2c66affSColin Finck                    IN PULONG UnsafeCounts,
412c2c66affSColin Finck                    IN ULONG Count,
413c2c66affSColin Finck                    IN INT iFunc )
414c2c66affSColin Finck {
415c2c66affSColin Finck     DC *dc;
416c2c66affSColin Finck     PVOID pTemp;
417c2c66affSColin Finck     LPPOINT SafePoints;
418c2c66affSColin Finck     PULONG SafeCounts;
419c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
420c2c66affSColin Finck     BOOL Ret = TRUE;
421c2c66affSColin Finck     ULONG nPoints = 0, nMaxPoints = 0, nInvalid = 0, i;
422c2c66affSColin Finck 
423c2c66affSColin Finck     if (!UnsafePoints || !UnsafeCounts ||
424c2c66affSColin Finck         Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn)
425c2c66affSColin Finck     {
426c2c66affSColin Finck         /* Windows doesn't set last error */
427c2c66affSColin Finck         return FALSE;
428c2c66affSColin Finck     }
429c2c66affSColin Finck 
430c2c66affSColin Finck     _SEH2_TRY
431c2c66affSColin Finck     {
432c2c66affSColin Finck         ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
433c2c66affSColin Finck         ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
434c2c66affSColin Finck 
435c2c66affSColin Finck         /* Count points and validate poligons */
436c2c66affSColin Finck         for (i = 0; i < Count; i++)
437c2c66affSColin Finck         {
438c2c66affSColin Finck             if (UnsafeCounts[i] < 2)
439c2c66affSColin Finck             {
440c2c66affSColin Finck                 nInvalid++;
441c2c66affSColin Finck             }
442c2c66affSColin Finck             nPoints += UnsafeCounts[i];
443c2c66affSColin Finck             nMaxPoints = max(nMaxPoints, UnsafeCounts[i]);
444c2c66affSColin Finck         }
445c2c66affSColin Finck     }
446c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
447c2c66affSColin Finck     {
448c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
449c2c66affSColin Finck     }
450c2c66affSColin Finck     _SEH2_END;
451c2c66affSColin Finck 
452c2c66affSColin Finck     if (!NT_SUCCESS(Status))
453c2c66affSColin Finck     {
454c2c66affSColin Finck         /* Windows doesn't set last error */
455c2c66affSColin Finck         return FALSE;
456c2c66affSColin Finck     }
457c2c66affSColin Finck 
458c2c66affSColin Finck     if (nPoints == 0 || nPoints < nMaxPoints)
459c2c66affSColin Finck     {
460c2c66affSColin Finck         /* If all polygon counts are zero, or we have overflow,
461c2c66affSColin Finck            return without setting a last error code. */
462c2c66affSColin Finck         return FALSE;
463c2c66affSColin Finck     }
464c2c66affSColin Finck 
465c2c66affSColin Finck     if (nInvalid != 0)
466c2c66affSColin Finck     {
467c2c66affSColin Finck         /* If at least one poly count is 0 or 1, fail */
468c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
469c2c66affSColin Finck         return FALSE;
470c2c66affSColin Finck     }
471c2c66affSColin Finck 
472c2c66affSColin Finck     /* Allocate one buffer for both counts and points */
473c2c66affSColin Finck     pTemp = ExAllocatePoolWithTag(PagedPool,
474c2c66affSColin Finck                                   Count * sizeof(ULONG) + nPoints * sizeof(POINT),
475c2c66affSColin Finck                                   TAG_SHAPE);
476c2c66affSColin Finck     if (!pTemp)
477c2c66affSColin Finck     {
478c2c66affSColin Finck         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
479c2c66affSColin Finck         return FALSE;
480c2c66affSColin Finck     }
481c2c66affSColin Finck 
482c2c66affSColin Finck     SafeCounts = pTemp;
483c2c66affSColin Finck     SafePoints = (PVOID)(SafeCounts + Count);
484c2c66affSColin Finck 
485c2c66affSColin Finck     _SEH2_TRY
486c2c66affSColin Finck     {
487c2c66affSColin Finck         /* Pointers already probed! */
488c2c66affSColin Finck         RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG));
489c2c66affSColin Finck         RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT));
490c2c66affSColin Finck     }
491c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
492c2c66affSColin Finck     {
493c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
494c2c66affSColin Finck     }
495c2c66affSColin Finck     _SEH2_END;
496c2c66affSColin Finck 
497c2c66affSColin Finck     if (!NT_SUCCESS(Status))
498c2c66affSColin Finck     {
499c2c66affSColin Finck         ExFreePoolWithTag(pTemp, TAG_SHAPE);
500c2c66affSColin Finck         return FALSE;
501c2c66affSColin Finck     }
502c2c66affSColin Finck 
503c2c66affSColin Finck     /* Special handling for GdiPolyPolyRgn */
504c2c66affSColin Finck     if (iFunc == GdiPolyPolyRgn)
505c2c66affSColin Finck     {
506c2c66affSColin Finck         INT iMode = (INT)(UINT_PTR)hDC;
507c2c66affSColin Finck         HRGN hrgn;
508c2c66affSColin Finck 
509c2c66affSColin Finck         hrgn = GreCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, iMode);
510c2c66affSColin Finck 
511c2c66affSColin Finck         ExFreePoolWithTag(pTemp, TAG_SHAPE);
512c2c66affSColin Finck         return (ULONG_PTR)hrgn;
513c2c66affSColin Finck     }
514c2c66affSColin Finck 
515c2c66affSColin Finck     dc = DC_LockDc(hDC);
516c2c66affSColin Finck     if (!dc)
517c2c66affSColin Finck     {
518c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
519c2c66affSColin Finck         ExFreePoolWithTag(pTemp, TAG_SHAPE);
520c2c66affSColin Finck         return FALSE;
521c2c66affSColin Finck     }
522c2c66affSColin Finck 
523c2c66affSColin Finck     DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL);
524c2c66affSColin Finck 
525c2c66affSColin Finck     if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
526c2c66affSColin Finck         DC_vUpdateFillBrush(dc);
527c2c66affSColin Finck 
528c2c66affSColin Finck     if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
529c2c66affSColin Finck         DC_vUpdateLineBrush(dc);
530c2c66affSColin Finck 
531c2c66affSColin Finck     /* Perform the actual work */
532c2c66affSColin Finck     switch (iFunc)
533c2c66affSColin Finck     {
534c2c66affSColin Finck         case GdiPolyPolygon:
535c2c66affSColin Finck             Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count);
536c2c66affSColin Finck             break;
537c2c66affSColin Finck         case GdiPolyPolyLine:
538c2c66affSColin Finck             Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count);
539c2c66affSColin Finck             break;
540c2c66affSColin Finck         case GdiPolyBezier:
541c2c66affSColin Finck             Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts);
542c2c66affSColin Finck             break;
543c2c66affSColin Finck         case GdiPolyLineTo:
544c2c66affSColin Finck             Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts);
545c2c66affSColin Finck             break;
546c2c66affSColin Finck         case GdiPolyBezierTo:
547c2c66affSColin Finck             Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
548c2c66affSColin Finck             break;
549c2c66affSColin Finck         default:
550c2c66affSColin Finck             EngSetLastError(ERROR_INVALID_PARAMETER);
551c2c66affSColin Finck             Ret = FALSE;
552c2c66affSColin Finck     }
553c2c66affSColin Finck 
554c2c66affSColin Finck     /* Cleanup and return */
555c2c66affSColin Finck     DC_vFinishBlit(dc, NULL);
556c2c66affSColin Finck     DC_UnlockDc(dc);
557c2c66affSColin Finck     ExFreePoolWithTag(pTemp, TAG_SHAPE);
558c2c66affSColin Finck 
559c2c66affSColin Finck     return (ULONG_PTR)Ret;
560c2c66affSColin Finck }
561c2c66affSColin Finck 
562c2c66affSColin Finck 
563c2c66affSColin Finck BOOL
564c2c66affSColin Finck FASTCALL
IntRectangle(PDC dc,int LeftRect,int TopRect,int RightRect,int BottomRect)565c2c66affSColin Finck IntRectangle(PDC dc,
566c2c66affSColin Finck              int LeftRect,
567c2c66affSColin Finck              int TopRect,
568c2c66affSColin Finck              int RightRect,
569c2c66affSColin Finck              int BottomRect)
570c2c66affSColin Finck {
571c2c66affSColin Finck     SURFACE *psurf = NULL;
572c2c66affSColin Finck     PBRUSH pbrLine, pbrFill;
573c2c66affSColin Finck     BOOL       ret = FALSE; // Default to failure
574c2c66affSColin Finck     RECTL      DestRect;
575c2c66affSColin Finck     MIX        Mix;
576c2c66affSColin Finck     PDC_ATTR pdcattr;
577c2c66affSColin Finck     POINTL BrushOrigin;
578*6358c4acSKatayama Hirofumi MZ     PPATH pPath;
579c2c66affSColin Finck 
580c2c66affSColin Finck     ASSERT ( dc ); // Caller's responsibility to set this up
581c2c66affSColin Finck 
582c2c66affSColin Finck     pdcattr = dc->pdcattr;
583c2c66affSColin Finck 
584c2c66affSColin Finck     // Rectangle Path only.
585c2c66affSColin Finck     if ( PATH_IsPathOpen(dc->dclevel) )
586c2c66affSColin Finck     {
587c2c66affSColin Finck         return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
588c2c66affSColin Finck     }
589c2c66affSColin Finck 
590c2c66affSColin Finck 	/* Make sure rectangle is not inverted */
591c2c66affSColin Finck     DestRect.left   = min(LeftRect, RightRect);
592c2c66affSColin Finck     DestRect.right  = max(LeftRect, RightRect);
593c2c66affSColin Finck     DestRect.top    = min(TopRect,  BottomRect);
594c2c66affSColin Finck     DestRect.bottom = max(TopRect,  BottomRect);
595c2c66affSColin Finck 
596c2c66affSColin Finck     IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
597c2c66affSColin Finck 
598c2c66affSColin Finck     DestRect.left   += dc->ptlDCOrig.x;
599c2c66affSColin Finck     DestRect.right  += dc->ptlDCOrig.x;
600c2c66affSColin Finck     DestRect.top    += dc->ptlDCOrig.y;
601c2c66affSColin Finck     DestRect.bottom += dc->ptlDCOrig.y;
602c2c66affSColin Finck 
603c2c66affSColin Finck     if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
604c2c66affSColin Finck     {
605c2c66affSColin Finck        IntUpdateBoundsRect(dc, &DestRect);
606c2c66affSColin Finck     }
607c2c66affSColin Finck 
608c2c66affSColin Finck     /* In GM_COMPATIBLE, don't include bottom and right edges */
609c2c66affSColin Finck     if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
610c2c66affSColin Finck     {
611c2c66affSColin Finck         DestRect.right--;
612c2c66affSColin Finck         DestRect.bottom--;
613c2c66affSColin Finck     }
614c2c66affSColin Finck 
615c2c66affSColin Finck     DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
616c2c66affSColin Finck 
617c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
618c2c66affSColin Finck         DC_vUpdateFillBrush(dc);
619c2c66affSColin Finck 
620c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
621c2c66affSColin Finck         DC_vUpdateLineBrush(dc);
622c2c66affSColin Finck 
623c2c66affSColin Finck     pbrFill = dc->dclevel.pbrFill;
624c2c66affSColin Finck     pbrLine = dc->dclevel.pbrLine;
625c2c66affSColin Finck     if (!pbrLine)
626c2c66affSColin Finck     {
627c2c66affSColin Finck         ret = FALSE;
628c2c66affSColin Finck         goto cleanup;
629c2c66affSColin Finck     }
630c2c66affSColin Finck 
631c2c66affSColin Finck     psurf = dc->dclevel.pSurface;
632c2c66affSColin Finck     if (!psurf)
633c2c66affSColin Finck     {
634c2c66affSColin Finck         ret = TRUE;
635c2c66affSColin Finck         goto cleanup;
636c2c66affSColin Finck     }
637c2c66affSColin Finck 
638c2c66affSColin Finck     if (pbrFill)
639c2c66affSColin Finck     {
640c2c66affSColin Finck         if (!(pbrFill->flAttrs & BR_IS_NULL))
641c2c66affSColin Finck         {
642c2c66affSColin Finck             BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
643c2c66affSColin Finck             BrushOrigin.x += dc->ptlDCOrig.x;
644c2c66affSColin Finck             BrushOrigin.y += dc->ptlDCOrig.y;
645c2c66affSColin Finck             ret = IntEngBitBlt(&psurf->SurfObj,
646c2c66affSColin Finck                                NULL,
647c2c66affSColin Finck                                NULL,
648c2c66affSColin Finck                                (CLIPOBJ *)&dc->co,
649c2c66affSColin Finck                                NULL,
650c2c66affSColin Finck                                &DestRect,
651c2c66affSColin Finck                                NULL,
652c2c66affSColin Finck                                NULL,
653c2c66affSColin Finck                                &dc->eboFill.BrushObject,
654c2c66affSColin Finck                                &BrushOrigin,
655c2c66affSColin Finck                                ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
656c2c66affSColin Finck         }
657c2c66affSColin Finck     }
658c2c66affSColin Finck 
659c2c66affSColin Finck     // Draw the rectangle with the current pen
660c2c66affSColin Finck 
661c2c66affSColin Finck     ret = TRUE; // Change default to success
662c2c66affSColin Finck 
663c2c66affSColin Finck     if (!(pbrLine->flAttrs & BR_IS_NULL))
664c2c66affSColin Finck     {
665*6358c4acSKatayama Hirofumi MZ         if (IntIsEffectiveWidePen(pbrLine))
666*6358c4acSKatayama Hirofumi MZ         {
667*6358c4acSKatayama Hirofumi MZ             /* Clear the path */
668*6358c4acSKatayama Hirofumi MZ             PATH_Delete(dc->dclevel.hPath);
669*6358c4acSKatayama Hirofumi MZ             dc->dclevel.hPath = NULL;
670*6358c4acSKatayama Hirofumi MZ 
671*6358c4acSKatayama Hirofumi MZ             /* Begin a path */
672*6358c4acSKatayama Hirofumi MZ             pPath = PATH_CreatePath(5);
673*6358c4acSKatayama Hirofumi MZ             dc->dclevel.flPath |= DCPATH_ACTIVE;
674*6358c4acSKatayama Hirofumi MZ             dc->dclevel.hPath = pPath->BaseObject.hHmgr;
675*6358c4acSKatayama Hirofumi MZ             pPath->pos.x = LeftRect;
676*6358c4acSKatayama Hirofumi MZ             pPath->pos.y = TopRect;
677*6358c4acSKatayama Hirofumi MZ             IntLPtoDP(dc, &pPath->pos, 1);
678*6358c4acSKatayama Hirofumi MZ 
679*6358c4acSKatayama Hirofumi MZ             PATH_MoveTo(dc, pPath);
680*6358c4acSKatayama Hirofumi MZ             PATH_LineTo(dc, RightRect, TopRect);
681*6358c4acSKatayama Hirofumi MZ             PATH_LineTo(dc, RightRect, BottomRect);
682*6358c4acSKatayama Hirofumi MZ             PATH_LineTo(dc, LeftRect, BottomRect);
683*6358c4acSKatayama Hirofumi MZ             PATH_LineTo(dc, LeftRect, TopRect);
684*6358c4acSKatayama Hirofumi MZ 
685*6358c4acSKatayama Hirofumi MZ             /* Close the path */
686*6358c4acSKatayama Hirofumi MZ             pPath->state = PATH_Closed;
687*6358c4acSKatayama Hirofumi MZ             dc->dclevel.flPath &= ~DCPATH_ACTIVE;
688*6358c4acSKatayama Hirofumi MZ 
689*6358c4acSKatayama Hirofumi MZ             /* Actually stroke a path */
690*6358c4acSKatayama Hirofumi MZ             ret = PATH_StrokePath(dc, pPath);
691*6358c4acSKatayama Hirofumi MZ 
692*6358c4acSKatayama Hirofumi MZ             /* Clear the path */
693*6358c4acSKatayama Hirofumi MZ             PATH_UnlockPath(pPath);
694*6358c4acSKatayama Hirofumi MZ             PATH_Delete(dc->dclevel.hPath);
695*6358c4acSKatayama Hirofumi MZ             dc->dclevel.hPath = NULL;
696*6358c4acSKatayama Hirofumi MZ         }
697*6358c4acSKatayama Hirofumi MZ         else
698*6358c4acSKatayama Hirofumi MZ         {
699c2c66affSColin Finck             Mix = ROP2_TO_MIX(pdcattr->jROP2);
700c2c66affSColin Finck             ret = ret && IntEngLineTo(&psurf->SurfObj,
701c2c66affSColin Finck                                       (CLIPOBJ *)&dc->co,
702c2c66affSColin Finck                                       &dc->eboLine.BrushObject,
703c2c66affSColin Finck                                       DestRect.left, DestRect.top, DestRect.right, DestRect.top,
704c2c66affSColin Finck                                       &DestRect, // Bounding rectangle
705c2c66affSColin Finck                                       Mix);
706c2c66affSColin Finck 
707c2c66affSColin Finck             ret = ret && IntEngLineTo(&psurf->SurfObj,
708c2c66affSColin Finck                                       (CLIPOBJ *)&dc->co,
709c2c66affSColin Finck                                       &dc->eboLine.BrushObject,
710c2c66affSColin Finck                                       DestRect.right, DestRect.top, DestRect.right, DestRect.bottom,
711c2c66affSColin Finck                                       &DestRect, // Bounding rectangle
712c2c66affSColin Finck                                       Mix);
713c2c66affSColin Finck 
714c2c66affSColin Finck             ret = ret && IntEngLineTo(&psurf->SurfObj,
715c2c66affSColin Finck                                       (CLIPOBJ *)&dc->co,
716c2c66affSColin Finck                                       &dc->eboLine.BrushObject,
717c2c66affSColin Finck                                       DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom,
718c2c66affSColin Finck                                       &DestRect, // Bounding rectangle
719c2c66affSColin Finck                                       Mix);
720c2c66affSColin Finck 
721c2c66affSColin Finck             ret = ret && IntEngLineTo(&psurf->SurfObj,
722c2c66affSColin Finck                                       (CLIPOBJ *)&dc->co,
723c2c66affSColin Finck                                       &dc->eboLine.BrushObject,
724c2c66affSColin Finck                                       DestRect.left, DestRect.bottom, DestRect.left, DestRect.top,
725c2c66affSColin Finck                                       &DestRect, // Bounding rectangle
726c2c66affSColin Finck                                       Mix);
727c2c66affSColin Finck         }
728*6358c4acSKatayama Hirofumi MZ     }
729c2c66affSColin Finck 
730c2c66affSColin Finck cleanup:
731c2c66affSColin Finck     DC_vFinishBlit(dc, NULL);
732c2c66affSColin Finck 
733c2c66affSColin Finck     /* Move current position in DC?
734c2c66affSColin Finck        MSDN: The current position is neither used nor updated by Rectangle. */
735c2c66affSColin Finck 
736c2c66affSColin Finck     return ret;
737c2c66affSColin Finck }
738c2c66affSColin Finck 
739c2c66affSColin Finck BOOL
740c2c66affSColin Finck APIENTRY
NtGdiRectangle(HDC hDC,int LeftRect,int TopRect,int RightRect,int BottomRect)741c2c66affSColin Finck NtGdiRectangle(HDC  hDC,
742c2c66affSColin Finck                int  LeftRect,
743c2c66affSColin Finck                int  TopRect,
744c2c66affSColin Finck                int  RightRect,
745c2c66affSColin Finck                int  BottomRect)
746c2c66affSColin Finck {
747c2c66affSColin Finck     DC   *dc;
748c2c66affSColin Finck     BOOL ret; // Default to failure
749c2c66affSColin Finck 
750c2c66affSColin Finck     dc = DC_LockDc(hDC);
751c2c66affSColin Finck     if (!dc)
752c2c66affSColin Finck     {
753c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
754c2c66affSColin Finck         return FALSE;
755c2c66affSColin Finck     }
756c2c66affSColin Finck 
757c2c66affSColin Finck     /* Do we rotate or shear? */
758c2c66affSColin Finck     if (!(dc->pdcattr->mxWorldToDevice.flAccel & XFORM_SCALE))
759c2c66affSColin Finck     {
760c2c66affSColin Finck         POINTL DestCoords[4];
761c2c66affSColin Finck         ULONG PolyCounts = 4;
762c2c66affSColin Finck 
763c2c66affSColin Finck         DestCoords[0].x = DestCoords[3].x = LeftRect;
764c2c66affSColin Finck         DestCoords[0].y = DestCoords[1].y = TopRect;
765c2c66affSColin Finck         DestCoords[1].x = DestCoords[2].x = RightRect;
766c2c66affSColin Finck         DestCoords[2].y = DestCoords[3].y = BottomRect;
767c2c66affSColin Finck         // Use IntGdiPolyPolygon so to support PATH.
768c2c66affSColin Finck         ret = IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
769c2c66affSColin Finck     }
770c2c66affSColin Finck     else
771c2c66affSColin Finck     {
772c2c66affSColin Finck         ret = IntRectangle(dc, LeftRect, TopRect, RightRect, BottomRect );
773c2c66affSColin Finck     }
774c2c66affSColin Finck 
775c2c66affSColin Finck     DC_UnlockDc(dc);
776c2c66affSColin Finck 
777c2c66affSColin Finck     return ret;
778c2c66affSColin Finck }
779c2c66affSColin Finck 
780c2c66affSColin Finck 
781c2c66affSColin Finck BOOL
782c2c66affSColin Finck FASTCALL
IntRoundRect(PDC dc,int Left,int Top,int Right,int Bottom,int xCurveDiameter,int yCurveDiameter)783c2c66affSColin Finck IntRoundRect(
784c2c66affSColin Finck     PDC  dc,
785c2c66affSColin Finck     int  Left,
786c2c66affSColin Finck     int  Top,
787c2c66affSColin Finck     int  Right,
788c2c66affSColin Finck     int  Bottom,
789c2c66affSColin Finck     int  xCurveDiameter,
790c2c66affSColin Finck     int  yCurveDiameter)
791c2c66affSColin Finck {
792c2c66affSColin Finck     PDC_ATTR pdcattr;
793c2c66affSColin Finck     PBRUSH   pbrLine, pbrFill;
794c2c66affSColin Finck     RECTL RectBounds;
795c2c66affSColin Finck     LONG PenWidth, PenOrigWidth;
796c2c66affSColin Finck     BOOL ret = TRUE; // Default to success
797c2c66affSColin Finck     BRUSH brushTemp;
798c2c66affSColin Finck 
799c2c66affSColin Finck     ASSERT ( dc ); // Caller's responsibility to set this up
800c2c66affSColin Finck 
801c2c66affSColin Finck     if ( PATH_IsPathOpen(dc->dclevel) )
802c2c66affSColin Finck         return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
803c2c66affSColin Finck                                 xCurveDiameter, yCurveDiameter );
804c2c66affSColin Finck 
805c2c66affSColin Finck     if ((Left == Right) || (Top == Bottom)) return TRUE;
806c2c66affSColin Finck 
807c2c66affSColin Finck     xCurveDiameter = max(abs( xCurveDiameter ), 1);
808c2c66affSColin Finck     yCurveDiameter = max(abs( yCurveDiameter ), 1);
809c2c66affSColin Finck 
810c2c66affSColin Finck     if (Right < Left)
811c2c66affSColin Finck     {
812c2c66affSColin Finck        INT tmp = Right; Right = Left; Left = tmp;
813c2c66affSColin Finck     }
814c2c66affSColin Finck     if (Bottom < Top)
815c2c66affSColin Finck     {
816c2c66affSColin Finck        INT tmp = Bottom; Bottom = Top; Top = tmp;
817c2c66affSColin Finck     }
818c2c66affSColin Finck 
819c2c66affSColin Finck     pdcattr = dc->pdcattr;
820c2c66affSColin Finck 
821c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
822c2c66affSColin Finck         DC_vUpdateFillBrush(dc);
823c2c66affSColin Finck 
824c2c66affSColin Finck     if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
825c2c66affSColin Finck         DC_vUpdateLineBrush(dc);
826c2c66affSColin Finck 
827c2c66affSColin Finck     pbrLine = PEN_ShareLockPen(pdcattr->hpen);
828c2c66affSColin Finck     if (!pbrLine)
829c2c66affSColin Finck     {
830c2c66affSColin Finck         /* Nothing to do, as we don't have a bitmap */
831c2c66affSColin Finck         EngSetLastError(ERROR_INTERNAL_ERROR);
832c2c66affSColin Finck         return FALSE;
833c2c66affSColin Finck     }
834c2c66affSColin Finck 
835c2c66affSColin Finck     PenOrigWidth = PenWidth = pbrLine->lWidth;
836c2c66affSColin Finck     if (pbrLine->ulPenStyle == PS_NULL) PenWidth = 0;
837c2c66affSColin Finck 
838c2c66affSColin Finck     if (pbrLine->ulPenStyle == PS_INSIDEFRAME)
839c2c66affSColin Finck     {
840c2c66affSColin Finck        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
841c2c66affSColin Finck        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
842c2c66affSColin Finck        Left   += PenWidth / 2;
843c2c66affSColin Finck        Right  -= (PenWidth - 1) / 2;
844c2c66affSColin Finck        Top    += PenWidth / 2;
845c2c66affSColin Finck        Bottom -= (PenWidth - 1) / 2;
846c2c66affSColin Finck     }
847c2c66affSColin Finck 
848c2c66affSColin Finck     if (!PenWidth) PenWidth = 1;
849c2c66affSColin Finck     pbrLine->lWidth = PenWidth;
850c2c66affSColin Finck 
851c2c66affSColin Finck     RectBounds.left = Left;
852c2c66affSColin Finck     RectBounds.top = Top;
853c2c66affSColin Finck     RectBounds.right = Right;
854c2c66affSColin Finck     RectBounds.bottom = Bottom;
855c2c66affSColin Finck 
856c2c66affSColin Finck     IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
857c2c66affSColin Finck 
858c2c66affSColin Finck     RectBounds.left   += dc->ptlDCOrig.x;
859c2c66affSColin Finck     RectBounds.top    += dc->ptlDCOrig.y;
860c2c66affSColin Finck     RectBounds.right  += dc->ptlDCOrig.x;
861c2c66affSColin Finck     RectBounds.bottom += dc->ptlDCOrig.y;
862c2c66affSColin Finck 
863c2c66affSColin Finck     pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
864c2c66affSColin Finck     if (!pbrFill)
865c2c66affSColin Finck     {
866c2c66affSColin Finck         DPRINT1("FillRound Fail\n");
867c2c66affSColin Finck         EngSetLastError(ERROR_INTERNAL_ERROR);
868c2c66affSColin Finck         ret = FALSE;
869c2c66affSColin Finck     }
870c2c66affSColin Finck     else
871c2c66affSColin Finck     {
872c2c66affSColin Finck 
873c2c66affSColin Finck         DC_vPrepareDCsForBlit(dc, &RectBounds, NULL, NULL);
874c2c66affSColin Finck 
875c2c66affSColin Finck         RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp));
876c2c66affSColin Finck         brushTemp.ptOrigin.x += RectBounds.left - Left;
877c2c66affSColin Finck         brushTemp.ptOrigin.y += RectBounds.top - Top;
878c2c66affSColin Finck         ret = IntFillRoundRect( dc,
879c2c66affSColin Finck                                 RectBounds.left,
880c2c66affSColin Finck                                 RectBounds.top,
881c2c66affSColin Finck                                 RectBounds.right,
882c2c66affSColin Finck                                 RectBounds.bottom,
883c2c66affSColin Finck                                 xCurveDiameter,
884c2c66affSColin Finck                                 yCurveDiameter,
885c2c66affSColin Finck                                 &brushTemp);
886c2c66affSColin Finck         BRUSH_ShareUnlockBrush(pbrFill);
887c2c66affSColin Finck 
888c2c66affSColin Finck         if (ret)
889c2c66affSColin Finck         {
890c2c66affSColin Finck            ret = IntDrawRoundRect( dc,
891c2c66affSColin Finck                       RectBounds.left,
892c2c66affSColin Finck                        RectBounds.top,
893c2c66affSColin Finck                      RectBounds.right,
894c2c66affSColin Finck                     RectBounds.bottom,
895c2c66affSColin Finck                        xCurveDiameter,
896c2c66affSColin Finck                        yCurveDiameter,
897c2c66affSColin Finck                        pbrLine);
898c2c66affSColin Finck         }
899c2c66affSColin Finck 
900c2c66affSColin Finck         DC_vFinishBlit(dc, NULL);
901c2c66affSColin Finck     }
902c2c66affSColin Finck 
903c2c66affSColin Finck 
904c2c66affSColin Finck     pbrLine->lWidth = PenOrigWidth;
905c2c66affSColin Finck     PEN_ShareUnlockPen(pbrLine);
906c2c66affSColin Finck     return ret;
907c2c66affSColin Finck }
908c2c66affSColin Finck 
909c2c66affSColin Finck BOOL
910c2c66affSColin Finck APIENTRY
NtGdiRoundRect(HDC hDC,int LeftRect,int TopRect,int RightRect,int BottomRect,int Width,int Height)911c2c66affSColin Finck NtGdiRoundRect(
912c2c66affSColin Finck     HDC  hDC,
913c2c66affSColin Finck     int  LeftRect,
914c2c66affSColin Finck     int  TopRect,
915c2c66affSColin Finck     int  RightRect,
916c2c66affSColin Finck     int  BottomRect,
917c2c66affSColin Finck     int  Width,
918c2c66affSColin Finck     int  Height)
919c2c66affSColin Finck {
920c2c66affSColin Finck     DC   *dc = DC_LockDc(hDC);
921c2c66affSColin Finck     BOOL  ret = FALSE; /* Default to failure */
922c2c66affSColin Finck 
923c2c66affSColin Finck     DPRINT("NtGdiRoundRect(0x%p,%i,%i,%i,%i,%i,%i)\n",hDC,LeftRect,TopRect,RightRect,BottomRect,Width,Height);
924c2c66affSColin Finck     if ( !dc )
925c2c66affSColin Finck     {
926c2c66affSColin Finck         DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
927c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
928c2c66affSColin Finck     }
929c2c66affSColin Finck     else
930c2c66affSColin Finck     {
931c2c66affSColin Finck         ret = IntRoundRect ( dc, LeftRect, TopRect, RightRect, BottomRect, Width, Height );
932c2c66affSColin Finck         DC_UnlockDc ( dc );
933c2c66affSColin Finck     }
934c2c66affSColin Finck 
935c2c66affSColin Finck     return ret;
936c2c66affSColin Finck }
937c2c66affSColin Finck 
938c2c66affSColin Finck BOOL
939c2c66affSColin Finck NTAPI
GreGradientFill(HDC hdc,PTRIVERTEX pVertex,ULONG nVertex,PVOID pMesh,ULONG nMesh,ULONG ulMode)940c2c66affSColin Finck GreGradientFill(
941c2c66affSColin Finck     HDC hdc,
942c2c66affSColin Finck     PTRIVERTEX pVertex,
943c2c66affSColin Finck     ULONG nVertex,
944c2c66affSColin Finck     PVOID pMesh,
945c2c66affSColin Finck     ULONG nMesh,
946c2c66affSColin Finck     ULONG ulMode)
947c2c66affSColin Finck {
948c2c66affSColin Finck     PDC pdc;
949c2c66affSColin Finck     SURFACE *psurf;
950c2c66affSColin Finck     EXLATEOBJ exlo;
951c2c66affSColin Finck     RECTL rclExtent;
952c2c66affSColin Finck     POINTL ptlDitherOrg;
953c2c66affSColin Finck     ULONG i;
954c2c66affSColin Finck     BOOL bRet;
955c2c66affSColin Finck 
956c2c66affSColin Finck     /* Check parameters */
957c2c66affSColin Finck     if (ulMode & GRADIENT_FILL_TRIANGLE)
958c2c66affSColin Finck     {
959c2c66affSColin Finck         PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
960c2c66affSColin Finck 
961c2c66affSColin Finck         for (i = 0; i < nMesh; i++, pTriangle++)
962c2c66affSColin Finck         {
963c2c66affSColin Finck             if (pTriangle->Vertex1 >= nVertex ||
964c2c66affSColin Finck                 pTriangle->Vertex2 >= nVertex ||
965c2c66affSColin Finck                 pTriangle->Vertex3 >= nVertex)
966c2c66affSColin Finck             {
967c2c66affSColin Finck                 EngSetLastError(ERROR_INVALID_PARAMETER);
968c2c66affSColin Finck                 return FALSE;
969c2c66affSColin Finck             }
970c2c66affSColin Finck         }
971c2c66affSColin Finck     }
972c2c66affSColin Finck     else
973c2c66affSColin Finck     {
974c2c66affSColin Finck         PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh;
975c2c66affSColin Finck         for (i = 0; i < nMesh; i++, pRect++)
976c2c66affSColin Finck         {
977c2c66affSColin Finck             if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex)
978c2c66affSColin Finck             {
979c2c66affSColin Finck                 EngSetLastError(ERROR_INVALID_PARAMETER);
980c2c66affSColin Finck                 return FALSE;
981c2c66affSColin Finck             }
982c2c66affSColin Finck         }
983c2c66affSColin Finck     }
984c2c66affSColin Finck 
985c2c66affSColin Finck     /* Lock the output DC */
986c2c66affSColin Finck     pdc = DC_LockDc(hdc);
987c2c66affSColin Finck     if(!pdc)
988c2c66affSColin Finck     {
989c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
990c2c66affSColin Finck         return FALSE;
991c2c66affSColin Finck     }
992c2c66affSColin Finck 
993c2c66affSColin Finck     if (!pdc->dclevel.pSurface)
994c2c66affSColin Finck     {
995c2c66affSColin Finck         /* Memory DC with no surface selected */
996c2c66affSColin Finck         DC_UnlockDc(pdc);
997c2c66affSColin Finck         return TRUE; // CHECKME
998c2c66affSColin Finck     }
999c2c66affSColin Finck 
1000c2c66affSColin Finck     /* Calculate extent */
1001c2c66affSColin Finck     rclExtent.left = rclExtent.right = pVertex->x;
1002c2c66affSColin Finck     rclExtent.top = rclExtent.bottom = pVertex->y;
1003c2c66affSColin Finck     for (i = 0; i < nVertex; i++)
1004c2c66affSColin Finck     {
1005c2c66affSColin Finck         rclExtent.left = min(rclExtent.left, (pVertex + i)->x);
1006c2c66affSColin Finck         rclExtent.right = max(rclExtent.right, (pVertex + i)->x);
1007c2c66affSColin Finck         rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
1008c2c66affSColin Finck         rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
1009c2c66affSColin Finck     }
1010c2c66affSColin Finck     IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
1011c2c66affSColin Finck 
1012c2c66affSColin Finck     rclExtent.left   += pdc->ptlDCOrig.x;
1013c2c66affSColin Finck     rclExtent.right  += pdc->ptlDCOrig.x;
1014c2c66affSColin Finck     rclExtent.top    += pdc->ptlDCOrig.y;
1015c2c66affSColin Finck     rclExtent.bottom += pdc->ptlDCOrig.y;
1016c2c66affSColin Finck 
1017456e2192STimo Kreuzer     if (RECTL_bIsEmptyRect(&rclExtent))
1018456e2192STimo Kreuzer     {
1019456e2192STimo Kreuzer         DC_UnlockDc(pdc);
1020456e2192STimo Kreuzer         return TRUE;
1021456e2192STimo Kreuzer     }
1022456e2192STimo Kreuzer 
1023c2c66affSColin Finck     ptlDitherOrg.x = ptlDitherOrg.y = 0;
1024c2c66affSColin Finck     IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
1025c2c66affSColin Finck 
1026c2c66affSColin Finck     ptlDitherOrg.x += pdc->ptlDCOrig.x;
1027c2c66affSColin Finck     ptlDitherOrg.y += pdc->ptlDCOrig.y;
1028c2c66affSColin Finck 
1029c2c66affSColin Finck    if (pdc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
1030c2c66affSColin Finck    {
1031c2c66affSColin Finck       IntUpdateBoundsRect(pdc, &rclExtent);
1032c2c66affSColin Finck    }
1033c2c66affSColin Finck 
1034c2c66affSColin Finck     DC_vPrepareDCsForBlit(pdc, &rclExtent, NULL, NULL);
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     psurf = pdc->dclevel.pSurface;
1037c2c66affSColin Finck 
1038c2c66affSColin Finck     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
1039c2c66affSColin Finck 
1040c2c66affSColin Finck     bRet = IntEngGradientFill(&psurf->SurfObj,
1041c2c66affSColin Finck                              (CLIPOBJ *)&pdc->co,
1042c2c66affSColin Finck                              &exlo.xlo,
1043c2c66affSColin Finck                              pVertex,
1044c2c66affSColin Finck                              nVertex,
1045c2c66affSColin Finck                              pMesh,
1046c2c66affSColin Finck                              nMesh,
1047c2c66affSColin Finck                              &rclExtent,
1048c2c66affSColin Finck                              &ptlDitherOrg,
1049c2c66affSColin Finck                              ulMode);
1050c2c66affSColin Finck 
1051c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
1052c2c66affSColin Finck     DC_vFinishBlit(pdc, NULL);
1053c2c66affSColin Finck     DC_UnlockDc(pdc);
1054c2c66affSColin Finck 
1055c2c66affSColin Finck     return bRet;
1056c2c66affSColin Finck }
1057c2c66affSColin Finck 
1058c2c66affSColin Finck BOOL
1059c2c66affSColin Finck APIENTRY
NtGdiGradientFill(HDC hdc,PTRIVERTEX pVertex,ULONG nVertex,PVOID pMesh,ULONG nMesh,ULONG ulMode)1060c2c66affSColin Finck NtGdiGradientFill(
1061c2c66affSColin Finck     HDC hdc,
1062c2c66affSColin Finck     PTRIVERTEX pVertex,
1063c2c66affSColin Finck     ULONG nVertex,
1064c2c66affSColin Finck     PVOID pMesh,
1065c2c66affSColin Finck     ULONG nMesh,
1066c2c66affSColin Finck     ULONG ulMode)
1067c2c66affSColin Finck {
1068c2c66affSColin Finck     BOOL bRet;
1069c2c66affSColin Finck     PTRIVERTEX SafeVertex;
1070c2c66affSColin Finck     PVOID SafeMesh;
1071c2c66affSColin Finck     ULONG cbVertex, cbMesh;
1072c2c66affSColin Finck 
1073c2c66affSColin Finck     /* Validate parameters */
1074c2c66affSColin Finck     if (!pVertex || !nVertex || !pMesh || !nMesh)
1075c2c66affSColin Finck     {
1076c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
1077c2c66affSColin Finck         return FALSE;
1078c2c66affSColin Finck     }
1079c2c66affSColin Finck 
1080c2c66affSColin Finck     switch (ulMode)
1081c2c66affSColin Finck     {
1082c2c66affSColin Finck         case GRADIENT_FILL_RECT_H:
1083c2c66affSColin Finck         case GRADIENT_FILL_RECT_V:
1084c2c66affSColin Finck             cbMesh = nMesh * sizeof(GRADIENT_RECT);
1085c2c66affSColin Finck             break;
1086c2c66affSColin Finck         case GRADIENT_FILL_TRIANGLE:
1087c2c66affSColin Finck             cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE);
1088c2c66affSColin Finck             break;
1089c2c66affSColin Finck         default:
1090c2c66affSColin Finck             EngSetLastError(ERROR_INVALID_PARAMETER);
1091c2c66affSColin Finck             return FALSE;
1092c2c66affSColin Finck     }
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     cbVertex = nVertex * sizeof(TRIVERTEX) ;
1095c2c66affSColin Finck     if(cbVertex + cbMesh <= cbVertex)
1096c2c66affSColin Finck     {
1097c2c66affSColin Finck         /* Overflow */
1098c2c66affSColin Finck         return FALSE ;
1099c2c66affSColin Finck     }
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     /* Allocate a kernel mode buffer */
1102c2c66affSColin Finck     SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
1103c2c66affSColin Finck     if(!SafeVertex)
1104c2c66affSColin Finck     {
1105c2c66affSColin Finck         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
1106c2c66affSColin Finck         return FALSE;
1107c2c66affSColin Finck     }
1108c2c66affSColin Finck 
1109c2c66affSColin Finck     SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex);
1110c2c66affSColin Finck 
1111c2c66affSColin Finck     /* Copy the parameters to kernel mode */
1112c2c66affSColin Finck     _SEH2_TRY
1113c2c66affSColin Finck     {
1114c2c66affSColin Finck         ProbeForRead(pVertex, cbVertex, 1);
1115c2c66affSColin Finck         ProbeForRead(pMesh, cbMesh, 1);
1116c2c66affSColin Finck         RtlCopyMemory(SafeVertex, pVertex, cbVertex);
1117c2c66affSColin Finck         RtlCopyMemory(SafeMesh, pMesh, cbMesh);
1118c2c66affSColin Finck     }
1119c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1120c2c66affSColin Finck     {
1121c2c66affSColin Finck         ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
1122c2c66affSColin Finck         SetLastNtError(_SEH2_GetExceptionCode());
1123c2c66affSColin Finck         _SEH2_YIELD(return FALSE;)
1124c2c66affSColin Finck     }
1125c2c66affSColin Finck     _SEH2_END;
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     /* Call the internal function */
1128c2c66affSColin Finck     bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode);
1129c2c66affSColin Finck 
1130c2c66affSColin Finck     /* Cleanup and return result */
1131c2c66affSColin Finck     ExFreePoolWithTag(SafeVertex, TAG_SHAPE);
1132c2c66affSColin Finck     return bRet;
1133c2c66affSColin Finck }
1134c2c66affSColin Finck 
1135c2c66affSColin Finck BOOL APIENTRY
NtGdiExtFloodFill(HDC hDC,INT XStart,INT YStart,COLORREF Color,UINT FillType)1136c2c66affSColin Finck NtGdiExtFloodFill(
1137c2c66affSColin Finck     HDC  hDC,
1138c2c66affSColin Finck     INT  XStart,
1139c2c66affSColin Finck     INT  YStart,
1140c2c66affSColin Finck     COLORREF  Color,
1141c2c66affSColin Finck     UINT  FillType)
1142c2c66affSColin Finck {
1143c2c66affSColin Finck     PDC dc;
1144c2c66affSColin Finck #if 0
1145c2c66affSColin Finck     PDC_ATTR   pdcattr;
1146c2c66affSColin Finck #endif
1147c2c66affSColin Finck     SURFACE    *psurf;
1148c2c66affSColin Finck     EXLATEOBJ  exlo;
1149c2c66affSColin Finck     BOOL       Ret = FALSE;
1150c2c66affSColin Finck     RECTL      DestRect;
1151c2c66affSColin Finck     POINTL     Pt;
1152c2c66affSColin Finck     ULONG      ConvColor;
115394b4b5c1Sjimtabor     PREGION    prgn;
1154c2c66affSColin Finck 
1155c2c66affSColin Finck     dc = DC_LockDc(hDC);
1156c2c66affSColin Finck     if (!dc)
1157c2c66affSColin Finck     {
1158c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1159c2c66affSColin Finck         return FALSE;
1160c2c66affSColin Finck     }
1161c2c66affSColin Finck 
1162c2c66affSColin Finck     if (!dc->dclevel.pSurface)
1163c2c66affSColin Finck     {
1164c2c66affSColin Finck         Ret = TRUE;
1165c2c66affSColin Finck         goto cleanup;
1166c2c66affSColin Finck     }
1167c2c66affSColin Finck 
1168c2c66affSColin Finck #if 0
1169c2c66affSColin Finck     pdcattr = dc->pdcattr;
1170c2c66affSColin Finck #endif
1171c2c66affSColin Finck 
1172c2c66affSColin Finck     Pt.x = XStart;
1173c2c66affSColin Finck     Pt.y = YStart;
1174c2c66affSColin Finck     IntLPtoDP(dc, (LPPOINT)&Pt, 1);
1175c2c66affSColin Finck 
1176c2c66affSColin Finck     DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL);
1177c2c66affSColin Finck 
1178c2c66affSColin Finck     psurf = dc->dclevel.pSurface;
117994b4b5c1Sjimtabor 
118094b4b5c1Sjimtabor     prgn = dc->prgnRao ? dc->prgnRao : dc->prgnVis;
118194b4b5c1Sjimtabor     if (prgn)
1182c2c66affSColin Finck     {
118394b4b5c1Sjimtabor         Ret = REGION_PtInRegion(prgn, Pt.x, Pt.y);
1184c2c66affSColin Finck         if (Ret)
118594b4b5c1Sjimtabor             REGION_GetRgnBox(prgn, (LPRECT)&DestRect);
1186c2c66affSColin Finck         else
1187c2c66affSColin Finck         {
1188c2c66affSColin Finck             DC_vFinishBlit(dc, NULL);
1189c2c66affSColin Finck             goto cleanup;
1190c2c66affSColin Finck         }
1191c2c66affSColin Finck     }
1192c2c66affSColin Finck     else
1193c2c66affSColin Finck     {
1194c2c66affSColin Finck         RECTL_vSetRect(&DestRect, 0, 0, psurf->SurfObj.sizlBitmap.cx, psurf->SurfObj.sizlBitmap.cy);
1195c2c66affSColin Finck     }
1196c2c66affSColin Finck 
1197c2c66affSColin Finck     if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR))
1198c2c66affSColin Finck     {
1199c2c66affSColin Finck        IntUpdateBoundsRect(dc, &DestRect);
1200c2c66affSColin Finck     }
1201c2c66affSColin Finck 
1202c2c66affSColin Finck     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);
1203c2c66affSColin Finck 
1204c2c66affSColin Finck     /* Only solid fills supported for now
1205c2c66affSColin Finck      * How to support pattern brushes and non standard surfaces (not offering dib functions):
1206c2c66affSColin Finck      * Version a (most likely slow): call DrvPatBlt for every pixel
1207c2c66affSColin Finck      * Version b: create a flood mask and let MaskBlt blit a masked brush */
1208c2c66affSColin Finck     ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
1209c2c66affSColin Finck     Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
1210c2c66affSColin Finck 
1211c2c66affSColin Finck     DC_vFinishBlit(dc, NULL);
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     EXLATEOBJ_vCleanup(&exlo);
1214c2c66affSColin Finck 
1215c2c66affSColin Finck cleanup:
1216c2c66affSColin Finck     DC_UnlockDc(dc);
1217c2c66affSColin Finck     return Ret;
1218c2c66affSColin Finck }
1219c2c66affSColin Finck 
1220c2c66affSColin Finck /* EOF */
1221