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.
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 + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
109 for (j = 0; j < dy; j++)
112 c8 = SourcePoint->x & 0x07;
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;
219 if (NULL != SourcePoint)
221 InputRect.left = SourcePoint->x;
222 InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
223 InputRect.top = SourcePoint->y;
224 InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
229 InputRect.right = DestRect->right - DestRect->left;
231 InputRect.bottom = DestRect->bottom - DestRect->top;
234 if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj))
239 if (NULL != SourcePoint)
241 InputPoint.x = SourcePoint->x + Translate.x;
242 InputPoint.y = SourcePoint->y + Translate.y;
250 if (NULL != InputObj)
252 InputGDI = (PSURFGDI) AccessInternalObjectFromUserObject(InputObj);
259 OutputRect = *DestRect;
260 if (NULL != ClipRegion)
262 if (OutputRect.left < ClipRegion->rclBounds.left)
264 InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
265 InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
266 OutputRect.left = ClipRegion->rclBounds.left;
268 if (ClipRegion->rclBounds.right < OutputRect.right)
270 InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right;
271 OutputRect.right = ClipRegion->rclBounds.right;
273 if (OutputRect.top < ClipRegion->rclBounds.top)
275 InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
276 InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
277 OutputRect.top = ClipRegion->rclBounds.top;
279 if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
281 InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom;
282 OutputRect.bottom = ClipRegion->rclBounds.bottom;
286 /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
288 if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
290 IntEngLeave(&EnterLeaveSource);
294 if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
296 IntEngLeave(&EnterLeaveSource);
300 OutputRect.left = DestRect->left + Translate.x;
301 OutputRect.right = DestRect->right + Translate.x;
302 OutputRect.top = DestRect->top + Translate.y;
303 OutputRect.bottom = DestRect->bottom + Translate.y;
305 if (NULL != OutputObj)
307 OutputGDI = (PSURFGDI)AccessInternalObjectFromUserObject(OutputObj);
310 // Determine clipping type
311 if (ClipRegion == (CLIPOBJ *) NULL)
313 clippingType = DC_TRIVIAL;
315 clippingType = ClipRegion->iDComplexity;
320 BltRectFunc = BltMask;
322 else if (PATCOPY == Rop4)
324 BltRectFunc = BltPatCopy;
328 BltRectFunc = CallDibBitBlt;
335 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
336 &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4);
339 // Clip the blt to the clip rectangle
340 ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
341 ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
342 ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
343 ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
344 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
345 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
346 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
347 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
348 &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
352 if (OutputObj == InputObj)
354 if (OutputRect.top < InputPoint.y)
356 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
360 Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
367 CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT);
370 EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
372 for (i = 0; i < RectEnum.c; i++)
374 ClipRect.left = RectEnum.arcl[i].left + Translate.x;
375 ClipRect.right = RectEnum.arcl[i].right + Translate.x;
376 ClipRect.top = RectEnum.arcl[i].top + Translate.y;
377 ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
378 EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
379 Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
380 Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
381 Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
382 &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) &&
391 IntEngLeave(&EnterLeaveDest);
392 IntEngLeave(&EnterLeaveSource);
398 IntEngBitBlt(SURFOBJ *DestObj,
402 XLATEOBJ *ColorTranslation,
416 if (NULL != SourcePoint)
418 InputPoint = *SourcePoint;
421 /* Clip against the bounds of the clipping region so we won't try to write
422 * outside the surface */
423 if (NULL != ClipRegion)
425 if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
429 InputPoint.x += OutputRect.left - DestRect->left;
430 InputPoint.y += OutputRect.top - DestRect->top;
434 OutputRect = *DestRect;
437 if (NULL != SourceObj)
439 SourceGDI = (PSURFGDI) AccessInternalObjectFromUserObject(SourceObj);
440 MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputPoint.x, InputPoint.y,
441 (InputPoint.x + abs(DestRect->right - DestRect->left)),
442 (InputPoint.y + abs(DestRect->bottom - DestRect->top)));
447 DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
448 MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
449 OutputRect.right, OutputRect.bottom);
451 /* Call the driver's DrvBitBlt if available */
452 if (NULL != DestGDI->BitBlt)
454 ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
455 &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
461 ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
462 &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
466 MouseSafetyOnDrawEnd(DestObj, DestGDI);
467 if (NULL != SourceObj)
469 MouseSafetyOnDrawEnd(SourceObj, SourceGDI);