Beispiel #1
0
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;
}
Beispiel #2
0
 /*
 * @implemented
 */
HPEN
APIENTRY
NtGdiSelectPen(
    IN HDC hDC,
    IN HPEN hPen)
{
    PDC pDC;
    HPEN hOrgPen;

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

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

    /* Simply return the user mode value, without checking */
    hOrgPen = pDC->pdcattr->hpen;
    pDC->pdcattr->hpen = hPen;
    DC_vUpdateLineBrush(pDC);

    DC_UnlockDc(pDC);

    return hOrgPen;
}
Beispiel #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;
}
Beispiel #4
0
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;
}
Beispiel #5
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;
}
Beispiel #6
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;
}
Beispiel #7
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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #12
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;
}
Beispiel #13
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) ;
    }
}
Beispiel #14
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);
        }
    }
}