예제 #1
0
static void dumpPCO(RECTL *prclTrg, CLIPOBJ *pco)
{
    LOG(("pco = %p Trg = %d-%d %d-%d", pco, prclTrg->left, prclTrg->right, prclTrg->top, prclTrg->bottom));

    if (pco)
    {
        BOOL bMore;
        CLIPRECTS cr;
        RECTL* prclClip;
        int cRects = 0;

        LOG(("pco = %d %d-%d %d-%d dc %d fc %d mode %d opt %d",
                 pco->iUniq,
                 pco->rclBounds.left, pco->rclBounds.right, pco->rclBounds.top, pco->rclBounds.bottom,
                 pco->iDComplexity, pco->iFComplexity, pco->iMode, pco->fjOptions));

        CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);

        do
        {
            bMore = CLIPOBJ_bEnum(pco, sizeof(cr), (ULONG*)&cr);

            for (prclClip = &cr.arcl[0]; cr.c != 0; cr.c--, prclClip++)
            {
                LOG(("      %d-%d %d-%d", prclClip->left, prclClip->right, prclClip->top, prclClip->bottom));
                cRects++;
            }
        } while (bMore);

        LOG(("Total %d rects", cRects));
    }
}
예제 #2
0
/*
 * @implemented
 */
BOOL
APIENTRY
WNDOBJ_bEnum(
  IN WNDOBJ  *pwo,
  IN ULONG  cj,
  OUT ULONG  *pul)
{
  WNDGDI *WndObjInt = ObjToGDI(pwo, WND);
  BOOL Ret;

  DPRINT("WNDOBJ_bEnum: pwo = 0x%p, cj = %lu, pul = 0x%p\n", pwo, cj, pul);
  Ret = CLIPOBJ_bEnum(WndObjInt->ClientClipObj, cj, pul);

  DPRINT("WNDOBJ_bEnum: Returning %s\n", Ret ? "True" : "False");
  return Ret;
}
예제 #3
0
BOOL APIENTRY
EngPaintRgn(SURFOBJ *pso, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix,
            BRUSHOBJ *BrushObj, POINTL *BrushPoint)
{
  RECT_ENUM RectEnum;
  BOOL EnumMore;
  ULONG i;

  ASSERT(pso);
  ASSERT(ClipRegion);

  DPRINT("ClipRegion->iMode:%u, ClipRegion->iDComplexity: %u\n Color: %lu", ClipRegion->iMode, ClipRegion->iDComplexity, iColor);
  switch(ClipRegion->iMode) {

    case TC_RECTANGLES:

    /* Rectangular clipping can be handled without enumeration.
       Note that trivial clipping is not possible, since the clipping
       region defines the area to fill */

    if (ClipRegion->iDComplexity == DC_RECT)
    {
      FillSolid(pso, &(ClipRegion->rclBounds), iColor);
    } else {

      /* Enumerate all the rectangles and draw them */
      CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0);

      do {
        EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
        for (i = 0; i < RectEnum.c; i++) {
          FillSolid(pso, RectEnum.arcl + i, iColor);
        }
      } while (EnumMore);
    }

    return(TRUE);

    default:
       return(FALSE);
  }
}
예제 #4
0
static int vrdpGetIntersectingClipRects(VRDPCLIPRECTS *pClipRects, SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco, POINTL *pptlSrc)
{
    BOOL bTooManyRects = FALSE;

    LOGF(("pso = %p, pptlSrc = %p", pso, pptlSrc));

    pso = getSurfObj(pso);

    pClipRects->rclDstOrig = *prcl;
    pClipRects->rclDst     = *prcl;
    pClipRects->rects.c    = 0;

    vrdpAdjustRect(pso, &pClipRects->rclDst);

    if (pco && (pco->iDComplexity != DC_TRIVIAL))
    {
        ULONG iDirection = CD_ANY;

        if (pptlSrc)
        {
            /* Operation is performed on the same (screen) surface and enumeration direction
             * must take into account the position of source and target rectangles.
             */
            if (pptlSrc->x <= prcl->left)
            {
                if (pptlSrc->y <= prcl->top)
                {
                    iDirection = CD_LEFTUP;
                }
                else
                {
                    iDirection = CD_LEFTDOWN;
                }
            }
            else
            {
                if (pptlSrc->y <= prcl->top)
                {
                    iDirection = CD_RIGHTUP;
                }
                else
                {
                    iDirection = CD_RIGHTDOWN;
                }
            }
        }

        /* Clip the target rect by entire clipping region. Obtain the effective target. */
        vrdpIntersectRects(&pClipRects->rclDst, &pClipRects->rclDst, &pco->rclBounds);

        /* Enumerate rectangles. Try to get all rectangles at once and if there is not
         * enough space (too many rectangles) fail with the bTooManyRects condition.
         */
        CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, 0);

        bTooManyRects = CLIPOBJ_bEnum(pco, sizeof(pClipRects->rects), &pClipRects->rects.c);

        if (!bTooManyRects)
        {
            RECTL *prclClipSrc = &pClipRects->rects.arcl[0];
            RECTL *prclClipDst = prclClipSrc;

            ULONG cRects = pClipRects->rects.c;

            LOGF(("%d rects", cRects));

            if (cRects > 0)
            {
                for (; cRects != 0; cRects--, prclClipSrc++)
                {
                    vrdpIntersectRects(prclClipDst, prclClipSrc, &pClipRects->rclDst);

                    if (vrdpIsRectEmpty(prclClipDst))
                    {
                        pClipRects->rects.c--;
                    }
                    else
                    {
                        prclClipDst++;
                    }
                }
            }

            if (pClipRects->rects.c == 0)
            {
                pClipRects->rclDst.left = pClipRects->rclDst.right = 0;
            }
            LOGF(("%d rects remains", pClipRects->rects.c));
        }
    }

    if (vrdpIsRectEmpty(&pClipRects->rclDst))
    {
        return VRDP_CLIP_NO_INTERSECTION;
    }

    if (bTooManyRects)
    {
        pClipRects->rects.c = 0;

        return VRDP_CLIP_TOO_MANY_RECTS;
    }

    return VRDP_CLIP_OK;
}
예제 #5
0
파일: lineto.c 프로젝트: GYGit/reactos
static void FASTCALL
vgaSWtoNE(
    IN CLIPOBJ* Clip,
    IN BRUSHOBJ* Brush,
    IN LONG x,
    IN LONG y,
    IN LONG deltax,
    IN LONG deltay)
{
    int i;
    int error;
    BOOLEAN EnumMore;
    PRECTL ClipRect;
    RECT_ENUM RectEnum;
    ULONG Pixel = Brush->iSolidColor;
    LONG delta;

    CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0);
    EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
    ClipRect = RectEnum.arcl;
    delta = max(deltax, deltay);
    i = 0;
    error = delta / 2;
    while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
    {
        while ((ClipRect < RectEnum.arcl + RectEnum.c
                && (y < ClipRect->top
                    || (y < ClipRect->bottom && ClipRect->right <= x)))
               || EnumMore)
        {
            if (RectEnum.arcl + RectEnum.c <= ClipRect)
            {
                EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
                ClipRect = RectEnum.arcl;
            }
            else
            {
                ClipRect++;
            }
        }
        if (ClipRect < RectEnum.arcl + RectEnum.c)
        {
            if (ClipRect->left <= x && y < ClipRect->bottom)
                vgaPutPixel(x, y, Pixel);
            if (deltax < deltay)
            {
                y--;
                error = error + deltax;
                if (deltay <= error)
                {
                    x++;
                    error = error - deltay;
                }
            }
            else
            {
                x++;
                error = error + deltay;
                if (deltax <= error)
                {
                    y--;
                    error = error - deltax;
                }
            }
            i++;
        }
    }
}
예제 #6
0
파일: lineto.c 프로젝트: GYGit/reactos
/*
 * FIXME: Use Mix to perform ROPs
 * FIXME: Non-solid Brush
 */
BOOL APIENTRY
DrvLineTo(
    IN SURFOBJ *DestObj,
    IN CLIPOBJ *Clip,
    IN BRUSHOBJ *Brush,
    IN LONG x1,
    IN LONG y1,
    IN LONG x2,
    IN LONG y2,
    IN RECTL *RectBounds,
    IN MIX mix)
{
    LONG x, y, deltax, deltay, xchange, ychange, hx, vy;
    ULONG i;
    ULONG Pixel = Brush->iSolidColor;
    RECT_ENUM RectEnum;
    BOOL EnumMore;

    x = x1;
    y = y1;
    deltax = x2 - x1;
    deltay = y2 - y1;

    if (deltax < 0)
    {
        xchange = -1;
        deltax = - deltax;
        hx = x2+1;
        //x--;
    }
    else
    {
        xchange = 1;
        hx = x1;
    }

    if (deltay < 0)
    {
        ychange = -1;
        deltay = - deltay;
        vy = y2+1;
        //y--;
    }
    else
    {
        ychange = 1;
        vy = y1;
    }

    if (y1 == y2)
    {
        CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
        do
        {
            EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID) &RectEnum);
            for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++)
            {
                if (y1 < RectEnum.arcl[i].bottom &&
                    RectEnum.arcl[i].left <= hx + deltax &&
                    hx < RectEnum.arcl[i].right)
                {
                    vgaHLine(max(hx, RectEnum.arcl[i].left), y1,
                             min(hx + deltax, RectEnum.arcl[i].right)
                             -max(hx, RectEnum.arcl[i].left), Pixel);
                }
            }
        } while (EnumMore);
    }
    else if (x1 == x2)
    {
        CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
        do
        {
            EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
            for (i = 0; i < RectEnum.c; i++)
            {
                if (RectEnum.arcl[i].left <= x1 &&
                    x1 < RectEnum.arcl[i].right &&
                    RectEnum.arcl[i].top <= vy + deltay &&
                    vy < RectEnum.arcl[i].bottom)
                {
                    vgaVLine(x1,
                        max(vy, RectEnum.arcl[i].top),
                        min(vy + deltay, RectEnum.arcl[i].bottom)
                        - max(vy, RectEnum.arcl[i].top),
                        Pixel);
                }
            }
        } while (EnumMore);
    }
    else
    {
        if (0 < xchange)
        {
            if (0 < ychange)
                vgaNWtoSE(Clip, Brush, x, y, deltax, deltay);
            else
                vgaSWtoNE(Clip, Brush, x, y, deltax, deltay);
        }
        else
        {
            if (0 < ychange)
                vgaNEtoSW(Clip, Brush, x, y, deltax, deltay);
            else
                vgaSEtoNW(Clip, Brush, x, y, deltax, deltay);
        }
    }

    return TRUE;
}
예제 #7
0
파일: lineto.c 프로젝트: GYGit/reactos
/*
 * Draw a line from top-left to bottom-right
 */
static void FASTCALL
vgaNWtoSE(
    IN CLIPOBJ* Clip,
    IN BRUSHOBJ* Brush,
    IN LONG x,
    IN LONG y,
    IN LONG deltax,
    IN LONG deltay)
{
    int i;
    int error;
    BOOLEAN EnumMore;
    PRECTL ClipRect;
    RECT_ENUM RectEnum;
    ULONG Pixel = Brush->iSolidColor;
    LONG delta;

    CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
    EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
    ClipRect = RectEnum.arcl;
    delta = max(deltax, deltay);
    i = 0;
    error = delta / 2;
    while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
    {
        while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */
                && (ClipRect->bottom <= y             /* but it's above us */
                    || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */
               || EnumMore)                           /* no current clip rect, but rects left */
        {
            /* Skip to the next clip rect */
            if (RectEnum.arcl + RectEnum.c <= ClipRect)
            {
                EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
                ClipRect = RectEnum.arcl;
            }
            else
            {
                ClipRect++;
            }
        }
        if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */
        {
            if (ClipRect->left <= x && ClipRect->top <= y)
                vgaPutPixel ( x, y, Pixel );
            if ( deltax < deltay )
            {
                y++;
                error += deltax;
                if ( error >= deltay )
                {
                    x++;
                    error -= deltay;
                }
            }
            else
            {
                x++;
                error += deltay;
                if ( error >= deltax )
                {
                    y++;
                    error -= deltax;
                }
            }
            i++;
        }
    }
}
예제 #8
0
/*
 * @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              InputRect;
    RECTL              OutputRect;
    RECTL              ClipRect;
    RECTL              CombinedRect;
    RECTL              Rect;
    POINTL             Translate;
    INTENG_ENTER_LEAVE EnterLeaveSource;
    INTENG_ENTER_LEAVE EnterLeaveDest;
    SURFOBJ*           InputObj;
    SURFOBJ*           OutputObj;
    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 */
    InputRect = *SourceRect;
    if ( (InputRect.top < 0) || (InputRect.bottom < 0) ||
         (InputRect.left < 0) || (InputRect.right < 0) ||
         InputRect.right > psoSource->sizlBitmap.cx ||
         InputRect.bottom > psoSource->sizlBitmap.cy )
    {
        EngSetLastError(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;
    }

    /* Now call the DIB function */
    if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
    {
        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))
    {
        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);

    return Ret;
}
예제 #9
0
파일: transblt.c 프로젝트: RPG-7/reactos
BOOL
APIENTRY
EngTransparentBlt(
    SURFOBJ *psoDest,
    SURFOBJ *psoSource,
    CLIPOBJ *Clip,
    XLATEOBJ *ColorTranslation,
    PRECTL DestRect,
    PRECTL SourceRect,
    ULONG iTransColor,
    ULONG Reserved)
{
    BOOL Ret = TRUE;
    BYTE ClippingType;
    INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest;
    SURFOBJ *InputObj, *OutputObj;
    RECTL OutputRect, InputRect;
    POINTL Translate;

    LONG DstHeight;
    LONG DstWidth;
    LONG SrcHeight;
    LONG SrcWidth;

    InputRect = *SourceRect;

    if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
    {
        return FALSE;
    }
    InputRect.left += Translate.x;
    InputRect.right += Translate.x;
    InputRect.top += Translate.y;
    InputRect.bottom += Translate.y;

    OutputRect = *DestRect;
    if (OutputRect.right < OutputRect.left)
    {
        OutputRect.left = DestRect->right;
        OutputRect.right = DestRect->left;
    }
    if (OutputRect.bottom < OutputRect.top)
    {
        OutputRect.top = DestRect->bottom;
        OutputRect.bottom = DestRect->top;
    }

    if (Clip)
    {
        if (OutputRect.left < Clip->rclBounds.left)
        {
            InputRect.left += Clip->rclBounds.left - OutputRect.left;
            OutputRect.left = Clip->rclBounds.left;
        }
        if (Clip->rclBounds.right < OutputRect.right)
        {
            InputRect.right -=  OutputRect.right - Clip->rclBounds.right;
            OutputRect.right = Clip->rclBounds.right;
        }
        if (OutputRect.top < Clip->rclBounds.top)
        {
            InputRect.top += Clip->rclBounds.top - OutputRect.top;
            OutputRect.top = Clip->rclBounds.top;
        }
        if (Clip->rclBounds.bottom < OutputRect.bottom)
        {
            InputRect.bottom -=  OutputRect.bottom - Clip->rclBounds.bottom;
            OutputRect.bottom = Clip->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, psoDest, &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;

    ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL);

    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 = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
                      OutputObj, InputObj, &OutputRect, &InputRect, ColorTranslation, iTransColor);
            break;
        }
        case DC_RECT:
        {
            RECTL ClipRect, CombinedRect;
            RECTL InputToCombinedRect;

            ClipRect.left = Clip->rclBounds.left + Translate.x;
            ClipRect.right = Clip->rclBounds.right + Translate.x;
            ClipRect.top = Clip->rclBounds.top + Translate.y;
            ClipRect.bottom = Clip->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 = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
                          OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor);
            }
            break;
        }
        case DC_COMPLEX:
        {
            ULONG Direction, i;
            RECT_ENUM RectEnum;
            BOOL EnumMore;

            if (OutputObj == InputObj)
            {
                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(Clip, FALSE, CT_RECTANGLES, Direction, 0);
            do
            {
                EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID)&RectEnum);
                for (i = 0; i < RectEnum.c; i++)
                {
                    RECTL ClipRect, CombinedRect;
                    RECTL InputToCombinedRect;

                    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 = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
                                  OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor);
                        if (!Ret)
                        {
                            break;
                        }
                    }
                }
            }
            while (EnumMore && Ret);
            break;
        }
        default:
        {
            Ret = FALSE;
            break;
        }
    }

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

    return Ret;
}
예제 #10
0
파일: bitblt.c 프로젝트: Gaikokujin/WinNT4
BOOL
DrvCopyBits(
SURFOBJ  *psoDst,
SURFOBJ  *psoSrc,
CLIPOBJ  *pco,
XLATEOBJ *pxlo,
RECTL    *prclDst,
POINTL   *pptlSrc)

/*++

Routine Description:

   Code for "hooking" CopyBits function for Jaguar VXL.

Arguments:


Return Value:


--*/

{
    RECTL    BltRectl;
    ENUMRECTLIST ClipEnum;
    BYTE     FixedComplexity;
    BOOL     MoreClipRects;
    FLONG    BltDir;
    BOOL     JaguarDir;
    ULONG    ClipRegions;
    POINTL   SrcPoint;



    //
    // Check that there is no color translation.
    //

    if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {

        //
        // Check that source and destination surfaces are the frame buffer.
        //

        if ((psoSrc->pvBits == (PVOID)Vxl.ScreenBase) &&
            (psoDst->pvBits == (PVOID)Vxl.ScreenBase)) {

            //
            // check BLT direction for setting up clip regions
            // And for Jaguar BitBlt Commands as follows:
            //    - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom
            //      to Top except when Src & Dst are in the same scan line
            //      and BltDir is not LEFTWARDS
            //

            BltDir = 0;
            JaguarDir = FALSE;
            if (pptlSrc->y <= prclDst->top) {
                BltDir = CD_UPWARDS;
                JaguarDir = TRUE;
            }

            if (pptlSrc->x <= prclDst->left) {
                BltDir |= CD_LEFTWARDS;
            } else {
                if ((JaguarDir) && (pptlSrc->y == prclDst->top)) {
                    JaguarDir = FALSE;
                }
            }

            //
            // Figure out the real clipping complexity
            //

            if (pco == (CLIPOBJ *)NULL) {
                FixedComplexity = DC_TRIVIAL;
            } else {
                FixedComplexity = pco->iDComplexity;
            }

            switch (FixedComplexity) {

            //
            // Entire destination is to be updated.
            // Proceed with the BitBlt.
            //

            case DC_TRIVIAL:

                DrvpBitBlt(prclDst,         // Target rectangle
                           pptlSrc,         // Source offset
                           JaguarDir        // Direction
                        );
                return(TRUE);

            //
            // Only one clip region.
            //

            case DC_RECT:

                //
                // only do the BLT if there is an intersection
                //

                if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) {

                    //
                    // Adjust the Source for the intersection rectangle.
                    //

                    pptlSrc->x += BltRectl.left - prclDst->left;
                    pptlSrc->y += BltRectl.top - prclDst->top;

                    DrvpBitBlt(&BltRectl,       // Target rectangle
                               pptlSrc,         // Source offset
                               JaguarDir        // Direction
                               );
                }

                return(TRUE);

            //
            // Multiple clip regions.
            //

            case DC_COMPLEX:

                CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT);
                do {

                    //
                    // Get list of clip rectangles.
                    //

                    MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);

                    for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {

                        //
                        // If the rectangles intersect calculate the offset to the
                        // source start location to match and do the BitBlt.
                        //
                        if (DrvpIntersectRect(prclDst,
                                              &ClipEnum.arcl[ClipRegions],
                                              &BltRectl)) {
                            SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left;
                            SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top;
                            DrvpBitBlt(&BltRectl,               // Target rectangle
                                       &SrcPoint,               // Source offset
                                       JaguarDir                // Direction
                                       );
                        }
                    }
                } while (MoreClipRects);

                return(TRUE);

            //
            // Unknown Clip complexity
            //

            default:
            break;
            }  // end switch complexity
        }

    }

    //
    // If the copy operation could be performed by the accelerator,
    // this routine has already returned.
    // If execution falls here, call the Engine routine.
    // No need to Synchronize here since the Eng routine will call DrvSyncrhonize.
    //

    return EngCopyBits(psoDst,
                       psoSrc,
                       pco,
                       pxlo,
                       prclDst,
                       pptlSrc);
}
예제 #11
0
파일: bitblt.c 프로젝트: Gaikokujin/WinNT4
BOOL
DrvBitBlt(
    IN SURFOBJ  *psoDst,            // Target surface
    IN SURFOBJ  *psoSrc,            // Source surface
    IN SURFOBJ  *psoMask,           // Mask
    IN CLIPOBJ  *pco,               // Clip through this
    IN XLATEOBJ *pxlo,              // Color translation
    IN PRECTL    prclDst,           // Target offset and extent
    IN PPOINTL   pptlSrc,           // Source offset
    IN PPOINTL   pptlMask,          // Mask offset
    IN BRUSHOBJ *pdbrush,           // Brush data (from cbRealizeBrush)
    IN PPOINTL   pptlBrush,         // Brush offset (origin)
    IN ROP4      rop4               // Raster operation
)

/*++

Routine Description:

   Code for "hooking" Bit Blt functions for Jaguar VXL.

Arguments:


Return Value:


--*/

{

    FLONG    BltDir;
    BOOL     JaguarDir;
    RECTL    BltRectl;
    ENUMRECTLIST ClipEnum;
    BOOL     MoreClipRects;
    ULONG    ClipRegions;
    POINTL   SrcPoint;
    PPDEV    ppdev = (PPDEV) psoDst->dhpdev;
    BYTE     FixedComplexity;

    //
    // Check that there is no color translation.
    //

    if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {

        //
        // Check that the blt operation has the screen as target surface.
        //

        if (psoDst->pvBits == (PVOID)Vxl.ScreenBase) {

            //
            // Check for rops that Jaguar handles.
            // Solid Fills,
            // SRCCOPPY
            //

            switch(rop4) {
            case 0x00000000:                        // DDx  (BLACKNESS)
                DrvpSolidFill(prclDst,pco,0);
                return(TRUE);

            case 0x0000FFFF:                        // DDxn    (WHITENESS)
                DrvpSolidFill(prclDst,pco,0xFFFFFF);
                return(TRUE);

            case 0x0000F0F0:                        // P        (PATCOPY)
            case 0x00000F0F:                        // Pn       (NOTPATCOPY)

                //
                // This is a pattern fill. Check if the brush pattern
                // is just a plain color, in this case procede with the
                // Solid Color Fill.
                //

                if (pdbrush->iSolidColor != 0xFFFFFFFF) {
                    DrvpSolidFill(prclDst,
                                  pco,
                                  (rop4 == 0xF0F) ? ~(pdbrush->iSolidColor) : pdbrush->iSolidColor);
                    return(TRUE);
                }

                break;

            //
            // Source copy
            //

            case 0x0000CCCC:

                //
                // Check that Source and Destination Surfaces are the same.
                // This is enough as we already checked that the dst is the frame buffer
                //

                if (psoDst->pvBits == psoSrc->pvBits) {

                    //
                    // check BLT direction for setting up clip regions
                    // And for Jaguar BitBlt Commands as follows:
                    //    - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom
                    //      to Top except when Src & Dst are in the same scan line
                    //      and BltDir is not LEFTWARDS
                    //

                    BltDir = 0;
                    JaguarDir = FALSE;
                    if (pptlSrc->y <= prclDst->top) {
                        BltDir = CD_UPWARDS;
                        JaguarDir = TRUE;
                    }

                    if (pptlSrc->x <= prclDst->left) {
                        BltDir |= CD_LEFTWARDS;
                    } else {
                        if ((JaguarDir) && (pptlSrc->y == prclDst->top)) {
                            JaguarDir = FALSE;
                        }
                    }

                    //
                    // Figure out the real clipping complexity
                    //

                    if (pco == (CLIPOBJ *)NULL) {
                        FixedComplexity = DC_TRIVIAL;
                    } else {
                        FixedComplexity = pco->iDComplexity;
                    }

                    switch (FixedComplexity) {

                    //
                    // Entire destination is to be updated.
                    // Proceed with the BitBlt.
                    //

                    case DC_TRIVIAL:

                        DrvpBitBlt(prclDst,         // Target rectangle
                                   pptlSrc,         // Source offset
                                   JaguarDir        // Direction
                                );
                        return(TRUE);

                    //
                    // Only one clip region.
                    //

                    case DC_RECT:

                        //
                        // only do the BLT if there is an intersection
                        //

                        if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) {

                            //
                            // Adjust the Source for the intersection rectangle.
                            //

                            pptlSrc->x += BltRectl.left - prclDst->left;
                            pptlSrc->y += BltRectl.top - prclDst->top;

                            DrvpBitBlt(&BltRectl,       // Target rectangle
                                       pptlSrc,         // Source offset
                                       JaguarDir        // Direction
                                       );
                        }

                        return(TRUE);

                    //
                    // Multiple clip regions.
                    //

                    case DC_COMPLEX:

                        CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT);
                        do {

                            //
                            // Get list of clip rectangles.
                            //

                            MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);

                            for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {

                                //
                                // If the rectangles intersect calculate the offset to the
                                // source start location to match and do the BitBlt.
                                //
                                if (DrvpIntersectRect(prclDst,
                                                      &ClipEnum.arcl[ClipRegions],
                                                      &BltRectl)) {
                                    SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left;
                                    SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top;
                                    DrvpBitBlt(&BltRectl,               // Target rectangle
                                               &SrcPoint,               // Source offset
                                               JaguarDir                // Direction
                                               );
                                }
                            }
                        } while (MoreClipRects);

                        return(TRUE);

                    //
                    // Unknown Clip complexity
                    //

                    default:
                    break;
                    }  // end switch complexity
                }      // end if Src surface = Dst surface
            }          // end switch rop4
        }
    }

    //
    // Call GDI to do the Blt for us. No need to syncrhonize here since
    // EngXXX routines call DrvSynchronize.
    //

    return(EngBitBlt(psoDst,        // Target surface
                     psoSrc,        // Source surface
                     psoMask,       // Mask
                     pco,           // Clip through this
                     pxlo,          // Color translation
                     prclDst,       // Target offset and extent
                     pptlSrc,       // Source offset
                     pptlMask,      // Mask offset
                     pdbrush,       // Brush data (from cbRealizeBrush)
                     pptlBrush,     // Brush offset (origin)
                     rop4           // Raster operation
                     )
          );
}
예제 #12
0
파일: bitblt.c 프로젝트: Gaikokujin/WinNT4
VOID
DrvpSolidFill(
    IN PRECTL DstRect,
    IN CLIPOBJ *pco,
    IN ULONG   Color
    )
/*++

Routine Description:

    This routine fills the unclipped areas of the destination rectangle with
    the given color.

Arguments:

   DstRect - Destination Rectangle
   pco    -  Clipping area.
   Color - Color to fill with.

Return Value:

   None.

--*/
{
    RECTL     BltRectl;
    ENUMRECTLIST ClipEnum;
    BOOL     MoreClipRects;
    ULONG     ClipRegions;
    BYTE     FixedComplexity;

    //
    // Figure out the real clipping complexity
    //
    if (pco == (CLIPOBJ *)NULL) {
        FixedComplexity = DC_TRIVIAL;
    } else {
        FixedComplexity = pco->iDComplexity;
    }
    switch (FixedComplexity) {

    //
    // Entire destination is to be updated.
    // Proceed with the Solid Fill.
    //
    case DC_TRIVIAL:

        DrvpFillRectangle(DstRect,          // Target rectangle
                          Color);           // Color

        break;

    //
    // Only one clip region.
    //

    case DC_RECT:
        //
        // only do the Fill if there is an intersection
        //

        if (DrvpIntersectRect(DstRect,&pco->rclBounds,&BltRectl)) {

            DrvpFillRectangle(&BltRectl,        // Target rectangle
                              Color);           // Color
        }
        break;

    //
    // Multiple clip regions.
    //

    case DC_COMPLEX:

        CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,CD_ANY,BB_RECT_LIMIT);
        do {

        //
        // Get list of clip rectangles.
        //

            MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);

            for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {

                //
                // If the rectangles intersect do the fill
                //
                if (DrvpIntersectRect(DstRect,
                                      &ClipEnum.arcl[ClipRegions],
                                      &BltRectl)) {
                    DrvpFillRectangle(&BltRectl,        // Target rectangle
                                      Color);           // Color

                }
            }
        } while (MoreClipRects);
        break;

    }  // end switch complexity
}
예제 #13
0
BOOL
FASTCALL
IntEngGradientFillRect(
    IN SURFOBJ  *psoDest,
    IN CLIPOBJ  *pco,
    IN XLATEOBJ  *pxlo,
    IN TRIVERTEX  *pVertex,
    IN ULONG  nVertex,
    IN PGRADIENT_RECT gRect,
    IN RECTL  *prclExtents,
    IN POINTL  *pptlDitherOrg,
    IN BOOL Horizontal)
{
    SURFOBJ *psoOutput;
    TRIVERTEX *v1, *v2;
    RECTL rcGradient, rcSG;
    RECT_ENUM RectEnum;
    BOOL EnumMore;
    ULONG i;
    POINTL Translate;
    INTENG_ENTER_LEAVE EnterLeave;
    LONG y, dy, c[3], dc[3], ec[3], ic[3];

    v1 = (pVertex + gRect->UpperLeft);
    v2 = (pVertex + gRect->LowerRight);

    rcGradient.left = min(v1->x, v2->x);
    rcGradient.right = max(v1->x, v2->x);
    rcGradient.top = min(v1->y, v2->y);
    rcGradient.bottom = max(v1->y, v2->y);
    rcSG = rcGradient;
    RECTL_vOffsetRect(&rcSG, pptlDitherOrg->x, pptlDitherOrg->y);

    if(Horizontal)
    {
        dy = abs(rcGradient.right - rcGradient.left);
    }
    else
    {
        dy = abs(rcGradient.bottom - rcGradient.top);
    }

    if(!IntEngEnter(&EnterLeave, psoDest, &rcSG, FALSE, &Translate, &psoOutput))
    {
        return FALSE;
    }

    if((v1->Red != v2->Red || v1->Green != v2->Green || v1->Blue != v2->Blue) && dy > 1)
    {
        CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
        do
        {
            RECTL FillRect;
            ULONG Color;

            if (Horizontal)
            {
                EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
                for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
                {
                    if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
                    {
                        HVINITCOL(Red, 0);
                        HVINITCOL(Green, 1);
                        HVINITCOL(Blue, 2);

                        for (y = rcSG.left; y < FillRect.right; y++)
                        {
                            if (y >= FillRect.left)
                            {
                                Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2]));
                                DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_VLine(
                                    psoOutput, y + Translate.x, FillRect.top + Translate.y, FillRect.bottom + Translate.y, Color);
                            }
                            HVSTEPCOL(0);
                            HVSTEPCOL(1);
                            HVSTEPCOL(2);
                        }
                    }
                }

                continue;
            }

            /* vertical */
            EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
            for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
            {
                if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
                {
                    HVINITCOL(Red, 0);
                    HVINITCOL(Green, 1);
                    HVINITCOL(Blue, 2);

                    for (y = rcSG.top; y < FillRect.bottom; y++)
                    {
                        if (y >= FillRect.top)
                        {
                            Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2]));
                            DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput,
                                                                                            FillRect.left + Translate.x,
                                                                                            FillRect.right + Translate.x,
                                                                                            y + Translate.y,
                                                                                            Color);
                        }
                        HVSTEPCOL(0);
                        HVSTEPCOL(1);
                        HVSTEPCOL(2);
                    }
                }
            }

        }
        while (EnumMore);

        return IntEngLeave(&EnterLeave);
    }

    /* rectangle has only one color, no calculation required */
    CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
    do
    {
        RECTL FillRect;
        ULONG Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red, v1->Green, v1->Blue));

        EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
        for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
        {
            if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
            {
                for (; FillRect.top < FillRect.bottom; FillRect.top++)
                {
                    DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput,
                                                                                    FillRect.left + Translate.x,
                                                                                    FillRect.right + Translate.x,
                                                                                    FillRect.top + Translate.y,
                                                                                    Color);
                }
            }
        }
    }
    while (EnumMore);

    return IntEngLeave(&EnterLeave);
}
예제 #14
0
파일: copybits.c 프로젝트: Strongc/reactos
/*
 * @implemented
 */
BOOL APIENTRY
EngCopyBits(
    _In_ SURFOBJ *psoDest,
    _In_ SURFOBJ *psoSource,
    _In_opt_ CLIPOBJ *Clip,
    _In_opt_ XLATEOBJ *ColorTranslation,
    _In_ RECTL *DestRect,
    _In_ POINTL *SourcePoint)
{
    BOOL      ret;
    BYTE      clippingType;
    RECT_ENUM RectEnum;
    BOOL      EnumMore;
    BLTINFO   BltInfo;
    SURFACE *psurfDest;
    SURFACE *psurfSource;
    RECTL rclDest = *DestRect;
    POINTL ptlSrc = *SourcePoint;

    ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);

    psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
    psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);

    /* Clip dest rect against source surface size / source point */
    if (psoSource->sizlBitmap.cx - ptlSrc.x < rclDest.right - rclDest.left)
        rclDest.right = rclDest.left + psoSource->sizlBitmap.cx - ptlSrc.x;
    if (psoSource->sizlBitmap.cy - ptlSrc.y < rclDest.bottom - rclDest.top)
        rclDest.bottom = rclDest.top + psoSource->sizlBitmap.cy - ptlSrc.y;

    /* Clip dest rect against target surface size */
    if (rclDest.right > psoDest->sizlBitmap.cx)
        rclDest.right = psoDest->sizlBitmap.cx;
    if (rclDest.bottom > psoDest->sizlBitmap.cy)
        rclDest.bottom = psoDest->sizlBitmap.cy;
    if (RECTL_bIsEmptyRect(&rclDest)) return TRUE;
    DestRect = &rclDest;

    // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
    //        mark the copy block function to be DrvCopyBits instead of the
    //        GDI's copy bit function so as to remove clipping from the
    //        driver's responsibility

    // If one of the surfaces isn't managed by the GDI
    if ((psoDest->iType!=STYPE_BITMAP) || (psoSource->iType!=STYPE_BITMAP))
    {
        // Destination surface is device managed
        if (psoDest->iType!=STYPE_BITMAP)
        {
            /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
            if (psurfDest->flags & HOOK_COPYBITS)
            {
                ret = GDIDEVFUNCS(psoDest).CopyBits(
                          psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);

                goto cleanup;
            }
        }

        // Source surface is device managed
        if (psoSource->iType!=STYPE_BITMAP)
        {
            /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
            if (psurfSource->flags & HOOK_COPYBITS)
            {
                ret = GDIDEVFUNCS(psoSource).CopyBits(
                          psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);

                goto cleanup;
            }
        }

        // If CopyBits wasn't hooked, BitBlt must be
        ret = IntEngBitBlt(psoDest, psoSource,
                           NULL, Clip, ColorTranslation, DestRect, SourcePoint,
                           NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));

        goto cleanup;
    }

    // Determine clipping type
    if (!Clip)
    {
        clippingType = DC_TRIVIAL;
    }
    else
    {
        clippingType = Clip->iDComplexity;
    }

    BltInfo.DestSurface = psoDest;
    BltInfo.SourceSurface = psoSource;
    BltInfo.PatternSurface = NULL;
    BltInfo.XlateSourceToDest = ColorTranslation;
    BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY);

    switch (clippingType)
    {
    case DC_TRIVIAL:
        BltInfo.DestRect = *DestRect;
        BltInfo.SourcePoint = *SourcePoint;

        ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
        break;

    case DC_RECT:
        // Clip the blt to the clip rectangle
        RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);

        BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
        BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top  - DestRect->top;

        ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
        break;

    case DC_COMPLEX:

        CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);

        do
        {
            EnumMore = CLIPOBJ_bEnum(Clip,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);

            if (RectEnum.c > 0)
            {
                RECTL* prclEnd = &RectEnum.arcl[RectEnum.c];
                RECTL* prcl    = &RectEnum.arcl[0];

                do
                {
                    RECTL_bIntersectRect(&BltInfo.DestRect, prcl, DestRect);

                    BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
                    BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;

                    if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
                    {
                        ret = FALSE;
                        goto cleanup;
                    }

                    prcl++;

                } while (prcl < prclEnd);
            }

        } while (EnumMore);
        ret = TRUE;
        break;

    default:
        ASSERT(FALSE);
        ret = FALSE;
        break;
    }

cleanup:
    return ret;
}
예제 #15
0
/*
 * @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 ROP4 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;

    if (Rop4 == ROP4_NOOP)
    {
        /* Copy destination onto itself: nop */
        return TRUE;
    }


    /* Determine clipping type */
    if (ClipRegion == (CLIPOBJ *) NULL)
    {
        clippingType = DC_TRIVIAL;
    }
    else
    {
        clippingType = ClipRegion->iDComplexity;
    }

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

    if (UsesSource)
    {
        if (NULL == prclSrc)
        {
            return FALSE;
        }
        InputRect = *prclSrc;

        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;
    }
    else
    {
        InputRect.left = 0;
        InputRect.right = OutputRect.right - OutputRect.left;
        InputRect.top = 0;
        InputRect.bottom = OutputRect.bottom - OutputRect.top;
        psoInput = NULL;
    }

    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;
}
예제 #16
0
파일: textout.c 프로젝트: mingpen/OpenNT
VOID vClipSolid(
PDEV*       ppdev,
LONG        crcl,
RECTL*      prcl,
ULONG       iColor,
CLIPOBJ*    pco)
{
    BOOL            bMore;              // Flag for clip enumeration
    CLIPENUM        ce;                 // Clip enumeration object
    ULONG           i;
    ULONG           j;
    RECTL           arclTmp[4];
    ULONG           crclTmp;
    RECTL*          prclTmp;
    RECTL*          prclClipTmp;
    LONG            iLastBottom;
    RECTL*          prclClip;
    RBRUSH_COLOR    rbc;

    ASSERTDD((crcl > 0) && (crcl <= 4), "Expected 1 to 4 rectangles");
    ASSERTDD((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL),
                       "Expected a non-null clip object");

    rbc.iSolidColor = iColor;
    if (pco->iDComplexity == DC_RECT)
    {
        crcl = cIntersect(&pco->rclBounds, prcl, crcl);
        if (crcl != 0)
        {
            (ppdev->pfnFillSolid)(ppdev, crcl, prcl, OVERPAINT, OVERPAINT,
                                  rbc, NULL);
        }
    }
    else // iDComplexity == DC_COMPLEX
    {
        // Bottom of last rectangle to fill

        iLastBottom = prcl[crcl - 1].bottom;

        // Initialize the clip rectangle enumeration to right-down so we can
        // take advantage of the rectangle list being right-down:

        CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);

        // Scan through all the clip rectangles, looking for intersects
        // of fill areas with region rectangles:

        do {
            // Get a batch of region rectangles:

            bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*)&ce);

            // Clip the rect list to each region rect:

            for (j = ce.c, prclClip = ce.arcl; j-- > 0; prclClip++)
            {
                // Since the rectangles and the region enumeration are both
                // right-down, we can zip through the region until we reach
                // the first fill rect, and are done when we've passed the
                // last fill rect.

                if (prclClip->top >= iLastBottom)
                {
                    // Past last fill rectangle; nothing left to do:

                    return;
                }

                // Do intersection tests only if we've reached the top of
                // the first rectangle to fill:

                if (prclClip->bottom > prcl->top)
                {
                    // We've reached the top Y scan of the first rect, so
                    // it's worth bothering checking for intersection.

                    // Generate a list of the rects clipped to this region
                    // rect:

                    prclTmp     = prcl;
                    prclClipTmp = arclTmp;

                    for (i = crcl, crclTmp = 0; i-- != 0; prclTmp++)
                    {
                        // Intersect fill and clip rectangles

                        if (bIntersect(prclTmp, prclClip, prclClipTmp))
                        {
                            // Add to list if anything's left to draw:

                            crclTmp++;
                            prclClipTmp++;
                        }
                    }

                    // Draw the clipped rects

                    if (crclTmp != 0)
                    {
                        (ppdev->pfnFillSolid)(ppdev, crclTmp, &arclTmp[0],
                                             OVERPAINT, OVERPAINT, rbc, NULL);
                    }
                }
            }
        } while (bMore);
    }
}
예제 #17
0
파일: gradient.c 프로젝트: Moteesh/reactos
BOOL
FASTCALL
IntEngGradientFillTriangle(
    IN SURFOBJ  *psoDest,
    IN CLIPOBJ  *pco,
    IN XLATEOBJ  *pxlo,
    IN TRIVERTEX  *pVertex,
    IN ULONG  nVertex,
    IN PGRADIENT_TRIANGLE gTriangle,
    IN RECTL  *prclExtents,
    IN POINTL  *pptlDitherOrg)
{
    SURFOBJ *psoOutput;
    PTRIVERTEX v1, v2, v3;
    RECT_ENUM RectEnum;
    BOOL EnumMore;
    ULONG i;
    POINTL Translate;
    INTENG_ENTER_LEAVE EnterLeave;
    RECTL FillRect = { 0, 0, 0, 0 };
    ULONG Color;

    BOOL sx[NLINES];
    LONG x[NLINES], dx[NLINES], dy[NLINES], incx[NLINES], ex[NLINES], destx[NLINES];
    LONG c[NLINES][3], dc[NLINES][3], ec[NLINES][3], ic[NLINES][3]; /* colors on lines */
    LONG g, gx, gxi, gc[3], gd[3], ge[3], gi[3]; /* colors in triangle */
    LONG sy, y, bt;

    v1 = (pVertex + gTriangle->Vertex1);
    v2 = (pVertex + gTriangle->Vertex2);
    v3 = (pVertex + gTriangle->Vertex3);

    /* bubble sort */
    if (SMALLER(v2, v1))
    {
        TRIVERTEX *t;
        SWAP(v1, v2, t);
    }

    if (SMALLER(v3, v2))
    {
        TRIVERTEX *t;
        SWAP(v2, v3, t);
        if (SMALLER(v2, v1))
        {
            SWAP(v1, v2, t);
        }
    }

    DPRINT("Triangle: (%i,%i) (%i,%i) (%i,%i)\n", v1->x, v1->y, v2->x, v2->y, v3->x, v3->y);
    /* FIXME: commented out because of an endless loop - fix triangles first */
    DPRINT("FIXME: IntEngGradientFillTriangle is broken\n");

    if (!IntEngEnter(&EnterLeave, psoDest, &FillRect, FALSE, &Translate, &psoOutput))
    {
        return FALSE;
    }

    if (VCMPCLRS(v1, v2, v3))
    {
      CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
      do
      {
        EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
        for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++)
        {
          if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents))
          {
            BOOL InY;

            DOINIT(v1, v3, 0);
            DOINIT(v1, v2, 1);
            DOINIT(v2, v3, 2);

            y = v1->y;
            sy = v1->y + pptlDitherOrg->y;
            bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom);

            while (sy < bt)
            {
              InY = !(sy < FillRect.top || sy >= FillRect.bottom);
              GOLINE(v1, v3, 0);
              DOLINE(v1, v3, 0);
              ENDLINE(v1, v3, 0);

              GOLINE(v1, v2, 1);
              DOLINE(v1, v2, 1);
              FILLLINE(0, 1);
              ENDLINE(v1, v2, 1);

              GOLINE(v2, v3, 2);
              DOLINE(v2, v3, 2);
              FILLLINE(0, 2);
              ENDLINE(23, v3, 2);

              y++;
              sy++;
            }
          }
        }
      } while (EnumMore);

      return IntEngLeave(&EnterLeave);
    }

    /* fill triangle with one solid color */

    Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red >> 8, v1->Green >> 8, v1->Blue >> 8));
    CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
    do
    {
      EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
      for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++)
      {
        if (RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents))
        {
          S_INITLINE(v1, v3, 0);
          S_INITLINE(v1, v2, 1);
          S_INITLINE(v2, v3, 2);

          y = v1->y;
          sy = v1->y + pptlDitherOrg->y;
          bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom);

          while (sy < bt)
          {
            S_GOLINE(v1, v3, 0);
            S_DOLINE(v1, v3, 0);
            S_ENDLINE(v1, v3, 0);

            S_GOLINE(v1, v2, 1);
            S_DOLINE(v1, v2, 1);
            S_FILLLINE(0, 1);
            S_ENDLINE(v1, v2, 1);

            S_GOLINE(v2, v3, 2);
            S_DOLINE(v2, v3, 2);
            S_FILLLINE(0, 2);
            S_ENDLINE(23, v3, 2);

            y++;
            sy++;
          }
        }
      }
    } while (EnumMore);

    return IntEngLeave(&EnterLeave);
}