⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitblt.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
            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 + -