2 * GDI drawing functions.
4 * Copyright 1993, 1994 Alexandre Julliard
5 * Copyright 1997 Bertho A. Stultiens
20 #include "debugtools.h"
22 DEFAULT_DEBUG_CHANNEL(gdi
);
25 /***********************************************************************
28 BOOL16 WINAPI
LineTo16( HDC16 hdc
, INT16 x
, INT16 y
)
30 return LineTo( hdc
, x
, y
);
34 /***********************************************************************
37 BOOL WINAPI
LineTo( HDC hdc
, INT x
, INT y
)
39 DC
* dc
= DC_GetDCUpdate( hdc
);
44 if(PATH_IsPathOpen(dc
->path
))
45 ret
= PATH_LineTo(dc
, x
, y
);
47 ret
= dc
->funcs
->pLineTo
&& dc
->funcs
->pLineTo(dc
,x
,y
);
52 GDI_ReleaseObj( hdc
);
57 /***********************************************************************
60 DWORD WINAPI
MoveTo16( HDC16 hdc
, INT16 x
, INT16 y
)
64 if (!MoveToEx( (HDC
)hdc
, x
, y
, &pt
)) return 0;
65 return MAKELONG(pt
.x
,pt
.y
);
69 /***********************************************************************
72 BOOL16 WINAPI
MoveToEx16( HDC16 hdc
, INT16 x
, INT16 y
, LPPOINT16 pt
)
76 if (!MoveToEx( (HDC
)hdc
, (INT
)x
, (INT
)y
, &pt32
)) return FALSE
;
77 if (pt
) CONV_POINT32TO16( &pt32
, pt
);
82 /***********************************************************************
85 BOOL WINAPI
MoveToEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
88 DC
* dc
= DC_GetDCPtr( hdc
);
99 if(PATH_IsPathOpen(dc
->path
)) ret
= PATH_MoveTo(dc
);
100 else if (dc
->funcs
->pMoveTo
) ret
= dc
->funcs
->pMoveTo(dc
,x
,y
);
101 GDI_ReleaseObj( hdc
);
106 /***********************************************************************
109 BOOL16 WINAPI
Arc16( HDC16 hdc
, INT16 left
, INT16 top
, INT16 right
,
110 INT16 bottom
, INT16 xstart
, INT16 ystart
,
111 INT16 xend
, INT16 yend
)
113 return Arc( (HDC
)hdc
, (INT
)left
, (INT
)top
, (INT
)right
,
114 (INT
)bottom
, (INT
)xstart
, (INT
)ystart
, (INT
)xend
,
119 /***********************************************************************
122 BOOL WINAPI
Arc( HDC hdc
, INT left
, INT top
, INT right
,
123 INT bottom
, INT xstart
, INT ystart
,
127 DC
* dc
= DC_GetDCUpdate( hdc
);
130 if(PATH_IsPathOpen(dc
->path
))
131 ret
= PATH_Arc(dc
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
,0);
132 else if (dc
->funcs
->pArc
)
133 ret
= dc
->funcs
->pArc(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
);
134 GDI_ReleaseObj( hdc
);
139 /***********************************************************************
142 BOOL WINAPI
ArcTo( HDC hdc
,
144 INT right
, INT bottom
,
145 INT xstart
, INT ystart
,
149 DC
* dc
= DC_GetDCUpdate( hdc
);
150 if(!dc
) return FALSE
;
152 if(dc
->funcs
->pArcTo
)
154 result
= dc
->funcs
->pArcTo( dc
, left
, top
, right
, bottom
,
155 xstart
, ystart
, xend
, yend
);
156 GDI_ReleaseObj( hdc
);
159 GDI_ReleaseObj( hdc
);
162 * According to the documentation, a line is drawn from the current
163 * position to the starting point of the arc.
165 LineTo(hdc
, xstart
, ystart
);
167 * Then the arc is drawn.
169 result
= Arc(hdc
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
171 * If no error occured, the current position is moved to the ending
174 if (result
) MoveToEx(hdc
, xend
, yend
, NULL
);
178 /***********************************************************************
181 BOOL16 WINAPI
Pie16( HDC16 hdc
, INT16 left
, INT16 top
,
182 INT16 right
, INT16 bottom
, INT16 xstart
, INT16 ystart
,
183 INT16 xend
, INT16 yend
)
185 return Pie( (HDC
)hdc
, (INT
)left
, (INT
)top
, (INT
)right
,
186 (INT
)bottom
, (INT
)xstart
, (INT
)ystart
, (INT
)xend
,
191 /***********************************************************************
194 BOOL WINAPI
Pie( HDC hdc
, INT left
, INT top
,
195 INT right
, INT bottom
, INT xstart
, INT ystart
,
199 DC
* dc
= DC_GetDCUpdate( hdc
);
200 if (!dc
) return FALSE
;
202 if(PATH_IsPathOpen(dc
->path
))
203 ret
= PATH_Arc(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
,2);
204 else if(dc
->funcs
->pPie
)
205 ret
= dc
->funcs
->pPie(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
);
207 GDI_ReleaseObj( hdc
);
212 /***********************************************************************
215 BOOL16 WINAPI
Chord16( HDC16 hdc
, INT16 left
, INT16 top
,
216 INT16 right
, INT16 bottom
, INT16 xstart
, INT16 ystart
,
217 INT16 xend
, INT16 yend
)
219 return Chord( hdc
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
223 /***********************************************************************
226 BOOL WINAPI
Chord( HDC hdc
, INT left
, INT top
,
227 INT right
, INT bottom
, INT xstart
, INT ystart
,
231 DC
* dc
= DC_GetDCUpdate( hdc
);
232 if (!dc
) return FALSE
;
234 if(PATH_IsPathOpen(dc
->path
))
235 ret
= PATH_Arc(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
,1);
236 else if(dc
->funcs
->pChord
)
237 ret
= dc
->funcs
->pChord(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
);
239 GDI_ReleaseObj( hdc
);
244 /***********************************************************************
247 BOOL16 WINAPI
Ellipse16( HDC16 hdc
, INT16 left
, INT16 top
,
248 INT16 right
, INT16 bottom
)
250 return Ellipse( hdc
, left
, top
, right
, bottom
);
254 /***********************************************************************
257 BOOL WINAPI
Ellipse( HDC hdc
, INT left
, INT top
,
258 INT right
, INT bottom
)
261 DC
* dc
= DC_GetDCUpdate( hdc
);
262 if (!dc
) return FALSE
;
264 if(PATH_IsPathOpen(dc
->path
))
265 ret
= PATH_Ellipse(dc
,left
,top
,right
,bottom
);
266 else if (dc
->funcs
->pEllipse
)
267 ret
= dc
->funcs
->pEllipse(dc
,left
,top
,right
,bottom
);
269 GDI_ReleaseObj( hdc
);
274 /***********************************************************************
277 BOOL16 WINAPI
Rectangle16( HDC16 hdc
, INT16 left
, INT16 top
,
278 INT16 right
, INT16 bottom
)
280 return Rectangle( hdc
, left
, top
, right
, bottom
);
284 /***********************************************************************
285 * Rectangle (GDI32.@)
287 BOOL WINAPI
Rectangle( HDC hdc
, INT left
, INT top
,
288 INT right
, INT bottom
)
291 DC
* dc
= DC_GetDCUpdate( hdc
);
294 if(PATH_IsPathOpen(dc
->path
))
295 ret
= PATH_Rectangle(dc
, left
, top
, right
, bottom
);
296 else if (dc
->funcs
->pRectangle
)
297 ret
= dc
->funcs
->pRectangle(dc
,left
,top
,right
,bottom
);
298 GDI_ReleaseObj( hdc
);
304 /***********************************************************************
307 BOOL16 WINAPI
RoundRect16( HDC16 hdc
, INT16 left
, INT16 top
, INT16 right
,
308 INT16 bottom
, INT16 ell_width
, INT16 ell_height
)
310 return RoundRect( hdc
, left
, top
, right
, bottom
, ell_width
, ell_height
);
314 /***********************************************************************
315 * RoundRect (GDI32.@)
317 BOOL WINAPI
RoundRect( HDC hdc
, INT left
, INT top
, INT right
,
318 INT bottom
, INT ell_width
, INT ell_height
)
321 DC
*dc
= DC_GetDCUpdate( hdc
);
325 if(PATH_IsPathOpen(dc
->path
))
326 ret
= PATH_RoundRect(dc
,left
,top
,right
,bottom
,ell_width
,ell_height
);
327 else if (dc
->funcs
->pRoundRect
)
328 ret
= dc
->funcs
->pRoundRect(dc
,left
,top
,right
,bottom
,ell_width
,ell_height
);
329 GDI_ReleaseObj( hdc
);
334 /***********************************************************************
337 COLORREF WINAPI
SetPixel16( HDC16 hdc
, INT16 x
, INT16 y
, COLORREF color
)
339 return SetPixel( hdc
, x
, y
, color
);
343 /***********************************************************************
346 COLORREF WINAPI
SetPixel( HDC hdc
, INT x
, INT y
, COLORREF color
)
349 DC
* dc
= DC_GetDCUpdate( hdc
);
352 if (dc
->funcs
->pSetPixel
) ret
= dc
->funcs
->pSetPixel(dc
,x
,y
,color
);
353 GDI_ReleaseObj( hdc
);
358 /***********************************************************************
359 * SetPixelV (GDI32.@)
361 BOOL WINAPI
SetPixelV( HDC hdc
, INT x
, INT y
, COLORREF color
)
364 DC
* dc
= DC_GetDCUpdate( hdc
);
367 if (dc
->funcs
->pSetPixel
)
369 dc
->funcs
->pSetPixel(dc
,x
,y
,color
);
372 GDI_ReleaseObj( hdc
);
377 /***********************************************************************
380 COLORREF WINAPI
GetPixel16( HDC16 hdc
, INT16 x
, INT16 y
)
382 return GetPixel( hdc
, x
, y
);
386 /***********************************************************************
389 COLORREF WINAPI
GetPixel( HDC hdc
, INT x
, INT y
)
391 COLORREF ret
= CLR_INVALID
;
392 DC
* dc
= DC_GetDCUpdate( hdc
);
396 /* FIXME: should this be in the graphics driver? */
397 if (PtVisible( hdc
, x
, y
))
399 if (dc
->funcs
->pGetPixel
) ret
= dc
->funcs
->pGetPixel(dc
,x
,y
);
401 GDI_ReleaseObj( hdc
);
407 /******************************************************************************
408 * ChoosePixelFormat [GDI32.@]
409 * Matches a pixel format to given format
412 * hdc [I] Device context to search for best pixel match
413 * ppfd [I] Pixel format for which a match is sought
416 * Success: Pixel format index closest to given format
419 INT WINAPI
ChoosePixelFormat( HDC hdc
, const LPPIXELFORMATDESCRIPTOR ppfd
)
422 DC
* dc
= DC_GetDCPtr( hdc
);
424 TRACE("(%08x,%p)\n",hdc
,ppfd
);
428 if (!dc
->funcs
->pChoosePixelFormat
) FIXME(" :stub\n");
429 else ret
= dc
->funcs
->pChoosePixelFormat(dc
,ppfd
);
431 GDI_ReleaseObj( hdc
);
436 /******************************************************************************
437 * SetPixelFormat [GDI32.@]
438 * Sets pixel format of device context
441 * hdc [I] Device context to search for best pixel match
442 * iPixelFormat [I] Pixel format index
443 * ppfd [I] Pixel format for which a match is sought
447 BOOL WINAPI
SetPixelFormat( HDC hdc
, INT iPixelFormat
,
448 const PIXELFORMATDESCRIPTOR
*ppfd
)
451 DC
* dc
= DC_GetDCPtr( hdc
);
453 TRACE("(%d,%d,%p)\n",hdc
,iPixelFormat
,ppfd
);
457 if (!dc
->funcs
->pSetPixelFormat
) FIXME(" :stub\n");
458 else bRet
= dc
->funcs
->pSetPixelFormat(dc
,iPixelFormat
,ppfd
);
460 GDI_ReleaseObj( hdc
);
465 /******************************************************************************
466 * GetPixelFormat [GDI32.@]
467 * Gets index of pixel format of DC
470 * hdc [I] Device context whose pixel format index is sought
473 * Success: Currently selected pixel format
476 INT WINAPI
GetPixelFormat( HDC hdc
)
479 DC
* dc
= DC_GetDCPtr( hdc
);
481 TRACE("(%08x)\n",hdc
);
485 if (!dc
->funcs
->pGetPixelFormat
) FIXME(" :stub\n");
486 else ret
= dc
->funcs
->pGetPixelFormat(dc
);
488 GDI_ReleaseObj( hdc
);
493 /******************************************************************************
494 * DescribePixelFormat [GDI32.@]
495 * Gets info about pixel format from DC
498 * hdc [I] Device context
499 * iPixelFormat [I] Pixel format selector
500 * nBytes [I] Size of buffer
501 * ppfd [O] Pointer to structure to receive pixel format data
504 * Success: Maximum pixel format index of the device context
507 INT WINAPI
DescribePixelFormat( HDC hdc
, INT iPixelFormat
, UINT nBytes
,
508 LPPIXELFORMATDESCRIPTOR ppfd
)
511 DC
* dc
= DC_GetDCPtr( hdc
);
513 TRACE("(%08x,%d,%d,%p): stub\n",hdc
,iPixelFormat
,nBytes
,ppfd
);
517 if (!dc
->funcs
->pDescribePixelFormat
)
520 ppfd
->nSize
= nBytes
;
524 else ret
= dc
->funcs
->pDescribePixelFormat(dc
,iPixelFormat
,nBytes
,ppfd
);
526 GDI_ReleaseObj( hdc
);
531 /******************************************************************************
532 * SwapBuffers [GDI32.@]
533 * Exchanges front and back buffers of window
536 * hdc [I] Device context whose buffers get swapped
540 BOOL WINAPI
SwapBuffers( HDC hdc
)
543 DC
* dc
= DC_GetDCPtr( hdc
);
545 TRACE("(%08x)\n",hdc
);
547 if (!dc
) return TRUE
;
549 if (!dc
->funcs
->pSwapBuffers
)
554 else bRet
= dc
->funcs
->pSwapBuffers(dc
);
556 GDI_ReleaseObj( hdc
);
561 /***********************************************************************
564 BOOL16 WINAPI
PaintRgn16( HDC16 hdc
, HRGN16 hrgn
)
566 return PaintRgn( hdc
, hrgn
);
570 /***********************************************************************
573 BOOL WINAPI
PaintRgn( HDC hdc
, HRGN hrgn
)
576 DC
* dc
= DC_GetDCUpdate( hdc
);
579 if (dc
->funcs
->pPaintRgn
) ret
= dc
->funcs
->pPaintRgn(dc
,hrgn
);
580 GDI_ReleaseObj( hdc
);
586 /***********************************************************************
589 BOOL16 WINAPI
FillRgn16( HDC16 hdc
, HRGN16 hrgn
, HBRUSH16 hbrush
)
591 return FillRgn( hdc
, hrgn
, hbrush
);
595 /***********************************************************************
598 BOOL WINAPI
FillRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
)
602 DC
* dc
= DC_GetDCUpdate( hdc
);
604 if (!dc
) return FALSE
;
605 if(dc
->funcs
->pFillRgn
)
606 retval
= dc
->funcs
->pFillRgn(dc
, hrgn
, hbrush
);
607 else if ((prevBrush
= SelectObject( hdc
, hbrush
)))
609 retval
= PaintRgn( hdc
, hrgn
);
610 SelectObject( hdc
, prevBrush
);
612 GDI_ReleaseObj( hdc
);
617 /***********************************************************************
620 BOOL16 WINAPI
FrameRgn16( HDC16 hdc
, HRGN16 hrgn
, HBRUSH16 hbrush
,
621 INT16 nWidth
, INT16 nHeight
)
623 return FrameRgn( hdc
, hrgn
, hbrush
, nWidth
, nHeight
);
627 /***********************************************************************
630 BOOL WINAPI
FrameRgn( HDC hdc
, HRGN hrgn
, HBRUSH hbrush
,
631 INT nWidth
, INT nHeight
)
634 DC
*dc
= DC_GetDCUpdate( hdc
);
636 if (!dc
) return FALSE
;
637 if(dc
->funcs
->pFrameRgn
)
638 ret
= dc
->funcs
->pFrameRgn( dc
, hrgn
, hbrush
, nWidth
, nHeight
);
641 HRGN tmp
= CreateRectRgn( 0, 0, 0, 0 );
644 if (REGION_FrameRgn( tmp
, hrgn
, nWidth
, nHeight
))
646 FillRgn( hdc
, tmp
, hbrush
);
652 GDI_ReleaseObj( hdc
);
657 /***********************************************************************
660 BOOL16 WINAPI
InvertRgn16( HDC16 hdc
, HRGN16 hrgn
)
662 return InvertRgn( hdc
, hrgn
);
666 /***********************************************************************
667 * InvertRgn (GDI32.@)
669 BOOL WINAPI
InvertRgn( HDC hdc
, HRGN hrgn
)
674 DC
*dc
= DC_GetDCUpdate( hdc
);
675 if (!dc
) return FALSE
;
677 if(dc
->funcs
->pInvertRgn
)
678 retval
= dc
->funcs
->pInvertRgn( dc
, hrgn
);
681 prevBrush
= SelectObject( hdc
, GetStockObject(BLACK_BRUSH
) );
682 prevROP
= SetROP2( hdc
, R2_NOT
);
683 retval
= PaintRgn( hdc
, hrgn
);
684 SelectObject( hdc
, prevBrush
);
685 SetROP2( hdc
, prevROP
);
687 GDI_ReleaseObj( hdc
);
691 /**********************************************************************
694 BOOL16 WINAPI
Polyline16( HDC16 hdc
, const POINT16
* pt
, INT16 count
)
698 LPPOINT pt32
= (LPPOINT
)HeapAlloc( GetProcessHeap(), 0,
699 count
*sizeof(POINT
) );
701 if (!pt32
) return FALSE
;
702 for (i
=count
;i
--;) CONV_POINT16TO32(&(pt
[i
]),&(pt32
[i
]));
703 ret
= Polyline(hdc
,pt32
,count
);
704 HeapFree( GetProcessHeap(), 0, pt32
);
709 /**********************************************************************
712 BOOL WINAPI
Polyline( HDC hdc
, const POINT
* pt
, INT count
)
715 DC
* dc
= DC_GetDCUpdate( hdc
);
718 if (PATH_IsPathOpen(dc
->path
)) ret
= PATH_Polyline(dc
, pt
, count
);
719 else if (dc
->funcs
->pPolyline
) ret
= dc
->funcs
->pPolyline(dc
,pt
,count
);
720 GDI_ReleaseObj( hdc
);
725 /**********************************************************************
726 * PolylineTo (GDI32.@)
728 BOOL WINAPI
PolylineTo( HDC hdc
, const POINT
* pt
, DWORD cCount
)
730 DC
* dc
= DC_GetDCUpdate( hdc
);
733 if(!dc
) return FALSE
;
735 if(PATH_IsPathOpen(dc
->path
))
736 ret
= PATH_PolylineTo(dc
, pt
, cCount
);
738 else if(dc
->funcs
->pPolylineTo
)
739 ret
= dc
->funcs
->pPolylineTo(dc
, pt
, cCount
);
741 else { /* do it using Polyline */
742 POINT
*pts
= HeapAlloc( GetProcessHeap(), 0,
743 sizeof(POINT
) * (cCount
+ 1) );
746 pts
[0].x
= dc
->CursPosX
;
747 pts
[0].y
= dc
->CursPosY
;
748 memcpy( pts
+ 1, pt
, sizeof(POINT
) * cCount
);
749 ret
= Polyline( hdc
, pts
, cCount
+ 1 );
750 HeapFree( GetProcessHeap(), 0, pts
);
754 dc
->CursPosX
= pt
[cCount
-1].x
;
755 dc
->CursPosY
= pt
[cCount
-1].y
;
757 GDI_ReleaseObj( hdc
);
761 /**********************************************************************
764 BOOL16 WINAPI
Polygon16( HDC16 hdc
, const POINT16
* pt
, INT16 count
)
768 LPPOINT pt32
= (LPPOINT
)HeapAlloc( GetProcessHeap(), 0,
769 count
*sizeof(POINT
) );
771 if (!pt32
) return FALSE
;
772 for (i
=count
;i
--;) CONV_POINT16TO32(&(pt
[i
]),&(pt32
[i
]));
773 ret
= Polygon(hdc
,pt32
,count
);
774 HeapFree( GetProcessHeap(), 0, pt32
);
779 /**********************************************************************
782 BOOL WINAPI
Polygon( HDC hdc
, const POINT
* pt
, INT count
)
785 DC
* dc
= DC_GetDCUpdate( hdc
);
788 if (PATH_IsPathOpen(dc
->path
)) ret
= PATH_Polygon(dc
, pt
, count
);
789 else if (dc
->funcs
->pPolygon
) ret
= dc
->funcs
->pPolygon(dc
,pt
,count
);
790 GDI_ReleaseObj( hdc
);
796 /**********************************************************************
797 * PolyPolygon (GDI.450)
799 BOOL16 WINAPI
PolyPolygon16( HDC16 hdc
, const POINT16
* pt
, const INT16
* counts
,
808 for (i
=polygons
;i
--;)
810 pt32
= (LPPOINT
)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT
)*nrpts
);
811 if(pt32
== NULL
) return FALSE
;
813 CONV_POINT16TO32(&(pt
[i
]),&(pt32
[i
]));
814 counts32
= (LPINT
)HeapAlloc( GetProcessHeap(), 0, polygons
*sizeof(INT
) );
815 if(counts32
== NULL
) {
816 HeapFree( GetProcessHeap(), 0, pt32
);
819 for (i
=polygons
;i
--;) counts32
[i
]=counts
[i
];
821 ret
= PolyPolygon(hdc
,pt32
,counts32
,polygons
);
822 HeapFree( GetProcessHeap(), 0, counts32
);
823 HeapFree( GetProcessHeap(), 0, pt32
);
827 /**********************************************************************
828 * PolyPolygon (GDI32.@)
830 BOOL WINAPI
PolyPolygon( HDC hdc
, const POINT
* pt
, const INT
* counts
,
834 DC
* dc
= DC_GetDCUpdate( hdc
);
837 if (PATH_IsPathOpen(dc
->path
)) ret
= PATH_PolyPolygon(dc
, pt
, counts
, polygons
);
838 else if (dc
->funcs
->pPolyPolygon
) ret
= dc
->funcs
->pPolyPolygon(dc
,pt
,counts
,polygons
);
839 GDI_ReleaseObj( hdc
);
844 /**********************************************************************
845 * PolyPolyline (GDI32.@)
847 BOOL WINAPI
PolyPolyline( HDC hdc
, const POINT
* pt
, const DWORD
* counts
,
851 DC
* dc
= DC_GetDCUpdate( hdc
);
854 if (PATH_IsPathOpen(dc
->path
)) ret
= PATH_PolyPolyline(dc
, pt
, counts
, polylines
);
855 else if (dc
->funcs
->pPolyPolyline
) ret
= dc
->funcs
->pPolyPolyline(dc
,pt
,counts
,polylines
);
856 GDI_ReleaseObj( hdc
);
861 /**********************************************************************
862 * ExtFloodFill (GDI.372)
864 BOOL16 WINAPI
ExtFloodFill16( HDC16 hdc
, INT16 x
, INT16 y
, COLORREF color
,
867 return ExtFloodFill( hdc
, x
, y
, color
, fillType
);
871 /**********************************************************************
872 * ExtFloodFill (GDI32.@)
874 BOOL WINAPI
ExtFloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
,
878 DC
* dc
= DC_GetDCUpdate( hdc
);
881 if (dc
->funcs
->pExtFloodFill
) ret
= dc
->funcs
->pExtFloodFill(dc
,x
,y
,color
,fillType
);
882 GDI_ReleaseObj( hdc
);
888 /**********************************************************************
891 BOOL16 WINAPI
FloodFill16( HDC16 hdc
, INT16 x
, INT16 y
, COLORREF color
)
893 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
897 /**********************************************************************
898 * FloodFill (GDI32.@)
900 BOOL WINAPI
FloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
)
902 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
906 /******************************************************************************
907 * PolyBezier [GDI.502]
909 BOOL16 WINAPI
PolyBezier16( HDC16 hDc
, const POINT16
* lppt
, INT16 cPoints
)
913 LPPOINT pt32
= (LPPOINT
)HeapAlloc( GetProcessHeap(), 0,
914 cPoints
*sizeof(POINT
) );
915 if(!pt32
) return FALSE
;
916 for (i
=cPoints
;i
--;) CONV_POINT16TO32(&(lppt
[i
]),&(pt32
[i
]));
917 ret
= PolyBezier(hDc
, pt32
, cPoints
);
918 HeapFree( GetProcessHeap(), 0, pt32
);
922 /******************************************************************************
923 * PolyBezierTo [GDI.503]
925 BOOL16 WINAPI
PolyBezierTo16( HDC16 hDc
, const POINT16
* lppt
, INT16 cPoints
)
929 LPPOINT pt32
= (LPPOINT
)HeapAlloc( GetProcessHeap(), 0,
930 cPoints
*sizeof(POINT
) );
931 if(!pt32
) return FALSE
;
932 for (i
=cPoints
;i
--;) CONV_POINT16TO32(&(lppt
[i
]),&(pt32
[i
]));
933 ret
= PolyBezierTo(hDc
, pt32
, cPoints
);
934 HeapFree( GetProcessHeap(), 0, pt32
);
938 /******************************************************************************
939 * PolyBezier [GDI32.@]
940 * Draws one or more Bezier curves
943 * hDc [I] Handle to device context
944 * lppt [I] Pointer to endpoints and control points
945 * cPoints [I] Count of endpoints and control points
949 BOOL WINAPI
PolyBezier( HDC hdc
, const POINT
* lppt
, DWORD cPoints
)
952 DC
* dc
= DC_GetDCUpdate( hdc
);
954 if(!dc
) return FALSE
;
956 if(PATH_IsPathOpen(dc
->path
))
957 ret
= PATH_PolyBezier(dc
, lppt
, cPoints
);
958 else if (dc
->funcs
->pPolyBezier
)
959 ret
= dc
->funcs
->pPolyBezier(dc
, lppt
, cPoints
);
960 else /* We'll convert it into line segments and draw them using Polyline */
965 if ((Pts
= GDI_Bezier( lppt
, cPoints
, &nOut
)))
967 TRACE("Pts = %p, no = %d\n", Pts
, nOut
);
968 ret
= Polyline( dc
->hSelf
, Pts
, nOut
);
969 HeapFree( GetProcessHeap(), 0, Pts
);
973 GDI_ReleaseObj( hdc
);
977 /******************************************************************************
978 * PolyBezierTo [GDI32.@]
979 * Draws one or more Bezier curves
982 * hDc [I] Handle to device context
983 * lppt [I] Pointer to endpoints and control points
984 * cPoints [I] Count of endpoints and control points
988 BOOL WINAPI
PolyBezierTo( HDC hdc
, const POINT
* lppt
, DWORD cPoints
)
990 DC
* dc
= DC_GetDCUpdate( hdc
);
993 if(!dc
) return FALSE
;
995 if(PATH_IsPathOpen(dc
->path
))
996 ret
= PATH_PolyBezierTo(dc
, lppt
, cPoints
);
997 else if(dc
->funcs
->pPolyBezierTo
)
998 ret
= dc
->funcs
->pPolyBezierTo(dc
, lppt
, cPoints
);
999 else { /* We'll do it using PolyBezier */
1001 pt
= HeapAlloc( GetProcessHeap(), 0, sizeof(POINT
) * (cPoints
+ 1) );
1002 if(!pt
) return FALSE
;
1003 pt
[0].x
= dc
->CursPosX
;
1004 pt
[0].y
= dc
->CursPosY
;
1005 memcpy(pt
+ 1, lppt
, sizeof(POINT
) * cPoints
);
1006 ret
= PolyBezier(dc
->hSelf
, pt
, cPoints
+1);
1007 HeapFree( GetProcessHeap(), 0, pt
);
1010 dc
->CursPosX
= lppt
[cPoints
-1].x
;
1011 dc
->CursPosY
= lppt
[cPoints
-1].y
;
1013 GDI_ReleaseObj( hdc
);
1017 /***********************************************************************
1018 * AngleArc (GDI32.@)
1020 BOOL WINAPI
AngleArc(HDC hdc
, INT x
, INT y
, DWORD dwRadius
, FLOAT eStartAngle
, FLOAT eSweepAngle
)
1022 INT x1
,y1
,x2
,y2
, arcdir
;
1026 if( (signed int)dwRadius
< 0 )
1029 dc
= DC_GetDCUpdate( hdc
);
1030 if(!dc
) return FALSE
;
1032 if(dc
->funcs
->pAngleArc
)
1034 result
= dc
->funcs
->pAngleArc( dc
, x
, y
, dwRadius
, eStartAngle
, eSweepAngle
);
1036 GDI_ReleaseObj( hdc
);
1039 GDI_ReleaseObj( hdc
);
1041 /* AngleArc always works counterclockwise */
1042 arcdir
= GetArcDirection( hdc
);
1043 SetArcDirection( hdc
, AD_COUNTERCLOCKWISE
);
1045 x1
= x
+ cos(eStartAngle
*M_PI
/180) * dwRadius
;
1046 y1
= y
- sin(eStartAngle
*M_PI
/180) * dwRadius
;
1047 x2
= x
+ cos((eStartAngle
+eSweepAngle
)*M_PI
/180) * dwRadius
;
1048 y2
= x
- sin((eStartAngle
+eSweepAngle
)*M_PI
/180) * dwRadius
;
1050 LineTo( hdc
, x1
, y1
);
1051 if( eSweepAngle
>= 0 )
1052 result
= Arc( hdc
, x
-dwRadius
, y
-dwRadius
, x
+dwRadius
, y
+dwRadius
,
1055 result
= Arc( hdc
, x
-dwRadius
, y
-dwRadius
, x
+dwRadius
, y
+dwRadius
,
1058 if( result
) MoveToEx( hdc
, x2
, y2
, NULL
);
1059 SetArcDirection( hdc
, arcdir
);
1063 /***********************************************************************
1064 * PolyDraw (GDI32.@)
1066 BOOL WINAPI
PolyDraw(HDC hdc
, const POINT
*lppt
, const BYTE
*lpbTypes
,
1074 dc
= DC_GetDCUpdate( hdc
);
1075 if(!dc
) return FALSE
;
1077 if(dc
->funcs
->pPolyDraw
)
1079 result
= dc
->funcs
->pPolyDraw( dc
, lppt
, lpbTypes
, cCount
);
1080 GDI_ReleaseObj( hdc
);
1083 GDI_ReleaseObj( hdc
);
1085 /* check for each bezierto if there are two more points */
1086 for( i
= 0; i
< cCount
; i
++ )
1087 if( lpbTypes
[i
] != PT_MOVETO
&&
1088 lpbTypes
[i
] & PT_BEZIERTO
)
1096 /* if no moveto occurs, we will close the figure here */
1097 lastmove
.x
= dc
->CursPosX
;
1098 lastmove
.y
= dc
->CursPosY
;
1100 /* now let's draw */
1101 for( i
= 0; i
< cCount
; i
++ )
1103 if( lpbTypes
[i
] == PT_MOVETO
)
1105 MoveToEx( hdc
, lppt
[i
].x
, lppt
[i
].y
, NULL
);
1106 lastmove
.x
= dc
->CursPosX
;
1107 lastmove
.y
= dc
->CursPosY
;
1109 else if( lpbTypes
[i
] & PT_LINETO
)
1110 LineTo( hdc
, lppt
[i
].x
, lppt
[i
].y
);
1111 else if( lpbTypes
[i
] & PT_BEZIERTO
)
1113 PolyBezierTo( hdc
, &lppt
[i
], 3 );
1119 if( lpbTypes
[i
] & PT_CLOSEFIGURE
)
1121 if( PATH_IsPathOpen( dc
->path
) )
1124 LineTo( hdc
, lastmove
.x
, lastmove
.y
);
1131 /******************************************************************
1133 * *Very* simple bezier drawing code,
1135 * It uses a recursive algorithm to divide the curve in a series
1136 * of straight line segements. Not ideal but for me sufficient.
1137 * If you are in need for something better look for some incremental
1140 * 7 July 1998 Rein Klazes
1144 * some macro definitions for bezier drawing
1146 * to avoid trucation errors the coordinates are
1147 * shifted upwards. When used in drawing they are
1148 * shifted down again, including correct rounding
1149 * and avoiding floating point arithmatic
1150 * 4 bits should allow 27 bits coordinates which I saw
1151 * somewere in the win32 doc's
1155 #define BEZIERSHIFTBITS 4
1156 #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
1157 #define BEZIERPIXEL BEZIERSHIFTUP(1)
1158 #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
1159 /* maximum depth of recursion */
1160 #define BEZIERMAXDEPTH 8
1162 /* size of array to store points on */
1163 /* enough for one curve */
1164 #define BEZIER_INITBUFSIZE (150)
1166 /* calculate Bezier average, in this case the middle
1167 * correctly rounded...
1170 #define BEZIERMIDDLE(Mid, P1, P2) \
1171 (Mid).x=((P1).x+(P2).x + 1)/2;\
1172 (Mid).y=((P1).y+(P2).y + 1)/2;
1174 /**********************************************************
1175 * BezierCheck helper function to check
1176 * that recursion can be terminated
1177 * Points[0] and Points[3] are begin and endpoint
1178 * Points[1] and Points[2] are control points
1179 * level is the recursion depth
1180 * returns true if the recusion can be terminated
1182 static BOOL
BezierCheck( int level
, POINT
*Points
)
1185 dx
=Points
[3].x
-Points
[0].x
;
1186 dy
=Points
[3].y
-Points
[0].y
;
1187 if(abs(dy
)<=abs(dx
)){/* shallow line */
1188 /* check that control points are between begin and end */
1189 if(Points
[1].x
< Points
[0].x
){
1190 if(Points
[1].x
< Points
[3].x
)
1193 if(Points
[1].x
> Points
[3].x
)
1195 if(Points
[2].x
< Points
[0].x
){
1196 if(Points
[2].x
< Points
[3].x
)
1199 if(Points
[2].x
> Points
[3].x
)
1201 dx
=BEZIERSHIFTDOWN(dx
);
1202 if(!dx
) return TRUE
;
1203 if(abs(Points
[1].y
-Points
[0].y
-(dy
/dx
)*
1204 BEZIERSHIFTDOWN(Points
[1].x
-Points
[0].x
)) > BEZIERPIXEL
||
1205 abs(Points
[2].y
-Points
[0].y
-(dy
/dx
)*
1206 BEZIERSHIFTDOWN(Points
[2].x
-Points
[0].x
)) > BEZIERPIXEL
)
1210 }else{ /* steep line */
1211 /* check that control points are between begin and end */
1212 if(Points
[1].y
< Points
[0].y
){
1213 if(Points
[1].y
< Points
[3].y
)
1216 if(Points
[1].y
> Points
[3].y
)
1218 if(Points
[2].y
< Points
[0].y
){
1219 if(Points
[2].y
< Points
[3].y
)
1222 if(Points
[2].y
> Points
[3].y
)
1224 dy
=BEZIERSHIFTDOWN(dy
);
1225 if(!dy
) return TRUE
;
1226 if(abs(Points
[1].x
-Points
[0].x
-(dx
/dy
)*
1227 BEZIERSHIFTDOWN(Points
[1].y
-Points
[0].y
)) > BEZIERPIXEL
||
1228 abs(Points
[2].x
-Points
[0].x
-(dx
/dy
)*
1229 BEZIERSHIFTDOWN(Points
[2].y
-Points
[0].y
)) > BEZIERPIXEL
)
1236 /* Helper for GDI_Bezier.
1237 * Just handles one Bezier, so Points should point to four POINTs
1239 static void GDI_InternalBezier( POINT
*Points
, POINT
**PtsOut
, INT
*dwOut
,
1240 INT
*nPtsOut
, INT level
)
1242 if(*nPtsOut
== *dwOut
) {
1244 *PtsOut
= HeapReAlloc( GetProcessHeap(), 0, *PtsOut
,
1245 *dwOut
* sizeof(POINT
) );
1248 if(!level
|| BezierCheck(level
, Points
)) {
1250 (*PtsOut
)[0].x
= BEZIERSHIFTDOWN(Points
[0].x
);
1251 (*PtsOut
)[0].y
= BEZIERSHIFTDOWN(Points
[0].y
);
1254 (*PtsOut
)[*nPtsOut
].x
= BEZIERSHIFTDOWN(Points
[3].x
);
1255 (*PtsOut
)[*nPtsOut
].y
= BEZIERSHIFTDOWN(Points
[3].y
);
1258 POINT Points2
[4]; /* for the second recursive call */
1259 Points2
[3]=Points
[3];
1260 BEZIERMIDDLE(Points2
[2], Points
[2], Points
[3]);
1261 BEZIERMIDDLE(Points2
[0], Points
[1], Points
[2]);
1262 BEZIERMIDDLE(Points2
[1],Points2
[0],Points2
[2]);
1264 BEZIERMIDDLE(Points
[1], Points
[0], Points
[1]);
1265 BEZIERMIDDLE(Points
[2], Points
[1], Points2
[0]);
1266 BEZIERMIDDLE(Points
[3], Points
[2], Points2
[1]);
1268 Points2
[0]=Points
[3];
1270 /* do the two halves */
1271 GDI_InternalBezier(Points
, PtsOut
, dwOut
, nPtsOut
, level
-1);
1272 GDI_InternalBezier(Points2
, PtsOut
, dwOut
, nPtsOut
, level
-1);
1278 /***********************************************************************
1279 * GDI_Bezier [INTERNAL]
1280 * Calculate line segments that approximate -what microsoft calls- a bezier
1282 * The routine recursively divides the curve in two parts until a straight
1287 * Points [I] Ptr to count POINTs which are the end and control points
1288 * of the set of Bezier curves to flatten.
1289 * count [I] Number of Points. Must be 3n+1.
1290 * nPtsOut [O] Will contain no of points that have been produced (i.e. no. of
1295 * Ptr to an array of POINTs that contain the lines that approximinate the
1296 * Beziers. The array is allocated on the process heap and it is the caller's
1297 * responsibility to HeapFree it. [this is not a particularly nice interface
1298 * but since we can't know in advance how many points will generate, the
1299 * alternative would be to call the function twice, once to determine the size
1300 * and a second time to do the work - I decided this was too much of a pain].
1302 POINT
*GDI_Bezier( const POINT
*Points
, INT count
, INT
*nPtsOut
)
1305 INT Bezier
, dwOut
= BEZIER_INITBUFSIZE
, i
;
1307 if((count
- 1) % 3 != 0) {
1308 ERR("Invalid no. of points\n");
1312 out
= HeapAlloc( GetProcessHeap(), 0, dwOut
* sizeof(POINT
));
1313 for(Bezier
= 0; Bezier
< (count
-1)/3; Bezier
++) {
1315 memcpy(ptBuf
, Points
+ Bezier
* 3, sizeof(POINT
) * 4);
1316 for(i
= 0; i
< 4; i
++) {
1317 ptBuf
[i
].x
= BEZIERSHIFTUP(ptBuf
[i
].x
);
1318 ptBuf
[i
].y
= BEZIERSHIFTUP(ptBuf
[i
].y
);
1320 GDI_InternalBezier( ptBuf
, &out
, &dwOut
, nPtsOut
, BEZIERMAXDEPTH
);
1322 TRACE("Produced %d points\n", *nPtsOut
);