2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
26 #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
28 BOOL FASTCALL
IntFillEllipse( PDC dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
, PBRUSH pbrush
);
29 BOOL FASTCALL
IntDrawEllipse( PDC dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
, PBRUSH pbrush
);
30 BOOL FASTCALL
IntFillRoundRect( PDC dc
, INT Left
, INT Top
, INT Right
, INT Bottom
, INT Wellipse
, INT Hellipse
, PBRUSH pbrush
);
31 BOOL FASTCALL
IntDrawRoundRect( PDC dc
, INT Left
, INT Top
, INT Right
, INT Bottom
, INT Wellipse
, INT Hellipse
, PBRUSH pbrush
);
39 PBRUSH pbrushLine
, pbrushFill
;
40 EBRUSHOBJ eboLine
, eboFill
;
41 BOOL ret
= FALSE
; // default to failure
49 ASSERT(dc
); // caller's responsibility to pass a valid dc
51 if (!Points
|| Count
< 2 )
53 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
61 for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
62 Left = min(Left, Points[CurrentPoint].x);
63 Top = min(Top, Points[CurrentPoint].y);
67 pdcattr
= dc
->pdcattr
;
69 /* Convert to screen coordinates */
70 IntLPtoDP(dc
, Points
, Count
);
71 for (CurrentPoint
= 0; CurrentPoint
< Count
; CurrentPoint
++)
73 Points
[CurrentPoint
].x
+= dc
->ptlDCOrig
.x
;
74 Points
[CurrentPoint
].y
+= dc
->ptlDCOrig
.y
;
76 // No need to have path here.
78 DestRect
.left
= Points
[0].x
;
79 DestRect
.right
= Points
[0].x
;
80 DestRect
.top
= Points
[0].y
;
81 DestRect
.bottom
= Points
[0].y
;
83 for (CurrentPoint
= 1; CurrentPoint
< Count
; ++CurrentPoint
)
85 DestRect
.left
= min(DestRect
.left
, Points
[CurrentPoint
].x
);
86 DestRect
.right
= max(DestRect
.right
, Points
[CurrentPoint
].x
);
87 DestRect
.top
= min(DestRect
.top
, Points
[CurrentPoint
].y
);
88 DestRect
.bottom
= max(DestRect
.bottom
, Points
[CurrentPoint
].y
);
91 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
92 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
94 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
95 IntGdiSelectPen(dc
,pdcattr
->hpen
);
97 /* Special locking order to avoid lock-ups */
98 pbrushFill
= BRUSH_LockBrush(pdcattr
->hbrush
);
99 pbrushLine
= PENOBJ_LockPen(pdcattr
->hpen
);
100 psurf
= SURFACE_LockSurface(dc
->rosdc
.hBitmap
);
101 /* FIXME - psurf can be NULL!!!! don't assert but handle this case gracefully! */
104 /* Now fill the polygon with the current brush. */
105 if (pbrushFill
&& !(pbrushFill
->flAttrs
& GDIBRUSH_IS_NULL
))
107 BrushOrigin
= *((PPOINTL
)&pbrushFill
->ptOrigin
);
108 BrushOrigin
.x
+= dc
->ptlDCOrig
.x
;
109 BrushOrigin
.y
+= dc
->ptlDCOrig
.y
;
110 IntGdiInitBrushInstance(&eboFill
, pbrushFill
, dc
->rosdc
.XlateBrush
);
111 ret
= IntFillPolygon (dc
, psurf
, &eboFill
.BrushObject
, Points
, Count
,
112 DestRect
, &BrushOrigin
);
115 BRUSH_UnlockBrush(pbrushFill
);
117 // Draw the Polygon Edges with the current pen ( if not a NULL pen )
118 if (pbrushLine
&& !(pbrushLine
->flAttrs
& GDIBRUSH_IS_NULL
))
122 IntGdiInitBrushInstance(&eboLine
, pbrushLine
, dc
->rosdc
.XlatePen
);
124 for (i
= 0; i
< Count
-1; i
++)
127 // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
128 // Points[0].x, Points[0].y,
129 // Points[1].x, Points[1].y );
131 ret
= IntEngLineTo(&psurf
->SurfObj
,
132 dc
->rosdc
.CombinedClip
,
133 &eboLine
.BrushObject
,
134 Points
[i
].x
, /* From */
136 Points
[i
+1].x
, /* To */
139 ROP2_TO_MIX(pdcattr
->jROP2
)); /* MIX */
142 /* Close the polygon */
145 ret
= IntEngLineTo(&psurf
->SurfObj
,
146 dc
->rosdc
.CombinedClip
,
147 &eboLine
.BrushObject
,
148 Points
[Count
-1].x
, /* From */
150 Points
[0].x
, /* To */
153 ROP2_TO_MIX(pdcattr
->jROP2
)); /* MIX */
157 PENOBJ_UnlockPen(pbrushLine
);
159 SURFACE_UnlockSurface(psurf
);
165 IntGdiPolyPolygon(DC
*dc
,
170 if (PATH_IsPathOpen(dc
->dclevel
))
171 return PATH_PolyPolygon ( dc
, Points
, (PINT
)PolyCounts
, Count
);
175 if (!IntGdiPolygon ( dc
, Points
, *PolyCounts
))
177 Points
+=*PolyCounts
++;
184 /******************************************************************************/
193 * This function uses optimized Bresenham's ellipse algorithm. It draws
194 * four lines of the ellipse in one pass.
211 LONG PenWidth
, PenOrigWidth
;
212 LONG RadiusX
, RadiusY
, CenterX
, CenterY
;
213 PBRUSH pFillBrushObj
;
214 BRUSH tmpFillBrushObj
;
216 if ((Left
== Right
) || (Top
== Bottom
)) return TRUE
;
221 SetLastWin32Error(ERROR_INVALID_HANDLE
);
224 if (dc
->dctype
== DC_TYPE_INFO
)
227 /* Yes, Windows really returns TRUE in this case */
231 if (PATH_IsPathOpen(dc
->dclevel
))
233 ret
= PATH_Ellipse(dc
, Left
, Top
, Right
, Bottom
);
240 INT tmp
= Right
; Right
= Left
; Left
= tmp
;
244 INT tmp
= Bottom
; Bottom
= Top
; Top
= tmp
;
247 pdcattr
= dc
->pdcattr
;
249 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
250 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
252 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
253 IntGdiSelectPen(dc
,pdcattr
->hpen
);
255 pbrush
= PENOBJ_LockPen(pdcattr
->hpen
);
258 DPRINT1("Ellipse Fail 1\n");
260 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
264 PenOrigWidth
= PenWidth
= pbrush
->ptPenWidth
.x
;
265 if (pbrush
->ulPenStyle
== PS_NULL
) PenWidth
= 0;
267 if (pbrush
->ulPenStyle
== PS_INSIDEFRAME
)
269 if (2*PenWidth
> (Right
- Left
)) PenWidth
= (Right
-Left
+ 1)/2;
270 if (2*PenWidth
> (Bottom
- Top
)) PenWidth
= (Bottom
-Top
+ 1)/2;
271 Left
+= PenWidth
/ 2;
272 Right
-= (PenWidth
- 1) / 2;
274 Bottom
-= (PenWidth
- 1) / 2;
277 if (!PenWidth
) PenWidth
= 1;
278 pbrush
->ptPenWidth
.x
= PenWidth
;
280 RectBounds
.left
= Left
;
281 RectBounds
.right
= Right
;
282 RectBounds
.top
= Top
;
283 RectBounds
.bottom
= Bottom
;
285 IntLPtoDP(dc
, (LPPOINT
)&RectBounds
, 2);
287 RectBounds
.left
+= dc
->ptlDCOrig
.x
;
288 RectBounds
.right
+= dc
->ptlDCOrig
.x
;
289 RectBounds
.top
+= dc
->ptlDCOrig
.y
;
290 RectBounds
.bottom
+= dc
->ptlDCOrig
.y
;
292 // Setup for dynamic width and height.
293 RadiusX
= max((RectBounds
.right
- RectBounds
.left
) / 2, 2); // Needs room
294 RadiusY
= max((RectBounds
.bottom
- RectBounds
.top
) / 2, 2);
295 CenterX
= (RectBounds
.right
+ RectBounds
.left
) / 2;
296 CenterY
= (RectBounds
.bottom
+ RectBounds
.top
) / 2;
298 DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
299 RectBounds
.left
,RectBounds
.top
,RectBounds
.right
,RectBounds
.bottom
);
301 DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
302 CenterX
- RadiusX
, CenterY
+ RadiusY
, RadiusX
*2, RadiusY
*2);
304 pFillBrushObj
= BRUSH_LockBrush(pdcattr
->hbrush
);
305 if (NULL
== pFillBrushObj
)
307 DPRINT1("FillEllipse Fail\n");
308 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
313 RtlCopyMemory(&tmpFillBrushObj
, pFillBrushObj
, sizeof(tmpFillBrushObj
));
314 // tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
315 // tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
316 tmpFillBrushObj
.ptOrigin
.x
+= dc
->ptlDCOrig
.x
;
317 tmpFillBrushObj
.ptOrigin
.y
+= dc
->ptlDCOrig
.y
;
318 ret
= IntFillEllipse( dc
,
324 BRUSH_UnlockBrush(pFillBrushObj
);
328 ret
= IntDrawEllipse( dc
,
335 pbrush
->ptPenWidth
.x
= PenOrigWidth
;
336 PENOBJ_UnlockPen(pbrush
);
338 DPRINT("Ellipse Exit.\n");
344 //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and
345 //even-numbered polygon sides on each scan line. That is, GDI fills the area between the
346 //first and second side, between the third and fourth side, and so on.
348 //WINDING Selects winding mode (fills any region with a nonzero winding value).
349 //When the fill mode is WINDING, GDI fills any region that has a nonzero winding value.
350 //This value is defined as the number of times a pen used to draw the polygon would go around the region.
351 //The direction of each edge of the polygon is important.
353 extern BOOL
FillPolygon(PDC dc
,
366 NtGdiPolyPolyDraw( IN HDC hDC
,
367 IN PPOINT UnsafePoints
,
368 IN PULONG UnsafeCounts
,
376 NTSTATUS Status
= STATUS_SUCCESS
;
378 INT nPoints
= 0, nMaxPoints
= 0, nInvalid
= 0, i
;
380 if (!UnsafePoints
|| !UnsafeCounts
||
381 Count
== 0 || iFunc
== 0 || iFunc
> GdiPolyPolyRgn
)
383 /* Windows doesn't set last error */
389 ProbeForRead(UnsafePoints
, Count
* sizeof(POINT
), 1);
390 ProbeForRead(UnsafeCounts
, Count
* sizeof(ULONG
), 1);
392 /* Count points and validate poligons */
393 for (i
= 0; i
< Count
; i
++)
395 if (UnsafeCounts
[i
] < 2)
399 nPoints
+= UnsafeCounts
[i
];
400 nMaxPoints
= max(nMaxPoints
, UnsafeCounts
[i
]);
403 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
405 Status
= _SEH2_GetExceptionCode();
409 if (!NT_SUCCESS(Status
))
411 /* Windows doesn't set last error */
415 if (nPoints
== 0 || nPoints
< nMaxPoints
)
417 /* If all polygon counts are zero, or we have overflow,
418 return without setting a last error code. */
424 /* If at least one poly count is 0 or 1, fail */
425 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
429 /* Allocate one buffer for both counts and points */
430 pTemp
= ExAllocatePoolWithTag(PagedPool
,
431 Count
* sizeof(ULONG
) + nPoints
* sizeof(POINT
),
435 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
440 SafePoints
= (PVOID
)(SafeCounts
+ Count
);
444 /* Pointers already probed! */
445 RtlCopyMemory(SafeCounts
, UnsafeCounts
, Count
* sizeof(ULONG
));
446 RtlCopyMemory(SafePoints
, UnsafePoints
, nPoints
* sizeof(POINT
));
448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
450 Status
= _SEH2_GetExceptionCode();
454 if (!NT_SUCCESS(Status
))
456 ExFreePoolWithTag(pTemp
, TAG_SHAPE
);
460 /* Special handling for GdiPolyPolyRgn */
461 if (iFunc
== GdiPolyPolyRgn
)
464 hRgn
= IntCreatePolyPolygonRgn(SafePoints
, SafeCounts
, Count
, (INT_PTR
)hDC
);
465 ExFreePoolWithTag(pTemp
, TAG_SHAPE
);
466 return (ULONG_PTR
)hRgn
;
472 SetLastWin32Error(ERROR_INVALID_HANDLE
);
477 if (dc
->dctype
== DC_TYPE_INFO
)
481 /* Yes, Windows really returns TRUE in this case */
485 /* Perform the actual work */
489 Ret
= IntGdiPolyPolygon(dc
, SafePoints
, SafeCounts
, Count
);
491 case GdiPolyPolyLine
:
492 Ret
= IntGdiPolyPolyline(dc
, SafePoints
, SafeCounts
, Count
);
495 Ret
= IntGdiPolyBezier(dc
, SafePoints
, *SafeCounts
);
498 Ret
= IntGdiPolylineTo(dc
, SafePoints
, *SafeCounts
);
500 case GdiPolyBezierTo
:
501 Ret
= IntGdiPolyBezierTo(dc
, SafePoints
, *SafeCounts
);
504 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
508 /* Cleanup and return */
512 return (ULONG_PTR
)Ret
;
524 SURFACE
*psurf
= NULL
;
525 PBRUSH pbrushLine
= NULL
, pbrushFill
= NULL
;
526 EBRUSHOBJ eboLine
, eboFill
;
527 BOOL ret
= FALSE
; // default to failure
533 ASSERT ( dc
); // caller's responsibility to set this up
535 pdcattr
= dc
->pdcattr
;
537 /* Do we rotate or shear? */
538 if (!(dc
->dclevel
.mxWorldToDevice
.flAccel
& MX_SCALE
))
541 POINTL DestCoords
[4];
542 ULONG PolyCounts
= 4;
543 DestCoords
[0].x
= DestCoords
[3].x
= LeftRect
;
544 DestCoords
[0].y
= DestCoords
[1].y
= TopRect
;
545 DestCoords
[1].x
= DestCoords
[2].x
= RightRect
;
546 DestCoords
[2].y
= DestCoords
[3].y
= BottomRect
;
547 // Use IntGdiPolyPolygon so to support PATH.
548 return IntGdiPolyPolygon(dc
, DestCoords
, &PolyCounts
, 1);
550 // Rectangle Path only.
551 if ( PATH_IsPathOpen(dc
->dclevel
) )
553 return PATH_Rectangle ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
);
556 DestRect
.left
= LeftRect
;
557 DestRect
.right
= RightRect
;
558 DestRect
.top
= TopRect
;
559 DestRect
.bottom
= BottomRect
;
561 IntLPtoDP(dc
, (LPPOINT
)&DestRect
, 2);
563 DestRect
.left
+= dc
->ptlDCOrig
.x
;
564 DestRect
.right
+= dc
->ptlDCOrig
.x
;
565 DestRect
.top
+= dc
->ptlDCOrig
.y
;
566 DestRect
.bottom
+= dc
->ptlDCOrig
.y
;
568 /* In GM_COMPATIBLE, don't include bottom and right edges */
569 if (IntGetGraphicsMode(dc
) == GM_COMPATIBLE
)
575 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
576 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
578 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
579 IntGdiSelectPen(dc
,pdcattr
->hpen
);
581 /* Special locking order to avoid lock-ups! */
582 pbrushFill
= BRUSH_LockBrush(pdcattr
->hbrush
);
583 pbrushLine
= PENOBJ_LockPen(pdcattr
->hpen
);
589 psurf
= SURFACE_LockSurface(dc
->rosdc
.hBitmap
);
598 if (!(pbrushFill
->flAttrs
& GDIBRUSH_IS_NULL
))
600 BrushOrigin
= *((PPOINTL
)&pbrushFill
->ptOrigin
);
601 BrushOrigin
.x
+= dc
->ptlDCOrig
.x
;
602 BrushOrigin
.y
+= dc
->ptlDCOrig
.y
;
603 IntGdiInitBrushInstance(&eboFill
, pbrushFill
, dc
->rosdc
.XlateBrush
);
604 ret
= IntEngBitBlt(&psurf
->SurfObj
,
607 dc
->rosdc
.CombinedClip
,
612 &eboFill
.BrushObject
,
614 ROP3_TO_ROP4(PATCOPY
));
618 IntGdiInitBrushInstance(&eboLine
, pbrushLine
, dc
->rosdc
.XlatePen
);
620 // Draw the rectangle with the current pen
622 ret
= TRUE
; // change default to success
624 if (!(pbrushLine
->flAttrs
& GDIBRUSH_IS_NULL
))
626 Mix
= ROP2_TO_MIX(pdcattr
->jROP2
);
627 ret
= ret
&& IntEngLineTo(&psurf
->SurfObj
,
628 dc
->rosdc
.CombinedClip
,
629 &eboLine
.BrushObject
,
630 DestRect
.left
, DestRect
.top
, DestRect
.right
, DestRect
.top
,
631 &DestRect
, // Bounding rectangle
634 ret
= ret
&& IntEngLineTo(&psurf
->SurfObj
,
635 dc
->rosdc
.CombinedClip
,
636 &eboLine
.BrushObject
,
637 DestRect
.right
, DestRect
.top
, DestRect
.right
, DestRect
.bottom
,
638 &DestRect
, // Bounding rectangle
641 ret
= ret
&& IntEngLineTo(&psurf
->SurfObj
,
642 dc
->rosdc
.CombinedClip
,
643 &eboLine
.BrushObject
,
644 DestRect
.right
, DestRect
.bottom
, DestRect
.left
, DestRect
.bottom
,
645 &DestRect
, // Bounding rectangle
648 ret
= ret
&& IntEngLineTo(&psurf
->SurfObj
,
649 dc
->rosdc
.CombinedClip
,
650 &eboLine
.BrushObject
,
651 DestRect
.left
, DestRect
.bottom
, DestRect
.left
, DestRect
.top
,
652 &DestRect
, // Bounding rectangle
658 BRUSH_UnlockBrush(pbrushFill
);
661 PENOBJ_UnlockPen(pbrushLine
);
664 SURFACE_UnlockSurface(psurf
);
666 /* Move current position in DC?
667 MSDN: The current position is neither used nor updated by Rectangle. */
674 NtGdiRectangle(HDC hDC
,
681 BOOL ret
; // default to failure
686 SetLastWin32Error(ERROR_INVALID_HANDLE
);
689 if (dc
->dctype
== DC_TYPE_INFO
)
692 /* Yes, Windows really returns TRUE in this case */
696 ret
= IntRectangle ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
);
715 PBRUSH pbrushLine
, pbrushFill
;
717 LONG PenWidth
, PenOrigWidth
;
718 BOOL ret
= TRUE
; // default to success
721 ASSERT ( dc
); // caller's responsibility to set this up
723 if ( PATH_IsPathOpen(dc
->dclevel
) )
724 return PATH_RoundRect ( dc
, Left
, Top
, Right
, Bottom
,
725 xCurveDiameter
, yCurveDiameter
);
727 if ((Left
== Right
) || (Top
== Bottom
)) return TRUE
;
729 xCurveDiameter
= max(abs( xCurveDiameter
), 1);
730 yCurveDiameter
= max(abs( yCurveDiameter
), 1);
734 INT tmp
= Right
; Right
= Left
; Left
= tmp
;
738 INT tmp
= Bottom
; Bottom
= Top
; Top
= tmp
;
741 pdcattr
= dc
->pdcattr
;
743 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
744 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
746 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
747 IntGdiSelectPen(dc
,pdcattr
->hpen
);
749 pbrushLine
= PENOBJ_LockPen(pdcattr
->hpen
);
752 /* Nothing to do, as we don't have a bitmap */
753 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
757 PenOrigWidth
= PenWidth
= pbrushLine
->ptPenWidth
.x
;
758 if (pbrushLine
->ulPenStyle
== PS_NULL
) PenWidth
= 0;
760 if (pbrushLine
->ulPenStyle
== PS_INSIDEFRAME
)
762 if (2*PenWidth
> (Right
- Left
)) PenWidth
= (Right
-Left
+ 1)/2;
763 if (2*PenWidth
> (Bottom
- Top
)) PenWidth
= (Bottom
-Top
+ 1)/2;
764 Left
+= PenWidth
/ 2;
765 Right
-= (PenWidth
- 1) / 2;
767 Bottom
-= (PenWidth
- 1) / 2;
770 if (!PenWidth
) PenWidth
= 1;
771 pbrushLine
->ptPenWidth
.x
= PenWidth
;
773 RectBounds
.left
= Left
;
774 RectBounds
.top
= Top
;
775 RectBounds
.right
= Right
;
776 RectBounds
.bottom
= Bottom
;
778 IntLPtoDP(dc
, (LPPOINT
)&RectBounds
, 2);
780 RectBounds
.left
+= dc
->ptlDCOrig
.x
;
781 RectBounds
.top
+= dc
->ptlDCOrig
.y
;
782 RectBounds
.right
+= dc
->ptlDCOrig
.x
;
783 RectBounds
.bottom
+= dc
->ptlDCOrig
.y
;
785 pbrushFill
= BRUSH_LockBrush(pdcattr
->hbrush
);
786 if (NULL
== pbrushFill
)
788 DPRINT1("FillRound Fail\n");
789 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
794 RtlCopyMemory(&brushTemp
, pbrushFill
, sizeof(brushTemp
));
795 brushTemp
.ptOrigin
.x
+= RectBounds
.left
- Left
;
796 brushTemp
.ptOrigin
.y
+= RectBounds
.top
- Top
;
797 ret
= IntFillRoundRect( dc
,
805 BRUSH_UnlockBrush(pbrushFill
);
809 ret
= IntDrawRoundRect( dc
,
818 pbrushLine
->ptPenWidth
.x
= PenOrigWidth
;
819 PENOBJ_UnlockPen(pbrushLine
);
834 DC
*dc
= DC_LockDc(hDC
);
835 BOOL ret
= FALSE
; /* default to failure */
837 DPRINT("NtGdiRoundRect(0x%x,%i,%i,%i,%i,%i,%i)\n",hDC
,LeftRect
,TopRect
,RightRect
,BottomRect
,Width
,Height
);
840 DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
841 SetLastWin32Error(ERROR_INVALID_HANDLE
);
843 else if (dc
->dctype
== DC_TYPE_INFO
)
846 /* Yes, Windows really returns TRUE in this case */
851 ret
= IntRoundRect ( dc
, LeftRect
, TopRect
, RightRect
, BottomRect
, Width
, Height
);
874 HPALETTE hDestPalette
;
882 /* check parameters */
883 if (ulMode
& GRADIENT_FILL_TRIANGLE
)
885 PGRADIENT_TRIANGLE tr
= (PGRADIENT_TRIANGLE
)pMesh
;
887 for (i
= 0; i
< uMesh
; i
++, tr
++)
889 if (tr
->Vertex1
>= uVertex
||
890 tr
->Vertex2
>= uVertex
||
891 tr
->Vertex3
>= uVertex
)
893 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
900 PGRADIENT_RECT rc
= (PGRADIENT_RECT
)pMesh
;
901 for (i
= 0; i
< uMesh
; i
++, rc
++)
903 if (rc
->UpperLeft
>= uVertex
|| rc
->LowerRight
>= uVertex
)
905 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
911 /* calculate extent */
912 Extent
.left
= Extent
.right
= pVertex
->x
;
913 Extent
.top
= Extent
.bottom
= pVertex
->y
;
914 for (i
= 0; i
< uVertex
; i
++)
916 Extent
.left
= min(Extent
.left
, (pVertex
+ i
)->x
);
917 Extent
.right
= max(Extent
.right
, (pVertex
+ i
)->x
);
918 Extent
.top
= min(Extent
.top
, (pVertex
+ i
)->y
);
919 Extent
.bottom
= max(Extent
.bottom
, (pVertex
+ i
)->y
);
922 DitherOrg
.x
= dc
->ptlDCOrig
.x
;
923 DitherOrg
.y
= dc
->ptlDCOrig
.y
;
924 Extent
.left
+= DitherOrg
.x
;
925 Extent
.right
+= DitherOrg
.x
;
926 Extent
.top
+= DitherOrg
.y
;
927 Extent
.bottom
+= DitherOrg
.y
;
929 psurf
= SURFACE_LockSurface(dc
->rosdc
.hBitmap
);
930 /* FIXME - psurf can be NULL!!! Don't assert but handle this case gracefully! */
933 hDestPalette
= psurf
->hDIBPalette
;
934 if (!hDestPalette
) hDestPalette
= pPrimarySurface
->DevInfo
.hpalDefault
;
936 PalDestGDI
= PALETTE_LockPalette(hDestPalette
);
939 Mode
= PalDestGDI
->Mode
;
940 PALETTE_UnlockPalette(PalDestGDI
);
945 XlateObj
= (XLATEOBJ
*)IntEngCreateXlate(Mode
, PAL_RGB
, hDestPalette
, NULL
);
948 Ret
= IntEngGradientFill(&psurf
->SurfObj
,
949 dc
->rosdc
.CombinedClip
,
959 SURFACE_UnlockSurface(psurf
);
960 EngDeleteXlate(XlateObj
);
977 PTRIVERTEX SafeVertex
;
980 NTSTATUS Status
= STATUS_SUCCESS
;
985 SetLastWin32Error(ERROR_INVALID_HANDLE
);
988 if (dc
->dctype
== DC_TYPE_INFO
)
991 /* Yes, Windows really returns TRUE in this case */
994 if (!pVertex
|| !uVertex
|| !pMesh
|| !uMesh
)
997 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1003 case GRADIENT_FILL_RECT_H
:
1004 case GRADIENT_FILL_RECT_V
:
1005 SizeMesh
= uMesh
* sizeof(GRADIENT_RECT
);
1007 case GRADIENT_FILL_TRIANGLE
:
1008 SizeMesh
= uMesh
* sizeof(TRIVERTEX
);
1012 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1018 ProbeForRead(pVertex
,
1019 uVertex
* sizeof(TRIVERTEX
),
1025 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1027 Status
= _SEH2_GetExceptionCode();
1031 if (!NT_SUCCESS(Status
))
1034 SetLastWin32Error(Status
);
1038 if (!(SafeVertex
= ExAllocatePoolWithTag(PagedPool
, (uVertex
* sizeof(TRIVERTEX
)) + SizeMesh
, TAG_SHAPE
)))
1041 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
1045 SafeMesh
= (PTRIVERTEX
)(SafeVertex
+ uVertex
);
1049 /* pointers were already probed! */
1050 RtlCopyMemory(SafeVertex
,
1052 uVertex
* sizeof(TRIVERTEX
));
1053 RtlCopyMemory(SafeMesh
,
1057 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1059 Status
= _SEH2_GetExceptionCode();
1063 if (!NT_SUCCESS(Status
))
1066 ExFreePoolWithTag(SafeVertex
, TAG_SHAPE
);
1067 SetLastNtError(Status
);
1071 Ret
= IntGdiGradientFill(dc
, SafeVertex
, uVertex
, SafeMesh
, uMesh
, ulMode
);
1074 ExFreePool(SafeVertex
);
1088 SURFACE
*psurf
= NULL
;
1089 PBRUSH pbrushFill
= NULL
;
1096 DPRINT1("FIXME: NtGdiExtFloodFill is UNIMPLEMENTED\n");
1098 dc
= DC_LockDc(hDC
);
1101 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1104 if (dc
->dctype
== DC_TYPE_INFO
)
1107 /* Yes, Windows really returns TRUE in this case */
1111 pdcattr
= dc
->pdcattr
;
1113 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
1114 IntGdiSelectPen(dc
,pdcattr
->hpen
);
1116 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
1117 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
1121 IntLPtoDP(dc
, (LPPOINT
)&Pt
, 1);
1123 Ret
= NtGdiPtInRegion(dc
->rosdc
.hGCClipRgn
, Pt
.x
, Pt
.y
);
1125 IntGdiGetRgnBox(dc
->rosdc
.hGCClipRgn
,(LPRECT
)&DestRect
);
1129 pbrushFill
= BRUSH_LockBrush(pdcattr
->hbrush
);
1135 psurf
= SURFACE_LockSurface(dc
->rosdc
.hBitmap
);
1142 if ( pbrushFill
&& (FillType
== FLOODFILLBORDER
))
1144 if (!(pbrushFill
->flAttrs
& GDIBRUSH_IS_NULL
))
1146 pbrushFill
->BrushAttr
.lbColor
= Color
;
1147 BrushOrigin
= *((PPOINTL
)&pbrushFill
->ptOrigin
);
1148 BrushOrigin
.x
+= dc
->ptlDCOrig
.x
;
1149 BrushOrigin
.y
+= dc
->ptlDCOrig
.y
;
1150 IntGdiInitBrushInstance(&eboFill
, pbrushFill
, dc
->rosdc
.XlateBrush
);
1151 Ret
= IntEngBitBlt(&psurf
->SurfObj
, NULL
, NULL
,
1152 dc
->rosdc
.CombinedClip
, NULL
,
1153 &DestRect
, NULL
, NULL
,
1154 &eboFill
.BrushObject
,
1156 ROP3_TO_ROP4(PATCOPY
));
1165 BRUSH_UnlockBrush(pbrushFill
);
1168 SURFACE_UnlockSurface(psurf
);