2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: GDI BitBlt Functions
24 * FILE: subsys/win32k/eng/bitblt.c
25 * PROGRAMER: Jason Filby
35 typedef BOOLEAN (APIENTRY
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
38 XLATEOBJ
* ColorTranslation
,
45 typedef BOOLEAN (APIENTRY
*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
49 XLATEOBJ
* ColorTranslation
,
57 BOOL APIENTRY
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
59 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
61 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
62 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
64 if (prcDst
->left
< prcDst
->right
)
66 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
67 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
69 if (prcDst
->top
< prcDst
->bottom
)
80 static BOOLEAN APIENTRY
81 BltMask(SURFOBJ
* Dest
,
84 XLATEOBJ
* ColorTranslation
,
92 LONG i
, j
, dx
, dy
, c8
;
94 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
96 PGDIBRUSHINST GdiBrush
= NULL
;
97 SURFOBJ
*psoPattern
= NULL
;
98 PSURFACE psurfPattern
;
99 ULONG PatternWidth
= 0, PatternHeight
= 0, PatternY
= 0;
106 dx
= DestRect
->right
- DestRect
->left
;
107 dy
= DestRect
->bottom
- DestRect
->top
;
109 if (Brush
&& Brush
->iSolidColor
== 0xFFFFFFFF)
111 GdiBrush
= CONTAINING_RECORD(
116 psurfPattern
= SURFACE_LockSurface(GdiBrush
->GdiBrushObject
->hbmPattern
);
117 if (psurfPattern
!= NULL
)
119 psoPattern
= &psurfPattern
->SurfObj
;
120 PatternWidth
= psoPattern
->sizlBitmap
.cx
;
121 PatternHeight
= psoPattern
->sizlBitmap
.cy
;
127 tMask
= (PBYTE
)Mask
->pvScan0
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
128 for (j
= 0; j
< dy
; j
++)
131 c8
= SourcePoint
->x
& 0x07;
133 if (psurfPattern
!= NULL
)
134 PatternY
= (DestRect
->top
+ j
) % PatternHeight
;
136 for (i
= 0; i
< dx
; i
++)
138 if (0 != (*lMask
& maskbit
[c8
]))
140 if (psurfPattern
== NULL
)
142 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
143 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
? Brush
->iSolidColor
: 0);
147 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
148 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
149 DIB_GetSource(psoPattern
, (DestRect
->left
+ i
) % PatternWidth
, PatternY
, GdiBrush
? GdiBrush
->XlateObject
: NULL
));
159 tMask
+= Mask
->lDelta
;
162 if (psurfPattern
!= NULL
)
163 SURFACE_UnlockSurface(psurfPattern
);
168 static BOOLEAN APIENTRY
169 BltPatCopy(SURFOBJ
* Dest
,
172 XLATEOBJ
* ColorTranslation
,
180 // These functions are assigned if we're working with a DIB
181 // The assigned functions depend on the bitsPerPixel of the DIB
183 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_ColorFill(Dest
, DestRect
, Brush
? Brush
->iSolidColor
: 0);
188 static BOOLEAN APIENTRY
189 CallDibBitBlt(SURFOBJ
* OutputObj
,
192 XLATEOBJ
* ColorTranslation
,
201 PGDIBRUSHINST GdiBrush
= NULL
;
202 SURFACE
*psurfPattern
;
205 BltInfo
.DestSurface
= OutputObj
;
206 BltInfo
.SourceSurface
= InputObj
;
207 BltInfo
.PatternSurface
= NULL
;
208 BltInfo
.XlateSourceToDest
= ColorTranslation
;
209 BltInfo
.DestRect
= *OutputRect
;
210 BltInfo
.SourcePoint
= *InputPoint
;
212 if (ROP3_TO_ROP4(SRCCOPY
) == Rop4
)
213 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
215 BltInfo
.XlatePatternToDest
= NULL
;
216 BltInfo
.Brush
= Brush
;
217 BltInfo
.BrushOrigin
= *BrushOrigin
;
221 if (ROP4_USES_PATTERN(Rop4
) && Brush
&& Brush
->iSolidColor
== 0xFFFFFFFF)
223 GdiBrush
= CONTAINING_RECORD(Brush
, GDIBRUSHINST
, BrushObject
);
224 if ((psurfPattern
= SURFACE_LockSurface(GdiBrush
->GdiBrushObject
->hbmPattern
)))
226 BltInfo
.PatternSurface
= &psurfPattern
->SurfObj
;
230 /* FIXME - What to do here? */
232 BltInfo
.XlatePatternToDest
= GdiBrush
->XlateObject
;
239 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
242 if (psurfPattern
!= NULL
)
244 SURFACE_UnlockSurface(psurfPattern
);
250 INT __cdecl
abs(INT nm
);
267 IN POINTL
*pptlBrush
,
277 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
278 RtlCopyMemory(&rclTrg
,prclTrg
, sizeof(RECTL
));
280 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
281 RtlCopyMemory(&ptlSrc
, pptlSrc
, sizeof(POINTL
));
283 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
284 RtlCopyMemory(&ptlMask
, pptlMask
, sizeof(POINTL
));
286 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
287 RtlCopyMemory(&ptlBrush
, pptlBrush
, sizeof(POINTL
));
290 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
292 _SEH2_YIELD(return FALSE
);
296 return EngBitBlt(psoTrg
, psoSrc
, psoMask
, pco
, pxlo
, &rclTrg
, &ptlSrc
, &ptlMask
, pbo
, &ptlBrush
, rop4
);
303 EngBitBlt(SURFOBJ
*DestObj
,
307 XLATEOBJ
*ColorTranslation
,
323 INTENG_ENTER_LEAVE EnterLeaveSource
;
324 INTENG_ENTER_LEAVE EnterLeaveDest
;
327 PBLTRECTFUNC BltRectFunc
;
335 POINTL AdjustedBrushOrigin
;
337 UsesSource
= ROP4_USES_SOURCE(Rop4
);
338 UsesPattern
= ROP4_USES_PATTERN(Rop4
);
341 /* Copy destination onto itself: nop */
345 OutputRect
= *DestRect
;
346 if (OutputRect
.right
< OutputRect
.left
)
348 OutputRect
.left
= DestRect
->right
;
349 OutputRect
.right
= DestRect
->left
;
351 if (OutputRect
.bottom
< OutputRect
.top
)
353 OutputRect
.left
= DestRect
->right
;
354 OutputRect
.right
= DestRect
->left
;
359 if (NULL
== SourcePoint
)
364 /* Make sure we don't try to copy anything outside the valid source
366 InputPoint
= *SourcePoint
;
367 if (InputPoint
.x
< 0)
369 OutputRect
.left
-= InputPoint
.x
;
372 if (InputPoint
.y
< 0)
374 OutputRect
.top
-= InputPoint
.y
;
377 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+
378 OutputRect
.right
- OutputRect
.left
)
380 OutputRect
.right
= OutputRect
.left
+
381 SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
383 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+
384 OutputRect
.bottom
- OutputRect
.top
)
386 OutputRect
.bottom
= OutputRect
.top
+
387 SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
390 InputRect
.left
= InputPoint
.x
;
391 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
392 InputRect
.top
= InputPoint
.y
;
393 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
395 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
,
396 &Translate
, &InputObj
))
401 InputPoint
.x
+= Translate
.x
;
402 InputPoint
.y
+= Translate
.y
;
407 InputRect
.right
= DestRect
->right
- DestRect
->left
;
409 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
412 if (NULL
!= ClipRegion
)
414 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
416 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
417 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
418 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
420 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
422 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
423 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
425 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
427 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
428 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
429 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
431 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
433 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
434 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
438 /* Check for degenerate case: if height or width of OutputRect is 0 pixels
439 there's nothing to do */
440 if (OutputRect
.right
<= OutputRect
.left
||
441 OutputRect
.bottom
<= OutputRect
.top
)
445 IntEngLeave(&EnterLeaveSource
);
450 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
,
455 IntEngLeave(&EnterLeaveSource
);
460 OutputRect
.left
+= Translate
.x
;
461 OutputRect
.right
+= Translate
.x
;
462 OutputRect
.top
+= Translate
.y
;
463 OutputRect
.bottom
+= Translate
.y
;
467 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
468 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
472 AdjustedBrushOrigin
= Translate
;
475 /* Determine clipping type */
476 if (ClipRegion
== (CLIPOBJ
*) NULL
)
478 clippingType
= DC_TRIVIAL
;
482 clippingType
= ClipRegion
->iDComplexity
;
487 BltRectFunc
= BltMask
;
489 else if (ROP3_TO_ROP4(PATCOPY
) == Rop4
)
491 if (Brush
&& Brush
->iSolidColor
== 0xFFFFFFFF)
492 BltRectFunc
= CallDibBitBlt
;
494 BltRectFunc
= BltPatCopy
;
498 BltRectFunc
= CallDibBitBlt
;
502 switch (clippingType
)
505 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
506 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
,
507 &AdjustedBrushOrigin
, Rop4
);
510 /* Clip the blt to the clip rectangle */
511 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
512 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
513 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
514 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
515 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
517 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
518 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
519 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
520 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
521 &AdjustedBrushOrigin
, Rop4
);
526 if (OutputObj
== InputObj
)
528 if (OutputRect
.top
< InputPoint
.y
)
530 Direction
= OutputRect
.left
< InputPoint
.x
?
531 CD_RIGHTDOWN
: CD_LEFTDOWN
;
535 Direction
= OutputRect
.left
< InputPoint
.x
?
536 CD_RIGHTUP
: CD_LEFTUP
;
543 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
546 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
549 for (i
= 0; i
< RectEnum
.c
; i
++)
551 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
552 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
553 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
554 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
555 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
557 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
558 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
559 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
,
560 ColorTranslation
, &CombinedRect
, &Pt
,
561 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
571 IntEngLeave(&EnterLeaveDest
);
574 IntEngLeave(&EnterLeaveSource
);
581 IntEngBitBltEx(SURFOBJ
*psoDest
,
585 XLATEOBJ
*ColorTranslation
,
595 RECTL InputClippedRect
;
600 SURFACE
*psurfSource
= NULL
;
605 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
608 InputClippedRect
= *DestRect
;
609 if (InputClippedRect
.right
< InputClippedRect
.left
)
611 InputClippedRect
.left
= DestRect
->right
;
612 InputClippedRect
.right
= DestRect
->left
;
614 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
616 InputClippedRect
.top
= DestRect
->bottom
;
617 InputClippedRect
.bottom
= DestRect
->top
;
619 UsesSource
= ROP4_USES_SOURCE(Rop4
);
622 if (NULL
== SourcePoint
|| NULL
== psoSource
)
626 InputPoint
= *SourcePoint
;
628 /* Make sure we don't try to copy anything outside the valid source
630 if (InputPoint
.x
< 0)
632 InputClippedRect
.left
-= InputPoint
.x
;
635 if (InputPoint
.y
< 0)
637 InputClippedRect
.top
-= InputPoint
.y
;
640 if (psoSource
->sizlBitmap
.cx
< InputPoint
.x
+
641 InputClippedRect
.right
-
642 InputClippedRect
.left
)
644 InputClippedRect
.right
= InputClippedRect
.left
+
645 psoSource
->sizlBitmap
.cx
- InputPoint
.x
;
647 if (psoSource
->sizlBitmap
.cy
< InputPoint
.y
+
648 InputClippedRect
.bottom
-
649 InputClippedRect
.top
)
651 InputClippedRect
.bottom
= InputClippedRect
.top
+
652 psoSource
->sizlBitmap
.cy
- InputPoint
.y
;
655 if (InputClippedRect
.right
< InputClippedRect
.left
||
656 InputClippedRect
.bottom
< InputClippedRect
.top
)
658 /* Everything clipped away, nothing to do */
663 /* Clip against the bounds of the clipping region so we won't try to write
664 * outside the surface */
665 if (NULL
!= ClipRegion
)
667 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
668 &ClipRegion
->rclBounds
))
672 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
673 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
677 OutputRect
= InputClippedRect
;
682 SURFACE_LockBitmapBits(psurfDest
);
686 if (psoSource
!= psoDest
)
688 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
689 SURFACE_LockBitmapBits(psurfSource
);
691 MouseSafetyOnDrawStart(psoSource
, InputPoint
.x
, InputPoint
.y
,
692 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
693 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
695 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
696 OutputRect
.right
, OutputRect
.bottom
);
702 /* Call the driver's DrvBitBlt if available */
703 if (psurfDest
->flHooks
& HOOK_BITBLT
)
705 ret
= GDIDEVFUNCS(psoDest
).BitBlt(
706 psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
707 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
713 ret
= EngBitBlt(psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
714 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
720 MouseSafetyOnDrawEnd(psoDest
);
723 MouseSafetyOnDrawEnd(psoSource
);
724 if (psoSource
!= psoDest
)
726 SURFACE_UnlockBitmapBits(psurfSource
);
730 SURFACE_UnlockBitmapBits(psurfDest
);
736 static BOOLEAN APIENTRY
737 CallDibStretchBlt(SURFOBJ
* psoDest
,
741 XLATEOBJ
* ColorTranslation
,
749 POINTL RealBrushOrigin
;
750 if (BrushOrigin
== NULL
)
752 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
756 RealBrushOrigin
= *BrushOrigin
;
758 return DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_StretchBlt(
759 psoDest
, psoSource
, OutputRect
, InputRect
, MaskOrigin
, Brush
, &RealBrushOrigin
, ClipRegion
, ColorTranslation
, Rop4
);
767 IN SURFOBJ
*psoSource
,
769 IN CLIPOBJ
*ClipRegion
,
770 IN XLATEOBJ
*ColorTranslation
,
771 IN COLORADJUSTMENT
*pca
,
772 IN POINTL
*BrushOrigin
,
775 IN POINTL
*MaskOrigin
,
786 ProbeForRead(pca
, sizeof(COLORADJUSTMENT
), 1);
787 RtlCopyMemory(&ca
,pca
, sizeof(COLORADJUSTMENT
));
789 ProbeForRead(BrushOrigin
, sizeof(POINTL
), 1);
790 RtlCopyMemory(&lBrushOrigin
, BrushOrigin
, sizeof(POINTL
));
792 ProbeForRead(prclDest
, sizeof(RECTL
), 1);
793 RtlCopyMemory(&rclDest
, prclDest
, sizeof(RECTL
));
795 ProbeForRead(prclSrc
, sizeof(RECTL
), 1);
796 RtlCopyMemory(&rclSrc
, prclSrc
, sizeof(RECTL
));
798 ProbeForRead(MaskOrigin
, sizeof(POINTL
), 1);
799 RtlCopyMemory(&lMaskOrigin
, MaskOrigin
, sizeof(POINTL
));
802 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
804 _SEH2_YIELD(return FALSE
);
808 return EngStretchBlt(psoDest
, psoSource
, Mask
, ClipRegion
, ColorTranslation
, &ca
, &lBrushOrigin
, &rclDest
, &rclSrc
, &lMaskOrigin
, Mode
);
818 IN SURFOBJ
*psoSource
,
820 IN CLIPOBJ
*ClipRegion
,
821 IN XLATEOBJ
*ColorTranslation
,
822 IN COLORADJUSTMENT
*pca
,
823 IN POINTL
*BrushOrigin
,
826 IN POINTL
*MaskOrigin
,
834 INTENG_ENTER_LEAVE EnterLeaveSource
;
835 INTENG_ENTER_LEAVE EnterLeaveDest
;
838 PSTRETCHRECTFUNC BltRectFunc
;
840 POINTL AdjustedBrushOrigin
;
841 BOOL UsesSource
= ROP4_USES_SOURCE(ROP4
);
845 /* Copy destination onto itself: nop */
849 OutputRect
= *prclDest
;
850 if (OutputRect
.right
< OutputRect
.left
)
852 OutputRect
.left
= prclDest
->right
;
853 OutputRect
.right
= prclDest
->left
;
855 if (OutputRect
.bottom
< OutputRect
.top
)
857 OutputRect
.left
= prclDest
->right
;
858 OutputRect
.right
= prclDest
->left
;
861 InputRect
= *prclSrc
;
869 /* Make sure we don't try to copy anything outside the valid source region */
870 if (InputRect
.left
< 0)
872 OutputRect
.left
-= InputRect
.left
;
875 if (InputRect
.top
< 0)
877 OutputRect
.top
-= InputRect
.top
;
881 if (! IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
,
882 &Translate
, &psoInput
))
887 InputRect
.left
+= Translate
.x
;
888 InputRect
.right
+= Translate
.x
;
889 InputRect
.top
+= Translate
.y
;
890 InputRect
.bottom
+= Translate
.y
;
893 if (NULL
!= ClipRegion
)
895 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
897 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
898 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
900 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
902 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
903 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
905 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
907 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
908 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
910 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
912 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
913 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
917 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
919 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
923 IntEngLeave(&EnterLeaveSource
);
928 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
932 IntEngLeave(&EnterLeaveSource
);
937 OutputRect
.left
+= Translate
.x
;
938 OutputRect
.right
+= Translate
.x
;
939 OutputRect
.top
+= Translate
.y
;
940 OutputRect
.bottom
+= Translate
.y
;
944 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
945 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
949 AdjustedBrushOrigin
= Translate
;
954 //BltRectFunc = BltMask;
955 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
956 IntEngLeave(&EnterLeaveDest
);
959 IntEngLeave(&EnterLeaveSource
);
965 BltRectFunc
= CallDibStretchBlt
;
968 Ret
= (*BltRectFunc
)(psoOutput
, psoInput
, Mask
, ClipRegion
,
969 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
970 Brush
, &AdjustedBrushOrigin
, ROP4
);
972 IntEngLeave(&EnterLeaveDest
);
975 IntEngLeave(&EnterLeaveSource
);
988 IN SURFOBJ
*psoSource
,
990 IN CLIPOBJ
*ClipRegion
,
991 IN XLATEOBJ
*ColorTranslation
,
992 IN COLORADJUSTMENT
*pca
,
993 IN POINTL
*BrushOrigin
,
996 IN POINTL
*MaskOrigin
,
999 return EngStretchBltROP(
1016 IntEngStretchBlt(SURFOBJ
*psoDest
,
1019 CLIPOBJ
*ClipRegion
,
1020 XLATEOBJ
*ColorTranslation
,
1023 POINTL
*pMaskOrigin
,
1025 POINTL
*BrushOrigin
,
1032 SURFACE
*psurfSource
= NULL
;
1033 RECTL InputClippedRect
;
1036 BOOL UsesSource
= ROP4_USES_SOURCE(ROP
);
1037 LONG InputClWidth
, InputClHeight
, InputWidth
, InputHeight
;
1040 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1044 InputClippedRect
= *DestRect
;
1045 if (InputClippedRect
.right
< InputClippedRect
.left
)
1047 InputClippedRect
.left
= DestRect
->right
;
1048 InputClippedRect
.right
= DestRect
->left
;
1050 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
1052 InputClippedRect
.top
= DestRect
->bottom
;
1053 InputClippedRect
.bottom
= DestRect
->top
;
1058 if (NULL
== SourceRect
|| NULL
== psoSource
)
1062 InputRect
= *SourceRect
;
1064 /* Make sure we don't try to copy anything outside the valid source region */
1065 if (InputRect
.left
< 0)
1067 InputClippedRect
.left
-= InputRect
.left
;
1070 if (InputRect
.top
< 0)
1072 InputClippedRect
.top
-= InputRect
.top
;
1076 if (InputClippedRect
.right
< InputClippedRect
.left
||
1077 InputClippedRect
.bottom
< InputClippedRect
.top
)
1079 /* Everything clipped away, nothing to do */
1086 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
1087 &ClipRegion
->rclBounds
))
1091 /* Update source rect */
1092 InputClWidth
= InputClippedRect
.right
- InputClippedRect
.left
;
1093 InputClHeight
= InputClippedRect
.bottom
- InputClippedRect
.top
;
1094 InputWidth
= InputRect
.right
- InputRect
.left
;
1095 InputHeight
= InputRect
.bottom
- InputRect
.top
;
1097 InputRect
.left
+= (InputWidth
* (OutputRect
.left
- InputClippedRect
.left
)) / InputClWidth
;
1098 InputRect
.right
-= (InputWidth
* (InputClippedRect
.right
- OutputRect
.right
)) / InputClWidth
;
1099 InputRect
.top
+= (InputHeight
* (OutputRect
.top
- InputClippedRect
.top
)) / InputClHeight
;
1100 InputRect
.bottom
-= (InputHeight
* (InputClippedRect
.bottom
- OutputRect
.bottom
)) / InputClHeight
;
1104 OutputRect
= InputClippedRect
;
1107 if (pMaskOrigin
!= NULL
)
1109 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
1112 /* No success yet */
1114 SURFACE_LockBitmapBits(psurfDest
);
1115 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
1116 OutputRect
.right
, OutputRect
.bottom
);
1120 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
1121 if (psoSource
!= psoDest
)
1123 SURFACE_LockBitmapBits(psurfSource
);
1125 MouseSafetyOnDrawStart(psoSource
, InputRect
.left
, InputRect
.top
,
1126 InputRect
.right
, InputRect
.bottom
);
1129 /* Prepare color adjustment */
1131 /* Call the driver's DrvStretchBlt if available */
1132 if (psurfDest
->flHooks
& HOOK_STRETCHBLT
)
1134 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm ) */
1135 // FIXME: MaskOrigin is always NULL !
1136 ret
= GDIDEVFUNCS(psoDest
).StretchBlt(
1137 psoDest
, (UsesSource
) ? psoSource
: NULL
, MaskSurf
, ClipRegion
, ColorTranslation
,
1138 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, ROP
);
1143 // FIXME: see previous fixme
1144 ret
= EngStretchBltROP(psoDest
, psoSource
, MaskSurf
, ClipRegion
, ColorTranslation
,
1145 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, COLORONCOLOR
, Brush
, ROP
);
1150 MouseSafetyOnDrawEnd(psoSource
);
1151 if (psoSource
!= psoDest
)
1153 SURFACE_UnlockBitmapBits(psurfSource
);
1156 MouseSafetyOnDrawEnd(psoDest
);
1157 SURFACE_UnlockBitmapBits(psurfDest
);
1168 NtGdiEngAlphaBlend(IN SURFOBJ
*psoDest
,
1169 IN SURFOBJ
*psoSource
,
1170 IN CLIPOBJ
*ClipRegion
,
1171 IN XLATEOBJ
*ColorTranslation
,
1172 IN PRECTL upDestRect
,
1173 IN PRECTL upSourceRect
,
1174 IN BLENDOBJ
*BlendObj
)
1181 ProbeForRead(upDestRect
, sizeof(RECTL
), 1);
1182 RtlCopyMemory(&DestRect
,upDestRect
, sizeof(RECTL
));
1184 ProbeForRead(upSourceRect
, sizeof(RECTL
), 1);
1185 RtlCopyMemory(&SourceRect
, upSourceRect
, sizeof(RECTL
));
1188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1190 _SEH2_YIELD(return FALSE
);
1194 return EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
, &DestRect
, &SourceRect
, BlendObj
);
1202 EngAlphaBlend(IN SURFOBJ
*psoDest
,
1203 IN SURFOBJ
*psoSource
,
1204 IN CLIPOBJ
*ClipRegion
,
1205 IN XLATEOBJ
*ColorTranslation
,
1207 IN PRECTL SourceRect
,
1208 IN BLENDOBJ
*BlendObj
)
1210 RECTL SourceStretchedRect
;
1211 SIZEL SourceStretchedSize
;
1212 HBITMAP SourceStretchedBitmap
= 0;
1213 SURFOBJ
* SourceStretchedObj
= NULL
;
1220 INTENG_ENTER_LEAVE EnterLeaveSource
;
1221 INTENG_ENTER_LEAVE EnterLeaveDest
;
1231 DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest
, psoSource
, ClipRegion
, ColorTranslation
);
1232 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
1233 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
1234 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
1235 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
1236 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
1237 BlendObj
->BlendFunction
.AlphaFormat
);
1240 /* Validate output */
1241 OutputRect
= *DestRect
;
1242 if (OutputRect
.right
< OutputRect
.left
)
1244 OutputRect
.left
= DestRect
->right
;
1245 OutputRect
.right
= DestRect
->left
;
1247 if (OutputRect
.bottom
< OutputRect
.top
)
1249 OutputRect
.left
= DestRect
->right
;
1250 OutputRect
.right
= DestRect
->left
;
1254 /* Validate input */
1256 /* FIXME when WindowOrg.x or .y are negitve this check are not vaild,
1257 * we need convert the inputRect to the windows org and do it right */
1258 InputRect
= *SourceRect
;
1259 if ( (InputRect
.top
< 0) || (InputRect
.bottom
< 0) ||
1260 (InputRect
.left
< 0) || (InputRect
.right
< 0) )
1262 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1266 if (psoDest
== psoSource
&&
1267 !(OutputRect
.left
>= SourceRect
->right
|| InputRect
.left
>= OutputRect
.right
||
1268 OutputRect
.top
>= SourceRect
->bottom
|| InputRect
.top
>= OutputRect
.bottom
))
1270 DPRINT1("Source and destination rectangles overlap!\n");
1274 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
1276 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
1279 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
1281 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
1284 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
1286 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
1290 /* Check if there is anything to draw */
1291 if (ClipRegion
!= NULL
&&
1292 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1293 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1299 /* Stretch source if needed */
1300 if (OutputRect
.right
- OutputRect
.left
!= InputRect
.right
- InputRect
.left
||
1301 OutputRect
.bottom
- OutputRect
.top
!= InputRect
.bottom
- InputRect
.top
)
1303 SourceStretchedSize
.cx
= OutputRect
.right
- OutputRect
.left
;
1304 SourceStretchedSize
.cy
= OutputRect
.bottom
- OutputRect
.top
;
1305 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(psoSource
->iBitmapFormat
));
1306 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
1307 if possible to get a HW accelerated stretch. */
1308 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, psoSource
->iBitmapFormat
,
1309 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
1310 if (SourceStretchedBitmap
== 0)
1312 DPRINT1("EngCreateBitmap failed!\n");
1315 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
1316 if (SourceStretchedObj
== NULL
)
1318 DPRINT1("EngLockSurface failed!\n");
1319 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1323 SourceStretchedRect
.left
= 0;
1324 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
1325 SourceStretchedRect
.top
= 0;
1326 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
1327 /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
1328 try to acquire an already acquired mutex (lock the already locked source surface) */
1329 /*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL,
1330 NULL, &SourceStretchedRect, SourceRect, NULL,
1331 NULL, NULL, COLORONCOLOR))*/
1332 if (!EngStretchBlt(SourceStretchedObj
, psoSource
, NULL
, NULL
, NULL
,
1333 NULL
, NULL
, &SourceStretchedRect
, &InputRect
,
1334 NULL
, COLORONCOLOR
))
1336 DPRINT1("EngStretchBlt failed!\n");
1337 EngFreeMem(SourceStretchedObj
->pvBits
);
1338 EngUnlockSurface(SourceStretchedObj
);
1339 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1342 InputRect
.top
= SourceStretchedRect
.top
;
1343 InputRect
.bottom
= SourceStretchedRect
.bottom
;
1344 InputRect
.left
= SourceStretchedRect
.left
;
1345 InputRect
.right
= SourceStretchedRect
.right
;
1346 psoSource
= SourceStretchedObj
;
1349 /* Now call the DIB function */
1350 if (!IntEngEnter(&EnterLeaveSource
, psoSource
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1352 if (SourceStretchedObj
!= NULL
)
1354 EngFreeMem(SourceStretchedObj
->pvBits
);
1355 EngUnlockSurface(SourceStretchedObj
);
1357 if (SourceStretchedBitmap
!= 0)
1359 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1363 InputRect
.left
+= Translate
.x
;
1364 InputRect
.right
+= Translate
.x
;
1365 InputRect
.top
+= Translate
.y
;
1366 InputRect
.bottom
+= Translate
.y
;
1368 if (!IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1370 IntEngLeave(&EnterLeaveSource
);
1371 if (SourceStretchedObj
!= NULL
)
1373 EngFreeMem(SourceStretchedObj
->pvBits
);
1374 EngUnlockSurface(SourceStretchedObj
);
1376 if (SourceStretchedBitmap
!= 0)
1378 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1382 OutputRect
.left
+= Translate
.x
;
1383 OutputRect
.right
+= Translate
.x
;
1384 OutputRect
.top
+= Translate
.y
;
1385 OutputRect
.bottom
+= Translate
.y
;
1388 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
1389 switch (ClippingType
)
1392 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1393 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
1397 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1398 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1399 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1400 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1401 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1403 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1404 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1405 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1406 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1407 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1408 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
1414 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
1417 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1420 for (i
= 0; i
< RectEnum
.c
; i
++)
1422 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1423 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1424 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1425 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1426 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1428 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1429 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1430 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1431 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1432 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1433 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
1446 IntEngLeave(&EnterLeaveDest
);
1447 IntEngLeave(&EnterLeaveSource
);
1449 if (SourceStretchedObj
!= NULL
)
1451 EngFreeMem(SourceStretchedObj
->pvBits
);
1452 EngUnlockSurface(SourceStretchedObj
);
1454 if (SourceStretchedBitmap
!= 0)
1456 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1463 IntEngAlphaBlend(IN SURFOBJ
*psoDest
,
1464 IN SURFOBJ
*psoSource
,
1465 IN CLIPOBJ
*ClipRegion
,
1466 IN XLATEOBJ
*ColorTranslation
,
1468 IN PRECTL SourceRect
,
1469 IN BLENDOBJ
*BlendObj
)
1473 SURFACE
*psurfSource
;
1476 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1479 psurfSource
= CONTAINING_RECORD(psoSource
, SURFACE
, SurfObj
);
1484 /* Check if there is anything to draw */
1485 if (ClipRegion
!= NULL
&&
1486 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1487 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1493 SURFACE_LockBitmapBits(psurfDest
);
1494 MouseSafetyOnDrawStart(psoDest
, DestRect
->left
, DestRect
->top
,
1495 DestRect
->right
, DestRect
->bottom
);
1497 if (psoSource
!= psoDest
)
1498 SURFACE_LockBitmapBits(psurfSource
);
1499 MouseSafetyOnDrawStart(psoSource
, SourceRect
->left
, SourceRect
->top
,
1500 SourceRect
->right
, SourceRect
->bottom
);
1502 /* Call the driver's DrvAlphaBlend if available */
1503 if (psurfDest
->flHooks
& HOOK_ALPHABLEND
)
1505 ret
= GDIDEVFUNCS(psoDest
).AlphaBlend(
1506 psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
1507 DestRect
, SourceRect
, BlendObj
);
1512 ret
= EngAlphaBlend(psoDest
, psoSource
, ClipRegion
, ColorTranslation
,
1513 DestRect
, SourceRect
, BlendObj
);
1516 MouseSafetyOnDrawEnd(psoSource
);
1517 if (psoSource
!= psoDest
)
1518 SURFACE_UnlockBitmapBits(psurfSource
);
1519 MouseSafetyOnDrawEnd(psoDest
);
1520 SURFACE_UnlockBitmapBits(psurfDest
);
1525 /**** REACTOS FONT RENDERING CODE *********************************************/
1527 /* renders the alpha mask bitmap */
1528 static BOOLEAN APIENTRY
1529 AlphaBltMask(SURFOBJ
* psoDest
,
1532 XLATEOBJ
* ColorTranslation
,
1533 XLATEOBJ
* SrcColorTranslation
,
1535 POINTL
* SourcePoint
,
1542 ULONG Background
, BrushColor
, NewColor
;
1543 BYTE
*tMask
, *lMask
;
1545 dx
= DestRect
->right
- DestRect
->left
;
1546 dy
= DestRect
->bottom
- DestRect
->top
;
1550 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
? Brush
->iSolidColor
: 0);
1551 r
= (int)GetRValue(BrushColor
);
1552 g
= (int)GetGValue(BrushColor
);
1553 b
= (int)GetBValue(BrushColor
);
1555 tMask
= (PBYTE
)Mask
->pvScan0
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
1556 for (j
= 0; j
< dy
; j
++)
1559 for (i
= 0; i
< dx
; i
++)
1565 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
1566 psoDest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
? Brush
->iSolidColor
: 0);
1570 Background
= DIB_GetSource(psoDest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
1571 SrcColorTranslation
);
1574 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
1575 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
1576 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
1578 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
1579 DibFunctionsForBitmapFormat
[psoDest
->iBitmapFormat
].DIB_PutPixel(
1580 psoDest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
1585 tMask
+= Mask
->lDelta
;
1596 EngMaskBitBlt(SURFOBJ
*psoDest
,
1598 CLIPOBJ
*ClipRegion
,
1599 XLATEOBJ
*DestColorTranslation
,
1600 XLATEOBJ
*SourceColorTranslation
,
1602 POINTL
*SourcePoint
,
1605 POINTL
*BrushOrigin
)
1615 INTENG_ENTER_LEAVE EnterLeaveSource
;
1616 INTENG_ENTER_LEAVE EnterLeaveDest
;
1624 POINTL AdjustedBrushOrigin
;
1628 if (NULL
!= SourcePoint
)
1630 InputRect
.left
= SourcePoint
->x
;
1631 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
1632 InputRect
.top
= SourcePoint
->y
;
1633 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
1638 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1640 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1643 if (! IntEngEnter(&EnterLeaveSource
, psoDest
, &InputRect
, TRUE
, &Translate
, &psoInput
))
1648 if (NULL
!= SourcePoint
)
1650 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
1651 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
1659 OutputRect
= *DestRect
;
1660 if (NULL
!= ClipRegion
)
1662 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1664 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1665 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1666 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1668 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1670 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1671 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1673 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1675 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1676 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1677 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1679 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1681 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1682 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1686 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1688 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1690 IntEngLeave(&EnterLeaveSource
);
1694 if (! IntEngEnter(&EnterLeaveDest
, psoDest
, &OutputRect
, FALSE
, &Translate
, &psoOutput
))
1696 IntEngLeave(&EnterLeaveSource
);
1700 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1701 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1702 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1703 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1707 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1708 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1711 AdjustedBrushOrigin
= Translate
;
1713 // Determine clipping type
1714 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1716 clippingType
= DC_TRIVIAL
;
1718 clippingType
= ClipRegion
->iDComplexity
;
1721 switch (clippingType
)
1724 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1725 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
, SourceColorTranslation
,
1726 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1728 Ret
= BltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
,
1729 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1733 // Clip the blt to the clip rectangle
1734 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1735 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1736 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1737 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1738 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1740 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1741 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1742 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1744 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
, SourceColorTranslation
,
1745 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1749 Ret
= BltMask(psoOutput
, psoInput
, psoMask
, DestColorTranslation
,
1750 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, R4_MASK
);
1756 if (psoOutput
== psoInput
)
1758 if (OutputRect
.top
< InputPoint
.y
)
1760 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1764 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1771 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1774 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1776 for (i
= 0; i
< RectEnum
.c
; i
++)
1778 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1779 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1780 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1781 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1782 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1784 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1785 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1786 if (psoMask
->iBitmapFormat
== BMF_8BPP
)
1788 Ret
= AlphaBltMask(psoOutput
, psoInput
, psoMask
,
1789 DestColorTranslation
,
1790 SourceColorTranslation
,
1791 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
1792 &AdjustedBrushOrigin
) && Ret
;
1796 Ret
= BltMask(psoOutput
, psoInput
, psoMask
,
1797 DestColorTranslation
, &CombinedRect
, &Pt
,
1798 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1809 IntEngLeave(&EnterLeaveDest
);
1810 IntEngLeave(&EnterLeaveSource
);
1816 IntEngMaskBlt(SURFOBJ
*psoDest
,
1818 CLIPOBJ
*ClipRegion
,
1819 XLATEOBJ
*DestColorTranslation
,
1820 XLATEOBJ
*SourceColorTranslation
,
1822 POINTL
*SourcePoint
,
1825 POINTL
*BrushOrigin
)
1834 if (NULL
!= SourcePoint
)
1836 InputPoint
= *SourcePoint
;
1839 /* Clip against the bounds of the clipping region so we won't try to write
1840 * outside the surface */
1841 if (NULL
!= ClipRegion
)
1843 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1847 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1848 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1852 OutputRect
= *DestRect
;
1855 /* No success yet */
1858 psurfDest
= CONTAINING_RECORD(psoDest
, SURFACE
, SurfObj
);
1860 SURFACE_LockBitmapBits(psurfDest
);
1861 MouseSafetyOnDrawStart(psoDest
, OutputRect
.left
, OutputRect
.top
,
1862 OutputRect
.right
, OutputRect
.bottom
);
1864 /* Dummy BitBlt to let driver know that it should flush its changes.
1865 This should really be done using a call to DrvSynchronizeSurface,
1866 but the VMware driver doesn't hook that call. */
1867 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1868 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1871 ret
= EngMaskBitBlt(psoDest
, psoMask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1872 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1874 /* Dummy BitBlt to let driver know that something has changed. */
1875 IntEngBitBltEx(psoDest
, NULL
, psoMask
, ClipRegion
, DestColorTranslation
,
1876 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1879 MouseSafetyOnDrawEnd(psoDest
);
1880 SURFACE_UnlockBitmapBits(psurfDest
);