path.c

来自「一个类似windows」· C语言 代码 · 共 1,307 行 · 第 1/3 页

C
1,307
字号
  /* Start a new stroke */
  pPath->newStroke = TRUE;

  return TRUE;
}

/* PATH_LineTo
 *
 * Should be called when a LineTo is performed on a DC that has an
 * open path. This adds a PT_LINETO entry to the path (and possibly
 * a PT_MOVETO entry, if this is the first LineTo in a stroke).
 * Returns TRUE if successful, else FALSE.
 */
BOOL
FASTCALL
PATH_LineTo ( PDC dc, INT x, INT y )
{
  GdiPath *pPath;
  POINT point, pointCurPos;

  /* Get pointer to path */
  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  /* Convert point to device coordinates */
  point.x=x;
  point.y=y;
  CoordLPtoDP ( dc, &point );

  /* Add a PT_MOVETO if necessary */
  if ( pPath->newStroke )
  {
    pPath->newStroke = FALSE;
    IntGetCurrentPositionEx ( dc, &pointCurPos );
    CoordLPtoDP ( dc, &pointCurPos );
    if ( !PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO) )
      return FALSE;
  }

  /* Add a PT_LINETO entry */
  return PATH_AddEntry(pPath, &point, PT_LINETO);
}

/* PATH_Rectangle
 *
 * Should be called when a call to Rectangle is performed on a DC that has
 * an open path. Returns TRUE if successful, else FALSE.
 */
BOOL
FASTCALL
PATH_Rectangle ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
{
  GdiPath *pPath;
  POINT corners[2], pointTemp;
  INT   temp;

  /* Get pointer to path */
  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  /* Convert points to device coordinates */
  corners[0].x=x1;
  corners[0].y=y1;
  corners[1].x=x2;
  corners[1].y=y2;
  IntLPtoDP ( dc, corners, 2 );

  /* Make sure first corner is top left and second corner is bottom right */
  if ( corners[0].x > corners[1].x )
  {
    temp=corners[0].x;
    corners[0].x=corners[1].x;
    corners[1].x=temp;
  }
  if ( corners[0].y > corners[1].y )
  {
    temp=corners[0].y;
    corners[0].y=corners[1].y;
    corners[1].y=temp;
  }

  /* In GM_COMPATIBLE, don't include bottom and right edges */
  if ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
  {
    corners[1].x--;
    corners[1].y--;
  }

  /* Close any previous figure */
  if ( !IntCloseFigure ( dc ) )
  {
    /* The NtGdiCloseFigure call shouldn't have failed */
    assert(FALSE);
    return FALSE;
  }

  /* Add four points to the path */
  pointTemp.x=corners[1].x;
  pointTemp.y=corners[0].y;
  if ( !PATH_AddEntry(pPath, &pointTemp, PT_MOVETO) )
    return FALSE;
  if ( !PATH_AddEntry(pPath, corners, PT_LINETO) )
    return FALSE;
  pointTemp.x=corners[0].x;
  pointTemp.y=corners[1].y;
  if ( !PATH_AddEntry(pPath, &pointTemp, PT_LINETO) )
    return FALSE;
  if ( !PATH_AddEntry(pPath, corners+1, PT_LINETO) )
    return FALSE;

  /* Close the rectangle figure */
  if ( !IntCloseFigure ( dc ) )
  {
    /* The IntCloseFigure call shouldn't have failed */
    assert(FALSE);
    return FALSE;
  }

  return TRUE;
}

BOOL
FASTCALL
PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius)
{
  UNIMPLEMENTED;
  return FALSE;
}

/* PATH_Ellipse
 *
 * Should be called when a call to Ellipse is performed on a DC that has
 * an open path. This adds four Bezier splines representing the ellipse
 * to the path. Returns TRUE if successful, else FALSE.
 */
BOOL
FASTCALL
PATH_Ellipse ( PDC dc, INT x1, INT y1, INT x2, INT y2 )
{
  /* TODO: This should probably be revised to call PATH_AngleArc */
  /* (once it exists) */
  return PATH_Arc ( dc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2 );
}

/* PATH_Arc
 *
 * Should be called when a call to Arc is performed on a DC that has
 * an open path. This adds up to five Bezier splines representing the arc
 * to the path. Returns TRUE if successful, else FALSE.
 */
BOOL
FASTCALL
PATH_Arc ( PDC dc, INT x1, INT y1, INT x2, INT y2,
   INT xStart, INT yStart, INT xEnd, INT yEnd)
{
  GdiPath *pPath;
  double  angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
          /* Initialize angleEndQuadrant to silence gcc's warning */
  double  x, y;
  FLOAT_POINT corners[2], pointStart, pointEnd;
  BOOL    start, end;
  INT     temp;
  BOOL    clockwise;

  /* FIXME: This function should check for all possible error returns */
  /* FIXME: Do we have to respect newStroke? */

  ASSERT ( dc );

  clockwise = ( IntGdiGetArcDirection(dc) == AD_CLOCKWISE );

  /* Get pointer to path */
  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  /* FIXME: Do we have to close the current figure? */

  /* Check for zero height / width */
  /* FIXME: Only in GM_COMPATIBLE? */
  if ( x1==x2 || y1==y2 )
    return TRUE;

  /* Convert points to device coordinates */
  corners[0].x=(FLOAT)x1;
  corners[0].y=(FLOAT)y1;
  corners[1].x=(FLOAT)x2;
  corners[1].y=(FLOAT)y2;
  pointStart.x=(FLOAT)xStart;
  pointStart.y=(FLOAT)yStart;
  pointEnd.x=(FLOAT)xEnd;
  pointEnd.y=(FLOAT)yEnd;
  INTERNAL_LPTODP_FLOAT(dc, corners);
  INTERNAL_LPTODP_FLOAT(dc, corners+1);
  INTERNAL_LPTODP_FLOAT(dc, &pointStart);
  INTERNAL_LPTODP_FLOAT(dc, &pointEnd);

  /* Make sure first corner is top left and second corner is bottom right */
  if ( corners[0].x > corners[1].x )
  {
    temp=corners[0].x;
    corners[0].x=corners[1].x;
    corners[1].x=temp;
  }
  if ( corners[0].y > corners[1].y )
  {
    temp=corners[0].y;
    corners[0].y=corners[1].y;
    corners[1].y=temp;
  }

  /* Compute start and end angle */
  PATH_NormalizePoint(corners, &pointStart, &x, &y);
  angleStart=atan2(y, x);
  PATH_NormalizePoint(corners, &pointEnd, &x, &y);
  angleEnd=atan2(y, x);

  /* Make sure the end angle is "on the right side" of the start angle */
  if ( clockwise )
  {
    if ( angleEnd <= angleStart )
    {
      angleEnd+=2*M_PI;
      assert(angleEnd>=angleStart);
    }
  }
  else
  {
    if(angleEnd>=angleStart)
    {
      angleEnd-=2*M_PI;
      assert(angleEnd<=angleStart);
    }
  }

  /* In GM_COMPATIBLE, don't include bottom and right edges */
  if ( IntGetGraphicsMode(dc) == GM_COMPATIBLE )
  {
    corners[1].x--;
    corners[1].y--;
  }

  /* Add the arc to the path with one Bezier spline per quadrant that the
   * arc spans */
  start=TRUE;
  end=FALSE;
  do
  {
    /* Determine the start and end angles for this quadrant */
    if(start)
    {
      angleStartQuadrant=angleStart;
      if ( clockwise )
        angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2;
      else
        angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2;
    }
    else
    {
      angleStartQuadrant=angleEndQuadrant;
      if ( clockwise )
        angleEndQuadrant+=M_PI_2;
      else
        angleEndQuadrant-=M_PI_2;
    }

    /* Have we reached the last part of the arc? */
    if ( (clockwise && angleEnd<angleEndQuadrant)
      || (!clockwise && angleEnd>angleEndQuadrant)
      )
    {
      /* Adjust the end angle for this quadrant */
     angleEndQuadrant = angleEnd;
     end = TRUE;
    }

    /* Add the Bezier spline to the path */
    PATH_DoArcPart ( pPath, corners, angleStartQuadrant, angleEndQuadrant, start );
    start = FALSE;
  } while(!end);

  return TRUE;
}

BOOL
FASTCALL
PATH_PolyBezierTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
  GdiPath *pPath;
  POINT pt;
  ULONG i;

  ASSERT ( dc );
  ASSERT ( pts );
  ASSERT ( cbPoints );

  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  /* Add a PT_MOVETO if necessary */
  if ( pPath->newStroke )
  {
    pPath->newStroke=FALSE;
    IntGetCurrentPositionEx ( dc, &pt );
    CoordLPtoDP ( dc, &pt );
    if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
        return FALSE;
  }

  for(i = 0; i < cbPoints; i++)
  {
    pt = pts[i];
    CoordLPtoDP ( dc, &pt );
    PATH_AddEntry(pPath, &pt, PT_BEZIERTO);
  }
  return TRUE;
}

BOOL
FASTCALL
PATH_PolyBezier ( PDC dc, const POINT *pts, DWORD cbPoints )
{
  GdiPath *pPath;
  POINT   pt;
  ULONG   i;

  ASSERT ( dc );
  ASSERT ( pts );
  ASSERT ( cbPoints );

  PATH_GetPathFromDC ( dc, &pPath );

   /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  for ( i = 0; i < cbPoints; i++ )
  {
    pt = pts[i];
    CoordLPtoDP ( dc, &pt );
    PATH_AddEntry ( pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO );
  }

  return TRUE;
}

BOOL
FASTCALL
PATH_Polyline ( PDC dc, const POINT *pts, DWORD cbPoints )
{
  GdiPath *pPath;
  POINT   pt;
  ULONG   i;

  ASSERT ( dc );
  ASSERT ( pts );
  ASSERT ( cbPoints );

  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  for ( i = 0; i < cbPoints; i++ )
  {
    pt = pts[i];
    CoordLPtoDP ( dc, &pt );
    PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO);
  }
  return TRUE;
}

BOOL
FASTCALL
PATH_PolylineTo ( PDC dc, const POINT *pts, DWORD cbPoints )
{
  GdiPath *pPath;
  POINT   pt;
  ULONG   i;

  ASSERT ( dc );
  ASSERT ( pts );
  ASSERT ( cbPoints );

  PATH_GetPathFromDC ( dc, &pPath );

  /* Check that path is open */
  if ( pPath->state != PATH_Open )
    return FALSE;

  /* Add a PT_MOVETO if necessary */
  if ( pPath->newStroke )
  {
    pPath->newStroke = FALSE;
    IntGetCurrentPositionEx ( dc, &pt );
    CoordLPtoDP ( dc, &pt );
    if ( !PATH_AddEntry(pPath, &pt, PT_MOVETO) )
      return FALSE;
  }

  for(i = 0; i < cbPoints; i++)
  {
    pt = pts[i];
    CoordLPtoDP ( dc, &pt );
    PATH_AddEntry(pPath, &pt, PT_LINETO);
  }

  return TRUE;
}


BOOL
FASTCALL
PATH_Polygon ( PDC dc, const POINT *pts, DWORD cbPoints )
{
  GdiPath *pPath;
  POINT   pt;
  ULONG   i;

  ASSERT ( dc );
  ASSERT ( pts );

  PATH_GetPathFromDC ( dc, &pPath );

⌨️ 快捷键说明

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