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.63 2004/12/14 03:28:34 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
;
500 SURFOBJ
*SourceSurf
= SourceObj
? &SourceObj
->SurfObj
: NULL
;
501 SURFOBJ
*MaskSurf
= MaskObj
? &MaskObj
->SurfObj
: NULL
;
504 DestSurf
= &DestObj
->SurfObj
;
507 InputClippedRect
= *DestRect
;
508 if (InputClippedRect
.right
< InputClippedRect
.left
)
510 InputClippedRect
.left
= DestRect
->right
;
511 InputClippedRect
.right
= DestRect
->left
;
513 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
515 InputClippedRect
.top
= DestRect
->bottom
;
516 InputClippedRect
.bottom
= DestRect
->top
;
518 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
521 if (NULL
== SourcePoint
|| NULL
== SourceSurf
)
525 InputPoint
= *SourcePoint
;
527 /* Make sure we don't try to copy anything outside the valid source region */
528 if (InputPoint
.x
< 0)
530 InputClippedRect
.left
-= InputPoint
.x
;
533 if (InputPoint
.y
< 0)
535 InputClippedRect
.top
-= InputPoint
.y
;
538 if (SourceSurf
->sizlBitmap
.cx
< InputPoint
.x
+ InputClippedRect
.right
- InputClippedRect
.left
)
540 InputClippedRect
.right
= InputClippedRect
.left
+ SourceSurf
->sizlBitmap
.cx
- InputPoint
.x
;
542 if (SourceSurf
->sizlBitmap
.cy
< InputPoint
.y
+ InputClippedRect
.bottom
- InputClippedRect
.top
)
544 InputClippedRect
.bottom
= InputClippedRect
.top
+ SourceSurf
->sizlBitmap
.cy
- InputPoint
.y
;
547 if (InputClippedRect
.right
< InputClippedRect
.left
||
548 InputClippedRect
.bottom
< InputClippedRect
.top
)
550 /* Everything clipped away, nothing to do */
555 /* Clip against the bounds of the clipping region so we won't try to write
556 * outside the surface */
557 if (NULL
!= ClipRegion
)
559 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
, &ClipRegion
->rclBounds
))
563 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
564 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
568 OutputRect
= InputClippedRect
;
573 MouseSafetyOnDrawStart(SourceSurf
, InputPoint
.x
, InputPoint
.y
,
574 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
575 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
580 MouseSafetyOnDrawStart(DestSurf
, OutputRect
.left
, OutputRect
.top
,
581 OutputRect
.right
, OutputRect
.bottom
);
583 /* Call the driver's DrvBitBlt if available */
584 if (DestObj
->flHooks
& HOOK_BITBLT
)
586 ret
= GDIDEVFUNCS(DestSurf
).BitBlt(
587 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
588 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
594 ret
= EngBitBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
595 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
599 MouseSafetyOnDrawEnd(DestSurf
);
602 MouseSafetyOnDrawEnd(SourceSurf
);
608 static BOOLEAN STDCALL
609 CallDibStretchBlt(SURFOBJ
* OutputObj
,
613 XLATEOBJ
* ColorTranslation
,
620 POINTL RealBrushOrigin
;
621 if (BrushOrigin
== NULL
)
623 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
627 RealBrushOrigin
= *BrushOrigin
;
629 return DibFunctionsForBitmapFormat
[OutputObj
->iBitmapFormat
].DIB_StretchBlt(
630 OutputObj
, InputObj
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ClipRegion
, ColorTranslation
, Mode
);
638 IN SURFOBJ
*SourceObj
,
640 IN CLIPOBJ
*ClipRegion
,
641 IN XLATEOBJ
*ColorTranslation
,
642 IN COLORADJUSTMENT
*pca
,
643 IN POINTL
*BrushOrigin
,
646 IN POINTL
*MaskOrigin
,
650 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
656 INTENG_ENTER_LEAVE EnterLeaveSource
;
657 INTENG_ENTER_LEAVE EnterLeaveDest
;
660 PSTRETCHRECTFUNC BltRectFunc
;
662 POINTL AdjustedBrushOrigin
;
664 InputRect
.left
= prclSrc
->left
;
665 InputRect
.right
= prclSrc
->right
;
666 InputRect
.top
= prclSrc
->top
;
667 InputRect
.bottom
= prclSrc
->bottom
;
669 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
674 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
675 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
677 OutputRect
= *prclDest
;
679 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
681 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
683 IntEngLeave(&EnterLeaveSource
);
687 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
689 IntEngLeave(&EnterLeaveSource
);
693 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
694 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
695 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
696 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
698 if (NULL
!= BrushOrigin
)
700 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
701 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
705 AdjustedBrushOrigin
= Translate
;
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
, InputObj
, Mask
, ClipRegion
,
724 ColorTranslation
, &OutputRect
, &InputRect
, MaskOrigin
,
725 &AdjustedBrushOrigin
, Mode
);
727 IntEngLeave(&EnterLeaveDest
);
728 IntEngLeave(&EnterLeaveSource
);
734 IntEngStretchBlt(BITMAPOBJ
*DestObj
,
735 BITMAPOBJ
*SourceObj
,
738 XLATEOBJ
*ColorTranslation
,
749 SURFOBJ
*DestSurf
= &DestObj
->SurfObj
;
750 SURFOBJ
*SourceSurf
= SourceObj
? &SourceObj
->SurfObj
: NULL
;
751 SURFOBJ
*MaskSurf
= MaskObj
? &MaskObj
->SurfObj
: NULL
;
753 if (pMaskOrigin
!= NULL
)
755 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
758 if (NULL
!= SourceObj
)
760 MouseSafetyOnDrawStart(SourceSurf
, SourceRect
->left
, SourceRect
->top
,
761 SourceRect
->right
, SourceRect
->bottom
);
766 MouseSafetyOnDrawStart(DestSurf
, DestRect
->left
, DestRect
->top
,
767 DestRect
->right
, DestRect
->bottom
);
769 /* Prepare color adjustment */
771 /* Call the driver's DrvStretchBlt if available */
772 if (DestObj
->flHooks
& HOOK_STRETCHBLT
)
774 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
775 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
776 // FIXME: MaskOrigin is always NULL !
777 ret
= GDIDEVFUNCS(DestSurf
).StretchBlt(
778 DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
779 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
784 // FIXME: see previous fixme
785 ret
= EngStretchBlt(DestSurf
, SourceSurf
, MaskSurf
, ClipRegion
, ColorTranslation
,
786 &ca
, BrushOrigin
, DestRect
, SourceRect
, NULL
, Mode
);
789 MouseSafetyOnDrawEnd(DestSurf
);
790 if (NULL
!= SourceSurf
)
792 MouseSafetyOnDrawEnd(SourceSurf
);
798 /**** REACTOS FONT RENDERING CODE *********************************************/
800 /* renders the alpha mask bitmap */
801 static BOOLEAN STDCALL
802 AlphaBltMask(SURFOBJ
* Dest
,
805 XLATEOBJ
* ColorTranslation
,
806 XLATEOBJ
* SrcColorTranslation
,
815 ULONG Background
, BrushColor
, NewColor
;
818 dx
= DestRect
->right
- DestRect
->left
;
819 dy
= DestRect
->bottom
- DestRect
->top
;
823 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
824 r
= (int)GetRValue(BrushColor
);
825 g
= (int)GetGValue(BrushColor
);
826 b
= (int)GetBValue(BrushColor
);
828 tMask
= Mask
->pvBits
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
829 for (j
= 0; j
< dy
; j
++)
832 for (i
= 0; i
< dx
; i
++)
838 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
839 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
843 Background
= DIB_GetSource(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, SrcColorTranslation
);
846 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
847 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
848 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
850 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
851 DibFunctionsForBitmapFormat
[Dest
->iBitmapFormat
].DIB_PutPixel(
852 Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
857 tMask
+= Mask
->lDelta
;
868 EngMaskBitBlt(SURFOBJ
*DestObj
,
871 XLATEOBJ
*DestColorTranslation
,
872 XLATEOBJ
*SourceColorTranslation
,
887 INTENG_ENTER_LEAVE EnterLeaveSource
;
888 INTENG_ENTER_LEAVE EnterLeaveDest
;
896 POINTL AdjustedBrushOrigin
;
898 if (NULL
!= SourcePoint
)
900 InputRect
.left
= SourcePoint
->x
;
901 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
902 InputRect
.top
= SourcePoint
->y
;
903 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
908 InputRect
.right
= DestRect
->right
- DestRect
->left
;
910 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
913 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
918 if (NULL
!= SourcePoint
)
920 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
921 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
929 OutputRect
= *DestRect
;
930 if (NULL
!= ClipRegion
)
932 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
934 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
935 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
936 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
938 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
940 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
941 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
943 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
945 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
946 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
947 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
949 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
951 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
952 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
956 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
958 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
960 IntEngLeave(&EnterLeaveSource
);
964 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
966 IntEngLeave(&EnterLeaveSource
);
970 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
971 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
972 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
973 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
977 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
978 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
981 AdjustedBrushOrigin
= Translate
;
983 // Determine clipping type
984 if (ClipRegion
== (CLIPOBJ
*) NULL
)
986 clippingType
= DC_TRIVIAL
;
988 clippingType
= ClipRegion
->iDComplexity
;
994 if(Mask
->iBitmapFormat
== BMF_8BPP
)
995 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
996 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
998 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
999 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1002 // Clip the blt to the clip rectangle
1003 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1004 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1005 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1006 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1007 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1008 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1009 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1010 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1011 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1012 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1014 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1015 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1019 if (OutputObj
== InputObj
)
1021 if (OutputRect
.top
< InputPoint
.y
)
1023 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1027 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1034 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1037 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1039 for (i
= 0; i
< RectEnum
.c
; i
++)
1041 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1042 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1043 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1044 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1045 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1046 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1047 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1048 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1049 Ret
= AlphaBltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1050 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
) && Ret
;
1052 Ret
= BltMask(OutputObj
, InputObj
, Mask
, DestColorTranslation
,
1053 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC) && Ret
;
1061 IntEngLeave(&EnterLeaveDest
);
1062 IntEngLeave(&EnterLeaveSource
);
1064 /* Dummy BitBlt to let driver know that something has changed.
1065 0x00AA0029 is the Rop for D (no-op) */
1066 /* FIXME: Remove the typecast! */
1067 IntEngBitBlt((BITMAPOBJ
*)DestObj
, NULL
, (BITMAPOBJ
*)Mask
, ClipRegion
, DestColorTranslation
,
1068 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, ROP_NOOP
);
1074 IntEngMaskBlt(SURFOBJ
*DestObj
,
1076 CLIPOBJ
*ClipRegion
,
1077 XLATEOBJ
*DestColorTranslation
,
1078 XLATEOBJ
*SourceColorTranslation
,
1080 POINTL
*SourcePoint
,
1083 POINTL
*BrushOrigin
)
1089 if (NULL
!= SourcePoint
)
1091 InputPoint
= *SourcePoint
;
1094 /* Clip against the bounds of the clipping region so we won't try to write
1095 * outside the surface */
1096 if (NULL
!= ClipRegion
)
1098 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1102 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1103 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1107 OutputRect
= *DestRect
;
1110 /* No success yet */
1112 MouseSafetyOnDrawStart(DestObj
, OutputRect
.left
, OutputRect
.top
,
1113 OutputRect
.right
, OutputRect
.bottom
);
1115 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1116 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1118 MouseSafetyOnDrawEnd(DestObj
);