📄 bitblt.c
字号:
/*
* 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: bitblt.c 28261 2007-08-09 10:11:47Z greatlrd $
*
* 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
*/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
typedef BOOLEAN (STDCALL *PBLTRECTFUNC)(SURFOBJ* OutputObj,
SURFOBJ* InputObj,
SURFOBJ* Mask,
XLATEOBJ* ColorTranslation,
RECTL* OutputRect,
POINTL* InputPoint,
POINTL* MaskOrigin,
BRUSHOBJ* Brush,
POINTL* BrushOrigin,
ROP4 Rop4);
typedef BOOLEAN (STDCALL *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
SURFOBJ* InputObj,
SURFOBJ* Mask,
CLIPOBJ* ClipRegion,
XLATEOBJ* ColorTranslation,
RECTL* OutputRect,
RECTL* InputRect,
POINTL* MaskOrigin,
POINTL* BrushOrigin,
ULONG Mode);
BOOL STDCALL EngIntersectRect(RECTL* prcDst, RECTL* prcSrc1, RECTL* prcSrc2)
{
static const RECTL rclEmpty = { 0, 0, 0, 0 };
prcDst->left = max(prcSrc1->left, prcSrc2->left);
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);
if (prcDst->top < prcDst->bottom)
{
return TRUE;
}
}
*prcDst = rclEmpty;
return FALSE;
}
static BOOLEAN STDCALL
BltMask(SURFOBJ* Dest,
SURFOBJ* Source,
SURFOBJ* Mask,
XLATEOBJ* ColorTranslation,
RECTL* DestRect,
POINTL* SourcePoint,
POINTL* MaskPoint,
BRUSHOBJ* Brush,
POINTL* BrushPoint,
ROP4 Rop4)
{
LONG i, j, dx, dy, c8;
BYTE *tMask, *lMask;
static BYTE maskbit[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
/* Pattern brushes */
PGDIBRUSHINST GdiBrush = NULL;
SURFOBJ *PatternObj = NULL;
PBITMAPOBJ PatternBitmap;
ULONG PatternWidth = 0, PatternHeight = 0, PatternY = 0;
if (Mask == NULL)
{
return FALSE;
}
dx = DestRect->right - DestRect->left;
dy = DestRect->bottom - DestRect->top;
if (Brush->iSolidColor == 0xFFFFFFFF)
{
GdiBrush = CONTAINING_RECORD(
Brush,
GDIBRUSHINST,
BrushObject);
PatternBitmap = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern);
if (PatternBitmap != NULL)
{
PatternObj = &PatternBitmap->SurfObj;
PatternWidth = PatternObj->sizlBitmap.cx;
PatternHeight = PatternObj->sizlBitmap.cy;
}
}
else
PatternBitmap = NULL;
tMask = (PBYTE)Mask->pvScan0 + SourcePoint->y * Mask->lDelta + (SourcePoint->x >> 3);
for (j = 0; j < dy; j++)
{
lMask = tMask;
c8 = SourcePoint->x & 0x07;
if (PatternBitmap != NULL)
PatternY = (DestRect->top + j) % PatternHeight;
for (i = 0; i < dx; i++)
{
if (0 != (*lMask & maskbit[c8]))
{
if (PatternBitmap == NULL)
{
DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
}
else
{
DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
Dest, DestRect->left + i, DestRect->top + j,
DIB_GetSource(PatternObj, (DestRect->left + i) % PatternWidth, PatternY, GdiBrush->XlateObject));
}
}
c8++;
if (8 == c8)
{
lMask++;
c8 = 0;
}
}
tMask += Mask->lDelta;
}
if (PatternBitmap != NULL)
BITMAPOBJ_UnlockBitmap(PatternBitmap);
return TRUE;
}
static BOOLEAN STDCALL
BltPatCopy(SURFOBJ* Dest,
SURFOBJ* Source,
SURFOBJ* Mask,
XLATEOBJ* ColorTranslation,
RECTL* DestRect,
POINTL* SourcePoint,
POINTL* MaskPoint,
BRUSHOBJ* Brush,
POINTL* BrushPoint,
ROP4 Rop4)
{
// These functions are assigned if we're working with a DIB
// The assigned functions depend on the bitsPerPixel of the DIB
DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_ColorFill(Dest, DestRect, Brush->iSolidColor);
return TRUE;
}
static BOOLEAN STDCALL
CallDibBitBlt(SURFOBJ* OutputObj,
SURFOBJ* InputObj,
SURFOBJ* Mask,
XLATEOBJ* ColorTranslation,
RECTL* OutputRect,
POINTL* InputPoint,
POINTL* MaskOrigin,
BRUSHOBJ* Brush,
POINTL* BrushOrigin,
ROP4 Rop4)
{
BLTINFO BltInfo;
PGDIBRUSHINST GdiBrush = NULL;
BITMAPOBJ *bmPattern;
BOOLEAN Result;
BltInfo.DestSurface = OutputObj;
BltInfo.SourceSurface = InputObj;
BltInfo.PatternSurface = NULL;
BltInfo.XlateSourceToDest = ColorTranslation;
BltInfo.DestRect = *OutputRect;
BltInfo.SourcePoint = *InputPoint;
if (ROP3_TO_ROP4(SRCCOPY) == Rop4)
return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
BltInfo.XlatePatternToDest = NULL;
BltInfo.Brush = Brush;
BltInfo.BrushOrigin = *BrushOrigin;
BltInfo.Rop4 = Rop4;
/* Pattern brush */
if (ROP4_USES_PATTERN(Rop4) && Brush->iSolidColor == 0xFFFFFFFF)
{
GdiBrush = CONTAINING_RECORD(Brush, GDIBRUSHINST, BrushObject);
if ((bmPattern = BITMAPOBJ_LockBitmap(GdiBrush->GdiBrushObject->hbmPattern)))
{
BltInfo.PatternSurface = &bmPattern->SurfObj;
}
else
{
/* FIXME - What to do here? */
}
BltInfo.XlatePatternToDest = GdiBrush->XlateObject;
}
else
{
bmPattern = NULL;
}
Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);
/* Pattern brush */
if (bmPattern != NULL)
{
BITMAPOBJ_UnlockBitmap(bmPattern);
}
return Result;
}
INT __cdecl abs(INT nm);
/*
* @implemented
*/
BOOL STDCALL
NtGdiEngBitBlt(
IN SURFOBJ *psoTrg,
IN SURFOBJ *psoSrc,
IN SURFOBJ *psoMask,
IN CLIPOBJ *pco,
IN XLATEOBJ *pxlo,
IN RECTL *prclTrg,
IN POINTL *pptlSrc,
IN POINTL *pptlMask,
IN BRUSHOBJ *pbo,
IN POINTL *pptlBrush,
IN ROP4 rop4 )
{
RECTL rclTrg;
POINTL ptlSrc;
POINTL ptlMask;
POINTL ptlBrush;
_SEH_TRY
{
ProbeForRead(prclTrg, sizeof(RECTL), 1);
RtlCopyMemory(&rclTrg,prclTrg, sizeof(RECTL));
ProbeForRead(pptlSrc, sizeof(POINTL), 1);
RtlCopyMemory(&ptlSrc, pptlSrc, sizeof(POINTL));
ProbeForRead(pptlMask, sizeof(POINTL), 1);
RtlCopyMemory(&ptlMask, pptlMask, sizeof(POINTL));
ProbeForRead(pptlBrush, sizeof(POINTL), 1);
RtlCopyMemory(&ptlBrush, pptlBrush, sizeof(POINTL));
}
_SEH_HANDLE
{
_SEH_YIELD(return FALSE);
}
_SEH_END;
return EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, &rclTrg, &ptlSrc, &ptlMask, pbo, &ptlBrush, rop4);
}
/*
* @implemented
*/
BOOL STDCALL
EngBitBlt(SURFOBJ *DestObj,
SURFOBJ *SourceObj,
SURFOBJ *Mask,
CLIPOBJ *ClipRegion,
XLATEOBJ *ColorTranslation,
RECTL *DestRect,
POINTL *SourcePoint,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
ROP4 Rop4)
{
BYTE clippingType;
RECTL CombinedRect;
RECT_ENUM RectEnum;
BOOL EnumMore;
POINTL InputPoint;
RECTL InputRect;
RECTL OutputRect;
POINTL Translate;
INTENG_ENTER_LEAVE EnterLeaveSource;
INTENG_ENTER_LEAVE EnterLeaveDest;
SURFOBJ* InputObj;
SURFOBJ* OutputObj;
PBLTRECTFUNC BltRectFunc;
BOOLEAN Ret = TRUE;
RECTL ClipRect;
unsigned i;
POINTL Pt;
ULONG Direction;
BOOL UsesSource;
BOOL UsesPattern;
POINTL AdjustedBrushOrigin;
UsesSource = ROP4_USES_SOURCE(Rop4);
UsesPattern = ROP4_USES_PATTERN(Rop4);
if (R4_NOOP == Rop4)
{
/* Copy destination onto itself: nop */
return TRUE;
}
OutputRect = *DestRect;
if (OutputRect.right < OutputRect.left)
{
OutputRect.left = DestRect->right;
OutputRect.right = DestRect->left;
}
if (OutputRect.bottom < OutputRect.top)
{
OutputRect.left = DestRect->right;
OutputRect.right = DestRect->left;
}
if (UsesSource)
{
if (NULL == SourcePoint)
{
return FALSE;
}
/* Make sure we don't try to copy anything outside the valid source
region */
InputPoint = *SourcePoint;
if (InputPoint.x < 0)
{
OutputRect.left -= InputPoint.x;
InputPoint.x = 0;
}
if (InputPoint.y < 0)
{
OutputRect.top -= InputPoint.y;
InputPoint.y = 0;
}
if (SourceObj->sizlBitmap.cx < InputPoint.x +
OutputRect.right - OutputRect.left)
{
OutputRect.right = OutputRect.left +
SourceObj->sizlBitmap.cx - InputPoint.x;
}
if (SourceObj->sizlBitmap.cy < InputPoint.y +
OutputRect.bottom - OutputRect.top)
{
OutputRect.bottom = OutputRect.top +
SourceObj->sizlBitmap.cy - InputPoint.y;
}
InputRect.left = InputPoint.x;
InputRect.right = InputPoint.x + (OutputRect.right - OutputRect.left);
InputRect.top = InputPoint.y;
InputRect.bottom = InputPoint.y + (OutputRect.bottom - OutputRect.top);
if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE,
&Translate, &InputObj))
{
return FALSE;
}
InputPoint.x += Translate.x;
InputPoint.y += Translate.y;
}
else
{
InputRect.left = 0;
InputRect.right = DestRect->right - DestRect->left;
InputRect.top = 0;
InputRect.bottom = DestRect->bottom - DestRect->top;
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -