xref: /reactos/win32ss/gdi/gdi32/objects/painting.c (revision 1ac9e484)
1 #include <precomp.h>
2 
3 
4 /*
5  * @implemented
6  */
7 BOOL
8 WINAPI
9 LineTo(
10     _In_ HDC hdc,
11     _In_ INT x,
12     _In_ INT y )
13 {
14     HANDLE_METADC(BOOL, LineTo, FALSE, hdc, x, y);
15 
16     return NtGdiLineTo(hdc, x, y);
17 }
18 
19 
20 BOOL
21 WINAPI
22 MoveToEx(
23     _In_ HDC hdc,
24     _In_ INT x,
25     _In_ INT y,
26     _Out_opt_ LPPOINT ppt)
27 {
28     PDC_ATTR pdcattr;
29 
30     HANDLE_METADC(BOOL, MoveTo, FALSE, hdc, x, y, ppt);
31 
32     /* Get the DC attribute */
33     pdcattr = GdiGetDcAttr(hdc);
34     if (pdcattr == NULL)
35     {
36         SetLastError(ERROR_INVALID_PARAMETER);
37         return FALSE;
38     }
39 
40     if (ppt)
41     {
42         if ( pdcattr->ulDirty_ & DIRTY_PTLCURRENT ) // Double hit!
43         {
44             ppt->x = pdcattr->ptfxCurrent.x; // ret prev before change.
45             ppt->y = pdcattr->ptfxCurrent.y;
46             DPtoLP (hdc, ppt, 1);          // reconvert back.
47         }
48         else
49         {
50             ppt->x = pdcattr->ptlCurrent.x;
51             ppt->y = pdcattr->ptlCurrent.y;
52         }
53     }
54 
55     pdcattr->ptlCurrent.x = x;
56     pdcattr->ptlCurrent.y = y;
57 
58     pdcattr->ulDirty_ &= ~DIRTY_PTLCURRENT;
59     pdcattr->ulDirty_ |= ( DIRTY_PTFXCURRENT|DIRTY_STYLESTATE); // Set dirty
60     return TRUE;
61 }
62 
63 
64 /*
65  * @implemented
66  */
67 BOOL
68 WINAPI
69 Ellipse(
70     _In_ HDC hdc,
71     _In_ INT left,
72     _In_ INT top,
73     _In_ INT right,
74     _In_ INT bottom)
75 {
76     HANDLE_METADC(BOOL, Ellipse, FALSE, hdc, left, top, right, bottom);
77 
78     return NtGdiEllipse(hdc, left, top, right, bottom);
79 }
80 
81 
82 /*
83  * @implemented
84  */
85 BOOL
86 WINAPI
87 Rectangle(
88     _In_ HDC hdc,
89     _In_ INT left,
90     _In_ INT top,
91     _In_ INT right,
92     _In_ INT bottom)
93 {
94     HANDLE_METADC(BOOL, Rectangle, FALSE, hdc, left, top, right, bottom);
95 
96     return NtGdiRectangle(hdc, left, top, right, bottom);
97 }
98 
99 
100 /*
101  * @implemented
102  */
103 BOOL
104 WINAPI
105 RoundRect(
106     _In_ HDC hdc,
107     _In_ INT left,
108     _In_ INT top,
109     _In_ INT right,
110     _In_ INT bottom,
111     _In_ INT width,
112     _In_ INT height)
113 {
114     HANDLE_METADC(BOOL, RoundRect, FALSE, hdc, left, top, right, bottom, width, height);
115 
116     return NtGdiRoundRect(hdc, left, top, right, bottom, width, height);
117 }
118 
119 
120 /*
121  * @implemented
122  */
123 COLORREF
124 WINAPI
125 GetPixel(
126     _In_ HDC hdc,
127     _In_ INT x,
128     _In_ INT y)
129 {
130     if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) return CLR_INVALID;
131     if (!GdiValidateHandle((HGDIOBJ) hdc)) return CLR_INVALID;
132     return NtGdiGetPixel(hdc, x, y);
133 }
134 
135 
136 /*
137  * @implemented
138  */
139 COLORREF
140 WINAPI
141 SetPixel(
142     _In_ HDC hdc,
143     _In_ INT x,
144     _In_ INT y,
145     _In_ COLORREF crColor)
146 {
147     HANDLE_METADC(COLORREF, SetPixel, CLR_INVALID, hdc, x, y, crColor);
148 
149     return NtGdiSetPixel(hdc, x, y, crColor);
150 }
151 
152 
153 /*
154  * @implemented
155  */
156 BOOL
157 WINAPI
158 SetPixelV(
159     _In_ HDC hdc,
160     _In_ INT x,
161     _In_ INT y,
162     _In_ COLORREF crColor)
163 {
164     return SetPixel(hdc, x, y, crColor) != CLR_INVALID;
165 }
166 
167 
168 /*
169  * @implemented
170  */
171 BOOL
172 WINAPI
173 FillRgn(
174     _In_ HDC hdc,
175     _In_ HRGN hrgn,
176     _In_ HBRUSH hbr)
177 {
178 
179     if ((hrgn == NULL) || (hbr == NULL))
180         return FALSE;
181 
182     HANDLE_METADC(BOOL, FillRgn, FALSE, hdc, hrgn, hbr);
183 
184     return NtGdiFillRgn(hdc, hrgn, hbr);
185 }
186 
187 
188 /*
189  * @implemented
190  */
191 BOOL
192 WINAPI
193 FrameRgn(
194     _In_ HDC hdc,
195     _In_ HRGN hrgn,
196     _In_ HBRUSH hbr,
197     _In_ INT nWidth,
198     _In_ INT nHeight)
199 {
200 
201     if ((hrgn == NULL) || (hbr == NULL))
202         return FALSE;
203 
204     HANDLE_METADC(BOOL, FrameRgn, FALSE, hdc, hrgn, hbr, nWidth, nHeight);
205 
206     return NtGdiFrameRgn(hdc, hrgn, hbr, nWidth, nHeight);
207 }
208 
209 
210 /*
211  * @implemented
212  */
213 BOOL
214 WINAPI
215 InvertRgn(
216     _In_ HDC hdc,
217     _In_ HRGN hrgn)
218 {
219 
220     if (hrgn == NULL)
221         return FALSE;
222 
223     HANDLE_METADC(BOOL, InvertRgn, FALSE, hdc, hrgn);
224 
225     return NtGdiInvertRgn(hdc, hrgn);
226 }
227 
228 
229 /*
230  * @implemented
231  */
232 BOOL
233 WINAPI
234 PaintRgn(
235     _In_ HDC hdc,
236     _In_ HRGN hrgn)
237 {
238     return FillRgn(hdc, hrgn, GetCurrentObject(hdc, OBJ_BRUSH));
239 }
240 
241 
242 /*
243  * @implemented
244  */
245 BOOL
246 WINAPI
247 PolyBezier(
248     _In_ HDC hdc,
249     _In_reads_(cpt) const POINT *apt,
250     _In_ DWORD cpt)
251 {
252     HANDLE_METADC(BOOL, PolyBezier, FALSE, hdc, apt, cpt);
253 
254     return NtGdiPolyPolyDraw(hdc ,(PPOINT)apt, &cpt, 1, GdiPolyBezier);
255 }
256 
257 
258 /*
259  * @implemented
260  */
261 BOOL
262 WINAPI
263 PolyBezierTo(
264     _In_ HDC hdc,
265     _In_reads_(cpt) const POINT *apt,
266     _In_ DWORD cpt)
267 {
268     HANDLE_METADC(BOOL, PolyBezierTo, FALSE, hdc, apt, cpt);
269 
270     return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyBezierTo);
271 }
272 
273 
274 /*
275  * @implemented
276  */
277 BOOL
278 WINAPI
279 PolyDraw(
280     _In_ HDC hdc,
281     _In_reads_(cpt) const POINT *apt,
282     _In_reads_(cpt) const BYTE *aj,
283     _In_ INT cpt)
284 {
285     HANDLE_METADC(BOOL, PolyDraw, FALSE, hdc, apt, aj, cpt);
286 
287     return NtGdiPolyDraw(hdc, (PPOINT)apt, (PBYTE)aj, cpt);
288 }
289 
290 
291 /*
292  * @implemented
293  */
294 BOOL
295 WINAPI
296 Polygon(
297     _In_ HDC hdc,
298     _In_reads_(cpt) const POINT *apt,
299     _In_ INT cpt)
300 {
301     HANDLE_METADC(BOOL, Polygon, FALSE, hdc, apt, cpt);
302 
303     return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, (PULONG)&cpt, 1, GdiPolyPolygon);
304 }
305 
306 
307 /*
308  * @implemented
309  */
310 BOOL
311 WINAPI
312 Polyline(
313     _In_ HDC hdc,
314     _In_reads_(cpt) const POINT *apt,
315     _In_ INT cpt)
316 {
317     HANDLE_METADC(BOOL, Polyline, FALSE, hdc, apt, cpt);
318 
319     return NtGdiPolyPolyDraw(hdc, (PPOINT)apt, (PULONG)&cpt, 1, GdiPolyPolyLine);
320 }
321 
322 
323 /*
324  * @implemented
325  */
326 BOOL
327 WINAPI
328 PolylineTo(
329     _In_ HDC hdc,
330     _In_reads_(cpt) const POINT *apt,
331     _In_ DWORD cpt)
332 {
333     HANDLE_METADC(BOOL, PolylineTo, FALSE, hdc, apt, cpt);
334 
335     return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyLineTo);
336 }
337 
338 
339 /*
340  * @implemented
341  */
342 BOOL
343 WINAPI
344 PolyPolygon(
345     _In_ HDC hdc,
346     _In_ const POINT *apt,
347     _In_reads_(csz) const INT *asz,
348     _In_ INT csz)
349 {
350     HANDLE_METADC(BOOL, PolyPolygon, FALSE, hdc, apt, asz, csz);
351 
352     return NtGdiPolyPolyDraw(hdc, (PPOINT)apt, (PULONG)asz, csz, GdiPolyPolygon);
353 }
354 
355 
356 /*
357  * @implemented
358  */
359 BOOL
360 WINAPI
361 PolyPolyline(
362     _In_ HDC hdc,
363     _In_ CONST POINT *apt,
364     _In_reads_(csz) CONST DWORD *asz,
365     _In_ DWORD csz)
366 {
367     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
368         return FALSE;
369 
370     HANDLE_METADC(BOOL, PolyPolyline, FALSE, hdc, apt, asz, csz);
371 
372     return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, (PULONG)asz, csz, GdiPolyPolyLine);
373 }
374 
375 
376 /*
377  * @implemented
378  */
379 BOOL
380 WINAPI
381 ExtFloodFill(
382     _In_ HDC hdc,
383     _In_ INT xStart,
384     _In_ INT yStart,
385     _In_ COLORREF crFill,
386     _In_ UINT fuFillType)
387 {
388     HANDLE_METADC(BOOL, ExtFloodFill, FALSE, hdc, xStart, yStart, crFill, fuFillType);
389 
390     return NtGdiExtFloodFill(hdc, xStart, yStart, crFill, fuFillType);
391 }
392 
393 
394 /*
395  * @implemented
396  */
397 BOOL
398 WINAPI
399 FloodFill(
400     _In_ HDC hdc,
401     _In_ INT xStart,
402     _In_ INT yStart,
403     _In_ COLORREF crFill)
404 {
405     return ExtFloodFill(hdc, xStart, yStart, crFill, FLOODFILLBORDER);
406 }
407 
408 /*
409  * @implemented
410  */
411 BOOL
412 WINAPI
413 BitBlt(
414     _In_ HDC hdcDest,
415     _In_ INT xDest,
416     _In_ INT yDest,
417     _In_ INT cx,
418     _In_ INT cy,
419     _In_opt_ HDC hdcSrc,
420     _In_ INT xSrc,
421     _In_ INT ySrc,
422     _In_ DWORD dwRop)
423 {
424     /* Use PatBlt for no source blt, like windows does */
425     if (!ROP_USES_SOURCE(dwRop))
426     {
427         return PatBlt(hdcDest, xDest, yDest, cx, cy, dwRop);
428     }
429 
430     /* For meta DCs we use StretchBlt */
431     HANDLE_METADC(BOOL,
432                   StretchBlt,
433                   FALSE,
434                   hdcDest,
435                   xDest,
436                   yDest,
437                   cx,
438                   cx,
439                   hdcSrc,
440                   xSrc,
441                   ySrc,
442                   cx,
443                   cx,
444                   dwRop);
445 
446     return NtGdiBitBlt(hdcDest, xDest, yDest, cx, cy, hdcSrc, xSrc, ySrc, dwRop, 0, 0);
447 }
448 
449 BOOL
450 WINAPI
451 PatBlt(
452     _In_ HDC hdc,
453     _In_ INT nXLeft,
454     _In_ INT nYLeft,
455     _In_ INT nWidth,
456     _In_ INT nHeight,
457     _In_ DWORD dwRop)
458 {
459     PDC_ATTR pdcattr;
460 
461     HANDLE_METADC(BOOL, PatBlt, FALSE, hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop);
462 
463     /* Get the DC attribute */
464     pdcattr = GdiGetDcAttr(hdc);
465     if (pdcattr && !(pdcattr->ulDirty_ & DC_DIBSECTION))
466     {
467         PGDIBSPATBLT pgO;
468 
469         pgO = GdiAllocBatchCommand(hdc, GdiBCPatBlt);
470         if (pgO)
471         {
472             pdcattr->ulDirty_ |= DC_MODE_DIRTY;
473             pgO->nXLeft  = nXLeft;
474             pgO->nYLeft  = nYLeft;
475             pgO->nWidth  = nWidth;
476             pgO->nHeight = nHeight;
477             pgO->dwRop   = dwRop;
478             /* Snapshot attributes */
479             pgO->hbrush          = pdcattr->hbrush;
480             pgO->crForegroundClr = pdcattr->crForegroundClr;
481             pgO->crBackgroundClr = pdcattr->crBackgroundClr;
482             pgO->crBrushClr      = pdcattr->crBrushClr;
483             pgO->ulForegroundClr = pdcattr->ulForegroundClr;
484             pgO->ulBackgroundClr = pdcattr->ulBackgroundClr;
485             pgO->ulBrushClr      = pdcattr->ulBrushClr;
486             return TRUE;
487         }
488     }
489     return NtGdiPatBlt( hdc,  nXLeft,  nYLeft,  nWidth,  nHeight,  dwRop);
490 }
491 
492 BOOL
493 WINAPI
494 PolyPatBlt(
495     _In_ HDC hdc,
496     _In_ DWORD dwRop,
497     _In_ PPOLYPATBLT pPoly,
498     _In_ DWORD nCount,
499     _In_ DWORD dwMode)
500 {
501     UINT i;
502     BOOL bResult;
503     HBRUSH hbrOld;
504     PDC_ATTR pdcattr;
505 
506     /* Handle meta DCs */
507     if ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
508         (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE))
509     {
510         if (!GdiValidateHandle(hdc))
511         {
512             return FALSE;
513         }
514 
515         /* Save the current DC brush */
516         hbrOld = SelectObject(hdc, GetStockObject(DC_BRUSH));
517 
518         /* Assume success */
519         bResult = TRUE;
520 
521         /* Loop all rect */
522         for (i = 0; i < nCount; i++)
523         {
524             /* Select the brush for this rect */
525             SelectObject(hdc, pPoly[i].hBrush);
526 
527             /* Do the PatBlt operation for this rect */
528             bResult &= PatBlt(hdc,
529                                pPoly[i].nXLeft,
530                                pPoly[i].nYLeft,
531                                pPoly[i].nWidth,
532                                pPoly[i].nHeight,
533                                dwRop);
534         }
535 
536         /* Restore the old brush */
537         SelectObject(hdc, hbrOld);
538 
539         return bResult;
540     }
541 
542     /* Get the DC attribute */
543     pdcattr = GdiGetDcAttr(hdc);
544     if (nCount && pdcattr && !(pdcattr->ulDirty_ & DC_DIBSECTION))
545     {
546         PGDIBSPPATBLT pgO;
547         PTEB pTeb = NtCurrentTeb();
548 
549         pgO = GdiAllocBatchCommand(hdc, GdiBCPolyPatBlt);
550         if (pgO)
551         {
552             USHORT cjSize = 0;
553             if (nCount > 1) cjSize = (nCount-1) * sizeof(PATRECT);
554 
555             if ((pTeb->GdiTebBatch.Offset + cjSize) <= GDIBATCHBUFSIZE)
556             {
557                 pdcattr->ulDirty_ |= DC_MODE_DIRTY;
558                 pgO->Count = nCount;
559                 pgO->Mode  = dwMode;
560                 pgO->rop4  = dwRop;
561                 /* Snapshot attributes */
562                 pgO->crForegroundClr = pdcattr->crForegroundClr;
563                 pgO->crBackgroundClr = pdcattr->crBackgroundClr;
564                 pgO->crBrushClr      = pdcattr->crBrushClr;
565                 pgO->ulForegroundClr = pdcattr->ulForegroundClr;
566                 pgO->ulBackgroundClr = pdcattr->ulBackgroundClr;
567                 pgO->ulBrushClr      = pdcattr->ulBrushClr;
568                 RtlCopyMemory(pgO->pRect, pPoly, nCount * sizeof(PATRECT));
569                 // Recompute offset and return size, remember one is already accounted for in the structure.
570                 pTeb->GdiTebBatch.Offset += cjSize;
571                 ((PGDIBATCHHDR)pgO)->Size += cjSize;
572                 return TRUE;
573             }
574             // Reset offset and count then fall through
575             pTeb->GdiTebBatch.Offset -= sizeof(GDIBSPPATBLT);
576             pTeb->GdiBatchCount--;
577         }
578     }
579     return NtGdiPolyPatBlt(hdc, dwRop, pPoly, nCount, dwMode);
580 }
581 
582 /*
583  * @implemented
584  */
585 BOOL
586 WINAPI
587 StretchBlt(
588     _In_ HDC hdcDest,
589     _In_ INT xDest,
590     _In_ INT yDest,
591     _In_ INT cxDest,
592     _In_ INT cyDest,
593     _In_opt_ HDC hdcSrc,
594     _In_ INT xSrc,
595     _In_ INT ySrc,
596     _In_ INT cxSrc,
597     _In_ INT cySrc,
598     _In_ DWORD dwRop)
599 {
600     HANDLE_METADC(BOOL,
601                   StretchBlt,
602                   FALSE,
603                   hdcDest,
604                   xDest,
605                   yDest,
606                   cxDest,
607                   cyDest,
608                   hdcSrc,
609                   xSrc,
610                   ySrc,
611                   cxSrc,
612                   cySrc,
613                   dwRop);
614 
615     return NtGdiStretchBlt(hdcDest,
616                            xDest,
617                            yDest,
618                            cxDest,
619                            cyDest,
620                            hdcSrc,
621                            xSrc,
622                            ySrc,
623                            cxSrc,
624                            cySrc,
625                            dwRop,
626                            0);
627 }
628 
629 
630 /*
631  * @implemented
632  */
633 BOOL
634 WINAPI
635 MaskBlt(
636     _In_ HDC hdcDest,
637     _In_ INT xDest,
638     _In_ INT yDest,
639     _In_ INT cx,
640     _In_ INT cy,
641     _In_ HDC hdcSrc,
642     _In_ INT xSrc,
643     _In_ INT ySrc,
644     _In_ HBITMAP hbmMask,
645     _In_ INT xMask,
646     _In_ INT yMask,
647     _In_ DWORD dwRop)
648 {
649     HANDLE_METADC(BOOL,
650                   MaskBlt,
651                   FALSE,
652                   hdcDest,
653                   xDest,
654                   yDest,
655                   cx,
656                   cy,
657                   hdcSrc,
658                   xSrc,
659                   ySrc,
660                   hbmMask,
661                   xMask,
662                   yMask,
663                   dwRop);
664 
665     return NtGdiMaskBlt(hdcDest,
666                         xDest,
667                         yDest,
668                         cx,
669                         cy,
670                         hdcSrc,
671                         xSrc,
672                         ySrc,
673                         hbmMask,
674                         xMask,
675                         yMask,
676                         dwRop,
677                         GetBkColor(hdcSrc));
678 }
679 
680 
681 /*
682  * @implemented
683  */
684 BOOL
685 WINAPI
686 PlgBlt(
687     _In_ HDC hdcDest,
688     _In_reads_(3) const POINT * ppt,
689     _In_ HDC hdcSrc,
690     _In_ INT xSrc,
691     _In_ INT ySrc,
692     _In_ INT cx,
693     _In_ INT cy,
694     _In_opt_ HBITMAP hbmMask,
695     _In_ INT xMask,
696     _In_ INT yMask)
697 {
698     HANDLE_METADC(BOOL,
699                   PlgBlt,
700                   FALSE,
701                   hdcDest,
702                   ppt,
703                   hdcSrc,
704                   xSrc,
705                   ySrc,
706                   cx,
707                   cy,
708                   hbmMask,
709                   xMask,
710                   yMask);
711 
712     return NtGdiPlgBlt(hdcDest,
713                        (LPPOINT)ppt,
714                        hdcSrc,
715                        xSrc,
716                        ySrc,
717                        cx,
718                        cy,
719                        hbmMask,
720                        xMask,
721                        yMask,
722                        GetBkColor(hdcSrc));
723 }
724 
725 BOOL
726 WINAPI
727 GdiAlphaBlend(
728     _In_ HDC hdcDst,
729     _In_ INT xDst,
730     _In_ INT yDst,
731     _In_ INT cxDst,
732     _In_ INT cyDst,
733     _In_ HDC hdcSrc,
734     _In_ INT xSrc,
735     _In_ INT ySrc,
736     _In_ INT cxSrc,
737     _In_ INT cySrc,
738     _In_ BLENDFUNCTION blendfn)
739 {
740     if (hdcSrc == NULL ) return FALSE;
741 
742     if (GDI_HANDLE_GET_TYPE(hdcSrc) == GDI_OBJECT_TYPE_METADC) return FALSE;
743 
744     HANDLE_METADC(BOOL,
745                   AlphaBlend,
746                   FALSE,
747                   hdcDst,
748                   xDst,
749                   yDst,
750                   cxDst,
751                   cyDst,
752                   hdcSrc,
753                   xSrc,
754                   ySrc,
755                   cxSrc,
756                   cySrc,
757                   blendfn);
758 
759     return NtGdiAlphaBlend(hdcDst,
760                            xDst,
761                            yDst,
762                            cxDst,
763                            cyDst,
764                            hdcSrc,
765                            xSrc,
766                            ySrc,
767                            cxSrc,
768                            cySrc,
769                            blendfn,
770                            0);
771 }
772 
773 
774 /*
775  * @implemented
776  */
777 BOOL
778 WINAPI
779 GdiTransparentBlt(
780     _In_ HDC hdcDst,
781     _In_ INT xDst,
782     _In_ INT yDst,
783     _In_ INT cxDst,
784     _In_ INT cyDst,
785     _In_ HDC hdcSrc,
786     _In_ INT xSrc,
787     _In_ INT ySrc,
788     _In_ INT cxSrc,
789     _In_ INT cySrc,
790     _In_ UINT crTransparent)
791 {
792     HANDLE_METADC(BOOL,
793                   TransparentBlt,
794                   FALSE,
795                   hdcDst,
796                   xDst,
797                   yDst,
798                   cxDst,
799                   cyDst,
800                   hdcSrc,
801                   xSrc,
802                   ySrc,
803                   cxSrc,
804                   cySrc,
805                   crTransparent);
806 
807     /* FIXME some part need be done in user mode */
808     return NtGdiTransparentBlt(hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, crTransparent);
809 }
810 
811 /*
812  * @implemented
813  */
814 BOOL
815 WINAPI
816 GdiGradientFill(
817     _In_ HDC hdc,
818     _In_reads_(nVertex) PTRIVERTEX pVertex,
819     _In_ ULONG nVertex,
820     _In_ PVOID pMesh,
821     _In_ ULONG nCount,
822     _In_ ULONG ulMode)
823 {
824     HANDLE_METADC(BOOL, GradientFill, FALSE, hdc, pVertex, nVertex, pMesh, nCount, ulMode);
825 
826     /* FIXME some part need be done in user mode */
827     return NtGdiGradientFill(hdc, pVertex, nVertex, pMesh, nCount, ulMode);
828 }
829