예제 #1
0
파일: dcutil.c 프로젝트: Moteesh/reactos
COLORREF
FASTCALL
IntGdiSetTextColor(HDC hDC,
                   COLORREF color)
{
    COLORREF crOldColor;
    PDC pdc;
    PDC_ATTR pdcattr;

    pdc = DC_LockDc(hDC);
    if (!pdc)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        return CLR_INVALID;
    }
    pdcattr = pdc->pdcattr;

    crOldColor = (COLORREF) pdcattr->ulForegroundClr;
    pdcattr->ulForegroundClr = (ULONG)color;

    if (pdcattr->crForegroundClr != color)
    {
        pdcattr->ulDirty_ |= (DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL);
        pdcattr->crForegroundClr = color;
    }

    DC_vUpdateTextBrush(pdc);
    DC_vUpdateLineBrush(pdc);
    DC_vUpdateFillBrush(pdc);

    DC_UnlockDc(pdc);

    return  crOldColor;
}
예제 #2
0
 /*
 * @implemented
 */
HBRUSH
APIENTRY
NtGdiSelectBrush(
    IN HDC hDC,
    IN HBRUSH hBrush)
{
    PDC pDC;
    HBRUSH hOrgBrush;

    if (hDC == NULL || hBrush == NULL) return NULL;

    pDC = DC_LockDc(hDC);
    if (!pDC)
    {
        return NULL;
    }

    /* Simply return the user mode value, without checking */
    hOrgBrush = pDC->pdcattr->hbrush;
    pDC->pdcattr->hbrush = hBrush;
    DC_vUpdateFillBrush(pDC);

    DC_UnlockDc(pDC);

    return hOrgBrush;
}
예제 #3
0
BOOL
APIENTRY
NtGdiArcInternal(
        ARCTYPE arctype,
        HDC  hDC,
        int  LeftRect,
        int  TopRect,
        int  RightRect,
        int  BottomRect,
        int  XStartArc,
        int  YStartArc,
        int  XEndArc,
        int  YEndArc)
{
  DC *dc;
  BOOL Ret;
  KFLOATING_SAVE FloatSave;

  dc = DC_LockDc (hDC);
  if(!dc)
  {
    EngSetLastError(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if (dc->dctype == DC_TYPE_INFO)
  {
    DC_UnlockDc(dc);
    /* Yes, Windows really returns TRUE in this case */
    return TRUE;
  }

  DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
                            NULL, dc->rosdc.CombinedClip->rclBounds);

  if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
    DC_vUpdateFillBrush(dc);

  if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
    DC_vUpdateLineBrush(dc);

  KeSaveFloatingPointState(&FloatSave);

  Ret = IntGdiArcInternal(
                  arctype,
                  dc,
                  LeftRect,
                  TopRect,
                  RightRect,
                  BottomRect,
                  XStartArc,
                  YStartArc,
                  XEndArc,
                  YEndArc);

  KeRestoreFloatingPointState(&FloatSave);
  DC_vFinishBlit(dc, NULL);
  DC_UnlockDc( dc );
  return Ret;
}
예제 #4
0
BOOL APIENTRY
NtGdiPatBlt(
    HDC hDC,
    INT XLeft,
    INT YLeft,
    INT Width,
    INT Height,
    DWORD ROP)
{
    PBRUSH pbrush;
    DC *dc;
    PDC_ATTR pdcattr;
    BOOL ret;

    BOOL UsesSource = ROP_USES_SOURCE(ROP);
    if (UsesSource)
    {
        /* In this case we call on GdiMaskBlt */
        return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0);
    }

    dc = DC_LockDc(hDC);
    if (dc == NULL)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }
    if (dc->dctype == DC_TYPE_INFO)
    {
        DC_UnlockDc(dc);
        DPRINT1("NtGdiPatBlt on info DC!\n");
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
    }

    pdcattr = dc->pdcattr;

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    pbrush = BRUSH_ShareLockBrush(pdcattr->hbrush);
    if (pbrush == NULL)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        DC_UnlockDc(dc);
        return FALSE;
    }

    ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush);

    BRUSH_ShareUnlockBrush(pbrush);
    DC_UnlockDc(dc);

    return ret;
}
예제 #5
0
BOOL
APIENTRY
NtGdiPatBlt(
    _In_ HDC hdcDest,
    _In_ INT x,
    _In_ INT y,
    _In_ INT cx,
    _In_ INT cy,
    _In_ DWORD dwRop)
{
    BOOL bResult;
    PDC pdc;

    /* Mask away everything except foreground rop index */
    dwRop = dwRop & 0x00FF0000;
    dwRop |= dwRop << 8;

    /* Check if the rop uses a source */
    if (ROP_USES_SOURCE(dwRop))
    {
        /* This is not possible */
        return 0;
    }

    /* Lock the DC */
    pdc = DC_LockDc(hdcDest);
    if (pdc == NULL)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }

    /* Check if the DC has no surface (empty mem or info DC) */
    if (pdc->dclevel.pSurface == NULL)
    {
        /* Nothing to do, Windows returns TRUE! */
        DC_UnlockDc(pdc);
        return TRUE;
    }

    /* Update the fill brush, if necessary */
    if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(pdc);

    /* Call the internal function */
    bResult = IntPatBlt(pdc, x, y, cx, cy, dwRop, &pdc->eboFill);

    /* Unlock the DC and return the result */
    DC_UnlockDc(pdc);
    return bResult;
}
예제 #6
0
파일: dcstate.c 프로젝트: Moteesh/reactos
BOOL
FASTCALL
IntGdiCleanDC(HDC hDC)
{
    PDC dc;
    if (!hDC) return FALSE;
    dc = DC_LockDc(hDC);
    if (!dc) return FALSE;
    // Clean the DC
    if (defaultDCstate)
    {
        DC_vCopyState(defaultDCstate, dc, FALSE);
        /* Update the brushes now, because they reference some objects (the DC palette)
         * Which belong to the current process, and this DC might be used for another process
         * after being cleaned up (for GetDC(0) for instance) */
        DC_vUpdateFillBrush(dc);
        DC_vUpdateBackgroundBrush(dc);
        DC_vUpdateLineBrush(dc);
        DC_vUpdateTextBrush(dc);
    }

    // Remove Path and reset flags.
    if (dc->dclevel.hPath)
    {
        DPRINT("Clean DC Remove Path\n");
        if (!PATH_Delete(dc->dclevel.hPath))
        {
           DPRINT1("Failed to remove Path\n");
        }
        dc->dclevel.hPath = 0;
        dc->dclevel.flPath = 0;
    }

    /* DC_vCopyState frees the Clip rgn and the Meta rgn. Take care of the other ones
     * There is no need to clear prgnVis, as UserGetDC updates it immediately. */
    if (dc->prgnRao)
        REGION_Delete(dc->prgnRao);
    if (dc->prgnAPI)
        REGION_Delete(dc->prgnAPI);
    dc->prgnRao = dc->prgnAPI = NULL;

    dc->fs |= DC_FLAG_DIRTY_RAO;

    DC_UnlockDc(dc);

    return TRUE;
}
예제 #7
0
BOOL
APIENTRY
NtGdiAngleArc(
    IN HDC hDC,
    IN INT x,
    IN INT y,
    IN DWORD dwRadius,
    IN DWORD dwStartAngle,
    IN DWORD dwSweepAngle)
{
  DC *pDC;
  BOOL Ret = FALSE;
  gxf_long worker, worker1;
  KFLOATING_SAVE FloatSave;

  pDC = DC_LockDc (hDC);
  if(!pDC)
  {
    EngSetLastError(ERROR_INVALID_HANDLE);
    return FALSE;
  }
  if (pDC->dctype == DC_TYPE_INFO)
  {
    DC_UnlockDc(pDC);
    /* Yes, Windows really returns TRUE in this case */
    return TRUE;
  }

  KeSaveFloatingPointState(&FloatSave);

  worker.l  = dwStartAngle;
  worker1.l = dwSweepAngle;
  DC_vPrepareDCsForBlit(pDC, pDC->rosdc.CombinedClip->rclBounds,
                           NULL, pDC->rosdc.CombinedClip->rclBounds);
  if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
    DC_vUpdateFillBrush(pDC);
  if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
    DC_vUpdateLineBrush(pDC);
  Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
  DC_vFinishBlit(pDC, NULL);
  DC_UnlockDc( pDC );

  KeRestoreFloatingPointState(&FloatSave);

  return Ret;
}
예제 #8
0
ULONG_PTR
APIENTRY
NtGdiPolyPolyDraw( IN HDC hDC,
                   IN PPOINT UnsafePoints,
                   IN PULONG UnsafeCounts,
                   IN ULONG Count,
                   IN INT iFunc )
{
    DC *dc;
    PVOID pTemp;
    LPPOINT SafePoints;
    PULONG SafeCounts;
    NTSTATUS Status = STATUS_SUCCESS;
    BOOL Ret = TRUE;
    ULONG nPoints = 0, nMaxPoints = 0, nInvalid = 0, i;

    if (!UnsafePoints || !UnsafeCounts ||
        Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn)
    {
        /* Windows doesn't set last error */
        return FALSE;
    }

    _SEH2_TRY
    {
        ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
        ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);

        /* Count points and validate poligons */
        for (i = 0; i < Count; i++)
        {
            if (UnsafeCounts[i] < 2)
            {
                nInvalid++;
            }
            nPoints += UnsafeCounts[i];
            nMaxPoints = max(nMaxPoints, UnsafeCounts[i]);
        }
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        Status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;

    if (!NT_SUCCESS(Status))
    {
        /* Windows doesn't set last error */
        return FALSE;
    }

    if (nPoints == 0 || nPoints < nMaxPoints)
    {
        /* If all polygon counts are zero, or we have overflow,
           return without setting a last error code. */
        return FALSE;
    }

    if (nInvalid != 0)
    {
        /* If at least one poly count is 0 or 1, fail */
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    /* Allocate one buffer for both counts and points */
    pTemp = ExAllocatePoolWithTag(PagedPool,
                                  Count * sizeof(ULONG) + nPoints * sizeof(POINT),
                                  TAG_SHAPE);
    if (!pTemp)
    {
        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }

    SafeCounts = pTemp;
    SafePoints = (PVOID)(SafeCounts + Count);

    _SEH2_TRY
    {
        /* Pointers already probed! */
        RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG));
        RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        Status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;

    if (!NT_SUCCESS(Status))
    {
        ExFreePoolWithTag(pTemp, TAG_SHAPE);
        return FALSE;
    }

    /* Special handling for GdiPolyPolyRgn */
    if (iFunc == GdiPolyPolyRgn)
    {
        HRGN hRgn;
        hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC);
        ExFreePoolWithTag(pTemp, TAG_SHAPE);
        return (ULONG_PTR)hRgn;
    }

    dc = DC_LockDc(hDC);
    if (!dc)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        ExFreePoolWithTag(pTemp, TAG_SHAPE);
        return FALSE;
    }

    if (dc->dctype == DC_TYPE_INFO)
    {
        DC_UnlockDc(dc);
        ExFreePoolWithTag(pTemp, TAG_SHAPE);
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
    }

    DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
                            NULL, dc->rosdc.CombinedClip->rclBounds);

    if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(dc);

    /* Perform the actual work */
    switch (iFunc)
    {
        case GdiPolyPolygon:
            Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count);
            break;
        case GdiPolyPolyLine:
            Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count);
            break;
        case GdiPolyBezier:
            Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts);
            break;
        case GdiPolyLineTo:
            Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts);
            break;
        case GdiPolyBezierTo:
            Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
            break;
        default:
            EngSetLastError(ERROR_INVALID_PARAMETER);
            Ret = FALSE;
    }

    /* Cleanup and return */
    DC_vFinishBlit(dc, NULL);
    DC_UnlockDc(dc);
    ExFreePoolWithTag(pTemp, TAG_SHAPE);

    return (ULONG_PTR)Ret;
}
예제 #9
0
BOOL APIENTRY
NtGdiEllipse(
    HDC hDC,
    int Left,
    int Top,
    int Right,
    int Bottom)
{
    PDC dc;
    PDC_ATTR pdcattr;
    RECTL RectBounds;
    PBRUSH pbrush;
    BOOL ret = TRUE;
    LONG PenWidth, PenOrigWidth;
    LONG RadiusX, RadiusY, CenterX, CenterY;
    PBRUSH pFillBrushObj;
    BRUSH tmpFillBrushObj;

    if ((Left == Right) || (Top == Bottom)) return TRUE;

    dc = DC_LockDc(hDC);
    if (dc == NULL)
    {
       EngSetLastError(ERROR_INVALID_HANDLE);
       return FALSE;
    }
    if (dc->dctype == DC_TYPE_INFO)
    {
       DC_UnlockDc(dc);
       /* Yes, Windows really returns TRUE in this case */
       return TRUE;
    }

    if (PATH_IsPathOpen(dc->dclevel))
    {
        ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
        DC_UnlockDc(dc);
        return ret;
    }

    if (Right < Left)
    {
       INT tmp = Right; Right = Left; Left = tmp;
    }
    if (Bottom < Top)
    {
       INT tmp = Bottom; Bottom = Top; Top = tmp;
    }

    pdcattr = dc->pdcattr;

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(dc);

    pbrush = PEN_ShareLockPen(pdcattr->hpen);
    if (!pbrush)
    {
        DPRINT1("Ellipse Fail 1\n");
        DC_UnlockDc(dc);
        EngSetLastError(ERROR_INTERNAL_ERROR);
        return FALSE;
    }

    PenOrigWidth = PenWidth = pbrush->ptPenWidth.x;
    if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0;

    if (pbrush->ulPenStyle == PS_INSIDEFRAME)
    {
       if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
       if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
       Left   += PenWidth / 2;
       Right  -= (PenWidth - 1) / 2;
       Top    += PenWidth / 2;
       Bottom -= (PenWidth - 1) / 2;
    }

    if (!PenWidth) PenWidth = 1;
    pbrush->ptPenWidth.x = PenWidth;

    RectBounds.left   = Left;
    RectBounds.right  = Right;
    RectBounds.top    = Top;
    RectBounds.bottom = Bottom;

    IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);

    RectBounds.left += dc->ptlDCOrig.x;
    RectBounds.right += dc->ptlDCOrig.x;
    RectBounds.top += dc->ptlDCOrig.y;
    RectBounds.bottom += dc->ptlDCOrig.y;

    // Setup for dynamic width and height.
    RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room
    RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2);
    CenterX = (RectBounds.right + RectBounds.left) / 2;
    CenterY = (RectBounds.bottom + RectBounds.top) / 2;

    DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
               RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);

    DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
               CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);

    pFillBrushObj = BRUSH_ShareLockBrush(pdcattr->hbrush);
    if (NULL == pFillBrushObj)
    {
        DPRINT1("FillEllipse Fail\n");
        EngSetLastError(ERROR_INTERNAL_ERROR);
        ret = FALSE;
    }
    else
    {
        RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj));
        //tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left;
        //tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top;
        tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x;
        tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y;

        DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds);

        ret = IntFillEllipse( dc,
                              CenterX - RadiusX,
                              CenterY - RadiusY,
                              RadiusX*2, // Width
                              RadiusY*2, // Height
                              &tmpFillBrushObj);
        BRUSH_ShareUnlockBrush(pFillBrushObj);

        if (ret)
        {
           ret = IntDrawEllipse( dc,
                                 CenterX - RadiusX,
                                 CenterY - RadiusY,
                                 RadiusX*2, // Width
                                 RadiusY*2, // Height
                                 pbrush);
        }

        DC_vFinishBlit(dc, NULL);
    }

    pbrush->ptPenWidth.x = PenOrigWidth;
    PEN_ShareUnlockPen(pbrush);
    DC_UnlockDc(dc);
    DPRINT("Ellipse Exit.\n");
    return ret;
}
예제 #10
0
BOOL FASTCALL
IntGdiPolygon(PDC    dc,
              PPOINT Points,
              int    Count)
{
    SURFACE *psurf;
    PBRUSH pbrLine, pbrFill;
    BOOL ret = FALSE; // Default to failure
    RECTL DestRect;
    int CurrentPoint;
    PDC_ATTR pdcattr;
    POINTL BrushOrigin;
//    int Left;
//    int Top;

    ASSERT(dc); // Caller's responsibility to pass a valid dc

    if (!Points || Count < 2 )
    {
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

/*
    // Find start x, y
    Left = Points[0].x;
    Top  = Points[0].y;
    for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) {
      Left = min(Left, Points[CurrentPoint].x);
      Top  = min(Top, Points[CurrentPoint].y);
    }
*/

    pdcattr = dc->pdcattr;

    /* Convert to screen coordinates */
    IntLPtoDP(dc, Points, Count);
    for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
    {
        Points[CurrentPoint].x += dc->ptlDCOrig.x;
        Points[CurrentPoint].y += dc->ptlDCOrig.y;
    }
    // No need to have path here.
    {
        DestRect.left   = Points[0].x;
        DestRect.right  = Points[0].x;
        DestRect.top    = Points[0].y;
        DestRect.bottom = Points[0].y;

        for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
        {
            DestRect.left     = min(DestRect.left, Points[CurrentPoint].x);
            DestRect.right    = max(DestRect.right, Points[CurrentPoint].x);
            DestRect.top      = min(DestRect.top, Points[CurrentPoint].y);
            DestRect.bottom   = max(DestRect.bottom, Points[CurrentPoint].y);
        }

        if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
            DC_vUpdateFillBrush(dc);

        if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
            DC_vUpdateLineBrush(dc);

        /* Special locking order to avoid lock-ups */
        pbrFill = dc->dclevel.pbrFill;
        pbrLine = dc->dclevel.pbrLine;
        psurf = dc->dclevel.pSurface;
        /* FIXME: psurf can be NULL!!!! don't assert but handle this case gracefully! */
        ASSERT(psurf);

        /* Now fill the polygon with the current fill brush. */
        if (!(pbrFill->flAttrs & BR_IS_NULL))
        {
            BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
            BrushOrigin.x += dc->ptlDCOrig.x;
            BrushOrigin.y += dc->ptlDCOrig.y;
            ret = IntFillPolygon (dc,
                                  psurf,
                                  &dc->eboFill.BrushObject,
                                  Points,
                                  Count,
                                  DestRect,
                                  &BrushOrigin);
        }

        // Draw the Polygon Edges with the current pen ( if not a NULL pen )
        if (!(pbrLine->flAttrs & BR_IS_NULL))
        {
            int i;

            for (i = 0; i < Count-1; i++)
            {

// DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
//                                 Points[0].x, Points[0].y,
//                                 Points[1].x, Points[1].y );

                ret = IntEngLineTo(&psurf->SurfObj,
                                   dc->rosdc.CombinedClip,
                                   &dc->eboLine.BrushObject,
                                   Points[i].x,          /* From */
                                   Points[i].y,
                                   Points[i+1].x,        /* To */
                                   Points[i+1].y,
                                   &DestRect,
                                   ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
                if (!ret) break;
            }
            /* Close the polygon */
            if (ret)
            {
                ret = IntEngLineTo(&psurf->SurfObj,
                                   dc->rosdc.CombinedClip,
                                   &dc->eboLine.BrushObject,
                                   Points[Count-1].x, /* From */
                                   Points[Count-1].y,
                                   Points[0].x,       /* To */
                                   Points[0].y,
                                   &DestRect,
                                   ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */
            }
        }
    }

    return ret;
}
예제 #11
0
BOOL APIENTRY
NtGdiExtFloodFill(
    HDC  hDC,
    INT  XStart,
    INT  YStart,
    COLORREF  Color,
    UINT  FillType)
{
    PDC dc;
    PDC_ATTR   pdcattr;
    SURFACE    *psurf = NULL;
    EXLATEOBJ  exlo;
    BOOL       Ret = FALSE;
    RECTL      DestRect;
    POINTL     Pt;
    ULONG      ConvColor;

    dc = DC_LockDc(hDC);
    if (!dc)
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }
    if (dc->dctype == DC_TYPE_INFO)
    {
        DC_UnlockDc(dc);
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
    }

    pdcattr = dc->pdcattr;

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(dc);

    Pt.x = XStart;
    Pt.y = YStart;
    IntLPtoDP(dc, (LPPOINT)&Pt, 1);

    Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y);
    if (Ret)
        IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect);
    else
        goto cleanup;

    DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);

    psurf = dc->dclevel.pSurface;
    if (!psurf)
    {
        Ret = FALSE;
        goto cleanup;
    }

    EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);

    /* Only solid fills supported for now
     * How to support pattern brushes and non standard surfaces (not offering dib functions):
     * Version a (most likely slow): call DrvPatBlt for every pixel
     * Version b: create a flood mask and let MaskBlt blit a masked brush */
    ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color);
    Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);

    EXLATEOBJ_vCleanup(&exlo);

cleanup:
    DC_vFinishBlit(dc, NULL);
    DC_UnlockDc(dc);
    return Ret;
}
예제 #12
0
BOOL FASTCALL
IntPatBlt(
    PDC pdc,
    INT XLeft,
    INT YLeft,
    INT Width,
    INT Height,
    DWORD dwRop,
    PBRUSH pbrush)
{
    RECTL DestRect;
    SURFACE *psurf;
    EBRUSHOBJ eboFill ;
    POINTL BrushOrigin;
    BOOL ret;

    ASSERT(pbrush);

    FIXUP_ROP(dwRop);

    if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
    {
        return TRUE;
    }

    if (Width > 0)
    {
        DestRect.left = XLeft;
        DestRect.right = XLeft + Width;
    }
    else
    {
        DestRect.left = XLeft + Width + 1;
        DestRect.right = XLeft + 1;
    }

    if (Height > 0)
    {
        DestRect.top = YLeft;
        DestRect.bottom = YLeft + Height;
    }
    else
    {
        DestRect.top = YLeft + Height + 1;
        DestRect.bottom = YLeft + 1;
    }

    IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);

    DestRect.left   += pdc->ptlDCOrig.x;
    DestRect.top    += pdc->ptlDCOrig.y;
    DestRect.right  += pdc->ptlDCOrig.x;
    DestRect.bottom += pdc->ptlDCOrig.y;
#ifdef _USE_DIBLIB_
    BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x + XLeft;
    BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y + YLeft;
#else
    BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
    BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
#endif

    DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);

    psurf = pdc->dclevel.pSurface;

    if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(pdc);

    EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);

    ret = IntEngBitBlt(
        &psurf->SurfObj,
        NULL,
        NULL,
        pdc->rosdc.CombinedClip,
        NULL,
        &DestRect,
        NULL,
        NULL,
        &eboFill.BrushObject,
        &BrushOrigin,
        ROP_TO_ROP4(dwRop));

    DC_vFinishBlit(pdc, NULL);

    EBRUSHOBJ_vCleanup(&eboFill);

    return ret;
}
예제 #13
0
BOOL APIENTRY
GreStretchBltMask(
    HDC hDCDest,
    INT XOriginDest,
    INT YOriginDest,
    INT WidthDest,
    INT HeightDest,
    HDC hDCSrc,
    INT XOriginSrc,
    INT YOriginSrc,
    INT WidthSrc,
    INT HeightSrc,
    DWORD ROP,
    IN DWORD dwBackColor,
    HDC hDCMask,
    INT XOriginMask,
    INT YOriginMask)
{
    PDC DCDest;
    PDC DCSrc  = NULL;
    PDC DCMask = NULL;
    HDC ahDC[3];
    PGDIOBJ apObj[3];
    PDC_ATTR pdcattr;
    SURFACE *BitmapDest, *BitmapSrc = NULL;
    SURFACE *BitmapMask = NULL;
    RECTL DestRect;
    RECTL SourceRect;
    POINTL MaskPoint;
    BOOL Status = FALSE;
    EXLATEOBJ exlo;
    XLATEOBJ *XlateObj = NULL;
    POINTL BrushOrigin;
    BOOL UsesSource;
    BOOL UsesMask;

    FIXUP_ROP(ROP);
    UsesSource = ROP_USES_SOURCE(ROP);
    UsesMask = ROP_USES_MASK(ROP);

    if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
    {
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return TRUE;
    }

    if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask))
    {
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    ahDC[0] = hDCDest;
    ahDC[1] = UsesSource ? hDCSrc : NULL;
    ahDC[2] = UsesMask ? hDCMask : NULL;
    if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
    {
        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc);
        EngSetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }
    DCDest = apObj[0];
    DCSrc = apObj[1];
    DCMask = apObj[2];

    if (DCDest->dctype == DC_TYPE_INFO)
    {
        if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
        if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
        GDIOBJ_vUnlockObject(&DCDest->BaseObject);
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
    }

    if (UsesSource)
    {
        if (DCSrc->dctype == DC_TYPE_INFO)
        {
            GDIOBJ_vUnlockObject(&DCDest->BaseObject);
            GDIOBJ_vUnlockObject(&DCSrc->BaseObject);
            if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject);
            /* Yes, Windows really returns TRUE in this case */
            return TRUE;
        }
    }

    pdcattr = DCDest->pdcattr;

    DestRect.left   = XOriginDest;
    DestRect.top    = YOriginDest;
    DestRect.right  = XOriginDest+WidthDest;
    DestRect.bottom = YOriginDest+HeightDest;
    IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);

    DestRect.left   += DCDest->ptlDCOrig.x;
    DestRect.top    += DCDest->ptlDCOrig.y;
    DestRect.right  += DCDest->ptlDCOrig.x;
    DestRect.bottom += DCDest->ptlDCOrig.y;

    SourceRect.left   = XOriginSrc;
    SourceRect.top    = YOriginSrc;
    SourceRect.right  = XOriginSrc+WidthSrc;
    SourceRect.bottom = YOriginSrc+HeightSrc;

    if (UsesSource)
    {
        IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);

        SourceRect.left   += DCSrc->ptlDCOrig.x;
        SourceRect.top    += DCSrc->ptlDCOrig.y;
        SourceRect.right  += DCSrc->ptlDCOrig.x;
        SourceRect.bottom += DCSrc->ptlDCOrig.y;
    }

    BrushOrigin.x = 0;
    BrushOrigin.y = 0;

    /* Only prepare Source and Dest, hdcMask represents a DIB */
    DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(DCDest);

    /* Determine surfaces to be used in the bitblt */
    BitmapDest = DCDest->dclevel.pSurface;
    if (BitmapDest == NULL)
        goto failed;
    if (UsesSource)
    {
        BitmapSrc = DCSrc->dclevel.pSurface;
        if (BitmapSrc == NULL)
            goto failed;

        /* Create the XLATEOBJ. */
        EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
        XlateObj = &exlo.xlo;
    }

    /* Offset the brush */
    BrushOrigin.x += DCDest->ptlDCOrig.x;
    BrushOrigin.y += DCDest->ptlDCOrig.y;

    /* Make mask surface for source surface */
    if (BitmapSrc && DCMask)
    {
        BitmapMask = DCMask->dclevel.pSurface;
        if (BitmapMask &&
            (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
             BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
        {
            WARN("%dx%d mask is smaller than %dx%d bitmap\n",
                    BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
                    WidthSrc, HeightSrc);
            EXLATEOBJ_vCleanup(&exlo);
            goto failed;
        }
        /* Create mask offset point */
        MaskPoint.x = XOriginMask;
        MaskPoint.y = YOriginMask;
        IntLPtoDP(DCMask, &MaskPoint, 1);
        MaskPoint.x += DCMask->ptlDCOrig.x;
        MaskPoint.y += DCMask->ptlDCOrig.y;
    }

    /* Perform the bitblt operation */
    Status = IntEngStretchBlt(&BitmapDest->SurfObj,
                              BitmapSrc ? &BitmapSrc->SurfObj : NULL,
                              BitmapMask ? &BitmapMask->SurfObj : NULL,
                              &DCDest->co.ClipObj,
                              XlateObj,
                              &DCDest->dclevel.ca,
                              &DestRect,
                              &SourceRect,
                              BitmapMask ? &MaskPoint : NULL,
                              &DCDest->eboFill.BrushObject,
                              &BrushOrigin,
                              ROP_TO_ROP4(ROP));
    if (UsesSource)
    {
        EXLATEOBJ_vCleanup(&exlo);
    }

failed:
    DC_vFinishBlit(DCDest, DCSrc);
    if (UsesSource)
    {
        DC_UnlockDc(DCSrc);
    }
    if (DCMask)
    {
        DC_UnlockDc(DCMask);
    }
    DC_UnlockDc(DCDest);

    return Status;
}
예제 #14
0
BOOL APIENTRY
NtGdiMaskBlt(
    HDC hdcDest,
    INT nXDest,
    INT nYDest,
    INT nWidth,
    INT nHeight,
    HDC hdcSrc,
    INT nXSrc,
    INT nYSrc,
    HBITMAP hbmMask,
    INT xMask,
    INT yMask,
    DWORD dwRop,
    IN DWORD crBackColor)
{
    PDC DCDest;
    PDC DCSrc = NULL;
    HDC ahDC[2];
    PGDIOBJ apObj[2];
    PDC_ATTR pdcattr = NULL;
    SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL;
    RECTL DestRect, SourceRect;
    POINTL SourcePoint, MaskPoint;
    BOOL Status = FALSE;
    EXLATEOBJ exlo;
    XLATEOBJ *XlateObj = NULL;
    BOOL UsesSource;

    FIXUP_ROP(dwRop); // FIXME: why do we need this???

    //DPRINT1("dwRop : 0x%08x\n", dwRop);
    UsesSource = ROP_USES_SOURCE(dwRop);
    if (!hdcDest || (UsesSource && !hdcSrc))
    {
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    /* Check if we need a mask and have a mask bitmap */
    if (ROP_USES_MASK(dwRop) && (hbmMask != NULL))
    {
        /* Reference the mask bitmap */
        psurfMask = SURFACE_ShareLockSurface(hbmMask);
        if (psurfMask == NULL)
        {
            EngSetLastError(ERROR_INVALID_HANDLE);
            return FALSE;
        }

        /* Make sure the mask bitmap is 1 BPP */
        if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1)
        {
            EngSetLastError(ERROR_INVALID_PARAMETER);
            SURFACE_ShareUnlockSurface(psurfMask);
            return FALSE;
        }
    }
    else
    {
        /* We use NULL, if we need a mask, the Eng function will take care of
           that and use the brushobject to get a mask */
        psurfMask = NULL;
    }

    MaskPoint.x = xMask;
    MaskPoint.y = yMask;

    /* Take care of source and destination bitmap */
    TRACE("Locking DCs\n");
    ahDC[0] = hdcDest;
    ahDC[1] = UsesSource ? hdcSrc : NULL;
    if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE))
    {
        WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc);
        EngSetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }
    DCDest = apObj[0];
    DCSrc = apObj[1];

    ASSERT(DCDest);
    if (NULL == DCDest)
    {
        if(DCSrc) DC_UnlockDc(DCSrc);
        WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest);
        return FALSE;
    }

    if (DCDest->dctype == DC_TYPE_INFO)
    {
        if(DCSrc) DC_UnlockDc(DCSrc);
        DC_UnlockDc(DCDest);
        /* Yes, Windows really returns TRUE in this case */
        return TRUE;
    }

    if (UsesSource)
    {
        ASSERT(DCSrc);
        if (DCSrc->dctype == DC_TYPE_INFO)
        {
            DC_UnlockDc(DCDest);
            DC_UnlockDc(DCSrc);
            /* Yes, Windows really returns TRUE in this case */
            return TRUE;
        }
    }

    pdcattr = DCDest->pdcattr;

    DestRect.left   = nXDest;
    DestRect.top    = nYDest;
    DestRect.right  = nXDest + nWidth;
    DestRect.bottom = nYDest + nHeight;
    IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);

    DestRect.left   += DCDest->ptlDCOrig.x;
    DestRect.top    += DCDest->ptlDCOrig.y;
    DestRect.right  += DCDest->ptlDCOrig.x;
    DestRect.bottom += DCDest->ptlDCOrig.y;

    SourcePoint.x = nXSrc;
    SourcePoint.y = nYSrc;

    if (UsesSource)
    {
        IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);

        SourcePoint.x += DCSrc->ptlDCOrig.x;
        SourcePoint.y += DCSrc->ptlDCOrig.y;
        /* Calculate Source Rect */
        SourceRect.left = SourcePoint.x;
        SourceRect.top = SourcePoint.y;
        SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
        SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
    }
    else
    {
        SourceRect.left = 0;
        SourceRect.top = 0;
        SourceRect.right = 0;
        SourceRect.bottom = 0;
    }

    /* Prepare blit */
    DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect);

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(DCDest);

    /* Determine surfaces to be used in the bitblt */
    BitmapDest = DCDest->dclevel.pSurface;
    if (!BitmapDest)
        goto cleanup;

    if (UsesSource)
    {
        {
            BitmapSrc = DCSrc->dclevel.pSurface;
            if (!BitmapSrc)
                goto cleanup;
        }
    }

    /* Create the XLATEOBJ. */
    if (UsesSource)
    {
        EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
        XlateObj = &exlo.xlo;
    }


    /* Perform the bitblt operation */
    Status = IntEngBitBlt(&BitmapDest->SurfObj,
                          BitmapSrc ? &BitmapSrc->SurfObj : NULL,
                          psurfMask ? &psurfMask->SurfObj : NULL,
                          &DCDest->co.ClipObj,
                          XlateObj,
                          &DestRect,
                          &SourcePoint,
                          &MaskPoint,
                          &DCDest->eboFill.BrushObject,
                          &DCDest->dclevel.pbrFill->ptOrigin,
                          ROP_TO_ROP4(dwRop));

    if (UsesSource)
        EXLATEOBJ_vCleanup(&exlo);
cleanup:
    DC_vFinishBlit(DCDest, DCSrc);
    if (UsesSource)
    {
        DC_UnlockDc(DCSrc);
    }
    DC_UnlockDc(DCDest);
    if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask);

    return Status;
}
예제 #15
0
/* rc1 and rc2 are the rectangles where we want to draw or
 * from where we take pixels. */
VOID
FASTCALL
DC_vPrepareDCsForBlit(PDC pdc1,
                      RECT rc1,
                      PDC pdc2,
                      RECT rc2)
{
    PDC pdcFirst, pdcSecond;
    PRECT prcFirst, prcSecond;

    /* Update brushes */
    if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(pdc1);
    if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(pdc1);
    if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT)
        DC_vUpdateTextBrush(pdc1);

    /* Lock them in good order */
    if(pdc2)
    {
        if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
        {
            pdcFirst = pdc1;
            prcFirst = &rc1;
            pdcSecond = pdc2;
            prcSecond = &rc2;
        }
        else
        {
            pdcFirst = pdc2;
            prcFirst = &rc2;
            pdcSecond = pdc1;
            prcSecond = &rc1;
        }
    }
    else
    {
        pdcFirst = pdc1 ;
        prcFirst = &rc1;
        pdcSecond = NULL;
        prcSecond = NULL;
    }

    if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
    {
        EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
        MouseSafetyOnDrawStart(pdcFirst->ppdev,
                                    prcFirst->left,
                                    prcFirst->top,
                                    prcFirst->right,
                                    prcFirst->bottom) ;
        /* Update surface if needed */
        if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
        {
            DC_vUpdateDC(pdcFirst);
        }
    }
    if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
    {
        EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
        MouseSafetyOnDrawStart(pdcSecond->ppdev,
                                    prcSecond->left,
                                    prcSecond->top,
                                    prcSecond->right,
                                    prcSecond->bottom) ;
        /* Update surface if needed */
        if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
        {
            DC_vUpdateDC(pdcSecond);
        }
    }
}
예제 #16
0
BOOL
FASTCALL
IntRectangle(PDC dc,
             int LeftRect,
             int TopRect,
             int RightRect,
             int BottomRect)
{
    SURFACE *psurf = NULL;
    PBRUSH pbrLine, pbrFill;
    BOOL       ret = FALSE; // Default to failure
    RECTL      DestRect;
    MIX        Mix;
    PDC_ATTR pdcattr;
    POINTL BrushOrigin;

    ASSERT ( dc ); // Caller's responsibility to set this up

    pdcattr = dc->pdcattr;

    // Rectangle Path only.
    if ( PATH_IsPathOpen(dc->dclevel) )
    {
        return PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
    }

	/* Make sure rectangle is not inverted */
    DestRect.left   = min(LeftRect, RightRect);
    DestRect.right  = max(LeftRect, RightRect);
    DestRect.top    = min(TopRect,  BottomRect);
    DestRect.bottom = max(TopRect,  BottomRect);

    IntLPtoDP(dc, (LPPOINT)&DestRect, 2);

    DestRect.left   += dc->ptlDCOrig.x;
    DestRect.right  += dc->ptlDCOrig.x;
    DestRect.top    += dc->ptlDCOrig.y;
    DestRect.bottom += dc->ptlDCOrig.y;

    /* In GM_COMPATIBLE, don't include bottom and right edges */
    if (pdcattr->iGraphicsMode == GM_COMPATIBLE)
    {
        DestRect.right--;
        DestRect.bottom--;
    }

    DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(dc);

    pbrFill = dc->dclevel.pbrFill;
    pbrLine = dc->dclevel.pbrLine;
    if (!pbrLine)
    {
        ret = FALSE;
        goto cleanup;
    }

    psurf = dc->dclevel.pSurface;
    if (!psurf)
    {
        ret = FALSE;
        goto cleanup;
    }

    if (pbrFill)
    {
        if (!(pbrFill->flAttrs & BR_IS_NULL))
        {
            BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin);
            BrushOrigin.x += dc->ptlDCOrig.x;
            BrushOrigin.y += dc->ptlDCOrig.y;
            ret = IntEngBitBlt(&psurf->SurfObj,
                               NULL,
                               NULL,
                               dc->rosdc.CombinedClip,
                               NULL,
                               &DestRect,
                               NULL,
                               NULL,
                               &dc->eboFill.BrushObject,
                               &BrushOrigin,
                               ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY));
        }
    }

    // Draw the rectangle with the current pen

    ret = TRUE; // Change default to success

    if (!(pbrLine->flAttrs & BR_IS_NULL))
    {
        Mix = ROP2_TO_MIX(pdcattr->jROP2);
        ret = ret && IntEngLineTo(&psurf->SurfObj,
                                  dc->rosdc.CombinedClip,
                                  &dc->eboLine.BrushObject,
                                  DestRect.left, DestRect.top, DestRect.right, DestRect.top,
                                  &DestRect, // Bounding rectangle
                                  Mix);

        ret = ret && IntEngLineTo(&psurf->SurfObj,
                                  dc->rosdc.CombinedClip,
                                  &dc->eboLine.BrushObject,
                                  DestRect.right, DestRect.top, DestRect.right, DestRect.bottom,
                                  &DestRect, // Bounding rectangle
                                  Mix);

        ret = ret && IntEngLineTo(&psurf->SurfObj,
                                  dc->rosdc.CombinedClip,
                                  &dc->eboLine.BrushObject,
                                  DestRect.right, DestRect.bottom, DestRect.left, DestRect.bottom,
                                  &DestRect, // Bounding rectangle
                                  Mix);

        ret = ret && IntEngLineTo(&psurf->SurfObj,
                                  dc->rosdc.CombinedClip,
                                  &dc->eboLine.BrushObject,
                                  DestRect.left, DestRect.bottom, DestRect.left, DestRect.top,
                                  &DestRect, // Bounding rectangle
                                  Mix);
    }

cleanup:
    DC_vFinishBlit(dc, NULL);

    /* Move current position in DC?
       MSDN: The current position is neither used nor updated by Rectangle. */

    return ret;
}
예제 #17
0
/* rc1 and rc2 are the rectangles where we want to draw or
 * from where we take pixels. */
VOID
FASTCALL
DC_vPrepareDCsForBlit(
    PDC pdcDest,
    const RECT* rcDest,
    PDC pdcSrc,
    const RECT* rcSrc)
{
    PDC pdcFirst, pdcSecond;
    const RECT *prcFirst, *prcSecond;

    /* Update brushes */
    if (pdcDest->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(pdcDest);
    if (pdcDest->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(pdcDest);
    if(pdcDest->pdcattr->ulDirty_ & DIRTY_TEXT)
        DC_vUpdateTextBrush(pdcDest);

    /* Lock them in good order */
    if(pdcSrc)
    {
        if((ULONG_PTR)pdcDest->ppdev->hsemDevLock >= (ULONG_PTR)pdcSrc->ppdev->hsemDevLock)
        {
            pdcFirst = pdcDest;
            prcFirst = rcDest;
            pdcSecond = pdcSrc;
            prcSecond = rcSrc;
        }
        else
        {
            pdcFirst = pdcSrc;
            prcFirst = rcSrc;
            pdcSecond = pdcDest;
            prcSecond = rcDest;
        }
    }
    else
    {
        pdcFirst = pdcDest ;
        prcFirst = rcDest;
        pdcSecond = NULL;
        prcSecond = NULL;
    }

    /* Update clipping of dest DC if needed */
    if (pdcDest->dctype == DCTYPE_DIRECT)
    {
        DCE* dce = DceGetDceFromDC(pdcDest->BaseObject.hHmgr);
        if (dce)
            DceUpdateVisRgn(dce, dce->pwndOrg, dce->DCXFlags);
    }

    if (pdcDest->fs & DC_FLAG_DIRTY_RAO)
        CLIPPING_UpdateGCRegion(pdcDest);

    /* Lock and update first DC */
    if(pdcFirst->dctype == DCTYPE_DIRECT)
    {
        EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
        /* Update surface if needed */
        if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
        {
            DC_vUpdateDC(pdcFirst);
        }
    }

    if(pdcFirst->dctype == DCTYPE_DIRECT)
    {
        if (!prcFirst)
            prcFirst = &pdcFirst->erclClip;

        MouseSafetyOnDrawStart(pdcFirst->ppdev,
                               prcFirst->left,
                               prcFirst->top,
                               prcFirst->right,
                               prcFirst->bottom) ;
    }

    if (!pdcSecond)
        return;

    /* Lock and update second DC */
    if(pdcSecond->dctype == DCTYPE_DIRECT)
    {
        EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
        /* Update surface if needed */
        if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
        {
            DC_vUpdateDC(pdcSecond);
        }
    }

    if(pdcSecond->dctype == DCTYPE_DIRECT)
    {
        if (!prcSecond)
            prcSecond = &pdcSecond->erclClip;
        MouseSafetyOnDrawStart(pdcSecond->ppdev,
                               prcSecond->left,
                               prcSecond->top,
                               prcSecond->right,
                               prcSecond->bottom) ;
    }
}
예제 #18
0
BOOL
FASTCALL
IntRoundRect(
    PDC  dc,
    int  Left,
    int  Top,
    int  Right,
    int  Bottom,
    int  xCurveDiameter,
    int  yCurveDiameter)
{
    PDC_ATTR pdcattr;
    PBRUSH   pbrLine, pbrFill;
    RECTL RectBounds;
    LONG PenWidth, PenOrigWidth;
    BOOL ret = TRUE; // Default to success
    BRUSH brushTemp;

    ASSERT ( dc ); // Caller's responsibility to set this up

    if ( PATH_IsPathOpen(dc->dclevel) )
        return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
                                xCurveDiameter, yCurveDiameter );

    if ((Left == Right) || (Top == Bottom)) return TRUE;

    xCurveDiameter = max(abs( xCurveDiameter ), 1);
    yCurveDiameter = max(abs( yCurveDiameter ), 1);

    if (Right < Left)
    {
       INT tmp = Right; Right = Left; Left = tmp;
    }
    if (Bottom < Top)
    {
       INT tmp = Bottom; Bottom = Top; Top = tmp;
    }

    pdcattr = dc->pdcattr;

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(dc);

    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(dc);

    pbrLine = PEN_ShareLockPen(pdcattr->hpen);
    if (!pbrLine)
    {
        /* Nothing to do, as we don't have a bitmap */
        EngSetLastError(ERROR_INTERNAL_ERROR);
        return FALSE;
    }

    PenOrigWidth = PenWidth = pbrLine->ptPenWidth.x;
    if (pbrLine->ulPenStyle == PS_NULL) PenWidth = 0;

    if (pbrLine->ulPenStyle == PS_INSIDEFRAME)
    {
       if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
       if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
       Left   += PenWidth / 2;
       Right  -= (PenWidth - 1) / 2;
       Top    += PenWidth / 2;
       Bottom -= (PenWidth - 1) / 2;
    }

    if (!PenWidth) PenWidth = 1;
    pbrLine->ptPenWidth.x = PenWidth;

    RectBounds.left = Left;
    RectBounds.top = Top;
    RectBounds.right = Right;
    RectBounds.bottom = Bottom;

    IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);

    RectBounds.left   += dc->ptlDCOrig.x;
    RectBounds.top    += dc->ptlDCOrig.y;
    RectBounds.right  += dc->ptlDCOrig.x;
    RectBounds.bottom += dc->ptlDCOrig.y;

    pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
    if (!pbrFill)
    {
        DPRINT1("FillRound Fail\n");
        EngSetLastError(ERROR_INTERNAL_ERROR);
        ret = FALSE;
    }
    else
    {

        DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds);

        RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp));
        brushTemp.ptOrigin.x += RectBounds.left - Left;
        brushTemp.ptOrigin.y += RectBounds.top - Top;
        ret = IntFillRoundRect( dc,
                                RectBounds.left,
                                RectBounds.top,
                                RectBounds.right,
                                RectBounds.bottom,
                                xCurveDiameter,
                                yCurveDiameter,
                                &brushTemp);
        BRUSH_ShareUnlockBrush(pbrFill);

        if (ret)
        {
           ret = IntDrawRoundRect( dc,
                      RectBounds.left,
                       RectBounds.top,
                     RectBounds.right,
                    RectBounds.bottom,
                       xCurveDiameter,
                       yCurveDiameter,
                       pbrLine);
        }

        DC_vFinishBlit(dc, NULL);
    }


    pbrLine->ptPenWidth.x = PenOrigWidth;
    PEN_ShareUnlockPen(pbrLine);
    return ret;
}
예제 #19
0
HANDLE
APIENTRY
NtGdiGetDCObject(HDC hDC, INT ObjectType)
{
    HGDIOBJ SelObject;
    DC *pdc;
    PDC_ATTR pdcattr;

    /* From Wine: GetCurrentObject does not SetLastError() on a null object */
    if(!hDC) return NULL;

    if(!(pdc = DC_LockDc(hDC)))
    {
        EngSetLastError(ERROR_INVALID_HANDLE);
        return NULL;
    }
    pdcattr = pdc->pdcattr;

    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
        DC_vUpdateFillBrush(pdc);

    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
        DC_vUpdateLineBrush(pdc);

    switch(ObjectType)
    {
        case GDI_OBJECT_TYPE_EXTPEN:
        case GDI_OBJECT_TYPE_PEN:
            SelObject = pdcattr->hpen;
            break;

        case GDI_OBJECT_TYPE_BRUSH:
            SelObject = pdcattr->hbrush;
            break;

        case GDI_OBJECT_TYPE_PALETTE:
            SelObject = pdc->dclevel.hpal;
            break;

        case GDI_OBJECT_TYPE_FONT:
            SelObject = pdcattr->hlfntNew;
            break;

        case GDI_OBJECT_TYPE_BITMAP:
        {
            SURFACE *psurf = pdc->dclevel.pSurface;
            SelObject = psurf ? psurf->BaseObject.hHmgr : NULL;
            break;
        }

        case GDI_OBJECT_TYPE_COLORSPACE:
            DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n");
            // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ?
            SelObject = NULL;
            break;

        default:
            SelObject = NULL;
            EngSetLastError(ERROR_INVALID_PARAMETER);
            break;
    }

    DC_UnlockDc(pdc);
    return SelObject;
}