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.36 2003/12/26 00:31:22 weiden 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
30 #include <ddk/winddi.h>
31 #include <ddk/ntddk.h>
32 #include <ddk/ntddmou.h>
33 #include <ntos/minmax.h>
37 #include "../dib/dib.h"
39 #include <include/mouse.h>
40 #include <include/object.h>
41 #include <include/dib.h>
42 #include <include/surface.h>
43 #include <include/inteng.h>
46 #include <win32k/debug1.h>
48 typedef BOOLEAN
STDCALL (*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
53 XLATEOBJ
* ColorTranslation
,
60 typedef BOOLEAN
STDCALL (*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
65 XLATEOBJ
* ColorTranslation
,
72 BOOL STDCALL
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
74 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
76 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
77 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
79 if (prcDst
->left
< prcDst
->right
)
81 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
82 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
84 if (prcDst
->top
< prcDst
->bottom
)
95 static BOOLEAN STDCALL
96 BltMask(SURFOBJ
* Dest
,
101 XLATEOBJ
* ColorTranslation
,
109 LONG i
, j
, dx
, dy
, c8
;
111 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
113 dx
= DestRect
->right
- DestRect
->left
;
114 dy
= DestRect
->bottom
- DestRect
->top
;
118 tMask
= Mask
->pvBits
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
119 for (j
= 0; j
< dy
; j
++)
122 c8
= SourcePoint
->x
& 0x07;
123 for (i
= 0; i
< dx
; i
++)
125 if (0 != (*lMask
& maskbit
[c8
]))
127 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
136 tMask
+= Mask
->lDelta
;
146 static BOOLEAN STDCALL
147 BltPatCopy(SURFOBJ
* Dest
,
152 XLATEOBJ
* ColorTranslation
,
160 // These functions are assigned if we're working with a DIB
161 // The assigned functions depend on the bitsPerPixel of the DIB
165 LineWidth
= DestRect
->right
- DestRect
->left
;
166 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
168 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
174 static BOOLEAN STDCALL
175 CallDibBitBlt(SURFOBJ
* OutputObj
,
180 XLATEOBJ
* ColorTranslation
,
188 return OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputPoint
, Brush
, BrushOrigin
, ColorTranslation
, Rop4
);
197 EngBitBlt(SURFOBJ
*DestObj
,
201 XLATEOBJ
*ColorTranslation
,
219 INTENG_ENTER_LEAVE EnterLeaveSource
;
220 INTENG_ENTER_LEAVE EnterLeaveDest
;
223 PBLTRECTFUNC BltRectFunc
;
230 if (NULL
!= SourcePoint
)
232 InputRect
.left
= SourcePoint
->x
;
233 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
234 InputRect
.top
= SourcePoint
->y
;
235 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
240 InputRect
.right
= DestRect
->right
- DestRect
->left
;
242 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
245 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
250 if (NULL
!= SourcePoint
)
252 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
253 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
261 if (NULL
!= InputObj
)
263 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
270 OutputRect
= *DestRect
;
271 if (NULL
!= ClipRegion
)
273 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
275 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
276 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
277 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
279 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
281 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
282 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
284 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
286 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
287 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
288 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
290 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
292 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
293 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
297 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
299 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
301 IntEngLeave(&EnterLeaveSource
);
305 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
307 IntEngLeave(&EnterLeaveSource
);
311 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
312 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
313 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
314 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
316 if (NULL
!= OutputObj
)
318 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
321 // Determine clipping type
322 if (ClipRegion
== (CLIPOBJ
*) NULL
)
324 clippingType
= DC_TRIVIAL
;
326 clippingType
= ClipRegion
->iDComplexity
;
331 BltRectFunc
= BltMask
;
333 else if (PATCOPY
== Rop4
)
335 BltRectFunc
= BltPatCopy
;
339 BltRectFunc
= CallDibBitBlt
;
346 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
347 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
350 // Clip the blt to the clip rectangle
351 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
352 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
353 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
354 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
355 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
356 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
357 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
358 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
359 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
363 if (OutputObj
== InputObj
)
365 if (OutputRect
.top
< InputPoint
.y
)
367 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
371 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
378 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, ENUM_RECT_LIMIT
);
381 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
383 for (i
= 0; i
< RectEnum
.c
; i
++)
385 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
386 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
387 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
388 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
389 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
390 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
391 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
392 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
393 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
) &&
402 IntEngLeave(&EnterLeaveDest
);
403 IntEngLeave(&EnterLeaveSource
);
409 IntEngBitBlt(SURFOBJ
*DestObj
,
413 XLATEOBJ
*ColorTranslation
,
427 if (NULL
!= SourcePoint
)
429 InputPoint
= *SourcePoint
;
432 /* Clip against the bounds of the clipping region so we won't try to write
433 * outside the surface */
434 if (NULL
!= ClipRegion
)
436 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
440 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
441 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
445 OutputRect
= *DestRect
;
448 if (NULL
!= SourceObj
)
450 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
451 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
452 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
453 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
458 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
459 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
460 OutputRect
.right
, OutputRect
.bottom
);
462 /* Call the driver's DrvBitBlt if available */
463 if (NULL
!= DestGDI
->BitBlt
)
465 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
466 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
472 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
473 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
477 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
478 if (NULL
!= SourceObj
)
480 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
486 static BOOLEAN STDCALL
487 CallDibStretchBlt(SURFOBJ
* OutputObj
,
492 XLATEOBJ
* ColorTranslation
,
499 return OutputGDI
->DIB_StretchBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputRect
, MaskOrigin
, BrushOrigin
, ColorTranslation
, Mode
);
507 IN SURFOBJ
*SourceObj
,
509 IN CLIPOBJ
*ClipRegion
,
510 IN XLATEOBJ
*ColorTranslation
,
511 IN COLORADJUSTMENT
*pca
,
512 IN POINTL
*BrushOrigin
,
515 IN POINTL
*MaskOrigin
,
519 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
523 // RECT_ENUM RectEnum;
531 INTENG_ENTER_LEAVE EnterLeaveSource
;
532 INTENG_ENTER_LEAVE EnterLeaveDest
;
535 PSTRETCHRECTFUNC BltRectFunc
;
542 InputRect
.left
= prclSrc
->left
;
543 InputRect
.right
= prclSrc
->right
;
544 InputRect
.top
= prclSrc
->top
;
545 InputRect
.bottom
= prclSrc
->bottom
;
547 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
552 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
553 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
555 if (NULL
!= InputObj
)
557 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
564 OutputRect
= *prclDest
;
565 if (NULL
!= ClipRegion
)
567 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
569 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
570 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
571 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
573 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
575 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
576 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
578 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
580 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
581 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
582 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
584 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
586 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
587 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
591 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
593 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
595 IntEngLeave(&EnterLeaveSource
);
599 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
601 IntEngLeave(&EnterLeaveSource
);
605 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
606 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
607 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
608 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
610 if (NULL
!= OutputObj
)
612 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
615 // Determine clipping type
616 if (ClipRegion
== (CLIPOBJ
*) NULL
)
618 clippingType
= DC_TRIVIAL
;
620 clippingType
= ClipRegion
->iDComplexity
;
623 if (Mask
!= NULL
)//(0xaacc == Rop4)
625 //BltRectFunc = BltMask;
626 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
627 IntEngLeave(&EnterLeaveDest
);
628 IntEngLeave(&EnterLeaveSource
);
634 BltRectFunc
= CallDibStretchBlt
;
641 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
642 &OutputRect
, &InputRect
, MaskOrigin
, BrushOrigin
, Mode
);
645 // Clip the blt to the clip rectangle
646 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
647 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
648 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
649 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
650 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
651 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
652 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
653 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
654 &OutputRect
, &InputRect
, MaskOrigin
, BrushOrigin
, Mode
);
655 //Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
656 // &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
657 DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n");
659 // TODO: Complex clipping
663 if (OutputObj == InputObj)
665 if (OutputRect.top < InputPoint.y)
667 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
671 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
678 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT);
681 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
683 for (i = 0; i < RectEnum.c; i++)
685 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
686 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
687 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
688 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
689 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
690 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
691 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
692 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
693 &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) &&
703 IntEngLeave(&EnterLeaveDest
);
704 IntEngLeave(&EnterLeaveSource
);
710 IntEngStretchBlt(SURFOBJ
*DestObj
,
714 XLATEOBJ
*ColorTranslation
,
730 if (pMaskOrigin
!= NULL
)
732 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
735 if (NULL
!= SourceRect
)
737 InputRect
= *SourceRect
;
740 // FIXME: Clipping is taken from IntEngBitBlt w/o modifications!
742 /* Clip against the bounds of the clipping region so we won't try to write
743 * outside the surface */
744 if (NULL
!= ClipRegion
)
746 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
750 DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n");
751 //InputPoint.x += OutputRect.left - DestRect->left;
752 //InputPoint.y += OutputRect.top - DestRect->top;
756 OutputRect
= *DestRect
;
759 if (NULL
!= SourceObj
)
761 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
762 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputRect
.left
, InputRect
.top
,
763 (InputRect
.left
+ abs(InputRect
.right
- InputRect
.left
)),
764 (InputRect
.top
+ abs(InputRect
.bottom
- InputRect
.top
)));
769 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
770 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
771 OutputRect
.right
, OutputRect
.bottom
);
773 /* Prepare color adjustment */
775 /* Call the driver's DrvStretchBlt if available */
776 if (NULL
!= DestGDI
->StretchBlt
)
778 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
779 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
780 // FIXME: MaskOrigin is always NULL !
781 ret
= DestGDI
->StretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
782 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, Mode
);
787 // FIXME: see previous fixme
788 ret
= EngStretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
789 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, 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
+ MaskPoint
->y
* Mask
->lDelta
+ MaskPoint
->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 if (NULL
!= SourcePoint
)
904 InputRect
.left
= SourcePoint
->x
;
905 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
906 InputRect
.top
= SourcePoint
->y
;
907 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
912 InputRect
.right
= DestRect
->right
- DestRect
->left
;
914 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
917 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
922 if (NULL
!= SourcePoint
)
924 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
925 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
933 if (NULL
!= InputObj
)
935 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
942 OutputRect
= *DestRect
;
943 if (NULL
!= ClipRegion
)
945 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
947 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
948 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
949 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
951 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
953 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
954 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
956 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
958 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
959 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
960 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
962 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
964 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
965 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
969 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
971 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
973 IntEngLeave(&EnterLeaveSource
);
977 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
979 IntEngLeave(&EnterLeaveSource
);
983 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
984 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
985 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
986 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
988 if (NULL
!= OutputObj
)
990 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
993 // Determine clipping type
994 if (ClipRegion
== (CLIPOBJ
*) NULL
)
996 clippingType
= DC_TRIVIAL
;
998 clippingType
= ClipRegion
->iDComplexity
;
1001 switch(clippingType
)
1004 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1005 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1006 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1008 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1009 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC);
1012 // Clip the blt to the clip rectangle
1013 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1014 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1015 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1016 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1017 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1018 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1019 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1020 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1021 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1022 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
);
1024 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1025 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC);
1029 if (OutputObj
== InputObj
)
1031 if (OutputRect
.top
< InputPoint
.y
)
1033 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1037 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1044 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, ENUM_RECT_LIMIT
);
1047 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1049 for (i
= 0; i
< RectEnum
.c
; i
++)
1051 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1052 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1053 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1054 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1055 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1056 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1057 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1058 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1059 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1060 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
) && Ret
;
1062 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1063 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC) && Ret
;
1071 IntEngLeave(&EnterLeaveDest
);
1072 IntEngLeave(&EnterLeaveSource
);
1078 IntEngMaskBlt(SURFOBJ
*DestObj
,
1080 CLIPOBJ
*ClipRegion
,
1081 XLATEOBJ
*DestColorTranslation
,
1082 XLATEOBJ
*SourceColorTranslation
,
1084 POINTL
*SourcePoint
,
1087 POINTL
*BrushOrigin
)
1094 if (NULL
!= SourcePoint
)
1096 InputPoint
= *SourcePoint
;
1099 /* Clip against the bounds of the clipping region so we won't try to write
1100 * outside the surface */
1101 if (NULL
!= ClipRegion
)
1103 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1107 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1108 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1112 OutputRect
= *DestRect
;
1115 /* No success yet */
1117 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
1118 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
1119 OutputRect
.right
, OutputRect
.bottom
);
1121 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1122 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1124 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);