2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI BitBlt Functions
5 * FILE: subsys/win32k/eng/bitblt.c
6 * PROGRAMER: Jason Filby
16 typedef BOOLEAN (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
19 XLATEOBJ
* ColorTranslation
,
27 static BOOLEAN APIENTRY
28 BltMask(SURFOBJ
* psoDest
,
29 SURFOBJ
* psoSource
, // unused
31 XLATEOBJ
* ColorTranslation
, // unused
33 POINTL
* pptlSource
, // unused
40 BYTE
*pjMskLine
, *pjMskCurrent
;
41 BYTE fjMaskBit0
, fjMaskBit
;
43 PEBRUSHOBJ pebo
= NULL
;
44 SURFOBJ
*psoPattern
= NULL
;
45 PSURFACE psurfPattern
;
46 ULONG PatternWidth
= 0, PatternHeight
= 0;
47 LONG PatternX0
= 0, PatternX
= 0, PatternY
= 0;
48 PFN_DIB_PutPixel fnDest_PutPixel
= NULL
;
49 PFN_DIB_GetPixel fnPattern_GetPixel
= NULL
;
58 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
60 pebo
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
62 psurfPattern
= SURFACE_LockSurface(pebo
->pbrush
->hbmPattern
);
63 if (psurfPattern
!= NULL
)
65 psoPattern
= &psurfPattern
->SurfObj
;
66 PatternWidth
= psoPattern
->sizlBitmap
.cx
;
67 PatternHeight
= psoPattern
->sizlBitmap
.cy
;
69 fnPattern_GetPixel
= DibFunctionsForBitmapFormat
[psoPattern
->iBitmapFormat
].DIB_GetPixel
;
74 pjMskLine
= (PBYTE
)psoMask
->pvScan0
+ pptlMask
->y
* psoMask
->lDelta
+ (pptlMask
->x
>> 3);
75 fjMaskBit0
= 0x80 >> (pptlMask
->x
& 0x07);
77 fnDest_PutPixel
= DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel
;
80 XlateObj
= pebo
? pebo
->XlateObject
: NULL
;
81 PatternY
= (prclDest
->top
- pptlBrush
->y
) % PatternHeight
;
84 PatternY
+= PatternHeight
;
86 PatternX0
= (prclDest
->left
- pptlBrush
->x
) % PatternWidth
;
89 PatternX0
+= PatternWidth
;
92 for (y
= prclDest
->top
; y
< prclDest
->bottom
; y
++)
94 pjMskCurrent
= pjMskLine
;
95 fjMaskBit
= fjMaskBit0
;
98 for (x
= prclDest
->left
; x
< prclDest
->right
; x
++)
100 if (*pjMskCurrent
& fjMaskBit
)
102 fnDest_PutPixel(psoDest
, x
, y
,
103 XLATEOBJ_iXlate(XlateObj
,
104 fnPattern_GetPixel(psoPattern
, PatternX
, PatternY
)));
106 fjMaskBit
= _rotr8(fjMaskBit
, 1);
107 pjMskCurrent
+= (fjMaskBit
>> 7);
109 PatternX
%= PatternWidth
;
111 pjMskLine
+= psoMask
->lDelta
;
113 PatternY
%= PatternHeight
;
118 Pattern
= pbo
? pbo
->iSolidColor
: 0;
119 for (y
= prclDest
->top
; y
< prclDest
->bottom
; y
++)
121 pjMskCurrent
= pjMskLine
;
122 fjMaskBit
= fjMaskBit0
;
124 for (x
= prclDest
->left
; x
< prclDest
->right
; x
++)
126 if (*pjMskCurrent
& fjMaskBit
)
128 fnDest_PutPixel(psoDest
, x
, y
, Pattern
);
130 fjMaskBit
= _rotr8(fjMaskBit
, 1);
131 pjMskCurrent
+= (fjMaskBit
>> 7);
133 pjMskLine
+= psoMask
->lDelta
;
138 SURFACE_UnlockSurface(psurfPattern
);
143 static BOOLEAN APIENTRY
144 BltPatCopy(SURFOBJ
* Dest
,
147 XLATEOBJ
* ColorTranslation
,
155 // These functions are assigned if we're working with a DIB
156 // The assigned functions depend on the bitsPerPixel of the DIB
158 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_ColorFill(Dest
, DestRect
, pbo
? pbo
->iSolidColor
: 0);
163 static BOOLEAN APIENTRY
164 CallDibBitBlt(SURFOBJ
* OutputObj
,
167 XLATEOBJ
* ColorTranslation
,
176 PEBRUSHOBJ GdiBrush
= NULL
;
177 SURFACE
*psurfPattern
;
180 BltInfo
.DestSurface
= OutputObj
;
181 BltInfo
.SourceSurface
= InputObj
;
182 BltInfo
.PatternSurface
= NULL
;
183 BltInfo
.XlateSourceToDest
= ColorTranslation
;
184 BltInfo
.DestRect
= *OutputRect
;
185 BltInfo
.SourcePoint
= *InputPoint
;
187 if (ROP3_TO_ROP4(SRCCOPY
) == Rop4
)
188 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
190 BltInfo
.XlatePatternToDest
= NULL
;
192 BltInfo
.BrushOrigin
= *BrushOrigin
;
196 if (ROP4_USES_PATTERN(Rop4
) && pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
198 GdiBrush
= CONTAINING_RECORD(pbo
, EBRUSHOBJ
, BrushObject
);
199 if ((psurfPattern
= SURFACE_LockSurface(GdiBrush
->pbrush
->hbmPattern
)))
201 BltInfo
.PatternSurface
= &psurfPattern
->SurfObj
;
205 /* FIXME - What to do here? */
207 BltInfo
.XlatePatternToDest
= GdiBrush
->XlateObject
;
214 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
217 if (psurfPattern
!= NULL
)
219 SURFACE_UnlockSurface(psurfPattern
);
225 INT __cdecl
abs(INT nm
);
242 IN POINTL
*pptlBrush
,
252 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
253 RtlCopyMemory(&rclTrg
,prclTrg
, sizeof(RECTL
));
255 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
256 RtlCopyMemory(&ptlSrc
, pptlSrc
, sizeof(POINTL
));
258 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
259 RtlCopyMemory(&ptlMask
, pptlMask
, sizeof(POINTL
));
261 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
262 RtlCopyMemory(&ptlBrush
, pptlBrush
, sizeof(POINTL
));
265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
267 _SEH2_YIELD(return FALSE
);
271 return EngBitBlt(psoTrg
, psoSrc
, psoMask
, pco
, pxlo
, &rclTrg
, &ptlSrc
, &ptlMask
, pbo
, &ptlBrush
, rop4
);
278 EngBitBlt(SURFOBJ
*DestObj
,
282 XLATEOBJ
*ColorTranslation
,
298 INTENG_ENTER_LEAVE EnterLeaveSource
;
299 INTENG_ENTER_LEAVE EnterLeaveDest
;
302 PBLTRECTFUNC BltRectFunc
;
310 POINTL AdjustedBrushOrigin
;
312 UsesSource
= ROP4_USES_SOURCE(Rop4
);
313 UsesPattern
= ROP4_USES_PATTERN(Rop4
);
316 /* Copy destination onto itself: nop */
320 OutputRect
= *DestRect
;
321 if (OutputRect
.right
< OutputRect
.left
)
323 OutputRect
.left
= DestRect
->right
;
324 OutputRect
.right
= DestRect
->left
;
326 if (OutputRect
.bottom
< OutputRect
.top
)
328 OutputRect
.left
= DestRect
->right
;
329 OutputRect
.right
= DestRect
->left
;
334 if (NULL
== SourcePoint
)
339 /* Make sure we don't try to copy anything outside the valid source
341 InputPoint
= *SourcePoint
;
342 if (InputPoint
.x
< 0)
344 OutputRect
.left
-= InputPoint
.x
;
347 if (InputPoint
.y
< 0)
349 OutputRect
.top
-= InputPoint
.y
;
352 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+
353 OutputRect
.right
- OutputRect
.left
)
355 OutputRect
.right
= OutputRect
.left
+
356 SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
358 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+
359 OutputRect
.bottom
- OutputRect
.top
)
361 OutputRect
.bottom
= OutputRect
.top
+
362 SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
365 InputRect
.left
= InputPoint
.x
;
366 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
367 InputRect
.top
= InputPoint
.y
;
368 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
370 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
,
371 &Translate
, &InputObj
))
376 InputPoint
.x
+= Translate
.x
;
377 InputPoint
.y
+= Translate
.y
;
382 InputRect
.right
= DestRect
->right
- DestRect
->left
;
384 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
387 if (NULL
!= ClipRegion
)
389 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
391 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
392 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
393 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
395 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
397 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
398 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
400 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
402 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
403 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
404 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
406 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
408 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
409 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
413 /* Check for degenerate case: if height or width of OutputRect is 0 pixels
414 there's nothing to do */
415 if (OutputRect
.right
<= OutputRect
.left
||
416 OutputRect
.bottom
<= OutputRect
.top
)
420 IntEngLeave(&EnterLeaveSource
);
425 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
,
430 IntEngLeave(&EnterLeaveSource
);
435 OutputRect
.left
+= Translate
.x
;
436 OutputRect
.right
+= Translate
.x
;
437 OutputRect
.top
+= Translate
.y
;
438 OutputRect
.bottom
+= Translate
.y
;
442 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
443 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
447 AdjustedBrushOrigin
= Translate
;
450 /* Determine clipping type */
451 if (ClipRegion
== (CLIPOBJ
*) NULL
)
453 clippingType
= DC_TRIVIAL
;
457 clippingType
= ClipRegion
->iDComplexity
;
462 BltRectFunc
= BltMask
;
464 else if (ROP3_TO_ROP4(PATCOPY
) == Rop4
)
466 if (pbo
&& pbo
->iSolidColor
== 0xFFFFFFFF)
467 BltRectFunc
= CallDibBitBlt
;
469 BltRectFunc
= BltPatCopy
;
473 BltRectFunc
= CallDibBitBlt
;
477 switch (clippingType
)
480 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
481 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
,
482 &AdjustedBrushOrigin
, Rop4
);
485 /* Clip the blt to the clip rectangle */
486 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
487 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
488 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
489 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
490 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
492 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
493 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
494 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
495 &CombinedRect
, &Pt
, MaskOrigin
, pbo
,
496 &AdjustedBrushOrigin
, Rop4
);
501 if (OutputObj
== InputObj
)
503 if (OutputRect
.top
< InputPoint
.y
)
505 Direction
= OutputRect
.left
< InputPoint
.x
?
506 CD_RIGHTDOWN
: CD_LEFTDOWN
;
510 Direction
= OutputRect
.left
< InputPoint
.x
?
511 CD_RIGHTUP
: CD_LEFTUP
;
518 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
521 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
524 for (i
= 0; i
< RectEnum
.c
; i
++)
526 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
527 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
528 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
529 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
530 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
532 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
533 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
534 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
,
535 ColorTranslation
, &CombinedRect
, &Pt
,
536 MaskOrigin
, pbo
, &AdjustedBrushOrigin
,
546 IntEngLeave(&EnterLeaveDest
);
549 IntEngLeave(&EnterLeaveSource
);
556 IntEngBitBltEx(SURFOBJ
*psoDest
,
560 XLATEOBJ
*ColorTranslation
,
570 RECTL InputClippedRect
;
575 SURFACE
*psurfSource
= NULL
;
580 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
583 InputClippedRect
= *DestRect
;
584 if (InputClippedRect
.right
< InputClippedRect
.left
)
586 InputClippedRect
.left
= DestRect
->right
;
587 InputClippedRect
.right
= DestRect
->left
;
589 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
591 InputClippedRect
.top
= DestRect
->bottom
;
592 InputClippedRect
.bottom
= DestRect
->top
;
594 UsesSource
= ROP4_USES_SOURCE(Rop4
);
597 if (NULL
== SourcePoint
|| NULL
== psoSource
)
601 InputPoint
= *SourcePoint
;
603 /* Make sure we don't try to copy anything outside the valid source
605 if (InputPoint
.x
< 0)
607 InputClippedRect
.left
-= InputPoint
.x
;
610 if (InputPoint
.y
< 0)
612 InputClippedRect
.top
-= InputPoint
.y
;
615 if (psoSource
->sizlBitmap
.cx
< InputPoint
.x
+
616 InputClippedRect
.right
-
617 InputClippedRect
.left
)
619 InputClippedRect
.right
= InputClippedRect
.left
+
620 psoSource
->sizlBitmap
.cx
- InputPoint
.x
;
622 if (psoSource
->sizlBitmap
.cy
< InputPoint
.y
+
623 InputClippedRect
.bottom
-
624 InputClippedRect
.top
)
626 InputClippedRect
.bottom
= InputClippedRect
.top
+
627 psoSource
->sizlBitmap
.cy
- InputPoint
.y
;
630 if (InputClippedRect
.right
< InputClippedRect
.left
||
631 InputClippedRect
.bottom
< InputClippedRect
.top
)
633 /* Everything clipped away, nothing to do */
638 /* Clip against the bounds of the clipping region so we won't try to write
639 * outside the surface */
640 if (NULL
!= ClipRegion
)
642 if (!RECTL_bIntersectRect(&OutputRect
, &InputClippedRect
,
643 &ClipRegion
->rclBounds
))
647 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
648 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
652 OutputRect
= InputClippedRect
;
657 SURFACE_LockBitmapBits(psurfDest
);
661 if (psoSource
!= psoDest
)
663 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
664 SURFACE_LockBitmapBits(psurfSource
);
666 MouseSafetyOnDrawStart(psoSource
, InputPoint
.x
, InputPoint
.y
,
667 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
668 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
670 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
671 OutputRect
.right
, OutputRect
.bottom
);
677 /* Call the driver's DrvBitBlt if available */
678 if (psurfDest
->flHooks
& HOOK_BITBLT
)
680 ret
= GDIDEVFUNCS(psoDest
).BitBlt(
681 psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
682 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
, BrushOrigin
,
688 ret
= EngBitBlt(psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
689 &OutputRect
, &InputPoint
, MaskOrigin
, pbo
, BrushOrigin
,
695 MouseSafetyOnDrawEnd(psoDest
);
698 MouseSafetyOnDrawEnd(psoSource
);
699 if (psoSource
!= psoDest
)
701 SURFACE_UnlockBitmapBits(psurfSource
);
705 SURFACE_UnlockBitmapBits(psurfDest
);
712 /**** REACTOS FONT RENDERING CODE *********************************************/
714 /* renders the alpha mask bitmap */
715 static BOOLEAN APIENTRY
716 AlphaBltMask(SURFOBJ
* psoDest
,
717 SURFOBJ
* psoSource
, // unused
719 XLATEOBJ
* ColorTranslation
,
720 XLATEOBJ
* SrcColorTranslation
,
722 POINTL
* pptlSource
, // unused
729 ULONG Background
, BrushColor
, NewColor
;
732 dx
= prclDest
->right
- prclDest
->left
;
733 dy
= prclDest
->bottom
- prclDest
->top
;
737 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, pbo
? pbo
->iSolidColor
: 0);
738 r
= (int)GetRValue(BrushColor
);
739 g
= (int)GetGValue(BrushColor
);
740 b
= (int)GetBValue(BrushColor
);
742 tMask
= (PBYTE
)psoMask
->pvScan0
+ (pptlMask
->y
* psoMask
->lDelta
) + pptlMask
->x
;
743 for (j
= 0; j
< dy
; j
++)
746 for (i
= 0; i
< dx
; i
++)
752 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
753 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, pbo
? pbo
->iSolidColor
: 0);
757 Background
= DIB_GetSource(psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
,
758 SrcColorTranslation
);
761 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
762 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
763 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
765 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
766 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
767 psoDest
, prclDest
->left
+ i
, prclDest
->top
+ j
, Background
);
772 tMask
+= psoMask
->lDelta
;
784 EngMaskBitBlt(SURFOBJ
*psoDest
,
787 XLATEOBJ
*DestColorTranslation
,
788 XLATEOBJ
*SourceColorTranslation
,
802 INTENG_ENTER_LEAVE EnterLeaveSource
;
803 INTENG_ENTER_LEAVE EnterLeaveDest
;
811 POINTL AdjustedBrushOrigin
;
817 InputRect
.left
= pptlMask
->x
;
818 InputRect
.right
= pptlMask
->x
+ (DestRect
->right
- DestRect
->left
);
819 InputRect
.top
= pptlMask
->y
;
820 InputRect
.bottom
= pptlMask
->y
+ (DestRect
->bottom
- DestRect
->top
);
825 InputRect
.right
= DestRect
->right
- DestRect
->left
;
827 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
830 OutputRect
= *DestRect
;
831 if (NULL
!= ClipRegion
)
833 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
835 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
836 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
838 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
840 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
841 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
843 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
845 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
846 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
848 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
850 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
851 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
855 if (! IntEngEnter(&EnterLeaveSource
, psoMask
, &InputRect
, TRUE
, &Translate
, &psoInput
))
860 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
861 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
863 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
865 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
867 IntEngLeave(&EnterLeaveSource
);
871 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
873 IntEngLeave(&EnterLeaveSource
);
877 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
878 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
879 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
880 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
884 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
885 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
888 AdjustedBrushOrigin
= Translate
;
890 // Determine clipping type
891 if (ClipRegion
== (CLIPOBJ
*) NULL
)
893 clippingType
= DC_TRIVIAL
;
895 clippingType
= ClipRegion
->iDComplexity
;
898 switch (clippingType
)
901 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
902 Ret
= AlphaBltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
, SourceColorTranslation
,
903 &OutputRect
, &InputPoint
, pptlMask
, pbo
, &AdjustedBrushOrigin
);
905 Ret
= BltMask(psoOutput
, NULL
, psoInput
, DestColorTranslation
,
906 &OutputRect
, &InputPoint
, pptlMask
, pbo
, &AdjustedBrushOrigin
,
910 // Clip the blt to the clip rectangle
911 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
912 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
913 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
914 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
915 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
917 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
918 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
919 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
921 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
, SourceColorTranslation
,
922 &CombinedRect
, &Pt
, pptlMask
, pbo
, &AdjustedBrushOrigin
);
926 Ret
= BltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
,
927 &CombinedRect
, &Pt
, pptlMask
, pbo
, &AdjustedBrushOrigin
, R4_MASK
);
933 if (psoOutput
== psoInput
)
935 if (OutputRect
.top
< InputPoint
.y
)
937 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
941 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
948 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
951 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
953 for (i
= 0; i
< RectEnum
.c
; i
++)
955 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
956 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
957 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
958 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
959 if (RECTL_bIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
961 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
962 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
963 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
965 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
,
966 DestColorTranslation
,
967 SourceColorTranslation
,
968 &CombinedRect
, &Pt
, pptlMask
, pbo
,
969 &AdjustedBrushOrigin
) && Ret
;
973 Ret
= BltMask(psoOutput
, psoInput
, psoMask
,
974 DestColorTranslation
, &CombinedRect
, &Pt
,
975 pptlMask
, pbo
, &AdjustedBrushOrigin
,
986 IntEngLeave(&EnterLeaveDest
);
987 IntEngLeave(&EnterLeaveSource
);
993 IntEngMaskBlt(SURFOBJ
*psoDest
,
996 XLATEOBJ
*DestColorTranslation
,
997 XLATEOBJ
*SourceColorTranslation
,
1001 POINTL
*BrushOrigin
)
1012 InputPoint
= *pptlMask
;
1015 /* Clip against the bounds of the clipping region so we won't try to write
1016 * outside the surface */
1017 if (NULL
!= ClipRegion
)
1019 if (!RECTL_bIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1023 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1024 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1028 OutputRect
= *DestRect
;
1031 /* No success yet */
1034 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1036 SURFACE_LockBitmapBits(psurfDest
);
1037 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
1038 OutputRect
.right
, OutputRect
.bottom
);
1040 /* Dummy BitBlt to let driver know that it should flush its changes.
1041 This should really be done using a call to DrvSynchronizeSurface,
1042 but the VMware driver doesn't hook that call. */
1043 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1044 DestRect
, pptlMask
, pptlMask
, pbo
, BrushOrigin
,
1047 ret
= EngMaskBitBlt(psoDest
, psoMask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1048 &OutputRect
, &InputPoint
, pbo
, BrushOrigin
);
1050 /* Dummy BitBlt to let driver know that something has changed. */
1051 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1052 DestRect
, pptlMask
, pptlMask
, pbo
, BrushOrigin
,
1055 MouseSafetyOnDrawEnd(psoDest
);
1056 SURFACE_UnlockBitmapBits(psurfDest
);