2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: GDI BitBlt Functions
5 * FILE: win32ss/gdi/eng/bitblt.c
6 * PROGRAMER: Jason Filby
15 XCLIPOBJ gxcoTrivial
=
20 {LONG_MIN
, LONG_MIN
, LONG_MAX
, LONG_MAX
}, /* rclBounds */
21 DC_TRIVIAL
, /* idCOmplexity */
22 FC_RECT
, /* iFComplexity */
23 TC_RECTANGLES
, /* iMode */
27 0, {0,0,0,0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
30 typedef BOOLEAN (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
33 XLATEOBJ
* ColorTranslation
,
41 static BOOLEAN APIENTRY
42 BltMask(SURFOBJ
* psoDest
,
45 XLATEOBJ
* ColorTranslation
,
54 BYTE
*pjMskLine
, *pjMskCurrent
;
55 BYTE fjMaskBit0
, fjMaskBit
;
58 ULONG PatternWidth
= 0, PatternHeight
= 0;
59 LONG PatternX0
= 0, PatternX
= 0, PatternY
= 0;
60 LONG SrcX
= 0, SrcY
= 0;
61 PFN_DIB_PutPixel fnDest_PutPixel
= NULL
;
62 PFN_DIB_GetPixel fnPattern_GetPixel
= NULL
, fnSrc_GetPixel
= NULL
, fnDest_GetPixel
;
63 ULONG Pattern
= 0, Source
= 0, Dest
= 0;
64 DWORD fgndRop
, bkgndRop
;
66 ASSERT(IS_VALID_ROP4(Rop4
));
67 ASSERT(psoMask
->iBitmapFormat
== BMF_1BPP
);
69 fgndRop
= ROP4_FGND(Rop4
);
70 bkgndRop
= ROP4_BKGND(Rop4
);
72 //DPRINT1("Rop4 : 0x%08x\n", Rop4);
74 /* Determine pattern */
75 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
77 psoPattern
= BRUSHOBJ_psoPattern(pbo
);
80 PatternWidth
= psoPattern
->sizlBitmap
.cx
;
81 PatternHeight
= psoPattern
->sizlBitmap
.cy
;
82 fnPattern_GetPixel
= DibFunctionsForBitmapFormat
[psoPattern
->iBitmapFormat
].DIB_GetPixel
;
88 cx
= prclDest
->right
- prclDest
->left
;
89 cy
= prclDest
->bottom
- prclDest
->top
;
90 if ((pptlMask
->x
+ cx
> psoMask
->sizlBitmap
.cx
) ||
91 (pptlMask
->y
+ cy
> psoMask
->sizlBitmap
.cy
))
96 pjMskLine
= (PBYTE
)psoMask
->pvScan0
+ pptlMask
->y
* psoMask
->lDelta
+ (pptlMask
->x
>> 3);
97 fjMaskBit0
= 0x80 >> (pptlMask
->x
& 0x07);
99 fnDest_PutPixel
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel
;
100 fnDest_GetPixel
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_GetPixel
;
102 /* Do we have a source */
106 ASSERT(ROP4_USES_SOURCE(Rop4
));
107 fnSrc_GetPixel
= DibFunctionsForBitmapFormat
[psoSource
->iBitmapFormat
].DIB_GetPixel
;
108 SrcY
= pptlSource
->y
;
109 SrcX
= pptlSource
->x
;
114 PatternY
= (prclDest
->top
- pptlBrush
->y
) % PatternHeight
;
117 PatternY
+= PatternHeight
;
119 PatternX0
= (prclDest
->left
- pptlBrush
->x
) % PatternWidth
;
122 PatternX0
+= PatternWidth
;
124 PatternX
= PatternX0
;
128 Pattern
= pbo
? pbo
->iSolidColor
: 0;
131 for (y
= prclDest
->top
; y
< prclDest
->bottom
; y
++)
133 pjMskCurrent
= pjMskLine
;
134 fjMaskBit
= fjMaskBit0
;
136 for (x
= prclDest
->left
; x
< prclDest
->right
; x
++)
138 Rop4
= (*pjMskCurrent
& fjMaskBit
) ? fgndRop
: bkgndRop
;
142 if(ROP4_USES_PATTERN(Rop4
))
143 Pattern
= fnPattern_GetPixel(psoPattern
, PatternX
, PatternY
);
145 PatternX
%= PatternWidth
;
150 if(ROP4_USES_SOURCE(Rop4
))
152 Source
= XLATEOBJ_iXlate(ColorTranslation
,
153 fnSrc_GetPixel(psoSource
, SrcX
, SrcY
));
158 if(ROP4_USES_DEST(Rop4
))
159 Dest
= fnDest_GetPixel(psoDest
, x
, y
);
161 fnDest_PutPixel(psoDest
,
168 fjMaskBit
= _rotr8(fjMaskBit
, 1);
169 pjMskCurrent
+= (fjMaskBit
>> 7);
171 pjMskLine
+= psoMask
->lDelta
;
175 PatternY
%= PatternHeight
;
176 PatternX
= PatternX0
;
181 SrcX
= pptlSource
->x
;
190 static BOOLEAN APIENTRY
191 BltPatCopy(SURFOBJ
* Dest
,
194 XLATEOBJ
* ColorTranslation
,
202 // These functions are assigned if we're working with a DIB
203 // The assigned functions depend on the bitsPerPixel of the DIB
205 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_ColorFill(Dest
, DestRect
, pbo
? pbo
->iSolidColor
: 0);
210 static BOOLEAN APIENTRY
211 CallDibBitBlt(SURFOBJ
* OutputObj
,
214 XLATEOBJ
* ColorTranslation
,
226 BltInfo
.DestSurface
= OutputObj
;
227 BltInfo
.SourceSurface
= InputObj
;
228 BltInfo
.PatternSurface
= NULL
;
229 BltInfo
.XlateSourceToDest
= ColorTranslation
;
230 BltInfo
.DestRect
= *OutputRect
;
231 BltInfo
.SourcePoint
= *InputPoint
;
233 if ((Rop4
& 0xFF) == R3_OPINDEX_SRCCOPY
)
234 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
237 BltInfo
.BrushOrigin
= *BrushOrigin
;
241 if (ROP4_USES_PATTERN(Rop4
) && pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
243 psoPattern
= BRUSHOBJ_psoPattern(pbo
);
246 BltInfo
.PatternSurface
= psoPattern
;
250 /* FIXME: What to do here? */
258 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
263 INT __cdecl
abs(INT nm
);
280 IN POINTL
*pptlBrush
,
290 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
291 RtlCopyMemory(&rclTrg
,prclTrg
, sizeof(RECTL
));
293 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
294 RtlCopyMemory(&ptlSrc
, pptlSrc
, sizeof(POINTL
));
296 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
297 RtlCopyMemory(&ptlMask
, pptlMask
, sizeof(POINTL
));
299 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
300 RtlCopyMemory(&ptlBrush
, pptlBrush
, sizeof(POINTL
));
303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
305 _SEH2_YIELD(return FALSE
);
309 return EngBitBlt(psoTrg
, psoSrc
, psoMask
, pco
, pxlo
, &rclTrg
, &ptlSrc
, &ptlMask
, pbo
, &ptlBrush
, Rop4
);
318 _Inout_ SURFOBJ
*psoTrg
,
319 _In_opt_ SURFOBJ
*psoSrc
,
320 _In_opt_ SURFOBJ
*psoMask
,
321 _In_opt_ CLIPOBJ
*pco
,
322 _In_opt_ XLATEOBJ
*pxlo
,
324 _In_opt_ POINTL
*pptlSrc
,
325 _In_opt_ POINTL
*pptlMask
,
326 _In_opt_ BRUSHOBJ
*pbo
,
327 _In_opt_ POINTL
*pptlBrush
,
337 SURFOBJ
* InputObj
= 0;
339 PBLTRECTFUNC BltRectFunc
;
345 BOOL UsesSource
, UsesMask
;
346 POINTL AdjustedBrushOrigin
;
348 UsesSource
= ROP4_USES_SOURCE(rop4
);
349 UsesMask
= ROP4_USES_MASK(rop4
);
351 if (rop4
== ROP4_NOOP
)
353 /* Copy destination onto itself: nop */
357 //DPRINT1("rop4 : 0x%08x\n", rop4);
359 OutputRect
= *prclTrg
;
360 RECTL_vMakeWellOrdered(&OutputRect
);
364 if (!psoSrc
|| !pptlSrc
)
369 /* Make sure we don't try to copy anything outside the valid source
371 InputPoint
= *pptlSrc
;
372 if (InputPoint
.x
< 0)
374 OutputRect
.left
-= InputPoint
.x
;
377 if (InputPoint
.y
< 0)
379 OutputRect
.top
-= InputPoint
.y
;
382 if (psoSrc
->sizlBitmap
.cx
< InputPoint
.x
+
383 OutputRect
.right
- OutputRect
.left
)
385 OutputRect
.right
= OutputRect
.left
+
386 psoSrc
->sizlBitmap
.cx
- InputPoint
.x
;
388 if (psoSrc
->sizlBitmap
.cy
< InputPoint
.y
+
389 OutputRect
.bottom
- OutputRect
.top
)
391 OutputRect
.bottom
= OutputRect
.top
+
392 psoSrc
->sizlBitmap
.cy
- InputPoint
.y
;
395 InputRect
.left
= InputPoint
.x
;
396 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
397 InputRect
.top
= InputPoint
.y
;
398 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
404 InputPoint
.x
= InputPoint
.y
= 0;
406 InputRect
.right
= prclTrg
->right
- prclTrg
->left
;
408 InputRect
.bottom
= prclTrg
->bottom
- prclTrg
->top
;
413 if (OutputRect
.left
< pco
->rclBounds
.left
)
415 InputRect
.left
+= pco
->rclBounds
.left
- OutputRect
.left
;
416 InputPoint
.x
+= pco
->rclBounds
.left
- OutputRect
.left
;
417 OutputRect
.left
= pco
->rclBounds
.left
;
419 if (pco
->rclBounds
.right
< OutputRect
.right
)
421 InputRect
.right
-= OutputRect
.right
- pco
->rclBounds
.right
;
422 OutputRect
.right
= pco
->rclBounds
.right
;
424 if (OutputRect
.top
< pco
->rclBounds
.top
)
426 InputRect
.top
+= pco
->rclBounds
.top
- OutputRect
.top
;
427 InputPoint
.y
+= pco
->rclBounds
.top
- OutputRect
.top
;
428 OutputRect
.top
= pco
->rclBounds
.top
;
430 if (pco
->rclBounds
.bottom
< OutputRect
.bottom
)
432 InputRect
.bottom
-= OutputRect
.bottom
- pco
->rclBounds
.bottom
;
433 OutputRect
.bottom
= pco
->rclBounds
.bottom
;
437 /* Check for degenerate case: if height or width of OutputRect is 0 pixels
438 there's nothing to do */
439 if (OutputRect
.right
<= OutputRect
.left
||
440 OutputRect
.bottom
<= OutputRect
.top
)
449 AdjustedBrushOrigin
.x
= pptlBrush
->x
;
450 AdjustedBrushOrigin
.y
= pptlBrush
->y
;
454 AdjustedBrushOrigin
.x
= 0;
455 AdjustedBrushOrigin
.y
= 0;
458 /* Determine clipping type */
459 if (pco
== (CLIPOBJ
*) NULL
)
461 clippingType
= DC_TRIVIAL
;
465 clippingType
= pco
->iDComplexity
;
468 /* Check if we need a mask but have no mask surface */
469 if (UsesMask
&& (psoMask
== NULL
))
471 /* Check if the BRUSHOBJ can provide the mask */
472 psoMask
= BRUSHOBJ_psoMask(pbo
);
475 /* We have no mask, assume the mask is all foreground */
476 rop4
= (rop4
& 0xFF) | ((rop4
& 0xFF) << 8);
483 BltRectFunc
= BltMask
;
485 else if ((rop4
& 0xFF) == R3_OPINDEX_PATCOPY
)
487 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
488 BltRectFunc
= CallDibBitBlt
;
490 BltRectFunc
= BltPatCopy
;
494 BltRectFunc
= CallDibBitBlt
;
498 switch (clippingType
)
501 Ret
= (*BltRectFunc
)(OutputObj
,
509 &AdjustedBrushOrigin
,
513 /* Clip the blt to the clip rectangle */
514 ClipRect
.left
= pco
->rclBounds
.left
;
515 ClipRect
.right
= pco
->rclBounds
.right
;
516 ClipRect
.top
= pco
->rclBounds
.top
;
517 ClipRect
.bottom
= pco
->rclBounds
.bottom
;
518 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
523 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ CombinedRect
.left
- OutputRect
.left
;
524 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ CombinedRect
.top
- OutputRect
.top
;
527 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
528 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
529 Ret
= (*BltRectFunc
)(OutputObj
,
537 &AdjustedBrushOrigin
,
543 if (OutputObj
== InputObj
)
545 if (OutputRect
.top
< InputPoint
.y
)
547 Direction
= OutputRect
.left
< InputPoint
.x
?
548 CD_RIGHTDOWN
: CD_LEFTDOWN
;
552 Direction
= OutputRect
.left
< InputPoint
.x
?
553 CD_RIGHTUP
: CD_LEFTUP
;
560 CLIPOBJ_cEnumStart(pco
, FALSE
, CT_RECTANGLES
, Direction
, 0);
563 EnumMore
= CLIPOBJ_bEnum(pco
, sizeof(RectEnum
),
566 for (i
= 0; i
< RectEnum
.c
; i
++)
568 ClipRect
.left
= RectEnum
.arcl
[i
].left
;
569 ClipRect
.right
= RectEnum
.arcl
[i
].right
;
570 ClipRect
.top
= RectEnum
.arcl
[i
].top
;
571 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
;
572 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
577 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ CombinedRect
.left
- OutputRect
.left
;
578 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ CombinedRect
.top
- OutputRect
.top
;
581 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
582 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
583 Ret
= (*BltRectFunc
)(OutputObj
,
591 &AdjustedBrushOrigin
,
618 SURFACE
*psurfSrc
= NULL
;
623 PFN_DrvBitBlt pfnBitBlt
;
626 psurfTrg
= CONTAINING_RECORD(psoTrg
, SURFACE
, SurfObj
);
628 /* FIXME: Should we really allow to pass non-well-ordered rects? */
629 rclClipped
= *prclTrg
;
630 RECTL_vMakeWellOrdered(&rclClipped
);
632 //DPRINT1("Rop4 : 0x%08x\n", Rop4);
635 ASSERT(IS_VALID_ROP4(Rop4
));
639 /* Clip target rect against the bounds of the clipping region */
640 if (!RECTL_bIntersectRect(&rclClipped
, &rclClipped
, &pco
->rclBounds
))
646 /* Don't pass a clipobj with only a single rect */
647 if (pco
->iDComplexity
== DC_RECT
)
651 pco
= (CLIPOBJ
*)&gxcoTrivial
;
653 if (ROP4_USES_SOURCE(Rop4
))
656 psurfSrc
= CONTAINING_RECORD(psoSrc
, SURFACE
, SurfObj
);
658 /* Calculate source rect */
659 rclSrc
.left
= pptlSrc
->x
+ rclClipped
.left
- prclTrg
->left
;
660 rclSrc
.top
= pptlSrc
->y
+ rclClipped
.top
- prclTrg
->top
;
661 rclSrc
.right
= rclSrc
.left
+ rclClipped
.right
- rclClipped
.left
;
662 rclSrc
.bottom
= rclSrc
.top
+ rclClipped
.bottom
- rclClipped
.top
;
663 pptlSrc
= (PPOINTL
)&rclSrc
;
674 ptlBrush
.x
= pptlBrush
->x
+ rclClipped
.left
- prclTrg
->left
;
675 ptlBrush
.y
= pptlBrush
->y
+ rclClipped
.top
- prclTrg
->top
;
677 ptlBrush
= *pptlBrush
;
681 /* Is the target surface device managed? */
682 if (psurfTrg
->flags
& HOOK_BITBLT
)
684 /* Is the source a different device managed surface? */
685 if (psoSrc
&& psoSrc
->hdev
!= psoTrg
->hdev
&& psurfSrc
->flags
& HOOK_BITBLT
)
687 DPRINT1("Need to copy to standard bitmap format!\n");
691 pfnBitBlt
= GDIDEVFUNCS(psoTrg
).BitBlt
;
694 /* Is the source surface device managed? */
695 else if (psoSrc
&& psurfSrc
->flags
& HOOK_BITBLT
)
697 pfnBitBlt
= GDIDEVFUNCS(psoSrc
).BitBlt
;
701 pfnBitBlt
= EngBitBlt
;
704 bResult
= pfnBitBlt(psoTrg
,
713 pptlBrush
? &ptlBrush
: NULL
,
716 // FIXME: cleanup temp surface!
721 #endif // !_USE_DIBLIB_
723 /**** REACTOS FONT RENDERING CODE *********************************************/
725 /* renders the alpha mask bitmap */
726 static BOOLEAN APIENTRY
727 AlphaBltMask(SURFOBJ
* psoDest
,
728 SURFOBJ
* psoSource
, // unused
730 XLATEOBJ
* pxloRGB2Dest
,
733 POINTL
* pptlSource
, // unused
740 ULONG Background
, BrushColor
, NewColor
;
743 ASSERT(psoSource
== NULL
);
744 ASSERT(pptlSource
== NULL
);
746 dx
= prclDest
->right
- prclDest
->left
;
747 dy
= prclDest
->bottom
- prclDest
->top
;
751 BrushColor
= XLATEOBJ_iXlate(pxloBrush
, pbo
? pbo
->iSolidColor
: 0);
752 r
= (int)GetRValue(BrushColor
);
753 g
= (int)GetGValue(BrushColor
);
754 b
= (int)GetBValue(BrushColor
);
756 tMask
= (PBYTE
)psoMask
->pvScan0
+ (pptlMask
->y
* psoMask
->lDelta
) + pptlMask
->x
;
757 for (j
= 0; j
< dy
; j
++)
760 for (i
= 0; i
< dx
; i
++)
766 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
767 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, pbo
? pbo
->iSolidColor
: 0);
771 Background
= DIB_GetSource(psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
,
775 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
776 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
777 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
779 Background
= XLATEOBJ_iXlate(pxloRGB2Dest
, NewColor
);
780 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
781 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, Background
);
786 tMask
+= psoMask
->lDelta
;
798 EngMaskBitBlt(SURFOBJ
*psoDest
,
801 XLATEOBJ
*DestColorTranslation
,
802 XLATEOBJ
*SourceColorTranslation
,
816 INTENG_ENTER_LEAVE EnterLeaveSource
;
817 INTENG_ENTER_LEAVE EnterLeaveDest
;
825 POINTL AdjustedBrushOrigin
;
831 InputRect
.left
= pptlMask
->x
;
832 InputRect
.right
= pptlMask
->x
+ (DestRect
->right
- DestRect
->left
);
833 InputRect
.top
= pptlMask
->y
;
834 InputRect
.bottom
= pptlMask
->y
+ (DestRect
->bottom
- DestRect
->top
);
839 InputRect
.right
= DestRect
->right
- DestRect
->left
;
841 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
844 OutputRect
= *DestRect
;
845 if (NULL
!= ClipRegion
)
847 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
849 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
850 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
852 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
854 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
855 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
857 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
859 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
860 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
862 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
864 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
865 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
869 if (! IntEngEnter(&EnterLeaveSource
, psoMask
, &InputRect
, TRUE
, &Translate
, &psoInput
))
874 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
875 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
877 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
879 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
881 IntEngLeave(&EnterLeaveSource
);
885 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
887 IntEngLeave(&EnterLeaveSource
);
891 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
892 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
893 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
894 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
898 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
899 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
902 AdjustedBrushOrigin
= Translate
;
904 // Determine clipping type
905 if (ClipRegion
== (CLIPOBJ
*) NULL
)
907 clippingType
= DC_TRIVIAL
;
909 clippingType
= ClipRegion
->iDComplexity
;
912 switch (clippingType
)
915 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
916 Ret
= AlphaBltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
, SourceColorTranslation
,
917 &OutputRect
, NULL
, &InputPoint
, pbo
, &AdjustedBrushOrigin
);
919 Ret
= BltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
,
920 &OutputRect
, NULL
, &InputPoint
, pbo
, &AdjustedBrushOrigin
,
924 // Clip the blt to the clip rectangle
925 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
926 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
927 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
928 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
929 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
931 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
932 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
933 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
935 Ret
= AlphaBltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
, SourceColorTranslation
,
936 &CombinedRect
, NULL
, &Pt
, pbo
, &AdjustedBrushOrigin
);
940 Ret
= BltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
,
941 &CombinedRect
, NULL
, &Pt
, pbo
, &AdjustedBrushOrigin
, ROP4_MASK
);
947 if (psoOutput
== psoInput
)
949 if (OutputRect
.top
< InputPoint
.y
)
951 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
955 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
962 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
965 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
967 for (i
= 0; i
< RectEnum
.c
; i
++)
969 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
970 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
971 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
972 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
973 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
975 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
976 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
977 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
979 Ret
= AlphaBltMask(psoOutput
, NULL
, psoInput
,
980 DestColorTranslation
,
981 SourceColorTranslation
,
982 &CombinedRect
, NULL
, &Pt
, pbo
,
983 &AdjustedBrushOrigin
) && Ret
;
987 Ret
= BltMask(psoOutput
, NULL
, psoInput
,
988 DestColorTranslation
, &CombinedRect
, NULL
,
989 &Pt
, pbo
, &AdjustedBrushOrigin
,
1000 IntEngLeave(&EnterLeaveDest
);
1001 IntEngLeave(&EnterLeaveSource
);
1009 _Inout_ SURFOBJ
*psoDest
,
1010 _In_ SURFOBJ
*psoMask
,
1012 _In_ XLATEOBJ
*pxloDest
,
1013 _In_ XLATEOBJ
*pxloSource
,
1014 _In_ RECTL
*prclDest
,
1015 _In_ POINTL
*pptlMask
,
1017 _In_ POINTL
*pptlBrushOrg
)
1021 POINTL ptMask
= {0,0};
1028 /* Is this a 1 BPP mask? */
1029 if (psoMask
->iBitmapFormat
== BMF_1BPP
)
1031 /* Use IntEngBitBlt with an appropriate ROP4 */
1032 return IntEngBitBlt(psoDest
,
1045 ASSERT(psoMask
->iBitmapFormat
== BMF_8BPP
);
1052 /* Clip against the bounds of the clipping region so we won't try to write
1053 * outside the surface */
1056 /* Intersect with the clip bounds and check if everything was clipped */
1057 if (!RECTL_bIntersectRect(&rcDest
, prclDest
, &pco
->rclBounds
))
1062 /* Adjust the mask point */
1063 ptMask
.x
+= rcDest
.left
- prclDest
->left
;
1064 ptMask
.y
+= rcDest
.top
- prclDest
->top
;
1071 /* Check if the target surface is device managed */
1072 if (psoDest
->iType
!= STYPE_BITMAP
)
1076 rcTemp
.right
= rcDest
.right
- rcDest
.left
;
1077 rcTemp
.bottom
= rcDest
.bottom
- rcDest
.top
;
1079 /* Allocate a temporary surface */
1080 psurfTemp
= SURFACE_AllocSurface(STYPE_BITMAP
,
1083 psoDest
->iBitmapFormat
,
1088 if (psurfTemp
== NULL
)
1093 /* Copy the current target surface bits to the temp surface */
1094 ret
= EngCopyBits(&psurfTemp
->SurfObj
,
1103 /* Do the operation on the temp surface */
1104 ret
= EngMaskBitBlt(&psurfTemp
->SurfObj
,
1117 /* Copy the result back to the dest surface */
1118 ret
= EngCopyBits(psoDest
,
1119 &psurfTemp
->SurfObj
,
1126 /* Delete the temp surface */
1127 GDIOBJ_vDeleteObject(&psurfTemp
->BaseObject
);
1131 /* Do the operation on the target surface */
1132 ret
= EngMaskBitBlt(psoDest
,