2000-03-17 21:44:02 +00:00
|
|
|
/*
|
2003-05-18 17:16:18 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
2004-03-22 14:58:56 +00:00
|
|
|
/* $Id: bitblt.c,v 1.43 2004/03/22 14:58:56 weiden Exp $
|
2003-05-18 17:16:18 +00:00
|
|
|
*
|
2000-03-17 21:44:02 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: GDI BitBlt Functions
|
|
|
|
* FILE: subsys/win32k/eng/bitblt.c
|
|
|
|
* PROGRAMER: Jason Filby
|
|
|
|
* REVISION HISTORY:
|
|
|
|
* 2/10/1999: Created
|
|
|
|
*/
|
2002-09-08 10:23:54 +00:00
|
|
|
|
2000-03-17 21:44:02 +00:00
|
|
|
#include <ddk/winddi.h>
|
|
|
|
#include <ddk/ntddk.h>
|
2003-05-18 17:16:18 +00:00
|
|
|
#include <ddk/ntddmou.h>
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <ntos/minmax.h>
|
2000-03-17 21:44:02 +00:00
|
|
|
#include "brush.h"
|
2002-08-18 13:55:11 +00:00
|
|
|
#include "clip.h"
|
2000-03-17 21:44:02 +00:00
|
|
|
#include "objects.h"
|
2003-02-15 19:16:34 +00:00
|
|
|
#include "../dib/dib.h"
|
2003-02-25 23:08:54 +00:00
|
|
|
#include "misc.h"
|
2002-01-13 22:52:08 +00:00
|
|
|
#include <include/mouse.h>
|
|
|
|
#include <include/object.h>
|
|
|
|
#include <include/dib.h>
|
|
|
|
#include <include/surface.h>
|
2004-02-24 13:27:03 +00:00
|
|
|
#include <include/eng.h>
|
2003-02-25 23:08:54 +00:00
|
|
|
#include <include/inteng.h>
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2004-01-17 01:04:45 +00:00
|
|
|
#define NDEBUG
|
2003-02-15 19:16:34 +00:00
|
|
|
#include <win32k/debug1.h>
|
|
|
|
|
2004-01-17 01:04:45 +00:00
|
|
|
#define ROP_NOOP 0x00AA0029
|
|
|
|
|
2003-10-29 08:38:55 +00:00
|
|
|
typedef BOOLEAN STDCALL (*PBLTRECTFUNC)(SURFOBJ* OutputObj,
|
|
|
|
SURFGDI* OutputGDI,
|
|
|
|
SURFOBJ* InputObj,
|
|
|
|
SURFGDI* InputGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* OutputRect,
|
|
|
|
POINTL* InputPoint,
|
|
|
|
POINTL* MaskOrigin,
|
|
|
|
BRUSHOBJ* Brush,
|
|
|
|
POINTL* BrushOrigin,
|
2003-06-28 08:39:18 +00:00
|
|
|
ROP4 Rop4);
|
2003-12-08 18:07:56 +00:00
|
|
|
typedef BOOLEAN STDCALL (*PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
|
|
|
|
SURFGDI* OutputGDI,
|
|
|
|
SURFOBJ* InputObj,
|
|
|
|
SURFGDI* InputGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* OutputRect,
|
|
|
|
RECTL* InputRect,
|
|
|
|
POINTL* MaskOrigin,
|
|
|
|
POINTL* BrushOrigin,
|
|
|
|
ULONG Mode);
|
2003-06-28 08:39:18 +00:00
|
|
|
|
2003-10-29 08:38:55 +00:00
|
|
|
BOOL STDCALL EngIntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* prcSrc2)
|
2000-03-17 21:44:02 +00:00
|
|
|
{
|
2001-03-31 15:35:08 +00:00
|
|
|
static const RECTL rclEmpty = { 0, 0, 0, 0 };
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
prcDst->left = max(prcSrc1->left, prcSrc2->left);
|
|
|
|
prcDst->right = min(prcSrc1->right, prcSrc2->right);
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
if (prcDst->left < prcDst->right)
|
2003-07-09 07:00:00 +00:00
|
|
|
{
|
|
|
|
prcDst->top = max(prcSrc1->top, prcSrc2->top);
|
|
|
|
prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2003-07-09 07:00:00 +00:00
|
|
|
if (prcDst->top < prcDst->bottom)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
*prcDst = rclEmpty;
|
2000-03-17 21:44:02 +00:00
|
|
|
|
2003-07-09 07:00:00 +00:00
|
|
|
return FALSE;
|
2000-03-17 21:44:02 +00:00
|
|
|
}
|
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
static BOOLEAN STDCALL
|
2003-10-29 08:38:55 +00:00
|
|
|
BltMask(SURFOBJ* Dest,
|
|
|
|
SURFGDI* DestGDI,
|
|
|
|
SURFOBJ* Source,
|
|
|
|
SURFGDI* SourceGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* DestRect,
|
|
|
|
POINTL* SourcePoint,
|
|
|
|
POINTL* MaskPoint,
|
|
|
|
BRUSHOBJ* Brush,
|
|
|
|
POINTL* BrushPoint,
|
2003-08-17 17:32:58 +00:00
|
|
|
ROP4 Rop4)
|
2003-02-15 19:16:34 +00:00
|
|
|
{
|
|
|
|
LONG i, j, dx, dy, c8;
|
|
|
|
BYTE *tMask, *lMask;
|
|
|
|
static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
|
2003-12-25 00:28:09 +00:00
|
|
|
|
2003-02-15 19:16:34 +00:00
|
|
|
dx = DestRect->right - DestRect->left;
|
|
|
|
dy = DestRect->bottom - DestRect->top;
|
|
|
|
|
|
|
|
if (Mask != NULL)
|
|
|
|
{
|
2003-09-09 09:39:21 +00:00
|
|
|
tMask = Mask->pvBits + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
|
2003-02-15 19:16:34 +00:00
|
|
|
for (j = 0; j < dy; j++)
|
|
|
|
{
|
|
|
|
lMask = tMask;
|
2003-09-09 09:39:21 +00:00
|
|
|
c8 = SourcePoint->x & 0x07;
|
2003-02-15 19:16:34 +00:00
|
|
|
for (i = 0; i < dx; i++)
|
|
|
|
{
|
|
|
|
if (0 != (*lMask & maskbit[c8]))
|
|
|
|
{
|
2003-03-04 10:09:01 +00:00
|
|
|
DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
|
2003-02-15 19:16:34 +00:00
|
|
|
}
|
|
|
|
c8++;
|
|
|
|
if (8 == c8)
|
|
|
|
{
|
|
|
|
lMask++;
|
|
|
|
c8=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tMask += Mask->lDelta;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
static BOOLEAN STDCALL
|
2003-10-29 08:38:55 +00:00
|
|
|
BltPatCopy(SURFOBJ* Dest,
|
|
|
|
SURFGDI* DestGDI,
|
|
|
|
SURFOBJ* Source,
|
|
|
|
SURFGDI* SourceGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* DestRect,
|
|
|
|
POINTL* SourcePoint,
|
|
|
|
POINTL* MaskPoint,
|
|
|
|
BRUSHOBJ* Brush,
|
|
|
|
POINTL* BrushPoint,
|
2003-08-17 17:32:58 +00:00
|
|
|
ROP4 Rop4)
|
2003-02-15 19:16:34 +00:00
|
|
|
{
|
|
|
|
// These functions are assigned if we're working with a DIB
|
|
|
|
// The assigned functions depend on the bitsPerPixel of the DIB
|
|
|
|
LONG y;
|
|
|
|
ULONG LineWidth;
|
|
|
|
|
|
|
|
LineWidth = DestRect->right - DestRect->left;
|
|
|
|
for (y = DestRect->top; y < DestRect->bottom; y++)
|
|
|
|
{
|
2003-03-04 10:09:01 +00:00
|
|
|
DestGDI->DIB_HLine(Dest, DestRect->left, DestRect->right, y, Brush->iSolidColor);
|
2003-02-15 19:16:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
static BOOLEAN STDCALL
|
2003-10-29 08:38:55 +00:00
|
|
|
CallDibBitBlt(SURFOBJ* OutputObj,
|
|
|
|
SURFGDI* OutputGDI,
|
|
|
|
SURFOBJ* InputObj,
|
|
|
|
SURFGDI* InputGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* OutputRect,
|
|
|
|
POINTL* InputPoint,
|
|
|
|
POINTL* MaskOrigin,
|
|
|
|
BRUSHOBJ* Brush,
|
|
|
|
POINTL* BrushOrigin,
|
2003-06-28 08:39:18 +00:00
|
|
|
ROP4 Rop4)
|
|
|
|
{
|
2003-07-27 18:37:23 +00:00
|
|
|
return OutputGDI->DIB_BitBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputPoint, Brush, BrushOrigin, ColorTranslation, Rop4);
|
2003-06-28 08:39:18 +00:00
|
|
|
}
|
|
|
|
|
2001-06-03 10:47:29 +00:00
|
|
|
INT abs(INT nm);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2003-07-11 15:59:37 +00:00
|
|
|
/*
|
2003-08-04 19:57:05 +00:00
|
|
|
* @implemented
|
2003-07-11 15:59:37 +00:00
|
|
|
*/
|
2002-06-15 21:44:08 +00:00
|
|
|
BOOL STDCALL
|
2003-02-25 23:08:54 +00:00
|
|
|
EngBitBlt(SURFOBJ *DestObj,
|
|
|
|
SURFOBJ *SourceObj,
|
2002-06-15 21:44:08 +00:00
|
|
|
SURFOBJ *Mask,
|
|
|
|
CLIPOBJ *ClipRegion,
|
|
|
|
XLATEOBJ *ColorTranslation,
|
|
|
|
RECTL *DestRect,
|
|
|
|
POINTL *SourcePoint,
|
2003-02-15 19:16:34 +00:00
|
|
|
POINTL *MaskOrigin,
|
2002-09-08 10:23:54 +00:00
|
|
|
BRUSHOBJ *Brush,
|
2002-06-15 21:44:08 +00:00
|
|
|
POINTL *BrushOrigin,
|
2003-06-28 08:39:18 +00:00
|
|
|
ROP4 Rop4)
|
2000-03-17 21:44:02 +00:00
|
|
|
{
|
2003-02-25 23:08:54 +00:00
|
|
|
BYTE clippingType;
|
2003-06-28 08:39:18 +00:00
|
|
|
RECTL CombinedRect;
|
2003-02-25 23:08:54 +00:00
|
|
|
RECT_ENUM RectEnum;
|
|
|
|
BOOL EnumMore;
|
2003-10-29 08:38:55 +00:00
|
|
|
SURFGDI* OutputGDI;
|
|
|
|
SURFGDI* InputGDI;
|
2003-02-25 23:08:54 +00:00
|
|
|
POINTL InputPoint;
|
|
|
|
RECTL InputRect;
|
|
|
|
RECTL OutputRect;
|
|
|
|
POINTL Translate;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveSource;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveDest;
|
2003-10-29 08:38:55 +00:00
|
|
|
SURFOBJ* InputObj;
|
|
|
|
SURFOBJ* OutputObj;
|
2003-06-28 08:39:18 +00:00
|
|
|
PBLTRECTFUNC BltRectFunc;
|
|
|
|
BOOLEAN Ret;
|
|
|
|
RECTL ClipRect;
|
|
|
|
unsigned i;
|
2003-09-09 09:39:21 +00:00
|
|
|
POINTL Pt;
|
|
|
|
ULONG Direction;
|
2004-01-11 19:52:27 +00:00
|
|
|
BOOL UsesSource;
|
|
|
|
BOOL UsesPattern;
|
|
|
|
|
|
|
|
UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
|
|
|
|
UsesPattern = ((Rop4 & 0xF00000) >> 4) != (Rop4 & 0x0F0000);
|
2004-01-17 01:04:45 +00:00
|
|
|
if (ROP_NOOP == Rop4)
|
2004-01-11 19:52:27 +00:00
|
|
|
{
|
|
|
|
/* Copy destination onto itself: nop */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
if (NULL != SourcePoint)
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2003-02-25 23:08:54 +00:00
|
|
|
InputRect.left = SourcePoint->x;
|
|
|
|
InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
|
|
|
|
InputRect.top = SourcePoint->y;
|
|
|
|
InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InputRect.left = 0;
|
|
|
|
InputRect.right = DestRect->right - DestRect->left;
|
|
|
|
InputRect.top = 0;
|
|
|
|
InputRect.bottom = DestRect->bottom - DestRect->top;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2003-02-25 23:08:54 +00:00
|
|
|
if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj))
|
|
|
|
{
|
2002-09-21 10:39:54 +00:00
|
|
|
return FALSE;
|
2003-02-25 23:08:54 +00:00
|
|
|
}
|
2002-09-21 10:39:54 +00:00
|
|
|
|
2003-02-25 23:08:54 +00:00
|
|
|
if (NULL != SourcePoint)
|
|
|
|
{
|
|
|
|
InputPoint.x = SourcePoint->x + Translate.x;
|
|
|
|
InputPoint.y = SourcePoint->y + Translate.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InputPoint.x = 0;
|
|
|
|
InputPoint.y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != InputObj)
|
|
|
|
{
|
2003-10-29 08:38:55 +00:00
|
|
|
InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj);
|
2003-02-25 23:08:54 +00:00
|
|
|
}
|
2003-07-27 18:37:23 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
InputGDI = NULL;
|
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
OutputRect = *DestRect;
|
2003-07-09 07:00:00 +00:00
|
|
|
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;
|
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
|
2001-03-31 15:35:08 +00:00
|
|
|
{
|
2003-02-25 23:08:54 +00:00
|
|
|
IntEngLeave(&EnterLeaveSource);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-06-03 10:47:29 +00:00
|
|
|
|
2003-02-25 23:08:54 +00:00
|
|
|
OutputRect.left = DestRect->left + Translate.x;
|
|
|
|
OutputRect.right = DestRect->right + Translate.x;
|
|
|
|
OutputRect.top = DestRect->top + Translate.y;
|
|
|
|
OutputRect.bottom = DestRect->bottom + Translate.y;
|
2001-06-03 10:47:29 +00:00
|
|
|
|
2003-02-25 23:08:54 +00:00
|
|
|
if (NULL != OutputObj)
|
|
|
|
{
|
2003-10-29 08:38:55 +00:00
|
|
|
OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj);
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
// Determine clipping type
|
|
|
|
if (ClipRegion == (CLIPOBJ *) NULL)
|
|
|
|
{
|
|
|
|
clippingType = DC_TRIVIAL;
|
|
|
|
} else {
|
|
|
|
clippingType = ClipRegion->iDComplexity;
|
|
|
|
}
|
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
if (0xaacc == Rop4)
|
|
|
|
{
|
|
|
|
BltRectFunc = BltMask;
|
|
|
|
}
|
|
|
|
else if (PATCOPY == Rop4)
|
|
|
|
{
|
|
|
|
BltRectFunc = BltPatCopy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BltRectFunc = CallDibBitBlt;
|
|
|
|
}
|
2003-02-15 19:16:34 +00:00
|
|
|
|
|
|
|
|
2001-03-31 15:35:08 +00:00
|
|
|
switch(clippingType)
|
|
|
|
{
|
|
|
|
case DC_TRIVIAL:
|
2003-06-28 08:39:18 +00:00
|
|
|
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
|
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, Rop4);
|
|
|
|
break;
|
2001-03-31 15:35:08 +00:00
|
|
|
case DC_RECT:
|
|
|
|
// Clip the blt to the clip rectangle
|
2003-06-28 08:39:18 +00:00
|
|
|
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);
|
2003-09-09 09:39:21 +00:00
|
|
|
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
|
|
|
|
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
|
2003-06-28 08:39:18 +00:00
|
|
|
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
|
2003-09-09 09:39:21 +00:00
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
|
2003-06-28 08:39:18 +00:00
|
|
|
break;
|
2001-03-31 15:35:08 +00:00
|
|
|
case DC_COMPLEX:
|
2003-06-28 08:39:18 +00:00
|
|
|
Ret = TRUE;
|
2003-09-09 09:39:21 +00:00
|
|
|
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;
|
|
|
|
}
|
2003-12-31 16:10:35 +00:00
|
|
|
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
|
2003-06-28 08:39:18 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
|
2001-03-31 15:35:08 +00:00
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
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);
|
2003-09-09 09:39:21 +00:00
|
|
|
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
|
|
|
|
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
|
2003-06-28 08:39:18 +00:00
|
|
|
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
|
2003-09-09 09:39:21 +00:00
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4) &&
|
2003-06-28 08:39:18 +00:00
|
|
|
Ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while(EnumMore);
|
|
|
|
break;
|
2001-03-31 15:35:08 +00:00
|
|
|
}
|
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
|
2003-02-25 23:08:54 +00:00
|
|
|
IntEngLeave(&EnterLeaveDest);
|
|
|
|
IntEngLeave(&EnterLeaveSource);
|
2001-06-03 10:47:29 +00:00
|
|
|
|
2003-06-28 08:39:18 +00:00
|
|
|
return Ret;
|
2000-03-17 21:44:02 +00:00
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
IntEngBitBlt(SURFOBJ *DestObj,
|
|
|
|
SURFOBJ *SourceObj,
|
|
|
|
SURFOBJ *Mask,
|
|
|
|
CLIPOBJ *ClipRegion,
|
|
|
|
XLATEOBJ *ColorTranslation,
|
|
|
|
RECTL *DestRect,
|
|
|
|
POINTL *SourcePoint,
|
|
|
|
POINTL *MaskOrigin,
|
|
|
|
BRUSHOBJ *Brush,
|
|
|
|
POINTL *BrushOrigin,
|
2003-06-28 08:39:18 +00:00
|
|
|
ROP4 Rop4)
|
2003-02-25 23:08:54 +00:00
|
|
|
{
|
|
|
|
BOOLEAN ret;
|
|
|
|
SURFGDI *DestGDI;
|
|
|
|
SURFGDI *SourceGDI;
|
2004-02-06 20:36:31 +00:00
|
|
|
RECTL InputClippedRect;
|
2003-07-09 07:00:00 +00:00
|
|
|
RECTL OutputRect;
|
|
|
|
POINTL InputPoint;
|
2004-02-06 20:36:31 +00:00
|
|
|
BOOLEAN UsesSource;
|
2003-07-09 07:00:00 +00:00
|
|
|
|
2004-02-06 20:36:31 +00:00
|
|
|
InputClippedRect = *DestRect;
|
|
|
|
if (InputClippedRect.right < InputClippedRect.left)
|
|
|
|
{
|
|
|
|
InputClippedRect.left = DestRect->right;
|
|
|
|
InputClippedRect.right = DestRect->left;
|
|
|
|
}
|
|
|
|
if (InputClippedRect.bottom < InputClippedRect.top)
|
|
|
|
{
|
|
|
|
InputClippedRect.top = DestRect->bottom;
|
|
|
|
InputClippedRect.bottom = DestRect->top;
|
|
|
|
}
|
|
|
|
UsesSource = ((Rop4 & 0xCC0000) >> 2) != (Rop4 & 0x330000);
|
|
|
|
if (UsesSource)
|
2003-07-09 07:00:00 +00:00
|
|
|
{
|
2004-02-06 20:36:31 +00:00
|
|
|
if (NULL == SourcePoint || NULL == SourceObj)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-07-09 07:00:00 +00:00
|
|
|
InputPoint = *SourcePoint;
|
2004-02-06 20:36:31 +00:00
|
|
|
SourceGDI = (SURFGDI*) AccessInternalObjectFromUserObject(SourceObj);
|
|
|
|
|
|
|
|
/* Make sure we don't try to copy anything outside the valid source region */
|
|
|
|
if (InputPoint.x < 0)
|
|
|
|
{
|
|
|
|
InputClippedRect.left -= InputPoint.x;
|
|
|
|
InputPoint.x = 0;
|
|
|
|
}
|
|
|
|
if (InputPoint.y < 0)
|
|
|
|
{
|
|
|
|
InputClippedRect.top -= InputPoint.y;
|
|
|
|
InputPoint.y = 0;
|
|
|
|
}
|
|
|
|
if (SourceObj->sizlBitmap.cx < InputPoint.x + InputClippedRect.right - InputClippedRect.left)
|
|
|
|
{
|
|
|
|
InputClippedRect.right = InputClippedRect.left + SourceObj->sizlBitmap.cx - InputPoint.x;
|
|
|
|
}
|
|
|
|
if (SourceObj->sizlBitmap.cy < InputPoint.y + InputClippedRect.bottom - InputClippedRect.top)
|
|
|
|
{
|
|
|
|
InputClippedRect.bottom = InputClippedRect.top + SourceObj->sizlBitmap.cy - InputPoint.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (InputClippedRect.right < InputClippedRect.left ||
|
|
|
|
InputClippedRect.bottom < InputClippedRect.top)
|
|
|
|
{
|
|
|
|
/* Everything clipped away, nothing to do */
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-07-09 07:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Clip against the bounds of the clipping region so we won't try to write
|
|
|
|
* outside the surface */
|
|
|
|
if (NULL != ClipRegion)
|
|
|
|
{
|
2004-02-06 20:36:31 +00:00
|
|
|
if (! EngIntersectRect(&OutputRect, &InputClippedRect, &ClipRegion->rclBounds))
|
2003-07-09 07:00:00 +00:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
InputPoint.x += OutputRect.left - DestRect->left;
|
|
|
|
InputPoint.y += OutputRect.top - DestRect->top;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-02-06 20:36:31 +00:00
|
|
|
OutputRect = InputClippedRect;
|
2003-07-09 07:00:00 +00:00
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
2004-02-06 20:36:31 +00:00
|
|
|
if (UsesSource)
|
2003-02-25 23:08:54 +00:00
|
|
|
{
|
2003-07-09 07:00:00 +00:00
|
|
|
MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputPoint.x, InputPoint.y,
|
|
|
|
(InputPoint.x + abs(DestRect->right - DestRect->left)),
|
|
|
|
(InputPoint.y + abs(DestRect->bottom - DestRect->top)));
|
2003-02-25 23:08:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* No success yet */
|
|
|
|
ret = FALSE;
|
|
|
|
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
|
2003-07-09 07:00:00 +00:00
|
|
|
MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
|
|
|
|
OutputRect.right, OutputRect.bottom);
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
/* Call the driver's DrvBitBlt if available */
|
2003-07-09 07:00:00 +00:00
|
|
|
if (NULL != DestGDI->BitBlt)
|
|
|
|
{
|
2004-02-24 13:27:03 +00:00
|
|
|
IntLockGDIDriver(DestGDI);
|
2003-07-09 07:00:00 +00:00
|
|
|
ret = DestGDI->BitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
|
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
|
|
|
|
Rop4);
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2003-07-09 07:00:00 +00:00
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
2003-07-09 07:00:00 +00:00
|
|
|
if (! ret)
|
|
|
|
{
|
|
|
|
ret = EngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
|
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
|
|
|
|
Rop4);
|
|
|
|
}
|
2003-02-25 23:08:54 +00:00
|
|
|
|
|
|
|
MouseSafetyOnDrawEnd(DestObj, DestGDI);
|
2004-02-06 20:36:31 +00:00
|
|
|
if (UsesSource)
|
2003-02-25 23:08:54 +00:00
|
|
|
{
|
|
|
|
MouseSafetyOnDrawEnd(SourceObj, SourceGDI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2003-12-08 11:11:11 +00:00
|
|
|
|
2003-12-08 18:07:56 +00:00
|
|
|
static BOOLEAN STDCALL
|
|
|
|
CallDibStretchBlt(SURFOBJ* OutputObj,
|
|
|
|
SURFGDI* OutputGDI,
|
|
|
|
SURFOBJ* InputObj,
|
|
|
|
SURFGDI* InputGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
RECTL* OutputRect,
|
|
|
|
RECTL* InputRect,
|
|
|
|
POINTL* MaskOrigin,
|
|
|
|
POINTL* BrushOrigin,
|
|
|
|
ULONG Mode)
|
|
|
|
{
|
|
|
|
return OutputGDI->DIB_StretchBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputRect, MaskOrigin, BrushOrigin, ColorTranslation, Mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
STDCALL
|
|
|
|
EngStretchBlt(
|
|
|
|
IN SURFOBJ *DestObj,
|
|
|
|
IN SURFOBJ *SourceObj,
|
|
|
|
IN SURFOBJ *Mask,
|
|
|
|
IN CLIPOBJ *ClipRegion,
|
|
|
|
IN XLATEOBJ *ColorTranslation,
|
|
|
|
IN COLORADJUSTMENT *pca,
|
|
|
|
IN POINTL *BrushOrigin,
|
|
|
|
IN RECTL *prclDest,
|
|
|
|
IN RECTL *prclSrc,
|
|
|
|
IN POINTL *MaskOrigin,
|
|
|
|
IN ULONG Mode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// www.osr.com/ddk/graphics/gdifncs_0bs7.htm
|
|
|
|
|
|
|
|
BYTE clippingType;
|
|
|
|
RECTL CombinedRect;
|
|
|
|
// RECT_ENUM RectEnum;
|
|
|
|
// BOOL EnumMore;
|
|
|
|
SURFGDI* OutputGDI;
|
|
|
|
SURFGDI* InputGDI;
|
|
|
|
POINTL InputPoint;
|
|
|
|
RECTL InputRect;
|
|
|
|
RECTL OutputRect;
|
|
|
|
POINTL Translate;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveSource;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveDest;
|
|
|
|
SURFOBJ* InputObj;
|
|
|
|
SURFOBJ* OutputObj;
|
|
|
|
PSTRETCHRECTFUNC BltRectFunc;
|
|
|
|
BOOLEAN Ret;
|
|
|
|
RECTL ClipRect;
|
|
|
|
// unsigned i;
|
|
|
|
POINTL Pt;
|
|
|
|
// ULONG Direction;
|
|
|
|
|
|
|
|
InputRect.left = prclSrc->left;
|
|
|
|
InputRect.right = prclSrc->right;
|
|
|
|
InputRect.top = prclSrc->top;
|
|
|
|
InputRect.bottom = prclSrc->bottom;
|
|
|
|
|
|
|
|
if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
InputPoint.x = InputRect.left + Translate.x;
|
|
|
|
InputPoint.y = InputRect.top + Translate.y;
|
|
|
|
|
|
|
|
if (NULL != InputObj)
|
|
|
|
{
|
|
|
|
InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InputGDI = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputRect = *prclDest;
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
IntEngLeave(&EnterLeaveSource);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputRect.left = prclDest->left + Translate.x;
|
|
|
|
OutputRect.right = prclDest->right + Translate.x;
|
|
|
|
OutputRect.top = prclDest->top + Translate.y;
|
|
|
|
OutputRect.bottom = prclDest->bottom + Translate.y;
|
|
|
|
|
|
|
|
if (NULL != OutputObj)
|
|
|
|
{
|
|
|
|
OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine clipping type
|
|
|
|
if (ClipRegion == (CLIPOBJ *) NULL)
|
|
|
|
{
|
|
|
|
clippingType = DC_TRIVIAL;
|
|
|
|
} else {
|
|
|
|
clippingType = ClipRegion->iDComplexity;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Mask != NULL)//(0xaacc == Rop4)
|
|
|
|
{
|
|
|
|
//BltRectFunc = BltMask;
|
|
|
|
DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
|
|
|
|
IntEngLeave(&EnterLeaveDest);
|
|
|
|
IntEngLeave(&EnterLeaveSource);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BltRectFunc = CallDibStretchBlt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(clippingType)
|
|
|
|
{
|
|
|
|
case DC_TRIVIAL:
|
|
|
|
Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
|
|
|
|
&OutputRect, &InputRect, MaskOrigin, BrushOrigin, Mode);
|
|
|
|
break;
|
|
|
|
case DC_RECT:
|
|
|
|
// Clip the blt to the clip rectangle
|
|
|
|
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,
|
|
|
|
&OutputRect, &InputRect, MaskOrigin, BrushOrigin, Mode);
|
|
|
|
//Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation,
|
|
|
|
// &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4);
|
|
|
|
DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n");
|
|
|
|
break;
|
|
|
|
// TODO: Complex clipping
|
|
|
|
/*
|
|
|
|
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;
|
|
|
|
}
|
2003-12-31 16:10:35 +00:00
|
|
|
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
|
2003-12-08 18:07:56 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
|
|
|
|
|
|
|
|
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 Ret;
|
|
|
|
}
|
|
|
|
|
2003-12-08 11:11:11 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
IntEngStretchBlt(SURFOBJ *DestObj,
|
|
|
|
SURFOBJ *SourceObj,
|
|
|
|
SURFOBJ *Mask,
|
|
|
|
CLIPOBJ *ClipRegion,
|
|
|
|
XLATEOBJ *ColorTranslation,
|
|
|
|
RECTL *DestRect,
|
|
|
|
RECTL *SourceRect,
|
|
|
|
POINTL *pMaskOrigin,
|
|
|
|
BRUSHOBJ *Brush,
|
|
|
|
POINTL *BrushOrigin,
|
|
|
|
ULONG Mode)
|
|
|
|
{
|
|
|
|
BOOLEAN ret;
|
|
|
|
SURFGDI *DestGDI;
|
|
|
|
SURFGDI *SourceGDI;
|
|
|
|
RECTL OutputRect;
|
|
|
|
RECTL InputRect;
|
|
|
|
COLORADJUSTMENT ca;
|
|
|
|
POINT MaskOrigin;
|
|
|
|
|
|
|
|
if (pMaskOrigin != NULL)
|
|
|
|
{
|
|
|
|
MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != SourceRect)
|
|
|
|
{
|
|
|
|
InputRect = *SourceRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Clipping is taken from IntEngBitBlt w/o modifications!
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n");
|
|
|
|
//InputPoint.x += OutputRect.left - DestRect->left;
|
|
|
|
//InputPoint.y += OutputRect.top - DestRect->top;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OutputRect = *DestRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != SourceObj)
|
|
|
|
{
|
|
|
|
SourceGDI = (SURFGDI*) AccessInternalObjectFromUserObject(SourceObj);
|
|
|
|
MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputRect.left, InputRect.top,
|
|
|
|
(InputRect.left + abs(InputRect.right - InputRect.left)),
|
|
|
|
(InputRect.top + abs(InputRect.bottom - InputRect.top)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No success yet */
|
|
|
|
ret = FALSE;
|
|
|
|
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
|
|
|
|
MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
|
|
|
|
OutputRect.right, OutputRect.bottom);
|
|
|
|
|
|
|
|
/* Prepare color adjustment */
|
|
|
|
|
|
|
|
/* Call the driver's DrvStretchBlt if available */
|
|
|
|
if (NULL != DestGDI->StretchBlt)
|
|
|
|
{
|
2003-12-08 18:07:56 +00:00
|
|
|
/* Drv->StretchBlt (look at http://www.osr.com/ddk/graphics/ddifncs_3ew7.htm )
|
|
|
|
SURFOBJ *psoMask // optional, if it exists, then rop4=0xCCAA, otherwise rop4=0xCCCC */
|
|
|
|
// FIXME: MaskOrigin is always NULL !
|
2004-02-24 13:27:03 +00:00
|
|
|
IntLockGDIDriver(DestGDI);
|
2003-12-08 11:11:11 +00:00
|
|
|
ret = DestGDI->StretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
|
2003-12-08 18:07:56 +00:00
|
|
|
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode);
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2003-12-08 11:11:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (! ret)
|
|
|
|
{
|
2003-12-08 18:07:56 +00:00
|
|
|
// FIXME: see previous fixme
|
|
|
|
ret = EngStretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation,
|
|
|
|
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode);
|
2003-12-08 11:11:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MouseSafetyOnDrawEnd(DestObj, DestGDI);
|
|
|
|
if (NULL != SourceObj)
|
|
|
|
{
|
|
|
|
MouseSafetyOnDrawEnd(SourceObj, SourceGDI);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2003-12-25 00:28:09 +00:00
|
|
|
|
|
|
|
/**** REACTOS FONT RENDERING CODE *********************************************/
|
|
|
|
|
|
|
|
/* renders the alpha mask bitmap */
|
|
|
|
static BOOLEAN STDCALL
|
|
|
|
AlphaBltMask(SURFOBJ* Dest,
|
|
|
|
SURFGDI* DestGDI,
|
|
|
|
SURFOBJ* Source,
|
|
|
|
SURFGDI* SourceGDI,
|
|
|
|
SURFOBJ* Mask,
|
|
|
|
XLATEOBJ* ColorTranslation,
|
|
|
|
XLATEOBJ* SrcColorTranslation,
|
|
|
|
RECTL* DestRect,
|
|
|
|
POINTL* SourcePoint,
|
|
|
|
POINTL* MaskPoint,
|
|
|
|
BRUSHOBJ* Brush,
|
|
|
|
POINTL* BrushPoint)
|
|
|
|
{
|
|
|
|
LONG i, j, dx, dy;
|
2003-12-25 10:21:02 +00:00
|
|
|
int r, g, b;
|
|
|
|
ULONG Background, BrushColor, NewColor;
|
2003-12-25 00:28:09 +00:00
|
|
|
BYTE *tMask, *lMask;
|
|
|
|
|
|
|
|
dx = DestRect->right - DestRect->left;
|
|
|
|
dy = DestRect->bottom - DestRect->top;
|
|
|
|
|
|
|
|
if (Mask != NULL)
|
|
|
|
{
|
2003-12-25 10:49:30 +00:00
|
|
|
BrushColor = XLATEOBJ_iXlate(SrcColorTranslation, Brush->iSolidColor);
|
2003-12-25 10:21:02 +00:00
|
|
|
r = (int)GetRValue(BrushColor);
|
|
|
|
g = (int)GetGValue(BrushColor);
|
|
|
|
b = (int)GetBValue(BrushColor);
|
2003-12-25 00:28:09 +00:00
|
|
|
|
2004-03-22 14:58:56 +00:00
|
|
|
tMask = Mask->pvBits + (SourcePoint->y * Mask->lDelta) + SourcePoint->x;
|
2003-12-25 00:28:09 +00:00
|
|
|
for (j = 0; j < dy; j++)
|
|
|
|
{
|
|
|
|
lMask = tMask;
|
|
|
|
for (i = 0; i < dx; i++)
|
|
|
|
{
|
|
|
|
if (*lMask > 0)
|
|
|
|
{
|
|
|
|
if(*lMask == 0xff)
|
|
|
|
{
|
|
|
|
DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Background = DIB_GetSource(Dest, DestGDI, DestRect->left + i, DestRect->top + j, SrcColorTranslation);
|
2003-12-25 10:21:02 +00:00
|
|
|
|
|
|
|
NewColor =
|
|
|
|
RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background),
|
|
|
|
(*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background),
|
|
|
|
(*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background));
|
2003-12-25 00:28:09 +00:00
|
|
|
|
2003-12-25 10:21:02 +00:00
|
|
|
Background = XLATEOBJ_iXlate(ColorTranslation, NewColor);
|
2003-12-25 00:28:09 +00:00
|
|
|
DestGDI->DIB_PutPixel(Dest, DestRect->left + i, DestRect->top + j, Background);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lMask++;
|
|
|
|
}
|
|
|
|
tMask += Mask->lDelta;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
EngMaskBitBlt(SURFOBJ *DestObj,
|
|
|
|
SURFOBJ *Mask,
|
|
|
|
CLIPOBJ *ClipRegion,
|
|
|
|
XLATEOBJ *DestColorTranslation,
|
|
|
|
XLATEOBJ *SourceColorTranslation,
|
|
|
|
RECTL *DestRect,
|
|
|
|
POINTL *SourcePoint,
|
|
|
|
POINTL *MaskOrigin,
|
|
|
|
BRUSHOBJ *Brush,
|
|
|
|
POINTL *BrushOrigin)
|
|
|
|
{
|
|
|
|
BYTE clippingType;
|
|
|
|
RECTL CombinedRect;
|
|
|
|
RECT_ENUM RectEnum;
|
|
|
|
BOOL EnumMore;
|
|
|
|
SURFGDI* OutputGDI;
|
|
|
|
SURFGDI* InputGDI;
|
|
|
|
POINTL InputPoint;
|
|
|
|
RECTL InputRect;
|
|
|
|
RECTL OutputRect;
|
|
|
|
POINTL Translate;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveSource;
|
|
|
|
INTENG_ENTER_LEAVE EnterLeaveDest;
|
|
|
|
SURFOBJ* InputObj;
|
|
|
|
SURFOBJ* OutputObj;
|
|
|
|
BOOLEAN Ret;
|
|
|
|
RECTL ClipRect;
|
|
|
|
unsigned i;
|
|
|
|
POINTL Pt;
|
|
|
|
ULONG Direction;
|
2004-01-16 19:32:00 +00:00
|
|
|
SURFGDI* DestGDI;
|
2003-12-25 00:28:09 +00:00
|
|
|
|
|
|
|
if (NULL != SourcePoint)
|
|
|
|
{
|
|
|
|
InputRect.left = SourcePoint->x;
|
|
|
|
InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
|
|
|
|
InputRect.top = SourcePoint->y;
|
|
|
|
InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InputRect.left = 0;
|
|
|
|
InputRect.right = DestRect->right - DestRect->left;
|
|
|
|
InputRect.top = 0;
|
|
|
|
InputRect.bottom = DestRect->bottom - DestRect->top;
|
|
|
|
}
|
|
|
|
|
2004-01-16 19:32:00 +00:00
|
|
|
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
|
2004-02-24 13:27:03 +00:00
|
|
|
IntLockGDIDriver(DestGDI);
|
2003-12-25 00:28:09 +00:00
|
|
|
if (! IntEngEnter(&EnterLeaveSource, NULL, &InputRect, TRUE, &Translate, &InputObj))
|
|
|
|
{
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2003-12-25 00:28:09 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != SourcePoint)
|
|
|
|
{
|
|
|
|
InputPoint.x = SourcePoint->x + Translate.x;
|
|
|
|
InputPoint.y = SourcePoint->y + Translate.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InputPoint.x = 0;
|
|
|
|
InputPoint.y = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != InputObj)
|
|
|
|
{
|
|
|
|
InputGDI = (SURFGDI*) 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);
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2003-12-25 00:28:09 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
|
|
|
|
{
|
|
|
|
IntEngLeave(&EnterLeaveSource);
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2003-12-25 00:28:09 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputRect.left = DestRect->left + Translate.x;
|
|
|
|
OutputRect.right = DestRect->right + Translate.x;
|
|
|
|
OutputRect.top = DestRect->top + Translate.y;
|
|
|
|
OutputRect.bottom = DestRect->bottom + Translate.y;
|
|
|
|
|
|
|
|
if (NULL != OutputObj)
|
|
|
|
{
|
|
|
|
OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine clipping type
|
|
|
|
if (ClipRegion == (CLIPOBJ *) NULL)
|
|
|
|
{
|
|
|
|
clippingType = DC_TRIVIAL;
|
|
|
|
} else {
|
|
|
|
clippingType = ClipRegion->iDComplexity;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(clippingType)
|
|
|
|
{
|
|
|
|
case DC_TRIVIAL:
|
2003-12-26 00:31:22 +00:00
|
|
|
if(Mask->iBitmapFormat == BMF_8BPP)
|
|
|
|
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
|
2003-12-25 00:28:09 +00:00
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);
|
2003-12-26 00:31:22 +00:00
|
|
|
else
|
|
|
|
Ret = BltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation,
|
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin, 0xAACC);
|
2003-12-25 00:28:09 +00:00
|
|
|
break;
|
|
|
|
case DC_RECT:
|
|
|
|
// Clip the blt to the clip rectangle
|
|
|
|
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;
|
2003-12-26 00:31:22 +00:00
|
|
|
if(Mask->iBitmapFormat == BMF_8BPP)
|
|
|
|
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
|
2003-12-25 00:28:09 +00:00
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin);
|
2003-12-26 00:31:22 +00:00
|
|
|
else
|
|
|
|
Ret = BltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation,
|
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, 0xAACC);
|
2003-12-25 00:28:09 +00:00
|
|
|
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;
|
|
|
|
}
|
2003-12-31 16:10:35 +00:00
|
|
|
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
|
2003-12-25 00:28:09 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
|
|
|
|
|
|
|
|
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;
|
2003-12-26 00:31:22 +00:00
|
|
|
if(Mask->iBitmapFormat == BMF_8BPP)
|
|
|
|
Ret = AlphaBltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation, SourceColorTranslation,
|
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin) && Ret;
|
|
|
|
else
|
|
|
|
Ret = BltMask(OutputObj, OutputGDI, InputObj, InputGDI, Mask, DestColorTranslation,
|
|
|
|
&CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, 0xAACC) && Ret;
|
2003-12-25 00:28:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while(EnumMore);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IntEngLeave(&EnterLeaveDest);
|
|
|
|
IntEngLeave(&EnterLeaveSource);
|
|
|
|
|
2004-02-24 13:27:03 +00:00
|
|
|
IntUnLockGDIDriver(DestGDI);
|
2004-01-16 19:32:00 +00:00
|
|
|
|
2004-01-11 19:52:27 +00:00
|
|
|
/* Dummy BitBlt to let driver know that something has changed.
|
|
|
|
0x00AA0029 is the Rop for D (no-op) */
|
|
|
|
IntEngBitBlt(DestObj, NULL, Mask, ClipRegion, DestColorTranslation,
|
2004-01-17 01:04:45 +00:00
|
|
|
DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, ROP_NOOP);
|
2004-01-11 19:52:27 +00:00
|
|
|
|
2003-12-25 00:28:09 +00:00
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
IntEngMaskBlt(SURFOBJ *DestObj,
|
|
|
|
SURFOBJ *Mask,
|
|
|
|
CLIPOBJ *ClipRegion,
|
|
|
|
XLATEOBJ *DestColorTranslation,
|
|
|
|
XLATEOBJ *SourceColorTranslation,
|
|
|
|
RECTL *DestRect,
|
|
|
|
POINTL *SourcePoint,
|
|
|
|
POINTL *MaskOrigin,
|
|
|
|
BRUSHOBJ *Brush,
|
|
|
|
POINTL *BrushOrigin)
|
|
|
|
{
|
|
|
|
BOOLEAN ret;
|
|
|
|
SURFGDI *DestGDI;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No success yet */
|
|
|
|
ret = FALSE;
|
|
|
|
DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj);
|
|
|
|
MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top,
|
|
|
|
OutputRect.right, OutputRect.bottom);
|
|
|
|
|
|
|
|
ret = EngMaskBitBlt(DestObj, Mask, ClipRegion, DestColorTranslation, SourceColorTranslation,
|
|
|
|
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);
|
|
|
|
|
|
|
|
MouseSafetyOnDrawEnd(DestObj, DestGDI);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2003-05-18 17:16:18 +00:00
|
|
|
/* EOF */
|