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

📄 bitblt.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:

    /* 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 != BrushOrigin)
    {
        AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
        AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
    }
    else
    {
        AdjustedBrushOrigin = Translate;
    }

    if (Mask != NULL)
    {
        //BltRectFunc = BltMask;
        DPRINT("EngStretchBlt isn't capable of handling mask yet.\n");
        IntEngLeave(&EnterLeaveDest);
        IntEngLeave(&EnterLeaveSource);

        return FALSE;
    }
    else
    {
        BltRectFunc = CallDibStretchBlt;
    }


    Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ClipRegion,
                         ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
                         &AdjustedBrushOrigin, Mode);

    IntEngLeave(&EnterLeaveDest);
    IntEngLeave(&EnterLeaveSource);

    return Ret;
}

BOOL STDCALL
IntEngStretchBlt(SURFOBJ *DestSurf,
                 SURFOBJ *SourceSurf,
                 SURFOBJ *MaskSurf,
                 CLIPOBJ *ClipRegion,
                 XLATEOBJ *ColorTranslation,
                 RECTL *DestRect,
                 RECTL *SourceRect,
                 POINTL *pMaskOrigin,
                 BRUSHOBJ *Brush,
                 POINTL *BrushOrigin,
                 ULONG Mode)
{
    BOOLEAN ret;
    COLORADJUSTMENT ca;
    POINT MaskOrigin;
    BITMAPOBJ *DestObj;
    BITMAPOBJ *SourceObj = NULL;

    ASSERT(DestSurf);
    DestObj = CONTAINING_RECORD(DestSurf, BITMAPOBJ, SurfObj);
    ASSERT(DestObj);

    if (pMaskOrigin != NULL)
    {
        MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
    }

    /* No success yet */
    ret = FALSE;
    ASSERT(DestRect);
    BITMAPOBJ_LockBitmapBits(DestObj);
    MouseSafetyOnDrawStart(DestSurf, DestRect->left, DestRect->top,
                           DestRect->right, DestRect->bottom);

    if (NULL != SourceSurf)
    {
        SourceObj = CONTAINING_RECORD(SourceSurf, BITMAPOBJ, SurfObj);
        ASSERT(SourceRect);
        if (SourceSurf != DestSurf)
        {
            BITMAPOBJ_LockBitmapBits(SourceObj);
        }
        MouseSafetyOnDrawStart(SourceSurf, SourceRect->left, SourceRect->top,
                               SourceRect->right, SourceRect->bottom);
    }

    /* Prepare color adjustment */

    /* Call the driver's DrvStretchBlt if available */
    if (DestObj->flHooks & HOOK_STRETCHBLT)
    {
        /* 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 !
        ret = GDIDEVFUNCS(DestSurf).StretchBlt(
                  DestSurf, SourceSurf, MaskSurf, ClipRegion, ColorTranslation,
                  &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode);
    }

    if (! ret)
    {
        // FIXME: see previous fixme
        ret = EngStretchBlt(DestSurf, SourceSurf, MaskSurf, ClipRegion, ColorTranslation,
                            &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode);
    }

    if (NULL != SourceSurf)
    {
        MouseSafetyOnDrawEnd(SourceSurf);
        if (SourceSurf != DestSurf)
        {
            BITMAPOBJ_UnlockBitmapBits(SourceObj);
        }
    }
    MouseSafetyOnDrawEnd(DestSurf);
    BITMAPOBJ_UnlockBitmapBits(DestObj);

    return ret;
}


/*
 * @implemented
 */
BOOL
STDCALL
NtGdiEngAlphaBlend(IN SURFOBJ *Dest,
                   IN SURFOBJ *Source,
                   IN CLIPOBJ *ClipRegion,
                   IN XLATEOBJ *ColorTranslation,
                   IN PRECTL upDestRect,
                   IN PRECTL upSourceRect,
                   IN BLENDOBJ *BlendObj)
{
    RECTL DestRect;
    RECTL SourceRect;

    _SEH_TRY
    {
        ProbeForRead(upDestRect, sizeof(RECTL), 1);
        RtlCopyMemory(&DestRect,upDestRect, sizeof(RECTL));

        ProbeForRead(upSourceRect, sizeof(RECTL), 1);
        RtlCopyMemory(&SourceRect, upSourceRect, sizeof(RECTL));

    }
    _SEH_HANDLE
    {
        _SEH_YIELD(return FALSE);
    }
    _SEH_END;

    return EngAlphaBlend(Dest, Source, ClipRegion, ColorTranslation, &DestRect, &SourceRect, BlendObj);
}

/*
 * @implemented
 */
BOOL
STDCALL
EngAlphaBlend(IN SURFOBJ *Dest,
              IN SURFOBJ *Source,
              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(Dest:0x%p, Source:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", Dest, Source, 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 input */
    if (DestRect->left >= DestRect->right || DestRect->top >= DestRect->bottom)
    {
        DPRINT1("Empty destination rectangle!\n");
        return FALSE;
    }
    if (SourceRect->left >= SourceRect->right || SourceRect->top >= SourceRect->bottom)
    {
        DPRINT1("Empty source rectangle!\n");
        return FALSE;
    }
    if (Dest == Source &&
            !(DestRect->left >= SourceRect->right || SourceRect->left >= DestRect->right ||
              DestRect->top >= SourceRect->bottom || SourceRect->top >= DestRect->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 (DestRect->right - DestRect->left != SourceRect->right - SourceRect->left ||
            DestRect->bottom - DestRect->top != SourceRect->bottom - SourceRect->top)
    {
        SourceStretchedSize.cx = DestRect->right - DestRect->left;
        SourceStretchedSize.cy = DestRect->bottom - DestRect->top;
        Width = DIB_GetDIBWidthBytes(SourceStretchedSize.cx, BitsPerFormat(Source->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, Source->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, Source, NULL, NULL,
                              NULL, &SourceStretchedRect, SourceRect, NULL,
                              NULL, NULL, COLORONCOLOR))*/
        if (!EngStretchBlt(SourceStretchedObj, Source, NULL, NULL, NULL,
                           NULL, NULL, &SourceStretchedRect, SourceRect,
                           NULL, COLORONCOLOR))
        {
            DPRINT1("EngStretchBlt failed!\n");
            EngFreeMem(SourceStretchedObj->pvBits);
            EngUnlockSurface(SourceStretchedObj);
            EngDeleteSurface((HSURF)SourceStretchedBitmap);
            return FALSE;
        }
        SourceRect = &SourceStretchedRect;
        Source = SourceStretchedObj;
    }

    /* Now call the DIB function */
    InputRect.left = SourceRect->left;
    InputRect.right = SourceRect->right;
    InputRect.top = SourceRect->top;
    InputRect.bottom = SourceRect->bottom;
    if (!IntEngEnter(&EnterLeaveSource, Source, &InputRect, TRUE, &Translate, &InputObj))
    {
        if (SourceStretchedObj != NULL)
        {
            EngFreeMem(SourceStretchedObj->pvBits);
            EngUnlockSurface(SourceStretchedObj);
        }
        if (SourceStretchedBitmap != 0)
        {
            EngDeleteSurface((HSURF)SourceStretchedBitmap);
        }
        return FALSE;
    }
    InputRect.left = SourceRect->left + Translate.x;
    InputRect.right = SourceRect->right + Translate.x;
    InputRect.top = SourceRect->top + Translate.y;
    InputRect.bottom = SourceRect->bottom + Translate.y;

    OutputRect.left = DestRect->left;
    OutputRect.right = DestRect->right;
    OutputRect.top = DestRect->top;
    OutputRect.bottom = DestRect->bottom;
    if (!IntEngEnter(&EnterLeaveDest, Dest, &OutputRect, FALSE, &Translate, &OutputObj))
    {
        IntEngLeave(&EnterLeaveSource);
        if (SourceStretchedObj != NULL)
        {
            EngFreeMem(SourceStretchedObj->pvBits);
            EngUnlockSurface(SourceStretchedObj);
        }
        if (SourceStretchedBitmap != 0)
        {
            EngDeleteSurface((HSURF)SourceStretchedBitmap);
        }
        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;

    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 (EngIntersectRect(&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 (EngIntersectRect(&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 STDCALL
IntEngAlphaBlend(IN SURFOBJ *Dest,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -