📄 bitblt.c
字号:
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, DestObj, &OutputRect, FALSE, &Translate,
&OutputObj))
{
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;
}
/* Determine clipping type */
if (ClipRegion == (CLIPOBJ *) NULL)
{
clippingType = DC_TRIVIAL;
}
else
{
clippingType = ClipRegion->iDComplexity;
}
if (R4_MASK == Rop4)
{
BltRectFunc = BltMask;
}
else if (ROP3_TO_ROP4(PATCOPY) == Rop4)
{
if (Brush->iSolidColor == 0xFFFFFFFF)
BltRectFunc = CallDibBitBlt;
else
BltRectFunc = BltPatCopy;
}
else
{
BltRectFunc = CallDibBitBlt;
}
switch (clippingType)
{
case DC_TRIVIAL:
Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush,
&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 (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
{
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
&CombinedRect, &Pt, MaskOrigin, Brush,
&AdjustedBrushOrigin, Rop4);
}
break;
case DC_COMPLEX:
Ret = TRUE;
if (OutputObj == InputObj)
{
if (OutputRect.top < InputPoint.y)
{
Direction = OutputRect.left < InputPoint.x ?
CD_RIGHTDOWN : CD_LEFTDOWN;
}
else
{
Direction = OutputRect.left < InputPoint.x ?
CD_RIGHTUP : CD_LEFTUP;
}
}
else
{
Direction = CD_ANY;
}
CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 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 (EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
{
Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
Ret = (*BltRectFunc)(OutputObj, InputObj, Mask,
ColorTranslation, &CombinedRect, &Pt,
MaskOrigin, Brush, &AdjustedBrushOrigin,
Rop4) && Ret;
}
}
}
while (EnumMore);
break;
}
IntEngLeave(&EnterLeaveDest);
if (UsesSource)
{
IntEngLeave(&EnterLeaveSource);
}
return Ret;
}
BOOL STDCALL
IntEngBitBltEx(SURFOBJ *DestSurf,
SURFOBJ *SourceSurf,
SURFOBJ *MaskSurf,
CLIPOBJ *ClipRegion,
XLATEOBJ *ColorTranslation,
RECTL *DestRect,
POINTL *SourcePoint,
POINTL *MaskOrigin,
BRUSHOBJ *Brush,
POINTL *BrushOrigin,
ROP4 Rop4,
BOOL RemoveMouse)
{
BOOLEAN ret;
RECTL InputClippedRect;
RECTL OutputRect;
POINTL InputPoint;
BOOLEAN UsesSource;
BITMAPOBJ *DestObj;
BITMAPOBJ *SourceObj = NULL;
if (DestSurf == NULL)
return FALSE;
ASSERT(DestSurf);
DestObj = CONTAINING_RECORD(DestSurf, BITMAPOBJ, SurfObj);
ASSERT(DestObj);
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_USES_SOURCE(Rop4);
if (UsesSource)
{
if (NULL == SourcePoint || NULL == SourceSurf)
{
return FALSE;
}
InputPoint = *SourcePoint;
/* 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 (SourceSurf->sizlBitmap.cx < InputPoint.x +
InputClippedRect.right -
InputClippedRect.left)
{
InputClippedRect.right = InputClippedRect.left +
SourceSurf->sizlBitmap.cx - InputPoint.x;
}
if (SourceSurf->sizlBitmap.cy < InputPoint.y +
InputClippedRect.bottom -
InputClippedRect.top)
{
InputClippedRect.bottom = InputClippedRect.top +
SourceSurf->sizlBitmap.cy - InputPoint.y;
}
if (InputClippedRect.right < InputClippedRect.left ||
InputClippedRect.bottom < InputClippedRect.top)
{
/* Everything clipped away, nothing to do */
return TRUE;
}
}
/* Clip against the bounds of the clipping region so we won't try to write
* outside the surface */
if (NULL != ClipRegion)
{
if (! EngIntersectRect(&OutputRect, &InputClippedRect,
&ClipRegion->rclBounds))
{
return TRUE;
}
InputPoint.x += OutputRect.left - InputClippedRect.left;
InputPoint.y += OutputRect.top - InputClippedRect.top;
}
else
{
OutputRect = InputClippedRect;
}
if (RemoveMouse)
{
BITMAPOBJ_LockBitmapBits(DestObj);
if (UsesSource)
{
if (SourceSurf != DestSurf)
{
SourceObj = CONTAINING_RECORD(SourceSurf, BITMAPOBJ, SurfObj);
BITMAPOBJ_LockBitmapBits(SourceObj);
}
MouseSafetyOnDrawStart(SourceSurf, InputPoint.x, InputPoint.y,
(InputPoint.x + abs(DestRect->right - DestRect->left)),
(InputPoint.y + abs(DestRect->bottom - DestRect->top)));
}
MouseSafetyOnDrawStart(DestSurf, OutputRect.left, OutputRect.top,
OutputRect.right, OutputRect.bottom);
}
/* No success yet */
ret = FALSE;
/* Call the driver's DrvBitBlt if available */
if (DestObj->flHooks & HOOK_BITBLT)
{
ret = GDIDEVFUNCS(DestSurf).BitBlt(
DestSurf, SourceSurf, MaskSurf, ClipRegion, ColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
Rop4);
}
if (! ret)
{
ret = EngBitBlt(DestSurf, SourceSurf, MaskSurf, ClipRegion, ColorTranslation,
&OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin,
Rop4);
}
if (RemoveMouse)
{
MouseSafetyOnDrawEnd(DestSurf);
if (UsesSource)
{
MouseSafetyOnDrawEnd(SourceSurf);
if (SourceSurf != DestSurf)
{
BITMAPOBJ_UnlockBitmapBits(SourceObj);
}
}
BITMAPOBJ_UnlockBitmapBits(DestObj);
}
return ret;
}
static BOOLEAN STDCALL
CallDibStretchBlt(SURFOBJ* OutputObj,
SURFOBJ* InputObj,
SURFOBJ* Mask,
CLIPOBJ* ClipRegion,
XLATEOBJ* ColorTranslation,
RECTL* OutputRect,
RECTL* InputRect,
POINTL* MaskOrigin,
POINTL* BrushOrigin,
ULONG Mode)
{
POINTL RealBrushOrigin;
if (BrushOrigin == NULL)
{
RealBrushOrigin.x = RealBrushOrigin.y = 0;
}
else
{
RealBrushOrigin = *BrushOrigin;
}
return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_StretchBlt(
OutputObj, InputObj, OutputRect, InputRect, MaskOrigin, RealBrushOrigin, ClipRegion, ColorTranslation, Mode);
}
BOOL
STDCALL
NtGdiEngStretchBlt(
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
)
{
COLORADJUSTMENT ca;
POINTL lBrushOrigin;
RECTL rclDest;
RECTL rclSrc;
POINTL lMaskOrigin;
_SEH_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));
}
_SEH_HANDLE
{
_SEH_YIELD(return FALSE);
}
_SEH_END;
return EngStretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, &ca, &lBrushOrigin, &rclDest, &rclSrc, &lMaskOrigin, 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
POINTL InputPoint;
RECTL InputRect;
RECTL OutputRect;
POINTL Translate;
INTENG_ENTER_LEAVE EnterLeaveSource;
INTENG_ENTER_LEAVE EnterLeaveDest;
SURFOBJ* InputObj;
SURFOBJ* OutputObj;
PSTRETCHRECTFUNC BltRectFunc;
BOOLEAN Ret;
POINTL AdjustedBrushOrigin;
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;
OutputRect = *prclDest;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -