Пример #1
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;
}
Пример #2
0
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;
}
Пример #3
0
BOOL
FASTCALL
IntEngTransparentBlt(
    SURFOBJ *psoDest,
    SURFOBJ *psoSource,
    CLIPOBJ *Clip,
    XLATEOBJ *ColorTranslation,
    PRECTL DestRect,
    PRECTL SourceRect,
    ULONG iTransColor,
    ULONG Reserved)
{
    BOOL Ret;
    RECTL OutputRect, InputClippedRect;
    SURFACE *psurfDest;
    SURFACE *psurfSource;
    RECTL InputRect;
    LONG InputClWidth, InputClHeight, InputWidth, InputHeight;

    ASSERT(psoDest);
    ASSERT(psoSource);
    ASSERT(DestRect);

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

    ASSERT(psurfDest);
    ASSERT(psurfSource);

    /* If no clip object is given, use trivial one */
    if (!Clip) Clip = &gxcoTrivial.ClipObj;

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

    InputRect = *SourceRect;
    /* Clip against the bounds of the clipping region so we won't try to write
     * outside the surface */
    if (Clip->iDComplexity != DC_TRIVIAL)
    {
        if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
        {
            return TRUE;
        }
        /* Update source rect */
        InputClWidth = InputClippedRect.right - InputClippedRect.left;
        InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
        InputWidth = InputRect.right - InputRect.left;
        InputHeight = InputRect.bottom - InputRect.top;

        InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth;
        InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth;
        InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight;
        InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight;
    }
    else
    {
        OutputRect = InputClippedRect;
    }

    if (psurfDest->flags & HOOK_TRANSPARENTBLT)
    {
        Ret = GDIDEVFUNCS(psoDest).TransparentBlt(psoDest,
                                                  psoSource,
                                                  Clip,
                                                  ColorTranslation,
                                                  &OutputRect,
                                                  &InputRect,
                                                  iTransColor,
                                                  Reserved);
    }
    else
        Ret = FALSE;

    if (!Ret)
    {
        Ret = EngTransparentBlt(psoDest,
                                psoSource,
                                Clip,
                                ColorTranslation,
                                &OutputRect,
                                &InputRect,
                                iTransColor,
                                Reserved);
    }

    return Ret;
}
Пример #4
0
/* IntGetMonitorsFromRect
 *
 * Returns a list of monitor handles/rectangles. The rectangles in the list are
 * the areas of intersection with the monitors.
 *
 * Arguments
 *
 *   pRect
 *      Rectangle in desktop coordinates. If this is NULL all monitors are
 *      returned and the rect list is filled with the sizes of the monitors.
 *
 *   phMonitorList
 *      Pointer to an array of HMONITOR which is filled with monitor handles.
 *      Can be NULL
 *
 *   prcMonitorList
 *      Pointer to an array of RECT which is filled with intersection rects in
 *      desktop coordinates.
 *      Can be NULL, will be ignored if no intersecting monitor is found and
 *      flags is MONITOR_DEFAULTTONEAREST
 *
 *   dwListSize
 *      Size of the phMonitorList and prcMonitorList arguments. If this is zero
 *      phMonitorList and prcMonitorList are ignored.
 *
 *   dwFlags
 *      Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
 *
 * Returns
 *   The number of monitors which intersect the specified region.
 */
static
UINT
IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
                       OPTIONAL OUT HMONITOR *phMonitorList,
                       OPTIONAL OUT PRECTL prcMonitorList,
                       OPTIONAL IN DWORD dwListSize,
                       OPTIONAL IN DWORD dwFlags)
{
    PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL;
    UINT cMonitors = 0;
    ULONG iNearestDistance = 0xffffffff;

    /* Find monitors which intersects the rectangle */
    for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
    {
        RECTL MonitorRect, IntersectionRect;

        MonitorRect = pMonitor->rcMonitor;

        TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
               MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);

        /* Save primary monitor for later usage */
        if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary)
            pPrimaryMonitor = pMonitor;

        /* Check if a rect is given */
        if (pRect == NULL)
        {
            /* No rect given, so use the full monitor rect */
            IntersectionRect = MonitorRect;
        }
        /* We have a rect, calculate intersection */
        else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect))
        {
            /* Rects did not intersect */
            if (dwFlags == MONITOR_DEFAULTTONEAREST)
            {
                ULONG cx, cy, iDistance;

                /* Get x and y distance */
                cx = min(abs(MonitorRect.left - pRect->right),
                         abs(pRect->left - MonitorRect.right));
                cy = min(abs(MonitorRect.top - pRect->bottom),
                         abs(pRect->top - MonitorRect.bottom));

                /* Calculate distance square */
                iDistance = cx * cx + cy * cy;

                /* Check if this is the new nearest monitor */
                if (iDistance < iNearestDistance)
                {
                    iNearestDistance = iDistance;
                    pNearestMonitor = pMonitor;
                }
            }

            continue;
        }

        /* Check if there's space in the buffer */
        if (cMonitors < dwListSize)
        {
            /* Save monitor data */
            if (phMonitorList != NULL)
                phMonitorList[cMonitors] = UserHMGetHandle(pMonitor);
            if (prcMonitorList != NULL)
                prcMonitorList[cMonitors] = IntersectionRect;
        }

        /* Increase count of found monitors */
        cMonitors++;
    }

    /* Nothing has been found? */
    if (cMonitors == 0)
    {
        /* Check if we shall default to the nearest monitor */
        if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor)
        {
            if (phMonitorList && dwListSize > 0)
                phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor);
            cMonitors++;
        }
        /* Check if we shall default to the primary monitor */
        else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor)
        {
            if (phMonitorList != NULL && dwListSize > 0)
                phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor);
            cMonitors++;
        }
    }

    return cMonitors;
}
Пример #5
0
/* IntGetMonitorsFromRect
 *
 * Returns a list of monitor handles/rectangles. The rectangles in the list are
 * the areas of intersection with the monitors.
 *
 * Arguments
 *
 *   pRect
 *      Rectangle in desktop coordinates. If this is NULL all monitors are
 *      returned and the rect list is filled with the sizes of the monitors.
 *
 *   hMonitorList
 *      Pointer to an array of HMONITOR which is filled with monitor handles.
 *      Can be NULL
 *
 *   monitorRectList
 *      Pointer to an array of RECT which is filled with intersection rects in
 *      desktop coordinates.
 *      Can be NULL, will be ignored if no intersecting monitor is found and
 *      flags is MONITOR_DEFAULTTONEAREST
 *
 *   listSize
 *      Size of the hMonitorList and monitorRectList arguments. If this is zero
 *      hMonitorList and monitorRectList are ignored.
 *
 *   flags
 *      Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
 *
 * Returns
 *   The number of monitors which intersect the specified region.
 */
static
UINT
IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
                       OPTIONAL OUT HMONITOR *hMonitorList,
                       OPTIONAL OUT PRECTL monitorRectList,
                       OPTIONAL IN DWORD listSize,
                       OPTIONAL IN DWORD flags)
{
    PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL;
    UINT iCount = 0;
    ULONG iNearestDistance = 0xffffffff;

    /* Find monitors which intersect the rectangle */
    for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next)
    {
        RECTL MonitorRect, IntersectionRect;

        ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock);
        MonitorRect = Monitor->rcMonitor;
        ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock);

        TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
               MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);

        if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary)
        {
            PrimaryMonitor = Monitor;
        }

        /* Check if a rect is given */
        if (pRect == NULL)
        {
            /* No rect given, so use the full monitor rect */
            IntersectionRect = MonitorRect;
        }

        /* We have a rect, calculate intersection */
        else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect))
        {
            /* Rects did not intersect */
            if (flags == MONITOR_DEFAULTTONEAREST)
            {
                ULONG cx, cy, iDistance;

                /* Get x and y distance */
                cx = min(abs(MonitorRect.left - pRect->right),
                         abs(pRect->left - MonitorRect.right));
                cy = min(abs(MonitorRect.top - pRect->bottom),
                         abs(pRect->top - MonitorRect.bottom));

                /* Calculate distance square */
                iDistance = cx * cx + cy * cy;

                /* Check if this is the new nearest monitor */
                if (iDistance < iNearestDistance)
                {
                    iNearestDistance = iDistance;
                    NearestMonitor = Monitor;
                }
            }

            continue;
        }

        /* Check if there's space in the buffer */
        if (iCount < listSize)
        {
            if (hMonitorList != NULL)
                hMonitorList[iCount] = UserHMGetHandle(Monitor);
            if (monitorRectList != NULL)
                monitorRectList[iCount] = IntersectionRect;
        }

        /* Increase count of found monitors */
        iCount++;
    }

    /* Found nothing intersecting? */
    if (iCount == 0)
    {
        /* Check if we shall default to the nearest monitor */
        if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor)
        {
            if (hMonitorList && listSize > 0)
                hMonitorList[iCount] = UserHMGetHandle(NearestMonitor);
            iCount++;
        }
        /* Check if we shall default to the primary monitor */
        else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor)
        {
            if (hMonitorList != NULL && listSize > 0)
                hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor);
            iCount++;
        }
    }

    return iCount;
}
Пример #6
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);
}
Пример #7
0
/*
 * @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;
}
Пример #8
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;
}
Пример #9
0
BOOL APIENTRY
IntEngStretchBlt(SURFOBJ *psoDest,
                 SURFOBJ *psoSource,
                 SURFOBJ *MaskSurf,
                 CLIPOBJ *ClipRegion,
                 XLATEOBJ *ColorTranslation,
                 COLORADJUSTMENT *pca,
                 RECTL *DestRect,
                 RECTL *SourceRect,
                 POINTL *pMaskOrigin,
                 BRUSHOBJ *pbo,
                 POINTL *BrushOrigin,
                 DWORD Rop4)
{
    BOOLEAN ret;
    POINTL MaskOrigin = {0, 0};
    SURFACE *psurfDest;
    //SURFACE *psurfSource = NULL;
    RECTL InputClippedRect;
    RECTL InputRect;
    RECTL OutputRect;
    BOOL UsesSource = ROP4_USES_SOURCE(Rop4);
    LONG InputClWidth, InputClHeight, InputWidth, InputHeight;

    ASSERT(psoDest);
    //ASSERT(psoSource); // FIXME!
    ASSERT(DestRect);
    //ASSERT(SourceRect); // FIXME!
    //ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME!

    /* If no clip object is given, use trivial one */
    if (!ClipRegion) ClipRegion = &gxcoTrivial.ClipObj;

    psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);

    /* Sanity check */
    ASSERT(IS_VALID_ROP4(Rop4));

    /* Check if source and dest size are equal */
    if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) &&
        ((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top)))
    {
        /* Pass the request to IntEngBitBlt */
        return IntEngBitBlt(psoDest,
                            psoSource,
                            MaskSurf,
                            ClipRegion,
                            ColorTranslation,
                            DestRect,
                            (PPOINTL)SourceRect,
                            pMaskOrigin,
                            pbo,
                            BrushOrigin,
                            Rop4);
    }

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

    if (NULL == SourceRect || NULL == psoSource)
    {
        return FALSE;
    }
    InputRect = *SourceRect;

    if (InputRect.right < InputRect.left ||
            InputRect.bottom < InputRect.top)
    {
        /* Everything clipped away, nothing to do */
        return TRUE;
    }

    if (ClipRegion->iDComplexity != DC_TRIVIAL)
    {
        if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect,
                               &ClipRegion->rclBounds))
        {
            return TRUE;
        }
        /* Update source rect */
        InputClWidth = InputClippedRect.right - InputClippedRect.left;
        InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
        InputWidth = InputRect.right - InputRect.left;
        InputHeight = InputRect.bottom - InputRect.top;

        InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) / InputClWidth;
        InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) / InputClWidth;
        InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) / InputClHeight;
        InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom)) / InputClHeight;
    }
    else
    {
        OutputRect = InputClippedRect;
    }

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

    /* No success yet */
    ret = FALSE;

    if (UsesSource)
    {
        //psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
    }

    /* Call the driver's DrvStretchBlt if available */
    if (psurfDest->flags & HOOK_STRETCHBLTROP)
    {
        /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
        ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
                                                 psoSource,
                                                 MaskSurf,
                                                 ClipRegion,
                                                 ColorTranslation,
                                                 pca,
                                                 BrushOrigin,
                                                 &OutputRect,
                                                 &InputRect,
                                                 &MaskOrigin,
                                                 COLORONCOLOR,
                                                 pbo,
                                                 Rop4);
    }

    if (! ret)
    {
        ret = EngStretchBltROP(psoDest,
                               psoSource,
                               MaskSurf,
                               ClipRegion,
                               ColorTranslation,
                               pca,
                               BrushOrigin,
                               &OutputRect,
                               &InputRect,
                               &MaskOrigin,
                               COLORONCOLOR,
                               pbo,
                               Rop4);
    }

    return ret;
}
Пример #10
0
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);
}