/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: GDI BitBlt Functions
#include <ddk/winddi.h>
#include <ddk/ntddk.h>
+#include <ddk/ntddmou.h>
#include <ntos/minmax.h>
#include "brush.h"
#include "clip.h"
#include <include/copybits.h>
#include <include/inteng.h>
-#define NDEBUG
+//#define NDEBUG
#include <win32k/debug1.h>
-BOOL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
+typedef BOOLEAN STDCALL (*PBLTRECTFUNC)(PSURFOBJ OutputObj,
+ PSURFGDI OutputGDI,
+ PSURFOBJ InputObj,
+ PSURFGDI InputGDI,
+ PSURFOBJ Mask,
+ PXLATEOBJ ColorTranslation,
+ PRECTL OutputRect,
+ PPOINTL InputPoint,
+ PPOINTL MaskOrigin,
+ PBRUSHOBJ Brush,
+ PPOINTL BrushOrigin,
+ ROP4 Rop4);
+
+BOOL STDCALL EngIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
{
static const RECTL rclEmpty = { 0, 0, 0, 0 };
prcDst->right = min(prcSrc1->right, prcSrc2->right);
if (prcDst->left < prcDst->right)
- {
- prcDst->top = max(prcSrc1->top, prcSrc2->top);
- prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
+ {
+ prcDst->top = max(prcSrc1->top, prcSrc2->top);
+ prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
- if (prcDst->top < prcDst->bottom) return(TRUE);
- }
+ if (prcDst->top < prcDst->bottom)
+ {
+ return TRUE;
+ }
+ }
*prcDst = rclEmpty;
- return(FALSE);
+ return FALSE;
}
-static BOOL STDCALL
-BltMask(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
- RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
- POINTL* BrushPoint)
+static BOOLEAN STDCALL
+BltMask(PSURFOBJ Dest,
+ PSURFGDI DestGDI,
+ PSURFOBJ Source,
+ PSURFGDI SourceGDI,
+ PSURFOBJ Mask,
+ PXLATEOBJ ColorTranslation,
+ PRECTL DestRect,
+ PPOINTL SourcePoint,
+ PPOINTL MaskPoint,
+ PBRUSHOBJ Brush,
+ PPOINTL BrushPoint,
+ ROP4 Rop4)
{
LONG i, j, dx, dy, c8;
BYTE *tMask, *lMask;
if (Mask != NULL)
{
- tMask = Mask->pvBits;
+ tMask = Mask->pvBits + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
for (j = 0; j < dy; j++)
{
lMask = tMask;
- c8 = 0;
+ c8 = SourcePoint->x & 0x07;
for (i = 0; i < dx; i++)
{
if (0 != (*lMask & maskbit[c8]))
}
}
-static BOOL STDCALL
-BltPatCopy(SURFOBJ *Dest, PSURFGDI DestGDI, SURFOBJ *Mask,
- RECTL *DestRect, POINTL *MaskPoint, BRUSHOBJ* Brush,
- POINTL* BrushPoint)
+static BOOLEAN STDCALL
+BltPatCopy(PSURFOBJ Dest,
+ PSURFGDI DestGDI,
+ PSURFOBJ Source,
+ PSURFGDI SourceGDI,
+ PSURFOBJ Mask,
+ PXLATEOBJ ColorTranslation,
+ PRECTL DestRect,
+ PPOINTL SourcePoint,
+ PPOINTL MaskPoint,
+ PBRUSHOBJ Brush,
+ PPOINTL BrushPoint,
+ ROP4 Rop4)
{
// These functions are assigned if we're working with a DIB
// The assigned functions depend on the bitsPerPixel of the DIB
return TRUE;
}
+static BOOLEAN STDCALL
+CallDibBitBlt(PSURFOBJ OutputObj,
+ PSURFGDI OutputGDI,
+ PSURFOBJ InputObj,
+ PSURFGDI InputGDI,
+ PSURFOBJ Mask,
+ PXLATEOBJ ColorTranslation,
+ PRECTL OutputRect,
+ PPOINTL InputPoint,
+ PPOINTL MaskOrigin,
+ PBRUSHOBJ Brush,
+ PPOINTL BrushOrigin,
+ ROP4 Rop4)
+{
+ return OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputPoint, Brush, BrushOrigin, ColorTranslation, Rop4);
+}
+
INT abs(INT nm);
+/*
+ * @implemented
+ */
BOOL STDCALL
EngBitBlt(SURFOBJ *DestObj,
SURFOBJ *SourceObj,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
- ROP4 rop4)
+ ROP4 Rop4)
{
- BOOLEAN ret;
BYTE clippingType;
- RECTL rclTmp;
- POINTL ptlTmp;
+ RECTL CombinedRect;
RECT_ENUM RectEnum;
BOOL EnumMore;
PSURFGDI OutputGDI, InputGDI;
INTENG_ENTER_LEAVE EnterLeaveDest;
PSURFOBJ InputObj;
PSURFOBJ OutputObj;
-
- /* Check for degenerate case: if height or width of DestRect is 0 pixels there's
- nothing to do */
- if (DestRect->right == DestRect->left || DestRect->bottom == DestRect->top)
- {
- return TRUE;
- }
+ PBLTRECTFUNC BltRectFunc;
+ BOOLEAN Ret;
+ RECTL ClipRect;
+ unsigned i;
+ POINTL Pt;
+ ULONG Direction;
if (NULL != SourcePoint)
{
{
InputGDI = (PSURFGDI) AccessInternalObjectFromUserObject(InputObj);
}
+ else
+ {
+ InputGDI = NULL;
+ }
OutputRect = *DestRect;
+ if (NULL != ClipRegion)
+ {
+ if (OutputRect.left < ClipRegion->rclBounds.left)
+ {
+ InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
+ InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
+ OutputRect.left = ClipRegion->rclBounds.left;
+ }
+ if (ClipRegion->rclBounds.right < OutputRect.right)
+ {
+ InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right;
+ OutputRect.right = ClipRegion->rclBounds.right;
+ }
+ if (OutputRect.top < ClipRegion->rclBounds.top)
+ {
+ InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
+ InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
+ OutputRect.top = ClipRegion->rclBounds.top;
+ }
+ if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
+ {
+ InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom;
+ OutputRect.bottom = ClipRegion->rclBounds.bottom;
+ }
+ }
+
+ /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
+ nothing to do */
+ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
+ {
+ IntEngLeave(&EnterLeaveSource);
+ return TRUE;
+ }
if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
{
OutputRect.top = DestRect->top + Translate.y;
OutputRect.bottom = DestRect->bottom + Translate.y;
-
if (NULL != OutputObj)
{
OutputGDI = (PSURFGDI)AccessInternalObjectFromUserObject(OutputObj);
}
- /* The code currently assumes there will be a source bitmap. This is not true when, for example, using this function to
- * paint a brush pattern on the destination. */
- if (NULL == InputObj && 0xaacc != rop4 && PATCOPY != rop4)
- {
- DbgPrint("EngBitBlt: A source is currently required, even though not all operations require one (FIXME)\n");
- return FALSE;
- }
-
// Determine clipping type
if (ClipRegion == (CLIPOBJ *) NULL)
{
clippingType = ClipRegion->iDComplexity;
}
- if (0xaacc == rop4)
- {
- ret = BltMask(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
- IntEngLeave(&EnterLeaveDest);
- IntEngLeave(&EnterLeaveSource);
- return ret;
- } else if (PATCOPY == rop4) {
- ret = BltPatCopy(OutputObj, OutputGDI, Mask, &OutputRect, MaskOrigin, Brush, BrushOrigin);
- IntEngLeave(&EnterLeaveDest);
- IntEngLeave(&EnterLeaveSource);
- return ret;
- }
+ if (0xaacc == Rop4)
+ {
+ BltRectFunc = BltMask;
+ }
+ else if (PATCOPY == Rop4)
+ {
+ BltRectFunc = BltPatCopy;
+ }
+ else
+ {
+ BltRectFunc = CallDibBitBlt;
+ }
- // We don't handle color translation just yet [we dont have to.. REMOVE REMOVE REMOVE]
switch(clippingType)
{
case DC_TRIVIAL:
- OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, &OutputRect, &InputPoint, ColorTranslation);
-
- IntEngLeave(&EnterLeaveDest);
- IntEngLeave(&EnterLeaveSource);
-
- return(TRUE);
-
+ Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
+ &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4);
+ break;
case DC_RECT:
-
// Clip the blt to the clip rectangle
- EngIntersectRect(&rclTmp, &OutputRect, &ClipRegion->rclBounds);
-
- ptlTmp.x = InputPoint.x + rclTmp.left - OutputRect.left;
- ptlTmp.y = InputPoint.y + rclTmp.top - OutputRect.top;
-
- IntEngLeave(&EnterLeaveDest);
- IntEngLeave(&EnterLeaveSource);
-
- return(TRUE);
-
+ ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
+ ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
+ ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
+ ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
+ EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
+ Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+ Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+ Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
+ &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
+ break;
case DC_COMPLEX:
+ Ret = TRUE;
+ if (OutputObj == InputObj)
+ {
+ if (OutputRect.top < InputPoint.y)
+ {
+ Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
+ }
+ else
+ {
+ Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
+ }
+ }
+ else
+ {
+ Direction = CD_ANY;
+ }
+ CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, ENUM_RECT_LIMIT);
+ do
+ {
+ EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
- CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
-
- do {
- EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
-
- if (RectEnum.c > 0)
- {
- RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
- RECTL* prcl = &RectEnum.arcl[0];
-
- do {
- EngIntersectRect(prcl, prcl, &OutputRect);
-
- ptlTmp.x = InputPoint.x + prcl->left - OutputRect.left;
- ptlTmp.y = InputPoint.y + prcl->top - OutputRect.top;
-
- prcl++;
-
- } while (prcl < prclEnd);
- }
-
- } while(EnumMore);
-
- IntEngLeave(&EnterLeaveDest);
- IntEngLeave(&EnterLeaveSource);
-
- return(TRUE);
+ for (i = 0; i < RectEnum.c; i++)
+ {
+ ClipRect.left = RectEnum.arcl[i].left + Translate.x;
+ ClipRect.right = RectEnum.arcl[i].right + Translate.x;
+ ClipRect.top = RectEnum.arcl[i].top + Translate.y;
+ ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
+ EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect);
+ Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
+ Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
+ Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
+ &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) &&
+ Ret;
+ }
+ }
+ while(EnumMore);
+ break;
}
+
IntEngLeave(&EnterLeaveDest);
IntEngLeave(&EnterLeaveSource);
- return(FALSE);
+ return Ret;
}
BOOL STDCALL
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
- ROP4 rop4)
+ ROP4 Rop4)
{
BOOLEAN ret;
SURFGDI *DestGDI;
SURFGDI *SourceGDI;
+ RECTL OutputRect;
+ POINTL InputPoint;
+
+ if (NULL != SourcePoint)
+ {
+ InputPoint = *SourcePoint;
+ }
+
+ /* Clip against the bounds of the clipping region so we won't try to write
+ * outside the surface */
+ if (NULL != ClipRegion)
+ {
+ if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
+ {
+ return TRUE;
+ }
+ InputPoint.x += OutputRect.left - DestRect->left;
+ InputPoint.y += OutputRect.top - DestRect->top;
+ }
+ else
+ {
+ OutputRect = *DestRect;
+ }
if (NULL != SourceObj)
{
SourceGDI = (PSURFGDI) AccessInternalObjectFromUserObject(SourceObj);
- MouseSafetyOnDrawStart(SourceObj, SourceGDI, SourcePoint->x, SourcePoint->y,
- (SourcePoint->x + abs(DestRect->right - DestRect->left)),
- (SourcePoint->y + abs(DestRect->bottom - DestRect->top)));
+ MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputPoint.x, InputPoint.y,
+ (InputPoint.x + abs(DestRect->right - DestRect->left)),
+ (InputPoint.y + abs(DestRect->bottom - DestRect->top)));
}
/* No success yet */
ret = FALSE;
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
- MouseSafetyOnDrawStart(DestObj, DestGDI, DestRect->left, DestRect->top,
- DestRect->right, DestRect->bottom);
+ MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
+ OutputRect.right, OutputRect.bottom);
/* Call the driver's DrvBitBlt if available */
- if (NULL != DestGDI->BitBlt) {
- ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
- DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
- }
+ if (NULL != DestGDI->BitBlt)
+ {
+ ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
+ &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
+ Rop4);
+ }
- if (! ret) {
- ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
- DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, rop4);
- }
+ if (! ret)
+ {
+ ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
+ &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
+ Rop4);
+ }
MouseSafetyOnDrawEnd(DestObj, DestGDI);
if (NULL != SourceObj)
return ret;
}
+/* EOF */