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 */
1129 _In_opt_ PBRUSH pbrFill
)
1138 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1140 if (pdc
->dclevel
.pSurface
== NULL
)
1145 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1146 if (prgnClip
== NULL
)
1151 /* Transform region into device coordinates */
1152 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1154 REGION_Delete(prgnClip
);
1158 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1160 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1162 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1164 /* Now account for the DC-origin */
1165 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1167 REGION_Delete(prgnClip
);
1171 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1174 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1175 IntUpdateBoundsRect(pdc
, &rcrgn
);
1178 IntEngInitClipObj(&xcoClip
);
1179 IntEngUpdateClipRegion(&xcoClip
,
1180 prgnClip
->rdh
.nCount
,
1182 &prgnClip
->rdh
.rcBound
);
1184 /* Get the FG rop and create a MIX based on the BK mode */
1185 rop2Fg
= FIXUP_ROP2(pdc
->pdcattr
->jROP2
);
1186 mix
= rop2Fg
| (pdc
->pdcattr
->jBkMode
== OPAQUE
? rop2Fg
: R2_NOP
) << 8;
1188 /* Prepare DC for blit */
1189 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1191 /* Check if we have a fill brush */
1192 if (pbrFill
!= NULL
)
1194 /* Initialize the brush object */
1195 /// \todo Check parameters
1196 EBRUSHOBJ_vInit(&eboFill
, pbrFill
, pdc
->dclevel
.pSurface
, 0x00FFFFFF, 0, NULL
);
1197 pbo
= &eboFill
.BrushObject
;
1201 /* Update the fill brush if needed */
1202 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1203 DC_vUpdateFillBrush(pdc
);
1205 /* Use the DC brush object */
1206 pbo
= &pdc
->eboFill
.BrushObject
;
1209 /* Call the internal function */
1210 bRet
= IntEngPaint(&pdc
->dclevel
.pSurface
->SurfObj
,
1211 (CLIPOBJ
*)&xcoClip
,
1213 &pdc
->pdcattr
->ptlBrushOrigin
,
1216 DC_vFinishBlit(pdc
, NULL
);
1217 REGION_Delete(prgnClip
);
1218 IntEngFreeClipResources(&xcoClip
);
1230 return IntGdiFillRgn(pdc
, prgn
, NULL
);
1246 pdc
= DC_LockDc(hdc
);
1249 ERR("Failed to lock hdc %p\n", hdc
);
1253 /* Check if the DC has no surface (empty mem or info DC) */
1254 if (pdc
->dclevel
.pSurface
== NULL
)
1260 /* Lock the region */
1261 prgn
= REGION_LockRgn(hrgn
);
1264 ERR("Failed to lock hrgn %p\n", hrgn
);
1269 /* Lock the brush */
1270 pbrFill
= BRUSH_ShareLockBrush(hbrush
);
1271 if (pbrFill
== NULL
)
1273 ERR("Failed to lock hbrush %p\n", hbrush
);
1274 REGION_UnlockRgn(prgn
);
1279 /* Call the internal function */
1280 bResult
= IntGdiFillRgn(pdc
, prgn
, pbrFill
);
1283 BRUSH_ShareUnlockBrush(pbrFill
);
1284 REGION_UnlockRgn(prgn
);
1302 hrgnFrame
= GreCreateFrameRgn(hrgn
, xWidth
, yHeight
);
1303 if (hrgnFrame
== NULL
)
1308 bResult
= NtGdiFillRgn(hdc
, hrgnFrame
, hbrush
);
1310 GreDeleteObject(hrgnFrame
);
1325 pdc
= DC_LockDc(hdc
);
1328 EngSetLastError(ERROR_INVALID_HANDLE
);
1332 /* Check if the DC has no surface (empty mem or info DC) */
1333 if (pdc
->dclevel
.pSurface
== NULL
)
1335 /* Nothing to do, Windows returns TRUE! */
1340 /* Lock the region */
1341 prgn
= REGION_LockRgn(hrgn
);
1348 /* Call the internal function */
1349 bResult
= IntGdiBitBltRgn(pdc
,
1355 /* Unlock the region and DC and return the result */
1356 REGION_UnlockRgn(prgn
);
1367 _In_ COLORREF crColor
)
1370 ULONG iOldColor
, iSolidColor
;
1377 pdc
= DC_LockDc(hdc
);
1380 EngSetLastError(ERROR_INVALID_HANDLE
);
1384 /* Check if the DC has no surface (empty mem or info DC) */
1385 if (pdc
->dclevel
.pSurface
== NULL
)
1392 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1396 RECTL_vSetRect(&rcDst
, x
, y
, x
+1, y
+1);
1398 IntLPtoDP(pdc
, (LPPOINT
)&rcDst
, 2);
1400 rcDst
.left
+= pdc
->ptlDCOrig
.x
;
1401 rcDst
.top
+= pdc
->ptlDCOrig
.y
;
1402 rcDst
.right
+= pdc
->ptlDCOrig
.x
;
1403 rcDst
.bottom
+= pdc
->ptlDCOrig
.y
;
1405 IntUpdateBoundsRect(pdc
, &rcDst
);
1408 /* Translate the color to the target format */
1409 iSolidColor
= TranslateCOLORREF(pdc
, crColor
);
1411 /* Use the DC's text brush, which is always a solid brush */
1412 pebo
= &pdc
->eboText
;
1414 /* Save the old solid color and set the one for the pixel */
1415 iOldColor
= EBRUSHOBJ_iSetSolidColor(pebo
, iSolidColor
);
1417 /* Save dirty flags and reset dirty text brush flag */
1418 ulDirty
= pdc
->pdcattr
->ulDirty_
;
1419 pdc
->pdcattr
->ulDirty_
&= ~DIRTY_TEXT
;
1421 /* Call the internal function */
1422 bResult
= IntPatBlt(pdc
, x
, y
, 1, 1, PATCOPY
, pebo
);
1424 /* Restore old text brush color and dirty flags */
1425 EBRUSHOBJ_iSetSolidColor(pebo
, iOldColor
);
1426 pdc
->pdcattr
->ulDirty_
= ulDirty
;
1428 /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked!
1429 /* Initialize an XLATEOBJ from the target surface to RGB */
1430 EXLATEOBJ_vInitialize(&exlo
,
1431 pdc
->dclevel
.pSurface
->ppal
,
1434 pdc
->pdcattr
->crBackgroundClr
,
1435 pdc
->pdcattr
->crForegroundClr
);
1437 /* Translate the color back to RGB */
1438 crColor
= XLATEOBJ_iXlate(&exlo
.xlo
, iSolidColor
);
1440 /* Cleanup and return the target format color */
1441 EXLATEOBJ_vCleanup(&exlo
);
1446 /* Return the new RGB color or -1 on failure */
1447 return bResult
? crColor
: -1;
1458 ULONG ulRGBColor
= CLR_INVALID
;
1461 PSURFACE psurfSrc
, psurfDest
;
1464 pdc
= DC_LockDc(hdc
);
1467 EngSetLastError(ERROR_INVALID_HANDLE
);
1471 /* Check if the DC has no surface (empty mem or info DC) */
1472 if (pdc
->dclevel
.pSurface
== NULL
)
1478 /* Get the logical coordinates */
1482 /* Translate coordinates to device coordinates */
1483 IntLPtoDP(pdc
, &ptlSrc
, 1);
1484 ptlSrc
.x
+= pdc
->ptlDCOrig
.x
;
1485 ptlSrc
.y
+= pdc
->ptlDCOrig
.y
;
1489 rcDest
.right
= x
+ 1;
1490 rcDest
.bottom
= y
+ 1;
1492 /* Prepare DC for blit */
1493 DC_vPrepareDCsForBlit(pdc
, &rcDest
, NULL
, NULL
);
1495 /* Check if the pixel is outside the surface */
1496 psurfSrc
= pdc
->dclevel
.pSurface
;
1497 if ((ptlSrc
.x
>= psurfSrc
->SurfObj
.sizlBitmap
.cx
) ||
1498 (ptlSrc
.y
>= psurfSrc
->SurfObj
.sizlBitmap
.cy
) ||
1506 /* Allocate a surface */
1507 psurfDest
= SURFACE_AllocSurface(STYPE_BITMAP
,
1517 RECTL rclDest
= {0, 0, 1, 1};
1520 /* Translate from the source palette to RGB color */
1521 EXLATEOBJ_vInitialize(&exlo
,
1525 RGB(0xff,0xff,0xff),
1528 /* Call the copy bits function */
1529 EngCopyBits(&psurfDest
->SurfObj
,
1536 /* Cleanup the XLATEOBJ */
1537 EXLATEOBJ_vCleanup(&exlo
);
1539 /* Delete the surface */
1540 GDIOBJ_vDeleteObject(&psurfDest
->BaseObject
);
1546 DC_vFinishBlit(pdc
, NULL
);
1549 /* Return the new RGB color or -1 on failure */