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.22 2003/07/09 07:00:00 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/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
, ColorTranslation
);
184 EngBitBlt(SURFOBJ
*DestObj
,
188 XLATEOBJ
*ColorTranslation
,
200 PSURFGDI OutputGDI
, InputGDI
;
205 INTENG_ENTER_LEAVE EnterLeaveSource
;
206 INTENG_ENTER_LEAVE EnterLeaveDest
;
209 PBLTRECTFUNC BltRectFunc
;
214 if (NULL
!= SourcePoint
)
216 InputRect
.left
= SourcePoint
->x
;
217 InputRect
.right
= SourcePoint
->x
+ (DestRect
->right
- DestRect
->left
);
218 InputRect
.top
= SourcePoint
->y
;
219 InputRect
.bottom
= SourcePoint
->y
+ (DestRect
->bottom
- DestRect
->top
);
224 InputRect
.right
= DestRect
->right
- DestRect
->left
;
226 InputRect
.bottom
= DestRect
->bottom
- DestRect
->top
;
229 if (! IntEngEnter(&EnterLeaveSource
, SourceObj
, &InputRect
, TRUE
, &Translate
, &InputObj
))
234 if (NULL
!= SourcePoint
)
236 InputPoint
.x
= SourcePoint
->x
+ Translate
.x
;
237 InputPoint
.y
= SourcePoint
->y
+ Translate
.y
;
245 if (NULL
!= InputObj
)
247 InputGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(InputObj
);
250 OutputRect
= *DestRect
;
251 if (NULL
!= ClipRegion
)
253 if (OutputRect
.left
< ClipRegion
->rclBounds
.left
)
255 InputRect
.left
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
256 InputPoint
.x
+= ClipRegion
->rclBounds
.left
- OutputRect
.left
;
257 OutputRect
.left
= ClipRegion
->rclBounds
.left
;
259 if (ClipRegion
->rclBounds
.right
< OutputRect
.right
)
261 InputRect
.right
-= OutputRect
.right
- ClipRegion
->rclBounds
.right
;
262 OutputRect
.right
= ClipRegion
->rclBounds
.right
;
264 if (OutputRect
.top
< ClipRegion
->rclBounds
.top
)
266 InputRect
.top
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
267 InputPoint
.y
+= ClipRegion
->rclBounds
.top
- OutputRect
.top
;
268 OutputRect
.top
= ClipRegion
->rclBounds
.top
;
270 if (ClipRegion
->rclBounds
.bottom
< OutputRect
.bottom
)
272 InputRect
.bottom
-= OutputRect
.bottom
- ClipRegion
->rclBounds
.bottom
;
273 OutputRect
.bottom
= ClipRegion
->rclBounds
.bottom
;
277 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
279 if (OutputRect
.right
<= OutputRect
.left
|| OutputRect
.bottom
<= OutputRect
.top
)
281 IntEngLeave(&EnterLeaveSource
);
285 if (! IntEngEnter(&EnterLeaveDest
, DestObj
, &OutputRect
, FALSE
, &Translate
, &OutputObj
))
287 IntEngLeave(&EnterLeaveSource
);
291 OutputRect
.left
= DestRect
->left
+ Translate
.x
;
292 OutputRect
.right
= DestRect
->right
+ Translate
.x
;
293 OutputRect
.top
= DestRect
->top
+ Translate
.y
;
294 OutputRect
.bottom
= DestRect
->bottom
+ Translate
.y
;
296 if (NULL
!= OutputObj
)
298 OutputGDI
= (PSURFGDI
)AccessInternalObjectFromUserObject(OutputObj
);
301 /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
302 * paint a brush pattern on the destination. */
303 if (NULL
== InputObj
&& 0xaacc != Rop4
&& PATCOPY
!= Rop4
)
305 DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
309 // Determine clipping type
310 if (ClipRegion
== (CLIPOBJ
*) NULL
)
312 clippingType
= DC_TRIVIAL
;
314 clippingType
= ClipRegion
->iDComplexity
;
319 BltRectFunc
= BltMask
;
321 else if (PATCOPY
== Rop4
)
323 BltRectFunc
= BltPatCopy
;
327 BltRectFunc
= CallDibBitBlt
;
334 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
335 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
338 // Clip the blt to the clip rectangle
339 ClipRect
.left
= ClipRegion
->rclBounds
.left
+ Translate
.x
;
340 ClipRect
.right
= ClipRegion
->rclBounds
.right
+ Translate
.x
;
341 ClipRect
.top
= ClipRegion
->rclBounds
.top
+ Translate
.y
;
342 ClipRect
.bottom
= ClipRegion
->rclBounds
.bottom
+ Translate
.y
;
343 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
344 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
345 &CombinedRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
);
349 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, ENUM_RECT_LIMIT
);
352 EnumMore
= CLIPOBJ_bEnum(ClipRegion
,(ULONG
) sizeof(RectEnum
), (PVOID
) &RectEnum
);
354 for (i
= 0; i
< RectEnum
.c
; i
++)
356 ClipRect
.left
= RectEnum
.arcl
[i
].left
+ Translate
.x
;
357 ClipRect
.right
= RectEnum
.arcl
[i
].right
+ Translate
.x
;
358 ClipRect
.top
= RectEnum
.arcl
[i
].top
+ Translate
.y
;
359 ClipRect
.bottom
= RectEnum
.arcl
[i
].bottom
+ Translate
.y
;
360 EngIntersectRect(&CombinedRect
, &OutputRect
, &ClipRect
);
361 Ret
= (*BltRectFunc
)(OutputObj
, OutputGDI
, InputObj
, InputGDI
, Mask
, ColorTranslation
,
362 &CombinedRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
, Rop4
) &&
371 IntEngLeave(&EnterLeaveDest
);
372 IntEngLeave(&EnterLeaveSource
);
378 IntEngBitBlt(SURFOBJ
*DestObj
,
382 XLATEOBJ
*ColorTranslation
,
396 if (NULL
!= SourcePoint
)
398 InputPoint
= *SourcePoint
;
401 /* Clip against the bounds of the clipping region so we won't try to write
402 * outside the surface */
403 if (NULL
!= ClipRegion
)
405 if (! EngIntersectRect(&OutputRect
, DestRect
, &ClipRegion
->rclBounds
))
409 InputPoint
.x
+= OutputRect
.left
- DestRect
->left
;
410 InputPoint
.y
+= OutputRect
.top
- DestRect
->top
;
414 OutputRect
= *DestRect
;
417 if (NULL
!= SourceObj
)
419 SourceGDI
= (PSURFGDI
) AccessInternalObjectFromUserObject(SourceObj
);
420 MouseSafetyOnDrawStart(SourceObj
, SourceGDI
, InputPoint
.x
, InputPoint
.y
,
421 (InputPoint
.x
+ abs(DestRect
->right
- DestRect
->left
)),
422 (InputPoint
.y
+ abs(DestRect
->bottom
- DestRect
->top
)));
427 DestGDI
= (SURFGDI
*)AccessInternalObjectFromUserObject(DestObj
);
428 MouseSafetyOnDrawStart(DestObj
, DestGDI
, OutputRect
.left
, OutputRect
.top
,
429 OutputRect
.right
, OutputRect
.bottom
);
431 /* Call the driver's DrvBitBlt if available */
432 if (NULL
!= DestGDI
->BitBlt
)
434 ret
= DestGDI
->BitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
435 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
441 ret
= EngBitBlt(DestObj
, SourceObj
, Mask
, ClipRegion
, ColorTranslation
,
442 &OutputRect
, &InputPoint
, MaskOrigin
, Brush
, BrushOrigin
,
446 MouseSafetyOnDrawEnd(DestObj
, DestGDI
);
447 if (NULL
!= SourceObj
)
449 MouseSafetyOnDrawEnd(SourceObj
, SourceGDI
);