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

📄 reg09.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 C
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************/
/*                                                                       */
/*         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          */
/*                                                                       */
/*      REG09.c                                          1.9             */
/*                                                                       */
/* COMPONENT                                                             */
/*                                                                       */
/*      All                                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This file contains the mwMergeRegion function.                   */
/*                                                                       */
/* AUTHOR                                                                */
/*                                                                       */
/*      Giac Dinh, Accelerated Technology, Inc.                          */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* FUNCTIONS                                                             */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* DEPENDENCIES           mpWorkEnd                                      */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         NAME            DATE                    REMARKS               */
/*                                                                       */
/*		   BobB			  5/5/98		Corrected to provide for case of */
/* two non-overlapping rectangles in the list.                           */
/*         BobB          11/9/99        Removed unused initialization    */
/*                                                                       */
/*************************************************************************/

#include "meta_wnd.h"
#include "metconst.h"    /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h"    /* MetaWINDOW Port & Bitmap Definitions */
#include "grafdata.h"
#include "metmacs3.h"


struct RBlock{
		struct RBlock* NextBlock;
		long rX;
		signed char rDir;
		byte rList;
		short rAlign;
		long rCount;
		};

rect *destPtr;
rect *destSave;

#if(SIZENAT == 4)
	#define STACK_BUFFER_SIZE 0x1000  
#else
	#define STACK_BUFFER_SIZE 0x1800
#endif 

/* Function mwMergeRegion() merges one or two YX sorted rectangle lists to 
create an new region rectangle list (also YX banded and sorted). NUMRECT1 and 
NUMRECT2 define the number of rectangles contained RECTLIST1 and RECTLIST2,
respectively.  Rectangle lists passed to mwMergeRegion() must be YX sorted
on the upper left corner, and must be in global coordinates.  A zero (0)
value for NUMRECT2 and "NULL" pointer for RECTLIST2 may be passed to create
a region from the sorted rectangles in RECTLIST1 only.

SIZERGN specifies the number of bytes available in the destination region,
DESTRGN.  To determine the required space for a region, a "NULL" DESTRGN 
pointer with a zero (0) SIZERGN value may be passed (no region is created,
only the size required is returned).

(For the region sizing case, the general memory pool in GRAFIX_DATA is used
to store the current YX band if and only if the general pool is larger than
half the size of the buffer allocated on the stack; otherwise, half the
stack buffer is used for storing the current YX band, and the other half is
used for the AET. If the general memory pool is used, or when a region is
actually being built, then the entire stack buffer is used for the AET. It
would be nice if the AET could be stored in the memory pool when it was
larger, so that larger numbers of rects on the same scan line could be
handled, but it's really handy to have the AET in SS.  Beside, we *do*
handle up to 768 edges (384 rects) on one scan line, which should be
adequate for most purposes!)

RGNOP specifies the region merge operation to be performed:

	0	Union (combine) RECTLIST1 with RECTLIST2.
	1	Intersection of RECTLIST1 and RECTLIST2.
	2	Subtract - RECTLIST1 with RECTLIST2 subtracted from it.
	3	XOR - areas of RECTLIST1 and RECTLIST2 not in both.

mwMergeRegion() returns returns two types of values dependent on if a
DESTRGN pointer is passed or not (NULL).  If SIZERGN is zero and DESTRGN
is NULL, mwMergeRegion() computes and returns the size (number of bytes)
needed for DESTRGN.  If SIZERGN is non-zero and DESTRGN in not NULL, mwMerge-
Region() returns the GrafErr status from creating the new region: 0 = no
errors, non-0 = GrafError() value.  */


unsigned int mwMergeRegion (int numRects1, rect *rectList1,
			     int numRects2, rect *rectList2,int sizeRGN,
				 region *destRGN, int rgnOP )
{
#define LEFT_EDGE    1
#define RGHT_EDGE   -1
#define RECT_LST1    1	
#define RECT_LST2   -1

	void SetupEmptyRegion(region *destRGN, int makeRegion, int sizeRGN);
	int HandleChange(region *destRGN, int *destSizeLeft, rect *destScanMax,
				 int baseDestSize, int curtY, int makeRegion);

	byte memPool[STACK_BUFFER_SIZE];	/* working storage space */
	struct RBlock aetHead;	/* the head of AET blocks */	

	char makeRegion;
	int destSizeLeft;
	int baseDestSize;
	unsigned int regionSize;
	int rXmin, rXmax;
	rect *destScanMax;
	int curtY;
	long freeBlocks;
	int rlistID;
	int edgeState;
	short grafErrValue;
 
	struct RBlock *dnPtr;
	struct RBlock *snPtr;
	
	/* Immediate value for looping or temporary storage  */
	short RLmin;
	rect *temRect;
	short temNUM;	
	int ret_val;	
/* BobB 11/9/99 - changed the following line since initialization is never used
	short alTest=0,ahTest=0; */
	short alTest,ahTest;
	
	/* struct declaration  */	
    struct RBlock *curtLeftEdge;
	struct RBlock *bePtr;

	baseDestSize = mpWorkEnd - mpWorkSpace;

	if(destRGN == 0)
	{

/* Mark that not building region, just find how large the 
   buffer. If the general memory pool is bigger than half
   the stack, store the current YX band.  */
		makeRegion = 0;

/* If smaller than half split stack memPool */	
		if(baseDestSize <= (STACK_BUFFER_SIZE/2))
		{
			baseDestSize = STACK_BUFFER_SIZE/2;
			destPtr = (rect *)(&memPool[baseDestSize]);
			temNUM = baseDestSize / sizeof(struct RBlock);
		}
		else
		{
			temNUM = STACK_BUFFER_SIZE / sizeof(struct RBlock);
			destPtr = (rect *) mpWorkSpace;
		}
	}
/*********** Setup to build a region **********/
	else
	{
		makeRegion = 1;
		destSizeLeft = sizeRGN - sizeof(region) - sizeof(rect);
		if(destSizeLeft < 0)
		{
			grafErrValue = c_RectList + c_RgnOflow;
			nuGrafErr(grafErrValue);
				
			SetupEmptyRegion(destRGN, makeRegion, sizeRGN);
			return(0);
		}
		destRGN->rgnAlloc = sizeRGN;

		destPtr = (rect *)((long) destRGN + sizeof(region));
 
/* value with which will fill initial sentinel  */
		destPtr->Xmin = rgnBOS;
		destPtr->Xmax = rgnBOS;
		destPtr->Ymin = rgnBOS;
		destPtr->Ymax = rgnBOS;
		destPtr++;

		temNUM = STACK_BUFFER_SIZE/sizeof(struct RBlock);
	}

	destScanMax = destPtr;
	destSave = destPtr;
	regionSize = sizeof(region) + sizeof(rect);
	/* Allocate CE rects at memPool entirely to free list  */
	freeBlocks = (long) memPool;
	temNUM--;				

	/* Point to the next linked block  */
    snPtr = (struct RBlock *) memPool;/* start of AET space Block  */	
	do{
		snPtr->NextBlock = snPtr + 1; /* snPtr->NextBlock = ++snPtr  */
		snPtr = snPtr->NextBlock;
	} while (--temNUM > 0);

	/* Mask the last available block  */
	snPtr->NextBlock = 0;

	aetHead.NextBlock = &aetHead;
/* Point to itself so aetHead is also the tail  */
	aetHead.rX = 32767;
/* end of list is a right edge because sort left edges to the 
   left of right edges at equal X coordiantes  */	
	aetHead.rDir = RGHT_EDGE;

/* Initial X range so that the first valid rect will set it  */
	rXmin =  32767;
	rXmax = -32768;

/********** Verify rectangle lists to insure they are sorted  */
	if((numRects1 | numRects2) == 0 ) goto FinishRegion;
	/* Goto FinishRegion and end  */

#if ErrChecks  /* Make sure rectangle sorted  */
	temNUM = numRects1;
	temRect = rectList1;
	while(--temNUM > 0)
	{
		/* Using temp location for comparation  */		
		alTest = temRect->Xmin;
		ahTest = temRect->Ymin;
		temRect++;
		if( (temRect->Ymin < ahTest) || ((temRect->Ymin == ahTest) &&
			(temRect->Xmin < alTest)) )
		{ /* return because of bad rectangle list  */
			grafErrValue = c_RectList + c_BadRectList;
			nuGrafErr(grafErrValue);
			
			SetupEmptyRegion(destRGN, makeRegion, sizeRGN);
			return(0);
		}	
	}
			
    temRect = rectList2;
	temNUM = numRects2;
	while(--temNUM > 0)
	{
		/* Using temp location for comparation  */		
		alTest = temRect->Xmin;
		ahTest = temRect->Ymin;
		temRect++;
		if( (temRect->Ymin < ahTest) || ((temRect->Ymin == ahTest) &&
			(temRect->Xmin < alTest)) )
		{ /* return because of bad rectangle list  */
			grafErrValue = c_RectList + c_BadRectList;
			nuGrafErr(grafErrValue);
		
			SetupEmptyRegion(destRGN, makeRegion, sizeRGN);
			return(0);
		}	
	}
#endif

/********** Determin min Y in list 1 or 2  *********/
	curtY = 32767;	
	
	if(numRects1 != 0 )	curtY = rectList1->Ymin;
	if((numRects2 != 0) && (rectList2->Ymin < curtY))
		curtY = rectList2->Ymin;

/* ------------------------------------------------------- */
ScanOutFirst:
/* Add any rects of positive width and height on the current
scan line from the build rect list to the AET in x-sorted 
order; advance build rect list pointer  */

	if(numRects1 == 0)
		goto DoRectList2;
	temRect = rectList1;
	rlistID = RECT_LST1;
	curtLeftEdge = &aetHead;

	while(1)  
	{
		if(temRect->Ymin == curtY)
		{
			if( (temRect->Ymax > temRect->Ymin) &&
				(temRect->Xmax > temRect->Xmin)  )
			{
				/* Take the Minimum value for Xmin  */
				if(temRect->Xmin < rXmin)
					rXmin = temRect->Xmin;
				bePtr = curtLeftEdge;
				do{
					snPtr = bePtr;
					bePtr = snPtr->NextBlock;
				}while(bePtr->rX < temRect->Xmin);

				bePtr = (struct RBlock *) freeBlocks;
				if(freeBlocks == NULL)
				{ /* There is no space left then get out  */
					grafErrValue = c_RectList + c_OutofMem;
					nuGrafErr(grafErrValue);
			
					SetupEmptyRegion(destRGN, makeRegion, sizeRGN);
					return(0);
				}
				freeBlocks = (long) bePtr->NextBlock;
	/* Set the edge X coord to left edge of rect  */
				bePtr->rX = temRect->Xmin;
				bePtr->rCount = temRect->Ymax - temRect->Ymin;
				bePtr->rDir = LEFT_EDGE;
				bePtr->rList = rlistID;
	/* Link preceding AET block to new one and new one to the next  */
				dnPtr = snPtr->NextBlock;
				snPtr->NextBlock = bePtr;
				bePtr->NextBlock = dnPtr;
	/* Remember where to start scanning for the insertion point  */
				curtLeftEdge = bePtr;

	/* Do link for the right Edge  */
/* Link in the right edge and find insertion point for Xmax edge  */
				if(temRect->Xmax  > rXmax )
					rXmax = temRect->Xmax ;
/* Start scanning right after the left edge block just added. For sorting
	order, right edges always go to the right of left edges when they have 
	same X coordinates  */
				do{
					snPtr = bePtr;
					bePtr = snPtr->NextBlock;
				}while((bePtr->rX < temRect->Xmax) || 
					((bePtr->rX == temRect->Xmax) &&
					(bePtr->rDir == LEFT_EDGE)));

				bePtr = (struct RBlock *) freeBlocks;
				if(freeBlocks == NULL)
				{ /* There is no space left then get out  */
					grafErrValue = c_RectList + c_OutofMem;
					nuGrafErr(grafErrValue);
			
					SetupEmptyRegion(destRGN, makeRegion, sizeRGN);
					return(0);
				}
				freeBlocks = (long) bePtr->NextBlock;
				bePtr->rX = temRect->Xmax;
				bePtr->rCount = temRect->Ymax - temRect->Ymin;
				bePtr->rDir = RGHT_EDGE;
				bePtr->rList = (byte) rlistID;
	/* Link preceding AET block to new one and new one to the next  */
				dnPtr = snPtr->NextBlock;
				snPtr->NextBlock = bePtr;
				bePtr->NextBlock = dnPtr;
			}/* end at AddRectLoopBottom  */
			temRect++;
			if(rlistID == RECT_LST1)
			{

⌨️ 快捷键说明

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