Replaced GetDC by CreateDC.
[wine.git] / graphics / painting.c
bloba507c61c07400b6027d138b0fab67028b36dc441
1 /*
2 * GDI drawing functions.
4 * Copyright 1993, 1994 Alexandre Julliard
5 * Copyright 1997 Bertho A. Stultiens
6 * 1999 Huw D M Davies
7 */
9 #include <string.h>
10 #include "dc.h"
11 #include "bitmap.h"
12 #include "heap.h"
13 #include "monitor.h"
14 #include "cache.h"
15 #include "region.h"
16 #include "path.h"
17 #include "debugtools.h"
18 #include "winerror.h"
19 #include "windef.h"
20 #include "wingdi.h"
21 #include "winuser.h"
22 #include "wine/winuser16.h"
24 DEFAULT_DEBUG_CHANNEL(gdi)
27 /***********************************************************************
28 * LineTo16 (GDI.19)
30 BOOL16 WINAPI LineTo16( HDC16 hdc, INT16 x, INT16 y )
32 return LineTo( hdc, x, y );
36 /***********************************************************************
37 * LineTo (GDI32.249)
39 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
41 DC * dc = DC_GetDCPtr( hdc );
42 BOOL ret;
44 if(!dc) return FALSE;
46 if(PATH_IsPathOpen(dc->w.path))
47 ret = PATH_LineTo(hdc, x, y);
48 else
49 ret = dc->funcs->pLineTo && dc->funcs->pLineTo(dc,x,y);
50 if(ret) {
51 dc->w.CursPosX = x;
52 dc->w.CursPosY = y;
54 return ret;
58 /***********************************************************************
59 * MoveTo16 (GDI.20)
61 DWORD WINAPI MoveTo16( HDC16 hdc, INT16 x, INT16 y )
63 POINT16 pt;
65 if (!MoveToEx16(hdc,x,y,&pt))
66 return 0;
67 return MAKELONG(pt.x,pt.y);
71 /***********************************************************************
72 * MoveToEx16 (GDI.483)
74 BOOL16 WINAPI MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
76 POINT pt32;
78 if (!MoveToEx( (HDC)hdc, (INT)x, (INT)y, &pt32 )) return FALSE;
79 if (pt) CONV_POINT32TO16( &pt32, pt );
80 return TRUE;
85 /***********************************************************************
86 * MoveToEx (GDI32.254)
88 BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
90 DC * dc = DC_GetDCPtr( hdc );
92 if(!dc) return FALSE;
94 if(pt) {
95 pt->x = dc->w.CursPosX;
96 pt->y = dc->w.CursPosY;
98 dc->w.CursPosX = x;
99 dc->w.CursPosY = y;
101 if(PATH_IsPathOpen(dc->w.path))
102 return PATH_MoveTo(hdc);
104 if(dc->funcs->pMoveToEx)
105 return dc->funcs->pMoveToEx(dc,x,y,pt);
106 return FALSE;
110 /***********************************************************************
111 * Arc16 (GDI.23)
113 BOOL16 WINAPI Arc16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
114 INT16 bottom, INT16 xstart, INT16 ystart,
115 INT16 xend, INT16 yend )
117 return Arc( (HDC)hdc, (INT)left, (INT)top, (INT)right,
118 (INT)bottom, (INT)xstart, (INT)ystart, (INT)xend,
119 (INT)yend );
123 /***********************************************************************
124 * Arc (GDI32.7)
126 BOOL WINAPI Arc( HDC hdc, INT left, INT top, INT right,
127 INT bottom, INT xstart, INT ystart,
128 INT xend, INT yend )
130 DC * dc = DC_GetDCPtr( hdc );
131 if(!dc) return FALSE;
133 if(PATH_IsPathOpen(dc->w.path))
134 return PATH_Arc(hdc, left, top, right, bottom, xstart, ystart, xend,
135 yend);
137 return dc->funcs->pArc &&
138 dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
141 /***********************************************************************
142 * ArcTo (GDI32.8)
144 BOOL WINAPI ArcTo( HDC hdc,
145 INT left, INT top,
146 INT right, INT bottom,
147 INT xstart, INT ystart,
148 INT xend, INT yend )
150 BOOL result;
151 DC * dc = DC_GetDCPtr( hdc );
152 if(!dc) return FALSE;
154 if(dc->funcs->pArcTo)
155 return dc->funcs->pArcTo( dc, left, top, right, bottom,
156 xstart, ystart, xend, yend );
158 * Else emulate it.
159 * According to the documentation, a line is drawn from the current
160 * position to the starting point of the arc.
162 LineTo(hdc, xstart, ystart);
165 * Then the arc is drawn.
167 result = Arc(hdc,
168 left, top,
169 right, bottom,
170 xstart, ystart,
171 xend, yend);
174 * If no error occured, the current position is moved to the ending
175 * point of the arc.
177 if (result)
179 MoveToEx(hdc, xend, yend, NULL);
182 return result;
185 /***********************************************************************
186 * Pie16 (GDI.26)
188 BOOL16 WINAPI Pie16( HDC16 hdc, INT16 left, INT16 top,
189 INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
190 INT16 xend, INT16 yend )
192 return Pie( (HDC)hdc, (INT)left, (INT)top, (INT)right,
193 (INT)bottom, (INT)xstart, (INT)ystart, (INT)xend,
194 (INT)yend );
198 /***********************************************************************
199 * Pie (GDI32.262)
201 BOOL WINAPI Pie( HDC hdc, INT left, INT top,
202 INT right, INT bottom, INT xstart, INT ystart,
203 INT xend, INT yend )
205 DC * dc = DC_GetDCPtr( hdc );
206 if(!dc) return FALSE;
208 if(PATH_IsPathOpen(dc->w.path)) {
209 FIXME("-> Path: stub\n");
210 return FALSE;
213 return dc->funcs->pPie &&
214 dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
218 /***********************************************************************
219 * Chord16 (GDI.348)
221 BOOL16 WINAPI Chord16( HDC16 hdc, INT16 left, INT16 top,
222 INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
223 INT16 xend, INT16 yend )
225 return Chord( hdc, left, top, right, bottom, xstart, ystart, xend, yend );
229 /***********************************************************************
230 * Chord (GDI32.14)
232 BOOL WINAPI Chord( HDC hdc, INT left, INT top,
233 INT right, INT bottom, INT xstart, INT ystart,
234 INT xend, INT yend )
236 DC * dc = DC_GetDCPtr( hdc );
237 if(!dc) return FALSE;
239 if(PATH_IsPathOpen(dc->w.path)) {
240 FIXME("-> Path: stub\n");
241 return FALSE;
244 return dc->funcs->pChord &&
245 dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
249 /***********************************************************************
250 * Ellipse16 (GDI.24)
252 BOOL16 WINAPI Ellipse16( HDC16 hdc, INT16 left, INT16 top,
253 INT16 right, INT16 bottom )
255 return Ellipse( hdc, left, top, right, bottom );
259 /***********************************************************************
260 * Ellipse (GDI32.75)
262 BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
263 INT right, INT bottom )
265 DC * dc = DC_GetDCPtr( hdc );
266 if(!dc) return FALSE;
268 if(PATH_IsPathOpen(dc->w.path)) {
269 FIXME("-> Path: stub\n");
270 return FALSE;
273 return dc->funcs->pEllipse &&
274 dc->funcs->pEllipse(dc,left,top,right,bottom);
278 /***********************************************************************
279 * Rectangle16 (GDI.27)
281 BOOL16 WINAPI Rectangle16( HDC16 hdc, INT16 left, INT16 top,
282 INT16 right, INT16 bottom )
284 return Rectangle( hdc, left, top, right, bottom );
288 /***********************************************************************
289 * Rectangle (GDI32.283)
291 BOOL WINAPI Rectangle( HDC hdc, INT left, INT top,
292 INT right, INT bottom )
294 DC * dc = DC_GetDCPtr( hdc );
295 if(!dc) return FALSE;
297 if(PATH_IsPathOpen(dc->w.path))
298 return PATH_Rectangle(hdc, left, top, right, bottom);
300 return dc->funcs->pRectangle &&
301 dc->funcs->pRectangle(dc,left,top,right,bottom);
305 /***********************************************************************
306 * RoundRect16 (GDI.28)
308 BOOL16 WINAPI RoundRect16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
309 INT16 bottom, INT16 ell_width, INT16 ell_height )
311 return RoundRect( hdc, left, top, right, bottom, ell_width, ell_height );
315 /***********************************************************************
316 * RoundRect (GDI32.291)
318 BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
319 INT bottom, INT ell_width, INT ell_height )
321 DC * dc = DC_GetDCPtr( hdc );
322 if(!dc) return FALSE;
324 if(PATH_IsPathOpen(dc->w.path)) {
325 FIXME("-> Path: stub\n");
326 return FALSE;
329 return dc->funcs->pRoundRect &&
330 dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
333 /***********************************************************************
334 * SetPixel16 (GDI.31)
336 COLORREF WINAPI SetPixel16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
338 return SetPixel( hdc, x, y, color );
342 /***********************************************************************
343 * SetPixel (GDI32.327)
345 COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
347 DC * dc = DC_GetDCPtr( hdc );
349 if (!dc || !dc->funcs->pSetPixel) return 0;
350 return dc->funcs->pSetPixel(dc,x,y,color);
353 /***********************************************************************
354 * SetPixelV (GDI32.329)
356 BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
358 DC * dc = DC_GetDCPtr( hdc );
360 if (!dc || !dc->funcs->pSetPixel) return FALSE;
361 dc->funcs->pSetPixel(dc,x,y,color);
362 return TRUE;
365 /***********************************************************************
366 * GetPixel16 (GDI.83)
368 COLORREF WINAPI GetPixel16( HDC16 hdc, INT16 x, INT16 y )
370 return GetPixel( hdc, x, y );
374 /***********************************************************************
375 * GetPixel (GDI32.211)
377 COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
379 DC * dc = DC_GetDCPtr( hdc );
381 if (!dc) return 0;
382 #ifdef SOLITAIRE_SPEED_HACK
383 return 0;
384 #endif
386 /* FIXME: should this be in the graphics driver? */
387 if (!PtVisible( hdc, x, y )) return 0;
388 if (!dc || !dc->funcs->pGetPixel) return 0;
389 return dc->funcs->pGetPixel(dc,x,y);
393 /******************************************************************************
394 * ChoosePixelFormat [GDI32.13]
395 * Matches a pixel format to given format
397 * PARAMS
398 * hdc [I] Device context to search for best pixel match
399 * ppfd [I] Pixel format for which a match is sought
401 * RETURNS
402 * Success: Pixel format index closest to given format
403 * Failure: 0
405 INT WINAPI ChoosePixelFormat( HDC hdc, const LPPIXELFORMATDESCRIPTOR ppfd )
407 DC * dc = DC_GetDCPtr( hdc );
409 TRACE("(%08x,%p)\n",hdc,ppfd);
411 if (dc == NULL) return 0;
412 if (dc->funcs->pChoosePixelFormat == NULL) {
413 FIXME(" :stub\n");
414 return 0;
417 return dc->funcs->pChoosePixelFormat(dc,ppfd);
421 /******************************************************************************
422 * SetPixelFormat [GDI32.328]
423 * Sets pixel format of device context
425 * PARAMS
426 * hdc [I] Device context to search for best pixel match
427 * iPixelFormat [I] Pixel format index
428 * ppfd [I] Pixel format for which a match is sought
430 * RETURNS STD
432 BOOL WINAPI SetPixelFormat( HDC hdc, INT iPixelFormat,
433 const PIXELFORMATDESCRIPTOR *ppfd)
435 DC * dc = DC_GetDCPtr( hdc );
437 TRACE("(%d,%d,%p)\n",hdc,iPixelFormat,ppfd);
439 if (dc == NULL) return 0;
440 if (dc->funcs->pSetPixelFormat == NULL) {
441 FIXME(" :stub\n");
442 return 0;
444 return dc->funcs->pSetPixelFormat(dc,iPixelFormat,ppfd);
448 /******************************************************************************
449 * GetPixelFormat [GDI32.212]
450 * Gets index of pixel format of DC
452 * PARAMETERS
453 * hdc [I] Device context whose pixel format index is sought
455 * RETURNS
456 * Success: Currently selected pixel format
457 * Failure: 0
459 INT WINAPI GetPixelFormat( HDC hdc )
461 DC * dc = DC_GetDCPtr( hdc );
463 TRACE("(%08x)\n",hdc);
465 if (dc == NULL) return 0;
466 if (dc->funcs->pGetPixelFormat == NULL) {
467 FIXME(" :stub\n");
468 return 0;
470 return dc->funcs->pGetPixelFormat(dc);
474 /******************************************************************************
475 * DescribePixelFormat [GDI32.71]
476 * Gets info about pixel format from DC
478 * PARAMS
479 * hdc [I] Device context
480 * iPixelFormat [I] Pixel format selector
481 * nBytes [I] Size of buffer
482 * ppfd [O] Pointer to structure to receive pixel format data
484 * RETURNS
485 * Success: Maximum pixel format index of the device context
486 * Failure: 0
488 INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes,
489 LPPIXELFORMATDESCRIPTOR ppfd )
491 DC * dc = DC_GetDCPtr( hdc );
493 TRACE("(%08x,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
495 if (dc == NULL) return 0;
496 if (dc->funcs->pDescribePixelFormat == NULL) {
497 FIXME(" :stub\n");
498 ppfd->nSize = nBytes;
499 ppfd->nVersion = 1;
500 return 3;
502 return dc->funcs->pDescribePixelFormat(dc,iPixelFormat,nBytes,ppfd);
506 /******************************************************************************
507 * SwapBuffers [GDI32.354]
508 * Exchanges front and back buffers of window
510 * PARAMS
511 * hdc [I] Device context whose buffers get swapped
513 * RETURNS STD
515 BOOL WINAPI SwapBuffers( HDC hdc )
517 DC * dc = DC_GetDCPtr( hdc );
519 TRACE("(%08x)\n",hdc);
521 if (dc == NULL) return 0;
522 if (dc->funcs->pSwapBuffers == NULL) {
523 FIXME(" :stub\n");
524 return TRUE;
526 return dc->funcs->pSwapBuffers(dc);
530 /***********************************************************************
531 * PaintRgn16 (GDI.43)
533 BOOL16 WINAPI PaintRgn16( HDC16 hdc, HRGN16 hrgn )
535 return PaintRgn( hdc, hrgn );
539 /***********************************************************************
540 * PaintRgn (GDI32.259)
542 BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
544 DC * dc = DC_GetDCPtr( hdc );
546 return dc && dc->funcs->pPaintRgn &&
547 dc->funcs->pPaintRgn(dc,hrgn);
551 /***********************************************************************
552 * FillRgn16 (GDI.40)
554 BOOL16 WINAPI FillRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush )
556 return FillRgn( hdc, hrgn, hbrush );
560 /***********************************************************************
561 * FillRgn (GDI32.101)
563 BOOL WINAPI FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
565 BOOL retval;
566 HBRUSH prevBrush;
567 DC * dc = DC_GetDCPtr( hdc );
569 if (!dc) return FALSE;
570 if(dc->funcs->pFillRgn)
571 return dc->funcs->pFillRgn(dc, hrgn, hbrush);
573 prevBrush = SelectObject( hdc, hbrush );
574 if (!prevBrush) return FALSE;
575 retval = PaintRgn( hdc, hrgn );
576 SelectObject( hdc, prevBrush );
577 return retval;
581 /***********************************************************************
582 * FrameRgn16 (GDI.41)
584 BOOL16 WINAPI FrameRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush,
585 INT16 nWidth, INT16 nHeight )
587 return FrameRgn( hdc, hrgn, hbrush, nWidth, nHeight );
591 /***********************************************************************
592 * FrameRgn (GDI32.105)
594 BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
595 INT nWidth, INT nHeight )
597 HRGN tmp;
598 DC *dc = DC_GetDCPtr( hdc );
600 if(dc->funcs->pFrameRgn)
601 return dc->funcs->pFrameRgn( dc, hrgn, hbrush, nWidth, nHeight );
603 tmp = CreateRectRgn( 0, 0, 0, 0 );
604 if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return FALSE;
605 FillRgn( hdc, tmp, hbrush );
606 DeleteObject( tmp );
607 return TRUE;
611 /***********************************************************************
612 * InvertRgn16 (GDI.42)
614 BOOL16 WINAPI InvertRgn16( HDC16 hdc, HRGN16 hrgn )
616 return InvertRgn( hdc, hrgn );
620 /***********************************************************************
621 * InvertRgn (GDI32.246)
623 BOOL WINAPI InvertRgn( HDC hdc, HRGN hrgn )
625 HBRUSH prevBrush;
626 INT prevROP;
627 BOOL retval;
628 DC *dc = DC_GetDCPtr( hdc );
630 if(dc->funcs->pInvertRgn)
631 return dc->funcs->pInvertRgn( dc, hrgn );
633 prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
634 prevROP = SetROP2( hdc, R2_NOT );
635 retval = PaintRgn( hdc, hrgn );
636 SelectObject( hdc, prevBrush );
637 SetROP2( hdc, prevROP );
638 return retval;
641 /**********************************************************************
642 * Polyline16 (GDI.37)
644 BOOL16 WINAPI Polyline16( HDC16 hdc, const POINT16* pt, INT16 count )
646 register int i;
647 BOOL16 ret;
648 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
649 count*sizeof(POINT) );
651 if (!pt32) return FALSE;
652 for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
653 ret = Polyline(hdc,pt32,count);
654 HeapFree( GetProcessHeap(), 0, pt32 );
655 return ret;
659 /**********************************************************************
660 * Polyline (GDI32.276)
662 BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
664 DC * dc = DC_GetDCPtr( hdc );
665 if(!dc) return FALSE;
667 if(PATH_IsPathOpen(dc->w.path))
668 return PATH_Polyline(hdc, pt, count);
670 return dc->funcs->pPolyline &&
671 dc->funcs->pPolyline(dc,pt,count);
674 /**********************************************************************
675 * PolylineTo (GDI32.277)
677 BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
679 DC * dc = DC_GetDCPtr( hdc );
680 BOOL ret;
682 if(!dc) return FALSE;
684 if(PATH_IsPathOpen(dc->w.path))
685 ret = PATH_PolylineTo(hdc, pt, cCount);
687 else if(dc->funcs->pPolylineTo)
688 ret = dc->funcs->pPolylineTo(dc, pt, cCount);
690 else { /* do it using Polyline */
691 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
692 sizeof(POINT) * (cCount + 1) );
693 if(!pts) return FALSE;
695 pts[0].x = dc->w.CursPosX;
696 pts[0].y = dc->w.CursPosY;
697 memcpy( pts + 1, pt, sizeof(POINT) * cCount );
698 ret = Polyline( hdc, pts, cCount + 1 );
699 HeapFree( GetProcessHeap(), 0, pts );
701 if(ret) {
702 dc->w.CursPosX = pt[cCount-1].x;
703 dc->w.CursPosY = pt[cCount-1].y;
705 return ret;
708 /**********************************************************************
709 * Polygon16 (GDI.36)
711 BOOL16 WINAPI Polygon16( HDC16 hdc, const POINT16* pt, INT16 count )
713 register int i;
714 BOOL ret;
715 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
716 count*sizeof(POINT) );
718 if (!pt32) return FALSE;
719 for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
720 ret = Polygon(hdc,pt32,count);
721 HeapFree( GetProcessHeap(), 0, pt32 );
722 return ret;
726 /**********************************************************************
727 * Polygon (GDI32.275)
729 BOOL WINAPI Polygon( HDC hdc, const POINT* pt, INT count )
731 DC * dc = DC_GetDCPtr( hdc );
732 if(!dc) return FALSE;
734 if(PATH_IsPathOpen(dc->w.path))
735 return PATH_Polygon(hdc, pt, count);
737 return dc->funcs->pPolygon &&
738 dc->funcs->pPolygon(dc,pt,count);
742 /**********************************************************************
743 * PolyPolygon16 (GDI.450)
745 BOOL16 WINAPI PolyPolygon16( HDC16 hdc, const POINT16* pt, const INT16* counts,
746 UINT16 polygons )
748 int i,nrpts;
749 LPPOINT pt32;
750 LPINT counts32;
751 BOOL16 ret;
753 nrpts=0;
754 for (i=polygons;i--;)
755 nrpts+=counts[i];
756 pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT)*nrpts);
757 if(pt32 == NULL) return FALSE;
758 for (i=nrpts;i--;)
759 CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
760 counts32 = (LPINT)HeapAlloc( GetProcessHeap(), 0, polygons*sizeof(INT) );
761 if(counts32 == NULL) {
762 HeapFree( GetProcessHeap(), 0, pt32 );
763 return FALSE;
765 for (i=polygons;i--;) counts32[i]=counts[i];
767 ret = PolyPolygon(hdc,pt32,counts32,polygons);
768 HeapFree( GetProcessHeap(), 0, counts32 );
769 HeapFree( GetProcessHeap(), 0, pt32 );
770 return ret;
773 /**********************************************************************
774 * PolyPolygon (GDI.450)
776 BOOL WINAPI PolyPolygon( HDC hdc, const POINT* pt, const INT* counts,
777 UINT polygons )
779 DC * dc = DC_GetDCPtr( hdc );
780 if(!dc) return FALSE;
782 if(PATH_IsPathOpen(dc->w.path))
783 return PATH_PolyPolygon(hdc, pt, counts, polygons);
785 return dc->funcs->pPolyPolygon &&
786 dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
789 /**********************************************************************
790 * PolyPolyline (GDI32.272)
792 BOOL WINAPI PolyPolyline( HDC hdc, const POINT* pt, const DWORD* counts,
793 DWORD polylines )
795 DC * dc = DC_GetDCPtr( hdc );
796 if(!dc) return FALSE;
798 if(PATH_IsPathOpen(dc->w.path))
799 return PATH_PolyPolyline(hdc, pt, counts, polylines);
801 return dc->funcs->pPolyPolyline &&
802 dc->funcs->pPolyPolyline(dc,pt,counts,polylines);
805 /**********************************************************************
806 * ExtFloodFill16 (GDI.372)
808 BOOL16 WINAPI ExtFloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color,
809 UINT16 fillType )
811 return ExtFloodFill( hdc, x, y, color, fillType );
815 /**********************************************************************
816 * ExtFloodFill (GDI32.96)
818 BOOL WINAPI ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color,
819 UINT fillType )
821 DC *dc = DC_GetDCPtr( hdc );
823 return dc && dc->funcs->pExtFloodFill &&
824 dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
828 /**********************************************************************
829 * FloodFill16 (GDI.25)
831 BOOL16 WINAPI FloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
833 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
837 /**********************************************************************
838 * FloodFill (GDI32.104)
840 BOOL WINAPI FloodFill( HDC hdc, INT x, INT y, COLORREF color )
842 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
846 /******************************************************************************
847 * PolyBezier16 [GDI.502]
849 BOOL16 WINAPI PolyBezier16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
851 int i;
852 BOOL16 ret;
853 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
854 cPoints*sizeof(POINT) );
855 if(!pt32) return FALSE;
856 for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
857 ret= PolyBezier(hDc, pt32, cPoints);
858 HeapFree( GetProcessHeap(), 0, pt32 );
859 return ret;
862 /******************************************************************************
863 * PolyBezierTo16 [GDI.503]
865 BOOL16 WINAPI PolyBezierTo16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
867 int i;
868 BOOL16 ret;
869 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
870 cPoints*sizeof(POINT) );
871 if(!pt32) return FALSE;
872 for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
873 ret= PolyBezierTo(hDc, pt32, cPoints);
874 HeapFree( GetProcessHeap(), 0, pt32 );
875 return ret;
878 /******************************************************************************
879 * PolyBezier [GDI32.268]
880 * Draws one or more Bezier curves
882 * PARAMS
883 * hDc [I] Handle to device context
884 * lppt [I] Pointer to endpoints and control points
885 * cPoints [I] Count of endpoints and control points
887 * RETURNS STD
889 BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
891 DC * dc = DC_GetDCPtr( hdc );
892 if(!dc) return FALSE;
894 if(PATH_IsPathOpen(dc->w.path))
895 return PATH_PolyBezier(hdc, lppt, cPoints);
897 if(dc->funcs->pPolyBezier)
898 return dc->funcs->pPolyBezier(dc, lppt, cPoints);
900 /* We'll convert it into line segments and draw them using Polyline */
902 POINT *Pts;
903 INT nOut;
904 BOOL ret;
906 Pts = GDI_Bezier( lppt, cPoints, &nOut );
907 if(!Pts) return FALSE;
908 TRACE("Pts = %p, no = %d\n", Pts, nOut);
909 ret = Polyline( dc->hSelf, Pts, nOut );
910 HeapFree( GetProcessHeap(), 0, Pts );
911 return ret;
915 /******************************************************************************
916 * PolyBezierTo [GDI32.269]
917 * Draws one or more Bezier curves
919 * PARAMS
920 * hDc [I] Handle to device context
921 * lppt [I] Pointer to endpoints and control points
922 * cPoints [I] Count of endpoints and control points
924 * RETURNS STD
926 BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
928 DC * dc = DC_GetDCPtr( hdc );
929 BOOL ret;
931 if(!dc) return FALSE;
933 if(PATH_IsPathOpen(dc->w.path))
934 ret = PATH_PolyBezierTo(hdc, lppt, cPoints);
935 else if(dc->funcs->pPolyBezierTo)
936 ret = dc->funcs->pPolyBezierTo(dc, lppt, cPoints);
937 else { /* We'll do it using PolyBezier */
938 POINT *pt;
939 pt = HeapAlloc( GetProcessHeap(), 0, sizeof(POINT) * (cPoints + 1) );
940 if(!pt) return FALSE;
941 pt[0].x = dc->w.CursPosX;
942 pt[0].y = dc->w.CursPosY;
943 memcpy(pt + 1, lppt, sizeof(POINT) * cPoints);
944 ret = PolyBezier(dc->hSelf, pt, cPoints+1);
945 HeapFree( GetProcessHeap(), 0, pt );
947 if(ret) {
948 dc->w.CursPosX = lppt[cPoints-1].x;
949 dc->w.CursPosY = lppt[cPoints-1].y;
951 return ret;
954 /***********************************************************************
955 * AngleArc (GDI32.5)
958 BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
959 FLOAT eStartAngle, FLOAT eSweepAngle)
961 FIXME("AngleArc, stub\n");
962 return 0;
965 /***********************************************************************
966 * PolyDraw (GDI32.270)
969 BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
970 DWORD cCount)
972 FIXME("PolyDraw, stub\n");
973 return 0;
976 /******************************************************************
978 * *Very* simple bezier drawing code,
980 * It uses a recursive algorithm to divide the curve in a series
981 * of straight line segements. Not ideal but for me sufficient.
982 * If you are in need for something better look for some incremental
983 * algorithm.
985 * 7 July 1998 Rein Klazes
989 * some macro definitions for bezier drawing
991 * to avoid trucation errors the coordinates are
992 * shifted upwards. When used in drawing they are
993 * shifted down again, including correct rounding
994 * and avoiding floating point arithmatic
995 * 4 bits should allow 27 bits coordinates which I saw
996 * somewere in the win32 doc's
1000 #define BEZIERSHIFTBITS 4
1001 #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
1002 #define BEZIERPIXEL BEZIERSHIFTUP(1)
1003 #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
1004 /* maximum depth of recursion */
1005 #define BEZIERMAXDEPTH 8
1007 /* size of array to store points on */
1008 /* enough for one curve */
1009 #define BEZIER_INITBUFSIZE (150)
1011 /* calculate Bezier average, in this case the middle
1012 * correctly rounded...
1013 * */
1015 #define BEZIERMIDDLE(Mid, P1, P2) \
1016 (Mid).x=((P1).x+(P2).x + 1)/2;\
1017 (Mid).y=((P1).y+(P2).y + 1)/2;
1019 /**********************************************************
1020 * BezierCheck helper function to check
1021 * that recursion can be terminated
1022 * Points[0] and Points[3] are begin and endpoint
1023 * Points[1] and Points[2] are control points
1024 * level is the recursion depth
1025 * returns true if the recusion can be terminated
1027 static BOOL BezierCheck( int level, POINT *Points)
1029 INT dx, dy;
1030 dx=Points[3].x-Points[0].x;
1031 dy=Points[3].y-Points[0].y;
1032 if(abs(dy)<=abs(dx)){/* shallow line */
1033 /* check that control points are between begin and end */
1034 if(Points[1].x < Points[0].x){
1035 if(Points[1].x < Points[3].x)
1036 return FALSE;
1037 }else
1038 if(Points[1].x > Points[3].x)
1039 return FALSE;
1040 if(Points[2].x < Points[0].x){
1041 if(Points[2].x < Points[3].x)
1042 return FALSE;
1043 }else
1044 if(Points[2].x > Points[3].x)
1045 return FALSE;
1046 dx=BEZIERSHIFTDOWN(dx);
1047 if(!dx) return TRUE;
1048 if(abs(Points[1].y-Points[0].y-(dy/dx)*
1049 BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL ||
1050 abs(Points[2].y-Points[0].y-(dy/dx)*
1051 BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL )
1052 return FALSE;
1053 else
1054 return TRUE;
1055 }else{ /* steep line */
1056 /* check that control points are between begin and end */
1057 if(Points[1].y < Points[0].y){
1058 if(Points[1].y < Points[3].y)
1059 return FALSE;
1060 }else
1061 if(Points[1].y > Points[3].y)
1062 return FALSE;
1063 if(Points[2].y < Points[0].y){
1064 if(Points[2].y < Points[3].y)
1065 return FALSE;
1066 }else
1067 if(Points[2].y > Points[3].y)
1068 return FALSE;
1069 dy=BEZIERSHIFTDOWN(dy);
1070 if(!dy) return TRUE;
1071 if(abs(Points[1].x-Points[0].x-(dx/dy)*
1072 BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL ||
1073 abs(Points[2].x-Points[0].x-(dx/dy)*
1074 BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL )
1075 return FALSE;
1076 else
1077 return TRUE;
1081 /* Helper for GDI_Bezier.
1082 * Just handles one Bezier, so Points should point to four POINTs
1084 static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut,
1085 INT *nPtsOut, INT level )
1087 if(*nPtsOut == *dwOut) {
1088 *dwOut *= 2;
1089 *PtsOut = HeapReAlloc( GetProcessHeap(), 0, *PtsOut,
1090 *dwOut * sizeof(POINT) );
1093 if(!level || BezierCheck(level, Points)) {
1094 if(*nPtsOut == 0) {
1095 (*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x);
1096 (*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y);
1097 *nPtsOut = 1;
1099 (*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x);
1100 (*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y);
1101 (*nPtsOut) ++;
1102 } else {
1103 POINT Points2[4]; /* for the second recursive call */
1104 Points2[3]=Points[3];
1105 BEZIERMIDDLE(Points2[2], Points[2], Points[3]);
1106 BEZIERMIDDLE(Points2[0], Points[1], Points[2]);
1107 BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]);
1109 BEZIERMIDDLE(Points[1], Points[0], Points[1]);
1110 BEZIERMIDDLE(Points[2], Points[1], Points2[0]);
1111 BEZIERMIDDLE(Points[3], Points[2], Points2[1]);
1113 Points2[0]=Points[3];
1115 /* do the two halves */
1116 GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1);
1117 GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1);
1123 /***********************************************************************
1124 * GDI_Bezier [INTERNAL]
1125 * Calculate line segments that approximate -what microsoft calls- a bezier
1126 * curve.
1127 * The routine recursively divides the curve in two parts until a straight
1128 * line can be drawn
1130 * PARAMS
1132 * Points [I] Ptr to count POINTs which are the end and control points
1133 * of the set of Bezier curves to flatten.
1134 * count [I] Number of Points. Must be 3n+1.
1135 * nPtsOut [O] Will contain no of points that have been produced (i.e. no. of
1136 * lines+1).
1138 * RETURNS
1140 * Ptr to an array of POINTs that contain the lines that approximinate the
1141 * Beziers. The array is allocated on the process heap and it is the caller's
1142 * responsibility to HeapFree it. [this is not a particularly nice interface
1143 * but since we can't know in advance how many points will generate, the
1144 * alternative would be to call the function twice, once to determine the size
1145 * and a second time to do the work - I decided this was too much of a pain].
1147 POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
1149 POINT *out;
1150 INT Bezier, dwOut = BEZIER_INITBUFSIZE, i;
1152 if((count - 1) % 3 != 0) {
1153 ERR("Invalid no. of points\n");
1154 return NULL;
1156 *nPtsOut = 0;
1157 out = HeapAlloc( GetProcessHeap(), 0, dwOut * sizeof(POINT));
1158 for(Bezier = 0; Bezier < (count-1)/3; Bezier++) {
1159 POINT ptBuf[4];
1160 memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4);
1161 for(i = 0; i < 4; i++) {
1162 ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x);
1163 ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y);
1165 GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH );
1167 TRACE("Produced %d points\n", *nPtsOut);
1168 return out;