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