|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T m ┃
Length: 10092 (0x276c) Types: TextFile Names: »makemask.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─ ⟦this⟧ »./X.V10R4/libibm/libsrc/makemask.c«
#ifndef lint static char *rcsid_makemask_c = "$Header: makemask.c,v 10.1 86/11/19 10:42:30 jg Exp $"; #endif lint /* makemask.c - builds a mask from vertex list * * MakeMask builds a mask from vertex list * AddEdge adds edges to edge table for fill operation * FillMask fills mask using scan line algorithm * * Author: * Scott Bates * Brown University * IRIS, Box 1946 * Providence, RI 02912 * * * Copyright (c) 1986 Brown University * * Permission to use, copy, modify and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies, and that both * that copyright notice and this permission notice appear in supporting * documentation, and that the name of Brown University not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Brown University makes no * representations about the suitability of this software for any purpose. * It is provided "as-is" without express or implied warranty. */ #include "private.h" #include "makemask.h" #include "pathlist.h" /* * Build mask from vertex list */ BITMAP * MakeMask(Verts, VertCount) Vertex *Verts; int VertCount; { register Vertex *LastPoint; register Vertex *ThisPoint; register Vertex *NextPoint; register Vertex *Poly; register struct Polygon *PolyData; register End; int Width = 0, Height = 0; int FirstScanLine = 10240; int Index, Size; BITMAP *BitMap; struct Polygon *FirstPoly; #ifdef TRACE_X fprintf (stderr, "In MakeMask\n"); fflush (stderr); #endif TRACE_X /* * Allocate space for polygon pointers */ FirstPoly = (struct Polygon *) calloc(VertCount << 1, sizeof(struct Polygon)); if (FirstPoly == NULL) { return (NULL); } /* * Determine width and height of off-screen bitmap * and the first scan line to be filled. */ PolyData = FirstPoly - 1; for(Index = 0; Index < VertCount; Index += 2) { if(Width < Verts[Index].x) Width = Verts[Index].x; if(Height < Verts[Index].y) Height = Verts[Index].y; if(FirstScanLine > Verts[Index].y) FirstScanLine = Verts[Index].y; if(Verts[Index].flags & START_OF_CLOSED_POLY) { (++PolyData)->PolyPoints = &Verts[Index]; PolyData->PolyCount = 2; } else { PolyData->PolyCount += 2; } } (++PolyData)->PolyPoints = (Vertex *)NULL; /* * Allocate space for bitmap structure */ BitMap = (BITMAP *) Xalloc (sizeof (BITMAP)); /* * Fill in bitmap structure * * NOTE: The bitmaps width has been rounded up * to the nearest 32 bit bound. This was done * so that the mask could be fill 32 bits at * a time instead of the usual 16. */ BitMap->width = Width = ((Width + 32) >> 5) << 5; BitMap->height = ++Height; /* * Allocated space to hold bitimage data */ if((BitMap->data = calloc(1, BitmapSize(Width, Height))) == NULL) { free ((caddr_t) BitMap); return (NULL); } /* * Allocate space for edges and reset EdgeCount */ Edges = (struct edge *) calloc(VertCount << 1, sizeof(struct edge)); if (Edges == NULL) { free ((caddr_t) BitMap->data); free ((caddr_t) BitMap); return (NULL); } if ((EdgeTable = (struct edge **)calloc(Height + 1, 4)) == NULL) { free((caddr_t) Edges); free ((caddr_t) BitMap->data); free ((caddr_t) BitMap); return (NULL); } EdgeCount = 0; /* * Add the edges of all polygons to * the edge table */ Poly = (PolyData = FirstPoly)->PolyPoints; do { /* * Test for valid polygon */ if(PolyData->PolyCount > 5) { /* * AddEdge() initialization before adding * each polygon */ ShortenStartOfEdge = 0; Direction = Poly[PolyData->PolyCount - 2].y > Poly[0].y; End = PolyData->PolyCount - 4; LastPoint = Poly; ThisPoint = NextPoint = Poly + 2; /* * Add edges of this polygon to edge table */ while(End) { NextPoint += 2; AddEdge(LastPoint, ThisPoint, NextPoint); LastPoint = ThisPoint; ThisPoint = NextPoint; End -= 2; } NextPoint = &Poly[0]; AddEdge(LastPoint, ThisPoint, NextPoint); LastPoint = ThisPoint; ThisPoint = NextPoint; NextPoint += 2; AddEdge(LastPoint, ThisPoint, NextPoint); } /* * Increment pointer to next polygon to add */ Poly = (++PolyData)->PolyPoints; } while(Poly); if(EdgeCount) { /* * Fill the mask */ FillMask(BitMap, FirstScanLine); /* * Frame mask to remove any abnomalities */ for (Index = 0; Index < VertCount; Index += 2) { SinglePixelLine(BitMap, Verts[Index].x, Verts[Index].y, Verts[Index + 1].x, Verts[Index + 1].y, (CLIP *) 0, GXor, DrawSolidLine, 1, 0, 0, 0, 0); } /* * Return mask bitmap */ return(BitMap); } /* * Indicate nothing to fill */ return(NULL); } /* * Add edge to edge table */ static AddEdge(LastPoint, ThisPoint, NextPoint) register Vertex *LastPoint; register Vertex *ThisPoint; register Vertex *NextPoint; { register struct edge *NewEdge = &Edges[EdgeCount]; #ifdef TRACE_X fprintf (stderr, "In AddEdge\n"); fflush (stderr); #endif TRACE_X /* * Fill in new edge data */ if (ThisPoint->y != LastPoint->y) { register Min_Y; if (ThisPoint->y < LastPoint->y) { Min_Y = ThisPoint->y; NewEdge->Min_X = SHIFT_LEFT_16(ThisPoint->x); NewEdge->Max_Y = LastPoint->y; NewEdge->Delta_X = SHIFT_LEFT_16(LastPoint->x - ThisPoint->x) / (LastPoint->y - ThisPoint->y); } else { Min_Y = LastPoint->y; NewEdge->Min_X = SHIFT_LEFT_16(LastPoint->x); NewEdge->Max_Y = ThisPoint->y; NewEdge->Delta_X = SHIFT_LEFT_16(ThisPoint->x - LastPoint->x) / (ThisPoint->y - LastPoint->y); } /* * Shorten edge if not maxima or minima (shortens end of edge) */ if((ThisPoint->y > LastPoint->y) ? (NextPoint->y > ThisPoint->y) : (NextPoint->y < ThisPoint->y)) { if (LastPoint->y > ThisPoint->y) { Min_Y++; NewEdge->Min_X += NewEdge->Delta_X; } else { NewEdge->Max_Y--; } } /* * Check to see if this edge needs to be shortened * at its start. */ if(ShortenStartOfEdge) { if (ThisPoint->y > LastPoint->y) { Min_Y++; NewEdge->Min_X += NewEdge->Delta_X; } else { NewEdge->Max_Y--; } ShortenStartOfEdge = 0; } /* * Save direction of this edge */ if (NextPoint->y == ThisPoint->y) { Direction = LastPoint->y > ThisPoint->y; } /* * Insert edge into edge table */ if (NewEdge->Max_Y >= Min_Y) { register struct edge *EdgeList = (struct edge *)&EdgeTable[Min_Y]; while(EdgeList->NextEdge) { if(EdgeList->NextEdge->Min_X >= NewEdge->Min_X) break; EdgeList = EdgeList->NextEdge; } NewEdge->NextEdge = EdgeList->NextEdge; EdgeList->NextEdge = NewEdge; EdgeCount++; } } else { /* * This is a horizontal edge. Therefore, if there is * a change of direction between the preceding edge and * and the next edge the next edge must be shortened at its * start. */ if(NextPoint->y != ThisPoint->y && (Direction != (NextPoint->y > ThisPoint->y))) { ShortenStartOfEdge++; } } } /* * Fill polygon(s) to create mask */ static FillMask(BitMap, FirstScanLine) BITMAP *BitMap; int FirstScanLine; { register long *Bits; register Start, Stop; register FirstWord, LastWord; register struct edge *AET; struct edge *ActiveEdgeTable; struct edge *TempEdge; int NumberOfWords, CurrentScanLine, SortAgain; #ifdef TRACE_X fprintf (stderr, "In FillMask\n"); fflush (stderr); #endif TRACE_X NumberOfWords = (BitMap->width + 31) >> 5; Bits = (long *)BitMap->data + FirstScanLine * NumberOfWords; ActiveEdgeTable = EdgeTable[FirstScanLine]; CurrentScanLine = FirstScanLine; while(EdgeCount) { /* * Fill all ranges for current scan line */ AET = (struct edge *)&ActiveEdgeTable; while(AET->NextEdge && AET->NextEdge->NextEdge) { Start = ROUND_16(AET->NextEdge->Min_X); Stop = ROUND_16(AET->NextEdge->NextEdge->Min_X); if ((FirstWord = Start >> 5) < (LastWord = Stop >> 5)) { Bits[FirstWord] |= RightMasks[Start & 0x1F]; while (++FirstWord < LastWord) Bits[FirstWord] = 0xFFFFFFFF; Bits[LastWord] |= LeftMasks[Stop & 0x1F]; } else { Bits[FirstWord] |= (RightMasks[Start & 0x1F] & LeftMasks[Stop & 0x1F]); } AET = AET->NextEdge->NextEdge; } Bits += NumberOfWords; /* * Remove finished edges from active edge table * and add any new edges for next scan line. */ AET = (struct edge *)&ActiveEdgeTable; while(AET->NextEdge) { if(AET->NextEdge->Max_Y == CurrentScanLine) { AET->NextEdge = AET->NextEdge->NextEdge; EdgeCount--; } else { AET->NextEdge->Min_X += AET->NextEdge->Delta_X; AET = AET->NextEdge; } } AET->NextEdge = EdgeTable[++CurrentScanLine]; /* * Sort active edge table */ do { SortAgain = 0; AET = (struct edge *)&ActiveEdgeTable; while(AET->NextEdge && AET->NextEdge->NextEdge) { if(AET->NextEdge->Min_X > AET->NextEdge->NextEdge->Min_X) { TempEdge = AET->NextEdge; AET->NextEdge = AET->NextEdge->NextEdge; TempEdge->NextEdge = AET->NextEdge->NextEdge; AET->NextEdge->NextEdge = TempEdge; SortAgain = 1; } AET = AET->NextEdge; } }while(SortAgain); } free((caddr_t) EdgeTable); free((caddr_t) Edges); }