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.49 2004/04/09 22:13:26 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
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/eng.h>
44 #include <include/inteng.h>
47 #include <win32k/debug1.h>
49 typedef BOOLEAN
STDCALL (*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
54 XLATEOBJ
* ColorTranslation
,
61 typedef BOOLEAN
STDCALL (*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
66 XLATEOBJ
* ColorTranslation
,
73 BOOL STDCALL
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
75 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
77 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
78 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
80 if (prcDst
->left
< prcDst
->right
)
82 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
83 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
85 if (prcDst
->top
< prcDst
->bottom
)
96 static BOOLEAN STDCALL
97 BltMask(SURFOBJ
* Dest
,
102 XLATEOBJ
* ColorTranslation
,
110 LONG i
, j
, dx
, dy
, c8
;
112 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
113 /* Pattern brushes */
114 PGDIBRUSHOBJ GdiBrush
;
115 HBITMAP PatternSurface
= NULL
;
117 ULONG PatternWidth
, PatternHeight
, PatternY
;
124 dx
= DestRect
->right
- DestRect
->left
;
125 dy
= DestRect
->bottom
- DestRect
->top
;
127 if (Brush
->iSolidColor
== 0xFFFFFFFF)
129 PBITMAPOBJ PatternBitmap
;
131 GdiBrush
= CONTAINING_RECORD(
136 PatternBitmap
= BITMAPOBJ_LockBitmap(GdiBrush
->hbmPattern
);
137 PatternSurface
= BitmapToSurf(PatternBitmap
, Dest
->hdev
);
138 BITMAPOBJ_UnlockBitmap(GdiBrush
->hbmPattern
);
140 PatternObj
= (SURFOBJ
*)AccessUserObject((ULONG
)PatternSurface
);
141 PatternWidth
= PatternObj
->sizlBitmap
.cx
;
142 PatternHeight
= PatternObj
->sizlBitmap
.cy
;
145 tMask
= Mask
->pvScan0
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
146 for (j
= 0; j
< dy
; j
++)
149 c8
= SourcePoint
->x
& 0x07;
152 PatternY
= (DestRect
->top
+ j
) % PatternHeight
;
154 for (i
= 0; i
< dx
; i
++)
156 if (0 != (*lMask
& maskbit
[c8
]))
158 if (PatternSurface
== NULL
)
160 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
164 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
,
165 DIB_1BPP_GetPixel(PatternObj
, (DestRect
->left
+ i
) % PatternWidth
, PatternY
) ? GdiBrush
->crFore
: GdiBrush
->crBack
);
175 tMask
+= Mask
->lDelta
;
178 if (PatternSurface
!= NULL
)
179 EngDeleteSurface((HSURF
)PatternSurface
);
184 static BOOLEAN STDCALL
185 BltPatCopy(SURFOBJ
* Dest
,
190 XLATEOBJ
* ColorTranslation
,
198 // These functions are assigned if we're working with a DIB
199 // The assigned functions depend on the bitsPerPixel of the DIB
203 LineWidth
= DestRect
->right
- DestRect
->left
;
204 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
206 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
212 static BOOLEAN STDCALL
213 CallDibBitBlt(SURFOBJ
* OutputObj
,
218 XLATEOBJ
* ColorTranslation
,
226 POINTL RealBrushOrigin
;
227 if (BrushOrigin
== NULL
)
229 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
233 RealBrushOrigin
= *BrushOrigin
;
235 return OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputPoint
, Brush
, RealBrushOrigin
, ColorTranslation
, Rop4
);
244 EngBitBlt(SURFOBJ
*DestObj
,
248 XLATEOBJ
*ColorTranslation
,
266 INTENG_ENTER_LEAVE EnterLeaveSource
;
267 INTENG_ENTER_LEAVE EnterLeaveDest
;
270 PBLTRECTFUNC BltRectFunc
;
278 POINTL AdjustedBrushOrigin
;
280 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
281 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
282 if (ROP_NOOP
== Rop4
)
284 /* Copy destination onto itself: nop */
288 if (NULL
!= SourcePoint
)
290 InputRect
.left
= SourcePoint
->x
;
291 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
292 InputRect
.top
= SourcePoint
->y
;
293 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
298 InputRect
.right
= DestRect
->right
- DestRect
->left
;
300 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
303 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
308 if (NULL
!= SourcePoint
)
310 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
311 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
319 if (NULL
!= InputObj
)
321 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
328 OutputRect
= *DestRect
;
329 if (NULL
!= ClipRegion
)
331 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
333 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
334 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
335 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
337 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
339 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
340 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
342 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
344 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
345 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
346 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
348 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
350 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
351 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
355 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
357 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
359 IntEngLeave(&EnterLeaveSource
);
363 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
365 IntEngLeave(&EnterLeaveSource
);
369 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
370 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
371 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
372 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
374 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
375 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
377 if (NULL
!= OutputObj
)
379 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
382 // Determine clipping type
383 if (ClipRegion
== (CLIPOBJ
*) NULL
)
385 clippingType
= DC_TRIVIAL
;
387 clippingType
= ClipRegion
->iDComplexity
;
392 BltRectFunc
= BltMask
;
394 else if (PATCOPY
== Rop4
)
397 BltRectFunc
= BltPatCopy
;
399 if (Brush
->iSolidColor
== 0xFFFFFFFF)
400 BltRectFunc
= CallDibBitBlt
;
402 BltRectFunc
= BltPatCopy
;
407 BltRectFunc
= CallDibBitBlt
;
414 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
415 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
418 // Clip the blt to the clip rectangle
419 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
420 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
421 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
422 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
423 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
424 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
425 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
426 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
427 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
);
431 if (OutputObj
== InputObj
)
433 if (OutputRect
.top
< InputPoint
.y
)
435 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
439 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
446 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
449 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
451 for (i
= 0; i
< RectEnum
.c
; i
++)
453 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
454 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
455 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
456 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
457 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
458 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
459 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
460 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
461 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, Rop4
) &&
470 IntEngLeave(&EnterLeaveDest
);
471 IntEngLeave(&EnterLeaveSource
);
477 IntEngBitBlt(SURFOBJ
*DestObj
,
481 XLATEOBJ
*ColorTranslation
,
492 RECTL InputClippedRect
;
497 InputClippedRect
= *DestRect
;
498 if (InputClippedRect
.right
< InputClippedRect
.left
)
500 InputClippedRect
.left
= DestRect
->right
;
501 InputClippedRect
.right
= DestRect
->left
;
503 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
505 InputClippedRect
.top
= DestRect
->bottom
;
506 InputClippedRect
.bottom
= DestRect
->top
;
508 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
511 if (NULL
== SourcePoint
|| NULL
== SourceObj
)
515 InputPoint
= *SourcePoint
;
516 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
518 /* Make sure we don't try to copy anything outside the valid source region */
519 if (InputPoint
.x
< 0)
521 InputClippedRect
.left
-= InputPoint
.x
;
524 if (InputPoint
.y
< 0)
526 InputClippedRect
.top
-= InputPoint
.y
;
529 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+ InputClippedRect
.right
- InputClippedRect
.left
)
531 InputClippedRect
.right
= InputClippedRect
.left
+ SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
533 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+ InputClippedRect
.bottom
- InputClippedRect
.top
)
535 InputClippedRect
.bottom
= InputClippedRect
.top
+ SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
538 if (InputClippedRect
.right
< InputClippedRect
.left
||
539 InputClippedRect
.bottom
< InputClippedRect
.top
)
541 /* Everything clipped away, nothing to do */
546 /* Clip against the bounds of the clipping region so we won't try to write
547 * outside the surface */
548 if (NULL
!= ClipRegion
)
550 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
, &ClipRegion
->rclBounds
))
554 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
555 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
559 OutputRect
= InputClippedRect
;
564 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
565 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
566 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
571 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
572 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
573 OutputRect
.right
, OutputRect
.bottom
);
575 /* Call the driver's DrvBitBlt if available */
576 if (NULL
!= DestGDI
->BitBlt
)
578 IntLockGDIDriver(DestGDI
);
579 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
580 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
582 IntUnLockGDIDriver(DestGDI
);
587 IntLockGDIDriver(DestGDI
);
588 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
589 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
591 IntUnLockGDIDriver(DestGDI
);
594 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
597 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
603 static BOOLEAN STDCALL
604 CallDibStretchBlt(SURFOBJ
* OutputObj
,
609 XLATEOBJ
* ColorTranslation
,
616 POINTL RealBrushOrigin
;
617 if (BrushOrigin
== NULL
)
619 RealBrushOrigin
.x
= RealBrushOrigin
.y
= 0;
623 RealBrushOrigin
= *BrushOrigin
;
625 return OutputGDI
->DIB_StretchBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputRect
, MaskOrigin
, RealBrushOrigin
, ColorTranslation
, Mode
);
633 IN SURFOBJ
*SourceObj
,
635 IN CLIPOBJ
*ClipRegion
,
636 IN XLATEOBJ
*ColorTranslation
,
637 IN COLORADJUSTMENT
*pca
,
638 IN POINTL
*BrushOrigin
,
641 IN POINTL
*MaskOrigin
,
645 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
649 // RECT_ENUM RectEnum;
657 INTENG_ENTER_LEAVE EnterLeaveSource
;
658 INTENG_ENTER_LEAVE EnterLeaveDest
;
661 PSTRETCHRECTFUNC BltRectFunc
;
667 POINTL AdjustedBrushOrigin
;
669 InputRect
.left
= prclSrc
->left
;
670 InputRect
.right
= prclSrc
->right
;
671 InputRect
.top
= prclSrc
->top
;
672 InputRect
.bottom
= prclSrc
->bottom
;
674 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
679 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
680 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
682 if (NULL
!= InputObj
)
684 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
691 OutputRect
= *prclDest
;
692 if (NULL
!= ClipRegion
)
694 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
696 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
697 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
698 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
700 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
702 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
703 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
705 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
707 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
708 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
709 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
711 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
713 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
714 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
718 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
720 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
722 IntEngLeave(&EnterLeaveSource
);
726 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
728 IntEngLeave(&EnterLeaveSource
);
732 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
733 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
734 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
735 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
737 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
738 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
740 if (NULL
!= OutputObj
)
742 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
745 // Determine clipping type
746 if (ClipRegion
== (CLIPOBJ
*) NULL
)
748 clippingType
= DC_TRIVIAL
;
750 clippingType
= ClipRegion
->iDComplexity
;
753 if (Mask
!= NULL
)//(0xaacc == Rop4)
755 //BltRectFunc = BltMask;
756 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
757 IntEngLeave(&EnterLeaveDest
);
758 IntEngLeave(&EnterLeaveSource
);
764 BltRectFunc
= CallDibStretchBlt
;
771 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
772 &OutputRect
, &InputRect
, MaskOrigin
, &AdjustedBrushOrigin
, Mode
);
775 // Clip the blt to the clip rectangle
776 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
777 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
778 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
779 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
780 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
781 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
782 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
783 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
784 &OutputRect
, &InputRect
, MaskOrigin
, &AdjustedBrushOrigin
, Mode
);
785 //Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
786 // &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
787 DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n");
789 // TODO: Complex clipping
793 if (OutputObj == InputObj)
795 if (OutputRect.top < InputPoint.y)
797 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
801 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
808 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
811 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
813 for (i = 0; i < RectEnum.c; i++)
815 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
816 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
817 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
818 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
819 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
820 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
821 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
822 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
823 &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4) &&
833 IntEngLeave(&EnterLeaveDest
);
834 IntEngLeave(&EnterLeaveSource
);
840 IntEngStretchBlt(SURFOBJ
*DestObj
,
844 XLATEOBJ
*ColorTranslation
,
860 if (pMaskOrigin
!= NULL
)
862 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
865 if (NULL
!= SourceRect
)
867 InputRect
= *SourceRect
;
870 // FIXME: Clipping is taken from IntEngBitBlt w/o modifications!
872 /* Clip against the bounds of the clipping region so we won't try to write
873 * outside the surface */
874 if (NULL
!= ClipRegion
)
876 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
880 DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n");
881 //InputPoint.x += OutputRect.left - DestRect->left;
882 //InputPoint.y += OutputRect.top - DestRect->top;
886 OutputRect
= *DestRect
;
889 if (NULL
!= SourceObj
)
891 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
892 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputRect
.left
, InputRect
.top
,
893 (InputRect
.left
+ abs(InputRect
.right
- InputRect
.left
)),
894 (InputRect
.top
+ abs(InputRect
.bottom
- InputRect
.top
)));
899 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
900 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
901 OutputRect
.right
, OutputRect
.bottom
);
903 /* Prepare color adjustment */
905 /* Call the driver's DrvStretchBlt if available */
906 if (NULL
!= DestGDI
->StretchBlt
)
908 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
909 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
910 // FIXME: MaskOrigin is always NULL !
911 IntLockGDIDriver(DestGDI
);
912 ret
= DestGDI
->StretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
913 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, Mode
);
914 IntUnLockGDIDriver(DestGDI
);
919 // FIXME: see previous fixme
920 ret
= EngStretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
921 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, Mode
);
924 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
925 if (NULL
!= SourceObj
)
927 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
933 /**** REACTOS FONT RENDERING CODE *********************************************/
935 /* renders the alpha mask bitmap */
936 static BOOLEAN STDCALL
937 AlphaBltMask(SURFOBJ
* Dest
,
942 XLATEOBJ
* ColorTranslation
,
943 XLATEOBJ
* SrcColorTranslation
,
952 ULONG Background
, BrushColor
, NewColor
;
955 dx
= DestRect
->right
- DestRect
->left
;
956 dy
= DestRect
->bottom
- DestRect
->top
;
960 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
961 r
= (int)GetRValue(BrushColor
);
962 g
= (int)GetGValue(BrushColor
);
963 b
= (int)GetBValue(BrushColor
);
965 tMask
= Mask
->pvBits
+ (SourcePoint
->y
* Mask
->lDelta
) + SourcePoint
->x
;
966 for (j
= 0; j
< dy
; j
++)
969 for (i
= 0; i
< dx
; i
++)
975 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
979 Background
= DIB_GetSource(Dest
, DestGDI
, DestRect
->left
+ i
, DestRect
->top
+ j
, SrcColorTranslation
);
982 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
983 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
984 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
986 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
987 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
992 tMask
+= Mask
->lDelta
;
1003 EngMaskBitBlt(SURFOBJ
*DestObj
,
1005 CLIPOBJ
*ClipRegion
,
1006 XLATEOBJ
*DestColorTranslation
,
1007 XLATEOBJ
*SourceColorTranslation
,
1009 POINTL
*SourcePoint
,
1012 POINTL
*BrushOrigin
)
1024 INTENG_ENTER_LEAVE EnterLeaveSource
;
1025 INTENG_ENTER_LEAVE EnterLeaveDest
;
1034 POINTL AdjustedBrushOrigin
;
1036 if (NULL
!= SourcePoint
)
1038 InputRect
.left
= SourcePoint
->x
;
1039 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
1040 InputRect
.top
= SourcePoint
->y
;
1041 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
1046 InputRect
.right
= DestRect
->right
- DestRect
->left
;
1048 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
1051 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
1052 IntLockGDIDriver(DestGDI
);
1053 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
1055 IntUnLockGDIDriver(DestGDI
);
1059 if (NULL
!= SourcePoint
)
1061 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
1062 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
1070 if (NULL
!= InputObj
)
1072 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
1079 OutputRect
= *DestRect
;
1080 if (NULL
!= ClipRegion
)
1082 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1084 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1085 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1086 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1088 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1090 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1091 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1093 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1095 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1096 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1097 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1099 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1101 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1102 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1106 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1108 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1110 IntEngLeave(&EnterLeaveSource
);
1111 IntUnLockGDIDriver(DestGDI
);
1115 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1117 IntEngLeave(&EnterLeaveSource
);
1118 IntUnLockGDIDriver(DestGDI
);
1122 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1123 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1124 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1125 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1127 AdjustedBrushOrigin
.x
= BrushOrigin
->x
+ Translate
.x
;
1128 AdjustedBrushOrigin
.y
= BrushOrigin
->y
+ Translate
.y
;
1130 if (NULL
!= OutputObj
)
1132 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
1135 // Determine clipping type
1136 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1138 clippingType
= DC_TRIVIAL
;
1140 clippingType
= ClipRegion
->iDComplexity
;
1143 switch(clippingType
)
1146 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1147 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1148 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1150 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1151 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1154 // Clip the blt to the clip rectangle
1155 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1156 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1157 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1158 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1159 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1160 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1161 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1162 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1163 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1164 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
);
1166 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1167 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC);
1171 if (OutputObj
== InputObj
)
1173 if (OutputRect
.top
< InputPoint
.y
)
1175 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1179 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1186 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1189 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1191 for (i
= 0; i
< RectEnum
.c
; i
++)
1193 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1194 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1195 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1196 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1197 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1198 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1199 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1200 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1201 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1202 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
) && Ret
;
1204 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1205 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, &AdjustedBrushOrigin
, 0xAACC) && Ret
;
1213 IntEngLeave(&EnterLeaveDest
);
1214 IntEngLeave(&EnterLeaveSource
);
1216 IntUnLockGDIDriver(DestGDI
);
1218 /* Dummy BitBlt to let driver know that something has changed.
1219 0x00AA0029 is the Rop for D (no-op) */
1220 IntEngBitBlt(DestObj
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1221 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, ROP_NOOP
);
1227 IntEngMaskBlt(SURFOBJ
*DestObj
,
1229 CLIPOBJ
*ClipRegion
,
1230 XLATEOBJ
*DestColorTranslation
,
1231 XLATEOBJ
*SourceColorTranslation
,
1233 POINTL
*SourcePoint
,
1236 POINTL
*BrushOrigin
)
1243 if (NULL
!= SourcePoint
)
1245 InputPoint
= *SourcePoint
;
1248 /* Clip against the bounds of the clipping region so we won't try to write
1249 * outside the surface */
1250 if (NULL
!= ClipRegion
)
1252 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1256 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1257 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1261 OutputRect
= *DestRect
;
1264 /* No success yet */
1266 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
1267 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
1268 OutputRect
.right
, OutputRect
.bottom
);
1270 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1271 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1273 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);