2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Bit blit functions
5 * FILE: win32ss/gdi/ntgdi/bitblt.c
10 DBG_DEFAULT_CHANNEL(GdiBlt
);
24 BLENDFUNCTION BlendFunc
,
31 SURFACE
*BitmapDest
, *BitmapSrc
;
32 RECTL DestRect
, SourceRect
;
36 BlendObj
.BlendFunction
= BlendFunc
;
38 if (WidthDest
< 0 || HeightDest
< 0 || WidthSrc
< 0 || HeightSrc
< 0)
40 EngSetLastError(ERROR_INVALID_PARAMETER
);
44 if ((hDCDest
== NULL
) || (hDCSrc
== NULL
))
46 EngSetLastError(ERROR_INVALID_PARAMETER
);
50 TRACE("Locking DCs\n");
53 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
55 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest
, hDCSrc
);
56 EngSetLastError(ERROR_INVALID_HANDLE
);
62 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
64 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
65 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
66 /* Yes, Windows really returns TRUE in this case */
70 DestRect
.left
= XOriginDest
;
71 DestRect
.top
= YOriginDest
;
72 DestRect
.right
= XOriginDest
+ WidthDest
;
73 DestRect
.bottom
= YOriginDest
+ HeightDest
;
74 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
76 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
77 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
78 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
79 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
81 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
83 IntUpdateBoundsRect(DCDest
, &DestRect
);
86 SourceRect
.left
= XOriginSrc
;
87 SourceRect
.top
= YOriginSrc
;
88 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
89 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
90 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
92 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
93 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
94 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
95 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
97 if (!DestRect
.right
||
102 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
103 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
107 /* Prepare DCs for blit */
108 TRACE("Preparing DCs for blit\n");
109 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
111 /* Determine surfaces to be used in the bitblt */
112 BitmapDest
= DCDest
->dclevel
.pSurface
;
119 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
126 /* Create the XLATEOBJ. */
127 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
129 /* Perform the alpha blend operation */
130 TRACE("Performing the alpha blend\n");
131 bResult
= IntEngAlphaBlend(&BitmapDest
->SurfObj
,
133 (CLIPOBJ
*)&DCDest
->co
,
139 EXLATEOBJ_vCleanup(&exlo
);
141 TRACE("Finishing blit\n");
142 DC_vFinishBlit(DCDest
, DCSrc
);
143 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
144 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
160 IN DWORD crBackColor
,
164 if (dwRop
& CAPTUREBLT
)
166 return NtGdiStretchBlt(hDCDest
,
180 dwRop
= dwRop
& ~(NOMIRRORBITMAP
|CAPTUREBLT
);
182 /* Forward to NtGdiMaskBlt */
183 // TODO: What's fl for? LOL not to send this to MaskBit!
184 return NtGdiMaskBlt(hDCDest
,
195 MAKEROP4(dwRop
, dwRop
),
217 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
218 ULONG TransparentColor
= 0;
222 if ((hdcDst
== NULL
) || (hdcSrc
== NULL
))
224 EngSetLastError(ERROR_INVALID_PARAMETER
);
228 TRACE("Locking DCs\n");
231 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
233 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst
, hdcSrc
);
234 EngSetLastError(ERROR_INVALID_HANDLE
);
240 if (DCDest
->dctype
== DC_TYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
242 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
243 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
244 /* Yes, Windows really returns TRUE in this case */
250 rcDest
.right
= rcDest
.left
+ cxDst
;
251 rcDest
.bottom
= rcDest
.top
+ cyDst
;
252 IntLPtoDP(DCDest
, (LPPOINT
)&rcDest
, 2);
254 rcDest
.left
+= DCDest
->ptlDCOrig
.x
;
255 rcDest
.top
+= DCDest
->ptlDCOrig
.y
;
256 rcDest
.right
+= DCDest
->ptlDCOrig
.x
;
257 rcDest
.bottom
+= DCDest
->ptlDCOrig
.y
;
261 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
262 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
263 IntLPtoDP(DCSrc
, (LPPOINT
)&rcSrc
, 2);
265 rcSrc
.left
+= DCSrc
->ptlDCOrig
.x
;
266 rcSrc
.top
+= DCSrc
->ptlDCOrig
.y
;
267 rcSrc
.right
+= DCSrc
->ptlDCOrig
.x
;
268 rcSrc
.bottom
+= DCSrc
->ptlDCOrig
.y
;
270 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
272 IntUpdateBoundsRect(DCDest
, &rcDest
);
275 /* Prepare for blit */
276 DC_vPrepareDCsForBlit(DCDest
, &rcDest
, DCSrc
, &rcSrc
);
278 BitmapDest
= DCDest
->dclevel
.pSurface
;
284 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
290 /* Translate Transparent (RGB) Color to the source palette */
291 EXLATEOBJ_vInitialize(&exlo
, &gpalRGB
, BitmapSrc
->ppal
, 0, 0, 0);
292 TransparentColor
= XLATEOBJ_iXlate(&exlo
.xlo
, (ULONG
)TransColor
);
293 EXLATEOBJ_vCleanup(&exlo
);
295 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
297 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
298 (CLIPOBJ
*)&DCDest
->co
, &exlo
.xlo
, &rcDest
, &rcSrc
,
299 TransparentColor
, 0);
301 EXLATEOBJ_vCleanup(&exlo
);
304 DC_vFinishBlit(DCDest
, DCSrc
);
305 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
306 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
325 IN DWORD crBackColor
)
331 PDC_ATTR pdcattr
= NULL
;
332 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
, *psurfMask
= NULL
;
333 RECTL DestRect
, SourceRect
;
334 POINTL SourcePoint
, MaskPoint
;
337 XLATEOBJ
*XlateObj
= NULL
;
341 rop4
= WIN32_ROP4_TO_ENG_ROP4(dwRop4
);
343 UsesSource
= ROP4_USES_SOURCE(rop4
);
344 if (!hdcDest
|| (UsesSource
&& !hdcSrc
))
346 EngSetLastError(ERROR_INVALID_PARAMETER
);
350 /* Check if we need a mask and have a mask bitmap */
351 if (ROP4_USES_MASK(rop4
) && (hbmMask
!= NULL
))
353 /* Reference the mask bitmap */
354 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
355 if (psurfMask
== NULL
)
357 EngSetLastError(ERROR_INVALID_HANDLE
);
361 /* Make sure the mask bitmap is 1 BPP */
362 if (gajBitsPerFormat
[psurfMask
->SurfObj
.iBitmapFormat
] != 1)
364 EngSetLastError(ERROR_INVALID_PARAMETER
);
365 SURFACE_ShareUnlockSurface(psurfMask
);
371 /* We use NULL, if we need a mask, the Eng function will take care of
372 that and use the brushobject to get a mask */
379 /* Take care of source and destination bitmap */
380 TRACE("Locking DCs\n");
382 ahDC
[1] = UsesSource
? hdcSrc
: NULL
;
383 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
385 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiMaskBlt\n", hdcDest
, hdcSrc
);
386 EngSetLastError(ERROR_INVALID_HANDLE
);
395 if(DCSrc
) DC_UnlockDc(DCSrc
);
396 WARN("Invalid destination dc handle (0x%p) passed to NtGdiMaskBlt\n", hdcDest
);
400 if (DCDest
->dctype
== DC_TYPE_INFO
)
402 if(DCSrc
) DC_UnlockDc(DCSrc
);
404 /* Yes, Windows really returns TRUE in this case */
411 if (DCSrc
->dctype
== DC_TYPE_INFO
)
415 /* Yes, Windows really returns TRUE in this case */
420 pdcattr
= DCDest
->pdcattr
;
422 DestRect
.left
= nXDest
;
423 DestRect
.top
= nYDest
;
424 DestRect
.right
= nXDest
+ nWidth
;
425 DestRect
.bottom
= nYDest
+ nHeight
;
426 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
428 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
429 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
430 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
431 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
433 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
435 IntUpdateBoundsRect(DCDest
, &DestRect
);
438 SourcePoint
.x
= nXSrc
;
439 SourcePoint
.y
= nYSrc
;
443 IntLPtoDP(DCSrc
, (LPPOINT
)&SourcePoint
, 1);
445 SourcePoint
.x
+= DCSrc
->ptlDCOrig
.x
;
446 SourcePoint
.y
+= DCSrc
->ptlDCOrig
.y
;
447 /* Calculate Source Rect */
448 SourceRect
.left
= SourcePoint
.x
;
449 SourceRect
.top
= SourcePoint
.y
;
450 SourceRect
.right
= SourcePoint
.x
+ DestRect
.right
- DestRect
.left
;
451 SourceRect
.bottom
= SourcePoint
.y
+ DestRect
.bottom
- DestRect
.top
;
457 SourceRect
.right
= 0;
458 SourceRect
.bottom
= 0;
462 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
464 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
465 DC_vUpdateFillBrush(DCDest
);
467 /* Determine surfaces to be used in the bitblt */
468 BitmapDest
= DCDest
->dclevel
.pSurface
;
475 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
481 /* Create the XLATEOBJ. */
484 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
485 XlateObj
= &exlo
.xlo
;
488 /* Perform the bitblt operation */
489 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
,
490 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
491 psurfMask
? &psurfMask
->SurfObj
: NULL
,
492 (CLIPOBJ
*)&DCDest
->co
,
497 &DCDest
->eboFill
.BrushObject
,
498 &DCDest
->dclevel
.pbrFill
->ptOrigin
,
502 EXLATEOBJ_vCleanup(&exlo
);
504 DC_vFinishBlit(DCDest
, DCSrc
);
510 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
528 IN DWORD crBackColor
)
530 FIXME("NtGdiPlgBlt: unimplemented.\n");
548 IN DWORD dwBackColor
,
559 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
560 SURFACE
*BitmapMask
= NULL
;
566 XLATEOBJ
*XlateObj
= NULL
;
572 rop4
= WIN32_ROP4_TO_ENG_ROP4(dwRop4
);
574 UsesSource
= ROP4_USES_SOURCE(rop4
);
575 UsesMask
= ROP4_USES_MASK(rop4
);
577 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
579 EngSetLastError(ERROR_INVALID_PARAMETER
);
583 if (!hDCDest
|| (UsesSource
&& !hDCSrc
) || (UsesMask
&& !hDCMask
))
585 EngSetLastError(ERROR_INVALID_PARAMETER
);
590 ahDC
[1] = UsesSource
? hDCSrc
: NULL
;
591 ahDC
[2] = UsesMask
? hDCMask
: NULL
;
592 if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
594 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest
, hDCSrc
);
595 EngSetLastError(ERROR_INVALID_HANDLE
);
602 if (DCDest
->dctype
== DC_TYPE_INFO
)
604 if(DCSrc
) GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
605 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
606 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
607 /* Yes, Windows really returns TRUE in this case */
613 if (DCSrc
->dctype
== DC_TYPE_INFO
)
615 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
616 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
617 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
618 /* Yes, Windows really returns TRUE in this case */
623 pdcattr
= DCDest
->pdcattr
;
625 DestRect
.left
= XOriginDest
;
626 DestRect
.top
= YOriginDest
;
627 DestRect
.right
= XOriginDest
+WidthDest
;
628 DestRect
.bottom
= YOriginDest
+HeightDest
;
629 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
631 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
632 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
633 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
634 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
636 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
638 IntUpdateBoundsRect(DCDest
, &DestRect
);
641 SourceRect
.left
= XOriginSrc
;
642 SourceRect
.top
= YOriginSrc
;
643 SourceRect
.right
= XOriginSrc
+WidthSrc
;
644 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
648 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
650 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
651 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
652 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
653 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
659 /* Only prepare Source and Dest, hdcMask represents a DIB */
660 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
662 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
663 DC_vUpdateFillBrush(DCDest
);
665 /* Determine surfaces to be used in the bitblt */
666 BitmapDest
= DCDest
->dclevel
.pSurface
;
667 if (BitmapDest
== NULL
)
671 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
672 if (BitmapSrc
== NULL
)
675 /* Create the XLATEOBJ. */
676 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
677 XlateObj
= &exlo
.xlo
;
680 /* Offset the brush */
681 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
682 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
684 /* Make mask surface for source surface */
685 if (BitmapSrc
&& DCMask
)
687 BitmapMask
= DCMask
->dclevel
.pSurface
;
689 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
690 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
692 WARN("%dx%d mask is smaller than %dx%d bitmap\n",
693 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
694 WidthSrc
, HeightSrc
);
695 EXLATEOBJ_vCleanup(&exlo
);
698 /* Create mask offset point */
699 MaskPoint
.x
= XOriginMask
;
700 MaskPoint
.y
= YOriginMask
;
701 IntLPtoDP(DCMask
, &MaskPoint
, 1);
702 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
703 MaskPoint
.y
+= DCMask
->ptlDCOrig
.y
;
706 /* Perform the bitblt operation */
707 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
708 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
709 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
710 (CLIPOBJ
*)&DCDest
->co
,
715 BitmapMask
? &MaskPoint
: NULL
,
716 &DCDest
->eboFill
.BrushObject
,
721 EXLATEOBJ_vCleanup(&exlo
);
725 DC_vFinishBlit(DCDest
, DCSrc
);
753 IN DWORD dwBackColor
)
755 dwRop3
= dwRop3
& ~(NOMIRRORBITMAP
|CAPTUREBLT
);
757 return GreStretchBltMask(
768 MAKEROP4(dwRop3
& 0xFF0000, dwRop3
),
793 pbrush
= pebo
->pbrush
;
796 if (pbrush
->flAttrs
& BR_IS_NULL
)
803 DestRect
.left
= XLeft
;
804 DestRect
.right
= XLeft
+ Width
;
808 DestRect
.left
= XLeft
+ Width
+ 1;
809 DestRect
.right
= XLeft
+ 1;
814 DestRect
.top
= YLeft
;
815 DestRect
.bottom
= YLeft
+ Height
;
819 DestRect
.top
= YLeft
+ Height
+ 1;
820 DestRect
.bottom
= YLeft
+ 1;
823 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
825 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
826 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
827 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
828 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
830 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
832 IntUpdateBoundsRect(pdc
, &DestRect
);
836 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
+ XLeft
;
837 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
+ YLeft
;
839 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
840 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
843 DC_vPrepareDCsForBlit(pdc
, &DestRect
, NULL
, NULL
);
845 psurf
= pdc
->dclevel
.pSurface
;
847 ret
= IntEngBitBlt(&psurf
->SurfObj
,
857 WIN32_ROP3_TO_ENG_ROP4(dwRop3
));
859 DC_vFinishBlit(pdc
, NULL
);
877 pdc
= DC_LockDc(hDC
);
880 EngSetLastError(ERROR_INVALID_HANDLE
);
884 if (pdc
->dctype
== DC_TYPE_INFO
)
887 /* Yes, Windows really returns TRUE in this case */
891 for (i
= 0; i
< cRects
; i
++)
893 pbrush
= BRUSH_ShareLockBrush(pRects
->hBrush
);
895 /* Check if we could lock the brush */
898 /* Initialize a brush object */
899 EBRUSHOBJ_vInitFromDC(&eboFill
, pbrush
, pdc
);
910 /* Cleanup the brush object and unlock the brush */
911 EBRUSHOBJ_vCleanup(&eboFill
);
912 BRUSH_ShareUnlockBrush(pbrush
);
935 /* Convert the ROP3 to a ROP4 */
936 dwRop
= MAKEROP4(dwRop
& 0xFF0000, dwRop
);
938 /* Check if the rop uses a source */
939 if (WIN32_ROP4_USES_SOURCE(dwRop
))
941 /* This is not possible */
946 pdc
= DC_LockDc(hdcDest
);
949 EngSetLastError(ERROR_INVALID_HANDLE
);
953 /* Check if the DC has no surface (empty mem or info DC) */
954 if (pdc
->dclevel
.pSurface
== NULL
)
956 /* Nothing to do, Windows returns TRUE! */
961 /* Update the fill brush, if necessary */
962 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
963 DC_vUpdateFillBrush(pdc
);
965 /* Call the internal function */
966 bResult
= IntPatBlt(pdc
, x
, y
, cx
, cy
, dwRop
, &pdc
->eboFill
);
968 /* Unlock the DC and return the result */
978 IN PPOLYPATBLT pRects
,
983 NTSTATUS Status
= STATUS_SUCCESS
;
988 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, GDITAG_PLGBLT_DATA
);
991 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
997 cRects
* sizeof(PATRECT
),
1001 cRects
* sizeof(PATRECT
));
1003 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1005 Status
= _SEH2_GetExceptionCode();
1009 if (!NT_SUCCESS(Status
))
1011 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1012 SetLastNtError(Status
);
1017 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
1020 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1030 _Inout_ PREGION prgnDest
,
1031 _In_ PREGION prgnSrc
)
1033 if (IntGdiCombineRgn(prgnDest
, prgnSrc
, NULL
, RGN_COPY
) == ERROR
)
1036 return REGION_bXformRgn(prgnDest
, DC_pmxWorldToDevice(pdc
));
1044 _In_opt_ BRUSHOBJ
*pbo
,
1045 _In_opt_ POINTL
*pptlBrush
,
1051 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1053 /* Check if we have a surface */
1054 if (pdc
->dclevel
.pSurface
== NULL
)
1059 /* Create an empty clip region */
1060 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1061 if (prgnClip
== NULL
)
1066 /* Transform given region into device coordinates */
1067 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1069 REGION_Delete(prgnClip
);
1073 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1075 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1077 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1079 /* Now account for the DC-origin */
1080 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1082 REGION_Delete(prgnClip
);
1086 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1089 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1090 IntUpdateBoundsRect(pdc
, &rcrgn
);
1093 /* Prepare the DC */
1094 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1096 /* Initialize a clip object */
1097 IntEngInitClipObj(&xcoClip
);
1098 IntEngUpdateClipRegion(&xcoClip
,
1099 prgnClip
->rdh
.nCount
,
1101 &prgnClip
->rdh
.rcBound
);
1103 /* Call the Eng or Drv function */
1104 bResult
= IntEngBitBlt(&pdc
->dclevel
.pSurface
->SurfObj
,
1107 (CLIPOBJ
*)&xcoClip
,
1109 &prgnClip
->rdh
.rcBound
,
1117 DC_vFinishBlit(pdc
, NULL
);
1118 REGION_Delete(prgnClip
);
1119 IntEngFreeClipResources(&xcoClip
);
1121 /* Return the result */
1130 _In_opt_ PBRUSH pbrFill
)
1139 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1141 if (pdc
->dclevel
.pSurface
== NULL
)
1146 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1147 if (prgnClip
== NULL
)
1152 /* Transform region into device coordinates */
1153 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1155 REGION_Delete(prgnClip
);
1159 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1161 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1163 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1165 /* Now account for the DC-origin */
1166 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1168 REGION_Delete(prgnClip
);
1172 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1175 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1176 IntUpdateBoundsRect(pdc
, &rcrgn
);
1179 IntEngInitClipObj(&xcoClip
);
1180 IntEngUpdateClipRegion(&xcoClip
,
1181 prgnClip
->rdh
.nCount
,
1183 &prgnClip
->rdh
.rcBound
);
1185 /* Get the FG rop and create a MIX based on the BK mode */
1186 rop2Fg
= FIXUP_ROP2(pdc
->pdcattr
->jROP2
);
1187 mix
= rop2Fg
| (pdc
->pdcattr
->jBkMode
== OPAQUE
? rop2Fg
: R2_NOP
) << 8;
1189 /* Prepare DC for blit */
1190 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1192 /* Check if we have a fill brush */
1193 if (pbrFill
!= NULL
)
1195 /* Initialize the brush object */
1196 /// \todo Check parameters
1197 EBRUSHOBJ_vInit(&eboFill
, pbrFill
, pdc
->dclevel
.pSurface
, 0x00FFFFFF, 0, NULL
);
1198 pbo
= &eboFill
.BrushObject
;
1202 /* Update the fill brush if needed */
1203 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1204 DC_vUpdateFillBrush(pdc
);
1206 /* Use the DC brush object */
1207 pbo
= &pdc
->eboFill
.BrushObject
;
1210 /* Call the internal function */
1211 bRet
= IntEngPaint(&pdc
->dclevel
.pSurface
->SurfObj
,
1212 (CLIPOBJ
*)&xcoClip
,
1214 &pdc
->pdcattr
->ptlBrushOrigin
,
1217 DC_vFinishBlit(pdc
, NULL
);
1218 REGION_Delete(prgnClip
);
1219 IntEngFreeClipResources(&xcoClip
);
1231 return IntGdiFillRgn(pdc
, prgn
, NULL
);
1247 pdc
= DC_LockDc(hdc
);
1250 ERR("Failed to lock hdc %p\n", hdc
);
1254 /* Check if the DC has no surface (empty mem or info DC) */
1255 if (pdc
->dclevel
.pSurface
== NULL
)
1261 /* Lock the region */
1262 prgn
= REGION_LockRgn(hrgn
);
1265 ERR("Failed to lock hrgn %p\n", hrgn
);
1270 /* Lock the brush */
1271 pbrFill
= BRUSH_ShareLockBrush(hbrush
);
1272 if (pbrFill
== NULL
)
1274 ERR("Failed to lock hbrush %p\n", hbrush
);
1275 REGION_UnlockRgn(prgn
);
1280 /* Call the internal function */
1281 bResult
= IntGdiFillRgn(pdc
, prgn
, pbrFill
);
1284 BRUSH_ShareUnlockBrush(pbrFill
);
1285 REGION_UnlockRgn(prgn
);
1303 hrgnFrame
= GreCreateFrameRgn(hrgn
, xWidth
, yHeight
);
1304 if (hrgnFrame
== NULL
)
1309 bResult
= NtGdiFillRgn(hdc
, hrgnFrame
, hbrush
);
1311 GreDeleteObject(hrgnFrame
);
1326 pdc
= DC_LockDc(hdc
);
1329 EngSetLastError(ERROR_INVALID_HANDLE
);
1333 /* Check if the DC has no surface (empty mem or info DC) */
1334 if (pdc
->dclevel
.pSurface
== NULL
)
1336 /* Nothing to do, Windows returns TRUE! */
1341 /* Lock the region */
1342 prgn
= REGION_LockRgn(hrgn
);
1349 /* Call the internal function */
1350 bResult
= IntGdiBitBltRgn(pdc
,
1356 /* Unlock the region and DC and return the result */
1357 REGION_UnlockRgn(prgn
);
1368 _In_ COLORREF crColor
)
1371 ULONG iOldColor
, iSolidColor
;
1378 pdc
= DC_LockDc(hdc
);
1381 EngSetLastError(ERROR_INVALID_HANDLE
);
1385 /* Check if the DC has no surface (empty mem or info DC) */
1386 if (pdc
->dclevel
.pSurface
== NULL
)
1393 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1397 RECTL_vSetRect(&rcDst
, x
, y
, x
+1, y
+1);
1399 IntLPtoDP(pdc
, (LPPOINT
)&rcDst
, 2);
1401 rcDst
.left
+= pdc
->ptlDCOrig
.x
;
1402 rcDst
.top
+= pdc
->ptlDCOrig
.y
;
1403 rcDst
.right
+= pdc
->ptlDCOrig
.x
;
1404 rcDst
.bottom
+= pdc
->ptlDCOrig
.y
;
1406 IntUpdateBoundsRect(pdc
, &rcDst
);
1409 /* Translate the color to the target format */
1410 iSolidColor
= TranslateCOLORREF(pdc
, crColor
);
1412 /* Use the DC's text brush, which is always a solid brush */
1413 pebo
= &pdc
->eboText
;
1415 /* Save the old solid color and set the one for the pixel */
1416 iOldColor
= EBRUSHOBJ_iSetSolidColor(pebo
, iSolidColor
);
1418 /* Save dirty flags and reset dirty text brush flag */
1419 ulDirty
= pdc
->pdcattr
->ulDirty_
;
1420 pdc
->pdcattr
->ulDirty_
&= ~DIRTY_TEXT
;
1422 /* Call the internal function */
1423 bResult
= IntPatBlt(pdc
, x
, y
, 1, 1, PATCOPY
, pebo
);
1425 /* Restore old text brush color and dirty flags */
1426 EBRUSHOBJ_iSetSolidColor(pebo
, iOldColor
);
1427 pdc
->pdcattr
->ulDirty_
= ulDirty
;
1429 /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked!
1430 /* Initialize an XLATEOBJ from the target surface to RGB */
1431 EXLATEOBJ_vInitialize(&exlo
,
1432 pdc
->dclevel
.pSurface
->ppal
,
1435 pdc
->pdcattr
->crBackgroundClr
,
1436 pdc
->pdcattr
->crForegroundClr
);
1438 /* Translate the color back to RGB */
1439 crColor
= XLATEOBJ_iXlate(&exlo
.xlo
, iSolidColor
);
1441 /* Cleanup and return the target format color */
1442 EXLATEOBJ_vCleanup(&exlo
);
1447 /* Return the new RGB color or -1 on failure */
1448 return bResult
? crColor
: -1;
1459 ULONG ulRGBColor
= CLR_INVALID
;
1462 PSURFACE psurfSrc
, psurfDest
;
1465 pdc
= DC_LockDc(hdc
);
1468 EngSetLastError(ERROR_INVALID_HANDLE
);
1472 /* Check if the DC has no surface (empty mem or info DC) */
1473 if (pdc
->dclevel
.pSurface
== NULL
)
1479 /* Get the logical coordinates */
1483 /* Translate coordinates to device coordinates */
1484 IntLPtoDP(pdc
, &ptlSrc
, 1);
1485 ptlSrc
.x
+= pdc
->ptlDCOrig
.x
;
1486 ptlSrc
.y
+= pdc
->ptlDCOrig
.y
;
1490 rcDest
.right
= x
+ 1;
1491 rcDest
.bottom
= y
+ 1;
1493 /* Prepare DC for blit */
1494 DC_vPrepareDCsForBlit(pdc
, &rcDest
, NULL
, NULL
);
1496 /* Check if the pixel is outside the surface */
1497 psurfSrc
= pdc
->dclevel
.pSurface
;
1498 if ((ptlSrc
.x
>= psurfSrc
->SurfObj
.sizlBitmap
.cx
) ||
1499 (ptlSrc
.y
>= psurfSrc
->SurfObj
.sizlBitmap
.cy
) ||
1507 /* Allocate a surface */
1508 psurfDest
= SURFACE_AllocSurface(STYPE_BITMAP
,
1518 RECTL rclDest
= {0, 0, 1, 1};
1521 /* Translate from the source palette to RGB color */
1522 EXLATEOBJ_vInitialize(&exlo
,
1526 RGB(0xff,0xff,0xff),
1529 /* Call the copy bits function */
1530 EngCopyBits(&psurfDest
->SurfObj
,
1537 /* Cleanup the XLATEOBJ */
1538 EXLATEOBJ_vCleanup(&exlo
);
1540 /* Delete the surface */
1541 GDIOBJ_vDeleteObject(&psurfDest
->BaseObject
);
1547 DC_vFinishBlit(pdc
, NULL
);
1550 /* Return the new RGB color or -1 on failure */