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

📄 bitblt.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                 IN SURFOBJ *Source,
                 IN CLIPOBJ *ClipRegion,
                 IN XLATEOBJ *ColorTranslation,
                 IN PRECTL DestRect,
                 IN PRECTL SourceRect,
                 IN BLENDOBJ *BlendObj)
{
    BOOL ret = FALSE;
    BITMAPOBJ *DestObj;
    BITMAPOBJ *SourceObj;

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

    ASSERT(Source);
    SourceObj = CONTAINING_RECORD(Source, BITMAPOBJ, SurfObj);
    ASSERT(SourceObj);

    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;
    }

    BITMAPOBJ_LockBitmapBits(DestObj);
    MouseSafetyOnDrawStart(Dest, DestRect->left, DestRect->top,
                           DestRect->right, DestRect->bottom);

    if (Source != Dest)
        BITMAPOBJ_LockBitmapBits(SourceObj);
    MouseSafetyOnDrawStart(Source, SourceRect->left, SourceRect->top,
                           SourceRect->right, SourceRect->bottom);

    /* Call the driver's DrvAlphaBlend if available */
    if (DestObj->flHooks & HOOK_ALPHABLEND)
    {
        ret = GDIDEVFUNCS(Dest).AlphaBlend(
                  Dest, Source, ClipRegion, ColorTranslation,
                  DestRect, SourceRect, BlendObj);
    }

    if (! ret)
    {
        ret = EngAlphaBlend(Dest, Source, ClipRegion, ColorTranslation,
                            DestRect, SourceRect, BlendObj);
    }

    MouseSafetyOnDrawEnd(Source);
    if (Source != Dest)
        BITMAPOBJ_UnlockBitmapBits(SourceObj);
    MouseSafetyOnDrawEnd(Dest);
    BITMAPOBJ_UnlockBitmapBits(DestObj);

    return ret;
}

/**** REACTOS FONT RENDERING CODE *********************************************/

/* renders the alpha mask bitmap */
static BOOLEAN STDCALL
AlphaBltMask(SURFOBJ* Dest,
             SURFOBJ* Source,
             SURFOBJ* Mask,
             XLATEOBJ* ColorTranslation,
             XLATEOBJ* SrcColorTranslation,
             RECTL* DestRect,
             POINTL* SourcePoint,
             POINTL* MaskPoint,
             BRUSHOBJ* Brush,
             POINTL* BrushPoint)
{
    LONG i, j, dx, dy;
    int r, g, b;
    ULONG Background, BrushColor, NewColor;
    BYTE *tMask, *lMask;

    dx = DestRect->right  - DestRect->left;
    dy = DestRect->bottom - DestRect->top;

    if (Mask != NULL)
    {
        BrushColor = XLATEOBJ_iXlate(SrcColorTranslation, Brush->iSolidColor);
        r = (int)GetRValue(BrushColor);
        g = (int)GetGValue(BrushColor);
        b = (int)GetBValue(BrushColor);

        tMask = (PBYTE)Mask->pvScan0 + (SourcePoint->y * Mask->lDelta) + SourcePoint->x;
        for (j = 0; j < dy; j++)
        {
            lMask = tMask;
            for (i = 0; i < dx; i++)
            {
                if (*lMask > 0)
                {
                    if (*lMask == 0xff)
                    {
                        DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                            Dest, DestRect->left + i, DestRect->top + j, Brush->iSolidColor);
                    }
                    else
                    {
                        Background = DIB_GetSource(Dest, DestRect->left + i, DestRect->top + j,
                                                   SrcColorTranslation);

                        NewColor =
                            RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background),
                                (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background),
                                (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background));

                        Background = XLATEOBJ_iXlate(ColorTranslation, NewColor);
                        DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel(
                            Dest, DestRect->left + i, DestRect->top + j, Background);
                    }
                }
                lMask++;
            }
            tMask += Mask->lDelta;
        }
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

BOOL STDCALL
EngMaskBitBlt(SURFOBJ *DestObj,
              SURFOBJ *Mask,
              CLIPOBJ *ClipRegion,
              XLATEOBJ *DestColorTranslation,
              XLATEOBJ *SourceColorTranslation,
              RECTL *DestRect,
              POINTL *SourcePoint,
              POINTL *MaskOrigin,
              BRUSHOBJ *Brush,
              POINTL *BrushOrigin)
{
    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;
    BOOLEAN            Ret = TRUE;
    RECTL              ClipRect;
    unsigned           i;
    POINTL             Pt;
    ULONG              Direction;
    POINTL             AdjustedBrushOrigin;

    ASSERT ( Mask );

    if (NULL != SourcePoint)
    {
        InputRect.left = SourcePoint->x;
        InputRect.right = SourcePoint->x + (DestRect->right - DestRect->left);
        InputRect.top = SourcePoint->y;
        InputRect.bottom = SourcePoint->y + (DestRect->bottom - DestRect->top);
    }
    else
    {
        InputRect.left = 0;
        InputRect.right = DestRect->right - DestRect->left;
        InputRect.top = 0;
        InputRect.bottom = DestRect->bottom - DestRect->top;
    }

    if (! IntEngEnter(&EnterLeaveSource, DestObj, &InputRect, TRUE, &Translate, &InputObj))
    {
        return FALSE;
    }

    if (NULL != SourcePoint)
    {
        InputPoint.x = SourcePoint->x + Translate.x;
        InputPoint.y = SourcePoint->y + Translate.y;
    }
    else
    {
        InputPoint.x = 0;
        InputPoint.y = 0;
    }

    OutputRect = *DestRect;
    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;
            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)
    {
        IntEngLeave(&EnterLeaveSource);
        return TRUE;
    }

    if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj))
    {
        IntEngLeave(&EnterLeaveSource);
        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;

    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;
    }

    switch (clippingType)
    {
        case DC_TRIVIAL:
            if (Mask->iBitmapFormat == BMF_8BPP)
                Ret = AlphaBltMask(OutputObj, InputObj, Mask, DestColorTranslation, SourceColorTranslation,
                                   &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin);
            else
                Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
                              &OutputRect, &InputPoint, MaskOrigin, Brush, &AdjustedBrushOrigin,
                              R4_MASK);
            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;
                if (Mask->iBitmapFormat == BMF_8BPP)
                {
                    Ret = AlphaBltMask(OutputObj, InputObj, Mask, DestColorTranslation, SourceColorTranslation,
                                       &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin);
                }
                else
                {
                    Ret = BltMask(OutputObj, InputObj, Mask, DestColorTranslation,
                                  &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, R4_MASK);
                }
            }
            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;
                        if (Mask->iBitmapFormat == BMF_8BPP)
                        {
                            Ret = AlphaBltMask(OutputObj, InputObj, Mask,
                                               DestColorTranslation,
                                               SourceColorTranslation,
                                               &CombinedRect, &Pt, MaskOrigin, Brush,
                                               &AdjustedBrushOrigin) && Ret;
                        }
                        else
                        {
                            Ret = BltMask(OutputObj, InputObj, Mask,
                                          DestColorTranslation, &CombinedRect, &Pt,
                                          MaskOrigin, Brush, &AdjustedBrushOrigin,
                                          R4_MASK) && Ret;
                        }
                    }
                }
            }
            while (EnumMore);
            break;
    }


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

    return Ret;
}

BOOL STDCALL
IntEngMaskBlt(SURFOBJ *DestSurf,
              SURFOBJ *Mask,
              CLIPOBJ *ClipRegion,
              XLATEOBJ *DestColorTranslation,
              XLATEOBJ *SourceColorTranslation,
              RECTL *DestRect,
              POINTL *SourcePoint,
              POINTL *MaskOrigin,
              BRUSHOBJ *Brush,
              POINTL *BrushOrigin)
{
    BOOLEAN ret;
    RECTL OutputRect;
    POINTL InputPoint;
    BITMAPOBJ *DestObj;

    ASSERT(Mask);

    if (NULL != SourcePoint)
    {
        InputPoint = *SourcePoint;
    }

    /* Clip against the bounds of the clipping region so we won't try to write
     * outside the surface */
    if (NULL != ClipRegion)
    {
        if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
        {
            return TRUE;
        }
        InputPoint.x += OutputRect.left - DestRect->left;
        InputPoint.y += OutputRect.top - DestRect->top;
    }
    else
    {
        OutputRect = *DestRect;
    }

    /* No success yet */
    ret = FALSE;
    ASSERT(DestSurf);
    DestObj = CONTAINING_RECORD(DestSurf, BITMAPOBJ, SurfObj);

    BITMAPOBJ_LockBitmapBits(DestObj);
    MouseSafetyOnDrawStart(DestSurf, OutputRect.left, OutputRect.top,
                           OutputRect.right, OutputRect.bottom);

    /* Dummy BitBlt to let driver know that it should flush its changes.
       This should really be done using a call to DrvSynchronizeSurface,
       but the VMware driver doesn't hook that call. */
    IntEngBitBltEx(DestSurf, NULL, Mask, ClipRegion, DestColorTranslation,
                   DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin,
                   R4_NOOP, FALSE);

    ret = EngMaskBitBlt(DestSurf, Mask, ClipRegion, DestColorTranslation, SourceColorTranslation,
                        &OutputRect, &InputPoint, MaskOrigin, Brush, BrushOrigin);

    /* Dummy BitBlt to let driver know that something has changed. */
    IntEngBitBltEx(DestSurf, NULL, Mask, ClipRegion, DestColorTranslation,
                   DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin,
                   R4_NOOP, FALSE);

    MouseSafetyOnDrawEnd(DestSurf);
    BITMAPOBJ_UnlockBitmapBits(DestObj);

    return ret;
}
/* EOF */

⌨️ 快捷键说明

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