2 * GDI drawing functions.
4 * Copyright 1993, 1994 Alexandre Julliard
5 * Copyright 1997 Bertho A. Stultiens
15 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(gdi
);
23 /***********************************************************************
26 BOOL16 WINAPI
LineTo16( HDC16 hdc
, INT16 x
, INT16 y
)
28 return LineTo( hdc
, x
, y
);
32 /***********************************************************************
35 BOOL WINAPI
LineTo( HDC hdc
, INT x
, INT y
)
37 DC
* dc
= DC_GetDCUpdate( hdc
);
42 if(PATH_IsPathOpen(dc
->w
.path
))
43 ret
= PATH_LineTo(dc
, x
, y
);
45 ret
= dc
->funcs
->pLineTo
&& dc
->funcs
->pLineTo(dc
,x
,y
);
50 GDI_ReleaseObj( hdc
);
55 /***********************************************************************
58 DWORD WINAPI
MoveTo16( HDC16 hdc
, INT16 x
, INT16 y
)
62 if (!MoveToEx16(hdc
,x
,y
,&pt
))
64 return MAKELONG(pt
.x
,pt
.y
);
68 /***********************************************************************
69 * MoveToEx16 (GDI.483)
71 BOOL16 WINAPI
MoveToEx16( HDC16 hdc
, INT16 x
, INT16 y
, LPPOINT16 pt
)
75 if (!MoveToEx( (HDC
)hdc
, (INT
)x
, (INT
)y
, &pt32
)) return FALSE
;
76 if (pt
) CONV_POINT32TO16( &pt32
, pt
);
82 /***********************************************************************
83 * MoveToEx (GDI32.254)
85 BOOL WINAPI
MoveToEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
88 DC
* dc
= DC_GetDCUpdate( hdc
);
93 pt
->x
= dc
->w
.CursPosX
;
94 pt
->y
= dc
->w
.CursPosY
;
99 if(PATH_IsPathOpen(dc
->w
.path
)) ret
= PATH_MoveTo(dc
);
100 else if (dc
->funcs
->pMoveToEx
) ret
= dc
->funcs
->pMoveToEx(dc
,x
,y
,pt
);
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
->w
.path
))
131 ret
= PATH_Arc(dc
, left
, top
, right
, bottom
, xstart
, ystart
, xend
, yend
);
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
);
202 if (PATH_IsPathOpen(dc
->w
.path
))
203 FIXME("-> Path: stub\n");
204 else if (dc
->funcs
->pPie
)
205 ret
= dc
->funcs
->pPie(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
);
206 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
);
234 if(PATH_IsPathOpen(dc
->w
.path
))
235 FIXME("-> Path: stub\n");
236 else if (dc
->funcs
->pChord
)
237 ret
= dc
->funcs
->pChord(dc
,left
,top
,right
,bottom
,xstart
,ystart
,xend
,yend
);
238 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
);
264 if(PATH_IsPathOpen(dc
->w
.path
))
265 FIXME("-> Path: stub\n");
266 else if (dc
->funcs
->pEllipse
)
267 ret
= dc
->funcs
->pEllipse(dc
,left
,top
,right
,bottom
);
268 GDI_ReleaseObj( hdc
);
274 /***********************************************************************
275 * Rectangle16 (GDI.27)
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.283)
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
->w
.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 /***********************************************************************
305 * RoundRect16 (GDI.28)
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.291)
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
->w
.path
))
326 FIXME("-> Path: stub\n");
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 /***********************************************************************
335 * SetPixel16 (GDI.31)
337 COLORREF WINAPI
SetPixel16( HDC16 hdc
, INT16 x
, INT16 y
, COLORREF color
)
339 return SetPixel( hdc
, x
, y
, color
);
343 /***********************************************************************
344 * SetPixel (GDI32.327)
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.329)
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 /***********************************************************************
378 * GetPixel16 (GDI.83)
380 COLORREF WINAPI
GetPixel16( HDC16 hdc
, INT16 x
, INT16 y
)
382 return GetPixel( hdc
, x
, y
);
386 /***********************************************************************
387 * GetPixel (GDI32.211)
389 COLORREF WINAPI
GetPixel( HDC hdc
, INT x
, INT y
)
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.13]
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.328]
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.212]
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.71]
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.354]
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 /***********************************************************************
562 * PaintRgn16 (GDI.43)
564 BOOL16 WINAPI
PaintRgn16( HDC16 hdc
, HRGN16 hrgn
)
566 return PaintRgn( hdc
, hrgn
);
570 /***********************************************************************
571 * PaintRgn (GDI32.259)
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 /***********************************************************************
596 * FillRgn (GDI32.101)
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 /***********************************************************************
618 * FrameRgn16 (GDI.41)
620 BOOL16 WINAPI
FrameRgn16( HDC16 hdc
, HRGN16 hrgn
, HBRUSH16 hbrush
,
621 INT16 nWidth
, INT16 nHeight
)
623 return FrameRgn( hdc
, hrgn
, hbrush
, nWidth
, nHeight
);
627 /***********************************************************************
628 * FrameRgn (GDI32.105)
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 /***********************************************************************
658 * InvertRgn16 (GDI.42)
660 BOOL16 WINAPI
InvertRgn16( HDC16 hdc
, HRGN16 hrgn
)
662 return InvertRgn( hdc
, hrgn
);
666 /***********************************************************************
667 * InvertRgn (GDI32.246)
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 /**********************************************************************
692 * Polyline16 (GDI.37)
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 /**********************************************************************
710 * Polyline (GDI32.276)
712 BOOL WINAPI
Polyline( HDC hdc
, const POINT
* pt
, INT count
)
715 DC
* dc
= DC_GetDCUpdate( hdc
);
718 if (PATH_IsPathOpen(dc
->w
.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.277)
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
->w
.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
->w
.CursPosX
;
747 pts
[0].y
= dc
->w
.CursPosY
;
748 memcpy( pts
+ 1, pt
, sizeof(POINT
) * cCount
);
749 ret
= Polyline( hdc
, pts
, cCount
+ 1 );
750 HeapFree( GetProcessHeap(), 0, pts
);
754 dc
->w
.CursPosX
= pt
[cCount
-1].x
;
755 dc
->w
.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 /**********************************************************************
780 * Polygon (GDI32.275)
782 BOOL WINAPI
Polygon( HDC hdc
, const POINT
* pt
, INT count
)
785 DC
* dc
= DC_GetDCUpdate( hdc
);
788 if (PATH_IsPathOpen(dc
->w
.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 * PolyPolygon16 (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 (GDI.450)
830 BOOL WINAPI
PolyPolygon( HDC hdc
, const POINT
* pt
, const INT
* counts
,
834 DC
* dc
= DC_GetDCUpdate( hdc
);
837 if (PATH_IsPathOpen(dc
->w
.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.272)
847 BOOL WINAPI
PolyPolyline( HDC hdc
, const POINT
* pt
, const DWORD
* counts
,
851 DC
* dc
= DC_GetDCUpdate( hdc
);
854 if (PATH_IsPathOpen(dc
->w
.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 * ExtFloodFill16 (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.96)
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 /**********************************************************************
889 * FloodFill16 (GDI.25)
891 BOOL16 WINAPI
FloodFill16( HDC16 hdc
, INT16 x
, INT16 y
, COLORREF color
)
893 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
897 /**********************************************************************
898 * FloodFill (GDI32.104)
900 BOOL WINAPI
FloodFill( HDC hdc
, INT x
, INT y
, COLORREF color
)
902 return ExtFloodFill( hdc
, x
, y
, color
, FLOODFILLBORDER
);
906 /******************************************************************************
907 * PolyBezier16 [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 * PolyBezierTo16 [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.268]
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
->w
.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.269]
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
->w
.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
->w
.CursPosX
;
1004 pt
[0].y
= dc
->w
.CursPosY
;
1005 memcpy(pt
+ 1, lppt
, sizeof(POINT
) * cPoints
);
1006 ret
= PolyBezier(dc
->hSelf
, pt
, cPoints
+1);
1007 HeapFree( GetProcessHeap(), 0, pt
);
1010 dc
->w
.CursPosX
= lppt
[cPoints
-1].x
;
1011 dc
->w
.CursPosY
= lppt
[cPoints
-1].y
;
1013 GDI_ReleaseObj( hdc
);
1017 /***********************************************************************
1018 * AngleArc (GDI32.5)
1021 BOOL WINAPI
AngleArc(HDC hdc
, INT x
, INT y
, DWORD dwRadius
,
1022 FLOAT eStartAngle
, FLOAT eSweepAngle
)
1028 if( (signed int)dwRadius
< 0 )
1031 dc
= DC_GetDCUpdate( hdc
);
1032 if(!dc
) return FALSE
;
1034 if(dc
->funcs
->pAngleArc
)
1036 result
= dc
->funcs
->pAngleArc( dc
, x
, y
, dwRadius
, eStartAngle
, eSweepAngle
);
1037 GDI_ReleaseObj( hdc
);
1040 GDI_ReleaseObj( hdc
);
1042 x1
= x
+ cos(eStartAngle
*M_PI
/180) * dwRadius
;
1043 y1
= y
- sin(eStartAngle
*M_PI
/180) * dwRadius
;
1044 x2
= x
+ cos((eStartAngle
+eSweepAngle
)*M_PI
/180) * dwRadius
;
1045 y2
= x
- sin((eStartAngle
+eSweepAngle
)*M_PI
/180) * dwRadius
;
1047 LineTo( hdc
, x1
, y1
);
1048 if( eSweepAngle
>= 0 )
1049 result
= Arc( hdc
, x
-dwRadius
, y
-dwRadius
, x
+dwRadius
, y
+dwRadius
,
1052 result
= Arc( hdc
, x
-dwRadius
, y
-dwRadius
, x
+dwRadius
, y
+dwRadius
,
1055 if( result
) MoveToEx( hdc
, x2
, y2
, NULL
);
1059 /***********************************************************************
1060 * PolyDraw (GDI32.270)
1063 BOOL WINAPI
PolyDraw(HDC hdc
, const POINT
*lppt
, const BYTE
*lpbTypes
,
1071 dc
= DC_GetDCUpdate( hdc
);
1072 if(!dc
) return FALSE
;
1074 if(dc
->funcs
->pPolyDraw
)
1076 result
= dc
->funcs
->pPolyDraw( dc
, lppt
, lpbTypes
, cCount
);
1077 GDI_ReleaseObj( hdc
);
1080 GDI_ReleaseObj( hdc
);
1082 /* check for each bezierto if there are two more points */
1083 for( i
= 0; i
< cCount
; i
++ )
1084 if( lpbTypes
[i
] != PT_MOVETO
&&
1085 lpbTypes
[i
] & PT_BEZIERTO
)
1093 /* if no moveto occurs, we will close the figure here */
1094 lastmove
.x
= dc
->w
.CursPosX
;
1095 lastmove
.y
= dc
->w
.CursPosY
;
1097 /* now let's draw */
1098 for( i
= 0; i
< cCount
; i
++ )
1099 if( lpbTypes
[i
] == PT_MOVETO
)
1101 MoveToEx( hdc
, lppt
[i
].x
, lppt
[i
].y
, NULL
);
1102 lastmove
.x
= dc
->w
.CursPosX
;
1103 lastmove
.y
= dc
->w
.CursPosY
;
1105 else if( lpbTypes
[i
] & PT_LINETO
)
1107 LineTo( hdc
, lppt
[i
].x
, lppt
[i
].y
);
1108 if( lpbTypes
[i
] & PT_CLOSEFIGURE
)
1109 LineTo( hdc
, lastmove
.x
, lastmove
.y
);
1111 else if( lpbTypes
[i
] & PT_BEZIERTO
)
1113 /* optimizeme: multiple BezierTo's with one PolyBezierTo call */
1114 PolyBezierTo( hdc
, &lppt
[i
], 3 );
1118 if( lpbTypes
[i
] & PT_CLOSEFIGURE
)
1119 LineTo( hdc
, lastmove
.x
, lastmove
.y
);
1127 /******************************************************************
1129 * *Very* simple bezier drawing code,
1131 * It uses a recursive algorithm to divide the curve in a series
1132 * of straight line segements. Not ideal but for me sufficient.
1133 * If you are in need for something better look for some incremental
1136 * 7 July 1998 Rein Klazes
1140 * some macro definitions for bezier drawing
1142 * to avoid trucation errors the coordinates are
1143 * shifted upwards. When used in drawing they are
1144 * shifted down again, including correct rounding
1145 * and avoiding floating point arithmatic
1146 * 4 bits should allow 27 bits coordinates which I saw
1147 * somewere in the win32 doc's
1151 #define BEZIERSHIFTBITS 4
1152 #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
1153 #define BEZIERPIXEL BEZIERSHIFTUP(1)
1154 #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
1155 /* maximum depth of recursion */
1156 #define BEZIERMAXDEPTH 8
1158 /* size of array to store points on */
1159 /* enough for one curve */
1160 #define BEZIER_INITBUFSIZE (150)
1162 /* calculate Bezier average, in this case the middle
1163 * correctly rounded...
1166 #define BEZIERMIDDLE(Mid, P1, P2) \
1167 (Mid).x=((P1).x+(P2).x + 1)/2;\
1168 (Mid).y=((P1).y+(P2).y + 1)/2;
1170 /**********************************************************
1171 * BezierCheck helper function to check
1172 * that recursion can be terminated
1173 * Points[0] and Points[3] are begin and endpoint
1174 * Points[1] and Points[2] are control points
1175 * level is the recursion depth
1176 * returns true if the recusion can be terminated
1178 static BOOL
BezierCheck( int level
, POINT
*Points
)
1181 dx
=Points
[3].x
-Points
[0].x
;
1182 dy
=Points
[3].y
-Points
[0].y
;
1183 if(abs(dy
)<=abs(dx
)){/* shallow line */
1184 /* check that control points are between begin and end */
1185 if(Points
[1].x
< Points
[0].x
){
1186 if(Points
[1].x
< Points
[3].x
)
1189 if(Points
[1].x
> Points
[3].x
)
1191 if(Points
[2].x
< Points
[0].x
){
1192 if(Points
[2].x
< Points
[3].x
)
1195 if(Points
[2].x
> Points
[3].x
)
1197 dx
=BEZIERSHIFTDOWN(dx
);
1198 if(!dx
) return TRUE
;
1199 if(abs(Points
[1].y
-Points
[0].y
-(dy
/dx
)*
1200 BEZIERSHIFTDOWN(Points
[1].x
-Points
[0].x
)) > BEZIERPIXEL
||
1201 abs(Points
[2].y
-Points
[0].y
-(dy
/dx
)*
1202 BEZIERSHIFTDOWN(Points
[2].x
-Points
[0].x
)) > BEZIERPIXEL
)
1206 }else{ /* steep line */
1207 /* check that control points are between begin and end */
1208 if(Points
[1].y
< Points
[0].y
){
1209 if(Points
[1].y
< Points
[3].y
)
1212 if(Points
[1].y
> Points
[3].y
)
1214 if(Points
[2].y
< Points
[0].y
){
1215 if(Points
[2].y
< Points
[3].y
)
1218 if(Points
[2].y
> Points
[3].y
)
1220 dy
=BEZIERSHIFTDOWN(dy
);
1221 if(!dy
) return TRUE
;
1222 if(abs(Points
[1].x
-Points
[0].x
-(dx
/dy
)*
1223 BEZIERSHIFTDOWN(Points
[1].y
-Points
[0].y
)) > BEZIERPIXEL
||
1224 abs(Points
[2].x
-Points
[0].x
-(dx
/dy
)*
1225 BEZIERSHIFTDOWN(Points
[2].y
-Points
[0].y
)) > BEZIERPIXEL
)
1232 /* Helper for GDI_Bezier.
1233 * Just handles one Bezier, so Points should point to four POINTs
1235 static void GDI_InternalBezier( POINT
*Points
, POINT
**PtsOut
, INT
*dwOut
,
1236 INT
*nPtsOut
, INT level
)
1238 if(*nPtsOut
== *dwOut
) {
1240 *PtsOut
= HeapReAlloc( GetProcessHeap(), 0, *PtsOut
,
1241 *dwOut
* sizeof(POINT
) );
1244 if(!level
|| BezierCheck(level
, Points
)) {
1246 (*PtsOut
)[0].x
= BEZIERSHIFTDOWN(Points
[0].x
);
1247 (*PtsOut
)[0].y
= BEZIERSHIFTDOWN(Points
[0].y
);
1250 (*PtsOut
)[*nPtsOut
].x
= BEZIERSHIFTDOWN(Points
[3].x
);
1251 (*PtsOut
)[*nPtsOut
].y
= BEZIERSHIFTDOWN(Points
[3].y
);
1254 POINT Points2
[4]; /* for the second recursive call */
1255 Points2
[3]=Points
[3];
1256 BEZIERMIDDLE(Points2
[2], Points
[2], Points
[3]);
1257 BEZIERMIDDLE(Points2
[0], Points
[1], Points
[2]);
1258 BEZIERMIDDLE(Points2
[1],Points2
[0],Points2
[2]);
1260 BEZIERMIDDLE(Points
[1], Points
[0], Points
[1]);
1261 BEZIERMIDDLE(Points
[2], Points
[1], Points2
[0]);
1262 BEZIERMIDDLE(Points
[3], Points
[2], Points2
[1]);
1264 Points2
[0]=Points
[3];
1266 /* do the two halves */
1267 GDI_InternalBezier(Points
, PtsOut
, dwOut
, nPtsOut
, level
-1);
1268 GDI_InternalBezier(Points2
, PtsOut
, dwOut
, nPtsOut
, level
-1);
1274 /***********************************************************************
1275 * GDI_Bezier [INTERNAL]
1276 * Calculate line segments that approximate -what microsoft calls- a bezier
1278 * The routine recursively divides the curve in two parts until a straight
1283 * Points [I] Ptr to count POINTs which are the end and control points
1284 * of the set of Bezier curves to flatten.
1285 * count [I] Number of Points. Must be 3n+1.
1286 * nPtsOut [O] Will contain no of points that have been produced (i.e. no. of
1291 * Ptr to an array of POINTs that contain the lines that approximinate the
1292 * Beziers. The array is allocated on the process heap and it is the caller's
1293 * responsibility to HeapFree it. [this is not a particularly nice interface
1294 * but since we can't know in advance how many points will generate, the
1295 * alternative would be to call the function twice, once to determine the size
1296 * and a second time to do the work - I decided this was too much of a pain].
1298 POINT
*GDI_Bezier( const POINT
*Points
, INT count
, INT
*nPtsOut
)
1301 INT Bezier
, dwOut
= BEZIER_INITBUFSIZE
, i
;
1303 if((count
- 1) % 3 != 0) {
1304 ERR("Invalid no. of points\n");
1308 out
= HeapAlloc( GetProcessHeap(), 0, dwOut
* sizeof(POINT
));
1309 for(Bezier
= 0; Bezier
< (count
-1)/3; Bezier
++) {
1311 memcpy(ptBuf
, Points
+ Bezier
* 3, sizeof(POINT
) * 4);
1312 for(i
= 0; i
< 4; i
++) {
1313 ptBuf
[i
].x
= BEZIERSHIFTUP(ptBuf
[i
].x
);
1314 ptBuf
[i
].y
= BEZIERSHIFTUP(ptBuf
[i
].y
);
1316 GDI_InternalBezier( ptBuf
, &out
, &dwOut
, nPtsOut
, BEZIERMAXDEPTH
);
1318 TRACE("Produced %d points\n", *nPtsOut
);