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.25 2003/08/04 19:57:05 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
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 typedef BOOLEAN
STDCALL (*PBLTRECTFUNC
)(PSURFOBJ OutputObj
,
54 PXLATEOBJ ColorTranslation
,
62 BOOL STDCALL
EngIntersectRect(PRECTL prcDst
, PRECTL prcSrc1
, PRECTL prcSrc2
)
64 static const RECTL rclEmpty
= { 0, 0, 0, 0 };
66 prcDst
->left
= max(prcSrc1
->left
, prcSrc2
->left
);
67 prcDst
->right
= min(prcSrc1
->right
, prcSrc2
->right
);
69 if (prcDst
->left
< prcDst
->right
)
71 prcDst
->top
= max(prcSrc1
->top
, prcSrc2
->top
);
72 prcDst
->bottom
= min(prcSrc1
->bottom
, prcSrc2
->bottom
);
74 if (prcDst
->top
< prcDst
->bottom
)
85 static BOOLEAN STDCALL
86 BltMask(PSURFOBJ Dest
,
91 PXLATEOBJ ColorTranslation
,
99 LONG i
, j
, dx
, dy
, c8
;
101 static BYTE maskbit
[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
103 dx
= DestRect
->right
- DestRect
->left
;
104 dy
= DestRect
->bottom
- DestRect
->top
;
108 tMask
= Mask
->pvBits
;
109 for (j
= 0; j
< dy
; j
++)
113 for (i
= 0; i
< dx
; i
++)
115 if (0 != (*lMask
& maskbit
[c8
]))
117 DestGDI
->DIB_PutPixel(Dest
, DestRect
->left
+ i
, DestRect
->top
+ j
, Brush
->iSolidColor
);
126 tMask
+= Mask
->lDelta
;
136 static BOOLEAN STDCALL
137 BltPatCopy(PSURFOBJ Dest
,
142 PXLATEOBJ ColorTranslation
,
150 // These functions are assigned if we're working with a DIB
151 // The assigned functions depend on the bitsPerPixel of the DIB
155 LineWidth
= DestRect
->right
- DestRect
->left
;
156 for (y
= DestRect
->top
; y
< DestRect
->bottom
; y
++)
158 DestGDI
->DIB_HLine(Dest
, DestRect
->left
, DestRect
->right
, y
, Brush
->iSolidColor
);
164 static BOOLEAN STDCALL
165 CallDibBitBlt(PSURFOBJ OutputObj
,
170 PXLATEOBJ ColorTranslation
,
178 return OutputGDI
->DIB_BitBlt(OutputObj
, InputObj
, OutputGDI
, InputGDI
, OutputRect
, InputPoint
, Brush
, BrushOrigin
, ColorTranslation
, Rop4
);
187 EngBitBlt(SURFOBJ
*DestObj
,
191 XLATEOBJ
*ColorTranslation
,
203 PSURFGDI OutputGDI
, InputGDI
;
208 INTENG_ENTER_LEAVE EnterLeaveSource
;
209 INTENG_ENTER_LEAVE EnterLeaveDest
;
212 PBLTRECTFUNC BltRectFunc
;
217 if (NULL
!= SourcePoint
)
219 InputRect
.left
= SourcePoint
->x
;
220 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
221 InputRect
.top
= SourcePoint
->y
;
222 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
227 InputRect
.right
= DestRect
->right
- DestRect
->left
;
229 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
232 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
237 if (NULL
!= SourcePoint
)
239 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
240 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
248 if (NULL
!= InputObj
)
250 InputGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(InputObj
);
257 OutputRect
= *DestRect
;
258 if (NULL
!= ClipRegion
)
260 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
262 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
263 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
264 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
266 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
268 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
269 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
271 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
273 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
274 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
275 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
277 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
279 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
280 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
284 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
286 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
288 IntEngLeave(&EnterLeaveSource
);
292 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
294 IntEngLeave(&EnterLeaveSource
);
298 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
299 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
300 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
301 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
303 if (NULL
!= OutputObj
)
305 OutputGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(OutputObj
);
308 // Determine clipping type
309 if (ClipRegion
== (CLIPOBJ
*) NULL
)
311 clippingType
= DC_TRIVIAL
;
313 clippingType
= ClipRegion
->iDComplexity
;
318 BltRectFunc
= BltMask
;
320 else if (PATCOPY
== Rop4
)
322 BltRectFunc
= BltPatCopy
;
326 BltRectFunc
= CallDibBitBlt
;
333 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
334 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
337 // Clip the blt to the clip rectangle
338 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
339 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
340 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
341 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
342 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
343 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
344 &CombinedRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
348 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, ENUM_RECT_LIMIT
);
351 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
353 for (i
= 0; i
< RectEnum
.c
; i
++)
355 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
356 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
357 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
358 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
359 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
360 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
361 &CombinedRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
) &&
370 IntEngLeave(&EnterLeaveDest
);
371 IntEngLeave(&EnterLeaveSource
);
377 IntEngBitBlt(SURFOBJ
*DestObj
,
381 XLATEOBJ
*ColorTranslation
,
395 if (NULL
!= SourcePoint
)
397 InputPoint
= *SourcePoint
;
400 /* Clip against the bounds of the clipping region so we won't try to write
401 * outside the surface */
402 if (NULL
!= ClipRegion
)
404 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
408 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
409 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
413 OutputRect
= *DestRect
;
416 if (NULL
!= SourceObj
)
418 SourceGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(SourceObj
);
419 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
420 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
421 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
426 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
427 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
428 OutputRect
.right
, OutputRect
.bottom
);
430 /* Call the driver's DrvBitBlt if available */
431 if (NULL
!= DestGDI
->BitBlt
)
433 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
434 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
440 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
441 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
445 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
446 if (NULL
!= SourceObj
)
448 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);