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

📄 xpol6.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 3 页
字号:
		return;
	}

	/* it's a Y-major (more vertical) edge */
	/* restart vector for next time */
	restartStrucPtr->restartVector = YMajorRestart;
	restartStrucPtr->restartAE = deltaX;
	restartStrucPtr->restartDE = advanceAmt;
	restartStrucPtr->restartBR = height;
	if (skipFirst == 1)
	{	/* skip the first point */
		errorTerm += deltaX;
		if (errorTerm >= 0)
		{	/* time for X coord to advance */
			startX += advanceAmt;
			errorTerm -= height;
		}
		numScans--;
	}
YMajorLoopR:
	while (numScans > 0)
	{
		scanListPtr->X = startX;
		scanListPtr += 2;
		errorTerm += deltaX;
		if (errorTerm >= 0)
		{	/* time for X coord to advance */
			startX += advanceAmt;
			errorTerm -= height;
		}
		numScans--;
	}
	restartStrucPtr->restartCE = errorTerm;
	restartStrucPtr->restartSN = startX;
	*scanListPtrPtr = scanListPtr;	/* update pointer for next time */
	return;
}


/* Function ScanBurst scans out edges for mwFC - updates pointer to
next vertex */
void ScanBurst(int scanCnt, int skipFirst, short xAdjust, char scanDir,
			   restartStruc *restartStrucPtr, point **scanListPtr,
			   point *currentVertex, short *currentXPtr, point *points, int mode)
{
	int tempXDelta;	/* used by previous mode code */
	int tempYDelta = 0;
	short startX = 0;
	short endX = 0;
	point *nextVertex;
	int numScans;	/* # of scan lines to scan out for edge when doing
					restartable scanning */

	nextVertex = currentVertex;	/* get passed vertex pointer */
	/* are we restarting this edge? */
	if (restartStrucPtr->scanEdgeFirstPass == 1)
	{	/* no, draw from the start, scan convert each line in the edge from
		top to bottom, for as long as we have room to store the rects */
		restartStrucPtr->restartVector = 0;
		if (mode == coordModePrevious)	/* which coord mode? */
		{	/* coord mode is previous (relative) */
			do {
				if (scanDir == 1)	/* scan in ascending order? */
				{	/* yes, point to the next vertex */
					nextVertex = nextVertex + 1;
					if ((long) nextVertex == vertexListEnd)
					{	/* wrap back to the start */
						nextVertex = points;
						/* first point is absolute */
						tempXDelta = nextVertex->X - lastPointX;
						tempYDelta = nextVertex->Y - lastPointY;
					}
						else
					{
						tempXDelta = nextVertex->X;
						tempYDelta = nextVertex->Y;
					}
				}
				else
				{	/* no, point to previous vertex */
					if (nextVertex == points)
					{	/* at the top of the list */
						nextVertex = (point *) vertexListEnd;
						/* first point is absolute */
						tempXDelta = lastPointX - nextVertex->X;
						tempYDelta = lastPointY - nextVertex->Y;
					}
					else
					{
						tempXDelta = - nextVertex->X;
						tempYDelta = - nextVertex->Y;
					}
					nextVertex = nextVertex - 1;
				}

				startX = *currentXPtr;	/* absolute X of this vertex */
				endX = startX + tempXDelta;	/* absolute X of next vertex */
				*currentXPtr  = endX;
				tempYDelta -= skipFirst;	/* # of scan lines drawn for
											this edge */
				if (tempYDelta != 0)	/* any rects to draw? */
				{	/* do we have that much room? */
					if ((tempYDelta < 0) || (tempYDelta > scanCnt))
					{	/* no, we'll have to start and then suspend it */
						/* undo earlier skipFirst to get true height */
						scanCnt += skipFirst;
						tempYDelta += skipFirst;
						numScans = scanCnt;
						/* # of scan lines left to process in this edge */
						restartStrucPtr->restartRemaining = tempYDelta - scanCnt;
						startX += xAdjust;
						endX += xAdjust;
						__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst, restartStrucPtr, numScans);
						return;	/* done with this burst */
					}
					else
					{	/* yes, we can draw this whole edge in a single
						burst */
						scanCnt -= tempYDelta;	/* # of scan lines
												available after this */
						tempYDelta += skipFirst;	/* undo earlier
										skipFirst to get true height */
						startX += xAdjust;
						endX += xAdjust;
						__mwScanEdge(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst);
						scanCnt += skipFirst;
					}
				}
SBPNextEdgeReentry:
				skipFirst = 0;	/* don't skip from now on */
				/* did this edge exactly finish out the buffer or complete
				the polygon? */
			} while (scanCnt > 0);

			return;
		}
		else
		{	/* coord mode is origin (absolute) */
			do {
				startX = nextVertex->X;	/* get previous coords */
				tempYDelta = nextVertex->Y;
				if (scanDir == 1)	/* scan in ascending order? */
				{	/* yes, point to the next vertex */
					nextVertex = nextVertex + 1;
					if ((long) nextVertex == vertexListEnd)
						nextVertex = points;
				}
				else
				{	/* no, point to previous vertex */
					if (nextVertex == points)
					{
						nextVertex = (point *) vertexListEnd;
					}
					nextVertex = nextVertex - 1;
				}

				/*	# of scan lines drawn for this edge */
				endX = nextVertex->X;	/* X of next vertex */
				tempYDelta = nextVertex->Y - tempYDelta - skipFirst;
				if (tempYDelta != 0)	/* any rects to draw? */
				{	/* do we have that much room? */
					if ((tempYDelta < 0) || (tempYDelta > scanCnt))
					{	/* no, we'll have to start and then suspend it */
						/* undo earlier skipFirst to get true height */
						scanCnt += skipFirst;
						tempYDelta += skipFirst;
						numScans = scanCnt;
						/* # of scan lines left to process in this edge */
						restartStrucPtr->restartRemaining = tempYDelta - scanCnt;
						startX += xAdjust;
						endX += xAdjust;
						__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst, restartStrucPtr, numScans);
						return;	/* done with this burst */
					}
					else
					{	/* yes, we can draw this whole edge in a single
						burst */
						scanCnt -= tempYDelta;	/* # of scan lines
												available after this */
						tempYDelta += skipFirst;	/* undo earlier
										skipFirst to get true height */
						startX += xAdjust;
						endX += xAdjust;
						__mwScanEdge(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst);
						scanCnt += skipFirst;
					}
				}
SBNextEdgeReentry:
				skipFirst = 0;	/* don't skip from now on */
				/* did this edge exactly finish out the buffer or complete
				the polygon? */
			} while (scanCnt > 0);

			return;
		}
	}
	else
	{	/* yes, do we have that much room? */
		if (restartStrucPtr->restartRemaining <= scanCnt)
		{	/* yes, so draw whatever remains and move on to the next edge */
			numScans = (int) restartStrucPtr->restartRemaining;
			scanCnt -= numScans;	/* # of scan lines available after this */
			/* next time we're starting a new edge, not restarting this one */
			restartStrucPtr->scanEdgeFirstPass = 1;
			if (scanDir == 1)	/* scan in ascending order? */
			{	/* yes, point to the next vertex */
				nextVertex = nextVertex + 1;
				if ((long) nextVertex == vertexListEnd)
					nextVertex = points;
			}
			else
			{	/* no, point to previous vertex */
				if (nextVertex == points)
				{
					nextVertex = (point *) vertexListEnd;
				}
				nextVertex = nextVertex - 1;
			}
			/* do the last restart */
			__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst, restartStrucPtr, numScans);
			/* which coord mode? */
			if (mode == coordModePrevious) goto SBPNextEdgeReentry;
			goto SBNextEdgeReentry;
		}
		else
		{	/* no, we'll have to restart and then suspend it again */
			numScans = scanCnt;
			/* # of scan lines left to process in this edge */
			restartStrucPtr->restartRemaining -= scanCnt;
			__mwScanEdgeRestart(startX, endX, (short) tempYDelta, scanListPtr,
							skipFirst, restartStrucPtr, numScans);
			return;	/* done with this burst */
		}
	}
}


/* Function mwFC scans and draws a convex polygon.  Intended for internal
use; doesn't check pnLevel.

Parameters:
  lclScratchBufferPtr = far pointer to buffer in which to build rect list;
	the buffer must have a filled-in blitRcd at the top. blitList is
	filled out in this module. We don't just use the default blitRcd
	because: a) this way the blitList and the blitRcd are both in the
	same segment, and, b) this way a caller can fill a convex polygon in
	any arbitrary bitmap
  lclScratchBufferSize = # of bytes in lclScratchBufferPtr (64K-1 max).
	Size includes the blitRcd at the top of the buffer
  points = far pointer to vertex list
  npoints = # of points in points vertex list (must be > 3)
  mode = coordModeOrigin (coordinates are absolute) or coordModePrevious
	(coordinates after the first are relative to the preceding one)
  lclXAdjust = amount to add to X coordinates, used to perform local to
	global coordinate conversion when needed, by being set to
	portOrgn.X - portRect.Xmin; should be set to 0 if coordinates are
	already in global coordinates
  lclYAdjust = amount to add to Y coordinates, used to perform local to
	global coordinate conversion when needed, by being set to
	portOrgn.Y - portRect.Ymin; should be set to 0 if coordinates are
	already in global coordinates

***IMPORTANT NOTES***

blitCnt and blitList are modified in the passed-in blitRcd, so this
should be a throwaway copy, not a permanent or reusable blitRcd.

Coordinates must be either global (in which case the adjust values
should be 0), or local with port origin = TOPBOT (in which case the
adjust values convert from local to global). Coordinates that are
virtual or coordinates with port origin != TOPBOT will not produce
proper results!  */

void mwFC(byte *lclScratchBufferPtr, long lclScratchBufferSize,
		  point * points, int npoints, int mode,
		  long lclXAdjust, long lclYAdjust)
{
	restartStruc leftRestartStruc;	/* stores left edge scanning state
						for edges that are too long to scan in one pass */
	restartStruc rightRestartStruc;	/* ditto for the right edge */
	blitRcd *lclBlitRcdPtr;	/* local bilt record pointer */
	rect *scanListPtrR;	/* offset of next free entry in rect list for
						scanned out polygon */
	point *scanListPtrP;	/* above offset as a point pointer for X values */
	point *scanListPtrPR;	/* above offset as a point pointer for X values */
	long maxRectCnt;	/* maximum # of rect strucs that will fit into the
						working buffer */
	short minPoint_Y;	/* lowest Y coord in polygon */
	short maxPoint_Y;	/* highest Y coord in polygon */
	short minX;	/* lowest X coord in poly */
	short maxX;	/* highest X coord in poly */
	point relPoint;	/* running total of relative points */
	point *minIndexLPtr;	/* pointer to point struc for leftmost point
							with Y coord of minPoint_Y */
	point *minIndexRPtr;	/* pointer to point struc for rightmost point
							with Y coord of minPoint_Y */
/* BobB 11/9/99 - removed the following variable since it is never used
	point *maxIndexPtr; */	/* pointer to point struc for a point with Y coord
						of maxPoint_Y */
	point *lPoints;	/* copy of points pointer */
	point *tmpMinIndexPtr;
	int topIsFlat;	/* 1 if the top of the polygon is flat,
					   0 if it's pointed */
	int currentYScan;	/* Y coord of scan line we're currently processing */
	int polyScans;	/* # of scan lines in polygon */
	int skipFirstL;	/* 1 to skip top scan line on left edge */
	int skipFirstR;	/* likewise for right edge */
	char leftEdgeDir;	/* 1 if left edge runs up through vertex list,
						  -1 if it runs down */
	char skipFill;	/* 1 to skip filling a given burst of scan lines,
					   0 to fill */
	short leftEdgeStartX;	/* in previous mode X coordinates of first point */
	short rightEdgeStartX;	/*   on each edge */
	short deltaXN;
	short deltaYN;
	short deltaXP;
	short deltaYP;
	long deltaXPYN;
	long deltaXNYP;
	rect clpR;	/* Clip rect */
	char rectClipFlag;	/* local copy of rectclip flag in the blitRcd */
	int i;

	/* set the blitList pointer */
	lclBlitRcdPtr = (blitRcd *) ((long) lclScratchBufferPtr);
/* BobB 10/2/98 - corrected the following line to keep from overwriting blitRcd
	lclBlitRcdPtr->blitList = (long) (lclBlitRcdPtr + 1); */
	lclBlitRcdPtr->blitList = (long) (lclBlitRcdPtr) + sizeof(blitRcd);
	/* copy clipping flags and clip rect (if enabled) to local vars
	***region clipping is ignored at this level***/
	rectClipFlag = lclBlitRcdPtr->blitFlags & bfClipRect;
	if (rectClipFlag)
	{
		clpR.Xmin = lclBlitRcdPtr->blitClip->Xmin;
		clpR.Xmax = lclBlitRcdPtr->blitClip->Xmax;
		clpR.Ymin = lclBlitRcdPtr->blitClip->Ymin;
		clpR.Ymax = lclBlitRcdPtr->blitClip->Ymax;
	}

	/* scan the list to find the top and bottom of the polygon & figure out
	how many rects we can handle at time */
	maxRectCnt = (lclScratchBufferSize - sizeof(blitRcd)) / sizeof(rect);
	if (maxRectCnt <= 0) return;	/* return if buffer not big enough */

	relPoint = *points;	/* get first point */
	minX = relPoint.X;	/* initial min and max X coords */
	maxX = minX;
	minPoint_Y = relPoint.Y;	/* initial min and max Y coords */
	maxPoint_Y = minPoint_Y;
	minIndexLPtr = points;	/* initial minIndexLPtr */
/* BobB 11/9/99 - removed the following line since maxIndexPtr is never used
	maxIndexPtr = points;  */	/* initial maxIndexPtr */
	leftEdgeStartX = points->X;	/* X coord of the initial Ymin point */
	lPoints = points;	/* get original pointer */
	lPoints++;	/* point to the next vertex */
	npoints--;	/* count off first point, which we've already done */
	if (mode == coordModePrevious)	/* which coord mode? */
	{	/* coord mode is previous (relative) */
		for (; npoints >= 1; npoints--)
		{
			relPoint.X += lPoints->X;	/* get the next vertex's X & Y coords */
			relPoint.Y += lPoints->Y;	/* as deltas from the last vertex and check min/max */
			if (relPoint.X < minX)
			{
				minX = relPoint.X;
			}
			else
			{
				if (relPoint.X > maxX) maxX = relPoint.X;
			}

⌨️ 快捷键说明

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