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

📄 line.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  ReactOS W32 Subsystem
 *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <w32k.h>

#define NDEBUG
#include <debug.h>

// Some code from the WINE project source (www.winehq.com)


BOOL FASTCALL
IntGdiMoveToEx(DC      *dc,
               int     X,
               int     Y,
               LPPOINT Point)
{
  BOOL  PathIsOpen;

  if ( Point )
  {
    Point->x = dc->Dc_Attr.ptlCurrent.x;
    Point->y = dc->Dc_Attr.ptlCurrent.y;
  }
  dc->Dc_Attr.ptlCurrent.x = X;
  dc->Dc_Attr.ptlCurrent.y = Y;

  PathIsOpen = PATH_IsPathOpen(dc->w.path);

  if ( PathIsOpen )
    return PATH_MoveTo ( dc );

  return TRUE;
}

BOOL FASTCALL
IntGdiLineTo(DC  *dc,
             int XEnd,
             int YEnd)
{
  BITMAPOBJ *BitmapObj;
  BOOL      Ret = TRUE;
  PGDIBRUSHOBJ PenBrushObj;
  GDIBRUSHINST PenBrushInst;
  RECTL     Bounds;
  POINT     Points[2];

  if (PATH_IsPathOpen(dc->w.path))
    {
      Ret = PATH_LineTo(dc, XEnd, YEnd);
      if (Ret)
	  {
	    // FIXME - PATH_LineTo should maybe do this...
	    dc->Dc_Attr.ptlCurrent.x = XEnd;
	    dc->Dc_Attr.ptlCurrent.y = YEnd;
	  }
      return Ret;
    }
  else
    {
      BitmapObj = BITMAPOBJ_LockBitmap ( dc->w.hBitmap );
      if (NULL == BitmapObj)
        {
          SetLastWin32Error(ERROR_INVALID_HANDLE);
          return FALSE;
        }

      Points[0].x = dc->Dc_Attr.ptlCurrent.x;
      Points[0].y = dc->Dc_Attr.ptlCurrent.y;
      Points[1].x = XEnd;
      Points[1].y = YEnd;

      IntLPtoDP(dc, Points, 2);

      /* FIXME: Is it correct to do this after the transformation? */
      Points[0].x += dc->w.DCOrgX;
      Points[0].y += dc->w.DCOrgY;
      Points[1].x += dc->w.DCOrgX;
      Points[1].y += dc->w.DCOrgY;

      Bounds.left = min(Points[0].x, Points[1].x);
      Bounds.top = min(Points[0].y, Points[1].y);
      Bounds.right = max(Points[0].x, Points[1].x);
      Bounds.bottom = max(Points[0].y, Points[1].y);

      /* get BRUSHOBJ from current pen. */
      PenBrushObj = PENOBJ_LockPen( dc->Dc_Attr.hpen );
      /* FIXME - PenBrushObj can be NULL!!!! Don't assert here! */
      ASSERT(PenBrushObj);

      if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
      {
        IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
        Ret = IntEngLineTo(&BitmapObj->SurfObj,
                           dc->CombinedClip,
                           &PenBrushInst.BrushObject,
                           Points[0].x, Points[0].y,
                           Points[1].x, Points[1].y,
                           &Bounds,
                           ROP2_TO_MIX(dc->Dc_Attr.jROP2));
      }

      BITMAPOBJ_UnlockBitmap ( BitmapObj );
      PENOBJ_UnlockPen( PenBrushObj );
    }

  if (Ret)
    {
      dc->Dc_Attr.ptlCurrent.x = XEnd;
      dc->Dc_Attr.ptlCurrent.y = YEnd;
    }

  return Ret;
}

BOOL FASTCALL
IntGdiPolyBezier(DC      *dc,
                 LPPOINT pt,
                 DWORD   Count)
{
  BOOL ret = FALSE; // default to FAILURE

  if ( PATH_IsPathOpen(dc->w.path) )
  {
    return PATH_PolyBezier ( dc, pt, Count );
  }

  /* We'll convert it into line segments and draw them using Polyline */
  {
    POINT *Pts;
    INT nOut;

    Pts = GDI_Bezier ( pt, Count, &nOut );
    if ( Pts )
    {
      ret = IntGdiPolyline(dc, Pts, nOut);
      ExFreePool(Pts);
    }
  }

  return ret;
}

BOOL FASTCALL
IntGdiPolyBezierTo(DC      *dc,
                   LPPOINT pt,
                   DWORD  Count)
{
  BOOL ret = FALSE; // default to failure

  if ( PATH_IsPathOpen(dc->w.path) )
    ret = PATH_PolyBezierTo ( dc, pt, Count );
  else /* We'll do it using PolyBezier */
  {
    POINT *npt;
    npt = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * (Count + 1), TAG_BEZIER);
    if ( npt )
    {
      npt[0].x = dc->Dc_Attr.ptlCurrent.x;
      npt[0].y = dc->Dc_Attr.ptlCurrent.y;
      memcpy(npt + 1, pt, sizeof(POINT) * Count);
      ret = IntGdiPolyBezier(dc, npt, Count+1);
      ExFreePool(npt);
    }
  }
  if ( ret )
  {
    dc->Dc_Attr.ptlCurrent.x = pt[Count-1].x;
    dc->Dc_Attr.ptlCurrent.y = pt[Count-1].y;
  }

  return ret;
}

BOOL FASTCALL
IntGdiPolyline(DC      *dc,
               LPPOINT pt,
               int     Count)
{
   BITMAPOBJ *BitmapObj;
   GDIBRUSHOBJ *PenBrushObj;
   GDIBRUSHINST PenBrushInst;
   LPPOINT Points;
   BOOL Ret = TRUE;
   LONG i;

   if (PATH_IsPathOpen(dc->w.path))
      return PATH_Polyline(dc, pt, Count);

   /* Get BRUSHOBJ from current pen. */
   PenBrushObj = PENOBJ_LockPen(dc->Dc_Attr.hpen);
   /* FIXME - PenBrushObj can be NULL! Don't assert here! */
   ASSERT(PenBrushObj);

   if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
   {
      Points = EngAllocMem(0, Count * sizeof(POINT), TAG_COORD);
      if (Points != NULL)
      {
         BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
         /* FIXME - BitmapObj can be NULL!!!! Don't assert but handle this case gracefully! */
         ASSERT(BitmapObj);

         RtlCopyMemory(Points, pt, Count * sizeof(POINT));
         IntLPtoDP(dc, Points, Count);

         /* Offset the array of point by the dc->w.DCOrg */
         for (i = 0; i < Count; i++)
         {
            Points[i].x += dc->w.DCOrgX;
            Points[i].y += dc->w.DCOrgY;
         }

         IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
         Ret = IntEngPolyline(&BitmapObj->SurfObj, dc->CombinedClip,
                              &PenBrushInst.BrushObject, Points, Count,
                              ROP2_TO_MIX(dc->Dc_Attr.jROP2));

         BITMAPOBJ_UnlockBitmap(BitmapObj);
         EngFreeMem(Points);
      }
      else
      {
         Ret = FALSE;
      }
   }

   PENOBJ_UnlockPen(PenBrushObj);

   return Ret;
}

BOOL FASTCALL
IntGdiPolylineTo(DC      *dc,
                 LPPOINT pt,
                 DWORD   Count)
{
  BOOL ret = FALSE; // default to failure

  if(PATH_IsPathOpen(dc->w.path))
  {
    ret = PATH_PolylineTo(dc, pt, Count);
  }
  else /* do it using Polyline */
  {
    POINT *pts = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * (Count + 1), TAG_SHAPE);
    if ( pts )
    {
      pts[0].x = dc->Dc_Attr.ptlCurrent.x;
      pts[0].y = dc->Dc_Attr.ptlCurrent.y;
      memcpy( pts + 1, pt, sizeof(POINT) * Count);
      ret = IntGdiPolyline(dc, pts, Count + 1);
      ExFreePool(pts);
    }
  }
  if ( ret )
  {
    dc->Dc_Attr.ptlCurrent.x = pt[Count-1].x;
    dc->Dc_Attr.ptlCurrent.y = pt[Count-1].y;
  }

  return ret;
}


BOOL FASTCALL
IntGdiPolyPolyline(DC      *dc,
                   LPPOINT pt,
                   LPDWORD PolyPoints,
                   DWORD   Count)
{
  int i;
  LPPOINT pts;
  LPDWORD pc;
  BOOL ret = FALSE; // default to failure
  pts = pt;
  pc = PolyPoints;

  for (i = 0; i < Count; i++)
  {
    ret = IntGdiPolyline ( dc, pts, *pc );
    if (ret == FALSE)
    {
      return ret;
    }
    pts+=*pc++;
  }

  return ret;
}

/******************************************************************************/

BOOL
APIENTRY
NtGdiAngleArc(
    IN HDC hdc,
    IN INT x,
    IN INT y,
    IN DWORD dwRadius,
    IN DWORD dwStartAngle,
    IN DWORD dwSweepAngle)
{
  UNIMPLEMENTED;
  return FALSE;
}


BOOL
STDCALL
NtGdiLineTo(HDC  hDC,
           int  XEnd,
           int  YEnd)
{
  DC *dc;
  BOOL Ret;

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

  Ret = IntGdiLineTo(dc, XEnd, YEnd);

  DC_UnlockDc(dc);
  return Ret;
}

BOOL
STDCALL
NtGdiMoveToEx(HDC      hDC,
             int      X,
             int      Y,
             LPPOINT  Point)
{
  DC *dc;
  POINT SafePoint;
  NTSTATUS Status = STATUS_SUCCESS;
  BOOL Ret;

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

  Ret = IntGdiMoveToEx(dc, X, Y, (Point ? &SafePoint : NULL));

  if(Point)
  {
    _SEH_TRY
    {
      ProbeForWrite(Point,
                   sizeof(POINT),
                   1);
      *Point = SafePoint;
    }
    _SEH_HANDLE
    {
      Status = _SEH_GetExceptionCode();
    }
    _SEH_END;

    if(!NT_SUCCESS(Status))
    {
      DC_UnlockDc(dc);
      SetLastNtError(Status);
      return FALSE;
    }
  }

  DC_UnlockDc(dc);
  return Ret;
}

BOOL
STDCALL
NtGdiPolyBezier(HDC           hDC,
               CONST LPPOINT  pt,
               DWORD          Count)
{
  DC *dc;
  LPPOINT Safept;
  NTSTATUS Status = STATUS_SUCCESS;
  BOOL Ret;

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

  if(Count > 0)
  {
    _SEH_TRY
    {
      ProbeForRead(pt,
                   Count * sizeof(POINT),
                   1);
    }
    _SEH_HANDLE
    {
      Status = _SEH_GetExceptionCode();
    }
    _SEH_END;
    
    if (!NT_SUCCESS(Status))
    {
      DC_UnlockDc(dc);
      SetLastNtError(Status);
      return FALSE;
    }
    
    Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_BEZIER);
    if(!Safept)
    {
      DC_UnlockDc(dc);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return FALSE;
    }

    _SEH_TRY
    {
      /* pointers were already probed */
      RtlCopyMemory(Safept,
                    pt,
                    Count * sizeof(POINT));
    }
    _SEH_HANDLE
    {

⌨️ 快捷键说明

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