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.
19 /* $Id: bitblt.c,v 1.55 2004/05/14 22:56:18 gvg Exp $
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
31 typedef BOOLEAN
STDCALL (*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
36 XLATEOBJ
* ColorTranslation
,
43 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
,
85 XLATEOBJ
* ColorTranslation
,
93 LONG i
, j
, dx
, dy
, c8
;
95 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
97 PGDIBRUSHOBJ GdiBrush
;
98 HBITMAP PatternSurface
= NULL
;
100 ULONG PatternWidth
, PatternHeight
, PatternY
;
107 dx
= DestRect
->right
- DestRect
->left
;
108 dy
= DestRect
->bottom
- DestRect
->top
;
110 if (Brush
->iSolidColor
== 0xFFFFFFFF)
112 PBITMAPOBJ PatternBitmap
;
114 GdiBrush
= CONTAINING_RECORD(
119 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
120 PatternSurface
= BitmapToSurf(PatternBitmap
, Dest
->hdev
);
121 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
123 PatternObj
= (SURFOBJ
*)AccessUserObject((ULONG
)PatternSurface
);
124 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
125 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
128 tMask
= Mask
->pvScan0
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
129 for (j
= 0; j
< dy
; j
++)
132 c8
= SourcePoint
->x
& 0x07;
135 PatternY
= (DestRect
->top
+ j
) % PatternHeight
;
137 for (i
= 0; i
< dx
; i
++)
139 if (0 != (*lMask
& maskbit
[c8
]))
141 if (PatternSurface
== NULL
)
143 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
147 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
148 DIB_1BPP_GetPixel(PatternObj
, (DestRect
->left
+ i
) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
);
158 tMask
+= Mask
->lDelta
;
161 if (PatternSurface
!= NULL
)
162 EngDeleteSurface((HSURF
)PatternSurface
);
167 static BOOLEAN STDCALL
168 BltPatCopy(SURFOBJ
* Dest
,
173 XLATEOBJ
* ColorTranslation
,
181 // These functions are assigned if we're working with a DIB
182 // The assigned functions depend on the bitsPerPixel of the DIB
186 LineWidth
= DestRect
->right
- DestRect
->left
;
187 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
189 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
195 static BOOLEAN STDCALL
196 CallDibBitBlt(SURFOBJ
* OutputObj
,
201 XLATEOBJ
* ColorTranslation
,
209 POINTL RealBrushOrigin
;
210 if (BrushOrigin
== NULL
)
212 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
216 RealBrushOrigin
= *BrushOrigin
;
218 return OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputPoint
, Brush
, RealBrushOrigin
, ColorTranslation
, Rop4
);
227 EngBitBlt(SURFOBJ
*DestObj
,
231 XLATEOBJ
*ColorTranslation
,
249 INTENG_ENTER_LEAVE EnterLeaveSource
;
250 INTENG_ENTER_LEAVE EnterLeaveDest
;
253 PBLTRECTFUNC BltRectFunc
;
261 POINTL AdjustedBrushOrigin
;
263 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
264 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
265 if (ROP_NOOP
== Rop4
)
267 /* Copy destination onto itself: nop */
271 if (NULL
!= SourcePoint
)
273 InputRect
.left
= SourcePoint
->x
;
274 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
275 InputRect
.top
= SourcePoint
->y
;
276 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
281 InputRect
.right
= DestRect
->right
- DestRect
->left
;
283 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
286 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
291 if (NULL
!= SourcePoint
)
293 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
294 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
302 if (NULL
!= InputObj
)
304 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
311 OutputRect
= *DestRect
;
312 if (NULL
!= ClipRegion
)
314 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
316 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
317 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
318 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
320 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
322 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
323 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
325 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
327 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
328 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
329 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
331 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
333 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
334 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
338 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
340 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
342 IntEngLeave(&EnterLeaveSource
);
346 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
348 IntEngLeave(&EnterLeaveSource
);
352 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
353 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
354 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
355 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
359 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
360 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
363 AdjustedBrushOrigin
= Translate
;
365 if (NULL
!= OutputObj
)
367 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
370 // Determine clipping type
371 if (ClipRegion
== (CLIPOBJ
*) NULL
)
373 clippingType
= DC_TRIVIAL
;
375 clippingType
= ClipRegion
->iDComplexity
;
380 BltRectFunc
= BltMask
;
382 else if (PATCOPY
== Rop4
)
385 BltRectFunc
= BltPatCopy
;
387 if (Brush
->iSolidColor
== 0xFFFFFFFF)
388 BltRectFunc
= CallDibBitBlt
;
390 BltRectFunc
= BltPatCopy
;
395 BltRectFunc
= CallDibBitBlt
;
402 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
403 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
406 // Clip the blt to the clip rectangle
407 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
408 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
409 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
410 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
411 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
412 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
413 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
414 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
415 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
419 if (OutputObj
== InputObj
)
421 if (OutputRect
.top
< InputPoint
.y
)
423 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
427 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
434 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
437 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
439 for (i
= 0; i
< RectEnum
.c
; i
++)
441 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
442 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
443 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
444 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
445 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
446 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
447 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
448 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
449 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
) &&
458 IntEngLeave(&EnterLeaveDest
);
459 IntEngLeave(&EnterLeaveSource
);
465 IntEngBitBlt(SURFOBJ
*DestObj
,
469 XLATEOBJ
*ColorTranslation
,
480 RECTL InputClippedRect
;
485 InputClippedRect
= *DestRect
;
486 if (InputClippedRect
.right
< InputClippedRect
.left
)
488 InputClippedRect
.left
= DestRect
->right
;
489 InputClippedRect
.right
= DestRect
->left
;
491 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
493 InputClippedRect
.top
= DestRect
->bottom
;
494 InputClippedRect
.bottom
= DestRect
->top
;
496 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
499 if (NULL
== SourcePoint
|| NULL
== SourceObj
)
503 InputPoint
= *SourcePoint
;
504 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
506 /* Make sure we don't try to copy anything outside the valid source region */
507 if (InputPoint
.x
< 0)
509 InputClippedRect
.left
-= InputPoint
.x
;
512 if (InputPoint
.y
< 0)
514 InputClippedRect
.top
-= InputPoint
.y
;
517 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+ InputClippedRect
.right
- InputClippedRect
.left
)
519 InputClippedRect
.right
= InputClippedRect
.left
+ SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
521 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+ InputClippedRect
.bottom
- InputClippedRect
.top
)
523 InputClippedRect
.bottom
= InputClippedRect
.top
+ SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
526 if (InputClippedRect
.right
< InputClippedRect
.left
||
527 InputClippedRect
.bottom
< InputClippedRect
.top
)
529 /* Everything clipped away, nothing to do */
534 /* Clip against the bounds of the clipping region so we won't try to write
535 * outside the surface */
536 if (NULL
!= ClipRegion
)
538 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
, &ClipRegion
->rclBounds
))
542 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
543 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
547 OutputRect
= InputClippedRect
;
552 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
553 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
554 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
559 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
560 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
561 OutputRect
.right
, OutputRect
.bottom
);
563 /* Call the driver's DrvBitBlt if available */
564 if (NULL
!= DestGDI
->BitBlt
)
566 IntLockGDIDriver(DestGDI
);
567 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
568 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
570 IntUnLockGDIDriver(DestGDI
);
575 IntLockGDIDriver(DestGDI
);
576 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
577 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
579 IntUnLockGDIDriver(DestGDI
);
582 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
585 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
591 static BOOLEAN STDCALL
592 CallDibStretchBlt(SURFOBJ
* OutputObj
,
598 XLATEOBJ
* ColorTranslation
,
605 POINTL RealBrushOrigin
;
606 if (BrushOrigin
== NULL
)
608 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
612 RealBrushOrigin
= *BrushOrigin
;
614 return OutputGDI
->DIB_StretchBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
622 IN SURFOBJ
*SourceObj
,
624 IN CLIPOBJ
*ClipRegion
,
625 IN XLATEOBJ
*ColorTranslation
,
626 IN COLORADJUSTMENT
*pca
,
627 IN POINTL
*BrushOrigin
,
630 IN POINTL
*MaskOrigin
,
634 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
642 INTENG_ENTER_LEAVE EnterLeaveSource
;
643 INTENG_ENTER_LEAVE EnterLeaveDest
;
646 PSTRETCHRECTFUNC BltRectFunc
;
648 POINTL AdjustedBrushOrigin
;
650 InputRect
.left
= prclSrc
->left
;
651 InputRect
.right
= prclSrc
->right
;
652 InputRect
.top
= prclSrc
->top
;
653 InputRect
.bottom
= prclSrc
->bottom
;
655 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
660 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
661 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
663 if (NULL
!= InputObj
)
665 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
672 OutputRect
= *prclDest
;
674 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
676 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
678 IntEngLeave(&EnterLeaveSource
);
682 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
684 IntEngLeave(&EnterLeaveSource
);
688 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
689 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
690 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
691 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
693 if (NULL
!= BrushOrigin
)
695 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
696 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
700 AdjustedBrushOrigin
= Translate
;
703 if (NULL
!= OutputObj
)
705 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
710 //BltRectFunc = BltMask;
711 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
712 IntEngLeave(&EnterLeaveDest
);
713 IntEngLeave(&EnterLeaveSource
);
719 BltRectFunc
= CallDibStretchBlt
;
723 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ClipRegion
,
724 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
725 &AdjustedBrushOrigin
, Mode
);
727 IntEngLeave(&EnterLeaveDest
);
728 IntEngLeave(&EnterLeaveSource
);
734 IntEngStretchBlt(SURFOBJ
*DestObj
,
738 XLATEOBJ
*ColorTranslation
,
752 if (pMaskOrigin
!= NULL
)
754 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
757 if (NULL
!= SourceObj
)
759 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
760 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, SourceRect
->left
, SourceRect
->top
,
761 (SourceRect
->left
+ abs(SourceRect
->right
- SourceRect
->left
)),
762 (SourceRect
->top
+ abs(SourceRect
->bottom
- SourceRect
->top
)));
767 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
768 MouseSafetyOnDrawStart(DestObj
, DestGDI
, DestRect
->left
, DestRect
->top
,
769 DestRect
->right
, DestRect
->bottom
);
771 /* Prepare color adjustment */
773 /* Call the driver's DrvStretchBlt if available */
774 if (NULL
!= DestGDI
->StretchBlt
)
776 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
777 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
778 // FIXME: MaskOrigin is always NULL !
779 IntLockGDIDriver(DestGDI
);
780 ret
= DestGDI
->StretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
781 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
782 IntUnLockGDIDriver(DestGDI
);
787 // FIXME: see previous fixme
788 ret
= EngStretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
789 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
792 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
793 if (NULL
!= SourceObj
)
795 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
801 /**** REACTOS FONT RENDERING CODE *********************************************/
803 /* renders the alpha mask bitmap */
804 static BOOLEAN STDCALL
805 AlphaBltMask(SURFOBJ
* Dest
,
810 XLATEOBJ
* ColorTranslation
,
811 XLATEOBJ
* SrcColorTranslation
,
820 ULONG Background
, BrushColor
, NewColor
;
823 dx
= DestRect
->right
- DestRect
->left
;
824 dy
= DestRect
->bottom
- DestRect
->top
;
828 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
829 r
= (int)GetRValue(BrushColor
);
830 g
= (int)GetGValue(BrushColor
);
831 b
= (int)GetBValue(BrushColor
);
833 tMask
= Mask
->pvBits
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
834 for (j
= 0; j
< dy
; j
++)
837 for (i
= 0; i
< dx
; i
++)
843 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
847 Background
= DIB_GetSource(Dest
, DestGDI
, DestRect
->left
+ i
, DestRect
->top
+ j
, SrcColorTranslation
);
850 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
851 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
852 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
854 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
855 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
860 tMask
+= Mask
->lDelta
;
871 EngMaskBitBlt(SURFOBJ
*DestObj
,
874 XLATEOBJ
*DestColorTranslation
,
875 XLATEOBJ
*SourceColorTranslation
,
892 INTENG_ENTER_LEAVE EnterLeaveSource
;
893 INTENG_ENTER_LEAVE EnterLeaveDest
;
902 POINTL AdjustedBrushOrigin
;
904 if (NULL
!= SourcePoint
)
906 InputRect
.left
= SourcePoint
->x
;
907 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
908 InputRect
.top
= SourcePoint
->y
;
909 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
914 InputRect
.right
= DestRect
->right
- DestRect
->left
;
916 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
919 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
920 IntLockGDIDriver(DestGDI
);
921 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
923 IntUnLockGDIDriver(DestGDI
);
927 if (NULL
!= SourcePoint
)
929 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
930 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
938 if (NULL
!= InputObj
)
940 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
947 OutputRect
= *DestRect
;
948 if (NULL
!= ClipRegion
)
950 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
952 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
953 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
954 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
956 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
958 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
959 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
961 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
963 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
964 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
965 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
967 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
969 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
970 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
974 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
976 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
978 IntEngLeave(&EnterLeaveSource
);
979 IntUnLockGDIDriver(DestGDI
);
983 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
985 IntEngLeave(&EnterLeaveSource
);
986 IntUnLockGDIDriver(DestGDI
);
990 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
991 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
992 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
993 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
997 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
998 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1001 AdjustedBrushOrigin
= Translate
;
1003 if (NULL
!= OutputObj
)
1005 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
1008 // Determine clipping type
1009 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1011 clippingType
= DC_TRIVIAL
;
1013 clippingType
= ClipRegion
->iDComplexity
;
1016 switch(clippingType
)
1019 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1020 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1021 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1023 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1024 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1027 // Clip the blt to the clip rectangle
1028 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1029 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1030 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1031 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1032 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1033 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1034 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1035 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1036 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1037 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1039 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1040 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1044 if (OutputObj
== InputObj
)
1046 if (OutputRect
.top
< InputPoint
.y
)
1048 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1052 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1059 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1062 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1064 for (i
= 0; i
< RectEnum
.c
; i
++)
1066 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1067 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1068 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1069 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1070 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1071 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1072 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1073 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1074 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1075 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
) && Ret
;
1077 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1078 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC) && Ret
;
1086 IntEngLeave(&EnterLeaveDest
);
1087 IntEngLeave(&EnterLeaveSource
);
1089 IntUnLockGDIDriver(DestGDI
);
1091 /* Dummy BitBlt to let driver know that something has changed.
1092 0x00AA0029 is the Rop for D (no-op) */
1093 IntEngBitBlt(DestObj
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1094 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, ROP_NOOP
);
1100 IntEngMaskBlt(SURFOBJ
*DestObj
,
1102 CLIPOBJ
*ClipRegion
,
1103 XLATEOBJ
*DestColorTranslation
,
1104 XLATEOBJ
*SourceColorTranslation
,
1106 POINTL
*SourcePoint
,
1109 POINTL
*BrushOrigin
)
1116 if (NULL
!= SourcePoint
)
1118 InputPoint
= *SourcePoint
;
1121 /* Clip against the bounds of the clipping region so we won't try to write
1122 * outside the surface */
1123 if (NULL
!= ClipRegion
)
1125 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1129 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1130 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1134 OutputRect
= *DestRect
;
1137 /* No success yet */
1139 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
1140 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
1141 OutputRect
.right
, OutputRect
.bottom
);
1143 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1144 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1146 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);