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.62 2004/12/14 03:23:14 royce 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
,
34 XLATEOBJ
* ColorTranslation
,
41 typedef BOOLEAN
STDCALL (*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
45 XLATEOBJ
* ColorTranslation
,
52 BOOL STDCALL
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
54 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
56 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
57 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
59 if (prcDst
->left
< prcDst
->right
)
61 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
62 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
64 if (prcDst
->top
< prcDst
->bottom
)
75 static BOOLEAN STDCALL
76 BltMask(SURFOBJ
* Dest
,
79 XLATEOBJ
* ColorTranslation
,
87 LONG i
, j
, dx
, dy
, c8
;
89 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
91 PGDIBRUSHINST GdiBrush
= NULL
;
92 HBITMAP PatternSurface
= NULL
;
93 SURFOBJ
*PatternObj
= NULL
;
94 PBITMAPOBJ PatternBitmap
;
95 ULONG PatternWidth
= 0, PatternHeight
= 0, PatternY
= 0;
102 dx
= DestRect
->right
- DestRect
->left
;
103 dy
= DestRect
->bottom
- DestRect
->top
;
105 if (Brush
->iSolidColor
== 0xFFFFFFFF)
107 GdiBrush
= CONTAINING_RECORD(
112 PatternSurface
= GdiBrush
->GdiBrushObject
->hbmPattern
;
113 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->GdiBrushObject
->hbmPattern
);
114 if(PatternBitmap
!= NULL
)
116 PatternObj
= &PatternBitmap
->SurfObj
;
117 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
118 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
122 PatternBitmap
= NULL
;
124 tMask
= Mask
->pvScan0
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
125 for (j
= 0; j
< dy
; j
++)
128 c8
= SourcePoint
->x
& 0x07;
130 if(PatternBitmap
!= NULL
)
131 PatternY
= (DestRect
->top
+ j
) % PatternHeight
;
133 for (i
= 0; i
< dx
; i
++)
135 if (0 != (*lMask
& maskbit
[c8
]))
137 if (PatternBitmap
== NULL
)
139 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
140 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
144 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
145 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
146 DIB_GetSource(PatternObj
, (DestRect
->left
+ i
) % PatternWidth
, PatternY
, GdiBrush
->XlateObject
));
156 tMask
+= Mask
->lDelta
;
159 if (PatternBitmap
!= NULL
)
160 BITMAPOBJ_UnlockBitmap(PatternSurface
);
165 static BOOLEAN STDCALL
166 BltPatCopy(SURFOBJ
* Dest
,
169 XLATEOBJ
* ColorTranslation
,
177 // These functions are assigned if we're working with a DIB
178 // The assigned functions depend on the bitsPerPixel of the DIB
182 LineWidth
= DestRect
->right
- DestRect
->left
;
183 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
185 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_HLine(
186 Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
192 static BOOLEAN STDCALL
193 CallDibBitBlt(SURFOBJ
* OutputObj
,
196 XLATEOBJ
* ColorTranslation
,
205 PGDIBRUSHINST GdiBrush
= NULL
;
206 BITMAPOBJ
*bmPattern
;
209 BltInfo
.DestSurface
= OutputObj
;
210 BltInfo
.SourceSurface
= InputObj
;
211 BltInfo
.PatternSurface
= NULL
;
212 BltInfo
.XlateSourceToDest
= ColorTranslation
;
213 BltInfo
.DestRect
= *OutputRect
;
214 BltInfo
.SourcePoint
= *InputPoint
;
217 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBltSrcCopy(&BltInfo
);
219 BltInfo
.XlatePatternToDest
= NULL
;
220 BltInfo
.Brush
= Brush
;
221 BltInfo
.BrushOrigin
= *BrushOrigin
;
225 if (ROP_USES_PATTERN(Rop4
) && Brush
->iSolidColor
== 0xFFFFFFFF)
227 GdiBrush
= CONTAINING_RECORD(Brush
, GDIBRUSHINST
, BrushObject
);
228 if((bmPattern
= BITMAPOBJ_LockBitmap(GdiBrush
->GdiBrushObject
->hbmPattern
)))
230 BltInfo
.PatternSurface
= &bmPattern
->SurfObj
;
234 /* FIXME - What to do here? */
236 BltInfo
.XlatePatternToDest
= GdiBrush
->XlateObject
;
243 Result
= DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_BitBlt(&BltInfo
);
246 if (bmPattern
!= NULL
)
248 BITMAPOBJ_UnlockBitmap(BltInfo
.PatternSurface
->hsurf
);
260 EngBitBlt(SURFOBJ
*DestObj
,
264 XLATEOBJ
*ColorTranslation
,
280 INTENG_ENTER_LEAVE EnterLeaveSource
;
281 INTENG_ENTER_LEAVE EnterLeaveDest
;
284 PBLTRECTFUNC BltRectFunc
;
292 POINTL AdjustedBrushOrigin
;
294 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
295 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
296 if (ROP_NOOP
== Rop4
)
298 /* Copy destination onto itself: nop */
302 if (NULL
!= SourcePoint
)
304 InputRect
.left
= SourcePoint
->x
;
305 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
306 InputRect
.top
= SourcePoint
->y
;
307 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
312 InputRect
.right
= DestRect
->right
- DestRect
->left
;
314 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
317 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
322 if (NULL
!= SourcePoint
)
324 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
325 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
333 OutputRect
= *DestRect
;
334 if (NULL
!= ClipRegion
)
336 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
338 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
339 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
340 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
342 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
344 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
345 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
347 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
349 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
350 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
351 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
353 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
355 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
356 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
360 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
362 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
364 IntEngLeave(&EnterLeaveSource
);
368 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
370 IntEngLeave(&EnterLeaveSource
);
374 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
375 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
376 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
377 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
381 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
382 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
385 AdjustedBrushOrigin
= Translate
;
387 // Determine clipping type
388 if (ClipRegion
== (CLIPOBJ
*) NULL
)
390 clippingType
= DC_TRIVIAL
;
392 clippingType
= ClipRegion
->iDComplexity
;
397 BltRectFunc
= BltMask
;
399 else if (PATCOPY
== Rop4
)
402 BltRectFunc
= BltPatCopy
;
404 if (Brush
->iSolidColor
== 0xFFFFFFFF)
405 BltRectFunc
= CallDibBitBlt
;
407 BltRectFunc
= BltPatCopy
;
412 BltRectFunc
= CallDibBitBlt
;
419 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
420 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
423 // Clip the blt to the clip rectangle
424 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
425 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
426 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
427 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
428 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
429 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
430 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
431 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
432 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
436 if (OutputObj
== InputObj
)
438 if (OutputRect
.top
< InputPoint
.y
)
440 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
444 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
451 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
454 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
456 for (i
= 0; i
< RectEnum
.c
; i
++)
458 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
459 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
460 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
461 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
462 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
463 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
464 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
465 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ColorTranslation
,
466 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
) &&
475 IntEngLeave(&EnterLeaveDest
);
476 IntEngLeave(&EnterLeaveSource
);
482 IntEngBitBlt(BITMAPOBJ
*DestObj
,
483 BITMAPOBJ
*SourceObj
,
486 XLATEOBJ
*ColorTranslation
,
495 RECTL InputClippedRect
;
499 SURFOBJ
*DestSurf
= &DestObj
->SurfObj
;
500 SURFOBJ
*SourceSurf
= SourceObj
? &SourceObj
->SurfObj
: NULL
;
501 SURFOBJ
*MaskSurf
= MaskObj
? &MaskObj
->SurfObj
: NULL
;
503 InputClippedRect
= *DestRect
;
504 if (InputClippedRect
.right
< InputClippedRect
.left
)
506 InputClippedRect
.left
= DestRect
->right
;
507 InputClippedRect
.right
= DestRect
->left
;
509 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
511 InputClippedRect
.top
= DestRect
->bottom
;
512 InputClippedRect
.bottom
= DestRect
->top
;
514 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
517 if (NULL
== SourcePoint
|| NULL
== SourceSurf
)
521 InputPoint
= *SourcePoint
;
523 /* Make sure we don't try to copy anything outside the valid source region */
524 if (InputPoint
.x
< 0)
526 InputClippedRect
.left
-= InputPoint
.x
;
529 if (InputPoint
.y
< 0)
531 InputClippedRect
.top
-= InputPoint
.y
;
534 if (SourceSurf
->sizlBitmap
.cx
< InputPoint
.x
+ InputClippedRect
.right
- InputClippedRect
.left
)
536 InputClippedRect
.right
= InputClippedRect
.left
+ SourceSurf
->sizlBitmap
.cx
- InputPoint
.x
;
538 if (SourceSurf
->sizlBitmap
.cy
< InputPoint
.y
+ InputClippedRect
.bottom
- InputClippedRect
.top
)
540 InputClippedRect
.bottom
= InputClippedRect
.top
+ SourceSurf
->sizlBitmap
.cy
- InputPoint
.y
;
543 if (InputClippedRect
.right
< InputClippedRect
.left
||
544 InputClippedRect
.bottom
< InputClippedRect
.top
)
546 /* Everything clipped away, nothing to do */
551 /* Clip against the bounds of the clipping region so we won't try to write
552 * outside the surface */
553 if (NULL
!= ClipRegion
)
555 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
, &ClipRegion
->rclBounds
))
559 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
560 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
564 OutputRect
= InputClippedRect
;
569 MouseSafetyOnDrawStart(SourceSurf
, InputPoint
.x
, InputPoint
.y
,
570 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
571 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
576 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
577 OutputRect
.right
, OutputRect
.bottom
);
579 /* Call the driver's DrvBitBlt if available */
580 if (DestObj
->flHooks
& HOOK_BITBLT
)
582 ret
= GDIDEVFUNCS(DestSurf
).BitBlt(
583 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
584 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
590 ret
= EngBitBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
591 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
595 MouseSafetyOnDrawEnd(DestSurf
);
598 MouseSafetyOnDrawEnd(SourceSurf
);
604 static BOOLEAN STDCALL
605 CallDibStretchBlt(SURFOBJ
* OutputObj
,
609 XLATEOBJ
* ColorTranslation
,
616 POINTL RealBrushOrigin
;
617 if (BrushOrigin
== NULL
)
619 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
623 RealBrushOrigin
= *BrushOrigin
;
625 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_StretchBlt(
626 OutputObj
, InputObj
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
634 IN SURFOBJ
*SourceObj
,
636 IN CLIPOBJ
*ClipRegion
,
637 IN XLATEOBJ
*ColorTranslation
,
638 IN COLORADJUSTMENT
*pca
,
639 IN POINTL
*BrushOrigin
,
642 IN POINTL
*MaskOrigin
,
646 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
652 INTENG_ENTER_LEAVE EnterLeaveSource
;
653 INTENG_ENTER_LEAVE EnterLeaveDest
;
656 PSTRETCHRECTFUNC BltRectFunc
;
658 POINTL AdjustedBrushOrigin
;
660 InputRect
.left
= prclSrc
->left
;
661 InputRect
.right
= prclSrc
->right
;
662 InputRect
.top
= prclSrc
->top
;
663 InputRect
.bottom
= prclSrc
->bottom
;
665 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
670 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
671 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
673 OutputRect
= *prclDest
;
675 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
677 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
679 IntEngLeave(&EnterLeaveSource
);
683 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
685 IntEngLeave(&EnterLeaveSource
);
689 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
690 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
691 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
692 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
694 if (NULL
!= BrushOrigin
)
696 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
697 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
701 AdjustedBrushOrigin
= Translate
;
706 //BltRectFunc = BltMask;
707 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
708 IntEngLeave(&EnterLeaveDest
);
709 IntEngLeave(&EnterLeaveSource
);
715 BltRectFunc
= CallDibStretchBlt
;
719 Ret
= (*BltRectFunc
)(OutputObj
, InputObj
, Mask
, ClipRegion
,
720 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
721 &AdjustedBrushOrigin
, Mode
);
723 IntEngLeave(&EnterLeaveDest
);
724 IntEngLeave(&EnterLeaveSource
);
730 IntEngStretchBlt(BITMAPOBJ
*DestObj
,
731 BITMAPOBJ
*SourceObj
,
734 XLATEOBJ
*ColorTranslation
,
745 SURFOBJ
*DestSurf
= &DestObj
->SurfObj
;
746 SURFOBJ
*SourceSurf
= SourceObj
? &SourceObj
->SurfObj
: NULL
;
747 SURFOBJ
*MaskSurf
= MaskObj
? &MaskObj
->SurfObj
: NULL
;
749 if (pMaskOrigin
!= NULL
)
751 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
754 if (NULL
!= SourceObj
)
756 MouseSafetyOnDrawStart(SourceSurf
, SourceRect
->left
, SourceRect
->top
,
757 SourceRect
->right
, SourceRect
->bottom
);
762 MouseSafetyOnDrawStart(DestSurf
, DestRect
->left
, DestRect
->top
,
763 DestRect
->right
, DestRect
->bottom
);
765 /* Prepare color adjustment */
767 /* Call the driver's DrvStretchBlt if available */
768 if (DestObj
->flHooks
& HOOK_STRETCHBLT
)
770 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
771 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
772 // FIXME: MaskOrigin is always NULL !
773 ret
= GDIDEVFUNCS(DestSurf
).StretchBlt(
774 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
775 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
780 // FIXME: see previous fixme
781 ret
= EngStretchBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
782 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
785 MouseSafetyOnDrawEnd(DestSurf
);
786 if (NULL
!= SourceSurf
)
788 MouseSafetyOnDrawEnd(SourceSurf
);
794 /**** REACTOS FONT RENDERING CODE *********************************************/
796 /* renders the alpha mask bitmap */
797 static BOOLEAN STDCALL
798 AlphaBltMask(SURFOBJ
* Dest
,
801 XLATEOBJ
* ColorTranslation
,
802 XLATEOBJ
* SrcColorTranslation
,
811 ULONG Background
, BrushColor
, NewColor
;
814 dx
= DestRect
->right
- DestRect
->left
;
815 dy
= DestRect
->bottom
- DestRect
->top
;
819 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
820 r
= (int)GetRValue(BrushColor
);
821 g
= (int)GetGValue(BrushColor
);
822 b
= (int)GetBValue(BrushColor
);
824 tMask
= Mask
->pvBits
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
825 for (j
= 0; j
< dy
; j
++)
828 for (i
= 0; i
< dx
; i
++)
834 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
835 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
839 Background
= DIB_GetSource(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, SrcColorTranslation
);
842 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
843 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
844 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
846 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
847 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
848 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
853 tMask
+= Mask
->lDelta
;
864 EngMaskBitBlt(SURFOBJ
*DestObj
,
867 XLATEOBJ
*DestColorTranslation
,
868 XLATEOBJ
*SourceColorTranslation
,
883 INTENG_ENTER_LEAVE EnterLeaveSource
;
884 INTENG_ENTER_LEAVE EnterLeaveDest
;
892 POINTL AdjustedBrushOrigin
;
894 if (NULL
!= SourcePoint
)
896 InputRect
.left
= SourcePoint
->x
;
897 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
898 InputRect
.top
= SourcePoint
->y
;
899 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
904 InputRect
.right
= DestRect
->right
- DestRect
->left
;
906 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
909 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
914 if (NULL
!= SourcePoint
)
916 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
917 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
925 OutputRect
= *DestRect
;
926 if (NULL
!= ClipRegion
)
928 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
930 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
931 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
932 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
934 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
936 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
937 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
939 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
941 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
942 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
943 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
945 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
947 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
948 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
952 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
954 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
956 IntEngLeave(&EnterLeaveSource
);
960 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
962 IntEngLeave(&EnterLeaveSource
);
966 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
967 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
968 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
969 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
973 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
974 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
977 AdjustedBrushOrigin
= Translate
;
979 // Determine clipping type
980 if (ClipRegion
== (CLIPOBJ
*) NULL
)
982 clippingType
= DC_TRIVIAL
;
984 clippingType
= ClipRegion
->iDComplexity
;
990 if(Mask
->iBitmapFormat
== BMF_8BPP
)
991 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
992 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
994 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
995 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
998 // Clip the blt to the clip rectangle
999 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1000 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1001 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1002 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1003 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1004 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1005 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1006 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1007 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1008 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1010 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1011 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1015 if (OutputObj
== InputObj
)
1017 if (OutputRect
.top
< InputPoint
.y
)
1019 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1023 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1030 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1033 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1035 for (i
= 0; i
< RectEnum
.c
; i
++)
1037 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1038 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1039 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1040 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1041 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1042 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1043 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1044 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1045 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1046 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
) && Ret
;
1048 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1049 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC) && Ret
;
1057 IntEngLeave(&EnterLeaveDest
);
1058 IntEngLeave(&EnterLeaveSource
);
1060 /* Dummy BitBlt to let driver know that something has changed.
1061 0x00AA0029 is the Rop for D (no-op) */
1062 /* FIXME: Remove the typecast! */
1063 IntEngBitBlt((BITMAPOBJ
*)DestObj
, NULL
, (BITMAPOBJ
*)Mask
, ClipRegion
, DestColorTranslation
,
1064 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, ROP_NOOP
);
1070 IntEngMaskBlt(SURFOBJ
*DestObj
,
1072 CLIPOBJ
*ClipRegion
,
1073 XLATEOBJ
*DestColorTranslation
,
1074 XLATEOBJ
*SourceColorTranslation
,
1076 POINTL
*SourcePoint
,
1079 POINTL
*BrushOrigin
)
1085 if (NULL
!= SourcePoint
)
1087 InputPoint
= *SourcePoint
;
1090 /* Clip against the bounds of the clipping region so we won't try to write
1091 * outside the surface */
1092 if (NULL
!= ClipRegion
)
1094 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1098 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1099 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1103 OutputRect
= *DestRect
;
1106 /* No success yet */
1108 MouseSafetyOnDrawStart(DestObj
, OutputRect
.left
, OutputRect
.top
,
1109 OutputRect
.right
, OutputRect
.bottom
);
1111 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1112 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1114 MouseSafetyOnDrawEnd(DestObj
);