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.20 2003/05/18 17:16:17 ea 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/copybits.h>
44 #include <include/inteng.h>
47 #include <win32k/debug1.h>
49 BOOL STDCALL
EngIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
51 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
53 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
54 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
56 if (prcDst
->left
< prcDst
->right
)
58 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
59 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
61 if (prcDst
->top
< prcDst
->bottom
) return(TRUE
);
70 BltMask(SURFOBJ
*Dest
, PSURFGDI DestGDI
, SURFOBJ
*Mask
,
71 RECTL
*DestRect
, POINTL
*MaskPoint
, BRUSHOBJ
* Brush
,
74 LONG i
, j
, dx
, dy
, c8
;
76 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
78 dx
= DestRect
->right
- DestRect
->left
;
79 dy
= DestRect
->bottom
- DestRect
->top
;
84 for (j
= 0; j
< dy
; j
++)
88 for (i
= 0; i
< dx
; i
++)
90 if (0 != (*lMask
& maskbit
[c8
]))
92 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
101 tMask
+= Mask
->lDelta
;
112 BltPatCopy(SURFOBJ
*Dest
, PSURFGDI DestGDI
, SURFOBJ
*Mask
,
113 RECTL
*DestRect
, POINTL
*MaskPoint
, BRUSHOBJ
* Brush
,
116 // These functions are assigned if we're working with a DIB
117 // The assigned functions depend on the bitsPerPixel of the DIB
121 LineWidth
= DestRect
->right
- DestRect
->left
;
122 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
124 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
133 EngBitBlt(SURFOBJ
*DestObj
,
137 XLATEOBJ
*ColorTranslation
,
151 PSURFGDI OutputGDI
, InputGDI
;
156 INTENG_ENTER_LEAVE EnterLeaveSource
;
157 INTENG_ENTER_LEAVE EnterLeaveDest
;
161 /* Check for degenerate case: if height or width of DestRect is 0 pixels there's
163 if (DestRect
->right
== DestRect
->left
|| DestRect
->bottom
== DestRect
->top
)
168 if (NULL
!= SourcePoint
)
170 InputRect
.left
= SourcePoint
->x
;
171 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
172 InputRect
.top
= SourcePoint
->y
;
173 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
178 InputRect
.right
= DestRect
->right
- DestRect
->left
;
180 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
183 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
188 if (NULL
!= SourcePoint
)
190 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
191 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
199 if (NULL
!= InputObj
)
201 InputGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(InputObj
);
204 OutputRect
= *DestRect
;
206 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
208 IntEngLeave(&EnterLeaveSource
);
212 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
213 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
214 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
215 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
218 if (NULL
!= OutputObj
)
220 OutputGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(OutputObj
);
223 /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
224 * paint a brush pattern on the destination. */
225 if (NULL
== InputObj
&& 0xaacc != rop4
&& PATCOPY
!= rop4
)
227 DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
231 // Determine clipping type
232 if (ClipRegion
== (CLIPOBJ
*) NULL
)
234 clippingType
= DC_TRIVIAL
;
236 clippingType
= ClipRegion
->iDComplexity
;
241 ret
= BltMask(OutputObj
, OutputGDI
, Mask
, &OutputRect
, MaskOrigin
, Brush
, BrushOrigin
);
242 IntEngLeave(&EnterLeaveDest
);
243 IntEngLeave(&EnterLeaveSource
);
245 } else if (PATCOPY
== rop4
) {
246 ret
= BltPatCopy(OutputObj
, OutputGDI
, Mask
, &OutputRect
, MaskOrigin
, Brush
, BrushOrigin
);
247 IntEngLeave(&EnterLeaveDest
);
248 IntEngLeave(&EnterLeaveSource
);
253 // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
257 OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, &OutputRect
, &InputPoint
, ColorTranslation
);
259 IntEngLeave(&EnterLeaveDest
);
260 IntEngLeave(&EnterLeaveSource
);
266 // Clip the blt to the clip rectangle
267 EngIntersectRect(&rclTmp
, &OutputRect
, &ClipRegion
->rclBounds
);
269 ptlTmp
.x
= InputPoint
.x
+ rclTmp
.left
- OutputRect
.left
;
270 ptlTmp
.y
= InputPoint
.y
+ rclTmp
.top
- OutputRect
.top
;
272 IntEngLeave(&EnterLeaveDest
);
273 IntEngLeave(&EnterLeaveSource
);
279 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, ENUM_RECT_LIMIT
);
282 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
286 RECTL
* prclEnd
= &RectEnum
.arcl
[RectEnum
.c
];
287 RECTL
* prcl
= &RectEnum
.arcl
[0];
290 EngIntersectRect(prcl
, prcl
, &OutputRect
);
292 ptlTmp
.x
= InputPoint
.x
+ prcl
->left
- OutputRect
.left
;
293 ptlTmp
.y
= InputPoint
.y
+ prcl
->top
- OutputRect
.top
;
297 } while (prcl
< prclEnd
);
302 IntEngLeave(&EnterLeaveDest
);
303 IntEngLeave(&EnterLeaveSource
);
308 IntEngLeave(&EnterLeaveDest
);
309 IntEngLeave(&EnterLeaveSource
);
315 IntEngBitBlt(SURFOBJ
*DestObj
,
319 XLATEOBJ
*ColorTranslation
,
331 if (NULL
!= SourceObj
)
333 SourceGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(SourceObj
);
334 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, SourcePoint
->x
, SourcePoint
->y
,
335 (SourcePoint
->x
+ abs(DestRect
->right
- DestRect
->left
)),
336 (SourcePoint
->y
+ abs(DestRect
->bottom
- DestRect
->top
)));
341 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
342 MouseSafetyOnDrawStart(DestObj
, DestGDI
, DestRect
->left
, DestRect
->top
,
343 DestRect
->right
, DestRect
->bottom
);
345 /* Call the driver's DrvBitBlt if available */
346 if (NULL
!= DestGDI
->BitBlt
) {
347 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
348 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, rop4
);
352 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
353 DestRect
, SourcePoint
, MaskOrigin
, Brush
, BrushOrigin
, rop4
);
356 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
357 if (NULL
!= SourceObj
)
359 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);