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

📄 fillshap.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
  return TRUE;
}

BOOL
STDCALL
NtGdiRectangle(HDC  hDC,
              int  LeftRect,
              int  TopRect,
              int  RightRect,
              int  BottomRect)
{
  DC   *dc;
  BOOL ret; // default to failure

  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 = IntRectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
  DC_UnlockDc ( dc );

  return ret;
}


BOOL
FASTCALL
IntRoundRect(
	PDC  dc,
	int  left,
	int  top,
	int  right,
	int  bottom,
	int  xCurveDiameter,
	int  yCurveDiameter)
{
  BITMAPOBJ   *BitmapObj;
  PGDIBRUSHOBJ   PenBrushObj, FillBrushObj;
  GDIBRUSHINST FillBrushInst, PenBrushInst;
  RECTL      RectBounds;
  int potential_steps;
  int i, col, row, width, height, x1, x1start, x2, x2start, y1, y2;
  int xradius, yradius;
  //float aspect_square;
  long a_square, b_square,
    two_a_square, two_b_square,
    four_a_square, four_b_square,
    d, dinc, ddec;
  BOOL first,
    ret = TRUE; // default to success

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

  if ( PATH_IsPathOpen(dc->w.path) )
    return PATH_RoundRect ( dc, left, top, right, bottom,
                            xCurveDiameter, yCurveDiameter );

  xradius = xCurveDiameter >> 1;
  yradius = yCurveDiameter >> 1;

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

  RectBounds.left = left;
  RectBounds.right = right;
  RectBounds.top = top;
  RectBounds.bottom = bottom;

  BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
  if (!BitmapObj)
  {
    /* Nothing to do, as we don't have a bitmap */
    SetLastWin32Error(ERROR_INTERNAL_ERROR);
    return FALSE;
  }

  FillBrushObj = BRUSHOBJ_LockBrush(dc->Dc_Attr.hbrush);
  if (FillBrushObj)
  {
    if (FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)
    {
      /* make null brush check simpler... */
      BRUSHOBJ_UnlockBrush(FillBrushObj);
      FillBrushObj = NULL;
    }
    else
    {
      IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
    }
  }

  PenBrushObj = PENOBJ_LockPen(dc->Dc_Attr.hpen);
  if (PenBrushObj)
  {
    if (PenBrushObj->flAttrs & GDIBRUSH_IS_NULL)
    {
      /* make null pen check simpler... */
      PENOBJ_UnlockPen(PenBrushObj);
      PenBrushObj = NULL;
    }
    else
    {
      IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
    }
  }

  right--;
  bottom--;

  width = right - left;
  height = bottom - top;

  if ( (xradius<<1) > width )
    xradius = width >> 1;
  if ( (yradius<<1) > height )
    yradius = height >> 1;

  b_square = yradius * yradius;
  a_square = xradius * xradius;
  row = yradius;
  col = 0;
  two_a_square = a_square << 1;
  four_a_square = a_square << 2;
  four_b_square = b_square << 2;
  two_b_square = b_square << 1;
  d = two_a_square * ((row - 1) * (row))
    + a_square
    + two_b_square * (1 - a_square);

  x1 = left+xradius;
  x2 = right-xradius;
  y1 = top;
  y2 = bottom;

  x1start = x1;
  x2start = x2;

  dinc = two_b_square*3; /* two_b_square * (3 + (col << 1)); */
  ddec = four_a_square * row;

  first = TRUE;
  for ( ;; )
  {
    if ( d >= 0 )
    {
      if ( FillBrushObj )
        PUTLINE ( x1, y1, x2, y1, FillBrushInst );
      if ( first )
      {
	if ( PenBrushObj )
	{
	  if ( x1start > x1 )
	  {
	    PUTLINE ( x1, y1, x1start, y1, PenBrushInst );
	    PUTLINE ( x2start+1, y2, x2+1, y2, PenBrushInst );
	  }
	  else
	  {
	    PUTPIXEL ( x1, y1, PenBrushInst );
	    PUTPIXEL ( x2, y2, PenBrushInst );
	  }
	}
	first = FALSE;
      }
      else
      {
	if ( FillBrushObj )
	  PUTLINE ( x1, y2, x2, y2, FillBrushInst );
	if ( PenBrushObj )
	{
	  if ( x1start >= x1 )
	  {
	    PUTLINE ( x1, y1, x1start+1, y1, PenBrushInst );
	    PUTLINE ( x2start, y2, x2+1, y2, PenBrushInst );
	  }
	  else
	  {
	    PUTPIXEL ( x1, y1, PenBrushInst );
	    PUTPIXEL ( x2, y2, PenBrushInst );
	  }
	}
      }
      if ( PenBrushObj )
      {
	if ( x1start > x1 )
	{
	  PUTLINE ( x1, y2, x1start+1, y2, PenBrushInst );
	  PUTLINE ( x2start, y1, x2+1, y1, PenBrushInst );
	}
	else
	{
	  PUTPIXEL ( x1, y2, PenBrushInst );
	  PUTPIXEL ( x2, y1, PenBrushInst );
	}
      }
      x1start = x1-1;
      x2start = x2+1;
      row--, y1++, y2--, ddec -= four_a_square;
      d -= ddec;
    }

    potential_steps = ( a_square * row ) / b_square - col + 1;
    while ( d < 0 && potential_steps-- )
    {
      d += dinc; /* two_b_square * (3 + (col << 1)); */
      col++, x1--, x2++, dinc += four_b_square;
    }

    if ( a_square * row <= b_square * col )
      break;
  };

  d = two_b_square * (col + 1) * col
    + two_a_square * (row * (row - 2) + 1)
    + (1 - two_a_square) * b_square;
  dinc = ddec; /* four_b_square * col; */
  ddec = two_a_square * ((row << 1) - 3);

  while ( row )
  {
    if ( FillBrushObj )
    {
      PUTLINE ( x1, y1, x2, y1, FillBrushInst );
      PUTLINE ( x1, y2, x2, y2, FillBrushInst );
    }
    if ( PenBrushObj )
    {
      PUTPIXEL ( x2, y1, PenBrushInst );
      PUTPIXEL ( x1, y2, PenBrushInst );
      PUTPIXEL ( x2, y2, PenBrushInst );
      PUTPIXEL ( x1, y1, PenBrushInst );
    }

    if ( d <= 0 )
    {
      col++, x1--, x2++, dinc += four_b_square;
      d += dinc; //four_b_square * col;
    }

    row--, y1++, y2--, ddec -= four_a_square;
    d -= ddec; //two_a_square * ((row << 1) - 3);
  }

  if ( FillBrushObj )
  {
    PUTLINE ( left, y1, right, y1, FillBrushInst );
    PUTLINE ( left, y2, right, y2, FillBrushInst );
  }
  if ( PenBrushObj )
  {
    if ( x1 > (left+1) )
    {
      PUTLINE ( left, y1, x1, y1, PenBrushInst );
      PUTLINE ( x2+1, y1, right, y1, PenBrushInst );
      PUTLINE ( left+1, y2, x1, y2, PenBrushInst );
      PUTLINE ( x2+1, y2, right+1, y2, PenBrushInst );
    }
    else
    {
      PUTPIXEL ( left, y1, PenBrushInst );
      PUTPIXEL ( right, y2, PenBrushInst );
    }
  }

  x1 = left+xradius;
  x2 = right-xradius;
  y1 = top+yradius;
  y2 = bottom-yradius;

  if ( FillBrushObj )
  {
    for ( i = y1+1; i < y2; i++ )
      PUTLINE ( left, i, right, i, FillBrushInst );
  }

  if ( PenBrushObj )
  {
    PUTLINE ( x1,    top,    x2,    top,    PenBrushInst );
    PUTLINE ( right, y1,     right, y2,     PenBrushInst );
    PUTLINE ( x2,    bottom, x1,    bottom, PenBrushInst );
    PUTLINE ( left,  y2,     left,  y1,     PenBrushInst );
  }

  BITMAPOBJ_UnlockBitmap(BitmapObj);
  if(PenBrushObj != NULL)
    PENOBJ_UnlockPen(PenBrushObj);
  if(FillBrushObj != NULL)
    BRUSHOBJ_UnlockBrush(FillBrushObj);

  return ret;
}

BOOL
STDCALL
NtGdiRoundRect(
	HDC  hDC,
	int  LeftRect,
	int  TopRect,
	int  RightRect,
	int  BottomRect,
	int  Width,
	int  Height)
{
  DC   *dc = DC_LockDc(hDC);
  BOOL  ret = FALSE; /* default to failure */

  DPRINT("NtGdiRoundRect(0x%x,%i,%i,%i,%i,%i,%i)\n",hDC,LeftRect,TopRect,RightRect,BottomRect,Width,Height);
  if ( !dc )
  {
    DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
    SetLastWin32Error(ERROR_INVALID_HANDLE);
  }
  else if (dc->IsIC)
  {
    DC_UnlockDc(dc);
    /* Yes, Windows really returns TRUE in this case */
    ret = TRUE;
  }
  else
  {
    ret = IntRoundRect ( dc, LeftRect, TopRect, RightRect, BottomRect, Width, Height );
    DC_UnlockDc ( dc );
  }

  return ret;
}

BOOL FASTCALL
IntGdiGradientFill(
  DC *dc,
  PTRIVERTEX pVertex,
  ULONG uVertex,
  PVOID pMesh,
  ULONG uMesh,
  ULONG ulMode)
{
  BITMAPOBJ *BitmapObj;
  PPALGDI PalDestGDI;
  XLATEOBJ *XlateObj;
  RECTL Extent;
  POINTL DitherOrg;
  ULONG Mode, i;
  BOOL Ret;

  ASSERT(dc);
  ASSERT(pVertex);
  ASSERT(uVertex);
  ASSERT(pMesh);
  ASSERT(uMesh);

  /* check parameters */
  if(ulMode & GRADIENT_FILL_TRIANGLE)
  {
    PGRADIENT_TRIANGLE tr = (PGRADIENT_TRIANGLE)pMesh;

    for(i = 0; i < uMesh; i++, tr++)
    {
      if(tr->Vertex1 >= uVertex ||
         tr->Vertex2 >= uVertex ||
         tr->Vertex3 >= uVertex)
      {
        SetLastWin32Error(ERROR_INVALID_PARAMETER);
        return FALSE;
      }
    }
  }
  else
  {
    PGRADIENT_RECT rc = (PGRADIENT_RECT)pMesh;
    for(i = 0; i < uMesh; i++, rc++)
    {
      if(rc->UpperLeft >= uVertex || rc->LowerRight >= uVertex)
      {
        SetLastWin32Error(ERROR_INVALID_PARAMETER);
        return FALSE;
      }
    }
  }

  /* calculate extent */
  Extent.left = Extent.right = pVertex->x;
  Extent.top = Extent.bottom = pVertex->y;
  for(i = 0; i < uVertex; i++)
  {
    Extent.left = min(Extent.left, (pVertex + i)->x);
    Extent.right = max(Extent.right, (pVertex + i)->x);
    Extent.top = min(Extent.top, (pVertex + i)->y);
    Extent.bottom = max(Extent.bottom, (pVertex + i)->y);
  }

  DitherOrg.x = dc->w.DCOrgX;
  DitherOrg.y = dc->w.DCOrgY;
  Extent.left += DitherOrg.x;
  Extent.right += DitherOrg.x;
  Extent.top += DitherOrg.y;
  Extent.bottom += DitherOrg.y;

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

  PalDestGDI = PALETTE_LockPalette(dc->w.hPalette);
  /* FIXME - PalDestGDI can be NULL!!! Don't assert but handle this case gracefully! */
  ASSERT(PalDestGDI);
  Mode = PalDestGDI->Mode;
  PALETTE_UnlockPalette(PalDestGDI);

  XlateObj = (XLATEOBJ*)IntEngCreateXlate(Mode, PAL_RGB, dc->w.hPalette, NULL);
  ASSERT(XlateObj);

  Ret = IntEngGradientFill(&BitmapObj->SurfObj,
                           dc->CombinedClip,
                           XlateObj,
                           pVertex,
                           uVertex,
                           pMesh,
                           uMesh,
                           &Extent,
                           &DitherOrg,
                           ulMode);

  BITMAPOBJ_UnlockBitmap(BitmapObj);
  EngDeleteXlate(XlateObj);

  return Ret;
}

BOOL
STDCALL
NtGdiGradientFill(
  HDC hdc,
  PTRIVERTEX pVertex,
  ULONG uVertex,
  PVOID pMesh,
  ULONG uMesh,
  ULONG ulMode)
{
  DC *dc;
  BOOL Ret;
  PTRIVERTEX SafeVertex;
  PVOID SafeMesh;
  ULONG SizeMesh;
  NTSTATUS Status = STATUS_SUCCESS;

  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(!pVertex || !uVertex || !pMesh || !uMesh)
  {
    DC_UnlockDc(dc);
    SetLastWin32Error(ERROR_INVALID_PARAMETER);
    return FALSE;
  }

  switch(ulMode)
  {
    case GRADIENT_FILL_RECT_H:
    case GRADIENT_FILL_RECT_V:
      SizeMesh = uMesh * sizeof(GRADIENT_RECT);
      break;
    case GRADIENT_FILL_TRIANGLE:
      SizeMesh = uMesh * sizeof(TRIVERTEX);
      break;
    default:
      DC_UnlockDc(dc);
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
      return FALSE;
  }
  
  _SEH_TRY
  {
    ProbeForRead(pVertex,
                 uVertex * sizeof(TRIVERTEX),
                 1);
    ProbeForRead(pMesh,
                 SizeMesh,
                 1);
  }
  _SEH_HANDLE
  {
    Status = _SEH_GetExceptionCode();
  }
  _SEH_END;
  
  if (!NT_SUCCESS(Status))
  {
    DC_UnlockDc(dc);
    SetLastWin32Error(Status);
    return FALSE;
  }

  if(!(SafeVertex = ExAllocatePoolWithTag(PagedPool, (uVertex * sizeof(TRIVERTEX)) + SizeMesh, TAG_SHAPE)))
  {
    DC_UnlockDc(dc);
    SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
    return FALSE;
  }
  
  SafeMesh = (PTRIVERTEX)(SafeVertex + uVertex);

  _SEH_TRY
  {
    /* pointers were already probed! */
    RtlCopyMemory(SafeVertex,
                  pVertex,
                  uVertex * sizeof(TRIVERTEX));
    RtlCopyMemory(SafeMesh,
                  pMesh,
                  SizeMesh);
  }
  _SEH_HANDLE
  {
    Status = _SEH_GetExceptionCode();
  }
  _SEH_END;
  
  if(!NT_SUCCESS(Status))
  {
    DC_UnlockDc(dc);
    ExFreePool(SafeVertex);
    SetLastNtError(Status);
    return FALSE;
  }

  Ret = IntGdiGradientFill(dc, SafeVertex, uVertex, SafeMesh, uMesh, ulMode);

  DC_UnlockDc(dc);
  ExFreePool(SafeVertex);
  return Ret;
}

/* EOF */

⌨️ 快捷键说明

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