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.42 2004/02/24 13:27:02 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/eng.h>
44 #include <include/inteng.h>
47 #include <win32k/debug1.h>
49 #define ROP_NOOP 0x00AA0029
51 typedef BOOLEAN
STDCALL (*PBLTRECTFUNC
)(SURFOBJ
* OutputObj
,
56 XLATEOBJ
* ColorTranslation
,
63 typedef BOOLEAN
STDCALL (*PSTRETCHRECTFUNC
)(SURFOBJ
* OutputObj
,
68 XLATEOBJ
* ColorTranslation
,
75 BOOL STDCALL
EngIntersectRect(RECTL
* prcDst
, RECTL
* prcSrc1
, RECTL
* prcSrc2
)
77 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
79 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
80 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
82 if (prcDst
->left
< prcDst
->right
)
84 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
85 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
87 if (prcDst
->top
< prcDst
->bottom
)
98 static BOOLEAN STDCALL
99 BltMask(SURFOBJ
* Dest
,
104 XLATEOBJ
* ColorTranslation
,
112 LONG i
, j
, dx
, dy
, c8
;
114 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
116 dx
= DestRect
->right
- DestRect
->left
;
117 dy
= DestRect
->bottom
- DestRect
->top
;
121 tMask
= Mask
->pvBits
+ SourcePoint
->y
* Mask
->lDelta
+ (SourcePoint
->x
>> 3);
122 for (j
= 0; j
< dy
; j
++)
125 c8
= SourcePoint
->x
& 0x07;
126 for (i
= 0; i
< dx
; i
++)
128 if (0 != (*lMask
& maskbit
[c8
]))
130 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
139 tMask
+= Mask
->lDelta
;
149 static BOOLEAN STDCALL
150 BltPatCopy(SURFOBJ
* Dest
,
155 XLATEOBJ
* ColorTranslation
,
163 // These functions are assigned if we're working with a DIB
164 // The assigned functions depend on the bitsPerPixel of the DIB
168 LineWidth
= DestRect
->right
- DestRect
->left
;
169 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
171 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
177 static BOOLEAN STDCALL
178 CallDibBitBlt(SURFOBJ
* OutputObj
,
183 XLATEOBJ
* ColorTranslation
,
191 return OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputPoint
, Brush
, BrushOrigin
, ColorTranslation
, Rop4
);
200 EngBitBlt(SURFOBJ
*DestObj
,
204 XLATEOBJ
*ColorTranslation
,
222 INTENG_ENTER_LEAVE EnterLeaveSource
;
223 INTENG_ENTER_LEAVE EnterLeaveDest
;
226 PBLTRECTFUNC BltRectFunc
;
235 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
236 UsesPattern
= ((Rop4
& 0xF00000) >> 4) != (Rop4
& 0x0F0000);
237 if (ROP_NOOP
== Rop4
)
239 /* Copy destination onto itself: nop */
243 if (NULL
!= SourcePoint
)
245 InputRect
.left
= SourcePoint
->x
;
246 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
247 InputRect
.top
= SourcePoint
->y
;
248 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
253 InputRect
.right
= DestRect
->right
- DestRect
->left
;
255 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
258 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
263 if (NULL
!= SourcePoint
)
265 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
266 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
274 if (NULL
!= InputObj
)
276 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
283 OutputRect
= *DestRect
;
284 if (NULL
!= ClipRegion
)
286 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
288 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
289 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
290 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
292 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
294 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
295 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
297 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
299 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
300 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
301 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
303 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
305 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
306 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
310 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
312 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
314 IntEngLeave(&EnterLeaveSource
);
318 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
320 IntEngLeave(&EnterLeaveSource
);
324 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
325 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
326 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
327 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
329 if (NULL
!= OutputObj
)
331 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
334 // Determine clipping type
335 if (ClipRegion
== (CLIPOBJ
*) NULL
)
337 clippingType
= DC_TRIVIAL
;
339 clippingType
= ClipRegion
->iDComplexity
;
344 BltRectFunc
= BltMask
;
346 else if (PATCOPY
== Rop4
)
348 BltRectFunc
= BltPatCopy
;
352 BltRectFunc
= CallDibBitBlt
;
359 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
360 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
363 // Clip the blt to the clip rectangle
364 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
365 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
366 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
367 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
368 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
369 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
370 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
371 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
372 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
376 if (OutputObj
== InputObj
)
378 if (OutputRect
.top
< InputPoint
.y
)
380 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
384 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
391 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
394 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
396 for (i
= 0; i
< RectEnum
.c
; i
++)
398 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
399 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
400 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
401 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
402 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
403 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
404 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
405 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
406 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
) &&
415 IntEngLeave(&EnterLeaveDest
);
416 IntEngLeave(&EnterLeaveSource
);
422 IntEngBitBlt(SURFOBJ
*DestObj
,
426 XLATEOBJ
*ColorTranslation
,
437 RECTL InputClippedRect
;
442 InputClippedRect
= *DestRect
;
443 if (InputClippedRect
.right
< InputClippedRect
.left
)
445 InputClippedRect
.left
= DestRect
->right
;
446 InputClippedRect
.right
= DestRect
->left
;
448 if (InputClippedRect
.bottom
< InputClippedRect
.top
)
450 InputClippedRect
.top
= DestRect
->bottom
;
451 InputClippedRect
.bottom
= DestRect
->top
;
453 UsesSource
= ((Rop4
& 0xCC0000) >> 2) != (Rop4
& 0x330000);
456 if (NULL
== SourcePoint
|| NULL
== SourceObj
)
460 InputPoint
= *SourcePoint
;
461 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
463 /* Make sure we don't try to copy anything outside the valid source region */
464 if (InputPoint
.x
< 0)
466 InputClippedRect
.left
-= InputPoint
.x
;
469 if (InputPoint
.y
< 0)
471 InputClippedRect
.top
-= InputPoint
.y
;
474 if (SourceObj
->sizlBitmap
.cx
< InputPoint
.x
+ InputClippedRect
.right
- InputClippedRect
.left
)
476 InputClippedRect
.right
= InputClippedRect
.left
+ SourceObj
->sizlBitmap
.cx
- InputPoint
.x
;
478 if (SourceObj
->sizlBitmap
.cy
< InputPoint
.y
+ InputClippedRect
.bottom
- InputClippedRect
.top
)
480 InputClippedRect
.bottom
= InputClippedRect
.top
+ SourceObj
->sizlBitmap
.cy
- InputPoint
.y
;
483 if (InputClippedRect
.right
< InputClippedRect
.left
||
484 InputClippedRect
.bottom
< InputClippedRect
.top
)
486 /* Everything clipped away, nothing to do */
491 /* Clip against the bounds of the clipping region so we won't try to write
492 * outside the surface */
493 if (NULL
!= ClipRegion
)
495 if (! EngIntersectRect(&OutputRect
, &InputClippedRect
, &ClipRegion
->rclBounds
))
499 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
500 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
504 OutputRect
= InputClippedRect
;
509 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
510 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
511 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
516 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
517 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
518 OutputRect
.right
, OutputRect
.bottom
);
520 /* Call the driver's DrvBitBlt if available */
521 if (NULL
!= DestGDI
->BitBlt
)
523 IntLockGDIDriver(DestGDI
);
524 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
525 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
527 IntUnLockGDIDriver(DestGDI
);
532 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
533 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
537 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
540 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
546 static BOOLEAN STDCALL
547 CallDibStretchBlt(SURFOBJ
* OutputObj
,
552 XLATEOBJ
* ColorTranslation
,
559 return OutputGDI
->DIB_StretchBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputRect
, MaskOrigin
, BrushOrigin
, ColorTranslation
, Mode
);
567 IN SURFOBJ
*SourceObj
,
569 IN CLIPOBJ
*ClipRegion
,
570 IN XLATEOBJ
*ColorTranslation
,
571 IN COLORADJUSTMENT
*pca
,
572 IN POINTL
*BrushOrigin
,
575 IN POINTL
*MaskOrigin
,
579 // www.osr.com/ddk/graphics/gdifncs_0bs7.htm
583 // RECT_ENUM RectEnum;
591 INTENG_ENTER_LEAVE EnterLeaveSource
;
592 INTENG_ENTER_LEAVE EnterLeaveDest
;
595 PSTRETCHRECTFUNC BltRectFunc
;
602 InputRect
.left
= prclSrc
->left
;
603 InputRect
.right
= prclSrc
->right
;
604 InputRect
.top
= prclSrc
->top
;
605 InputRect
.bottom
= prclSrc
->bottom
;
607 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
612 InputPoint
.x
= InputRect
.left
+ Translate
.x
;
613 InputPoint
.y
= InputRect
.top
+ Translate
.y
;
615 if (NULL
!= InputObj
)
617 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
624 OutputRect
= *prclDest
;
625 if (NULL
!= ClipRegion
)
627 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
629 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
630 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
631 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
633 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
635 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
636 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
638 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
640 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
641 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
642 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
644 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
646 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
647 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
651 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
653 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
655 IntEngLeave(&EnterLeaveSource
);
659 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
661 IntEngLeave(&EnterLeaveSource
);
665 OutputRect
.left
= prclDest
->left
+ Translate
.x
;
666 OutputRect
.right
= prclDest
->right
+ Translate
.x
;
667 OutputRect
.top
= prclDest
->top
+ Translate
.y
;
668 OutputRect
.bottom
= prclDest
->bottom
+ Translate
.y
;
670 if (NULL
!= OutputObj
)
672 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
675 // Determine clipping type
676 if (ClipRegion
== (CLIPOBJ
*) NULL
)
678 clippingType
= DC_TRIVIAL
;
680 clippingType
= ClipRegion
->iDComplexity
;
683 if (Mask
!= NULL
)//(0xaacc == Rop4)
685 //BltRectFunc = BltMask;
686 DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
687 IntEngLeave(&EnterLeaveDest
);
688 IntEngLeave(&EnterLeaveSource
);
694 BltRectFunc
= CallDibStretchBlt
;
701 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
702 &OutputRect
, &InputRect
, MaskOrigin
, BrushOrigin
, Mode
);
705 // Clip the blt to the clip rectangle
706 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
707 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
708 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
709 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
710 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
711 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
712 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
713 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
714 &OutputRect
, &InputRect
, MaskOrigin
, BrushOrigin
, Mode
);
715 //Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
716 // &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
717 DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n");
719 // TODO: Complex clipping
723 if (OutputObj == InputObj)
725 if (OutputRect.top < InputPoint.y)
727 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
731 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
738 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
741 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
743 for (i = 0; i < RectEnum.c; i++)
745 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
746 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
747 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
748 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
749 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
750 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
751 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
752 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
753 &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) &&
763 IntEngLeave(&EnterLeaveDest
);
764 IntEngLeave(&EnterLeaveSource
);
770 IntEngStretchBlt(SURFOBJ
*DestObj
,
774 XLATEOBJ
*ColorTranslation
,
790 if (pMaskOrigin
!= NULL
)
792 MaskOrigin
.x
= pMaskOrigin
->x
; MaskOrigin
.y
= pMaskOrigin
->y
;
795 if (NULL
!= SourceRect
)
797 InputRect
= *SourceRect
;
800 // FIXME: Clipping is taken from IntEngBitBlt w/o modifications!
802 /* Clip against the bounds of the clipping region so we won't try to write
803 * outside the surface */
804 if (NULL
!= ClipRegion
)
806 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
810 DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n");
811 //InputPoint.x += OutputRect.left - DestRect->left;
812 //InputPoint.y += OutputRect.top - DestRect->top;
816 OutputRect
= *DestRect
;
819 if (NULL
!= SourceObj
)
821 SourceGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(SourceObj
);
822 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputRect
.left
, InputRect
.top
,
823 (InputRect
.left
+ abs(InputRect
.right
- InputRect
.left
)),
824 (InputRect
.top
+ abs(InputRect
.bottom
- InputRect
.top
)));
829 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
830 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
831 OutputRect
.right
, OutputRect
.bottom
);
833 /* Prepare color adjustment */
835 /* Call the driver's DrvStretchBlt if available */
836 if (NULL
!= DestGDI
->StretchBlt
)
838 /* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
839 SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
840 // FIXME: MaskOrigin is always NULL !
841 IntLockGDIDriver(DestGDI
);
842 ret
= DestGDI
->StretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
843 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, Mode
);
844 IntUnLockGDIDriver(DestGDI
);
849 // FIXME: see previous fixme
850 ret
= EngStretchBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
851 &ca
, BrushOrigin
, &OutputRect
, &InputRect
, NULL
, Mode
);
854 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
855 if (NULL
!= SourceObj
)
857 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);
863 /**** REACTOS FONT RENDERING CODE *********************************************/
865 /* renders the alpha mask bitmap */
866 static BOOLEAN STDCALL
867 AlphaBltMask(SURFOBJ
* Dest
,
872 XLATEOBJ
* ColorTranslation
,
873 XLATEOBJ
* SrcColorTranslation
,
882 ULONG Background
, BrushColor
, NewColor
;
885 dx
= DestRect
->right
- DestRect
->left
;
886 dy
= DestRect
->bottom
- DestRect
->top
;
890 BrushColor
= XLATEOBJ_iXlate(SrcColorTranslation
, Brush
->iSolidColor
);
891 r
= (int)GetRValue(BrushColor
);
892 g
= (int)GetGValue(BrushColor
);
893 b
= (int)GetBValue(BrushColor
);
895 tMask
= Mask
->pvBits
+ MaskPoint
->y
* Mask
->lDelta
+ MaskPoint
->x
;
896 for (j
= 0; j
< dy
; j
++)
899 for (i
= 0; i
< dx
; i
++)
905 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
909 Background
= DIB_GetSource(Dest
, DestGDI
, DestRect
->left
+ i
, DestRect
->top
+ j
, SrcColorTranslation
);
912 RGB((*lMask
* (r
- GetRValue(Background
)) >> 8) + GetRValue(Background
),
913 (*lMask
* (g
- GetGValue(Background
)) >> 8) + GetGValue(Background
),
914 (*lMask
* (b
- GetBValue(Background
)) >> 8) + GetBValue(Background
));
916 Background
= XLATEOBJ_iXlate(ColorTranslation
, NewColor
);
917 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Background
);
922 tMask
+= Mask
->lDelta
;
933 EngMaskBitBlt(SURFOBJ
*DestObj
,
936 XLATEOBJ
*DestColorTranslation
,
937 XLATEOBJ
*SourceColorTranslation
,
954 INTENG_ENTER_LEAVE EnterLeaveSource
;
955 INTENG_ENTER_LEAVE EnterLeaveDest
;
965 if (NULL
!= SourcePoint
)
967 InputRect
.left
= SourcePoint
->x
;
968 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
969 InputRect
.top
= SourcePoint
->y
;
970 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
975 InputRect
.right
= DestRect
->right
- DestRect
->left
;
977 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
980 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
981 IntLockGDIDriver(DestGDI
);
982 if (! IntEngEnter(&EnterLeaveSource
, NULL
, &InputRect
, TRUE
, &Translate
, &InputObj
))
984 IntUnLockGDIDriver(DestGDI
);
988 if (NULL
!= SourcePoint
)
990 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
991 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
999 if (NULL
!= InputObj
)
1001 InputGDI
= (SURFGDI
*) AccessInternalObjectFromUserObject(InputObj
);
1008 OutputRect
= *DestRect
;
1009 if (NULL
!= ClipRegion
)
1011 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
1013 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1014 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
1015 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
1017 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
1019 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
1020 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
1022 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
1024 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1025 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
1026 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
1028 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
1030 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
1031 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
1035 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
1037 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
1039 IntEngLeave(&EnterLeaveSource
);
1040 IntUnLockGDIDriver(DestGDI
);
1044 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
1046 IntEngLeave(&EnterLeaveSource
);
1047 IntUnLockGDIDriver(DestGDI
);
1051 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
1052 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
1053 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
1054 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
1056 if (NULL
!= OutputObj
)
1058 OutputGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(OutputObj
);
1061 // Determine clipping type
1062 if (ClipRegion
== (CLIPOBJ
*) NULL
)
1064 clippingType
= DC_TRIVIAL
;
1066 clippingType
= ClipRegion
->iDComplexity
;
1069 switch(clippingType
)
1072 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1073 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1074 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1076 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1077 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC);
1080 // Clip the blt to the clip rectangle
1081 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
1082 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
1083 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
1084 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
1085 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1086 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1087 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1088 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1089 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1090 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
);
1092 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1093 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC);
1097 if (OutputObj
== InputObj
)
1099 if (OutputRect
.top
< InputPoint
.y
)
1101 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTDOWN
: CD_LEFTDOWN
;
1105 Direction
= OutputRect
.left
< InputPoint
.x
? CD_RIGHTUP
: CD_LEFTUP
;
1112 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, Direction
, 0);
1115 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
1117 for (i
= 0; i
< RectEnum
.c
; i
++)
1119 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
1120 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
1121 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
1122 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
1123 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
1124 Pt
.x
= InputPoint
.x
+ CombinedRect
.left
- OutputRect
.left
;
1125 Pt
.y
= InputPoint
.y
+ CombinedRect
.top
- OutputRect
.top
;
1126 if(Mask
->iBitmapFormat
== BMF_8BPP
)
1127 Ret
= AlphaBltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
, SourceColorTranslation
,
1128 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
) && Ret
;
1130 Ret
= BltMask(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, DestColorTranslation
,
1131 &CombinedRect
, &Pt
, MaskOrigin
, Brush
, BrushOrigin
, 0xAACC) && Ret
;
1139 IntEngLeave(&EnterLeaveDest
);
1140 IntEngLeave(&EnterLeaveSource
);
1142 IntUnLockGDIDriver(DestGDI
);
1144 /* Dummy BitBlt to let driver know that something has changed.
1145 0x00AA0029 is the Rop for D (no-op) */
1146 IntEngBitBlt(DestObj
, NULL
, Mask
, ClipRegion
, DestColorTranslation
,
1147 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, ROP_NOOP
);
1153 IntEngMaskBlt(SURFOBJ
*DestObj
,
1155 CLIPOBJ
*ClipRegion
,
1156 XLATEOBJ
*DestColorTranslation
,
1157 XLATEOBJ
*SourceColorTranslation
,
1159 POINTL
*SourcePoint
,
1162 POINTL
*BrushOrigin
)
1169 if (NULL
!= SourcePoint
)
1171 InputPoint
= *SourcePoint
;
1174 /* Clip against the bounds of the clipping region so we won't try to write
1175 * outside the surface */
1176 if (NULL
!= ClipRegion
)
1178 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
1182 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
1183 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
1187 OutputRect
= *DestRect
;
1190 /* No success yet */
1192 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
1193 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
1194 OutputRect
.right
, OutputRect
.bottom
);
1196 ret
= EngMaskBitBlt(DestObj
, Mask
, ClipRegion
, DestColorTranslation
, SourceColorTranslation
,
1197 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
);
1199 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);