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 (STDCALL
*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
38 XLATEOBJ
* ColorTranslation
,
45 typedef BOOLEAN (STDCALL
*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
49 XLATEOBJ
* ColorTranslation
,
56 BOOL STDCALL
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
58 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
60 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
61 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
63 if (prcDst
->left
< prcDst
->right
)
65 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
66 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
68 if (prcDst
->top
< prcDst
->bottom
)
79 static BOOLEAN STDCALL
80 BltMask(SURFOBJ
* Dest
,
83 XLATEOBJ
* ColorTranslation
,
91 LONG i
, j
, dx
, dy
, c8
;
93 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
95 PGDIBRUSHINST GdiBrush
= NULL
;
96 SURFOBJ
*PatternObj
= NULL
;
97 PBITMAPOBJ PatternBitmap
;
98 ULONG PatternWidth
= 0, PatternHeight
= 0, PatternY
= 0;
105 dx
= DestRect
->right
- DestRect
->left
;
106 dy
= DestRect
->bottom
- DestRect
->top
;
108 if (Brush
->iSolidColor
== 0xFFFFFFFF)
110 GdiBrush
= CONTAINING_RECORD(
115 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->GdiBrushObject
->hbmPattern
);
116 if (PatternBitmap
!= NULL
)
118 PatternObj
= &PatternBitmap
->SurfObj
;
119 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
120 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
124 PatternBitmap
= NULL
;
126 tMask
= (PBYTE
)Mask
->pvScan0
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
127 for (j
= 0; j
< dy
; j
++)
130 c8
= SourcePoint
->x
& 0x07;
132 if (PatternBitmap
!= NULL
)
133 PatternY
= (DestRect
->top
+ j
) % PatternHeight
;
135 for (i
= 0; i
< dx
; i
++)
137 if (0 != (*lMask
& maskbit
[c8
]))
139 if (PatternBitmap
== NULL
)
141 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
142 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
146 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
147 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
148 DIB_GetSource(PatternObj
, (DestRect
->left
+ i
) % PatternWidth
, PatternY
, GdiBrush
->XlateObject
));
158 tMask
+= Mask
->lDelta
;
161 if (PatternBitmap
!= NULL
)
162 BITMAPOBJ_UnlockBitmap(PatternBitmap
);
167 static BOOLEAN STDCALL
168 BltPatCopy(SURFOBJ
* Dest
,
171 XLATEOBJ
* ColorTranslation
,
179 // These functions are assigned if we're working with a DIB
180 // The assigned functions depend on the bitsPerPixel of the DIB
182 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_ColorFill(Dest
, DestRect
, Brush
->iSolidColor
);
187 static BOOLEAN STDCALL
188 CallDibBitBlt(SURFOBJ
* OutputObj
,
191 XLATEOBJ
* ColorTranslation
,
200 PGDIBRUSHINST GdiBrush
= NULL
;
201 BITMAPOBJ
*bmPattern
;
204 BltInfo
.DestSurface
= OutputObj
;
205 BltInfo
.SourceSurface
= InputObj
;
206 BltInfo
.PatternSurface
= NULL
;
207 BltInfo
.XlateSourceToDest
= ColorTranslation
;
208 BltInfo
.DestRect
= *OutputRect
;
209 BltInfo
.SourcePoint
= *InputPoint
;
211 if (ROP3_TO_ROP4(SRCCOPY
) == Rop4
)
212 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
214 BltInfo
.XlatePatternToDest
= NULL
;
215 BltInfo
.Brush
= Brush
;
216 BltInfo
.BrushOrigin
= *BrushOrigin
;
220 if (ROP4_USES_PATTERN(Rop4
) && Brush
->iSolidColor
== 0xFFFFFFFF)
222 GdiBrush
= CONTAINING_RECORD(Brush
, GDIBRUSHINST
, BrushObject
);
223 if ((bmPattern
= BITMAPOBJ_LockBitmap(GdiBrush
->GdiBrushObject
->hbmPattern
)))
225 BltInfo
.PatternSurface
= &bmPattern
->SurfObj
;
229 /* FIXME - What to do here? */
231 BltInfo
.XlatePatternToDest
= GdiBrush
->XlateObject
;
238 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
241 if (bmPattern
!= NULL
)
243 BITMAPOBJ_UnlockBitmap(bmPattern
);
249 INT __cdecl
abs(INT nm
);
266 IN POINTL
*pptlBrush
,
276 ProbeForRead(prclTrg
, sizeof(RECTL
), 1);
277 RtlCopyMemory(&rclTrg
,prclTrg
, sizeof(RECTL
));
279 ProbeForRead(pptlSrc
, sizeof(POINTL
), 1);
280 RtlCopyMemory(&ptlSrc
, pptlSrc
, sizeof(POINTL
));
282 ProbeForRead(pptlMask
, sizeof(POINTL
), 1);
283 RtlCopyMemory(&ptlMask
, pptlMask
, sizeof(POINTL
));
285 ProbeForRead(pptlBrush
, sizeof(POINTL
), 1);
286 RtlCopyMemory(&ptlBrush
, pptlBrush
, sizeof(POINTL
));
291 _SEH_YIELD(return FALSE
);
295 return EngBitBlt(psoTrg
, psoSrc
, psoMask
, pco
, pxlo
, &rclTrg
, &ptlSrc
, &ptlMask
, pbo
, &ptlBrush
, rop4
);
302 EngBitBlt(SURFOBJ
*DestObj
,
306 XLATEOBJ
*ColorTranslation
,
322 INTENG_ENTER_LEAVE EnterLeaveSource
;
323 INTENG_ENTER_LEAVE EnterLeaveDest
;
326 PBLTRECTFUNC BltRectFunc
;
334 POINTL AdjustedBrushOrigin
;
336 UsesSource
= ROP4_USES_SOURCE(Rop4
);
337 UsesPattern
= ROP4_USES_PATTERN(Rop4
);
340 /* Copy destination onto itself: nop */
344 OutputRect
= *DestRect
;
345 if (OutputRect
.right
< OutputRect
.left
)
347 OutputRect
.left
= DestRect
->right
;
348 OutputRect
.right
= DestRect
->left
;
350 if (OutputRect
.bottom
< OutputRect
.top
)
352 OutputRect
.left
= DestRect
->right
;
353 OutputRect
.right
= DestRect
->left
;
358 if (NULL
== SourcePoint
)
363 /* Make sure we don't try to copy anything outside the valid source
365 InputPoint
= *SourcePoint
;
366 if (InputPoint
.x
< 0)
368 OutputRect
.left
-= InputPoint
.x
;
371 if (InputPoint
.y
< 0)
373 OutputRect
.top
-= InputPoint
.y
;
376 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+
377 OutputRect
.right
- OutputRect
.left
)
379 OutputRect
.right
= OutputRect
.left
+
380 SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
382 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+
383 OutputRect
.bottom
- OutputRect
.top
)
385 OutputRect
.bottom
= OutputRect
.top
+
386 SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
389 InputRect
.left
= InputPoint
.x
;
390 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
391 InputRect
.top
= InputPoint
.y
;
392 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
394 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
,
395 &Translate
, &InputObj
))
400 InputPoint
.x
+= Translate
.x
;
401 InputPoint
.y
+= Translate
.y
;
406 InputRect
.right
= DestRect
->right
- DestRect
->left
;
408 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
411 if (NULL
!= ClipRegion
)
413 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
415 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
416 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
417 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
419 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
421 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
422 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
424 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
426 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
427 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
428 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
430 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
432 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
433 OutputRect
.bottom
= ClipRegion
->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
)
444 IntEngLeave(&EnterLeaveSource
);
449 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
,
454 IntEngLeave(&EnterLeaveSource
);
459 OutputRect
.left
+= Translate
.x
;
460 OutputRect
.right
+= Translate
.x
;
461 OutputRect
.top
+= Translate
.y
;
462 OutputRect
.bottom
+= Translate
.y
;
466 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
467 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
471 AdjustedBrushOrigin
= Translate
;
474 /* Determine clipping type */
475 if (ClipRegion
== (CLIPOBJ
*) NULL
)
477 clippingType
= DC_TRIVIAL
;
481 clippingType
= ClipRegion
->iDComplexity
;
486 BltRectFunc
= BltMask
;
488 else if (ROP3_TO_ROP4(PATCOPY
) == Rop4
)
490 if (Brush
->iSolidColor
== 0xFFFFFFFF)
491 BltRectFunc
= CallDibBitBlt
;
493 BltRectFunc
= BltPatCopy
;
497 BltRectFunc
= CallDibBitBlt
;
501 switch (clippingType
)
504 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
505 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
,
506 &AdjustedBrushOrigin
, Rop4
);
509 /* Clip the blt to the clip rectangle */
510 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
511 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
512 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
513 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
514 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
516 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
517 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
518 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
519 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
520 &AdjustedBrushOrigin
, Rop4
);
525 if (OutputObj
== InputObj
)
527 if (OutputRect
.top
< InputPoint
.y
)
529 Direction
= OutputRect
.left
< InputPoint
.x
?
530 CD_RIGHTDOWN
: CD_LEFTDOWN
;
534 Direction
= OutputRect
.left
< InputPoint
.x
?
535 CD_RIGHTUP
: CD_LEFTUP
;
542 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
545 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
548 for (i
= 0; i
< RectEnum
.c
; i
++)
550 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
551 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
552 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
553 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
554 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
556 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
557 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
558 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
,
559 ColorTranslation
, &CombinedRect
, &Pt
,
560 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
570 IntEngLeave(&EnterLeaveDest
);
573 IntEngLeave(&EnterLeaveSource
);
580 IntEngBitBltEx(SURFOBJ
*DestSurf
,
584 XLATEOBJ
*ColorTranslation
,
594 RECTL InputClippedRect
;
599 BITMAPOBJ
*SourceObj
= NULL
;
601 if (DestSurf
== NULL
)
604 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
607 InputClippedRect
= *DestRect
;
608 if (InputClippedRect
.right
< InputClippedRect
.left
)
610 InputClippedRect
.left
= DestRect
->right
;
611 InputClippedRect
.right
= DestRect
->left
;
613 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
615 InputClippedRect
.top
= DestRect
->bottom
;
616 InputClippedRect
.bottom
= DestRect
->top
;
618 UsesSource
= ROP4_USES_SOURCE(Rop4
);
621 if (NULL
== SourcePoint
|| NULL
== SourceSurf
)
625 InputPoint
= *SourcePoint
;
627 /* Make sure we don't try to copy anything outside the valid source
629 if (InputPoint
.x
< 0)
631 InputClippedRect
.left
-= InputPoint
.x
;
634 if (InputPoint
.y
< 0)
636 InputClippedRect
.top
-= InputPoint
.y
;
639 if (SourceSurf
->sizlBitmap
.cx
< InputPoint
.x
+
640 InputClippedRect
.right
-
641 InputClippedRect
.left
)
643 InputClippedRect
.right
= InputClippedRect
.left
+
644 SourceSurf
->sizlBitmap
.cx
- InputPoint
.x
;
646 if (SourceSurf
->sizlBitmap
.cy
< InputPoint
.y
+
647 InputClippedRect
.bottom
-
648 InputClippedRect
.top
)
650 InputClippedRect
.bottom
= InputClippedRect
.top
+
651 SourceSurf
->sizlBitmap
.cy
- InputPoint
.y
;
654 if (InputClippedRect
.right
< InputClippedRect
.left
||
655 InputClippedRect
.bottom
< InputClippedRect
.top
)
657 /* Everything clipped away, nothing to do */
662 /* Clip against the bounds of the clipping region so we won't try to write
663 * outside the surface */
664 if (NULL
!= ClipRegion
)
666 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
667 &ClipRegion
->rclBounds
))
671 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
672 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
676 OutputRect
= InputClippedRect
;
681 BITMAPOBJ_LockBitmapBits(DestObj
);
685 if (SourceSurf
!= DestSurf
)
687 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
688 BITMAPOBJ_LockBitmapBits(SourceObj
);
690 MouseSafetyOnDrawStart(SourceSurf
, InputPoint
.x
, InputPoint
.y
,
691 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
692 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
694 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
695 OutputRect
.right
, OutputRect
.bottom
);
701 /* Call the driver's DrvBitBlt if available */
702 if (DestObj
->flHooks
& HOOK_BITBLT
)
704 ret
= GDIDEVFUNCS(DestSurf
).BitBlt(
705 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
706 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
712 ret
= EngBitBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
713 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
719 MouseSafetyOnDrawEnd(DestSurf
);
722 MouseSafetyOnDrawEnd(SourceSurf
);
723 if (SourceSurf
!= DestSurf
)
725 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
729 BITMAPOBJ_UnlockBitmapBits(DestObj
);
735 static BOOLEAN STDCALL
736 CallDibStretchBlt(SURFOBJ
* OutputObj
,
740 XLATEOBJ
* ColorTranslation
,
747 POINTL RealBrushOrigin
;
748 if (BrushOrigin
== NULL
)
750 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
754 RealBrushOrigin
= *BrushOrigin
;
756 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_StretchBlt(
757 OutputObj
, InputObj
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
765 IN SURFOBJ
*SourceObj
,
767 IN CLIPOBJ
*ClipRegion
,
768 IN XLATEOBJ
*ColorTranslation
,
769 IN COLORADJUSTMENT
*pca
,
770 IN POINTL
*BrushOrigin
,
773 IN POINTL
*MaskOrigin
,
785 ProbeForRead(pca
, sizeof(COLORADJUSTMENT
), 1);
786 RtlCopyMemory(&ca
,pca
, sizeof(COLORADJUSTMENT
));
788 ProbeForRead(BrushOrigin
, sizeof(POINTL
), 1);
789 RtlCopyMemory(&lBrushOrigin
, BrushOrigin
, sizeof(POINTL
));
791 ProbeForRead(prclDest
, sizeof(RECTL
), 1);
792 RtlCopyMemory(&rclDest
, prclDest
, sizeof(RECTL
));
794 ProbeForRead(prclSrc
, sizeof(RECTL
), 1);
795 RtlCopyMemory(&rclSrc
, prclSrc
, sizeof(RECTL
));
797 ProbeForRead(MaskOrigin
, sizeof(POINTL
), 1);
798 RtlCopyMemory(&lMaskOrigin
, MaskOrigin
, sizeof(POINTL
));
803 _SEH_YIELD(return FALSE
);
807 return EngStretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
, &ca
, &lBrushOrigin
, &rclDest
, &rclSrc
, &lMaskOrigin
, Mode
);
814 IN SURFOBJ
*SourceObj
,
816 IN CLIPOBJ
*ClipRegion
,
817 IN XLATEOBJ
*ColorTranslation
,
818 IN COLORADJUSTMENT
*pca
,
819 IN POINTL
*BrushOrigin
,
822 IN POINTL
*MaskOrigin
,
826 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
832 INTENG_ENTER_LEAVE EnterLeaveSource
;
833 INTENG_ENTER_LEAVE EnterLeaveDest
;
836 PSTRETCHRECTFUNC BltRectFunc
;
838 POINTL AdjustedBrushOrigin
;
840 InputRect
.left
= prclSrc
->left
;
841 InputRect
.right
= prclSrc
->right
;
842 InputRect
.top
= prclSrc
->top
;
843 InputRect
.bottom
= prclSrc
->bottom
;
845 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
850 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
851 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
853 OutputRect
= *prclDest
;
855 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
857 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
859 IntEngLeave(&EnterLeaveSource
);
863 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
865 IntEngLeave(&EnterLeaveSource
);
869 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
870 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
871 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
872 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
874 if (NULL
!= BrushOrigin
)
876 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
877 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
881 AdjustedBrushOrigin
= Translate
;
886 //BltRectFunc = BltMask;
887 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
888 IntEngLeave(&EnterLeaveDest
);
889 IntEngLeave(&EnterLeaveSource
);
895 BltRectFunc
= CallDibStretchBlt
;
899 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ClipRegion
,
900 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
901 &AdjustedBrushOrigin
, Mode
);
903 IntEngLeave(&EnterLeaveDest
);
904 IntEngLeave(&EnterLeaveSource
);
910 IntEngStretchBlt(SURFOBJ
*DestSurf
,
914 XLATEOBJ
*ColorTranslation
,
926 BITMAPOBJ
*SourceObj
= NULL
;
929 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
932 if (pMaskOrigin
!= NULL
)
934 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
940 BITMAPOBJ_LockBitmapBits(DestObj
);
941 MouseSafetyOnDrawStart(DestSurf
, DestRect
->left
, DestRect
->top
,
942 DestRect
->right
, DestRect
->bottom
);
944 if (NULL
!= SourceSurf
)
946 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
948 if (SourceSurf
!= DestSurf
)
950 BITMAPOBJ_LockBitmapBits(SourceObj
);
952 MouseSafetyOnDrawStart(SourceSurf
, SourceRect
->left
, SourceRect
->top
,
953 SourceRect
->right
, SourceRect
->bottom
);
956 /* Prepare color adjustment */
958 /* Call the driver's DrvStretchBlt if available */
959 if (DestObj
->flHooks
& HOOK_STRETCHBLT
)
961 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
962 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
963 // FIXME: MaskOrigin is always NULL !
964 ret
= GDIDEVFUNCS(DestSurf
).StretchBlt(
965 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
966 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
971 // FIXME: see previous fixme
972 ret
= EngStretchBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
973 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
976 if (NULL
!= SourceSurf
)
978 MouseSafetyOnDrawEnd(SourceSurf
);
979 if (SourceSurf
!= DestSurf
)
981 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
984 MouseSafetyOnDrawEnd(DestSurf
);
985 BITMAPOBJ_UnlockBitmapBits(DestObj
);
996 NtGdiEngAlphaBlend(IN SURFOBJ
*Dest
,
998 IN CLIPOBJ
*ClipRegion
,
999 IN XLATEOBJ
*ColorTranslation
,
1000 IN PRECTL upDestRect
,
1001 IN PRECTL upSourceRect
,
1002 IN BLENDOBJ
*BlendObj
)
1009 ProbeForRead(upDestRect
, sizeof(RECTL
), 1);
1010 RtlCopyMemory(&DestRect
,upDestRect
, sizeof(RECTL
));
1012 ProbeForRead(upSourceRect
, sizeof(RECTL
), 1);
1013 RtlCopyMemory(&SourceRect
, upSourceRect
, sizeof(RECTL
));
1018 _SEH_YIELD(return FALSE
);
1022 return EngAlphaBlend(Dest
, Source
, ClipRegion
, ColorTranslation
, &DestRect
, &SourceRect
, BlendObj
);
1030 EngAlphaBlend(IN SURFOBJ
*Dest
,
1032 IN CLIPOBJ
*ClipRegion
,
1033 IN XLATEOBJ
*ColorTranslation
,
1035 IN PRECTL SourceRect
,
1036 IN BLENDOBJ
*BlendObj
)
1038 RECTL SourceStretchedRect
;
1039 SIZEL SourceStretchedSize
;
1040 HBITMAP SourceStretchedBitmap
= 0;
1041 SURFOBJ
* SourceStretchedObj
= NULL
;
1048 INTENG_ENTER_LEAVE EnterLeaveSource
;
1049 INTENG_ENTER_LEAVE EnterLeaveDest
;
1059 DPRINT("EngAlphaBlend(Dest:0x%p, Source:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", Dest
, Source
, ClipRegion
, ColorTranslation
);
1060 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
1061 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
1062 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
1063 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
1064 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
1065 BlendObj
->BlendFunction
.AlphaFormat
);
1068 /* Validate input */
1069 OutputRect
= *DestRect
;
1070 if (OutputRect
.right
< OutputRect
.left
)
1072 OutputRect
.left
= DestRect
->right
;
1073 OutputRect
.right
= DestRect
->left
;
1075 if (OutputRect
.bottom
< OutputRect
.top
)
1077 OutputRect
.left
= DestRect
->right
;
1078 OutputRect
.right
= DestRect
->left
;
1082 /* Validate input */
1084 /* FIXME when WindowOrg.x or .y are negitve this check are not vaild,
1085 * we need convert the inputRect to the windows org and do it right */
1086 InputRect
= *SourceRect
;
1087 if ( (InputRect
.top
< 0) || (InputRect
.bottom
< 0) ||
1088 (InputRect
.left
< 0) || (InputRect
.right
< 0) )
1090 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1094 if (Dest
== Source
&&
1095 !(OutputRect
.left
>= SourceRect
->right
|| InputRect
.left
>= OutputRect
.right
||
1096 OutputRect
.top
>= SourceRect
->bottom
|| InputRect
.top
>= OutputRect
.bottom
))
1098 DPRINT1("Source and destination rectangles overlap!\n");
1102 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
1104 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
1107 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
1109 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
1112 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
1114 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
1118 /* Check if there is anything to draw */
1119 if (ClipRegion
!= NULL
&&
1120 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1121 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1127 /* Stretch source if needed */
1128 if (OutputRect
.right
- OutputRect
.left
!= InputRect
.right
- InputRect
.left
||
1129 OutputRect
.bottom
- OutputRect
.top
!= InputRect
.bottom
- InputRect
.top
)
1131 SourceStretchedSize
.cx
= OutputRect
.right
- OutputRect
.left
;
1132 SourceStretchedSize
.cy
= OutputRect
.bottom
- OutputRect
.top
;
1133 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(Source
->iBitmapFormat
));
1134 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
1135 if possible to get a HW accelerated stretch. */
1136 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, Source
->iBitmapFormat
,
1137 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
1138 if (SourceStretchedBitmap
== 0)
1140 DPRINT1("EngCreateBitmap failed!\n");
1143 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
1144 if (SourceStretchedObj
== NULL
)
1146 DPRINT1("EngLockSurface failed!\n");
1147 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1151 SourceStretchedRect
.left
= 0;
1152 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
1153 SourceStretchedRect
.top
= 0;
1154 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
1155 /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
1156 try to acquire an already acquired mutex (lock the already locked source surface) */
1157 /*if (!IntEngStretchBlt(SourceStretchedObj, Source, NULL, NULL,
1158 NULL, &SourceStretchedRect, SourceRect, NULL,
1159 NULL, NULL, COLORONCOLOR))*/
1160 if (!EngStretchBlt(SourceStretchedObj
, Source
, NULL
, NULL
, NULL
,
1161 NULL
, NULL
, &SourceStretchedRect
, &InputRect
,
1162 NULL
, COLORONCOLOR
))
1164 DPRINT1("EngStretchBlt failed!\n");
1165 EngFreeMem(SourceStretchedObj
->pvBits
);
1166 EngUnlockSurface(SourceStretchedObj
);
1167 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1170 InputRect
.top
= SourceStretchedRect
.top
;
1171 InputRect
.bottom
= SourceStretchedRect
.bottom
;
1172 InputRect
.left
= SourceStretchedRect
.left
;
1173 InputRect
.right
= SourceStretchedRect
.right
;
1174 Source
= SourceStretchedObj
;
1177 /* Now call the DIB function */
1178 if (!IntEngEnter(&EnterLeaveSource
, Source
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1180 if (SourceStretchedObj
!= NULL
)
1182 EngFreeMem(SourceStretchedObj
->pvBits
);
1183 EngUnlockSurface(SourceStretchedObj
);
1185 if (SourceStretchedBitmap
!= 0)
1187 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1191 InputRect
.left
+= Translate
.x
;
1192 InputRect
.right
+= Translate
.x
;
1193 InputRect
.top
+= Translate
.y
;
1194 InputRect
.bottom
+= Translate
.y
;
1196 if (!IntEngEnter(&EnterLeaveDest
, Dest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1198 IntEngLeave(&EnterLeaveSource
);
1199 if (SourceStretchedObj
!= NULL
)
1201 EngFreeMem(SourceStretchedObj
->pvBits
);
1202 EngUnlockSurface(SourceStretchedObj
);
1204 if (SourceStretchedBitmap
!= 0)
1206 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1210 OutputRect
.left
+= Translate
.x
;
1211 OutputRect
.right
+= Translate
.x
;
1212 OutputRect
.top
+= Translate
.y
;
1213 OutputRect
.bottom
+= Translate
.y
;
1216 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
1217 switch (ClippingType
)
1220 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1221 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
1225 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1226 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1227 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1228 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1229 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1231 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1232 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1233 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1234 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1235 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1236 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
1242 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
1245 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1248 for (i
= 0; i
< RectEnum
.c
; i
++)
1250 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1251 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1252 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1253 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1254 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1256 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1257 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1258 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1259 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1260 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1261 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
1274 IntEngLeave(&EnterLeaveDest
);
1275 IntEngLeave(&EnterLeaveSource
);
1277 if (SourceStretchedObj
!= NULL
)
1279 EngFreeMem(SourceStretchedObj
->pvBits
);
1280 EngUnlockSurface(SourceStretchedObj
);
1282 if (SourceStretchedBitmap
!= 0)
1284 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1291 IntEngAlphaBlend(IN SURFOBJ
*Dest
,
1293 IN CLIPOBJ
*ClipRegion
,
1294 IN XLATEOBJ
*ColorTranslation
,
1296 IN PRECTL SourceRect
,
1297 IN BLENDOBJ
*BlendObj
)
1301 BITMAPOBJ
*SourceObj
;
1304 DestObj
= CONTAINING_RECORD(Dest
, BITMAPOBJ
, SurfObj
);
1308 SourceObj
= CONTAINING_RECORD(Source
, BITMAPOBJ
, SurfObj
);
1314 /* Check if there is anything to draw */
1315 if (ClipRegion
!= NULL
&&
1316 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1317 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1323 BITMAPOBJ_LockBitmapBits(DestObj
);
1324 MouseSafetyOnDrawStart(Dest
, DestRect
->left
, DestRect
->top
,
1325 DestRect
->right
, DestRect
->bottom
);
1328 BITMAPOBJ_LockBitmapBits(SourceObj
);
1329 MouseSafetyOnDrawStart(Source
, SourceRect
->left
, SourceRect
->top
,
1330 SourceRect
->right
, SourceRect
->bottom
);
1332 /* Call the driver's DrvAlphaBlend if available */
1333 if (DestObj
->flHooks
& HOOK_ALPHABLEND
)
1335 ret
= GDIDEVFUNCS(Dest
).AlphaBlend(
1336 Dest
, Source
, ClipRegion
, ColorTranslation
,
1337 DestRect
, SourceRect
, BlendObj
);
1342 ret
= EngAlphaBlend(Dest
, Source
, ClipRegion
, ColorTranslation
,
1343 DestRect
, SourceRect
, BlendObj
);
1346 MouseSafetyOnDrawEnd(Source
);
1348 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
1349 MouseSafetyOnDrawEnd(Dest
);
1350 BITMAPOBJ_UnlockBitmapBits(DestObj
);
1355 /**** REACTOS FONT RENDERING CODE *********************************************/
1357 /* renders the alpha mask bitmap */
1358 static BOOLEAN STDCALL
1359 AlphaBltMask(SURFOBJ
* Dest
,
1362 XLATEOBJ
* ColorTranslation
,
1363 XLATEOBJ
* SrcColorTranslation
,
1365 POINTL
* SourcePoint
,
1372 ULONG Background
, BrushColor
, NewColor
;
1373 BYTE
*tMask
, *lMask
;
1375 dx
= DestRect
->right
- DestRect
->left
;
1376 dy
= DestRect
->bottom
- DestRect
->top
;
1380 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
1381 r
= (int)GetRValue(BrushColor
);
1382 g
= (int)GetGValue(BrushColor
);
1383 b
= (int)GetBValue(BrushColor
);
1385 tMask
= (PBYTE
)Mask
->pvScan0
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
1386 for (j
= 0; j
< dy
; j
++)
1389 for (i
= 0; i
< dx
; i
++)
1395 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1396 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
1400 Background
= DIB_GetSource(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
1401 SrcColorTranslation
);
1404 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
1405 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
1406 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
1408 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
1409 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1410 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
1415 tMask
+= Mask
->lDelta
;
1426 EngMaskBitBlt(SURFOBJ
*DestObj
,
1428 CLIPOBJ
*ClipRegion
,
1429 XLATEOBJ
*DestColorTranslation
,
1430 XLATEOBJ
*SourceColorTranslation
,
1432 POINTL
*SourcePoint
,
1435 POINTL
*BrushOrigin
)
1445 INTENG_ENTER_LEAVE EnterLeaveSource
;
1446 INTENG_ENTER_LEAVE EnterLeaveDest
;
1454 POINTL AdjustedBrushOrigin
;
1458 if (NULL
!= SourcePoint
)
1460 InputRect
.left
= SourcePoint
->x
;
1461 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
1462 InputRect
.top
= SourcePoint
->y
;
1463 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
1468 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1470 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1473 if (! IntEngEnter(&EnterLeaveSource
, DestObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1478 if (NULL
!= SourcePoint
)
1480 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
1481 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
1489 OutputRect
= *DestRect
;
1490 if (NULL
!= ClipRegion
)
1492 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1494 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1495 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1496 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1498 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1500 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1501 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1503 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1505 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1506 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1507 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1509 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1511 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1512 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1516 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1518 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1520 IntEngLeave(&EnterLeaveSource
);
1524 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1526 IntEngLeave(&EnterLeaveSource
);
1530 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1531 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1532 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1533 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1537 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1538 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1541 AdjustedBrushOrigin
= Translate
;
1543 // Determine clipping type
1544 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1546 clippingType
= DC_TRIVIAL
;
1548 clippingType
= ClipRegion
->iDComplexity
;
1551 switch (clippingType
)
1554 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1555 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1556 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1558 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1559 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1563 // Clip the blt to the clip rectangle
1564 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1565 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1566 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1567 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1568 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1570 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1571 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1572 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1574 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1575 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1579 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1580 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, R4_MASK
);
1586 if (OutputObj
== InputObj
)
1588 if (OutputRect
.top
< InputPoint
.y
)
1590 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1594 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1601 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1604 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1606 for (i
= 0; i
< RectEnum
.c
; i
++)
1608 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1609 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1610 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1611 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1612 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1614 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1615 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1616 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1618 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
,
1619 DestColorTranslation
,
1620 SourceColorTranslation
,
1621 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
1622 &AdjustedBrushOrigin
) && Ret
;
1626 Ret
= BltMask(OutputObj
, InputObj
, Mask
,
1627 DestColorTranslation
, &CombinedRect
, &Pt
,
1628 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1639 IntEngLeave(&EnterLeaveDest
);
1640 IntEngLeave(&EnterLeaveSource
);
1646 IntEngMaskBlt(SURFOBJ
*DestSurf
,
1648 CLIPOBJ
*ClipRegion
,
1649 XLATEOBJ
*DestColorTranslation
,
1650 XLATEOBJ
*SourceColorTranslation
,
1652 POINTL
*SourcePoint
,
1655 POINTL
*BrushOrigin
)
1664 if (NULL
!= SourcePoint
)
1666 InputPoint
= *SourcePoint
;
1669 /* Clip against the bounds of the clipping region so we won't try to write
1670 * outside the surface */
1671 if (NULL
!= ClipRegion
)
1673 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1677 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1678 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1682 OutputRect
= *DestRect
;
1685 /* No success yet */
1688 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
1690 BITMAPOBJ_LockBitmapBits(DestObj
);
1691 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
1692 OutputRect
.right
, OutputRect
.bottom
);
1694 /* Dummy BitBlt to let driver know that it should flush its changes.
1695 This should really be done using a call to DrvSynchronizeSurface,
1696 but the VMware driver doesn't hook that call. */
1697 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1698 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1701 ret
= EngMaskBitBlt(DestSurf
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1702 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1704 /* Dummy BitBlt to let driver know that something has changed. */
1705 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1706 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1709 MouseSafetyOnDrawEnd(DestSurf
);
1710 BITMAPOBJ_UnlockBitmapBits(DestObj
);