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
12 DBG_DEFAULT_CHANNEL(GdiBlt
);
26 BLENDFUNCTION BlendFunc
,
33 SURFACE
*BitmapDest
, *BitmapSrc
;
34 RECTL DestRect
, SourceRect
;
38 BlendObj
.BlendFunction
= BlendFunc
;
40 if (WidthDest
< 0 || HeightDest
< 0 || WidthSrc
< 0 || HeightSrc
< 0)
42 EngSetLastError(ERROR_INVALID_PARAMETER
);
46 if ((hDCDest
== NULL
) || (hDCSrc
== NULL
))
48 EngSetLastError(ERROR_INVALID_PARAMETER
);
52 TRACE("Locking DCs\n");
55 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
57 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hDCDest
, hDCSrc
);
58 EngSetLastError(ERROR_INVALID_HANDLE
);
64 if (DCDest
->dctype
== DCTYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
66 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
67 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
68 /* Yes, Windows really returns TRUE in this case */
72 DestRect
.left
= XOriginDest
;
73 DestRect
.top
= YOriginDest
;
74 DestRect
.right
= XOriginDest
+ WidthDest
;
75 DestRect
.bottom
= YOriginDest
+ HeightDest
;
76 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
78 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
79 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
80 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
81 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
83 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
85 IntUpdateBoundsRect(DCDest
, &DestRect
);
88 SourceRect
.left
= XOriginSrc
;
89 SourceRect
.top
= YOriginSrc
;
90 SourceRect
.right
= XOriginSrc
+ WidthSrc
;
91 SourceRect
.bottom
= YOriginSrc
+ HeightSrc
;
92 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
94 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
95 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
96 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
97 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
99 if (!DestRect
.right
||
104 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
105 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
109 /* Prepare DCs for blit */
110 TRACE("Preparing DCs for blit\n");
111 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
113 /* Determine surfaces to be used in the bitblt */
114 BitmapDest
= DCDest
->dclevel
.pSurface
;
121 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
128 /* Create the XLATEOBJ. */
129 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
131 /* Perform the alpha blend operation */
132 TRACE("Performing the alpha blend\n");
133 bResult
= IntEngAlphaBlend(&BitmapDest
->SurfObj
,
135 (CLIPOBJ
*)&DCDest
->co
,
141 EXLATEOBJ_vCleanup(&exlo
);
143 TRACE("Finishing blit\n");
144 DC_vFinishBlit(DCDest
, DCSrc
);
145 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
146 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
162 IN DWORD crBackColor
,
166 if (dwRop
& CAPTUREBLT
)
168 return NtGdiStretchBlt(hDCDest
,
182 dwRop
= dwRop
& ~(NOMIRRORBITMAP
|CAPTUREBLT
);
184 /* Forward to NtGdiMaskBlt */
185 // TODO: What's fl for? LOL not to send this to MaskBit!
186 return NtGdiMaskBlt(hDCDest
,
197 MAKEROP4(dwRop
, dwRop
),
219 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
220 ULONG TransparentColor
= 0;
224 if ((hdcDst
== NULL
) || (hdcSrc
== NULL
))
226 EngSetLastError(ERROR_INVALID_PARAMETER
);
230 TRACE("Locking DCs\n");
233 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
235 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst
, hdcSrc
);
236 EngSetLastError(ERROR_INVALID_HANDLE
);
242 if (DCDest
->dctype
== DCTYPE_INFO
|| DCDest
->dctype
== DCTYPE_INFO
)
244 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
245 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
246 /* Yes, Windows really returns TRUE in this case */
252 rcDest
.right
= rcDest
.left
+ cxDst
;
253 rcDest
.bottom
= rcDest
.top
+ cyDst
;
254 IntLPtoDP(DCDest
, (LPPOINT
)&rcDest
, 2);
256 rcDest
.left
+= DCDest
->ptlDCOrig
.x
;
257 rcDest
.top
+= DCDest
->ptlDCOrig
.y
;
258 rcDest
.right
+= DCDest
->ptlDCOrig
.x
;
259 rcDest
.bottom
+= DCDest
->ptlDCOrig
.y
;
263 rcSrc
.right
= rcSrc
.left
+ cxSrc
;
264 rcSrc
.bottom
= rcSrc
.top
+ cySrc
;
265 IntLPtoDP(DCSrc
, (LPPOINT
)&rcSrc
, 2);
267 rcSrc
.left
+= DCSrc
->ptlDCOrig
.x
;
268 rcSrc
.top
+= DCSrc
->ptlDCOrig
.y
;
269 rcSrc
.right
+= DCSrc
->ptlDCOrig
.x
;
270 rcSrc
.bottom
+= DCSrc
->ptlDCOrig
.y
;
272 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
274 IntUpdateBoundsRect(DCDest
, &rcDest
);
277 /* Prepare for blit */
278 DC_vPrepareDCsForBlit(DCDest
, &rcDest
, DCSrc
, &rcSrc
);
280 BitmapDest
= DCDest
->dclevel
.pSurface
;
286 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
292 /* Translate Transparent (RGB) Color to the source palette */
293 EXLATEOBJ_vInitialize(&exlo
, &gpalRGB
, BitmapSrc
->ppal
, 0, 0, 0);
294 TransparentColor
= XLATEOBJ_iXlate(&exlo
.xlo
, (ULONG
)TransColor
);
295 EXLATEOBJ_vCleanup(&exlo
);
297 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
299 Ret
= IntEngTransparentBlt(&BitmapDest
->SurfObj
, &BitmapSrc
->SurfObj
,
300 (CLIPOBJ
*)&DCDest
->co
, &exlo
.xlo
, &rcDest
, &rcSrc
,
301 TransparentColor
, 0);
303 EXLATEOBJ_vCleanup(&exlo
);
306 DC_vFinishBlit(DCDest
, DCSrc
);
307 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
308 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
327 IN DWORD crBackColor
)
333 PDC_ATTR pdcattr
= NULL
;
334 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
, *psurfMask
= NULL
;
335 RECTL DestRect
, SourceRect
;
336 POINTL SourcePoint
, MaskPoint
;
339 XLATEOBJ
*XlateObj
= NULL
;
343 rop4
= WIN32_ROP4_TO_ENG_ROP4(dwRop4
);
345 UsesSource
= ROP4_USES_SOURCE(rop4
);
346 if (!hdcDest
|| (UsesSource
&& !hdcSrc
))
348 EngSetLastError(ERROR_INVALID_PARAMETER
);
352 /* Check if we need a mask and have a mask bitmap */
353 if (ROP4_USES_MASK(rop4
) && (hbmMask
!= NULL
))
355 /* Reference the mask bitmap */
356 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
357 if (psurfMask
== NULL
)
359 EngSetLastError(ERROR_INVALID_HANDLE
);
363 /* Make sure the mask bitmap is 1 BPP */
364 if (gajBitsPerFormat
[psurfMask
->SurfObj
.iBitmapFormat
] != 1)
366 EngSetLastError(ERROR_INVALID_PARAMETER
);
367 SURFACE_ShareUnlockSurface(psurfMask
);
373 /* We use NULL, if we need a mask, the Eng function will take care of
374 that and use the brushobject to get a mask */
381 /* Take care of source and destination bitmap */
382 TRACE("Locking DCs\n");
384 ahDC
[1] = UsesSource
? hdcSrc
: NULL
;
385 if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
387 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiMaskBlt\n", hdcDest
, hdcSrc
);
388 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
389 EngSetLastError(ERROR_INVALID_HANDLE
);
398 if(DCSrc
) DC_UnlockDc(DCSrc
);
399 WARN("Invalid destination dc handle (0x%p) passed to NtGdiMaskBlt\n", hdcDest
);
400 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
404 if (DCDest
->dctype
== DCTYPE_INFO
)
406 if(DCSrc
) DC_UnlockDc(DCSrc
);
408 /* Yes, Windows really returns TRUE in this case */
409 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
416 if (DCSrc
->dctype
== DCTYPE_INFO
)
420 /* Yes, Windows really returns TRUE in this case */
421 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
426 pdcattr
= DCDest
->pdcattr
;
428 DestRect
.left
= nXDest
;
429 DestRect
.top
= nYDest
;
430 DestRect
.right
= nXDest
+ nWidth
;
431 DestRect
.bottom
= nYDest
+ nHeight
;
432 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
434 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
435 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
436 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
437 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
439 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
441 IntUpdateBoundsRect(DCDest
, &DestRect
);
444 SourcePoint
.x
= nXSrc
;
445 SourcePoint
.y
= nYSrc
;
449 IntLPtoDP(DCSrc
, (LPPOINT
)&SourcePoint
, 1);
451 SourcePoint
.x
+= DCSrc
->ptlDCOrig
.x
;
452 SourcePoint
.y
+= DCSrc
->ptlDCOrig
.y
;
453 /* Calculate Source Rect */
454 SourceRect
.left
= SourcePoint
.x
;
455 SourceRect
.top
= SourcePoint
.y
;
456 SourceRect
.right
= SourcePoint
.x
+ DestRect
.right
- DestRect
.left
;
457 SourceRect
.bottom
= SourcePoint
.y
+ DestRect
.bottom
- DestRect
.top
;
463 SourceRect
.right
= 0;
464 SourceRect
.bottom
= 0;
468 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
470 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
471 DC_vUpdateFillBrush(DCDest
);
473 /* Determine surfaces to be used in the bitblt */
474 BitmapDest
= DCDest
->dclevel
.pSurface
;
480 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
484 /* Create the XLATEOBJ. */
485 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
486 XlateObj
= &exlo
.xlo
;
489 DPRINT("DestRect: (%d,%d)-(%d,%d) and SourcePoint is (%d,%d)\n",
490 DestRect
.left
, DestRect
.top
, DestRect
.right
, DestRect
.bottom
,
491 SourcePoint
.x
, SourcePoint
.y
);
493 DPRINT("nWidth is '%d' and nHeight is '%d'.\n", nWidth
, nHeight
);
495 /* Fix BitBlt so that it will not flip left to right */
496 if ((DestRect
.left
> DestRect
.right
) && (nWidth
< 0))
498 SourcePoint
.x
+= nWidth
;
502 /* Fix BitBlt so that it will not flip top to bottom */
503 if ((DestRect
.top
> DestRect
.bottom
) && (nHeight
< 0))
505 SourcePoint
.y
+= nHeight
;
509 /* Make Well Ordered so that we don't flip either way */
510 RECTL_vMakeWellOrdered(&DestRect
);
512 /* Perform the bitblt operation */
513 Status
= IntEngBitBlt(&BitmapDest
->SurfObj
,
514 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
515 psurfMask
? &psurfMask
->SurfObj
: NULL
,
516 (CLIPOBJ
*)&DCDest
->co
,
521 &DCDest
->eboFill
.BrushObject
,
522 &DCDest
->dclevel
.pbrFill
->ptOrigin
,
526 EXLATEOBJ_vCleanup(&exlo
);
528 DC_vFinishBlit(DCDest
, DCSrc
);
534 if(psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
552 IN DWORD crBackColor
)
554 FIXME("NtGdiPlgBlt: unimplemented.\n");
572 IN DWORD dwBackColor
,
583 SURFACE
*BitmapDest
, *BitmapSrc
= NULL
;
584 SURFACE
*BitmapMask
= NULL
;
590 XLATEOBJ
*XlateObj
= NULL
;
595 BOOL Case0000
, Case0101
, Case1010
, CaseExcept
;
597 rop4
= WIN32_ROP4_TO_ENG_ROP4(dwRop4
);
599 UsesSource
= ROP4_USES_SOURCE(rop4
);
600 UsesMask
= ROP4_USES_MASK(rop4
);
602 if (0 == WidthDest
|| 0 == HeightDest
|| 0 == WidthSrc
|| 0 == HeightSrc
)
604 EngSetLastError(ERROR_INVALID_PARAMETER
);
608 if (!hDCDest
|| (UsesSource
&& !hDCSrc
) || (UsesMask
&& !hDCMask
))
610 EngSetLastError(ERROR_INVALID_PARAMETER
);
615 ahDC
[1] = UsesSource
? hDCSrc
: NULL
;
616 ahDC
[2] = UsesMask
? hDCMask
: NULL
;
617 if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ
*)ahDC
, apObj
, GDIObjType_DC_TYPE
))
619 WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest
, hDCSrc
);
620 EngSetLastError(ERROR_INVALID_HANDLE
);
627 if (DCDest
->dctype
== DCTYPE_INFO
)
629 if(DCSrc
) GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
630 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
631 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
632 /* Yes, Windows really returns TRUE in this case */
638 if (DCSrc
->dctype
== DCTYPE_INFO
)
640 GDIOBJ_vUnlockObject(&DCDest
->BaseObject
);
641 GDIOBJ_vUnlockObject(&DCSrc
->BaseObject
);
642 if(DCMask
) GDIOBJ_vUnlockObject(&DCMask
->BaseObject
);
643 /* Yes, Windows really returns TRUE in this case */
649 Case0000
= ((WidthDest
< 0) && (HeightDest
< 0) && (WidthSrc
< 0) && (HeightSrc
< 0));
650 Case0101
= ((WidthDest
< 0) && (HeightDest
> 0) && (WidthSrc
< 0) && (HeightSrc
> 0));
651 Case1010
= ((WidthDest
> 0) && (HeightDest
< 0) && (WidthSrc
> 0) && (HeightSrc
< 0));
652 CaseExcept
= (Case0000
|| Case0101
|| Case1010
);
654 pdcattr
= DCDest
->pdcattr
;
656 DestRect
.left
= XOriginDest
;
657 DestRect
.top
= YOriginDest
;
658 DestRect
.right
= XOriginDest
+WidthDest
;
659 DestRect
.bottom
= YOriginDest
+HeightDest
;
661 /* Account for possible negative span values */
662 if ((WidthDest
< 0) && !CaseExcept
)
667 if ((HeightDest
< 0) && !CaseExcept
)
673 IntLPtoDP(DCDest
, (LPPOINT
)&DestRect
, 2);
675 DestRect
.left
+= DCDest
->ptlDCOrig
.x
;
676 DestRect
.top
+= DCDest
->ptlDCOrig
.y
;
677 DestRect
.right
+= DCDest
->ptlDCOrig
.x
;
678 DestRect
.bottom
+= DCDest
->ptlDCOrig
.y
;
680 if (DCDest
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
682 IntUpdateBoundsRect(DCDest
, &DestRect
);
685 SourceRect
.left
= XOriginSrc
;
686 SourceRect
.top
= YOriginSrc
;
687 SourceRect
.right
= XOriginSrc
+WidthSrc
;
688 SourceRect
.bottom
= YOriginSrc
+HeightSrc
;
690 /* Account for possible negative span values */
691 if ((WidthSrc
< 0) && !CaseExcept
)
696 if ((HeightSrc
< 0) && !CaseExcept
)
704 IntLPtoDP(DCSrc
, (LPPOINT
)&SourceRect
, 2);
706 SourceRect
.left
+= DCSrc
->ptlDCOrig
.x
;
707 SourceRect
.top
+= DCSrc
->ptlDCOrig
.y
;
708 SourceRect
.right
+= DCSrc
->ptlDCOrig
.x
;
709 SourceRect
.bottom
+= DCSrc
->ptlDCOrig
.y
;
715 /* Only prepare Source and Dest, hdcMask represents a DIB */
716 DC_vPrepareDCsForBlit(DCDest
, &DestRect
, DCSrc
, &SourceRect
);
718 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
719 DC_vUpdateFillBrush(DCDest
);
721 /* Determine surfaces to be used in the bitblt */
722 BitmapDest
= DCDest
->dclevel
.pSurface
;
723 if (BitmapDest
== NULL
)
727 BitmapSrc
= DCSrc
->dclevel
.pSurface
;
728 if (BitmapSrc
== NULL
)
731 /* Create the XLATEOBJ. */
732 EXLATEOBJ_vInitXlateFromDCs(&exlo
, DCSrc
, DCDest
);
733 XlateObj
= &exlo
.xlo
;
736 /* Offset the brush */
737 BrushOrigin
.x
+= DCDest
->ptlDCOrig
.x
;
738 BrushOrigin
.y
+= DCDest
->ptlDCOrig
.y
;
740 /* Make mask surface for source surface */
741 if (BitmapSrc
&& DCMask
)
743 BitmapMask
= DCMask
->dclevel
.pSurface
;
745 (BitmapMask
->SurfObj
.sizlBitmap
.cx
< WidthSrc
||
746 BitmapMask
->SurfObj
.sizlBitmap
.cy
< HeightSrc
))
748 WARN("%dx%d mask is smaller than %dx%d bitmap\n",
749 BitmapMask
->SurfObj
.sizlBitmap
.cx
, BitmapMask
->SurfObj
.sizlBitmap
.cy
,
750 WidthSrc
, HeightSrc
);
751 EXLATEOBJ_vCleanup(&exlo
);
754 /* Create mask offset point */
755 MaskPoint
.x
= XOriginMask
;
756 MaskPoint
.y
= YOriginMask
;
757 IntLPtoDP(DCMask
, &MaskPoint
, 1);
758 MaskPoint
.x
+= DCMask
->ptlDCOrig
.x
;
759 MaskPoint
.y
+= DCMask
->ptlDCOrig
.y
;
762 DPRINT("Calling IntEngStrethBlt SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d).\n",
763 SourceRect
.left
, SourceRect
.top
, SourceRect
.right
, SourceRect
.bottom
,
764 DestRect
.left
, DestRect
.top
, DestRect
.right
, DestRect
.bottom
);
766 /* Perform the bitblt operation */
767 Status
= IntEngStretchBlt(&BitmapDest
->SurfObj
,
768 BitmapSrc
? &BitmapSrc
->SurfObj
: NULL
,
769 BitmapMask
? &BitmapMask
->SurfObj
: NULL
,
770 (CLIPOBJ
*)&DCDest
->co
,
775 BitmapMask
? &MaskPoint
: NULL
,
776 &DCDest
->eboFill
.BrushObject
,
781 EXLATEOBJ_vCleanup(&exlo
);
785 DC_vFinishBlit(DCDest
, DCSrc
);
813 IN DWORD dwBackColor
)
815 dwRop3
= dwRop3
& ~(NOMIRRORBITMAP
|CAPTUREBLT
);
817 return GreStretchBltMask(
828 MAKEROP4(dwRop3
& 0xFF0000, dwRop3
),
853 pbrush
= pebo
->pbrush
;
856 if (pbrush
->flAttrs
& BR_IS_NULL
)
863 DestRect
.left
= XLeft
;
864 DestRect
.right
= XLeft
+ Width
;
868 DestRect
.left
= XLeft
+ Width
;
869 DestRect
.right
= XLeft
;
874 DestRect
.top
= YLeft
;
875 DestRect
.bottom
= YLeft
+ Height
;
879 DestRect
.top
= YLeft
+ Height
;
880 DestRect
.bottom
= YLeft
;
883 IntLPtoDP(pdc
, (LPPOINT
)&DestRect
, 2);
885 DestRect
.left
+= pdc
->ptlDCOrig
.x
;
886 DestRect
.top
+= pdc
->ptlDCOrig
.y
;
887 DestRect
.right
+= pdc
->ptlDCOrig
.x
;
888 DestRect
.bottom
+= pdc
->ptlDCOrig
.y
;
890 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
892 IntUpdateBoundsRect(pdc
, &DestRect
);
896 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
+ XLeft
;
897 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
+ YLeft
;
899 BrushOrigin
.x
= pbrush
->ptOrigin
.x
+ pdc
->ptlDCOrig
.x
;
900 BrushOrigin
.y
= pbrush
->ptOrigin
.y
+ pdc
->ptlDCOrig
.y
;
903 DC_vPrepareDCsForBlit(pdc
, &DestRect
, NULL
, NULL
);
905 psurf
= pdc
->dclevel
.pSurface
;
907 ret
= IntEngBitBlt(&psurf
->SurfObj
,
917 WIN32_ROP3_TO_ENG_ROP4(dwRop3
));
919 DC_vFinishBlit(pdc
, NULL
);
937 pdc
= DC_LockDc(hDC
);
940 EngSetLastError(ERROR_INVALID_HANDLE
);
944 if (pdc
->dctype
== DCTYPE_INFO
)
947 /* Yes, Windows really returns TRUE in this case */
951 for (i
= 0; i
< cRects
; i
++)
953 pbrush
= BRUSH_ShareLockBrush(pRects
->hBrush
);
955 /* Check if we could lock the brush */
958 /* Initialize a brush object */
959 EBRUSHOBJ_vInitFromDC(&eboFill
, pbrush
, pdc
);
970 /* Cleanup the brush object and unlock the brush */
971 EBRUSHOBJ_vCleanup(&eboFill
);
972 BRUSH_ShareUnlockBrush(pbrush
);
995 /* Convert the ROP3 to a ROP4 */
996 dwRop
= MAKEROP4(dwRop
& 0xFF0000, dwRop
);
998 /* Check if the rop uses a source */
999 if (WIN32_ROP4_USES_SOURCE(dwRop
))
1001 /* This is not possible */
1006 pdc
= DC_LockDc(hdcDest
);
1009 EngSetLastError(ERROR_INVALID_HANDLE
);
1013 /* Check if the DC has no surface (empty mem or info DC) */
1014 if (pdc
->dclevel
.pSurface
== NULL
)
1016 /* Nothing to do, Windows returns TRUE! */
1021 /* Update the fill brush, if necessary */
1022 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1023 DC_vUpdateFillBrush(pdc
);
1025 /* Call the internal function */
1026 bResult
= IntPatBlt(pdc
, x
, y
, cx
, cy
, dwRop
, &pdc
->eboFill
);
1028 /* Unlock the DC and return the result */
1038 IN PPOLYPATBLT pRects
,
1043 NTSTATUS Status
= STATUS_SUCCESS
;
1048 rb
= ExAllocatePoolWithTag(PagedPool
, sizeof(PATRECT
) * cRects
, GDITAG_PLGBLT_DATA
);
1051 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1056 ProbeForRead(pRects
,
1057 cRects
* sizeof(PATRECT
),
1061 cRects
* sizeof(PATRECT
));
1063 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1065 Status
= _SEH2_GetExceptionCode();
1069 if (!NT_SUCCESS(Status
))
1071 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1072 SetLastNtError(Status
);
1077 Ret
= IntGdiPolyPatBlt(hDC
, dwRop
, rb
, cRects
, Mode
);
1080 ExFreePoolWithTag(rb
, GDITAG_PLGBLT_DATA
);
1090 _Inout_ PREGION prgnDest
,
1091 _In_ PREGION prgnSrc
)
1093 if (IntGdiCombineRgn(prgnDest
, prgnSrc
, NULL
, RGN_COPY
) == ERROR
)
1096 return REGION_bXformRgn(prgnDest
, DC_pmxWorldToDevice(pdc
));
1104 _In_opt_ BRUSHOBJ
*pbo
,
1105 _In_opt_ POINTL
*pptlBrush
,
1111 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1113 /* Check if we have a surface */
1114 if (pdc
->dclevel
.pSurface
== NULL
)
1119 /* Create an empty clip region */
1120 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1121 if (prgnClip
== NULL
)
1126 /* Transform given region into device coordinates */
1127 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1129 REGION_Delete(prgnClip
);
1133 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1135 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1137 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1139 /* Now account for the DC-origin */
1140 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1142 REGION_Delete(prgnClip
);
1146 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1149 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1150 IntUpdateBoundsRect(pdc
, &rcrgn
);
1153 /* Prepare the DC */
1154 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1156 /* Initialize a clip object */
1157 IntEngInitClipObj(&xcoClip
);
1158 IntEngUpdateClipRegion(&xcoClip
,
1159 prgnClip
->rdh
.nCount
,
1161 &prgnClip
->rdh
.rcBound
);
1163 /* Call the Eng or Drv function */
1164 bResult
= IntEngBitBlt(&pdc
->dclevel
.pSurface
->SurfObj
,
1167 (CLIPOBJ
*)&xcoClip
,
1169 &prgnClip
->rdh
.rcBound
,
1177 DC_vFinishBlit(pdc
, NULL
);
1178 REGION_Delete(prgnClip
);
1179 IntEngFreeClipResources(&xcoClip
);
1181 /* Return the result */
1189 _In_opt_ PBRUSH pbrFill
)
1198 NT_ASSERT((pdc
!= NULL
) && (prgn
!= NULL
));
1200 if (pdc
->dclevel
.pSurface
== NULL
)
1205 prgnClip
= IntSysCreateRectpRgn(0, 0, 0, 0);
1206 if (prgnClip
== NULL
)
1211 /* Transform region into device coordinates */
1212 if (!REGION_LPTODP(pdc
, prgnClip
, prgn
))
1214 REGION_Delete(prgnClip
);
1218 /* Intersect with the system or RAO region (these are (atm) without DC-origin) */
1220 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnRao
, RGN_AND
);
1222 IntGdiCombineRgn(prgnClip
, prgnClip
, pdc
->prgnVis
, RGN_AND
);
1224 /* Now account for the DC-origin */
1225 if (!REGION_bOffsetRgn(prgnClip
, pdc
->ptlDCOrig
.x
, pdc
->ptlDCOrig
.y
))
1227 REGION_Delete(prgnClip
);
1231 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1234 REGION_GetRgnBox(prgnClip
, &rcrgn
);
1235 IntUpdateBoundsRect(pdc
, &rcrgn
);
1238 IntEngInitClipObj(&xcoClip
);
1239 IntEngUpdateClipRegion(&xcoClip
,
1240 prgnClip
->rdh
.nCount
,
1242 &prgnClip
->rdh
.rcBound
);
1244 /* Get the FG rop and create a MIX based on the BK mode */
1245 rop2Fg
= FIXUP_ROP2(pdc
->pdcattr
->jROP2
);
1246 mix
= rop2Fg
| (pdc
->pdcattr
->jBkMode
== OPAQUE
? rop2Fg
: R2_NOP
) << 8;
1248 /* Prepare DC for blit */
1249 DC_vPrepareDCsForBlit(pdc
, &prgnClip
->rdh
.rcBound
, NULL
, NULL
);
1251 /* Check if we have a fill brush */
1252 if (pbrFill
!= NULL
)
1254 /* Initialize the brush object */
1255 /// \todo Check parameters
1256 EBRUSHOBJ_vInit(&eboFill
, pbrFill
, pdc
->dclevel
.pSurface
, 0x00FFFFFF, 0, NULL
);
1257 pbo
= &eboFill
.BrushObject
;
1261 /* Update the fill brush if needed */
1262 if (pdc
->pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
1263 DC_vUpdateFillBrush(pdc
);
1265 /* Use the DC brush object */
1266 pbo
= &pdc
->eboFill
.BrushObject
;
1269 /* Call the internal function */
1270 bRet
= IntEngPaint(&pdc
->dclevel
.pSurface
->SurfObj
,
1271 (CLIPOBJ
*)&xcoClip
,
1273 &pdc
->pdcattr
->ptlBrushOrigin
,
1276 DC_vFinishBlit(pdc
, NULL
);
1277 REGION_Delete(prgnClip
);
1278 IntEngFreeClipResources(&xcoClip
);
1290 return IntGdiFillRgn(pdc
, prgn
, NULL
);
1306 pdc
= DC_LockDc(hdc
);
1309 ERR("Failed to lock hdc %p\n", hdc
);
1313 /* Check if the DC has no surface (empty mem or info DC) */
1314 if (pdc
->dclevel
.pSurface
== NULL
)
1320 /* Lock the region */
1321 prgn
= REGION_LockRgn(hrgn
);
1324 ERR("Failed to lock hrgn %p\n", hrgn
);
1329 /* Lock the brush */
1330 pbrFill
= BRUSH_ShareLockBrush(hbrush
);
1331 if (pbrFill
== NULL
)
1333 ERR("Failed to lock hbrush %p\n", hbrush
);
1334 REGION_UnlockRgn(prgn
);
1339 /* Call the internal function */
1340 bResult
= IntGdiFillRgn(pdc
, prgn
, pbrFill
);
1343 BRUSH_ShareUnlockBrush(pbrFill
);
1344 REGION_UnlockRgn(prgn
);
1362 hrgnFrame
= GreCreateFrameRgn(hrgn
, xWidth
, yHeight
);
1363 if (hrgnFrame
== NULL
)
1368 bResult
= NtGdiFillRgn(hdc
, hrgnFrame
, hbrush
);
1370 GreDeleteObject(hrgnFrame
);
1385 pdc
= DC_LockDc(hdc
);
1388 EngSetLastError(ERROR_INVALID_HANDLE
);
1392 /* Check if the DC has no surface (empty mem or info DC) */
1393 if (pdc
->dclevel
.pSurface
== NULL
)
1395 /* Nothing to do, Windows returns TRUE! */
1400 /* Lock the region */
1401 prgn
= REGION_LockRgn(hrgn
);
1408 /* Call the internal function */
1409 bResult
= IntGdiBitBltRgn(pdc
,
1415 /* Unlock the region and DC and return the result */
1416 REGION_UnlockRgn(prgn
);
1427 _In_ COLORREF crColor
)
1430 ULONG iOldColor
, iSolidColor
;
1437 pdc
= DC_LockDc(hdc
);
1440 EngSetLastError(ERROR_INVALID_HANDLE
);
1444 /* Check if the DC has no surface (empty mem or info DC) */
1445 if (pdc
->dclevel
.pSurface
== NULL
)
1452 if (pdc
->fs
& (DC_ACCUM_APP
|DC_ACCUM_WMGR
))
1456 RECTL_vSetRect(&rcDst
, x
, y
, x
+1, y
+1);
1458 IntLPtoDP(pdc
, (LPPOINT
)&rcDst
, 2);
1460 rcDst
.left
+= pdc
->ptlDCOrig
.x
;
1461 rcDst
.top
+= pdc
->ptlDCOrig
.y
;
1462 rcDst
.right
+= pdc
->ptlDCOrig
.x
;
1463 rcDst
.bottom
+= pdc
->ptlDCOrig
.y
;
1465 IntUpdateBoundsRect(pdc
, &rcDst
);
1468 /* Translate the color to the target format */
1469 iSolidColor
= TranslateCOLORREF(pdc
, crColor
);
1471 /* Use the DC's text brush, which is always a solid brush */
1472 pebo
= &pdc
->eboText
;
1474 /* Save the old solid color and set the one for the pixel */
1475 iOldColor
= EBRUSHOBJ_iSetSolidColor(pebo
, iSolidColor
);
1477 /* Save dirty flags and reset dirty text brush flag */
1478 ulDirty
= pdc
->pdcattr
->ulDirty_
;
1479 pdc
->pdcattr
->ulDirty_
&= ~DIRTY_TEXT
;
1481 /* Call the internal function */
1482 bResult
= IntPatBlt(pdc
, x
, y
, 1, 1, PATCOPY
, pebo
);
1484 /* Restore old text brush color and dirty flags */
1485 EBRUSHOBJ_iSetSolidColor(pebo
, iOldColor
);
1486 pdc
->pdcattr
->ulDirty_
= ulDirty
;
1488 /// FIXME: we shouldn't dereference pSurface while the PDEV is not locked!
1489 /* Initialize an XLATEOBJ from the target surface to RGB */
1490 EXLATEOBJ_vInitialize(&exlo
,
1491 pdc
->dclevel
.pSurface
->ppal
,
1494 pdc
->pdcattr
->crBackgroundClr
,
1495 pdc
->pdcattr
->crForegroundClr
);
1497 /* Translate the color back to RGB */
1498 crColor
= XLATEOBJ_iXlate(&exlo
.xlo
, iSolidColor
);
1500 /* Cleanup and return the target format color */
1501 EXLATEOBJ_vCleanup(&exlo
);
1506 /* Return the new RGB color or -1 on failure */
1507 return bResult
? crColor
: -1;
1518 ULONG ulRGBColor
= CLR_INVALID
;
1521 PSURFACE psurfSrc
, psurfDest
;
1524 pdc
= DC_LockDc(hdc
);
1527 EngSetLastError(ERROR_INVALID_HANDLE
);
1531 /* Check if the DC has no surface (empty mem or info DC) */
1532 if (pdc
->dclevel
.pSurface
== NULL
)
1538 /* Get the logical coordinates */
1542 /* Translate coordinates to device coordinates */
1543 IntLPtoDP(pdc
, &ptlSrc
, 1);
1544 ptlSrc
.x
+= pdc
->ptlDCOrig
.x
;
1545 ptlSrc
.y
+= pdc
->ptlDCOrig
.y
;
1549 rcDest
.right
= x
+ 1;
1550 rcDest
.bottom
= y
+ 1;
1552 /* Prepare DC for blit */
1553 DC_vPrepareDCsForBlit(pdc
, &rcDest
, NULL
, NULL
);
1555 /* Check if the pixel is outside the surface */
1556 psurfSrc
= pdc
->dclevel
.pSurface
;
1557 if ((ptlSrc
.x
>= psurfSrc
->SurfObj
.sizlBitmap
.cx
) ||
1558 (ptlSrc
.y
>= psurfSrc
->SurfObj
.sizlBitmap
.cy
) ||
1566 /* Allocate a surface */
1567 psurfDest
= SURFACE_AllocSurface(STYPE_BITMAP
,
1577 RECTL rclDest
= {0, 0, 1, 1};
1580 /* Translate from the source palette to RGB color */
1581 EXLATEOBJ_vInitialize(&exlo
,
1585 RGB(0xff,0xff,0xff),
1588 /* Call the copy bits function */
1589 EngCopyBits(&psurfDest
->SurfObj
,
1596 /* Cleanup the XLATEOBJ */
1597 EXLATEOBJ_vCleanup(&exlo
);
1599 /* Delete the surface */
1600 GDIOBJ_vDeleteObject(&psurfDest
->BaseObject
);
1602 /* The top byte is zero */
1603 ulRGBColor
&= 0x00FFFFFF;
1609 DC_vFinishBlit(pdc
, NULL
);
1612 /* Return the new RGB color or -1 on failure */