📄 xpol6.c
字号:
/*************************************************************************/
/* */
/* Copyright (c) 1997 - 1999 Accelerated Technology, Inc. */
/* */
/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */
/* subject matter of this material. All manufacturing, reproduction, */
/* use, and sales rights pertaining to this subject matter are governed */
/* by the license agreement. The recipient of this software implicitly */
/* accepts the terms of the license. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* XPOL6.c 1.9 */
/* */
/* COMPONENT */
/* */
/* All */
/* */
/* DESCRIPTION */
/* */
/* This file contains the __mwScanEdge, __mwScanEdgeRestart, */
/* ScanBurst & mwFC functions. */
/* */
/* AUTHOR */
/* */
/* Robert G. Burrill, Accelerated Technology, Inc. */
/* */
/* DATA STRUCTURES */
/* */
/* None */
/* */
/* FUNCTIONS */
/* */
/* None */
/* */
/* DEPENDENCIES */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* BobB 10/2/98 - correction to keep from overwriting */
/* blit record */
/* BobB 5/12/99 Corrected fo pen size 1,1 */
/* BobB 11/9/99 Removed unused variable */
/* */
/*************************************************************************/
#include "meta_wnd.h"
#include "metconst.h" /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h" /* MetaWINDOW Port & Bitmap Definitions */
#include "grafdata.h"
#include "metmacs3.h"
#include "xpol_4.h"
/* Structure used to store the state of suspended edge tracing and later
restore it. */
typedef struct _restartStruc{
byte scanEdgeFirstPass; /* if this is the first time scanning an edge
in the restartable scanning code, 0 else */
byte filler[3];
long restartVector; /* case vector to restart routine */
long restartRemaining; /* # of scan lines left in suspended edge */
long restartAE; /* various registers and variables saved to */
long restartCE; /* restart various routines */
long restartDE;
long restartSN;
long restartBR;
long restartAdvanceAmt;
long restartHeight;
} restartStruc;
long vertexListEnd; /* offset of first location after the last point struc
in the points array */
int lastPointX; /* in previous (relative) mode only, the X and Y */
int lastPointY; /* coordinates of the last point in the vertex list */
/* Function __mwScanEdge scan converts an edge from (X1, Y1) to (X2, Y2),
not including the point at (X2, Y2). If skipFirst == 1, the point at (X1,
Y1) isn't drawn; if skipFirst == 0, it is. For each scan line, the pixel
closest to the scanned edge without being to the left of the scanned edge
is chosen. Scan-converted X coordinates are stored in the array of rects
pointed to by DI. Uses an all-integer approach for speed & precision.
__mwScanEdge is for use in scanning convex polygon edges for which there
is adequate room in the rect list (don't need to be restarted).
Edges must not go bottom to top.
Updates scanListPtr to next element to set in array of rects */
void __mwScanEdge(short startX, short endX, short height, point **scanListPtrPtr,
int skipFirst)
{
short errorTerm;
short advanceAmt;
short deltaX;
short advanceX;
short advanceErrorTerm;
short i;
point *scanListPtr;
scanListPtr = *scanListPtrPtr; /* get pointer to store data */
if ((deltaX = endX - startX) == 0)
{ /* it's a vertical edge--special case it */
height -= skipFirst;
if (height == 0) return; /* no scan lines left after skipping 1st */
for (; height > 0; height--)
{
scanListPtr->X = startX;
scanListPtr += 2;
}
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
if (deltaX < 0)
{ /* move left as we draw */
errorTerm = -height;
advanceAmt = -1;
deltaX = -deltaX; /* width = abs(deltaX) */
}
else
{
errorTerm = -1;
advanceAmt = 1;
}
/* Figure out whether the edge is diagonal, X-major (more horizontal),
or Y-major (more vertical) and handle appropriately.*/
if (deltaX == height)
{ /* it's a diagonal edge--special case */
if (skipFirst == 1)
{ /* skip the first point */
startX += advanceAmt;
height--;
}
while (height > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
startX += advanceAmt;
height--;
}
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
if (deltaX > height)
{ /* it's an X-major (more horz) edge */
i = height;
advanceX = deltaX / height;
advanceErrorTerm = deltaX % height;
if (advanceAmt < 0) advanceX = -advanceX;
if (skipFirst == 1)
{ /* skip the first point */
startX += advanceX;
errorTerm += advanceErrorTerm;
if (errorTerm >= 0)
{ /* time for X coord to advance one extra */
startX += advanceAmt;
errorTerm -= height;
}
i--;
}
while (i > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
startX += advanceX;
errorTerm += advanceErrorTerm;
if (errorTerm >= 0)
{ /* time for X coord to advance one extra */
startX += advanceAmt;
errorTerm -= height;
}
i--;
}
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
/* it's a Y-major (more vertical) edge */
i = height;
if (skipFirst == 1)
{ /* skip the first point */
errorTerm += deltaX;
if (errorTerm >= 0)
{ /* time for X coord to advance */
startX += advanceAmt;
errorTerm -= height;
}
i--;
}
while (i > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
errorTerm += deltaX;
if (errorTerm >= 0)
{ /* time for X coord to advance */
startX += advanceAmt;
errorTerm -= height;
}
i--;
}
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
/* Function __mwScanEdgeRestart is for use in scanning convex polygon
edges for which there is not adequate room in the rect list (need to
be restarted). This is the entry point the first time such an edge is
scanned; restartVector in the restart structure should be called to
restart the line thereafter.
Edges must not go bottom to top.
Updates scanListPtr to next element to set in array of rects */
void __mwScanEdgeRestart(short startX, short endX, short height,
point **scanListPtrPtr, int skipFirst,
restartStruc *restartStrucPtr, int numScans)
{
#define VerticalRestart 1
#define DiagonalRestart 2
#define XMajorRestart 3
#define YMajorRestart 4
short errorTerm;
short advanceAmt;
short deltaX;
short advanceX;
short advanceErrorTerm;
point *scanListPtr;
scanListPtr = *scanListPtrPtr; /* get pointer to store data */
switch (restartStrucPtr->restartVector)
{
/* entry points to load suspended scanning state */
case VerticalRestart:
startX = (short) restartStrucPtr->restartSN;
goto VerticalLoopR; /* never need to skip first point on restart */
case DiagonalRestart:
advanceAmt = (short) restartStrucPtr->restartDE;
startX = (short) restartStrucPtr->restartSN;
goto DiagonalLoopR;
case XMajorRestart:
advanceAmt = (short) restartStrucPtr->restartAdvanceAmt;
height = (short) restartStrucPtr->restartHeight;
advanceX = (short) restartStrucPtr->restartAE;
errorTerm = (short) restartStrucPtr->restartCE;
advanceErrorTerm = (short) restartStrucPtr->restartDE;
startX = (short) restartStrucPtr->restartSN;
goto XMajorLoopR;
case YMajorRestart:
deltaX = (short) restartStrucPtr->restartAE;
errorTerm = (short) restartStrucPtr->restartCE;
advanceAmt = (short) restartStrucPtr->restartDE;
startX = (short) restartStrucPtr->restartSN;
height = (short) restartStrucPtr->restartBR;
goto YMajorLoopR;
default:
goto restartEntry;
}
restartEntry:
/* not the first pass after this */
restartStrucPtr->scanEdgeFirstPass = 0;
if ((deltaX = endX - startX) == 0)
{ /* it's a vertical edge--special case it */
/* restart vector for next time */
restartStrucPtr->restartVector = VerticalRestart;
restartStrucPtr->restartSN = startX; /* this doesn't change
from one pass to the next */
numScans -= skipFirst;
if (numScans == 0) return; /* no scan lines left after skipping 1st */
VerticalLoopR:
for (; numScans > 0; numScans--)
{
scanListPtr->X = startX;
scanListPtr += 2;
}
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
if (deltaX < 0)
{ /* move left as we draw */
errorTerm = -height;
advanceAmt = -1;
deltaX = -deltaX; /* width = abs(deltaX) */
}
else
{
errorTerm = -1;
advanceAmt = 1;
}
/* Figure out whether the edge is diagonal, X-major (more horizontal),
or Y-major (more vertical) and handle appropriately.*/
if (deltaX == height)
{ /* it's a diagonal edge--special case */
/* restart vector for next time */
restartStrucPtr->restartVector = DiagonalRestart;
restartStrucPtr->restartDE = advanceAmt; /* this doesn't change
from one pass to the next */
if (skipFirst == 1)
{ /* skip the first point */
startX += advanceAmt;
numScans--;
}
DiagonalLoopR:
while (numScans > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
startX += advanceAmt;
numScans--;
}
restartStrucPtr->restartSN = startX;
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
return;
}
if (deltaX > height)
{ /* it's an X-major (more horz) edge */
/* restart vector for next time */
restartStrucPtr->restartVector = XMajorRestart;
restartStrucPtr->restartHeight = height;
restartStrucPtr->restartAdvanceAmt = advanceAmt;
advanceX = deltaX / height;
advanceErrorTerm = deltaX % height;
if (advanceAmt < 0) advanceX = -advanceX;
restartStrucPtr->restartAE = advanceX;
restartStrucPtr->restartDE = advanceErrorTerm;
if (skipFirst == 1)
{ /* skip the first point */
startX += advanceX;
errorTerm += advanceErrorTerm;
if (errorTerm >= 0)
{ /* time for X coord to advance one extra */
startX += advanceAmt;
errorTerm -= height;
}
numScans--;
}
XMajorLoopR:
while (numScans > 0)
{
scanListPtr->X = startX;
scanListPtr += 2;
startX += advanceX;
errorTerm += advanceErrorTerm;
if (errorTerm >= 0)
{ /* time for X coord to advance one extra */
startX += advanceAmt;
errorTerm -= height;
}
numScans--;
}
restartStrucPtr->restartCE = errorTerm;
restartStrucPtr->restartSN = startX;
*scanListPtrPtr = scanListPtr; /* update pointer for next time */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -