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