📄 xpolyreg.c
字号:
* * Just a simple insertion sort using * pointers and back pointers to sort the Active * Edge Table. * */static intInsertionSort(AET) register EdgeTableEntry *AET;{ register EdgeTableEntry *pETEchase; register EdgeTableEntry *pETEinsert; register EdgeTableEntry *pETEchaseBackTMP; register int changed = 0; AET = AET->next; while (AET) { pETEinsert = AET; pETEchase = AET; while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis) pETEchase = pETEchase->back; AET = AET->next; if (pETEchase != pETEinsert) { pETEchaseBackTMP = pETEchase->back; pETEinsert->back->next = AET; if (AET) AET->back = pETEinsert->back; pETEinsert->next = pETEchase; pETEchase->back->next = pETEinsert; pETEchase->back = pETEinsert; pETEinsert->back = pETEchaseBackTMP; changed = 1; } } return(changed);}/* * Clean up our act. */static voidFreeStorage(pSLLBlock) register ScanLineListBlock *pSLLBlock;{ register ScanLineListBlock *tmpSLLBlock; while (pSLLBlock) { tmpSLLBlock = pSLLBlock->next; Xfree((char *)pSLLBlock); pSLLBlock = tmpSLLBlock; }}/* * Create an array of rectangles from a list of points. * If indeed these things (POINTS, RECTS) are the same, * then this proc is still needed, because it allocates * storage for the array, which was allocated on the * stack by the calling procedure. * */static int PtsToRegion(numFullPtBlocks, iCurPtBlock, FirstPtBlock, reg) register int numFullPtBlocks, iCurPtBlock; POINTBLOCK *FirstPtBlock; REGION *reg;{ register BOX *rects; register XPoint *pts; register POINTBLOCK *CurPtBlock; register int i; register BOX *extents; register int numRects; extents = ®->extents; numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1; if (!(reg->rects = (BOX *)Xrealloc((char *)reg->rects, (unsigned) (sizeof(BOX) * numRects)))) return(0); reg->size = numRects; CurPtBlock = FirstPtBlock; rects = reg->rects - 1; numRects = 0; extents->x1 = MAXSHORT, extents->x2 = MINSHORT; for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) { /* the loop uses 2 points per iteration */ i = NUMPTSTOBUFFER >> 1; if (!numFullPtBlocks) i = iCurPtBlock >> 1; for (pts = CurPtBlock->pts; i--; pts += 2) { if (pts->x == pts[1].x) continue; if (numRects && pts->x == rects->x1 && pts->y == rects->y2 && pts[1].x == rects->x2 && (numRects == 1 || rects[-1].y1 != rects->y1) && (!i || pts[2].y > pts[1].y)) { rects->y2 = pts[1].y + 1; continue; } numRects++; rects++; rects->x1 = pts->x; rects->y1 = pts->y; rects->x2 = pts[1].x; rects->y2 = pts[1].y + 1; if (rects->x1 < extents->x1) extents->x1 = rects->x1; if (rects->x2 > extents->x2) extents->x2 = rects->x2; } CurPtBlock = CurPtBlock->next; } if (numRects) { extents->y1 = reg->rects->y1; extents->y2 = rects->y2; } else { extents->x1 = 0; extents->y1 = 0; extents->x2 = 0; extents->y2 = 0; } reg->numRects = numRects; return(TRUE);}/* * polytoregion * * Scan converts a polygon by returning a run-length * encoding of the resultant bitmap -- the run-length * encoding is in the form of an array of rectangles. */Region XPolygonRegion(Pts, Count, rule) int Count; /* number of pts */ XPoint *Pts; /* the pts */ int rule; /* winding rule */{ Region region; register EdgeTableEntry *pAET; /* Active Edge Table */ register int y; /* current scanline */ register int iPts = 0; /* number of pts in buffer */ register EdgeTableEntry *pWETE; /* Winding Edge Table Entry*/ register ScanLineList *pSLL; /* current scanLineList */ register XPoint *pts; /* output buffer */ EdgeTableEntry *pPrevAET; /* ptr to previous AET */ EdgeTable ET; /* header node for ET */ EdgeTableEntry AET; /* header node for AET */ EdgeTableEntry *pETEs; /* EdgeTableEntries pool */ ScanLineListBlock SLLBlock; /* header for scanlinelist */ int fixWAET = FALSE; POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers */ POINTBLOCK *tmpPtBlock; int numFullPtBlocks = 0; if (! (region = XCreateRegion())) return (Region) NULL; /* special case a rectangle */ pts = Pts; if (((Count == 4) || ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) && (((pts[0].y == pts[1].y) && (pts[1].x == pts[2].x) && (pts[2].y == pts[3].y) && (pts[3].x == pts[0].x)) || ((pts[0].x == pts[1].x) && (pts[1].y == pts[2].y) && (pts[2].x == pts[3].x) && (pts[3].y == pts[0].y)))) { region->extents.x1 = min(pts[0].x, pts[2].x); region->extents.y1 = min(pts[0].y, pts[2].y); region->extents.x2 = max(pts[0].x, pts[2].x); region->extents.y2 = max(pts[0].y, pts[2].y); if ((region->extents.x1 != region->extents.x2) && (region->extents.y1 != region->extents.y2)) { region->numRects = 1; *(region->rects) = region->extents; } return(region); } if (! (pETEs = (EdgeTableEntry *) Xmalloc((unsigned) (sizeof(EdgeTableEntry) * Count)))) return (Region) NULL; pts = FirstPtBlock.pts; CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock); pSLL = ET.scanlines.next; curPtBlock = &FirstPtBlock; if (rule == EvenOddRule) { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { loadAET(&AET, pSLL->edgelist); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; /* * for each active edge */ while (pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = (POINTBLOCK *)Xmalloc(sizeof(POINTBLOCK)); curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } EVALUATEEDGEEVENODD(pAET, pPrevAET, y); } (void) InsertionSort(&AET); } } else { /* * for each scanline */ for (y = ET.ymin; y < ET.ymax; y++) { /* * Add a new edge to the active edge table when we * get to the next edge. */ if (pSLL != NULL && y == pSLL->scanline) { loadAET(&AET, pSLL->edgelist); computeWAET(&AET); pSLL = pSLL->next; } pPrevAET = &AET; pAET = AET.next; pWETE = pAET; /* * for each active edge */ while (pAET) { /* * add to the buffer only those edges that * are in the Winding active edge table. */ if (pWETE == pAET) { pts->x = pAET->bres.minor_axis, pts->y = y; pts++, iPts++; /* * send out the buffer */ if (iPts == NUMPTSTOBUFFER) { tmpPtBlock = (POINTBLOCK *)Xmalloc(sizeof(POINTBLOCK)); curPtBlock->next = tmpPtBlock; curPtBlock = tmpPtBlock; pts = curPtBlock->pts; numFullPtBlocks++; iPts = 0; } pWETE = pWETE->nextWETE; } EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET); } /* * recompute the winding active edge table if * we just resorted or have exited an edge. */ if (InsertionSort(&AET) || fixWAET) { computeWAET(&AET); fixWAET = FALSE; } } } FreeStorage(SLLBlock.next); (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) { tmpPtBlock = curPtBlock->next; Xfree((char *)curPtBlock); curPtBlock = tmpPtBlock; } Xfree((char *)pETEs); return(region);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -