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
,
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 &DCDest
->co
.ClipObj
, &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 NtGdiAlphaBlend\n", hdcDest
, hdcSrc
);
386 EngSetLastError(ERROR_INVALID_HANDLE
);
395 if(DCSrc
) DC_UnlockDc(DCSrc
);
396 WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\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
;
489 /* Perform the bitblt operation */
490 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
,
491 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
492 psurfMask
? &psurfMask
->SurfObj
: NULL
,
498 &DCDest
->eboFill
.BrushObject
,
499 &DCDest
->dclevel
.pbrFill
->ptOrigin
,
503 EXLATEOBJ_vCleanup(&exlo
);
505 DC_vFinishBlit(DCDest
, DCSrc
);
511 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
529 IN DWORD crBackColor
)
531 FIXME("NtGdiPlgBlt: unimplemented.\n");
549 IN DWORD dwBackColor
,
560 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
561 SURFACE
*BitmapMask
= NULL
;
567 XLATEOBJ
*XlateObj
= NULL
;
573 rop4
= WIN32_ROP4_TO_ENG_ROP4(dwRop4
);
575 UsesSource
= ROP4_USES_SOURCE(rop4
);
576 UsesMask
= ROP4_USES_MASK(rop4
);
578 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
580 EngSetLastError(ERROR_INVALID_PARAMETER
);
584 if (!hDCDest
|| (UsesSource
&& !hDCSrc
) || (UsesMask
&& !hDCMask
))
586 EngSetLastError(ERROR_INVALID_PARAMETER
);
591 ahDC
[1] = UsesSource
? hDCSrc
: NULL
;
592 ahDC
[2] = UsesMask
? hDCMask
: NULL
;
593 if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
595 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest
, hDCSrc
);
596 EngSetLastError(ERROR_INVALID_HANDLE
);
603 if (DCDest
->dctype
== DC_TYPE_INFO
)
605 if(DCSrc
) GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
606 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
607 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
608 /* Yes, Windows really returns TRUE in this case */
614 if (DCSrc
->dctype
== DC_TYPE_INFO
)
616 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
617 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
618 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
619 /* Yes, Windows really returns TRUE in this case */
624 pdcattr
= DCDest
->pdcattr
;
626 DestRect
.left
= XOriginDest
;
627 DestRect
.top
= YOriginDest
;
628 DestRect
.right
= XOriginDest
+WidthDest
;
629 DestRect
.bottom
= YOriginDest
+HeightDest
;
630 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
632 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
633 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
634 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
635 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
637 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
639 IntUpdateBoundsRect(DCDest
, &DestRect
);
642 SourceRect
.left
= XOriginSrc
;
643 SourceRect
.top
= YOriginSrc
;
644 SourceRect
.right
= XOriginSrc
+WidthSrc
;
645 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
649 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
651 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
652 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
653 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
654 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
660 /* Only prepare Source and Dest, hdcMask represents a DIB */
661 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
663 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
664 DC_vUpdateFillBrush(DCDest
);
666 /* Determine surfaces to be used in the bitblt */
667 BitmapDest
= DCDest
->dclevel
.pSurface
;
668 if (BitmapDest
== NULL
)
672 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
673 if (BitmapSrc
== NULL
)
676 /* Create the XLATEOBJ. */
677 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
678 XlateObj
= &exlo
.xlo
;
681 /* Offset the brush */
682 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
683 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
685 /* Make mask surface for source surface */
686 if (BitmapSrc
&& DCMask
)
688 BitmapMask
= DCMask
->dclevel
.pSurface
;
690 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
691 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
693 WARN("%dx%d mask is smaller than %dx%d bitmap\n",
694 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
695 WidthSrc
, HeightSrc
);
696 EXLATEOBJ_vCleanup(&exlo
);
699 /* Create mask offset point */
700 MaskPoint
.x
= XOriginMask
;
701 MaskPoint
.y
= YOriginMask
;
702 IntLPtoDP(DCMask
, &MaskPoint
, 1);
703 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
704 MaskPoint
.y
+= DCMask
->ptlDCOrig
.y
;
707 /* Perform the bitblt operation */
708 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
709 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
710 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
716 BitmapMask
? &MaskPoint
: NULL
,
717 &DCDest
->eboFill
.BrushObject
,
722 EXLATEOBJ_vCleanup(&exlo
);
726 DC_vFinishBlit(DCDest
, DCSrc
);
754 IN DWORD dwBackColor
)
756 dwRop3
= dwRop3
& ~(NOMIRRORBITMAP
|CAPTUREBLT
);
758 return GreStretchBltMask(
769 MAKEROP4(dwRop3
& 0xFF0000, dwRop3
),
794 pbrush
= pebo
->pbrush
;
797 if (pbrush
->flAttrs
& BR_IS_NULL
)
804 DestRect
.left
= XLeft
;
805 DestRect
.right
= XLeft
+ Width
;
809 DestRect
.left
= XLeft
+ Width
+ 1;
810 DestRect
.right
= XLeft
+ 1;
815 DestRect
.top
= YLeft
;
816 DestRect
.bottom
= YLeft
+ Height
;
820 DestRect
.top
= YLeft
+ Height
+ 1;
821 DestRect
.bottom
= YLeft
+ 1;
824 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
826 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
827 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
828 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
829 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
831 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
833 IntUpdateBoundsRect(pdc
, &DestRect
);
837 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
+ XLeft
;
838 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
+ YLeft
;
840 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
841 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
844 DC_vPrepareDCsForBlit(pdc
, &DestRect
, NULL
, NULL
);
846 psurf
= pdc
->dclevel
.pSurface
;
848 ret
= IntEngBitBlt(&psurf
->SurfObj
,
858 WIN32_ROP3_TO_ENG_ROP4(dwRop3
));
860 DC_vFinishBlit(pdc
, NULL
);
878 pdc
= DC_LockDc(hDC
);
881 EngSetLastError(ERROR_INVALID_HANDLE
);
885 if (pdc
->dctype
== DC_TYPE_INFO
)
888 /* Yes, Windows really returns TRUE in this case */
892 for (i
= 0; i
< cRects
; i
++)
894 pbrush
= BRUSH_ShareLockBrush(pRects
->hBrush
);
896 /* Check if we could lock the brush */
899 /* Initialize a brush object */
900 EBRUSHOBJ_vInitFromDC(&eboFill
, pbrush
, pdc
);
911 /* Cleanup the brush object and unlock the brush */
912 EBRUSHOBJ_vCleanup(&eboFill
);
913 BRUSH_ShareUnlockBrush(pbrush
);
936 /* Convert the ROP3 to a ROP4 */
937 dwRop
= MAKEROP4(dwRop
& 0xFF0000, dwRop
);
939 /* Check if the rop uses a source */
940 if (WIN32_ROP4_USES_SOURCE(dwRop
))
942 /* This is not possible */
947 pdc
= DC_LockDc(hdcDest
);
950 EngSetLastError(ERROR_INVALID_HANDLE
);
954 /* Check if the DC has no surface (empty mem or info DC) */
955 if (pdc
->dclevel
.pSurface
== NULL
)
957 /* Nothing to do, Windows returns TRUE! */
962 /* Update the fill brush, if necessary */
963 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
964 DC_vUpdateFillBrush(pdc
);
966 /* Call the internal function */
967 bResult
= IntPatBlt(pdc
, x
, y
, cx
, cy
, dwRop
, &pdc
->eboFill
);
969 /* Unlock the DC and return the result */
979 IN PPOLYPATBLT pRects
,
984 NTSTATUS Status
= STATUS_SUCCESS
;
989 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, GDITAG_PLGBLT_DATA
);
992 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
998 cRects
* sizeof(PATRECT
),
1002 cRects
* sizeof(PATRECT
));
1004 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1006 Status
= _SEH2_GetExceptionCode();
1010 if (!NT_SUCCESS(Status
))
1012 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1013 SetLastNtError(Status
);
1018 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
1021 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1031 _Inout_ PREGION prgnDest
,
1032 _In_ PREGION prgnSrc
)
1034 if (IntGdiCombineRgn(prgnDest
, prgnSrc
, NULL
, RGN_COPY
) == ERROR
)
1037 return REGION_bXformRgn(prgnDest
, DC_pmxWorldToDevice(pdc
));
1045 _In_opt_ BRUSHOBJ
*pbo
,
1046 _In_opt_ POINTL
*pptlBrush
,
1052 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1054 /* Check if we have a surface */
1055 if (pdc
->dclevel
.pSurface
== NULL
)
1060 /* Create an empty clip region */
1061 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1062 if (prgnClip
== NULL
)
1067 /* Transform given region into device coordinates */
1068 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1070 REGION_Delete(prgnClip
);
1074 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1076 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1078 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1080 /* Now account for the DC-origin */
1081 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1083 REGION_Delete(prgnClip
);
1087 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1090 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1091 IntUpdateBoundsRect(pdc
, &rcrgn
);
1094 /* Prepare the DC */
1095 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1097 /* Initialize a clip object */
1098 IntEngInitClipObj(&xcoClip
);
1099 IntEngUpdateClipRegion(&xcoClip
,
1100 prgnClip
->rdh
.nCount
,
1102 &prgnClip
->rdh
.rcBound
);
1104 /* Call the Eng or Drv function */
1105 bResult
= IntEngBitBlt(&pdc
->dclevel
.pSurface
->SurfObj
,
1110 &prgnClip
->rdh
.rcBound
,
1118 DC_vFinishBlit(pdc
, NULL
);
1119 REGION_Delete(prgnClip
);
1120 IntEngFreeClipResources(&xcoClip
);
1122 /* Return the result */
1131 _In_opt_ PBRUSH pbrFill
)
1140 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1142 if (pdc
->dclevel
.pSurface
== NULL
)
1147 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1148 if (prgnClip
== NULL
)
1153 /* Transform region into device coordinates */
1154 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1156 REGION_Delete(prgnClip
);
1160 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1162 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1164 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1166 /* Now account for the DC-origin */
1167 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1169 REGION_Delete(prgnClip
);
1173 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1176 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1177 IntUpdateBoundsRect(pdc
, &rcrgn
);
1180 IntEngInitClipObj(&xcoClip
);
1181 IntEngUpdateClipRegion(&xcoClip
,
1182 prgnClip
->rdh
.nCount
,
1184 &prgnClip
->rdh
.rcBound
);
1186 /* Get the FG rop and create a MIX based on the BK mode */
1187 rop2Fg
= FIXUP_ROP2(pdc
->pdcattr
->jROP2
);
1188 mix
= rop2Fg
| (pdc
->pdcattr
->jBkMode
== OPAQUE
? rop2Fg
: R2_NOP
) << 8;
1190 /* Prepare DC for blit */
1191 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1193 /* Check if we have a fill brush */
1194 if (pbrFill
!= NULL
)
1196 /* Initialize the brush object */
1197 /// \todo Check parameters
1198 EBRUSHOBJ_vInit(&eboFill
, pbrFill
, pdc
->dclevel
.pSurface
, 0x00FFFFFF, 0, NULL
);
1199 pbo
= &eboFill
.BrushObject
;
1203 /* Update the fill brush if needed */
1204 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1205 DC_vUpdateFillBrush(pdc
);
1207 /* Use the DC brush object */
1208 pbo
= &pdc
->eboFill
.BrushObject
;
1211 /* Call the internal function */
1212 bRet
= IntEngPaint(&pdc
->dclevel
.pSurface
->SurfObj
,
1215 &pdc
->pdcattr
->ptlBrushOrigin
,
1218 DC_vFinishBlit(pdc
, NULL
);
1219 REGION_Delete(prgnClip
);
1220 IntEngFreeClipResources(&xcoClip
);
1232 return IntGdiFillRgn(pdc
, prgn
, NULL
);
1248 pdc
= DC_LockDc(hdc
);
1251 ERR("Failed to lock hdc %p\n", hdc
);
1255 /* Check if the DC has no surface (empty mem or info DC) */
1256 if (pdc
->dclevel
.pSurface
== NULL
)
1262 /* Lock the region */
1263 prgn
= REGION_LockRgn(hrgn
);
1266 ERR("Failed to lock hrgn %p\n", hrgn
);
1271 /* Lock the brush */
1272 pbrFill
= BRUSH_ShareLockBrush(hbrush
);
1273 if (pbrFill
== NULL
)
1275 ERR("Failed to lock hbrush %p\n", hbrush
);
1276 REGION_UnlockRgn(prgn
);
1281 /* Call the internal function */
1282 bResult
= IntGdiFillRgn(pdc
, prgn
, pbrFill
);
1285 BRUSH_ShareUnlockBrush(pbrFill
);
1286 REGION_UnlockRgn(prgn
);
1304 hrgnFrame
= GreCreateFrameRgn(hrgn
, xWidth
, yHeight
);
1305 if (hrgnFrame
== NULL
)
1310 bResult
= NtGdiFillRgn(hdc
, hrgnFrame
, hbrush
);
1312 GreDeleteObject(hrgnFrame
);
1327 pdc
= DC_LockDc(hdc
);
1330 EngSetLastError(ERROR_INVALID_HANDLE
);
1334 /* Check if the DC has no surface (empty mem or info DC) */
1335 if (pdc
->dclevel
.pSurface
== NULL
)
1337 /* Nothing to do, Windows returns TRUE! */
1342 /* Lock the region */
1343 prgn
= REGION_LockRgn(hrgn
);
1350 /* Call the internal function */
1351 bResult
= IntGdiBitBltRgn(pdc
,
1357 /* Unlock the region and DC and return the result */
1358 REGION_UnlockRgn(prgn
);
1369 _In_ COLORREF crColor
)
1372 ULONG iOldColor
, iSolidColor
;
1379 pdc
= DC_LockDc(hdc
);
1382 EngSetLastError(ERROR_INVALID_HANDLE
);
1386 /* Check if the DC has no surface (empty mem or info DC) */
1387 if (pdc
->dclevel
.pSurface
== NULL
)
1394 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1398 RECTL_vSetRect(&rcDst
, x
, y
, x
+1, y
+1);
1400 IntLPtoDP(pdc
, (LPPOINT
)&rcDst
, 2);
1402 rcDst
.left
+= pdc
->ptlDCOrig
.x
;
1403 rcDst
.top
+= pdc
->ptlDCOrig
.y
;
1404 rcDst
.right
+= pdc
->ptlDCOrig
.x
;
1405 rcDst
.bottom
+= pdc
->ptlDCOrig
.y
;
1407 IntUpdateBoundsRect(pdc
, &rcDst
);
1410 /* Translate the color to the target format */
1411 iSolidColor
= TranslateCOLORREF(pdc
, crColor
);
1413 /* Use the DC's text brush, which is always a solid brush */
1414 pebo
= &pdc
->eboText
;
1416 /* Save the old solid color and set the one for the pixel */
1417 iOldColor
= EBRUSHOBJ_iSetSolidColor(pebo
, iSolidColor
);
1419 /* Save dirty flags and reset dirty text brush flag */
1420 ulDirty
= pdc
->pdcattr
->ulDirty_
;
1421 pdc
->pdcattr
->ulDirty_
&= ~DIRTY_TEXT
;
1423 /* Call the internal function */
1424 bResult
= IntPatBlt(pdc
, x
, y
, 1, 1, PATCOPY
, pebo
);
1426 /* Restore old text brush color and dirty flags */
1427 EBRUSHOBJ_iSetSolidColor(pebo
, iOldColor
);
1428 pdc
->pdcattr
->ulDirty_
= ulDirty
;
1430 /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked!
1431 /* Initialize an XLATEOBJ from the target surface to RGB */
1432 EXLATEOBJ_vInitialize(&exlo
,
1433 pdc
->dclevel
.pSurface
->ppal
,
1436 pdc
->pdcattr
->crBackgroundClr
,
1437 pdc
->pdcattr
->crForegroundClr
);
1439 /* Translate the color back to RGB */
1440 crColor
= XLATEOBJ_iXlate(&exlo
.xlo
, iSolidColor
);
1442 /* Cleanup and return the target format color */
1443 EXLATEOBJ_vCleanup(&exlo
);
1448 /* Return the new RGB color or -1 on failure */
1449 return bResult
? crColor
: -1;
1460 ULONG ulRGBColor
= CLR_INVALID
;
1463 PSURFACE psurfSrc
, psurfDest
;
1466 pdc
= DC_LockDc(hdc
);
1469 EngSetLastError(ERROR_INVALID_HANDLE
);
1473 /* Check if the DC has no surface (empty mem or info DC) */
1474 if (pdc
->dclevel
.pSurface
== NULL
)
1480 /* Get the logical coordinates */
1484 /* Translate coordinates to device coordinates */
1485 IntLPtoDP(pdc
, &ptlSrc
, 1);
1486 ptlSrc
.x
+= pdc
->ptlDCOrig
.x
;
1487 ptlSrc
.y
+= pdc
->ptlDCOrig
.y
;
1491 rcDest
.right
= x
+ 1;
1492 rcDest
.bottom
= y
+ 1;
1494 /* Prepare DC for blit */
1495 DC_vPrepareDCsForBlit(pdc
, &rcDest
, NULL
, NULL
);
1497 /* Check if the pixel is outside the surface */
1498 psurfSrc
= pdc
->dclevel
.pSurface
;
1499 if ((ptlSrc
.x
>= psurfSrc
->SurfObj
.sizlBitmap
.cx
) ||
1500 (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 */