mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 14:53:40 +00:00
Divide eng/bitblt.c into bitblt.c, alphablend.c and stretchblt.c. Remove EngIntersectRect and replace it with RECTL_bIntersectRect, which is changed to the code of EngIntersectRect, that was better.
svn path=/trunk/; revision=40451
This commit is contained in:
parent
ee2d3933cb
commit
8d3981bfa5
7 changed files with 951 additions and 959 deletions
376
reactos/subsystems/win32/win32k/eng/alphablend.c
Normal file
376
reactos/subsystems/win32/win32k/eng/alphablend.c
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* PURPOSE: GDI alpha blending functions
|
||||||
|
* FILE: subsystems/win32/win32k/eng/alphablend.c
|
||||||
|
* PROGRAMER: Jason Filby
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <w32k.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
EngAlphaBlend(IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
IN CLIPOBJ *ClipRegion,
|
||||||
|
IN XLATEOBJ *ColorTranslation,
|
||||||
|
IN PRECTL DestRect,
|
||||||
|
IN PRECTL SourceRect,
|
||||||
|
IN BLENDOBJ *BlendObj)
|
||||||
|
{
|
||||||
|
RECTL SourceStretchedRect;
|
||||||
|
SIZEL SourceStretchedSize;
|
||||||
|
HBITMAP SourceStretchedBitmap = 0;
|
||||||
|
SURFOBJ* SourceStretchedObj = NULL;
|
||||||
|
RECTL InputRect;
|
||||||
|
RECTL OutputRect;
|
||||||
|
RECTL ClipRect;
|
||||||
|
RECTL CombinedRect;
|
||||||
|
RECTL Rect;
|
||||||
|
POINTL Translate;
|
||||||
|
INTENG_ENTER_LEAVE EnterLeaveSource;
|
||||||
|
INTENG_ENTER_LEAVE EnterLeaveDest;
|
||||||
|
SURFOBJ* InputObj;
|
||||||
|
SURFOBJ* OutputObj;
|
||||||
|
LONG Width;
|
||||||
|
LONG ClippingType;
|
||||||
|
RECT_ENUM RectEnum;
|
||||||
|
BOOL EnumMore;
|
||||||
|
INT i;
|
||||||
|
BOOLEAN Ret;
|
||||||
|
|
||||||
|
DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest, psoSource, ClipRegion, ColorTranslation);
|
||||||
|
DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n",
|
||||||
|
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom,
|
||||||
|
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom);
|
||||||
|
DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj->BlendFunction.BlendOp,
|
||||||
|
BlendObj->BlendFunction.BlendFlags, BlendObj->BlendFunction.SourceConstantAlpha,
|
||||||
|
BlendObj->BlendFunction.AlphaFormat);
|
||||||
|
|
||||||
|
|
||||||
|
/* Validate output */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Validate input */
|
||||||
|
|
||||||
|
/* FIXME when WindowOrg.x or .y are negitve this check are not vaild,
|
||||||
|
* we need convert the inputRect to the windows org and do it right */
|
||||||
|
InputRect = *SourceRect;
|
||||||
|
if ( (InputRect.top < 0) || (InputRect.bottom < 0) ||
|
||||||
|
(InputRect.left < 0) || (InputRect.right < 0) )
|
||||||
|
{
|
||||||
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (psoDest == psoSource &&
|
||||||
|
!(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right ||
|
||||||
|
OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom))
|
||||||
|
{
|
||||||
|
DPRINT1("Source and destination rectangles overlap!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER)
|
||||||
|
{
|
||||||
|
DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (BlendObj->BlendFunction.BlendFlags != 0)
|
||||||
|
{
|
||||||
|
DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0)
|
||||||
|
{
|
||||||
|
DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there is anything to draw */
|
||||||
|
if (ClipRegion != NULL &&
|
||||||
|
(ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right ||
|
||||||
|
ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom))
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stretch source if needed */
|
||||||
|
if (OutputRect.right - OutputRect.left != InputRect.right - InputRect.left ||
|
||||||
|
OutputRect.bottom - OutputRect.top != InputRect.bottom - InputRect.top)
|
||||||
|
{
|
||||||
|
SourceStretchedSize.cx = OutputRect.right - OutputRect.left;
|
||||||
|
SourceStretchedSize.cy = OutputRect.bottom - OutputRect.top;
|
||||||
|
Width = DIB_GetDIBWidthBytes(SourceStretchedSize.cx, BitsPerFormat(psoSource->iBitmapFormat));
|
||||||
|
/* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
|
||||||
|
if possible to get a HW accelerated stretch. */
|
||||||
|
SourceStretchedBitmap = EngCreateBitmap(SourceStretchedSize, Width, psoSource->iBitmapFormat,
|
||||||
|
BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
|
||||||
|
if (SourceStretchedBitmap == 0)
|
||||||
|
{
|
||||||
|
DPRINT1("EngCreateBitmap failed!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
SourceStretchedObj = EngLockSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
if (SourceStretchedObj == NULL)
|
||||||
|
{
|
||||||
|
DPRINT1("EngLockSurface failed!\n");
|
||||||
|
EngDeleteSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceStretchedRect.left = 0;
|
||||||
|
SourceStretchedRect.right = SourceStretchedSize.cx;
|
||||||
|
SourceStretchedRect.top = 0;
|
||||||
|
SourceStretchedRect.bottom = SourceStretchedSize.cy;
|
||||||
|
/* FIXME: IntEngStretchBlt isn't used here atm because it results in a
|
||||||
|
try to acquire an already acquired mutex (lock the already locked source surface) */
|
||||||
|
/*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL,
|
||||||
|
NULL, &SourceStretchedRect, SourceRect, NULL,
|
||||||
|
NULL, NULL, COLORONCOLOR))*/
|
||||||
|
if (!EngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, &SourceStretchedRect, &InputRect,
|
||||||
|
NULL, COLORONCOLOR))
|
||||||
|
{
|
||||||
|
DPRINT1("EngStretchBlt failed!\n");
|
||||||
|
EngFreeMem(SourceStretchedObj->pvBits);
|
||||||
|
EngUnlockSurface(SourceStretchedObj);
|
||||||
|
EngDeleteSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
InputRect.top = SourceStretchedRect.top;
|
||||||
|
InputRect.bottom = SourceStretchedRect.bottom;
|
||||||
|
InputRect.left = SourceStretchedRect.left;
|
||||||
|
InputRect.right = SourceStretchedRect.right;
|
||||||
|
psoSource = SourceStretchedObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now call the DIB function */
|
||||||
|
if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
|
||||||
|
{
|
||||||
|
if (SourceStretchedObj != NULL)
|
||||||
|
{
|
||||||
|
EngFreeMem(SourceStretchedObj->pvBits);
|
||||||
|
EngUnlockSurface(SourceStretchedObj);
|
||||||
|
}
|
||||||
|
if (SourceStretchedBitmap != 0)
|
||||||
|
{
|
||||||
|
EngDeleteSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
InputRect.left += Translate.x;
|
||||||
|
InputRect.right += Translate.x;
|
||||||
|
InputRect.top += Translate.y;
|
||||||
|
InputRect.bottom += Translate.y;
|
||||||
|
|
||||||
|
if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj))
|
||||||
|
{
|
||||||
|
IntEngLeave(&EnterLeaveSource);
|
||||||
|
if (SourceStretchedObj != NULL)
|
||||||
|
{
|
||||||
|
EngFreeMem(SourceStretchedObj->pvBits);
|
||||||
|
EngUnlockSurface(SourceStretchedObj);
|
||||||
|
}
|
||||||
|
if (SourceStretchedBitmap != 0)
|
||||||
|
{
|
||||||
|
EngDeleteSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
OutputRect.left += Translate.x;
|
||||||
|
OutputRect.right += Translate.x;
|
||||||
|
OutputRect.top += Translate.y;
|
||||||
|
OutputRect.bottom += Translate.y;
|
||||||
|
|
||||||
|
Ret = FALSE;
|
||||||
|
ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity;
|
||||||
|
switch (ClippingType)
|
||||||
|
{
|
||||||
|
case DC_TRIVIAL:
|
||||||
|
Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend(
|
||||||
|
OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DC_RECT:
|
||||||
|
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;
|
||||||
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
|
{
|
||||||
|
Rect.left = InputRect.left + CombinedRect.left - OutputRect.left;
|
||||||
|
Rect.right = InputRect.right + CombinedRect.right - OutputRect.right;
|
||||||
|
Rect.top = InputRect.top + CombinedRect.top - OutputRect.top;
|
||||||
|
Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom;
|
||||||
|
Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend(
|
||||||
|
OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DC_COMPLEX:
|
||||||
|
Ret = TRUE;
|
||||||
|
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
||||||
|
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;
|
||||||
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
|
{
|
||||||
|
Rect.left = InputRect.left + CombinedRect.left - OutputRect.left;
|
||||||
|
Rect.right = InputRect.right + CombinedRect.right - OutputRect.right;
|
||||||
|
Rect.top = InputRect.top + CombinedRect.top - OutputRect.top;
|
||||||
|
Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom;
|
||||||
|
Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend(
|
||||||
|
OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (EnumMore);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
ASSERT(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntEngLeave(&EnterLeaveDest);
|
||||||
|
IntEngLeave(&EnterLeaveSource);
|
||||||
|
|
||||||
|
if (SourceStretchedObj != NULL)
|
||||||
|
{
|
||||||
|
EngFreeMem(SourceStretchedObj->pvBits);
|
||||||
|
EngUnlockSurface(SourceStretchedObj);
|
||||||
|
}
|
||||||
|
if (SourceStretchedBitmap != 0)
|
||||||
|
{
|
||||||
|
EngDeleteSurface((HSURF)SourceStretchedBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY
|
||||||
|
IntEngAlphaBlend(IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
IN CLIPOBJ *ClipRegion,
|
||||||
|
IN XLATEOBJ *ColorTranslation,
|
||||||
|
IN PRECTL DestRect,
|
||||||
|
IN PRECTL SourceRect,
|
||||||
|
IN BLENDOBJ *BlendObj)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
SURFACE *psurfDest;
|
||||||
|
SURFACE *psurfSource;
|
||||||
|
|
||||||
|
ASSERT(psoDest);
|
||||||
|
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
|
||||||
|
|
||||||
|
ASSERT(psoSource);
|
||||||
|
psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
|
||||||
|
|
||||||
|
ASSERT(DestRect);
|
||||||
|
ASSERT(SourceRect);
|
||||||
|
|
||||||
|
/* Check if there is anything to draw */
|
||||||
|
if (ClipRegion != NULL &&
|
||||||
|
(ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right ||
|
||||||
|
ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom))
|
||||||
|
{
|
||||||
|
/* Nothing to do */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SURFACE_LockBitmapBits(psurfDest);
|
||||||
|
MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top,
|
||||||
|
DestRect->right, DestRect->bottom);
|
||||||
|
|
||||||
|
if (psoSource != psoDest)
|
||||||
|
SURFACE_LockBitmapBits(psurfSource);
|
||||||
|
MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top,
|
||||||
|
SourceRect->right, SourceRect->bottom);
|
||||||
|
|
||||||
|
/* Call the driver's DrvAlphaBlend if available */
|
||||||
|
if (psurfDest->flHooks & HOOK_ALPHABLEND)
|
||||||
|
{
|
||||||
|
ret = GDIDEVFUNCS(psoDest).AlphaBlend(
|
||||||
|
psoDest, psoSource, ClipRegion, ColorTranslation,
|
||||||
|
DestRect, SourceRect, BlendObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ret)
|
||||||
|
{
|
||||||
|
ret = EngAlphaBlend(psoDest, psoSource, ClipRegion, ColorTranslation,
|
||||||
|
DestRect, SourceRect, BlendObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseSafetyOnDrawEnd(psoSource);
|
||||||
|
if (psoSource != psoDest)
|
||||||
|
SURFACE_UnlockBitmapBits(psurfSource);
|
||||||
|
MouseSafetyOnDrawEnd(psoDest);
|
||||||
|
SURFACE_UnlockBitmapBits(psurfDest);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
NtGdiEngAlphaBlend(IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
IN CLIPOBJ *ClipRegion,
|
||||||
|
IN XLATEOBJ *ColorTranslation,
|
||||||
|
IN PRECTL upDestRect,
|
||||||
|
IN PRECTL upSourceRect,
|
||||||
|
IN BLENDOBJ *BlendObj)
|
||||||
|
{
|
||||||
|
RECTL DestRect;
|
||||||
|
RECTL SourceRect;
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(upDestRect, sizeof(RECTL), 1);
|
||||||
|
RtlCopyMemory(&DestRect,upDestRect, sizeof(RECTL));
|
||||||
|
|
||||||
|
ProbeForRead(upSourceRect, sizeof(RECTL), 1);
|
||||||
|
RtlCopyMemory(&SourceRect, upSourceRect, sizeof(RECTL));
|
||||||
|
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
_SEH2_YIELD(return FALSE);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
return EngAlphaBlend(psoDest, psoSource, ClipRegion, ColorTranslation, &DestRect, &SourceRect, BlendObj);
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -155,7 +155,7 @@ EngCopyBits(SURFOBJ *psoDest,
|
||||||
|
|
||||||
case DC_RECT:
|
case DC_RECT:
|
||||||
// Clip the blt to the clip rectangle
|
// Clip the blt to the clip rectangle
|
||||||
EngIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
|
RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
|
||||||
|
|
||||||
BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
|
BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
|
||||||
BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
|
BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
|
||||||
|
@ -183,7 +183,7 @@ EngCopyBits(SURFOBJ *psoDest,
|
||||||
RECTL* prcl = &RectEnum.arcl[0];
|
RECTL* prcl = &RectEnum.arcl[0];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
EngIntersectRect(&BltInfo.DestRect, prcl, DestRect);
|
RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect);
|
||||||
|
|
||||||
BltInfo.SourcePoint.x = SourcePoint->x + prcl->left - DestRect->left;
|
BltInfo.SourcePoint.x = SourcePoint->x + prcl->left - DestRect->left;
|
||||||
BltInfo.SourcePoint.y = SourcePoint->y + prcl->top - DestRect->top;
|
BltInfo.SourcePoint.y = SourcePoint->y + prcl->top - DestRect->top;
|
||||||
|
|
548
reactos/subsystems/win32/win32k/eng/stretchblt.c
Normal file
548
reactos/subsystems/win32/win32k/eng/stretchblt.c
Normal file
|
@ -0,0 +1,548 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* PURPOSE: GDI stretch blt functions
|
||||||
|
* FILE: subsystems/win32/win32k/eng/stretchblt.c
|
||||||
|
* PROGRAMER: Jason Filby
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <w32k.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
|
||||||
|
SURFOBJ* InputObj,
|
||||||
|
SURFOBJ* Mask,
|
||||||
|
XLATEOBJ* ColorTranslation,
|
||||||
|
RECTL* OutputRect,
|
||||||
|
RECTL* InputRect,
|
||||||
|
POINTL* MaskOrigin,
|
||||||
|
BRUSHOBJ* pbo,
|
||||||
|
POINTL* BrushOrigin,
|
||||||
|
ROP4 Rop4);
|
||||||
|
|
||||||
|
static BOOLEAN APIENTRY
|
||||||
|
CallDibStretchBlt(SURFOBJ* psoDest,
|
||||||
|
SURFOBJ* psoSource,
|
||||||
|
SURFOBJ* Mask,
|
||||||
|
XLATEOBJ* ColorTranslation,
|
||||||
|
RECTL* OutputRect,
|
||||||
|
RECTL* InputRect,
|
||||||
|
POINTL* MaskOrigin,
|
||||||
|
BRUSHOBJ* pbo,
|
||||||
|
POINTL* BrushOrigin,
|
||||||
|
ROP4 Rop4)
|
||||||
|
{
|
||||||
|
POINTL RealBrushOrigin;
|
||||||
|
SURFACE* psurfPattern;
|
||||||
|
PEBRUSHOBJ GdiBrush = NULL;
|
||||||
|
SURFOBJ* PatternSurface = NULL;
|
||||||
|
XLATEOBJ* XlatePatternToDest = NULL;
|
||||||
|
|
||||||
|
if (BrushOrigin == NULL)
|
||||||
|
{
|
||||||
|
RealBrushOrigin.x = RealBrushOrigin.y = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RealBrushOrigin = *BrushOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pattern brush */
|
||||||
|
if (ROP4_USES_PATTERN(Rop4) && pbo && pbo->iSolidColor == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
GdiBrush = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
|
||||||
|
psurfPattern = SURFACE_LockSurface(GdiBrush->pbrush->hbmPattern);
|
||||||
|
if (psurfPattern)
|
||||||
|
{
|
||||||
|
PatternSurface = &psurfPattern->SurfObj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* FIXME - What to do here? */
|
||||||
|
}
|
||||||
|
XlatePatternToDest = GdiBrush->XlateObject;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psurfPattern = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_StretchBlt(
|
||||||
|
psoDest, psoSource, Mask, PatternSurface,
|
||||||
|
OutputRect, InputRect, MaskOrigin, pbo, &RealBrushOrigin,
|
||||||
|
ColorTranslation, XlatePatternToDest, Rop4);
|
||||||
|
|
||||||
|
/* Pattern brush */
|
||||||
|
if (psurfPattern)
|
||||||
|
{
|
||||||
|
SURFACE_UnlockSurface(psurfPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
EngStretchBltROP(
|
||||||
|
IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
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,
|
||||||
|
IN BRUSHOBJ *pbo,
|
||||||
|
IN DWORD ROP4)
|
||||||
|
{
|
||||||
|
RECTL InputRect;
|
||||||
|
RECTL OutputRect;
|
||||||
|
POINTL Translate;
|
||||||
|
INTENG_ENTER_LEAVE EnterLeaveSource;
|
||||||
|
INTENG_ENTER_LEAVE EnterLeaveDest;
|
||||||
|
SURFOBJ* psoInput;
|
||||||
|
SURFOBJ* psoOutput;
|
||||||
|
PSTRETCHRECTFUNC BltRectFunc;
|
||||||
|
BOOLEAN Ret = TRUE;
|
||||||
|
POINTL AdjustedBrushOrigin;
|
||||||
|
BOOL UsesSource = ROP4_USES_SOURCE(ROP4);
|
||||||
|
|
||||||
|
BYTE clippingType;
|
||||||
|
RECTL ClipRect;
|
||||||
|
RECT_ENUM RectEnum;
|
||||||
|
BOOL EnumMore;
|
||||||
|
ULONG Direction;
|
||||||
|
RECTL CombinedRect;
|
||||||
|
RECTL InputToCombinedRect;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
LONG DstHeight;
|
||||||
|
LONG DstWidth;
|
||||||
|
LONG SrcHeight;
|
||||||
|
LONG SrcWidth;
|
||||||
|
|
||||||
|
/* Determine clipping type */
|
||||||
|
if (ClipRegion == (CLIPOBJ *) NULL)
|
||||||
|
{
|
||||||
|
clippingType = DC_TRIVIAL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clippingType = ClipRegion->iDComplexity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ROP4 == R4_NOOP)
|
||||||
|
{
|
||||||
|
/* Copy destination onto itself: nop */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputRect = *prclDest;
|
||||||
|
if (OutputRect.right < OutputRect.left)
|
||||||
|
{
|
||||||
|
OutputRect.left = prclDest->right;
|
||||||
|
OutputRect.right = prclDest->left;
|
||||||
|
}
|
||||||
|
if (OutputRect.bottom < OutputRect.top)
|
||||||
|
{
|
||||||
|
OutputRect.top = prclDest->bottom;
|
||||||
|
OutputRect.bottom = prclDest->top;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputRect = *prclSrc;
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
if (NULL == prclSrc)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE,
|
||||||
|
&Translate, &psoInput))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputRect.left += Translate.x;
|
||||||
|
InputRect.right += Translate.x;
|
||||||
|
InputRect.top += Translate.y;
|
||||||
|
InputRect.bottom += Translate.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != ClipRegion)
|
||||||
|
{
|
||||||
|
if (OutputRect.left < ClipRegion->rclBounds.left)
|
||||||
|
{
|
||||||
|
InputRect.left += 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;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
IntEngLeave(&EnterLeaveSource);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput))
|
||||||
|
{
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
IntEngLeave(&EnterLeaveSource);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OutputRect.left += Translate.x;
|
||||||
|
OutputRect.right += Translate.x;
|
||||||
|
OutputRect.top += Translate.y;
|
||||||
|
OutputRect.bottom += Translate.y;
|
||||||
|
|
||||||
|
if (BrushOrigin)
|
||||||
|
{
|
||||||
|
AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
|
||||||
|
AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AdjustedBrushOrigin = Translate;
|
||||||
|
}
|
||||||
|
|
||||||
|
BltRectFunc = CallDibStretchBlt;
|
||||||
|
|
||||||
|
DstHeight = OutputRect.bottom - OutputRect.top;
|
||||||
|
DstWidth = OutputRect.right - OutputRect.left;
|
||||||
|
SrcHeight = InputRect.bottom - InputRect.top;
|
||||||
|
SrcWidth = InputRect.right - InputRect.left;
|
||||||
|
switch (clippingType)
|
||||||
|
{
|
||||||
|
case DC_TRIVIAL:
|
||||||
|
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
|
||||||
|
ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
|
||||||
|
pbo, &AdjustedBrushOrigin, ROP4);
|
||||||
|
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;
|
||||||
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
|
{
|
||||||
|
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
|
||||||
|
InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
|
||||||
|
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
|
||||||
|
ColorTranslation,
|
||||||
|
&CombinedRect,
|
||||||
|
&InputToCombinedRect,
|
||||||
|
MaskOrigin,
|
||||||
|
pbo,
|
||||||
|
&AdjustedBrushOrigin,
|
||||||
|
ROP4);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DC_COMPLEX:
|
||||||
|
if (psoOutput == psoInput)
|
||||||
|
{
|
||||||
|
if (OutputRect.top < InputRect.top)
|
||||||
|
{
|
||||||
|
Direction = OutputRect.left < InputRect.left ?
|
||||||
|
CD_RIGHTDOWN : CD_LEFTDOWN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Direction = OutputRect.left < InputRect.left ?
|
||||||
|
CD_RIGHTUP : CD_LEFTUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Direction = CD_ANY;
|
||||||
|
}
|
||||||
|
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
|
||||||
|
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;
|
||||||
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
|
{
|
||||||
|
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
|
||||||
|
InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
|
||||||
|
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
|
||||||
|
ColorTranslation,
|
||||||
|
&CombinedRect,
|
||||||
|
&InputToCombinedRect,
|
||||||
|
MaskOrigin,
|
||||||
|
pbo,
|
||||||
|
&AdjustedBrushOrigin,
|
||||||
|
ROP4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (EnumMore);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntEngLeave(&EnterLeaveDest);
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
IntEngLeave(&EnterLeaveSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
EngStretchBlt(
|
||||||
|
IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return EngStretchBltROP(
|
||||||
|
psoDest,
|
||||||
|
psoSource,
|
||||||
|
Mask,
|
||||||
|
ClipRegion,
|
||||||
|
ColorTranslation,
|
||||||
|
pca,
|
||||||
|
BrushOrigin,
|
||||||
|
prclDest,
|
||||||
|
prclSrc,
|
||||||
|
MaskOrigin,
|
||||||
|
Mode,
|
||||||
|
NULL,
|
||||||
|
ROP3_TO_ROP4(SRCCOPY));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY
|
||||||
|
IntEngStretchBlt(SURFOBJ *psoDest,
|
||||||
|
SURFOBJ *psoSource,
|
||||||
|
SURFOBJ *MaskSurf,
|
||||||
|
CLIPOBJ *ClipRegion,
|
||||||
|
XLATEOBJ *ColorTranslation,
|
||||||
|
RECTL *DestRect,
|
||||||
|
RECTL *SourceRect,
|
||||||
|
POINTL *pMaskOrigin,
|
||||||
|
BRUSHOBJ *pbo,
|
||||||
|
POINTL *BrushOrigin,
|
||||||
|
ROP4 ROP)
|
||||||
|
{
|
||||||
|
BOOLEAN ret;
|
||||||
|
COLORADJUSTMENT ca;
|
||||||
|
POINT MaskOrigin;
|
||||||
|
SURFACE *psurfDest;
|
||||||
|
SURFACE *psurfSource = NULL;
|
||||||
|
RECTL InputClippedRect;
|
||||||
|
RECTL InputRect;
|
||||||
|
RECTL OutputRect;
|
||||||
|
BOOL UsesSource = ROP4_USES_SOURCE(ROP);
|
||||||
|
LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
|
||||||
|
|
||||||
|
ASSERT(psoDest);
|
||||||
|
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
|
||||||
|
ASSERT(psurfDest);
|
||||||
|
ASSERT(DestRect);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
if (NULL == SourceRect || NULL == psoSource)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
InputRect = *SourceRect;
|
||||||
|
|
||||||
|
if (InputRect.right < InputRect.left ||
|
||||||
|
InputRect.bottom < InputRect.top)
|
||||||
|
{
|
||||||
|
/* Everything clipped away, nothing to do */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClipRegion)
|
||||||
|
{
|
||||||
|
if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect,
|
||||||
|
&ClipRegion->rclBounds))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* Update source rect */
|
||||||
|
InputClWidth = InputClippedRect.right - InputClippedRect.left;
|
||||||
|
InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
|
||||||
|
InputWidth = InputRect.right - InputRect.left;
|
||||||
|
InputHeight = InputRect.bottom - InputRect.top;
|
||||||
|
|
||||||
|
InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth;
|
||||||
|
InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth;
|
||||||
|
InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight;
|
||||||
|
InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutputRect = InputClippedRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pMaskOrigin != NULL)
|
||||||
|
{
|
||||||
|
MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No success yet */
|
||||||
|
ret = FALSE;
|
||||||
|
SURFACE_LockBitmapBits(psurfDest);
|
||||||
|
MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
|
||||||
|
OutputRect.right, OutputRect.bottom);
|
||||||
|
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
|
||||||
|
if (psoSource != psoDest)
|
||||||
|
{
|
||||||
|
SURFACE_LockBitmapBits(psurfSource);
|
||||||
|
}
|
||||||
|
MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
|
||||||
|
InputRect.right, InputRect.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare color adjustment */
|
||||||
|
|
||||||
|
/* Call the driver's DrvStretchBlt if available */
|
||||||
|
if (psurfDest->flHooks & HOOK_STRETCHBLTROP)
|
||||||
|
{
|
||||||
|
/* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
|
||||||
|
// FIXME: MaskOrigin is always NULL !
|
||||||
|
ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion, ColorTranslation,
|
||||||
|
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, COLORONCOLOR, pbo, ROP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ret)
|
||||||
|
{
|
||||||
|
// FIXME: see previous fixme
|
||||||
|
ret = EngStretchBltROP(psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion, ColorTranslation,
|
||||||
|
&ca, BrushOrigin, &OutputRect, &InputRect, NULL, COLORONCOLOR, pbo, ROP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UsesSource)
|
||||||
|
{
|
||||||
|
MouseSafetyOnDrawEnd(psoSource);
|
||||||
|
if (psoSource != psoDest)
|
||||||
|
{
|
||||||
|
SURFACE_UnlockBitmapBits(psurfSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseSafetyOnDrawEnd(psoDest);
|
||||||
|
SURFACE_UnlockBitmapBits(psurfDest);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
NtGdiEngStretchBlt(
|
||||||
|
IN SURFOBJ *psoDest,
|
||||||
|
IN SURFOBJ *psoSource,
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
COLORADJUSTMENT ca;
|
||||||
|
POINTL lBrushOrigin;
|
||||||
|
RECTL rclDest;
|
||||||
|
RECTL rclSrc;
|
||||||
|
POINTL lMaskOrigin;
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(pca, sizeof(COLORADJUSTMENT), 1);
|
||||||
|
RtlCopyMemory(&ca,pca, sizeof(COLORADJUSTMENT));
|
||||||
|
|
||||||
|
ProbeForRead(BrushOrigin, sizeof(POINTL), 1);
|
||||||
|
RtlCopyMemory(&lBrushOrigin, BrushOrigin, sizeof(POINTL));
|
||||||
|
|
||||||
|
ProbeForRead(prclDest, sizeof(RECTL), 1);
|
||||||
|
RtlCopyMemory(&rclDest, prclDest, sizeof(RECTL));
|
||||||
|
|
||||||
|
ProbeForRead(prclSrc, sizeof(RECTL), 1);
|
||||||
|
RtlCopyMemory(&rclSrc, prclSrc, sizeof(RECTL));
|
||||||
|
|
||||||
|
ProbeForRead(MaskOrigin, sizeof(POINTL), 1);
|
||||||
|
RtlCopyMemory(&lMaskOrigin, MaskOrigin, sizeof(POINTL));
|
||||||
|
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
_SEH2_YIELD(return FALSE);
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
return EngStretchBlt(psoDest, psoSource, Mask, ClipRegion, ColorTranslation, &ca, &lBrushOrigin, &rclDest, &rclSrc, &lMaskOrigin, Mode);
|
||||||
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ EngTransparentBlt(SURFOBJ *psoDest,
|
||||||
ClipRect.right = Clip->rclBounds.right + Translate.x;
|
ClipRect.right = Clip->rclBounds.right + Translate.x;
|
||||||
ClipRect.top = Clip->rclBounds.top + Translate.y;
|
ClipRect.top = Clip->rclBounds.top + Translate.y;
|
||||||
ClipRect.bottom = Clip->rclBounds.bottom + Translate.y;
|
ClipRect.bottom = Clip->rclBounds.bottom + Translate.y;
|
||||||
if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
{
|
{
|
||||||
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
@ -189,7 +189,7 @@ EngTransparentBlt(SURFOBJ *psoDest,
|
||||||
ClipRect.right = RectEnum.arcl[i].right + Translate.x;
|
ClipRect.right = RectEnum.arcl[i].right + Translate.x;
|
||||||
ClipRect.top = RectEnum.arcl[i].top + Translate.y;
|
ClipRect.top = RectEnum.arcl[i].top + Translate.y;
|
||||||
ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
|
ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
|
||||||
if (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
|
||||||
{
|
{
|
||||||
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
|
||||||
|
@ -264,7 +264,7 @@ IntEngTransparentBlt(SURFOBJ *psoDest,
|
||||||
* outside the surface */
|
* outside the surface */
|
||||||
if(Clip)
|
if(Clip)
|
||||||
{
|
{
|
||||||
if(!EngIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
|
if(!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,21 +64,24 @@ BOOL
|
||||||
FASTCALL
|
FASTCALL
|
||||||
RECTL_bIntersectRect(RECTL* prclDst, const RECTL* prcl1, const RECTL* prcl2)
|
RECTL_bIntersectRect(RECTL* prclDst, const RECTL* prcl1, const RECTL* prcl2)
|
||||||
{
|
{
|
||||||
if (RECTL_bIsEmptyRect(prcl1) || RECTL_bIsEmptyRect(prcl2) ||
|
|
||||||
prcl1->left >= prcl2->right || prcl2->left >= prcl1->right ||
|
|
||||||
prcl1->top >= prcl2->bottom || prcl2->top >= prcl1->bottom)
|
|
||||||
{
|
|
||||||
RECTL_vSetEmptyRect(prclDst);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
prclDst->left = max(prcl1->left, prcl2->left);
|
prclDst->left = max(prcl1->left, prcl2->left);
|
||||||
prclDst->right = min(prcl1->right, prcl2->right);
|
prclDst->right = min(prcl1->right, prcl2->right);
|
||||||
|
|
||||||
|
if (prclDst->left < prclDst->right)
|
||||||
|
{
|
||||||
prclDst->top = max(prcl1->top, prcl2->top);
|
prclDst->top = max(prcl1->top, prcl2->top);
|
||||||
prclDst->bottom = min(prcl1->bottom, prcl2->bottom);
|
prclDst->bottom = min(prcl1->bottom, prcl2->bottom);
|
||||||
|
|
||||||
|
if (prclDst->top < prclDst->bottom)
|
||||||
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RECTL_vSetEmptyRect(prclDst);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
</ifnot>
|
</ifnot>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="eng">
|
<directory name="eng">
|
||||||
|
<file>alphablend.c</file>
|
||||||
<file>bitblt.c</file>
|
<file>bitblt.c</file>
|
||||||
<file>engbrush.c</file>
|
<file>engbrush.c</file>
|
||||||
<file>clip.c</file>
|
<file>clip.c</file>
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
<file>semaphor.c</file>
|
<file>semaphor.c</file>
|
||||||
<file>sort.c</file>
|
<file>sort.c</file>
|
||||||
<file>string.c</file>
|
<file>string.c</file>
|
||||||
|
<file>stretchblt.c</file>
|
||||||
<file>surface.c</file>
|
<file>surface.c</file>
|
||||||
<file>transblt.c</file>
|
<file>transblt.c</file>
|
||||||
<file>engwindow.c</file>
|
<file>engwindow.c</file>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue