Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / graphics / painting.c
blobaacb7fc0ceb8cb36838c4ec8b09a4d7828711619
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 "region.h"
14 #include "path.h"
15 #include "debugtools.h"
16 #include "winerror.h"
17 #include "windef.h"
18 #include "wingdi.h"
20 DEFAULT_DEBUG_CHANNEL(gdi);
23 /***********************************************************************
24 * LineTo16 (GDI.19)
26 BOOL16 WINAPI LineTo16( HDC16 hdc, INT16 x, INT16 y )
28 return LineTo( hdc, x, y );
32 /***********************************************************************
33 * LineTo (GDI32.249)
35 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
37 DC * dc = DC_GetDCPtr( hdc );
38 BOOL ret;
40 if(!dc) return FALSE;
42 if(PATH_IsPathOpen(dc->w.path))
43 ret = PATH_LineTo(hdc, x, y);
44 else
45 ret = dc->funcs->pLineTo && dc->funcs->pLineTo(dc,x,y);
46 if(ret) {
47 dc->w.CursPosX = x;
48 dc->w.CursPosY = y;
50 return ret;
54 /***********************************************************************
55 * MoveTo16 (GDI.20)
57 DWORD WINAPI MoveTo16( HDC16 hdc, INT16 x, INT16 y )
59 POINT16 pt;
61 if (!MoveToEx16(hdc,x,y,&pt))
62 return 0;
63 return MAKELONG(pt.x,pt.y);
67 /***********************************************************************
68 * MoveToEx16 (GDI.483)
70 BOOL16 WINAPI MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
72 POINT pt32;
74 if (!MoveToEx( (HDC)hdc, (INT)x, (INT)y, &pt32 )) return FALSE;
75 if (pt) CONV_POINT32TO16( &pt32, pt );
76 return TRUE;
81 /***********************************************************************
82 * MoveToEx (GDI32.254)
84 BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
86 DC * dc = DC_GetDCPtr( hdc );
88 if(!dc) return FALSE;
90 if(pt) {
91 pt->x = dc->w.CursPosX;
92 pt->y = dc->w.CursPosY;
94 dc->w.CursPosX = x;
95 dc->w.CursPosY = y;
97 if(PATH_IsPathOpen(dc->w.path))
98 return PATH_MoveTo(hdc);
100 if(dc->funcs->pMoveToEx)
101 return dc->funcs->pMoveToEx(dc,x,y,pt);
102 return TRUE;
106 /***********************************************************************
107 * Arc16 (GDI.23)
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,
115 (INT)yend );
119 /***********************************************************************
120 * Arc (GDI32.7)
122 BOOL WINAPI Arc( HDC hdc, INT left, INT top, INT right,
123 INT bottom, INT xstart, INT ystart,
124 INT xend, INT yend )
126 DC * dc = DC_GetDCPtr( hdc );
127 if(!dc) return FALSE;
129 if(PATH_IsPathOpen(dc->w.path))
130 return PATH_Arc(hdc, left, top, right, bottom, xstart, ystart, xend,
131 yend);
133 return dc->funcs->pArc &&
134 dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
137 /***********************************************************************
138 * ArcTo (GDI32.8)
140 BOOL WINAPI ArcTo( HDC hdc,
141 INT left, INT top,
142 INT right, INT bottom,
143 INT xstart, INT ystart,
144 INT xend, INT yend )
146 BOOL result;
147 DC * dc = DC_GetDCPtr( hdc );
148 if(!dc) return FALSE;
150 if(dc->funcs->pArcTo)
151 return dc->funcs->pArcTo( dc, left, top, right, bottom,
152 xstart, ystart, xend, yend );
154 * Else emulate it.
155 * According to the documentation, a line is drawn from the current
156 * position to the starting point of the arc.
158 LineTo(hdc, xstart, ystart);
161 * Then the arc is drawn.
163 result = Arc(hdc,
164 left, top,
165 right, bottom,
166 xstart, ystart,
167 xend, yend);
170 * If no error occured, the current position is moved to the ending
171 * point of the arc.
173 if (result)
175 MoveToEx(hdc, xend, yend, NULL);
178 return result;
181 /***********************************************************************
182 * Pie16 (GDI.26)
184 BOOL16 WINAPI Pie16( HDC16 hdc, INT16 left, INT16 top,
185 INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
186 INT16 xend, INT16 yend )
188 return Pie( (HDC)hdc, (INT)left, (INT)top, (INT)right,
189 (INT)bottom, (INT)xstart, (INT)ystart, (INT)xend,
190 (INT)yend );
194 /***********************************************************************
195 * Pie (GDI32.262)
197 BOOL WINAPI Pie( HDC hdc, INT left, INT top,
198 INT right, INT bottom, INT xstart, INT ystart,
199 INT xend, INT yend )
201 DC * dc = DC_GetDCPtr( hdc );
202 if(!dc) return FALSE;
204 if(PATH_IsPathOpen(dc->w.path)) {
205 FIXME("-> Path: stub\n");
206 return FALSE;
209 return dc->funcs->pPie &&
210 dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
214 /***********************************************************************
215 * Chord16 (GDI.348)
217 BOOL16 WINAPI Chord16( HDC16 hdc, INT16 left, INT16 top,
218 INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
219 INT16 xend, INT16 yend )
221 return Chord( hdc, left, top, right, bottom, xstart, ystart, xend, yend );
225 /***********************************************************************
226 * Chord (GDI32.14)
228 BOOL WINAPI Chord( HDC hdc, INT left, INT top,
229 INT right, INT bottom, INT xstart, INT ystart,
230 INT xend, INT yend )
232 DC * dc = DC_GetDCPtr( hdc );
233 if(!dc) return FALSE;
235 if(PATH_IsPathOpen(dc->w.path)) {
236 FIXME("-> Path: stub\n");
237 return FALSE;
240 return dc->funcs->pChord &&
241 dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
245 /***********************************************************************
246 * Ellipse16 (GDI.24)
248 BOOL16 WINAPI Ellipse16( HDC16 hdc, INT16 left, INT16 top,
249 INT16 right, INT16 bottom )
251 return Ellipse( hdc, left, top, right, bottom );
255 /***********************************************************************
256 * Ellipse (GDI32.75)
258 BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
259 INT right, INT bottom )
261 DC * dc = DC_GetDCPtr( hdc );
262 if(!dc) return FALSE;
264 if(PATH_IsPathOpen(dc->w.path)) {
265 FIXME("-> Path: stub\n");
266 return FALSE;
269 return dc->funcs->pEllipse &&
270 dc->funcs->pEllipse(dc,left,top,right,bottom);
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 )
290 DC * dc = DC_GetDCPtr( hdc );
291 if(!dc) return FALSE;
293 if(PATH_IsPathOpen(dc->w.path))
294 return PATH_Rectangle(hdc, left, top, right, bottom);
296 return dc->funcs->pRectangle &&
297 dc->funcs->pRectangle(dc,left,top,right,bottom);
301 /***********************************************************************
302 * RoundRect16 (GDI.28)
304 BOOL16 WINAPI RoundRect16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
305 INT16 bottom, INT16 ell_width, INT16 ell_height )
307 return RoundRect( hdc, left, top, right, bottom, ell_width, ell_height );
311 /***********************************************************************
312 * RoundRect (GDI32.291)
314 BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
315 INT bottom, INT ell_width, INT ell_height )
317 DC * dc = DC_GetDCPtr( hdc );
318 if(!dc) return FALSE;
320 if(PATH_IsPathOpen(dc->w.path)) {
321 FIXME("-> Path: stub\n");
322 return FALSE;
325 return dc->funcs->pRoundRect &&
326 dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
329 /***********************************************************************
330 * SetPixel16 (GDI.31)
332 COLORREF WINAPI SetPixel16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
334 return SetPixel( hdc, x, y, color );
338 /***********************************************************************
339 * SetPixel (GDI32.327)
341 COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
343 DC * dc = DC_GetDCPtr( hdc );
345 if (!dc || !dc->funcs->pSetPixel) return 0;
346 return dc->funcs->pSetPixel(dc,x,y,color);
349 /***********************************************************************
350 * SetPixelV (GDI32.329)
352 BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
354 DC * dc = DC_GetDCPtr( hdc );
356 if (!dc || !dc->funcs->pSetPixel) return FALSE;
357 dc->funcs->pSetPixel(dc,x,y,color);
358 return TRUE;
361 /***********************************************************************
362 * GetPixel16 (GDI.83)
364 COLORREF WINAPI GetPixel16( HDC16 hdc, INT16 x, INT16 y )
366 return GetPixel( hdc, x, y );
370 /***********************************************************************
371 * GetPixel (GDI32.211)
373 COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
375 DC * dc = DC_GetDCPtr( hdc );
377 if (!dc) return 0;
378 #ifdef SOLITAIRE_SPEED_HACK
379 return 0;
380 #endif
382 /* FIXME: should this be in the graphics driver? */
383 if (!PtVisible( hdc, x, y )) return 0;
384 if (!dc || !dc->funcs->pGetPixel) return 0;
385 return dc->funcs->pGetPixel(dc,x,y);
389 /******************************************************************************
390 * ChoosePixelFormat [GDI32.13]
391 * Matches a pixel format to given format
393 * PARAMS
394 * hdc [I] Device context to search for best pixel match
395 * ppfd [I] Pixel format for which a match is sought
397 * RETURNS
398 * Success: Pixel format index closest to given format
399 * Failure: 0
401 INT WINAPI ChoosePixelFormat( HDC hdc, const LPPIXELFORMATDESCRIPTOR ppfd )
403 DC * dc = DC_GetDCPtr( hdc );
405 TRACE("(%08x,%p)\n",hdc,ppfd);
407 if (dc == NULL) return 0;
408 if (dc->funcs->pChoosePixelFormat == NULL) {
409 FIXME(" :stub\n");
410 return 0;
413 return dc->funcs->pChoosePixelFormat(dc,ppfd);
417 /******************************************************************************
418 * SetPixelFormat [GDI32.328]
419 * Sets pixel format of device context
421 * PARAMS
422 * hdc [I] Device context to search for best pixel match
423 * iPixelFormat [I] Pixel format index
424 * ppfd [I] Pixel format for which a match is sought
426 * RETURNS STD
428 BOOL WINAPI SetPixelFormat( HDC hdc, INT iPixelFormat,
429 const PIXELFORMATDESCRIPTOR *ppfd)
431 DC * dc = DC_GetDCPtr( hdc );
433 TRACE("(%d,%d,%p)\n",hdc,iPixelFormat,ppfd);
435 if (dc == NULL) return 0;
436 if (dc->funcs->pSetPixelFormat == NULL) {
437 FIXME(" :stub\n");
438 return 0;
440 return dc->funcs->pSetPixelFormat(dc,iPixelFormat,ppfd);
444 /******************************************************************************
445 * GetPixelFormat [GDI32.212]
446 * Gets index of pixel format of DC
448 * PARAMETERS
449 * hdc [I] Device context whose pixel format index is sought
451 * RETURNS
452 * Success: Currently selected pixel format
453 * Failure: 0
455 INT WINAPI GetPixelFormat( HDC hdc )
457 DC * dc = DC_GetDCPtr( hdc );
459 TRACE("(%08x)\n",hdc);
461 if (dc == NULL) return 0;
462 if (dc->funcs->pGetPixelFormat == NULL) {
463 FIXME(" :stub\n");
464 return 0;
466 return dc->funcs->pGetPixelFormat(dc);
470 /******************************************************************************
471 * DescribePixelFormat [GDI32.71]
472 * Gets info about pixel format from DC
474 * PARAMS
475 * hdc [I] Device context
476 * iPixelFormat [I] Pixel format selector
477 * nBytes [I] Size of buffer
478 * ppfd [O] Pointer to structure to receive pixel format data
480 * RETURNS
481 * Success: Maximum pixel format index of the device context
482 * Failure: 0
484 INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes,
485 LPPIXELFORMATDESCRIPTOR ppfd )
487 DC * dc = DC_GetDCPtr( hdc );
489 TRACE("(%08x,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
491 if (dc == NULL) return 0;
492 if (dc->funcs->pDescribePixelFormat == NULL) {
493 FIXME(" :stub\n");
494 ppfd->nSize = nBytes;
495 ppfd->nVersion = 1;
496 return 3;
498 return dc->funcs->pDescribePixelFormat(dc,iPixelFormat,nBytes,ppfd);
502 /******************************************************************************
503 * SwapBuffers [GDI32.354]
504 * Exchanges front and back buffers of window
506 * PARAMS
507 * hdc [I] Device context whose buffers get swapped
509 * RETURNS STD
511 BOOL WINAPI SwapBuffers( HDC hdc )
513 DC * dc = DC_GetDCPtr( hdc );
515 TRACE("(%08x)\n",hdc);
517 if (dc == NULL) return 0;
518 if (dc->funcs->pSwapBuffers == NULL) {
519 FIXME(" :stub\n");
520 return TRUE;
522 return dc->funcs->pSwapBuffers(dc);
526 /***********************************************************************
527 * PaintRgn16 (GDI.43)
529 BOOL16 WINAPI PaintRgn16( HDC16 hdc, HRGN16 hrgn )
531 return PaintRgn( hdc, hrgn );
535 /***********************************************************************
536 * PaintRgn (GDI32.259)
538 BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
540 DC * dc = DC_GetDCPtr( hdc );
542 return dc && dc->funcs->pPaintRgn &&
543 dc->funcs->pPaintRgn(dc,hrgn);
547 /***********************************************************************
548 * FillRgn16 (GDI.40)
550 BOOL16 WINAPI FillRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush )
552 return FillRgn( hdc, hrgn, hbrush );
556 /***********************************************************************
557 * FillRgn (GDI32.101)
559 BOOL WINAPI FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
561 BOOL retval;
562 HBRUSH prevBrush;
563 DC * dc = DC_GetDCPtr( hdc );
565 if (!dc) return FALSE;
566 if(dc->funcs->pFillRgn)
567 return dc->funcs->pFillRgn(dc, hrgn, hbrush);
569 prevBrush = SelectObject( hdc, hbrush );
570 if (!prevBrush) return FALSE;
571 retval = PaintRgn( hdc, hrgn );
572 SelectObject( hdc, prevBrush );
573 return retval;
577 /***********************************************************************
578 * FrameRgn16 (GDI.41)
580 BOOL16 WINAPI FrameRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush,
581 INT16 nWidth, INT16 nHeight )
583 return FrameRgn( hdc, hrgn, hbrush, nWidth, nHeight );
587 /***********************************************************************
588 * FrameRgn (GDI32.105)
590 BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
591 INT nWidth, INT nHeight )
593 HRGN tmp;
594 DC *dc = DC_GetDCPtr( hdc );
596 if(dc->funcs->pFrameRgn)
597 return dc->funcs->pFrameRgn( dc, hrgn, hbrush, nWidth, nHeight );
599 tmp = CreateRectRgn( 0, 0, 0, 0 );
600 if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return FALSE;
601 FillRgn( hdc, tmp, hbrush );
602 DeleteObject( tmp );
603 return TRUE;
607 /***********************************************************************
608 * InvertRgn16 (GDI.42)
610 BOOL16 WINAPI InvertRgn16( HDC16 hdc, HRGN16 hrgn )
612 return InvertRgn( hdc, hrgn );
616 /***********************************************************************
617 * InvertRgn (GDI32.246)
619 BOOL WINAPI InvertRgn( HDC hdc, HRGN hrgn )
621 HBRUSH prevBrush;
622 INT prevROP;
623 BOOL retval;
624 DC *dc = DC_GetDCPtr( hdc );
626 if(dc->funcs->pInvertRgn)
627 return dc->funcs->pInvertRgn( dc, hrgn );
629 prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
630 prevROP = SetROP2( hdc, R2_NOT );
631 retval = PaintRgn( hdc, hrgn );
632 SelectObject( hdc, prevBrush );
633 SetROP2( hdc, prevROP );
634 return retval;
637 /**********************************************************************
638 * Polyline16 (GDI.37)
640 BOOL16 WINAPI Polyline16( HDC16 hdc, const POINT16* pt, INT16 count )
642 register int i;
643 BOOL16 ret;
644 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
645 count*sizeof(POINT) );
647 if (!pt32) return FALSE;
648 for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
649 ret = Polyline(hdc,pt32,count);
650 HeapFree( GetProcessHeap(), 0, pt32 );
651 return ret;
655 /**********************************************************************
656 * Polyline (GDI32.276)
658 BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
660 DC * dc = DC_GetDCPtr( hdc );
661 if(!dc) return FALSE;
663 if(PATH_IsPathOpen(dc->w.path))
664 return PATH_Polyline(hdc, pt, count);
666 return dc->funcs->pPolyline &&
667 dc->funcs->pPolyline(dc,pt,count);
670 /**********************************************************************
671 * PolylineTo (GDI32.277)
673 BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
675 DC * dc = DC_GetDCPtr( hdc );
676 BOOL ret;
678 if(!dc) return FALSE;
680 if(PATH_IsPathOpen(dc->w.path))
681 ret = PATH_PolylineTo(hdc, pt, cCount);
683 else if(dc->funcs->pPolylineTo)
684 ret = dc->funcs->pPolylineTo(dc, pt, cCount);
686 else { /* do it using Polyline */
687 POINT *pts = HeapAlloc( GetProcessHeap(), 0,
688 sizeof(POINT) * (cCount + 1) );
689 if(!pts) return FALSE;
691 pts[0].x = dc->w.CursPosX;
692 pts[0].y = dc->w.CursPosY;
693 memcpy( pts + 1, pt, sizeof(POINT) * cCount );
694 ret = Polyline( hdc, pts, cCount + 1 );
695 HeapFree( GetProcessHeap(), 0, pts );
697 if(ret) {
698 dc->w.CursPosX = pt[cCount-1].x;
699 dc->w.CursPosY = pt[cCount-1].y;
701 return ret;
704 /**********************************************************************
705 * Polygon16 (GDI.36)
707 BOOL16 WINAPI Polygon16( HDC16 hdc, const POINT16* pt, INT16 count )
709 register int i;
710 BOOL ret;
711 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
712 count*sizeof(POINT) );
714 if (!pt32) return FALSE;
715 for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
716 ret = Polygon(hdc,pt32,count);
717 HeapFree( GetProcessHeap(), 0, pt32 );
718 return ret;
722 /**********************************************************************
723 * Polygon (GDI32.275)
725 BOOL WINAPI Polygon( HDC hdc, const POINT* pt, INT count )
727 DC * dc = DC_GetDCPtr( hdc );
728 if(!dc) return FALSE;
730 if(PATH_IsPathOpen(dc->w.path))
731 return PATH_Polygon(hdc, pt, count);
733 return dc->funcs->pPolygon &&
734 dc->funcs->pPolygon(dc,pt,count);
738 /**********************************************************************
739 * PolyPolygon16 (GDI.450)
741 BOOL16 WINAPI PolyPolygon16( HDC16 hdc, const POINT16* pt, const INT16* counts,
742 UINT16 polygons )
744 int i,nrpts;
745 LPPOINT pt32;
746 LPINT counts32;
747 BOOL16 ret;
749 nrpts=0;
750 for (i=polygons;i--;)
751 nrpts+=counts[i];
752 pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT)*nrpts);
753 if(pt32 == NULL) return FALSE;
754 for (i=nrpts;i--;)
755 CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
756 counts32 = (LPINT)HeapAlloc( GetProcessHeap(), 0, polygons*sizeof(INT) );
757 if(counts32 == NULL) {
758 HeapFree( GetProcessHeap(), 0, pt32 );
759 return FALSE;
761 for (i=polygons;i--;) counts32[i]=counts[i];
763 ret = PolyPolygon(hdc,pt32,counts32,polygons);
764 HeapFree( GetProcessHeap(), 0, counts32 );
765 HeapFree( GetProcessHeap(), 0, pt32 );
766 return ret;
769 /**********************************************************************
770 * PolyPolygon (GDI.450)
772 BOOL WINAPI PolyPolygon( HDC hdc, const POINT* pt, const INT* counts,
773 UINT polygons )
775 DC * dc = DC_GetDCPtr( hdc );
776 if(!dc) return FALSE;
778 if(PATH_IsPathOpen(dc->w.path))
779 return PATH_PolyPolygon(hdc, pt, counts, polygons);
781 return dc->funcs->pPolyPolygon &&
782 dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
785 /**********************************************************************
786 * PolyPolyline (GDI32.272)
788 BOOL WINAPI PolyPolyline( HDC hdc, const POINT* pt, const DWORD* counts,
789 DWORD polylines )
791 DC * dc = DC_GetDCPtr( hdc );
792 if(!dc) return FALSE;
794 if(PATH_IsPathOpen(dc->w.path))
795 return PATH_PolyPolyline(hdc, pt, counts, polylines);
797 return dc->funcs->pPolyPolyline &&
798 dc->funcs->pPolyPolyline(dc,pt,counts,polylines);
801 /**********************************************************************
802 * ExtFloodFill16 (GDI.372)
804 BOOL16 WINAPI ExtFloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color,
805 UINT16 fillType )
807 return ExtFloodFill( hdc, x, y, color, fillType );
811 /**********************************************************************
812 * ExtFloodFill (GDI32.96)
814 BOOL WINAPI ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color,
815 UINT fillType )
817 DC *dc = DC_GetDCPtr( hdc );
819 return dc && dc->funcs->pExtFloodFill &&
820 dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
824 /**********************************************************************
825 * FloodFill16 (GDI.25)
827 BOOL16 WINAPI FloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
829 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
833 /**********************************************************************
834 * FloodFill (GDI32.104)
836 BOOL WINAPI FloodFill( HDC hdc, INT x, INT y, COLORREF color )
838 return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
842 /******************************************************************************
843 * PolyBezier16 [GDI.502]
845 BOOL16 WINAPI PolyBezier16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
847 int i;
848 BOOL16 ret;
849 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
850 cPoints*sizeof(POINT) );
851 if(!pt32) return FALSE;
852 for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
853 ret= PolyBezier(hDc, pt32, cPoints);
854 HeapFree( GetProcessHeap(), 0, pt32 );
855 return ret;
858 /******************************************************************************
859 * PolyBezierTo16 [GDI.503]
861 BOOL16 WINAPI PolyBezierTo16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
863 int i;
864 BOOL16 ret;
865 LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
866 cPoints*sizeof(POINT) );
867 if(!pt32) return FALSE;
868 for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
869 ret= PolyBezierTo(hDc, pt32, cPoints);
870 HeapFree( GetProcessHeap(), 0, pt32 );
871 return ret;
874 /******************************************************************************
875 * PolyBezier [GDI32.268]
876 * Draws one or more Bezier curves
878 * PARAMS
879 * hDc [I] Handle to device context
880 * lppt [I] Pointer to endpoints and control points
881 * cPoints [I] Count of endpoints and control points
883 * RETURNS STD
885 BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
887 DC * dc = DC_GetDCPtr( hdc );
888 if(!dc) return FALSE;
890 if(PATH_IsPathOpen(dc->w.path))
891 return PATH_PolyBezier(hdc, lppt, cPoints);
893 if(dc->funcs->pPolyBezier)
894 return dc->funcs->pPolyBezier(dc, lppt, cPoints);
896 /* We'll convert it into line segments and draw them using Polyline */
898 POINT *Pts;
899 INT nOut;
900 BOOL ret;
902 Pts = GDI_Bezier( lppt, cPoints, &nOut );
903 if(!Pts) return FALSE;
904 TRACE("Pts = %p, no = %d\n", Pts, nOut);
905 ret = Polyline( dc->hSelf, Pts, nOut );
906 HeapFree( GetProcessHeap(), 0, Pts );
907 return ret;
911 /******************************************************************************
912 * PolyBezierTo [GDI32.269]
913 * Draws one or more Bezier curves
915 * PARAMS
916 * hDc [I] Handle to device context
917 * lppt [I] Pointer to endpoints and control points
918 * cPoints [I] Count of endpoints and control points
920 * RETURNS STD
922 BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
924 DC * dc = DC_GetDCPtr( hdc );
925 BOOL ret;
927 if(!dc) return FALSE;
929 if(PATH_IsPathOpen(dc->w.path))
930 ret = PATH_PolyBezierTo(hdc, lppt, cPoints);
931 else if(dc->funcs->pPolyBezierTo)
932 ret = dc->funcs->pPolyBezierTo(dc, lppt, cPoints);
933 else { /* We'll do it using PolyBezier */
934 POINT *pt;
935 pt = HeapAlloc( GetProcessHeap(), 0, sizeof(POINT) * (cPoints + 1) );
936 if(!pt) return FALSE;
937 pt[0].x = dc->w.CursPosX;
938 pt[0].y = dc->w.CursPosY;
939 memcpy(pt + 1, lppt, sizeof(POINT) * cPoints);
940 ret = PolyBezier(dc->hSelf, pt, cPoints+1);
941 HeapFree( GetProcessHeap(), 0, pt );
943 if(ret) {
944 dc->w.CursPosX = lppt[cPoints-1].x;
945 dc->w.CursPosY = lppt[cPoints-1].y;
947 return ret;
950 /***********************************************************************
951 * AngleArc (GDI32.5)
954 BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
955 FLOAT eStartAngle, FLOAT eSweepAngle)
957 FIXME("AngleArc, stub\n");
958 return 0;
961 /***********************************************************************
962 * PolyDraw (GDI32.270)
965 BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
966 DWORD cCount)
968 FIXME("PolyDraw, stub\n");
969 return 0;
972 /******************************************************************
974 * *Very* simple bezier drawing code,
976 * It uses a recursive algorithm to divide the curve in a series
977 * of straight line segements. Not ideal but for me sufficient.
978 * If you are in need for something better look for some incremental
979 * algorithm.
981 * 7 July 1998 Rein Klazes
985 * some macro definitions for bezier drawing
987 * to avoid trucation errors the coordinates are
988 * shifted upwards. When used in drawing they are
989 * shifted down again, including correct rounding
990 * and avoiding floating point arithmatic
991 * 4 bits should allow 27 bits coordinates which I saw
992 * somewere in the win32 doc's
996 #define BEZIERSHIFTBITS 4
997 #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
998 #define BEZIERPIXEL BEZIERSHIFTUP(1)
999 #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
1000 /* maximum depth of recursion */
1001 #define BEZIERMAXDEPTH 8
1003 /* size of array to store points on */
1004 /* enough for one curve */
1005 #define BEZIER_INITBUFSIZE (150)
1007 /* calculate Bezier average, in this case the middle
1008 * correctly rounded...
1009 * */
1011 #define BEZIERMIDDLE(Mid, P1, P2) \
1012 (Mid).x=((P1).x+(P2).x + 1)/2;\
1013 (Mid).y=((P1).y+(P2).y + 1)/2;
1015 /**********************************************************
1016 * BezierCheck helper function to check
1017 * that recursion can be terminated
1018 * Points[0] and Points[3] are begin and endpoint
1019 * Points[1] and Points[2] are control points
1020 * level is the recursion depth
1021 * returns true if the recusion can be terminated
1023 static BOOL BezierCheck( int level, POINT *Points)
1025 INT dx, dy;
1026 dx=Points[3].x-Points[0].x;
1027 dy=Points[3].y-Points[0].y;
1028 if(abs(dy)<=abs(dx)){/* shallow line */
1029 /* check that control points are between begin and end */
1030 if(Points[1].x < Points[0].x){
1031 if(Points[1].x < Points[3].x)
1032 return FALSE;
1033 }else
1034 if(Points[1].x > Points[3].x)
1035 return FALSE;
1036 if(Points[2].x < Points[0].x){
1037 if(Points[2].x < Points[3].x)
1038 return FALSE;
1039 }else
1040 if(Points[2].x > Points[3].x)
1041 return FALSE;
1042 dx=BEZIERSHIFTDOWN(dx);
1043 if(!dx) return TRUE;
1044 if(abs(Points[1].y-Points[0].y-(dy/dx)*
1045 BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL ||
1046 abs(Points[2].y-Points[0].y-(dy/dx)*
1047 BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL )
1048 return FALSE;
1049 else
1050 return TRUE;
1051 }else{ /* steep line */
1052 /* check that control points are between begin and end */
1053 if(Points[1].y < Points[0].y){
1054 if(Points[1].y < Points[3].y)
1055 return FALSE;
1056 }else
1057 if(Points[1].y > Points[3].y)
1058 return FALSE;
1059 if(Points[2].y < Points[0].y){
1060 if(Points[2].y < Points[3].y)
1061 return FALSE;
1062 }else
1063 if(Points[2].y > Points[3].y)
1064 return FALSE;
1065 dy=BEZIERSHIFTDOWN(dy);
1066 if(!dy) return TRUE;
1067 if(abs(Points[1].x-Points[0].x-(dx/dy)*
1068 BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL ||
1069 abs(Points[2].x-Points[0].x-(dx/dy)*
1070 BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL )
1071 return FALSE;
1072 else
1073 return TRUE;
1077 /* Helper for GDI_Bezier.
1078 * Just handles one Bezier, so Points should point to four POINTs
1080 static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut,
1081 INT *nPtsOut, INT level )
1083 if(*nPtsOut == *dwOut) {
1084 *dwOut *= 2;
1085 *PtsOut = HeapReAlloc( GetProcessHeap(), 0, *PtsOut,
1086 *dwOut * sizeof(POINT) );
1089 if(!level || BezierCheck(level, Points)) {
1090 if(*nPtsOut == 0) {
1091 (*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x);
1092 (*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y);
1093 *nPtsOut = 1;
1095 (*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x);
1096 (*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y);
1097 (*nPtsOut) ++;
1098 } else {
1099 POINT Points2[4]; /* for the second recursive call */
1100 Points2[3]=Points[3];
1101 BEZIERMIDDLE(Points2[2], Points[2], Points[3]);
1102 BEZIERMIDDLE(Points2[0], Points[1], Points[2]);
1103 BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]);
1105 BEZIERMIDDLE(Points[1], Points[0], Points[1]);
1106 BEZIERMIDDLE(Points[2], Points[1], Points2[0]);
1107 BEZIERMIDDLE(Points[3], Points[2], Points2[1]);
1109 Points2[0]=Points[3];
1111 /* do the two halves */
1112 GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1);
1113 GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1);
1119 /***********************************************************************
1120 * GDI_Bezier [INTERNAL]
1121 * Calculate line segments that approximate -what microsoft calls- a bezier
1122 * curve.
1123 * The routine recursively divides the curve in two parts until a straight
1124 * line can be drawn
1126 * PARAMS
1128 * Points [I] Ptr to count POINTs which are the end and control points
1129 * of the set of Bezier curves to flatten.
1130 * count [I] Number of Points. Must be 3n+1.
1131 * nPtsOut [O] Will contain no of points that have been produced (i.e. no. of
1132 * lines+1).
1134 * RETURNS
1136 * Ptr to an array of POINTs that contain the lines that approximinate the
1137 * Beziers. The array is allocated on the process heap and it is the caller's
1138 * responsibility to HeapFree it. [this is not a particularly nice interface
1139 * but since we can't know in advance how many points will generate, the
1140 * alternative would be to call the function twice, once to determine the size
1141 * and a second time to do the work - I decided this was too much of a pain].
1143 POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
1145 POINT *out;
1146 INT Bezier, dwOut = BEZIER_INITBUFSIZE, i;
1148 if((count - 1) % 3 != 0) {
1149 ERR("Invalid no. of points\n");
1150 return NULL;
1152 *nPtsOut = 0;
1153 out = HeapAlloc( GetProcessHeap(), 0, dwOut * sizeof(POINT));
1154 for(Bezier = 0; Bezier < (count-1)/3; Bezier++) {
1155 POINT ptBuf[4];
1156 memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4);
1157 for(i = 0; i < 4; i++) {
1158 ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x);
1159 ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y);
1161 GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH );
1163 TRACE("Produced %d points\n", *nPtsOut);
1164 return out;