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
);
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
;
454 switch (clippingType
)
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
;
554 if (DestSurf
== NULL
)
558 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
561 InputClippedRect
= *DestRect
;
562 if (InputClippedRect
.right
< InputClippedRect
.left
)
564 InputClippedRect
.left
= DestRect
->right
;
565 InputClippedRect
.right
= DestRect
->left
;
567 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
569 InputClippedRect
.top
= DestRect
->bottom
;
570 InputClippedRect
.bottom
= DestRect
->top
;
572 UsesSource
= ROP4_USES_SOURCE(Rop4
);
575 if (NULL
== SourcePoint
|| NULL
== SourceSurf
)
579 InputPoint
= *SourcePoint
;
581 /* Make sure we don't try to copy anything outside the valid source
583 if (InputPoint
.x
< 0)
585 InputClippedRect
.left
-= InputPoint
.x
;
588 if (InputPoint
.y
< 0)
590 InputClippedRect
.top
-= InputPoint
.y
;
593 if (SourceSurf
->sizlBitmap
.cx
< InputPoint
.x
+
594 InputClippedRect
.right
-
595 InputClippedRect
.left
)
597 InputClippedRect
.right
= InputClippedRect
.left
+
598 SourceSurf
->sizlBitmap
.cx
- InputPoint
.x
;
600 if (SourceSurf
->sizlBitmap
.cy
< InputPoint
.y
+
601 InputClippedRect
.bottom
-
602 InputClippedRect
.top
)
604 InputClippedRect
.bottom
= InputClippedRect
.top
+
605 SourceSurf
->sizlBitmap
.cy
- InputPoint
.y
;
608 if (InputClippedRect
.right
< InputClippedRect
.left
||
609 InputClippedRect
.bottom
< InputClippedRect
.top
)
611 /* Everything clipped away, nothing to do */
616 /* Clip against the bounds of the clipping region so we won't try to write
617 * outside the surface */
618 if (NULL
!= ClipRegion
)
620 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
,
621 &ClipRegion
->rclBounds
))
625 InputPoint
.x
+= OutputRect
.left
- InputClippedRect
.left
;
626 InputPoint
.y
+= OutputRect
.top
- InputClippedRect
.top
;
630 OutputRect
= InputClippedRect
;
635 BITMAPOBJ_LockBitmapBits(DestObj
);
639 if (SourceSurf
!= DestSurf
)
641 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
642 BITMAPOBJ_LockBitmapBits(SourceObj
);
644 MouseSafetyOnDrawStart(SourceSurf
, InputPoint
.x
, InputPoint
.y
,
645 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
646 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
648 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
649 OutputRect
.right
, OutputRect
.bottom
);
655 /* Call the driver's DrvBitBlt if available */
656 if (DestObj
->flHooks
& HOOK_BITBLT
)
658 ret
= GDIDEVFUNCS(DestSurf
).BitBlt(
659 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
660 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
666 ret
= EngBitBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
667 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
673 MouseSafetyOnDrawEnd(DestSurf
);
676 MouseSafetyOnDrawEnd(SourceSurf
);
677 if (SourceSurf
!= DestSurf
)
679 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
683 BITMAPOBJ_UnlockBitmapBits(DestObj
);
689 static BOOLEAN STDCALL
690 CallDibStretchBlt(SURFOBJ
* OutputObj
,
694 XLATEOBJ
* ColorTranslation
,
701 POINTL RealBrushOrigin
;
702 if (BrushOrigin
== NULL
)
704 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
708 RealBrushOrigin
= *BrushOrigin
;
710 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_StretchBlt(
711 OutputObj
, InputObj
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
719 IN SURFOBJ
*SourceObj
,
721 IN CLIPOBJ
*ClipRegion
,
722 IN XLATEOBJ
*ColorTranslation
,
723 IN COLORADJUSTMENT
*pca
,
724 IN POINTL
*BrushOrigin
,
727 IN POINTL
*MaskOrigin
,
731 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
737 INTENG_ENTER_LEAVE EnterLeaveSource
;
738 INTENG_ENTER_LEAVE EnterLeaveDest
;
741 PSTRETCHRECTFUNC BltRectFunc
;
743 POINTL AdjustedBrushOrigin
;
745 InputRect
.left
= prclSrc
->left
;
746 InputRect
.right
= prclSrc
->right
;
747 InputRect
.top
= prclSrc
->top
;
748 InputRect
.bottom
= prclSrc
->bottom
;
750 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
755 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
756 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
758 OutputRect
= *prclDest
;
760 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
762 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
764 IntEngLeave(&EnterLeaveSource
);
768 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
770 IntEngLeave(&EnterLeaveSource
);
774 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
775 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
776 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
777 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
779 if (NULL
!= BrushOrigin
)
781 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
782 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
786 AdjustedBrushOrigin
= Translate
;
791 //BltRectFunc = BltMask;
792 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
793 IntEngLeave(&EnterLeaveDest
);
794 IntEngLeave(&EnterLeaveSource
);
800 BltRectFunc
= CallDibStretchBlt
;
804 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ClipRegion
,
805 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
806 &AdjustedBrushOrigin
, Mode
);
808 IntEngLeave(&EnterLeaveDest
);
809 IntEngLeave(&EnterLeaveSource
);
815 IntEngStretchBlt(SURFOBJ
*DestSurf
,
819 XLATEOBJ
*ColorTranslation
,
831 BITMAPOBJ
*SourceObj
= NULL
;
834 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
837 if (pMaskOrigin
!= NULL
)
839 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
845 BITMAPOBJ_LockBitmapBits(DestObj
);
846 MouseSafetyOnDrawStart(DestSurf
, DestRect
->left
, DestRect
->top
,
847 DestRect
->right
, DestRect
->bottom
);
849 if (NULL
!= SourceSurf
)
851 SourceObj
= CONTAINING_RECORD(SourceSurf
, BITMAPOBJ
, SurfObj
);
853 if (SourceSurf
!= DestSurf
)
855 BITMAPOBJ_LockBitmapBits(SourceObj
);
857 MouseSafetyOnDrawStart(SourceSurf
, SourceRect
->left
, SourceRect
->top
,
858 SourceRect
->right
, SourceRect
->bottom
);
861 /* Prepare color adjustment */
863 /* Call the driver's DrvStretchBlt if available */
864 if (DestObj
->flHooks
& HOOK_STRETCHBLT
)
866 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
867 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
868 // FIXME: MaskOrigin is always NULL !
869 ret
= GDIDEVFUNCS(DestSurf
).StretchBlt(
870 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
871 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
876 // FIXME: see previous fixme
877 ret
= EngStretchBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
878 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
881 if (NULL
!= SourceSurf
)
883 MouseSafetyOnDrawEnd(SourceSurf
);
884 if (SourceSurf
!= DestSurf
)
886 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
889 MouseSafetyOnDrawEnd(DestSurf
);
890 BITMAPOBJ_UnlockBitmapBits(DestObj
);
897 EngAlphaBlend(IN SURFOBJ
*Dest
,
899 IN CLIPOBJ
*ClipRegion
,
900 IN XLATEOBJ
*ColorTranslation
,
902 IN PRECTL SourceRect
,
903 IN BLENDOBJ
*BlendObj
)
905 RECTL SourceStretchedRect
;
906 SIZEL SourceStretchedSize
;
907 HBITMAP SourceStretchedBitmap
= 0;
908 SURFOBJ
* SourceStretchedObj
= NULL
;
915 INTENG_ENTER_LEAVE EnterLeaveSource
;
916 INTENG_ENTER_LEAVE EnterLeaveDest
;
926 DPRINT("EngAlphaBlend(Dest:0x%p, Source:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", Dest
, Source
, ClipRegion
, ColorTranslation
);
927 DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
928 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
,
929 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
);
930 DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj
->BlendFunction
.BlendOp
,
931 BlendObj
->BlendFunction
.BlendFlags
, BlendObj
->BlendFunction
.SourceConstantAlpha
,
932 BlendObj
->BlendFunction
.AlphaFormat
);
935 if (DestRect
->left
>= DestRect
->right
|| DestRect
->top
>= DestRect
->bottom
)
937 DPRINT1("Empty destination rectangle!\n");
940 if (SourceRect
->left
>= SourceRect
->right
|| SourceRect
->top
>= SourceRect
->bottom
)
942 DPRINT1("Empty source rectangle!\n");
945 if (Dest
== Source
&&
946 !(DestRect
->left
>= SourceRect
->right
|| SourceRect
->left
>= DestRect
->right
||
947 DestRect
->top
>= SourceRect
->bottom
|| SourceRect
->top
>= DestRect
->bottom
))
949 DPRINT1("Source and destination rectangles overlap!\n");
953 if (BlendObj
->BlendFunction
.BlendOp
!= AC_SRC_OVER
)
955 DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj
->BlendFunction
.BlendOp
);
958 if (BlendObj
->BlendFunction
.BlendFlags
!= 0)
960 DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj
->BlendFunction
.BlendFlags
);
963 if ((BlendObj
->BlendFunction
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
965 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj
->BlendFunction
.AlphaFormat
);
969 /* Check if there is anything to draw */
970 if (ClipRegion
!= NULL
&&
971 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
972 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
978 /* Stretch source if needed */
979 if (DestRect
->right
- DestRect
->left
!= SourceRect
->right
- SourceRect
->left
||
980 DestRect
->bottom
- DestRect
->top
!= SourceRect
->bottom
- SourceRect
->top
)
982 SourceStretchedSize
.cx
= DestRect
->right
- DestRect
->left
;
983 SourceStretchedSize
.cy
= DestRect
->bottom
- DestRect
->top
;
984 Width
= DIB_GetDIBWidthBytes(SourceStretchedSize
.cx
, BitsPerFormat(Source
->iBitmapFormat
));
985 /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
986 if possible to get a HW accelerated stretch. */
987 SourceStretchedBitmap
= EngCreateBitmap(SourceStretchedSize
, Width
, Source
->iBitmapFormat
,
988 BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
989 if (SourceStretchedBitmap
== 0)
991 DPRINT1("EngCreateBitmap failed!\n");
994 SourceStretchedObj
= EngLockSurface((HSURF
)SourceStretchedBitmap
);
995 if (SourceStretchedObj
== NULL
)
997 DPRINT1("EngLockSurface failed!\n");
998 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1002 SourceStretchedRect
.left
= 0;
1003 SourceStretchedRect
.right
= SourceStretchedSize
.cx
;
1004 SourceStretchedRect
.top
= 0;
1005 SourceStretchedRect
.bottom
= SourceStretchedSize
.cy
;
1006 /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
1007 try to acquire an already acquired mutex (lock the already locked source surface) */
1008 /*if (!IntEngStretchBlt(SourceStretchedObj, Source, NULL, NULL,
1009 NULL, &SourceStretchedRect, SourceRect, NULL,
1010 NULL, NULL, COLORONCOLOR))*/
1011 if (!EngStretchBlt(SourceStretchedObj
, Source
, NULL
, NULL
, NULL
,
1012 NULL
, NULL
, &SourceStretchedRect
, SourceRect
,
1013 NULL
, COLORONCOLOR
))
1015 DPRINT1("EngStretchBlt failed!\n");
1016 EngFreeMem(SourceStretchedObj
->pvBits
);
1017 EngUnlockSurface(SourceStretchedObj
);
1018 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1021 SourceRect
= &SourceStretchedRect
;
1022 Source
= SourceStretchedObj
;
1025 /* Now call the DIB function */
1026 InputRect
.left
= SourceRect
->left
;
1027 InputRect
.right
= SourceRect
->right
;
1028 InputRect
.top
= SourceRect
->top
;
1029 InputRect
.bottom
= SourceRect
->bottom
;
1030 if (!IntEngEnter(&EnterLeaveSource
, Source
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1032 if (SourceStretchedObj
!= NULL
)
1034 EngFreeMem(SourceStretchedObj
->pvBits
);
1035 EngUnlockSurface(SourceStretchedObj
);
1037 if (SourceStretchedBitmap
!= 0)
1039 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1043 InputRect
.left
= SourceRect
->left
+ Translate
.x
;
1044 InputRect
.right
= SourceRect
->right
+ Translate
.x
;
1045 InputRect
.top
= SourceRect
->top
+ Translate
.y
;
1046 InputRect
.bottom
= SourceRect
->bottom
+ Translate
.y
;
1048 OutputRect
.left
= DestRect
->left
;
1049 OutputRect
.right
= DestRect
->right
;
1050 OutputRect
.top
= DestRect
->top
;
1051 OutputRect
.bottom
= DestRect
->bottom
;
1052 if (!IntEngEnter(&EnterLeaveDest
, Dest
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1054 IntEngLeave(&EnterLeaveSource
);
1055 if (SourceStretchedObj
!= NULL
)
1057 EngFreeMem(SourceStretchedObj
->pvBits
);
1058 EngUnlockSurface(SourceStretchedObj
);
1060 if (SourceStretchedBitmap
!= 0)
1062 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1066 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1067 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1068 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1069 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1072 ClippingType
= (ClipRegion
== NULL
) ? DC_TRIVIAL
: ClipRegion
->iDComplexity
;
1073 switch (ClippingType
)
1076 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1077 OutputObj
, InputObj
, &OutputRect
, &InputRect
, ClipRegion
, ColorTranslation
, BlendObj
);
1081 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1082 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1083 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1084 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1085 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1087 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1088 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1089 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1090 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1091 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1092 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
);
1098 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
1101 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
),
1104 for (i
= 0; i
< RectEnum
.c
; i
++)
1106 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1107 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1108 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1109 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1110 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1112 Rect
.left
= InputRect
.left
+ CombinedRect
.left
- OutputRect
.left
;
1113 Rect
.right
= InputRect
.right
+ CombinedRect
.right
- OutputRect
.right
;
1114 Rect
.top
= InputRect
.top
+ CombinedRect
.top
- OutputRect
.top
;
1115 Rect
.bottom
= InputRect
.bottom
+ CombinedRect
.bottom
- OutputRect
.bottom
;
1116 Ret
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_AlphaBlend(
1117 OutputObj
, InputObj
, &CombinedRect
, &Rect
, ClipRegion
, ColorTranslation
, BlendObj
) && Ret
;
1130 IntEngLeave(&EnterLeaveDest
);
1131 IntEngLeave(&EnterLeaveSource
);
1133 if (SourceStretchedObj
!= NULL
)
1135 EngFreeMem(SourceStretchedObj
->pvBits
);
1136 EngUnlockSurface(SourceStretchedObj
);
1138 if (SourceStretchedBitmap
!= 0)
1140 EngDeleteSurface((HSURF
)SourceStretchedBitmap
);
1147 IntEngAlphaBlend(IN SURFOBJ
*Dest
,
1149 IN CLIPOBJ
*ClipRegion
,
1150 IN XLATEOBJ
*ColorTranslation
,
1152 IN PRECTL SourceRect
,
1153 IN BLENDOBJ
*BlendObj
)
1157 BITMAPOBJ
*SourceObj
;
1160 DestObj
= CONTAINING_RECORD(Dest
, BITMAPOBJ
, SurfObj
);
1164 SourceObj
= CONTAINING_RECORD(Source
, BITMAPOBJ
, SurfObj
);
1170 /* Check if there is anything to draw */
1171 if (ClipRegion
!= NULL
&&
1172 (ClipRegion
->rclBounds
.left
>= ClipRegion
->rclBounds
.right
||
1173 ClipRegion
->rclBounds
.top
>= ClipRegion
->rclBounds
.bottom
))
1179 BITMAPOBJ_LockBitmapBits(DestObj
);
1180 MouseSafetyOnDrawStart(Dest
, DestRect
->left
, DestRect
->top
,
1181 DestRect
->right
, DestRect
->bottom
);
1184 BITMAPOBJ_LockBitmapBits(SourceObj
);
1185 MouseSafetyOnDrawStart(Source
, SourceRect
->left
, SourceRect
->top
,
1186 SourceRect
->right
, SourceRect
->bottom
);
1188 /* Call the driver's DrvAlphaBlend if available */
1189 if (DestObj
->flHooks
& HOOK_ALPHABLEND
)
1191 ret
= GDIDEVFUNCS(Dest
).AlphaBlend(
1192 Dest
, Source
, ClipRegion
, ColorTranslation
,
1193 DestRect
, SourceRect
, BlendObj
);
1198 ret
= EngAlphaBlend(Dest
, Source
, ClipRegion
, ColorTranslation
,
1199 DestRect
, SourceRect
, BlendObj
);
1202 MouseSafetyOnDrawEnd(Source
);
1204 BITMAPOBJ_UnlockBitmapBits(SourceObj
);
1205 MouseSafetyOnDrawEnd(Dest
);
1206 BITMAPOBJ_UnlockBitmapBits(DestObj
);
1211 /**** REACTOS FONT RENDERING CODE *********************************************/
1213 /* renders the alpha mask bitmap */
1214 static BOOLEAN STDCALL
1215 AlphaBltMask(SURFOBJ
* Dest
,
1218 XLATEOBJ
* ColorTranslation
,
1219 XLATEOBJ
* SrcColorTranslation
,
1221 POINTL
* SourcePoint
,
1228 ULONG Background
, BrushColor
, NewColor
;
1229 BYTE
*tMask
, *lMask
;
1231 dx
= DestRect
->right
- DestRect
->left
;
1232 dy
= DestRect
->bottom
- DestRect
->top
;
1236 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
1237 r
= (int)GetRValue(BrushColor
);
1238 g
= (int)GetGValue(BrushColor
);
1239 b
= (int)GetBValue(BrushColor
);
1241 tMask
= (PBYTE
)Mask
->pvScan0
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
1242 for (j
= 0; j
< dy
; j
++)
1245 for (i
= 0; i
< dx
; i
++)
1251 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1252 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
1256 Background
= DIB_GetSource(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
1257 SrcColorTranslation
);
1260 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
1261 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
1262 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
1264 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
1265 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
1266 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
1271 tMask
+= Mask
->lDelta
;
1282 EngMaskBitBlt(SURFOBJ
*DestObj
,
1284 CLIPOBJ
*ClipRegion
,
1285 XLATEOBJ
*DestColorTranslation
,
1286 XLATEOBJ
*SourceColorTranslation
,
1288 POINTL
*SourcePoint
,
1291 POINTL
*BrushOrigin
)
1301 INTENG_ENTER_LEAVE EnterLeaveSource
;
1302 INTENG_ENTER_LEAVE EnterLeaveDest
;
1310 POINTL AdjustedBrushOrigin
;
1314 if (NULL
!= SourcePoint
)
1316 InputRect
.left
= SourcePoint
->x
;
1317 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
1318 InputRect
.top
= SourcePoint
->y
;
1319 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
1324 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1326 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1329 if (! IntEngEnter(&EnterLeaveSource
, DestObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1334 if (NULL
!= SourcePoint
)
1336 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
1337 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
1345 OutputRect
= *DestRect
;
1346 if (NULL
!= ClipRegion
)
1348 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1350 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1351 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1352 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1354 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1356 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1357 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1359 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1361 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1362 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1363 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1365 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1367 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1368 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1372 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1374 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1376 IntEngLeave(&EnterLeaveSource
);
1380 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1382 IntEngLeave(&EnterLeaveSource
);
1386 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1387 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1388 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1389 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1393 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1394 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1397 AdjustedBrushOrigin
= Translate
;
1399 // Determine clipping type
1400 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1402 clippingType
= DC_TRIVIAL
;
1404 clippingType
= ClipRegion
->iDComplexity
;
1407 switch (clippingType
)
1410 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1411 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1412 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1414 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1415 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1419 // Clip the blt to the clip rectangle
1420 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1421 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1422 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1423 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1424 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1426 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1427 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1428 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1430 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1431 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1435 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1436 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, R4_MASK
);
1442 if (OutputObj
== InputObj
)
1444 if (OutputRect
.top
< InputPoint
.y
)
1446 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1450 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1457 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1460 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1462 for (i
= 0; i
< RectEnum
.c
; i
++)
1464 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1465 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1466 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1467 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1468 if (EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
))
1470 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1471 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1472 if (Mask
->iBitmapFormat
== BMF_8BPP
)
1474 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
,
1475 DestColorTranslation
,
1476 SourceColorTranslation
,
1477 &CombinedRect
, &Pt
, MaskOrigin
, Brush
,
1478 &AdjustedBrushOrigin
) && Ret
;
1482 Ret
= BltMask(OutputObj
, InputObj
, Mask
,
1483 DestColorTranslation
, &CombinedRect
, &Pt
,
1484 MaskOrigin
, Brush
, &AdjustedBrushOrigin
,
1495 IntEngLeave(&EnterLeaveDest
);
1496 IntEngLeave(&EnterLeaveSource
);
1502 IntEngMaskBlt(SURFOBJ
*DestSurf
,
1504 CLIPOBJ
*ClipRegion
,
1505 XLATEOBJ
*DestColorTranslation
,
1506 XLATEOBJ
*SourceColorTranslation
,
1508 POINTL
*SourcePoint
,
1511 POINTL
*BrushOrigin
)
1520 if (NULL
!= SourcePoint
)
1522 InputPoint
= *SourcePoint
;
1525 /* Clip against the bounds of the clipping region so we won't try to write
1526 * outside the surface */
1527 if (NULL
!= ClipRegion
)
1529 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1533 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1534 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1538 OutputRect
= *DestRect
;
1541 /* No success yet */
1544 DestObj
= CONTAINING_RECORD(DestSurf
, BITMAPOBJ
, SurfObj
);
1546 BITMAPOBJ_LockBitmapBits(DestObj
);
1547 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
1548 OutputRect
.right
, OutputRect
.bottom
);
1550 /* Dummy BitBlt to let driver know that it should flush its changes.
1551 This should really be done using a call to DrvSynchronizeSurface,
1552 but the VMware driver doesn't hook that call. */
1553 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1554 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1557 ret
= EngMaskBitBlt(DestSurf
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1558 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1560 /* Dummy BitBlt to let driver know that something has changed. */
1561 IntEngBitBltEx(DestSurf
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1562 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
,
1565 MouseSafetyOnDrawEnd(DestSurf
);
1566 BITMAPOBJ_UnlockBitmapBits(DestObj
);