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
);
255 EngBitBlt(SURFOBJ
*DestObj
,
259 XLATEOBJ
*ColorTranslation
,
275 INTENG_ENTER_LEAVE EnterLeaveSource
;
276 INTENG_ENTER_LEAVE EnterLeaveDest
;
279 PBLTRECTFUNC BltRectFunc
;
287 POINTL AdjustedBrushOrigin
;
289 UsesSource
= ROP4_USES_SOURCE(Rop4
);
290 UsesPattern
= ROP4_USES_PATTERN(Rop4
);
293 /* Copy destination onto itself: nop */
297 OutputRect
= *DestRect
;
298 if (OutputRect
.right
< OutputRect
.left
)
300 OutputRect
.left
= DestRect
->right
;
301 OutputRect
.right
= DestRect
->left
;
303 if (OutputRect
.bottom
< OutputRect
.top
)
305 OutputRect
.left
= DestRect
->right
;
306 OutputRect
.right
= DestRect
->left
;
311 if (NULL
== SourcePoint
)
316 /* Make sure we don't try to copy anything outside the valid source
318 InputPoint
= *SourcePoint
;
319 if (InputPoint
.x
< 0)
321 OutputRect
.left
-= InputPoint
.x
;
324 if (InputPoint
.y
< 0)
326 OutputRect
.top
-= InputPoint
.y
;
329 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+
330 OutputRect
.right
- OutputRect
.left
)
332 OutputRect
.right
= OutputRect
.left
+
333 SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
335 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+
336 OutputRect
.bottom
- OutputRect
.top
)
338 OutputRect
.bottom
= OutputRect
.top
+
339 SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
342 InputRect
.left
= InputPoint
.x
;
343 InputRect
.right
= InputPoint
.x
+ (OutputRect
.right
- OutputRect
.left
);
344 InputRect
.top
= InputPoint
.y
;
345 InputRect
.bottom
= InputPoint
.y
+ (OutputRect
.bottom
- OutputRect
.top
);
347 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
,
348 &Translate
, &InputObj
))
353 InputPoint
.x
+= Translate
.x
;
354 InputPoint
.y
+= Translate
.y
;
359 InputRect
.right
= DestRect
->right
- DestRect
->left
;
361 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
364 if (NULL
!= ClipRegion
)
366 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
368 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
369 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
370 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
372 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
374 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
375 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
377 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
379 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
380 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
381 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
383 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
385 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
386 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
390 /* Check for degenerate case: if height or width of OutputRect is 0 pixels
391 there's nothing to do */
392 if (OutputRect
.right
<= OutputRect
.left
||
393 OutputRect
.bottom
<= OutputRect
.top
)
397 IntEngLeave(&EnterLeaveSource
);
402 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
,
407 IntEngLeave(&EnterLeaveSource
);
412 OutputRect
.left
+= Translate
.x
;
413 OutputRect
.right
+= Translate
.x
;
414 OutputRect
.top
+= Translate
.y
;
415 OutputRect
.bottom
+= Translate
.y
;
419 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
420 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
424 AdjustedBrushOrigin
= Translate
;
427 /* Determine clipping type */
428 if (ClipRegion
== (CLIPOBJ
*) NULL
)
430 clippingType
= DC_TRIVIAL
;
434 clippingType
= ClipRegion
->iDComplexity
;
439 BltRectFunc
= BltMask
;
441 else if (ROP3_TO_ROP4(PATCOPY
) == Rop4
)
443 if (Brush
->iSolidColor
== 0xFFFFFFFF)
444 BltRectFunc
= CallDibBitBlt
;
446 BltRectFunc
= BltPatCopy
;
450 BltRectFunc
= CallDibBitBlt
;
457 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
458 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
,
459 &AdjustedBrushOrigin
, Rop4
);
462 /* Clip the blt to the clip rectangle */
463 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
464 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
465 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
466 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
467 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
469 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
470 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
471 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
472 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
473 &AdjustedBrushOrigin
, Rop4
);
478 if (OutputObj
== InputObj
)
480 if (OutputRect
.top
< InputPoint
.y
)
482 Direction
= OutputRect
.left
< InputPoint
.x
?
483 CD_RIGHTDOWN
: CD_LEFTDOWN
;
487 Direction
= OutputRect
.left
< InputPoint
.x
?
488 CD_RIGHTUP
: CD_LEFTUP
;
495 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
498 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
501 for (i
= 0; i
< RectEnum
.c
; i
++)
503 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
504 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
505 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
506 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
507 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
509 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
510 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
511 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
,
512 ColorTranslation
, &CombinedRect
, &Pt
,
513 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
523 IntEngLeave(&EnterLeaveDest
);
526 IntEngLeave(&EnterLeaveSource
);
533 IntEngBitBltEx(SURFOBJ
*DestSurf
,
537 XLATEOBJ
*ColorTranslation
,
547 RECTL InputClippedRect
;
552 BITMAPOBJ
*SourceObj
= NULL
;
555 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
558 InputClippedRect
= *DestRect
;
559 if (InputClippedRect
.right
< InputClippedRect
.left
)
561 InputClippedRect
.left
= DestRect
->right
;
562 InputClippedRect
.right
= DestRect
->left
;
564 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
566 InputClippedRect
.top
= DestRect
->bottom
;
567 InputClippedRect
.bottom
= DestRect
->top
;
569 UsesSource
= ROP4_USES_SOURCE(Rop4
);
572 if (NULL
== SourcePoint
|| NULL
== SourceSurf
)
576 InputPoint
= *SourcePoint
;
578 /* Make sure we don't try to copy anything outside the valid source
580 if (InputPoint
.x
< 0)
582 InputClippedRect
.left
-= InputPoint
.x
;
585 if (InputPoint
.y
< 0)
587 InputClippedRect
.top
-= InputPoint
.y
;
590 if (SourceSurf
->sizlBitmap
.cx
< InputPoint
.x
+
591 InputClippedRect
.right
-
592 InputClippedRect
.left
)
594 InputClippedRect
.right
= InputClippedRect
.left
+
595 SourceSurf
->sizlBitmap
.cx
- InputPoint
.x
;
597 if (SourceSurf
->sizlBitmap
.cy
< InputPoint
.y
+
598 InputClippedRect
.bottom
-
599 InputClippedRect
.top
)
601 InputClippedRect
.bottom
= InputClippedRect
.top
+
602 SourceSurf
->sizlBitmap
.cy
- InputPoint
.y
;
605 if (InputClippedRect
.right
< InputClippedRect
.left
||
606 InputClippedRect
.bottom
< InputClippedRect
.top
)
608 /* Everything clipped away, nothing to do */
613 /* Clip against the bounds of the clipping region so we won't try to write
614 * outside the surface */
615 if (NULL
!= ClipRegion
)
617 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
618 &ClipRegion
->rclBounds
))
622 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
623 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
627 OutputRect
= InputClippedRect
;
632 BITMAPOBJ_LockBitmapBits(DestObj
);
636 if (SourceSurf
!= DestSurf
)
638 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
639 BITMAPOBJ_LockBitmapBits(SourceObj
);
641 MouseSafetyOnDrawStart(SourceSurf
, InputPoint
.x
, InputPoint
.y
,
642 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
643 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
645 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
646 OutputRect
.right
, OutputRect
.bottom
);
652 /* Call the driver's DrvBitBlt if available */
653 if (DestObj
->flHooks
& HOOK_BITBLT
)
655 ret
= GDIDEVFUNCS(DestSurf
).BitBlt(
656 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
657 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
663 ret
= EngBitBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
664 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
670 MouseSafetyOnDrawEnd(DestSurf
);
673 MouseSafetyOnDrawEnd(SourceSurf
);
674 if (SourceSurf
!= DestSurf
)
676 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
680 BITMAPOBJ_UnlockBitmapBits(DestObj
);
686 static BOOLEAN STDCALL
687 CallDibStretchBlt(SURFOBJ
* OutputObj
,
691 XLATEOBJ
* ColorTranslation
,
698 POINTL RealBrushOrigin
;
699 if (BrushOrigin
== NULL
)
701 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
705 RealBrushOrigin
= *BrushOrigin
;
707 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_StretchBlt(
708 OutputObj
, InputObj
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
716 IN SURFOBJ
*SourceObj
,
718 IN CLIPOBJ
*ClipRegion
,
719 IN XLATEOBJ
*ColorTranslation
,
720 IN COLORADJUSTMENT
*pca
,
721 IN POINTL
*BrushOrigin
,
724 IN POINTL
*MaskOrigin
,
728 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
734 INTENG_ENTER_LEAVE EnterLeaveSource
;
735 INTENG_ENTER_LEAVE EnterLeaveDest
;
738 PSTRETCHRECTFUNC BltRectFunc
;
740 POINTL AdjustedBrushOrigin
;
742 InputRect
.left
= prclSrc
->left
;
743 InputRect
.right
= prclSrc
->right
;
744 InputRect
.top
= prclSrc
->top
;
745 InputRect
.bottom
= prclSrc
->bottom
;
747 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
752 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
753 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
755 OutputRect
= *prclDest
;
757 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
759 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
761 IntEngLeave(&EnterLeaveSource
);
765 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
767 IntEngLeave(&EnterLeaveSource
);
771 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
772 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
773 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
774 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
776 if (NULL
!= BrushOrigin
)
778 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
779 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
783 AdjustedBrushOrigin
= Translate
;
788 //BltRectFunc = BltMask;
789 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
790 IntEngLeave(&EnterLeaveDest
);
791 IntEngLeave(&EnterLeaveSource
);
797 BltRectFunc
= CallDibStretchBlt
;
801 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ClipRegion
,
802 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
803 &AdjustedBrushOrigin
, Mode
);
805 IntEngLeave(&EnterLeaveDest
);
806 IntEngLeave(&EnterLeaveSource
);
812 IntEngStretchBlt(SURFOBJ
*DestSurf
,
816 XLATEOBJ
*ColorTranslation
,
828 BITMAPOBJ
*SourceObj
= NULL
;
831 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
834 if (pMaskOrigin
!= NULL
)
836 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
842 BITMAPOBJ_LockBitmapBits(DestObj
);
843 MouseSafetyOnDrawStart(DestSurf
, DestRect
->left
, DestRect
->top
,
844 DestRect
->right
, DestRect
->bottom
);
846 if (NULL
!= SourceSurf
)
848 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
850 if (SourceSurf
!= DestSurf
)
852 BITMAPOBJ_LockBitmapBits(SourceObj
);
854 MouseSafetyOnDrawStart(SourceSurf
, SourceRect
->left
, SourceRect
->top
,
855 SourceRect
->right
, SourceRect
->bottom
);
858 /* Prepare color adjustment */
860 /* Call the driver's DrvStretchBlt if available */
861 if (DestObj
->flHooks
& HOOK_STRETCHBLT
)
863 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
864 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
865 // FIXME: MaskOrigin is always NULL !
866 ret
= GDIDEVFUNCS(DestSurf
).StretchBlt(
867 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
868 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
873 // FIXME: see previous fixme
874 ret
= EngStretchBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
875 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
878 if (NULL
!= SourceSurf
)
880 MouseSafetyOnDrawEnd(SourceSurf
);
881 if (SourceSurf
!= DestSurf
)
883 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
886 MouseSafetyOnDrawEnd(DestSurf
);
887 BITMAPOBJ_UnlockBitmapBits(DestObj
);
894 EngAlphaBlend(IN SURFOBJ
*Dest
,
896 IN CLIPOBJ
*ClipRegion
,
897 IN XLATEOBJ
*ColorTranslation
,
899 IN PRECTL SourceRect
,
900 IN BLENDOBJ
*BlendObj
)
902 RECTL SourceStretchedRect
;
903 SIZEL SourceStretchedSize
;
904 HBITMAP SourceStretchedBitmap
= 0;
905 SURFOBJ
* SourceStretchedObj
= NULL
;
912 INTENG_ENTER_LEAVE EnterLeaveSource
;
913 INTENG_ENTER_LEAVE EnterLeaveDest
;
923 DPRINT("EngAlphaBlend(Dest:0x%p, Source:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", Dest
, Source
, ClipRegion
, ColorTranslation
);
924 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
925 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
926 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
927 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
928 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
929 BlendObj
->BlendFunction
.AlphaFormat
);
932 if (DestRect
->left
>= DestRect
->right
|| DestRect
->top
>= DestRect
->bottom
)
934 DPRINT1("Empty destination rectangle!\n");
937 if (SourceRect
->left
>= SourceRect
->right
|| SourceRect
->top
>= SourceRect
->bottom
)
939 DPRINT1("Empty source rectangle!\n");
942 if (Dest
== Source
&&
943 !(DestRect
->left
>= SourceRect
->right
|| SourceRect
->left
>= DestRect
->right
||
944 DestRect
->top
>= SourceRect
->bottom
|| SourceRect
->top
>= DestRect
->bottom
))
946 DPRINT1("Source and destination rectangles overlap!\n");
950 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
952 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
955 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
957 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
960 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
962 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
966 /* Check if there is anything to draw */
967 if (ClipRegion
!= NULL
&&
968 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
969 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
975 /* Stretch source if needed */
976 if (DestRect
->right
- DestRect
->left
!= SourceRect
->right
- SourceRect
->left
||
977 DestRect
->bottom
- DestRect
->top
!= SourceRect
->bottom
- SourceRect
->top
)
979 SourceStretchedSize
.cx
= DestRect
->right
- DestRect
->left
;
980 SourceStretchedSize
.cy
= DestRect
->bottom
- DestRect
->top
;
981 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(Source
->iBitmapFormat
));
982 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
983 if possible to get a HW accelerated stretch. */
984 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, Source
->iBitmapFormat
,
985 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
986 if (SourceStretchedBitmap
== 0)
988 DPRINT1("EngCreateBitmap failed!\n");
991 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
992 if (SourceStretchedObj
== NULL
)
994 DPRINT1("EngLockSurface failed!\n");
995 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
999 SourceStretchedRect
.left
= 0;
1000 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
1001 SourceStretchedRect
.top
= 0;
1002 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
1003 /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
1004 try to acquire an already acquired mutex (lock the already locked source surface) */
1005 /*if (!IntEngStretchBlt(SourceStretchedObj, Source, NULL, NULL,
1006 NULL, &SourceStretchedRect, SourceRect, NULL,
1007 NULL, NULL, COLORONCOLOR))*/
1008 if (!EngStretchBlt(SourceStretchedObj
, Source
, NULL
, NULL
, NULL
,
1009 NULL
, NULL
, &SourceStretchedRect
, SourceRect
,
1010 NULL
, COLORONCOLOR
))
1012 DPRINT1("EngStretchBlt failed!\n");
1013 EngFreeMem(SourceStretchedObj
->pvBits
);
1014 EngUnlockSurface(SourceStretchedObj
);
1015 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1018 SourceRect
= &SourceStretchedRect
;
1019 Source
= SourceStretchedObj
;
1022 /* Now call the DIB function */
1023 InputRect
.left
= SourceRect
->left
;
1024 InputRect
.right
= SourceRect
->right
;
1025 InputRect
.top
= SourceRect
->top
;
1026 InputRect
.bottom
= SourceRect
->bottom
;
1027 if (!IntEngEnter(&EnterLeaveSource
, Source
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1029 if (SourceStretchedObj
!= NULL
)
1031 EngFreeMem(SourceStretchedObj
->pvBits
);
1032 EngUnlockSurface(SourceStretchedObj
);
1034 if (SourceStretchedBitmap
!= 0)
1036 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1040 InputRect
.left
= SourceRect
->left
+ Translate
.x
;
1041 InputRect
.right
= SourceRect
->right
+ Translate
.x
;
1042 InputRect
.top
= SourceRect
->top
+ Translate
.y
;
1043 InputRect
.bottom
= SourceRect
->bottom
+ Translate
.y
;
1045 OutputRect
.left
= DestRect
->left
;
1046 OutputRect
.right
= DestRect
->right
;
1047 OutputRect
.top
= DestRect
->top
;
1048 OutputRect
.bottom
= DestRect
->bottom
;
1049 if (!IntEngEnter(&EnterLeaveDest
, Dest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1051 IntEngLeave(&EnterLeaveSource
);
1052 if (SourceStretchedObj
!= NULL
)
1054 EngFreeMem(SourceStretchedObj
->pvBits
);
1055 EngUnlockSurface(SourceStretchedObj
);
1057 if (SourceStretchedBitmap
!= 0)
1059 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1063 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1064 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1065 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1066 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1069 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
1070 switch(ClippingType
)
1073 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1074 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
1078 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1079 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1080 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1081 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1082 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1084 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1085 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1086 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1087 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1088 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1089 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
1095 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
1098 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1101 for (i
= 0; i
< RectEnum
.c
; i
++)
1103 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1104 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1105 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1106 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1107 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1109 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1110 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1111 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1112 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1113 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1114 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
1127 IntEngLeave(&EnterLeaveDest
);
1128 IntEngLeave(&EnterLeaveSource
);
1130 if (SourceStretchedObj
!= NULL
)
1132 EngFreeMem(SourceStretchedObj
->pvBits
);
1133 EngUnlockSurface(SourceStretchedObj
);
1135 if (SourceStretchedBitmap
!= 0)
1137 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1144 IntEngAlphaBlend(IN SURFOBJ
*Dest
,
1146 IN CLIPOBJ
*ClipRegion
,
1147 IN XLATEOBJ
*ColorTranslation
,
1149 IN PRECTL SourceRect
,
1150 IN BLENDOBJ
*BlendObj
)
1154 BITMAPOBJ
*SourceObj
;
1157 DestObj
= CONTAINING_RECORD(Dest
, BITMAPOBJ
, SurfObj
);
1161 SourceObj
= CONTAINING_RECORD(Source
, BITMAPOBJ
, SurfObj
);
1167 /* Check if there is anything to draw */
1168 if (ClipRegion
!= NULL
&&
1169 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1170 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1176 BITMAPOBJ_LockBitmapBits(DestObj
);
1177 MouseSafetyOnDrawStart(Dest
, DestRect
->left
, DestRect
->top
,
1178 DestRect
->right
, DestRect
->bottom
);
1181 BITMAPOBJ_LockBitmapBits(SourceObj
);
1182 MouseSafetyOnDrawStart(Source
, SourceRect
->left
, SourceRect
->top
,
1183 SourceRect
->right
, SourceRect
->bottom
);
1185 /* Call the driver's DrvAlphaBlend if available */
1186 if (DestObj
->flHooks
& HOOK_ALPHABLEND
)
1188 ret
= GDIDEVFUNCS(Dest
).AlphaBlend(
1189 Dest
, Source
, ClipRegion
, ColorTranslation
,
1190 DestRect
, SourceRect
, BlendObj
);
1195 ret
= EngAlphaBlend(Dest
, Source
, ClipRegion
, ColorTranslation
,
1196 DestRect
, SourceRect
, BlendObj
);
1199 MouseSafetyOnDrawEnd(Source
);
1201 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
1202 MouseSafetyOnDrawEnd(Dest
);
1203 BITMAPOBJ_UnlockBitmapBits(DestObj
);
1208 /**** REACTOS FONT RENDERING CODE *********************************************/
1210 /* renders the alpha mask bitmap */
1211 static BOOLEAN STDCALL
1212 AlphaBltMask(SURFOBJ
* Dest
,
1215 XLATEOBJ
* ColorTranslation
,
1216 XLATEOBJ
* SrcColorTranslation
,
1218 POINTL
* SourcePoint
,
1225 ULONG Background
, BrushColor
, NewColor
;
1226 BYTE
*tMask
, *lMask
;
1228 dx
= DestRect
->right
- DestRect
->left
;
1229 dy
= DestRect
->bottom
- DestRect
->top
;
1233 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
1234 r
= (int)GetRValue(BrushColor
);
1235 g
= (int)GetGValue(BrushColor
);
1236 b
= (int)GetBValue(BrushColor
);
1238 tMask
= (PBYTE
)Mask
->pvScan0
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
1239 for (j
= 0; j
< dy
; j
++)
1242 for (i
= 0; i
< dx
; i
++)
1248 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1249 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
1253 Background
= DIB_GetSource(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
1254 SrcColorTranslation
);
1257 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
1258 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
1259 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
1261 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
1262 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1263 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
1268 tMask
+= Mask
->lDelta
;
1279 EngMaskBitBlt(SURFOBJ
*DestObj
,
1281 CLIPOBJ
*ClipRegion
,
1282 XLATEOBJ
*DestColorTranslation
,
1283 XLATEOBJ
*SourceColorTranslation
,
1285 POINTL
*SourcePoint
,
1288 POINTL
*BrushOrigin
)
1298 INTENG_ENTER_LEAVE EnterLeaveSource
;
1299 INTENG_ENTER_LEAVE EnterLeaveDest
;
1307 POINTL AdjustedBrushOrigin
;
1311 if (NULL
!= SourcePoint
)
1313 InputRect
.left
= SourcePoint
->x
;
1314 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
1315 InputRect
.top
= SourcePoint
->y
;
1316 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
1321 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1323 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1326 if (! IntEngEnter(&EnterLeaveSource
, DestObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1331 if (NULL
!= SourcePoint
)
1333 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
1334 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
1342 OutputRect
= *DestRect
;
1343 if (NULL
!= ClipRegion
)
1345 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1347 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1348 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1349 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1351 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1353 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1354 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1356 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1358 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1359 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1360 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1362 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1364 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1365 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1369 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1371 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1373 IntEngLeave(&EnterLeaveSource
);
1377 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1379 IntEngLeave(&EnterLeaveSource
);
1383 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1384 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1385 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1386 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1390 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1391 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1394 AdjustedBrushOrigin
= Translate
;
1396 // Determine clipping type
1397 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1399 clippingType
= DC_TRIVIAL
;
1401 clippingType
= ClipRegion
->iDComplexity
;
1404 switch(clippingType
)
1407 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1408 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1409 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1411 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1412 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1416 // Clip the blt to the clip rectangle
1417 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1418 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1419 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1420 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1421 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1423 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1424 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1425 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1427 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1428 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1432 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1433 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, R4_MASK
);
1439 if (OutputObj
== InputObj
)
1441 if (OutputRect
.top
< InputPoint
.y
)
1443 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1447 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1454 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1457 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1459 for (i
= 0; i
< RectEnum
.c
; i
++)
1461 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1462 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1463 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1464 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1465 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1467 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1468 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1469 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1471 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
,
1472 DestColorTranslation
,
1473 SourceColorTranslation
,
1474 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
1475 &AdjustedBrushOrigin
) && Ret
;
1479 Ret
= BltMask(OutputObj
, InputObj
, Mask
,
1480 DestColorTranslation
, &CombinedRect
, &Pt
,
1481 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1492 IntEngLeave(&EnterLeaveDest
);
1493 IntEngLeave(&EnterLeaveSource
);
1499 IntEngMaskBlt(SURFOBJ
*DestSurf
,
1501 CLIPOBJ
*ClipRegion
,
1502 XLATEOBJ
*DestColorTranslation
,
1503 XLATEOBJ
*SourceColorTranslation
,
1505 POINTL
*SourcePoint
,
1508 POINTL
*BrushOrigin
)
1517 if (NULL
!= SourcePoint
)
1519 InputPoint
= *SourcePoint
;
1522 /* Clip against the bounds of the clipping region so we won't try to write
1523 * outside the surface */
1524 if (NULL
!= ClipRegion
)
1526 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1530 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1531 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1535 OutputRect
= *DestRect
;
1538 /* No success yet */
1541 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
1543 BITMAPOBJ_LockBitmapBits(DestObj
);
1544 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
1545 OutputRect
.right
, OutputRect
.bottom
);
1547 /* Dummy BitBlt to let driver know that it should flush its changes.
1548 This should really be done using a call to DrvSynchronizeSurface,
1549 but the VMware driver doesn't hook that call. */
1550 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1551 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1554 ret
= EngMaskBitBlt(DestSurf
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1555 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1557 /* Dummy BitBlt to let driver know that something has changed. */
1558 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1559 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1562 MouseSafetyOnDrawEnd(DestSurf
);
1563 BITMAPOBJ_UnlockBitmapBits(DestObj
);