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

📄 fillshap.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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>

/*
 * a couple macros to fill a single pixel or a line
 */
#define PUTPIXEL(x,y,BrushInst)        \
  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
       dc->CombinedClip,                         \
       &BrushInst.BrushObject,                   \
       x, y, (x)+1, y,                           \
       &RectBounds,                              \
       ROP2_TO_MIX(dc->Dc_Attr.jROP2));

#define PUTLINE(x1,y1,x2,y2,BrushInst) \
  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
       dc->CombinedClip,                         \
       &BrushInst.BrushObject,                   \
       x1, y1, x2, y2,                           \
       &RectBounds,                              \
       ROP2_TO_MIX(dc->Dc_Attr.jROP2));

BOOL FASTCALL
IntGdiPolygon(PDC    dc,
              PPOINT UnsafePoints,
              int    Count)
{
  BITMAPOBJ *BitmapObj;
  PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
  GDIBRUSHINST PenBrushInst, FillBrushInst;
  BOOL ret = FALSE; // default to failure
  RECTL DestRect;
  int CurrentPoint;

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

  if ( NULL == UnsafePoints || Count < 2 )
    {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return FALSE;
    }

  BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
  /* FIXME - BitmapObj can be NULL!!!! don't assert but handle this case gracefully! */
  ASSERT(BitmapObj);

      /* Convert to screen coordinates */
      IntLPtoDP(dc, UnsafePoints, Count);
      for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
	{
	  UnsafePoints[CurrentPoint].x += dc->w.DCOrgX;
	  UnsafePoints[CurrentPoint].y += dc->w.DCOrgY;
	}

      if (PATH_IsPathOpen(dc->w.path))
	ret = PATH_Polygon(dc, UnsafePoints, Count );
      else
      {
	DestRect.left   = UnsafePoints[0].x;
	DestRect.right  = UnsafePoints[0].x;
	DestRect.top    = UnsafePoints[0].y;
	DestRect.bottom = UnsafePoints[0].y;

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

	/* Now fill the polygon with the current brush. */
	FillBrushObj = BRUSHOBJ_LockBrush(dc->Dc_Attr.hbrush);
	if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
	{
          IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
          ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(dc->Dc_Attr.jROP2), UnsafePoints, Count, DestRect );  
	}
	BRUSHOBJ_UnlockBrush(FillBrushObj);

	/* get BRUSHOBJ from current pen. */
	PenBrushObj = PENOBJ_LockPen(dc->Dc_Attr.hpen);
	// Draw the Polygon Edges with the current pen ( if not a NULL pen )
	if (PenBrushObj && !(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
	{
	  IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);

        while(Count-- >1)
          {

// DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
//                                 UnsafePoints[0].x, UnsafePoints[0].y,
//                                 UnsafePoints[1].x, UnsafePoints[1].y );
                                 
  	    ret = IntEngLineTo(&BitmapObj->SurfObj,
			       dc->CombinedClip,
			       &PenBrushInst.BrushObject,
			       UnsafePoints[0].x,          /* From */
			       UnsafePoints[0].y,
			       UnsafePoints[1].x,          /* To */
			       UnsafePoints[1].y,
			       &DestRect,
			       ROP2_TO_MIX(dc->Dc_Attr.jROP2)); /* MIX */
             if(!ret) break;
             UnsafePoints++;
	  }
	}
	PENOBJ_UnlockPen(PenBrushObj);
      }
      BITMAPOBJ_UnlockBitmap(BitmapObj);

  return ret;
}

BOOL FASTCALL
IntGdiPolyPolygon(DC      *dc,
                  LPPOINT Points,
                  LPINT   PolyCounts,
                  int     Count)
{
  while(--Count >=0)
  {
    if(!IntGdiPolygon ( dc, Points, *PolyCounts )) return FALSE;
    Points+=*PolyCounts++;
  }
  return TRUE;
}

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

/*
 * NtGdiEllipse
 *
 * Author
 *    Filip Navara
 *
 * Remarks
 *    This function uses optimized Bresenham's ellipse algorithm. It draws
 *    four lines of the ellipse in one pass.
 *
 * Todo
 *    Make it look like a Windows ellipse.
 */

BOOL STDCALL
NtGdiEllipse(
   HDC hDC,
   int nLeftRect,
   int nTopRect,
   int nRightRect,
   int nBottomRect)
{
   int ix, iy;
   int A, B, C, D;
   int da, db;
   int NewA, NewB, NewC, NewD;
   int nx, ny;
   int CenterX, CenterY;
   int RadiusX, RadiusY;
   int Temp;
   PGDIBRUSHOBJ FillBrush, PenBrush;
   GDIBRUSHINST FillBrushInst, PenBrushInst;
   BITMAPOBJ *BitmapObj;
   RECTL RectBounds;
   PDC dc;
   BOOL ret = TRUE, Cond1, Cond2;

   /*
    * Check the parameters.
    */

   if (nRightRect <= nLeftRect || nBottomRect <= nTopRect)
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return FALSE;
   }

   /*
    * Get pointers to all necessary GDI objects.
    */

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

   FillBrush = BRUSHOBJ_LockBrush(dc->Dc_Attr.hbrush);
   if (NULL == FillBrush)
   {
      DC_UnlockDc(dc);
      SetLastWin32Error(ERROR_INTERNAL_ERROR);
      return FALSE;
   }

   PenBrush = PENOBJ_LockPen(dc->Dc_Attr.hpen);
   if (NULL == PenBrush)
   {
      BRUSHOBJ_UnlockBrush(FillBrush);
      DC_UnlockDc(dc);
      SetLastWin32Error(ERROR_INTERNAL_ERROR);
      return FALSE;
   }

   BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
   if (NULL == BitmapObj)
   {
      BRUSHOBJ_UnlockBrush(FillBrush);
      PENOBJ_UnlockPen(PenBrush);
      DC_UnlockDc(dc);
      SetLastWin32Error(ERROR_INTERNAL_ERROR);
      return FALSE;
   }

   IntGdiInitBrushInstance(&FillBrushInst, FillBrush, dc->XlateBrush);
   IntGdiInitBrushInstance(&PenBrushInst, PenBrush, dc->XlatePen);

   RectBounds.left = nLeftRect;
   RectBounds.right = nRightRect;
   RectBounds.top = nTopRect;
   RectBounds.bottom = nBottomRect;

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

   RectBounds.left += dc->w.DCOrgX;
   RectBounds.right += dc->w.DCOrgX;
   RectBounds.top += dc->w.DCOrgY;
   RectBounds.bottom += dc->w.DCOrgY;

   RadiusX = max((RectBounds.right - RectBounds.left) >> 1, 1);
   RadiusY = max((RectBounds.bottom - RectBounds.top) >> 1, 1);
   CenterX = RectBounds.left + RadiusX;
   CenterY = RectBounds.top + RadiusY;

   if (RadiusX > RadiusY)
   {
      nx = RadiusX;
      ny = RadiusY;
   }
   else
   {
      nx = RadiusY;
      ny = RadiusX;
   }

   da = -1;
   db = 0xFFFF;
   ix = 0;
   iy = nx * 64;
   NewA = 0;
   NewB = (iy + 32) >> 6;
   NewC = 0;
   NewD = (NewB * ny) / nx;

   do {
      A = NewA;
      B = NewB;
      C = NewC;
      D = NewD;

      ix += iy / nx;
      iy -= ix / nx;
      NewA = (ix + 32) >> 6;
      NewB = (iy + 32) >> 6;
      NewC = (NewA * ny) / nx;
      NewD = (NewB * ny) / nx;

      if (RadiusX > RadiusY)
      {
         Temp = A; A = C; C = Temp;
         Temp = B; B = D; D = Temp;
         Cond1 = ((C != NewA) || (B != NewD)) && (NewC <= NewD);
         Cond2 = ((D != NewB) || (A != NewC)) && (NewC <= B);
      }
      else
      {
         Cond1 = ((C != NewC) || (B != NewB)) && (NewA <= NewB);
         Cond2 = ((D != NewD) || (A != NewA)) && (NewA <= B);
      }

      /*
       * Draw the lines going from inner to outer (+ mirrored).
       */

      if ((A > da) && (A < db))
      {
         PUTLINE(CenterX - D, CenterY + A, CenterX + D, CenterY + A, FillBrushInst);
         if (A)
         {
            PUTLINE(CenterX - D, CenterY - A, CenterX + D, CenterY - A, FillBrushInst);
         }
         da = A;
      }

      /*
       * Draw the lines going from outer to inner (+ mirrored).
       */

      if ((B < db) && (B > da))
      {
         PUTLINE(CenterX - C, CenterY + B, CenterX + C, CenterY + B, FillBrushInst);
         PUTLINE(CenterX - C, CenterY - B, CenterX + C, CenterY - B, FillBrushInst);
         db = B;
      }

      /*
       * Draw the pixels on the margin.
       */

      if (Cond1)
      {
         PUTPIXEL(CenterX + C, CenterY + B, PenBrushInst);
         if (C)
            PUTPIXEL(CenterX - C, CenterY + B, PenBrushInst);
         if (B)
         {
            PUTPIXEL(CenterX + C, CenterY - B, PenBrushInst);
            if (C)
               PUTPIXEL(CenterX - C, CenterY - B, PenBrushInst);
         }
      }

      if (Cond2)
      {
         PUTPIXEL(CenterX + D, CenterY + A, PenBrushInst);
         if (D)
            PUTPIXEL(CenterX - D, CenterY + A, PenBrushInst);
         if (A)
         {
            PUTPIXEL(CenterX + D, CenterY - A, PenBrushInst);
            if (D)
               PUTPIXEL(CenterX - D, CenterY - A, PenBrushInst);
         }
      }
   } while (B > A);

   BITMAPOBJ_UnlockBitmap(BitmapObj);
   BRUSHOBJ_UnlockBrush(FillBrush);
   PENOBJ_UnlockPen(PenBrush);
   DC_UnlockDc(dc);

   return ret;
}

typedef struct tagSHAPEPOINT
{
  int X;
  int Y;
  int Type;
} SHAPEPOINT, *PSHAPEPOINT;

#define SHAPEPOINT_TYPE_CIRCLE     'C'
#define SHAPEPOINT_TYPE_LINE_RIGHT 'R' /* Fill at right side of line */
#define SHAPEPOINT_TYPE_LINE_LEFT  'L' /* Fill at left side of line */

#define SETPOINT(x, y, type) \
  ShapePoints[*PointCount].X = (x); \
  ShapePoints[*PointCount].Y = (y); \
  ShapePoints[*PointCount].Type = (type); \
  (*PointCount)++

#define SETCIRCLEPOINT(x, y) \
  SETPOINT(x, y, SHAPEPOINT_TYPE_CIRCLE)

#ifdef TODO
STATIC VOID
FASTCALL
CirclePoints(UINT *PointCount, PSHAPEPOINT ShapePoints, int Left, int Top,
             int Right, int Bottom)
{
  int X, X18, X27, X36, X45;
  int Y, Y14, Y23, Y58, Y67;
  int d, Radius;
  BOOL Even;

  Even = (0 == (Right - Left) % 2);
  Right--;
  Bottom--;
  Radius = (Right - Left) >> 1;

  if (Even)
    {
      X = 0;
      Y = Radius;
      d = 2 - Radius;
      X18 = Right;
      X27 = ((Left + Right) >> 1) + 1;
      X36 = (Left + Right) >> 1;
      X45 = Left;
      Y14 = Top + Radius;
      Y23 = Top;
      Y58 = Top + Radius + 1;
      Y67 = Top + (Right - Left);
      ShapePoints[*PointCount].X = X27;
      SETCIRCLEPOINT(X27, Y23);
      SETCIRCLEPOINT(X36, Y23);
      SETCIRCLEPOINT(X18, Y14);
      SETCIRCLEPOINT(X45, Y14);
      SETCIRCLEPOINT(X18, Y58);
      SETCIRCLEPOINT(X45, Y58);
      SETCIRCLEPOINT(X27, Y67);
      SETCIRCLEPOINT(X36, Y67);
    }
  else
    {
      X = 0;
      Y = Radius;
      d = 1 - Radius;
      X18 = Right;
      X27 = (Left + Right) >> 1;
      X36 = (Left + Right) >> 1;
      X45 = Left;
      Y14 = Top + Radius;
      Y23 = Top;
      Y58 = Top + Radius;
      Y67 = Top + (Right - Left);
      SETCIRCLEPOINT(X27, Y23);
      SETCIRCLEPOINT(X45, Y14);
      SETCIRCLEPOINT(X18, Y58);
      SETCIRCLEPOINT(X27, Y67);
    }

  while (X < Y)
    {
      if (d < 0)
	{
	  d += (X << 1) + (Even ? 4 : 3);

	  X27++;
	  X36--;
	  Y14--;
	  Y58++;
	}
      else
	{
	  d += ((X - Y) << 1) + 5;
	  Y--;

	  Y23++;
	  Y67--;
	  X18--;
	  X45++;
	  X27++;
	  X36--;
	  Y14--;
	  Y58++;
	}
      X++;

      SETCIRCLEPOINT(X27, Y23);
      SETCIRCLEPOINT(X36, Y23);
      SETCIRCLEPOINT(X18, Y14);
      SETCIRCLEPOINT(X45, Y14);
      SETCIRCLEPOINT(X18, Y58);
      SETCIRCLEPOINT(X45, Y58);
      SETCIRCLEPOINT(X27, Y67);
      SETCIRCLEPOINT(X36, Y67);
    }
}

STATIC VOID
LinePoints(UINT *PointCount, PSHAPEPOINT ShapePoints, int Left, int Top,
           int Right, int Bottom, int XTo, int YTo, BOOL Start)
{
  LONG x, y, deltax, deltay, i, xchange, ychange, error;
  int Type;

  x = (Right + Left) >> 1;
  y = (Bottom + Top) >> 1;
  deltax = XTo - x;
  deltay = YTo - y;

  if (deltax < 0)
    {
      xchange = -1;
      deltax = - deltax;
      x--;
    }
  else
    {
      xchange = 1;
    }

  if (deltay < 0)
    {
      ychange = -1;
      deltay = - deltay;
      y--;
      Type = (Start ? SHAPEPOINT_TYPE_LINE_LEFT : SHAPEPOINT_TYPE_LINE_RIGHT);
    }
  else
    {
      ychange = 1;
      Type = (Start ? SHAPEPOINT_TYPE_LINE_RIGHT : SHAPEPOINT_TYPE_LINE_LEFT);
    }

  if (y == YTo)
    {
      for (i = x; i <= XTo; i++)
	{
	  SETPOINT(i, y, Type);
	}
    }
  else if (x == XTo)
    {
      for (i = y; i <= YTo; i++)
	{
	  SETPOINT(x, i, Type);
	}
    }
  else
    {
      error = 0;

      if (deltax < deltay)
	{
	  for (i = 0; i < deltay; i++)
	    {
	      SETPOINT(x, y, Type);
	      y = y + ychange;
	      error = error + deltax;

	      if (deltay <= error)
		{
		  x = x + xchange;
		  error = error - deltay;
		}

⌨️ 快捷键说明

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