Changed stdlib.h to string.h.
[wine] / graphics / painting.c
1 /*
2  * Misc. graphics operations
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  * Copyright 1997 Bertho A. Stultiens
6  */
7
8 #include <string.h>
9 #include "dc.h"
10 #include "bitmap.h"
11 #include "heap.h"
12 #include "monitor.h"
13 #include "cache.h"
14 #include "region.h"
15 #include "path.h"
16 #include "debug.h"
17 #include "winerror.h"
18 #include "winuser.h"
19 #include "wine/winuser16.h"
20
21
22 /***********************************************************************
23  *           LineTo16    (GDI.19)
24  */
25 BOOL16 WINAPI LineTo16( HDC16 hdc, INT16 x, INT16 y )
26 {
27     return LineTo( hdc, x, y );
28 }
29
30
31 /***********************************************************************
32  *           LineTo32    (GDI32.249)
33  */
34 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
35 {
36     DC * dc = DC_GetDCPtr( hdc );
37
38     if(dc && PATH_IsPathOpen(dc->w.path))
39         if(!PATH_LineTo(hdc, x, y))
40            return FALSE;
41     
42     return dc && dc->funcs->pLineTo &&
43            dc->funcs->pLineTo(dc,x,y);
44 }
45
46
47 /***********************************************************************
48  *           MoveTo    (GDI.20)
49  */
50 DWORD WINAPI MoveTo16( HDC16 hdc, INT16 x, INT16 y )
51 {
52     POINT16     pt;
53
54     if (!MoveToEx16(hdc,x,y,&pt))
55         return 0;
56     return MAKELONG(pt.x,pt.y);
57 }
58
59
60 /***********************************************************************
61  *           MoveToEx16    (GDI.483)
62  */
63 BOOL16 WINAPI MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
64 {
65     POINT pt32;
66
67     if (!MoveToEx( (HDC)hdc, (INT)x, (INT)y, &pt32 )) return FALSE;
68     if (pt) CONV_POINT32TO16( &pt32, pt );
69     return TRUE;
70
71 }
72
73
74 /***********************************************************************
75  *           MoveToEx32    (GDI32.254)
76  */
77 BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
78 {
79     DC * dc = DC_GetDCPtr( hdc );
80   
81     if(dc && PATH_IsPathOpen(dc->w.path))
82         if(!PATH_MoveTo(hdc))
83             return FALSE;
84
85     return dc && dc->funcs->pMoveToEx &&
86            dc->funcs->pMoveToEx(dc,x,y,pt);
87 }
88
89
90 /***********************************************************************
91  *           Arc16    (GDI.23)
92  */
93 BOOL16 WINAPI Arc16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
94                      INT16 bottom, INT16 xstart, INT16 ystart,
95                      INT16 xend, INT16 yend )
96 {
97     return Arc( (HDC)hdc, (INT)left, (INT)top, (INT)right,
98                   (INT)bottom, (INT)xstart, (INT)ystart, (INT)xend,
99                   (INT)yend );
100 }
101
102
103 /***********************************************************************
104  *           Arc32    (GDI32.7)
105  */
106 BOOL WINAPI Arc( HDC hdc, INT left, INT top, INT right,
107                      INT bottom, INT xstart, INT ystart,
108                      INT xend, INT yend )
109 {
110     DC * dc = DC_GetDCPtr( hdc );
111   
112     if(dc && PATH_IsPathOpen(dc->w.path))
113         if(!PATH_Arc(hdc, left, top, right, bottom, xstart, ystart, xend,
114            yend))
115            return FALSE;
116     
117     return dc && dc->funcs->pArc &&
118            dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
119 }
120
121 /***********************************************************************
122  *           ArcTo    (GDI32.8)
123  */
124 BOOL WINAPI ArcTo( HDC hdc, 
125                      INT left,   INT top, 
126                      INT right,  INT bottom,
127                      INT xstart, INT ystart,
128                      INT xend,   INT yend )
129 {
130     BOOL result;
131
132     /*
133      * According to the documentation, a line is drawn from the current
134      * position to the starting point of the arc.
135      */
136     LineTo(hdc, xstart, ystart);
137
138     /*
139      * Then the arc is drawn.
140      */
141     result = Arc(hdc, 
142                   left, top,
143                   right, bottom,
144                   xstart, ystart,
145                   xend, yend);
146
147     /*
148      * If no error occured, the current position is moved to the ending
149      * point of the arc.
150      */
151     if (result)
152     {
153         MoveToEx(hdc, xend, yend, NULL);
154     }
155
156     return result;
157 }
158
159 /***********************************************************************
160  *           Pie16    (GDI.26)
161  */
162 BOOL16 WINAPI Pie16( HDC16 hdc, INT16 left, INT16 top,
163                      INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
164                      INT16 xend, INT16 yend )
165 {
166     return Pie( (HDC)hdc, (INT)left, (INT)top, (INT)right,
167                   (INT)bottom, (INT)xstart, (INT)ystart, (INT)xend,
168                   (INT)yend );
169 }
170
171
172 /***********************************************************************
173  *           Pie32   (GDI32.262)
174  */
175 BOOL WINAPI Pie( HDC hdc, INT left, INT top,
176                      INT right, INT bottom, INT xstart, INT ystart,
177                      INT xend, INT yend )
178 {
179     DC * dc = DC_GetDCPtr( hdc );
180   
181     return dc && dc->funcs->pPie &&
182            dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
183 }
184
185
186 /***********************************************************************
187  *           Chord16    (GDI.348)
188  */
189 BOOL16 WINAPI Chord16( HDC16 hdc, INT16 left, INT16 top,
190                        INT16 right, INT16 bottom, INT16 xstart, INT16 ystart,
191                        INT16 xend, INT16 yend )
192 {
193     return Chord( hdc, left, top, right, bottom, xstart, ystart, xend, yend );
194 }
195
196
197 /***********************************************************************
198  *           Chord32    (GDI32.14)
199  */
200 BOOL WINAPI Chord( HDC hdc, INT left, INT top,
201                        INT right, INT bottom, INT xstart, INT ystart,
202                        INT xend, INT yend )
203 {
204     DC * dc = DC_GetDCPtr( hdc );
205   
206     return dc && dc->funcs->pChord &&
207            dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
208 }
209
210
211 /***********************************************************************
212  *           Ellipse16    (GDI.24)
213  */
214 BOOL16 WINAPI Ellipse16( HDC16 hdc, INT16 left, INT16 top,
215                          INT16 right, INT16 bottom )
216 {
217     return Ellipse( hdc, left, top, right, bottom );
218 }
219
220
221 /***********************************************************************
222  *           Ellipse32    (GDI32.75)
223  */
224 BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
225                          INT right, INT bottom )
226 {
227     DC * dc = DC_GetDCPtr( hdc );
228   
229     return dc && dc->funcs->pEllipse &&
230            dc->funcs->pEllipse(dc,left,top,right,bottom);
231 }
232
233
234 /***********************************************************************
235  *           Rectangle16    (GDI.27)
236  */
237 BOOL16 WINAPI Rectangle16( HDC16 hdc, INT16 left, INT16 top,
238                            INT16 right, INT16 bottom )
239 {
240     return Rectangle( hdc, left, top, right, bottom );
241 }
242
243
244 /***********************************************************************
245  *           Rectangle32    (GDI32.283)
246  */
247 BOOL WINAPI Rectangle( HDC hdc, INT left, INT top,
248                            INT right, INT bottom )
249 {
250     DC * dc = DC_GetDCPtr( hdc );
251   
252     if(dc && PATH_IsPathOpen(dc->w.path))
253         if(!PATH_Rectangle(hdc, left, top, right, bottom))
254            return FALSE;
255
256     return dc && dc->funcs->pRectangle &&
257            dc->funcs->pRectangle(dc,left,top,right,bottom);
258 }
259
260
261 /***********************************************************************
262  *           RoundRect16    (GDI.28)
263  */
264 BOOL16 WINAPI RoundRect16( HDC16 hdc, INT16 left, INT16 top, INT16 right,
265                            INT16 bottom, INT16 ell_width, INT16 ell_height )
266 {
267     return RoundRect( hdc, left, top, right, bottom, ell_width, ell_height );
268 }
269
270
271 /***********************************************************************
272  *           RoundRect32    (GDI32.291)
273  */
274 BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
275                            INT bottom, INT ell_width, INT ell_height )
276 {
277   
278     if(ell_width == 0 || ell_height == 0) /* Just an optimization */
279         return Rectangle(hdc, left, top, right, bottom);
280
281     else {
282         DC * dc = DC_GetDCPtr( hdc );
283
284         return dc && dc->funcs->pRoundRect &&
285            dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
286     }
287 }
288
289
290 /***********************************************************************
291  *           FillRect16    (USER.81)
292  */
293 INT16 WINAPI FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
294 {
295     HBRUSH16 prevBrush;
296
297     /* coordinates are logical so we cannot fast-check 'rect',
298      * it will be done later in the PatBlt().
299      */
300
301     if (!(prevBrush = SelectObject16( hdc, hbrush ))) return 0;
302     PatBlt( hdc, rect->left, rect->top,
303               rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
304     SelectObject16( hdc, prevBrush );
305     return 1;
306 }
307
308
309 /***********************************************************************
310  *           FillRect32    (USER32.197)
311  */
312 INT WINAPI FillRect( HDC hdc, const RECT *rect, HBRUSH hbrush )
313 {
314     HBRUSH prevBrush;
315
316     if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0;
317     PatBlt( hdc, rect->left, rect->top,
318               rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
319     SelectObject( hdc, prevBrush );
320     return 1;
321 }
322
323
324 /***********************************************************************
325  *           InvertRect16    (USER.82)
326  */
327 void WINAPI InvertRect16( HDC16 hdc, const RECT16 *rect )
328 {
329     PatBlt( hdc, rect->left, rect->top,
330               rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
331 }
332
333
334 /***********************************************************************
335  *           InvertRect32    (USER32.330)
336  */
337 BOOL WINAPI InvertRect( HDC hdc, const RECT *rect )
338 {
339     return PatBlt( hdc, rect->left, rect->top,
340                      rect->right - rect->left, rect->bottom - rect->top, 
341                      DSTINVERT );
342 }
343
344
345 /***********************************************************************
346  *           FrameRect16    (USER.83)
347  */
348 INT16 WINAPI FrameRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
349 {
350     HBRUSH16 prevBrush;
351     int left, top, right, bottom;
352
353     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
354     if (!dc) return FALSE;
355
356     left   = XLPTODP( dc, rect->left );
357     top    = YLPTODP( dc, rect->top );
358     right  = XLPTODP( dc, rect->right );
359     bottom = YLPTODP( dc, rect->bottom );
360
361     if ( (right <= left) || (bottom <= top) ) return 0;
362     if (!(prevBrush = SelectObject16( hdc, hbrush ))) return 0;
363     
364     PatBlt( hdc, rect->left, rect->top, 1,
365               rect->bottom - rect->top, PATCOPY );
366     PatBlt( hdc, rect->right - 1, rect->top, 1,
367               rect->bottom - rect->top, PATCOPY );
368     PatBlt( hdc, rect->left, rect->top,
369               rect->right - rect->left, 1, PATCOPY );
370     PatBlt( hdc, rect->left, rect->bottom - 1,
371               rect->right - rect->left, 1, PATCOPY );
372
373     SelectObject16( hdc, prevBrush );
374     return 1;
375 }
376
377
378 /***********************************************************************
379  *           FrameRect32    (USER32.203)
380  */
381 INT WINAPI FrameRect( HDC hdc, const RECT *rect, HBRUSH hbrush )
382 {
383     RECT16 rect16;
384     CONV_RECT32TO16( rect, &rect16 );
385     return FrameRect16( (HDC16)hdc, &rect16, (HBRUSH16)hbrush );
386 }
387
388
389 /***********************************************************************
390  *           SetPixel16    (GDI.31)
391  */
392 COLORREF WINAPI SetPixel16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
393 {
394     return SetPixel( hdc, x, y, color );
395 }
396
397
398 /***********************************************************************
399  *           SetPixel32    (GDI32.327)
400  */
401 COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
402 {
403     DC * dc = DC_GetDCPtr( hdc );
404   
405     if (!dc || !dc->funcs->pSetPixel) return 0;
406     return dc->funcs->pSetPixel(dc,x,y,color);
407 }
408
409 /***********************************************************************
410  *           SetPixelV32    (GDI32.329)
411  */
412 BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
413 {
414     DC * dc = DC_GetDCPtr( hdc );
415   
416     if (!dc || !dc->funcs->pSetPixel) return FALSE;
417     dc->funcs->pSetPixel(dc,x,y,color);
418     return TRUE;
419 }
420
421 /***********************************************************************
422  *           GetPixel16    (GDI.83)
423  */
424 COLORREF WINAPI GetPixel16( HDC16 hdc, INT16 x, INT16 y )
425 {
426     return GetPixel( hdc, x, y );
427 }
428
429
430 /***********************************************************************
431  *           GetPixel32    (GDI32.211)
432  */
433 COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
434 {
435     DC * dc = DC_GetDCPtr( hdc );
436
437     if (!dc) return 0;
438 #ifdef SOLITAIRE_SPEED_HACK
439     return 0;
440 #endif
441
442     /* FIXME: should this be in the graphics driver? */
443     if (!PtVisible( hdc, x, y )) return 0;
444     if (!dc || !dc->funcs->pGetPixel) return 0;
445     return dc->funcs->pGetPixel(dc,x,y);
446 }
447
448
449 /******************************************************************************
450  * ChoosePixelFormat [GDI32.13]
451  * Matches a pixel format to given format
452  *
453  * PARAMS
454  *    hdc  [I] Device context to search for best pixel match
455  *    ppfd [I] Pixel format for which a match is sought
456  *
457  * RETURNS
458  *    Success: Pixel format index closest to given format
459  *    Failure: 0
460  */
461 INT WINAPI ChoosePixelFormat( HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd )
462 {
463     FIXME(gdi, "(%d,%p): stub\n",hdc,ppfd);
464     return 1;
465 }
466
467
468 /******************************************************************************
469  * SetPixelFormat [GDI32.328]
470  * Sets pixel format of device context
471  *
472  * PARAMS
473  *    hdc          [I] Device context to search for best pixel match
474  *    iPixelFormat [I] Pixel format index
475  *    ppfd         [I] Pixel format for which a match is sought
476  *
477  * RETURNS STD
478  */
479 BOOL WINAPI SetPixelFormat( HDC hdc, int iPixelFormat, 
480                               const PIXELFORMATDESCRIPTOR* ppfd)
481 {
482     FIXME(gdi, "(%d,%d,%p): stub\n",hdc,iPixelFormat,ppfd);
483     return TRUE;
484 }
485
486
487 /******************************************************************************
488  * GetPixelFormat [GDI32.212]
489  * Gets index of pixel format of DC
490  *
491  * PARAMETERS
492  *    hdc [I] Device context whose pixel format index is sought
493  *
494  * RETURNS
495  *    Success: Currently selected pixel format
496  *    Failure: 0
497  */
498 int WINAPI GetPixelFormat( HDC hdc )
499 {
500     FIXME(gdi, "(%d): stub\n",hdc);
501     return 1;
502 }
503
504
505 /******************************************************************************
506  * DescribePixelFormat [GDI32.71]
507  * Gets info about pixel format from DC
508  *
509  * PARAMS
510  *    hdc          [I] Device context
511  *    iPixelFormat [I] Pixel format selector
512  *    nBytes       [I] Size of buffer
513  *    ppfd         [O] Pointer to structure to receive pixel format data
514  *
515  * RETURNS
516  *    Success: Maximum pixel format index of the device context
517  *    Failure: 0
518  */
519 int WINAPI DescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes,
520                                 LPPIXELFORMATDESCRIPTOR ppfd )
521 {
522     FIXME(gdi, "(%d,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
523     ppfd->nSize = nBytes;
524     ppfd->nVersion = 1;
525     return 3;
526 }
527
528
529 /******************************************************************************
530  * SwapBuffers [GDI32.354]
531  * Exchanges front and back buffers of window
532  *
533  * PARAMS
534  *    hdc [I] Device context whose buffers get swapped
535  *
536  * RETURNS STD
537  */
538 BOOL WINAPI SwapBuffers( HDC hdc )
539 {
540     FIXME(gdi, "(%d): stub\n",hdc);
541     return TRUE;
542 }
543
544
545 /***********************************************************************
546  *           PaintRgn16    (GDI.43)
547  */
548 BOOL16 WINAPI PaintRgn16( HDC16 hdc, HRGN16 hrgn )
549 {
550     return PaintRgn( hdc, hrgn );
551 }
552
553
554 /***********************************************************************
555  *           PaintRgn32    (GDI32.259)
556  */
557 BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
558 {
559     DC * dc = DC_GetDCPtr( hdc );
560
561     return dc && dc->funcs->pPaintRgn &&
562            dc->funcs->pPaintRgn(dc,hrgn);
563 }
564
565
566 /***********************************************************************
567  *           FillRgn16    (GDI.40)
568  */
569 BOOL16 WINAPI FillRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush )
570 {
571     return FillRgn( hdc, hrgn, hbrush );
572 }
573
574     
575 /***********************************************************************
576  *           FillRgn32    (GDI32.101)
577  */
578 BOOL WINAPI FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
579 {
580     BOOL retval;
581     HBRUSH prevBrush = SelectObject( hdc, hbrush );
582     if (!prevBrush) return FALSE;
583     retval = PaintRgn( hdc, hrgn );
584     SelectObject( hdc, prevBrush );
585     return retval;
586 }
587
588
589 /***********************************************************************
590  *           FrameRgn16     (GDI.41)
591  */
592 BOOL16 WINAPI FrameRgn16( HDC16 hdc, HRGN16 hrgn, HBRUSH16 hbrush,
593                           INT16 nWidth, INT16 nHeight )
594 {
595     return FrameRgn( hdc, hrgn, hbrush, nWidth, nHeight );
596 }
597
598
599 /***********************************************************************
600  *           FrameRgn32     (GDI32.105)
601  */
602 BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
603                           INT nWidth, INT nHeight )
604 {
605     HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
606     if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return FALSE;
607     FillRgn( hdc, tmp, hbrush );
608     DeleteObject( tmp );
609     return TRUE;
610 }
611
612
613 /***********************************************************************
614  *           InvertRgn16    (GDI.42)
615  */
616 BOOL16 WINAPI InvertRgn16( HDC16 hdc, HRGN16 hrgn )
617 {
618     return InvertRgn( hdc, hrgn );
619 }
620
621
622 /***********************************************************************
623  *           InvertRgn32    (GDI32.246)
624  */
625 BOOL WINAPI InvertRgn( HDC hdc, HRGN hrgn )
626 {
627     HBRUSH prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
628     INT prevROP = SetROP2( hdc, R2_NOT );
629     BOOL retval = PaintRgn( hdc, hrgn );
630     SelectObject( hdc, prevBrush );
631     SetROP2( hdc, prevROP );
632     return retval;
633 }
634
635
636 /***********************************************************************
637  *           DrawFocusRect16    (USER.466)
638  */
639 void WINAPI DrawFocusRect16( HDC16 hdc, const RECT16* rc )
640 {
641     RECT rect32;
642     CONV_RECT16TO32( rc, &rect32 );
643     DrawFocusRect( hdc, &rect32 );
644 }
645
646
647 /***********************************************************************
648  *           DrawFocusRect32    (USER32.156)
649  *
650  * FIXME: PatBlt(PATINVERT) with background brush.
651  */
652 BOOL WINAPI DrawFocusRect( HDC hdc, const RECT* rc )
653 {
654     HBRUSH hOldBrush;
655     HPEN hOldPen, hNewPen;
656     INT oldDrawMode, oldBkMode;
657
658     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
659     if (!dc) 
660     {
661        SetLastError( ERROR_INVALID_HANDLE );
662        return FALSE;
663     }
664
665     hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
666     hNewPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_WINDOWTEXT));
667     hOldPen = SelectObject(hdc, hNewPen);
668     oldDrawMode = SetROP2(hdc, R2_XORPEN);
669     oldBkMode = SetBkMode(hdc, TRANSPARENT);
670
671     Rectangle(hdc, rc->left, rc->top, rc->right, rc->bottom);
672
673     SetBkMode(hdc, oldBkMode);
674     SetROP2(hdc, oldDrawMode);
675     SelectObject(hdc, hOldPen);
676     DeleteObject(hNewPen);
677     SelectObject(hdc, hOldBrush);
678
679     return TRUE;
680 }
681
682
683 /**********************************************************************
684  *          Polyline16  (GDI.37)
685  */
686 BOOL16 WINAPI Polyline16( HDC16 hdc, const POINT16* pt, INT16 count )
687 {
688     register int i;
689     BOOL16 ret;
690     LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
691                                            count*sizeof(POINT) );
692
693     if (!pt32) return FALSE;
694     for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
695     ret = Polyline(hdc,pt32,count);
696     HeapFree( GetProcessHeap(), 0, pt32 );
697     return ret;
698 }
699
700
701 /**********************************************************************
702  *          Polyline32   (GDI32.276)
703  */
704 BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
705 {
706     DC * dc = DC_GetDCPtr( hdc );
707
708     return dc && dc->funcs->pPolyline &&
709            dc->funcs->pPolyline(dc,pt,count);
710 }
711
712 /**********************************************************************
713  *          PolylineTo32   (GDI32.277)
714  */
715 BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
716 {
717     POINT *pts = HeapAlloc( GetProcessHeap(), 0,
718                               sizeof(POINT) * (cCount + 1) );
719     if(!pts) return FALSE;
720
721     /* Get the current point */
722     MoveToEx( hdc, 0, 0, pts);
723
724     /* Add in the other points */
725     memcpy( pts + 1, pt, sizeof(POINT) * cCount );
726
727     /* Draw the lines */
728     Polyline( hdc, pts, cCount + 1 );
729
730     /* Move to last point */
731     MoveToEx( hdc, (pts + cCount)->x, (pts + cCount)->y, NULL );
732
733     HeapFree( GetProcessHeap(), 0, pts );
734     return TRUE;
735 }
736
737 /**********************************************************************
738  *          Polygon16  (GDI.36)
739  */
740 BOOL16 WINAPI Polygon16( HDC16 hdc, const POINT16* pt, INT16 count )
741 {
742     register int i;
743     BOOL ret;
744     LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
745                                            count*sizeof(POINT) );
746
747     if (!pt32) return FALSE;
748     for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
749     ret = Polygon(hdc,pt32,count);
750     HeapFree( GetProcessHeap(), 0, pt32 );
751     return ret;
752 }
753
754
755 /**********************************************************************
756  *          Polygon32  (GDI32.275)
757  */
758 BOOL WINAPI Polygon( HDC hdc, const POINT* pt, INT count )
759 {
760     DC * dc = DC_GetDCPtr( hdc );
761
762     return dc && dc->funcs->pPolygon &&
763            dc->funcs->pPolygon(dc,pt,count);
764 }
765
766
767 /**********************************************************************
768  *          PolyPolygon16  (GDI.450)
769  */
770 BOOL16 WINAPI PolyPolygon16( HDC16 hdc, const POINT16* pt, const INT16* counts,
771                              UINT16 polygons )
772 {
773     int         i,nrpts;
774     LPPOINT     pt32;
775     LPINT       counts32;
776     BOOL16      ret;
777
778     nrpts=0;
779     for (i=polygons;i--;)
780         nrpts+=counts[i];
781     pt32 = (LPPOINT)HEAP_xalloc( GetProcessHeap(), 0, sizeof(POINT)*nrpts);
782     for (i=nrpts;i--;)
783         CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
784     counts32 = (LPINT)HEAP_xalloc( GetProcessHeap(), 0,
785                                      polygons*sizeof(INT) );
786     for (i=polygons;i--;) counts32[i]=counts[i];
787    
788     ret = PolyPolygon(hdc,pt32,counts32,polygons);
789     HeapFree( GetProcessHeap(), 0, counts32 );
790     HeapFree( GetProcessHeap(), 0, pt32 );
791     return ret;
792 }
793
794 /**********************************************************************
795  *          PolyPolygon32  (GDI.450)
796  */
797 BOOL WINAPI PolyPolygon( HDC hdc, const POINT* pt, const INT* counts,
798                              UINT polygons )
799 {
800     DC * dc = DC_GetDCPtr( hdc );
801
802     return dc && dc->funcs->pPolyPolygon &&
803            dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
804 }
805
806 /**********************************************************************
807  *          PolyPolyline  (GDI32.272)
808  */
809 BOOL WINAPI PolyPolyline( HDC hdc, const POINT* pt, const DWORD* counts,
810                             DWORD polylines )
811 {
812     DC * dc = DC_GetDCPtr( hdc );
813
814     return dc && dc->funcs->pPolyPolyline &&
815            dc->funcs->pPolyPolyline(dc,pt,counts,polylines);
816 }
817
818 /**********************************************************************
819  *          ExtFloodFill16   (GDI.372)
820  */
821 BOOL16 WINAPI ExtFloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color,
822                               UINT16 fillType )
823 {
824     return ExtFloodFill( hdc, x, y, color, fillType );
825 }
826
827
828 /**********************************************************************
829  *          ExtFloodFill32   (GDI32.96)
830  */
831 BOOL WINAPI ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color,
832                               UINT fillType )
833 {
834     DC *dc = DC_GetDCPtr( hdc );
835
836     return dc && dc->funcs->pExtFloodFill &&
837            dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
838 }
839
840
841 /**********************************************************************
842  *          FloodFill16   (GDI.25)
843  */
844 BOOL16 WINAPI FloodFill16( HDC16 hdc, INT16 x, INT16 y, COLORREF color )
845 {
846     return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
847 }
848
849
850 /**********************************************************************
851  *          FloodFill32   (GDI32.104)
852  */
853 BOOL WINAPI FloodFill( HDC hdc, INT x, INT y, COLORREF color )
854 {
855     return ExtFloodFill( hdc, x, y, color, FLOODFILLBORDER );
856 }
857
858
859 /**********************************************************************
860  *          DrawAnimatedRects16  (USER.448)
861  */
862 BOOL16 WINAPI DrawAnimatedRects16( HWND16 hwnd, INT16 idAni,
863                                    const RECT16* lprcFrom,
864                                    const RECT16* lprcTo )
865 {
866     RECT rcFrom32, rcTo32;
867
868     rcFrom32.left       = (INT)lprcFrom->left;
869     rcFrom32.top        = (INT)lprcFrom->top;
870     rcFrom32.right      = (INT)lprcFrom->right;
871     rcFrom32.bottom     = (INT)lprcFrom->bottom;
872
873     rcTo32.left         = (INT)lprcTo->left;
874     rcTo32.top          = (INT)lprcTo->top;
875     rcTo32.right        = (INT)lprcTo->right;
876     rcTo32.bottom       = (INT)lprcTo->bottom;
877
878     return DrawAnimatedRects((HWND)hwnd, (INT)idAni, &rcFrom32, &rcTo32);
879 }
880
881
882 /**********************************************************************
883  *          DrawAnimatedRects32  (USER32.153)
884  */
885 BOOL WINAPI DrawAnimatedRects( HWND hwnd, int idAni,
886                                    const RECT* lprcFrom,
887                                    const RECT* lprcTo )
888 {
889     FIXME(gdi,"(0x%x,%d,%p,%p): stub\n",hwnd,idAni,lprcFrom,lprcTo);
890     return TRUE;
891 }
892
893
894 /**********************************************************************
895  *          PAINTING_DrawStateJam
896  *
897  * Jams in the requested type in the dc
898  */
899 static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode,
900                                     DRAWSTATEPROC func, LPARAM lp, WPARAM wp, 
901                                     LPRECT rc, UINT dtflags,
902                                     BOOL unicode, BOOL _32bit)
903 {
904     HDC memdc;
905     HBITMAP hbmsave;
906     BOOL retval;
907     INT cx = rc->right - rc->left;
908     INT cy = rc->bottom - rc->top;
909     
910     switch(opcode)
911     {
912     case DST_TEXT:
913     case DST_PREFIXTEXT:
914         if(unicode)
915             return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags);
916         else if(_32bit)
917             return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags);
918         else
919             return DrawTextA(hdc, (LPSTR)PTR_SEG_TO_LIN(lp), (INT)wp, rc, dtflags);
920
921     case DST_ICON:
922         return DrawIcon(hdc, rc->left, rc->top, (HICON)lp);
923
924     case DST_BITMAP:
925         memdc = CreateCompatibleDC(hdc);
926         if(!memdc) return FALSE;
927         hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp);
928         if(!hbmsave) 
929         {
930             DeleteDC(memdc);
931             return FALSE;
932         }
933         retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY);
934         SelectObject(memdc, hbmsave);
935         DeleteDC(memdc);
936         return retval;
937             
938     case DST_COMPLEX:
939         if(func)
940             if(_32bit)
941                 return func(hdc, lp, wp, cx, cy);
942             else
943                 return (BOOL)((DRAWSTATEPROC16)func)((HDC16)hdc, (LPARAM)lp, (WPARAM16)wp, (INT16)cx, (INT16)cy);
944         else
945             return FALSE;
946     }
947     return FALSE;
948 }
949
950 /**********************************************************************
951  *      PAINTING_DrawState32()
952  */
953 static BOOL PAINTING_DrawState(HDC hdc, HBRUSH hbr, 
954                                    DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
955                                    INT x, INT y, INT cx, INT cy, 
956                                    UINT flags, BOOL unicode, BOOL _32bit)
957 {
958     HBITMAP hbm, hbmsave;
959     HFONT hfsave;
960     HBRUSH hbsave;
961     HDC memdc;
962     RECT rc;
963     UINT dtflags = DT_NOCLIP;
964     COLORREF fg, bg;
965     UINT opcode = flags & 0xf;
966     INT len = wp;
967     BOOL retval, tmp;
968
969     if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len)    /* The string is '\0' terminated */
970     {
971         if(unicode)
972             len = lstrlenW((LPWSTR)lp);
973         else if(_32bit)
974             len = lstrlenA((LPSTR)lp);
975         else
976             len = lstrlenA((LPSTR)PTR_SEG_TO_LIN(lp));
977     }
978
979     /* Find out what size the image has if not given by caller */
980     if(!cx || !cy)
981     {
982         SIZE s;
983         CURSORICONINFO *ici;
984         BITMAPOBJ *bmp;
985
986         switch(opcode)
987         {
988         case DST_TEXT:
989         case DST_PREFIXTEXT:
990             if(unicode)
991                 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s);
992             else if(_32bit)
993                 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s);
994             else
995                 retval = GetTextExtentPoint32A(hdc, PTR_SEG_TO_LIN(lp), len, &s);
996             if(!retval) return FALSE;
997             break;
998             
999         case DST_ICON:
1000             ici = (CURSORICONINFO *)GlobalLock16((HGLOBAL16)lp);
1001             if(!ici) return FALSE;
1002             s.cx = ici->nWidth;
1003             s.cy = ici->nHeight;
1004             GlobalUnlock16((HGLOBAL16)lp);
1005             break;            
1006
1007         case DST_BITMAP:
1008             bmp = (BITMAPOBJ *)GDI_GetObjPtr((HBITMAP16)lp, BITMAP_MAGIC);
1009             if(!bmp) return FALSE;
1010             s.cx = bmp->bitmap.bmWidth;
1011             s.cy = bmp->bitmap.bmHeight;
1012             break;
1013             
1014         case DST_COMPLEX: /* cx and cy must be set in this mode */
1015             return FALSE;
1016         }
1017                     
1018         if(!cx) cx = s.cx;
1019         if(!cy) cy = s.cy;
1020     }
1021
1022     rc.left   = x;
1023     rc.top    = y;
1024     rc.right  = x + cx;
1025     rc.bottom = y + cy;
1026
1027     if(flags & DSS_RIGHT)    /* This one is not documented in the win32.hlp file */
1028         dtflags |= DT_RIGHT;
1029     if(opcode == DST_TEXT)
1030         dtflags |= DT_NOPREFIX;
1031
1032     /* For DSS_NORMAL we just jam in the image and return */
1033     if((flags & 0x7ff0) == DSS_NORMAL)
1034     {
1035         return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit);
1036     }
1037
1038     /* For all other states we need to convert the image to B/W in a local bitmap */
1039     /* before it is displayed */
1040     fg = SetTextColor(hdc, RGB(0, 0, 0));
1041     bg = SetBkColor(hdc, RGB(255, 255, 255));
1042     hbm = (HBITMAP)NULL; hbmsave = (HBITMAP)NULL;
1043     memdc = (HDC)NULL; hbsave = (HBRUSH)NULL;
1044     retval = FALSE; /* assume failure */
1045     
1046     /* From here on we must use "goto cleanup" when something goes wrong */
1047     hbm     = CreateBitmap(cx, cy, 1, 1, NULL);
1048     if(!hbm) goto cleanup;
1049     memdc   = CreateCompatibleDC(hdc);
1050     if(!memdc) goto cleanup;
1051     hbmsave = (HBITMAP)SelectObject(memdc, hbm);
1052     if(!hbmsave) goto cleanup;
1053     rc.left = rc.top = 0;
1054     rc.right = cx;
1055     rc.bottom = cy;
1056     if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup;
1057     SetBkColor(memdc, RGB(255, 255, 255));
1058     SetTextColor(memdc, RGB(0, 0, 0));
1059     hfsave  = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
1060     if(!hfsave && (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)) goto cleanup;
1061     tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode, _32bit);
1062     if(hfsave) SelectObject(memdc, hfsave);
1063     if(!tmp) goto cleanup;
1064     
1065     /* These states cause the image to be dithered */
1066     if(flags & (DSS_UNION|DSS_DISABLED))
1067     {
1068         hbsave = (HBRUSH)SelectObject(memdc, CACHE_GetPattern55AABrush());
1069         if(!hbsave) goto cleanup;
1070         tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089);
1071         if(hbsave) SelectObject(memdc, hbsave);
1072         if(!tmp) goto cleanup;
1073     }
1074
1075     hbsave = (HBRUSH)SelectObject(hdc, hbr ? hbr : GetStockObject(WHITE_BRUSH));
1076     if(!hbsave) goto cleanup;
1077     
1078     if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
1079     
1080     /* DSS_DEFAULT makes the image boldface */
1081     if(flags & DSS_DEFAULT)
1082     {
1083         if(!BitBlt(hdc, x+1, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
1084     }
1085
1086     retval = TRUE; /* We succeeded */
1087     
1088 cleanup:    
1089     SetTextColor(hdc, fg);
1090     SetBkColor(hdc, bg);
1091
1092     if(hbsave)  SelectObject(hdc, hbsave);
1093     if(hbmsave) SelectObject(memdc, hbmsave);
1094     if(hbm)     DeleteObject(hbm);
1095     if(memdc)   DeleteDC(memdc);
1096
1097     return retval;
1098 }
1099
1100 /**********************************************************************
1101  *      DrawState32A()   (USER32.162)
1102  */
1103 BOOL WINAPI DrawStateA(HDC hdc, HBRUSH hbr,
1104                    DRAWSTATEPROC func, LPARAM ldata, WPARAM wdata,
1105                    INT x, INT y, INT cx, INT cy, UINT flags)
1106 {
1107     return PAINTING_DrawState(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, FALSE, TRUE);
1108 }
1109
1110 /**********************************************************************
1111  *      DrawState32W()   (USER32.163)
1112  */
1113 BOOL WINAPI DrawStateW(HDC hdc, HBRUSH hbr,
1114                    DRAWSTATEPROC func, LPARAM ldata, WPARAM wdata,
1115                    INT x, INT y, INT cx, INT cy, UINT flags)
1116 {
1117     return PAINTING_DrawState(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, TRUE, TRUE);
1118 }
1119
1120 /**********************************************************************
1121  *      DrawState16()   (USER.449)
1122  */
1123 BOOL16 WINAPI DrawState16(HDC16 hdc, HBRUSH16 hbr,
1124                    DRAWSTATEPROC16 func, LPARAM ldata, WPARAM16 wdata,
1125                    INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags)
1126 {
1127     return PAINTING_DrawState(hdc, hbr, (DRAWSTATEPROC)func, ldata, wdata, x, y, cx, cy, flags, FALSE, FALSE);
1128 }
1129
1130
1131 /******************************************************************************
1132  * PolyBezier16 [GDI.502]
1133  */
1134 BOOL16 WINAPI PolyBezier16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
1135 {
1136     int i;
1137     BOOL16 ret;
1138     LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
1139                                            cPoints*sizeof(POINT) );
1140     if(!pt32) return FALSE;
1141     for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
1142     ret= PolyBezier(hDc, pt32, cPoints);
1143     HeapFree( GetProcessHeap(), 0, pt32 );
1144     return ret;
1145 }
1146
1147 /******************************************************************************
1148  * PolyBezierTo16 [GDI.503]
1149  */
1150 BOOL16 WINAPI PolyBezierTo16( HDC16 hDc, const POINT16* lppt, INT16 cPoints )
1151 {
1152     int i;
1153     BOOL16 ret;
1154     LPPOINT pt32 = (LPPOINT)HeapAlloc( GetProcessHeap(), 0,
1155                                            cPoints*sizeof(POINT) );
1156     if(!pt32) return FALSE;
1157     for (i=cPoints;i--;) CONV_POINT16TO32(&(lppt[i]),&(pt32[i]));
1158     ret= PolyBezierTo(hDc, pt32, cPoints);
1159     HeapFree( GetProcessHeap(), 0, pt32 );
1160     return ret;
1161 }
1162
1163 /******************************************************************************
1164  * PolyBezier32 [GDI32.268]
1165  * Draws one or more Bezier curves
1166  *
1167  * PARAMS
1168  *    hDc     [I] Handle to device context
1169  *    lppt    [I] Pointer to endpoints and control points
1170  *    cPoints [I] Count of endpoints and control points
1171  *
1172  * RETURNS STD
1173  */
1174 BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
1175 {
1176     DC * dc = DC_GetDCPtr( hdc );
1177     if(!dc) return FALSE;
1178     if(dc && PATH_IsPathOpen(dc->w.path))
1179         FIXME(gdi, "PATH_PolyBezier is not implemented!\n");
1180 /*        if(!PATH_PolyBezier(hdc, x, y))
1181            return FALSE; */
1182     return dc->funcs->pPolyBezier&&
1183            dc->funcs->pPolyBezier(dc, lppt[0], lppt+1, cPoints-1);
1184 }
1185
1186 /******************************************************************************
1187  * PolyBezierTo32 [GDI32.269]
1188  * Draws one or more Bezier curves
1189  *
1190  * PARAMS
1191  *    hDc     [I] Handle to device context
1192  *    lppt    [I] Pointer to endpoints and control points
1193  *    cPoints [I] Count of endpoints and control points
1194  *
1195  * RETURNS STD
1196  */
1197 BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
1198 {
1199     DC * dc = DC_GetDCPtr( hdc );
1200     POINT pt;
1201     BOOL ret;
1202     if(!dc) return FALSE;
1203     pt.x=dc->w.CursPosX;
1204     pt.y=dc->w.CursPosY;
1205     if(dc && PATH_IsPathOpen(dc->w.path))
1206         FIXME(gdi, "PATH_PolyBezierTo is not implemented!\n");
1207 /*        if(!PATH_PolyBezier(hdc, x, y))
1208            return FALSE; */
1209     ret= dc->funcs->pPolyBezier &&
1210            dc->funcs->pPolyBezier(dc, pt, lppt, cPoints);
1211     if( dc->funcs->pMoveToEx)
1212            dc->funcs->pMoveToEx(dc,lppt[cPoints].x,lppt[cPoints].y,&pt);
1213     return ret;
1214 }
1215
1216 /***************************************************************
1217  *      AngleArc (GDI32.5)
1218  *
1219  */
1220 BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius,
1221                        FLOAT eStartAngle, FLOAT eSweepAngle)
1222 {
1223         FIXME(gdi,"AngleArc, stub\n");
1224         return 0;
1225 }
1226
1227 /***************************************************************
1228  *      PolyDraw (GDI32.270)
1229  *
1230  */
1231 BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
1232                        DWORD cCount)
1233 {
1234         FIXME(gdi,"PolyDraw, stub\n");
1235         return 0;
1236 }