Annotation of 43BSDTahoe/new/X/libibm/libsrc/makemask.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *rcsid_makemask_c = "$Header: makemask.c,v 10.1 86/11/19 10:42:30 jg Exp $";
        !             3: #endif lint
        !             4: /* makemask.c -  builds a mask from vertex list
        !             5:  *
        !             6:  *     MakeMask     builds a mask from vertex list
        !             7:  *     AddEdge      adds edges to edge table for fill operation
        !             8:  *     FillMask     fills mask using scan line algorithm
        !             9:  *
        !            10:  *     Author:
        !            11:  *             Scott Bates
        !            12:  *             Brown University
        !            13:  *             IRIS, Box 1946
        !            14:  *             Providence, RI 02912
        !            15:  *
        !            16:  *
        !            17:  *             Copyright (c) 1986 Brown University
        !            18:  *
        !            19:  * Permission to use, copy, modify and distribute this software and its
        !            20:  * documentation for any purpose and without fee is hereby granted, provided
        !            21:  * that the above copyright notice appear in all copies, and that both
        !            22:  * that copyright notice and this permission notice appear in supporting
        !            23:  * documentation, and that the name of Brown University not be used in
        !            24:  * advertising or publicity pertaining to distribution of the software
        !            25:  * without specific, written prior permission. Brown University makes no
        !            26:  * representations about the suitability of this software for any purpose.
        !            27:  * It is provided "as-is" without express or implied warranty.
        !            28:  */
        !            29: 
        !            30: #include "private.h"
        !            31: #include "makemask.h"
        !            32: #include "pathlist.h"
        !            33: 
        !            34: /*
        !            35:  * Build mask from vertex list
        !            36:  */
        !            37: 
        !            38: BITMAP *
        !            39: MakeMask(Verts, VertCount)
        !            40:        Vertex *Verts;
        !            41:        int VertCount;
        !            42: {
        !            43:        register Vertex *LastPoint;
        !            44:        register Vertex *ThisPoint;
        !            45:        register Vertex *NextPoint;
        !            46:        register Vertex *Poly;
        !            47:        register struct Polygon *PolyData;
        !            48:        register End;
        !            49:        int Width = 0, Height = 0;
        !            50:        int FirstScanLine = 10240;
        !            51:        int Index, Size;
        !            52:        BITMAP *BitMap;
        !            53:        struct Polygon *FirstPoly;
        !            54: 
        !            55: #ifdef TRACE_X
        !            56:         fprintf (stderr, "In MakeMask\n");
        !            57:         fflush (stderr);
        !            58: #endif TRACE_X
        !            59: 
        !            60:        /*
        !            61:         * Allocate space for polygon pointers
        !            62:         */
        !            63: 
        !            64:        FirstPoly = (struct Polygon *) calloc(VertCount << 1,
        !            65:                   sizeof(struct Polygon));
        !            66:         if (FirstPoly == NULL) {
        !            67:             return (NULL);
        !            68:         }
        !            69: 
        !            70:        /*
        !            71:         * Determine width and height of off-screen bitmap
        !            72:         * and the first scan line to be filled.
        !            73:         */
        !            74: 
        !            75:        PolyData = FirstPoly - 1;
        !            76:        for(Index = 0; Index < VertCount; Index += 2) {
        !            77:                if(Width < Verts[Index].x)
        !            78:                        Width = Verts[Index].x;
        !            79:                if(Height < Verts[Index].y)
        !            80:                        Height = Verts[Index].y;
        !            81:                if(FirstScanLine > Verts[Index].y)
        !            82:                        FirstScanLine = Verts[Index].y;
        !            83:                if(Verts[Index].flags & START_OF_CLOSED_POLY) {
        !            84:                        (++PolyData)->PolyPoints = &Verts[Index];
        !            85:                        PolyData->PolyCount = 2;
        !            86:                } else {
        !            87:                        PolyData->PolyCount += 2;
        !            88:                }
        !            89:        }
        !            90:        (++PolyData)->PolyPoints = (Vertex *)NULL;
        !            91: 
        !            92:         /*
        !            93:          * Allocate space for bitmap structure
        !            94:          */
        !            95: 
        !            96:         BitMap = (BITMAP *) Xalloc (sizeof (BITMAP));
        !            97: 
        !            98:         /*
        !            99:          * Fill in bitmap structure
        !           100:         *
        !           101:         * NOTE: The bitmaps width has been rounded up 
        !           102:         *       to the nearest 32 bit bound. This was done
        !           103:         *       so that the mask could be fill 32 bits at
        !           104:         *       a time instead of the usual 16.
        !           105:          */
        !           106: 
        !           107:         BitMap->width = Width = ((Width + 32) >> 5) << 5;
        !           108:         BitMap->height = ++Height;
        !           109: 
        !           110:         /*
        !           111:          * Allocated space to hold bitimage data
        !           112:          */
        !           113:        
        !           114:         if((BitMap->data = calloc(1, BitmapSize(Width, Height))) == NULL) {
        !           115:             free ((caddr_t) BitMap);
        !           116:             return (NULL);
        !           117:         }
        !           118: 
        !           119:        /*
        !           120:         * Allocate space for edges and reset EdgeCount
        !           121:         */
        !           122: 
        !           123:        Edges = (struct edge *) calloc(VertCount << 1, sizeof(struct edge));
        !           124:         if (Edges == NULL) {
        !           125:             free ((caddr_t) BitMap->data);
        !           126:             free ((caddr_t) BitMap);
        !           127:             return (NULL);
        !           128:         }
        !           129:         if ((EdgeTable = (struct edge **)calloc(Height + 1, 4)) == NULL) {
        !           130:            free((caddr_t) Edges);
        !           131:             free ((caddr_t) BitMap->data);
        !           132:             free ((caddr_t) BitMap);
        !           133:             return (NULL);
        !           134:         }
        !           135:        EdgeCount = 0;
        !           136: 
        !           137:        /*
        !           138:         * Add the edges of all polygons to
        !           139:         * the edge table
        !           140:         */
        !           141: 
        !           142:        Poly = (PolyData = FirstPoly)->PolyPoints;
        !           143:        do {
        !           144:                /*
        !           145:                 * Test for valid polygon
        !           146:                 */
        !           147: 
        !           148:                if(PolyData->PolyCount > 5) {
        !           149:                        /*
        !           150:                         * AddEdge() initialization before adding
        !           151:                         * each polygon
        !           152:                         */
        !           153: 
        !           154:                        ShortenStartOfEdge = 0;
        !           155:                        Direction = Poly[PolyData->PolyCount - 2].y > Poly[0].y;
        !           156:                        End = PolyData->PolyCount - 4;
        !           157:                        LastPoint = Poly;
        !           158:                        ThisPoint = NextPoint =  Poly + 2;
        !           159: 
        !           160:                        /*
        !           161:                         * Add edges of this polygon to edge table
        !           162:                         */
        !           163: 
        !           164:                        while(End) {
        !           165:                                NextPoint += 2;
        !           166:                                AddEdge(LastPoint, ThisPoint, NextPoint);
        !           167:                                LastPoint = ThisPoint;
        !           168:                                ThisPoint = NextPoint;
        !           169:                                End -= 2;
        !           170:                        }
        !           171:                        NextPoint = &Poly[0];
        !           172:                        AddEdge(LastPoint, ThisPoint, NextPoint);
        !           173:                        LastPoint = ThisPoint;
        !           174:                        ThisPoint = NextPoint;
        !           175:                        NextPoint += 2;
        !           176:                        AddEdge(LastPoint, ThisPoint, NextPoint);
        !           177:                }
        !           178: 
        !           179:                /*
        !           180:                 * Increment pointer to next polygon to add
        !           181:                 */
        !           182: 
        !           183:                Poly = (++PolyData)->PolyPoints;
        !           184: 
        !           185:        } while(Poly);
        !           186: 
        !           187:        if(EdgeCount) {
        !           188:                /*
        !           189:                 * Fill the mask
        !           190:                 */
        !           191: 
        !           192:                FillMask(BitMap, FirstScanLine);
        !           193: 
        !           194:                /*
        !           195:                 * Frame mask to remove any abnomalities
        !           196:                 */
        !           197: 
        !           198:                for (Index = 0; Index < VertCount; Index += 2) {
        !           199:                        SinglePixelLine(BitMap, Verts[Index].x, Verts[Index].y,
        !           200:                                        Verts[Index + 1].x, Verts[Index + 1].y,
        !           201:                                        (CLIP *) 0, GXor, DrawSolidLine, 1, 0,
        !           202:                                        0, 0, 0);
        !           203:                }
        !           204: 
        !           205:                /* 
        !           206:                 * Return mask bitmap
        !           207:                 */
        !           208: 
        !           209:                return(BitMap);
        !           210:        }
        !           211: 
        !           212:        /*
        !           213:         * Indicate nothing to fill
        !           214:         */
        !           215: 
        !           216:        return(NULL);
        !           217: }
        !           218: 
        !           219: /*
        !           220:  * Add edge to edge table
        !           221:  */
        !           222: 
        !           223: static
        !           224: AddEdge(LastPoint, ThisPoint, NextPoint)
        !           225:     register Vertex *LastPoint;
        !           226:     register Vertex *ThisPoint;
        !           227:     register Vertex *NextPoint;
        !           228: {
        !           229:     register struct edge *NewEdge = &Edges[EdgeCount];
        !           230: 
        !           231: #ifdef TRACE_X
        !           232:     fprintf (stderr, "In AddEdge\n");
        !           233:     fflush (stderr);
        !           234: #endif TRACE_X
        !           235: 
        !           236:     /*
        !           237:      * Fill in new edge data
        !           238:      */
        !           239: 
        !           240:     if (ThisPoint->y != LastPoint->y) {
        !           241:        register Min_Y;
        !           242: 
        !           243:         if (ThisPoint->y < LastPoint->y) {
        !           244:             Min_Y = ThisPoint->y;
        !           245:             NewEdge->Min_X = SHIFT_LEFT_16(ThisPoint->x);
        !           246:             NewEdge->Max_Y = LastPoint->y;
        !           247:             NewEdge->Delta_X = SHIFT_LEFT_16(LastPoint->x - ThisPoint->x) /
        !           248:                                (LastPoint->y - ThisPoint->y);
        !           249:         } else {
        !           250:             Min_Y = LastPoint->y;
        !           251:             NewEdge->Min_X = SHIFT_LEFT_16(LastPoint->x);
        !           252:             NewEdge->Max_Y = ThisPoint->y;
        !           253:             NewEdge->Delta_X = SHIFT_LEFT_16(ThisPoint->x - LastPoint->x) /
        !           254:                                (ThisPoint->y - LastPoint->y);  
        !           255:         }
        !           256: 
        !           257:        /*
        !           258:         * Shorten edge if not maxima or minima (shortens end of edge)
        !           259:         */
        !           260: 
        !           261:         if((ThisPoint->y > LastPoint->y) ?
        !           262:           (NextPoint->y > ThisPoint->y) : (NextPoint->y < ThisPoint->y)) {
        !           263:                if (LastPoint->y > ThisPoint->y) {
        !           264:                        Min_Y++;
        !           265:                        NewEdge->Min_X += NewEdge->Delta_X;
        !           266:                } else  {
        !           267:                        NewEdge->Max_Y--;
        !           268:                }
        !           269:         }
        !           270: 
        !           271:        /*
        !           272:         * Check to see if this edge needs to be shortened
        !           273:         * at its start.
        !           274:         */
        !           275: 
        !           276:        if(ShortenStartOfEdge) {
        !           277:                if (ThisPoint->y > LastPoint->y) {
        !           278:                        Min_Y++;
        !           279:                        NewEdge->Min_X += NewEdge->Delta_X;
        !           280:                } else  {
        !           281:                        NewEdge->Max_Y--;
        !           282:                }
        !           283:                ShortenStartOfEdge = 0;
        !           284:        }
        !           285: 
        !           286:        /*
        !           287:         * Save direction of this edge
        !           288:         */
        !           289: 
        !           290:        if (NextPoint->y == ThisPoint->y) {
        !           291:                Direction = LastPoint->y > ThisPoint->y;
        !           292:        }
        !           293: 
        !           294:        /*
        !           295:         * Insert edge into edge table
        !           296:         */
        !           297: 
        !           298:         if (NewEdge->Max_Y >= Min_Y) {
        !           299:            register struct edge *EdgeList = (struct edge *)&EdgeTable[Min_Y];
        !           300: 
        !           301:            while(EdgeList->NextEdge) {
        !           302:                if(EdgeList->NextEdge->Min_X >= NewEdge->Min_X)
        !           303:                    break;
        !           304:                EdgeList = EdgeList->NextEdge;
        !           305:            }
        !           306:            NewEdge->NextEdge = EdgeList->NextEdge;
        !           307:            EdgeList->NextEdge = NewEdge;
        !           308:            EdgeCount++;
        !           309:         }
        !           310:     } else  { 
        !           311:        /*
        !           312:         * This is a horizontal edge. Therefore, if there is
        !           313:         * a change of direction between the preceding edge and
        !           314:         * and the next edge the next edge must be shortened at its 
        !           315:         * start.
        !           316:         */
        !           317: 
        !           318:        if(NextPoint->y != ThisPoint->y &&
        !           319:           (Direction != (NextPoint->y > ThisPoint->y))) {
        !           320:                ShortenStartOfEdge++;
        !           321:        }
        !           322:     }
        !           323: }
        !           324: 
        !           325: /*
        !           326:  * Fill polygon(s) to create mask
        !           327:  */
        !           328: 
        !           329: static
        !           330: FillMask(BitMap, FirstScanLine)
        !           331:     BITMAP *BitMap;
        !           332:     int FirstScanLine;
        !           333: {
        !           334:     register long *Bits;
        !           335:     register Start, Stop;
        !           336:     register FirstWord, LastWord;
        !           337:     register struct edge *AET;
        !           338:     struct edge *ActiveEdgeTable;
        !           339:     struct edge *TempEdge;
        !           340:     int NumberOfWords, CurrentScanLine, SortAgain;
        !           341: 
        !           342: #ifdef TRACE_X
        !           343:     fprintf (stderr, "In FillMask\n");
        !           344:     fflush (stderr);
        !           345: #endif TRACE_X
        !           346: 
        !           347:     NumberOfWords = (BitMap->width + 31) >> 5;
        !           348:     Bits = (long *)BitMap->data + FirstScanLine * NumberOfWords;
        !           349:     ActiveEdgeTable = EdgeTable[FirstScanLine];
        !           350:     CurrentScanLine = FirstScanLine;
        !           351: 
        !           352:     while(EdgeCount) {
        !           353:            /*
        !           354:             * Fill all ranges for current scan line
        !           355:             */
        !           356: 
        !           357:            AET = (struct edge *)&ActiveEdgeTable;
        !           358: 
        !           359:            while(AET->NextEdge && AET->NextEdge->NextEdge) {
        !           360:                Start = ROUND_16(AET->NextEdge->Min_X);
        !           361:                Stop = ROUND_16(AET->NextEdge->NextEdge->Min_X);
        !           362: 
        !           363:                if ((FirstWord = Start >> 5) < (LastWord = Stop >> 5)) {
        !           364:                        Bits[FirstWord] |= RightMasks[Start & 0x1F];
        !           365:                        while (++FirstWord < LastWord)
        !           366:                                Bits[FirstWord] = 0xFFFFFFFF;
        !           367:                        Bits[LastWord] |= LeftMasks[Stop & 0x1F];
        !           368:                } else {
        !           369:                        Bits[FirstWord] |= (RightMasks[Start & 0x1F] &
        !           370:                                LeftMasks[Stop & 0x1F]);
        !           371:                }
        !           372: 
        !           373:                AET = AET->NextEdge->NextEdge;
        !           374:            }
        !           375:            Bits += NumberOfWords;
        !           376: 
        !           377:            /*
        !           378:             * Remove finished edges from active edge table 
        !           379:             * and add any new edges for next scan line.
        !           380:             */
        !           381: 
        !           382:            AET = (struct edge *)&ActiveEdgeTable;
        !           383:            while(AET->NextEdge) {
        !           384:                    if(AET->NextEdge->Max_Y == CurrentScanLine) {
        !           385:                            AET->NextEdge = AET->NextEdge->NextEdge;
        !           386:                            EdgeCount--;
        !           387:                    } else  {
        !           388:                            AET->NextEdge->Min_X += AET->NextEdge->Delta_X;
        !           389:                            AET = AET->NextEdge;
        !           390:                    }
        !           391:            }
        !           392:            AET->NextEdge = EdgeTable[++CurrentScanLine];
        !           393: 
        !           394:            /*
        !           395:             * Sort active edge table
        !           396:             */
        !           397: 
        !           398:            do {
        !           399:                SortAgain = 0;
        !           400:                AET = (struct edge *)&ActiveEdgeTable;
        !           401:                while(AET->NextEdge && AET->NextEdge->NextEdge) {
        !           402:                    if(AET->NextEdge->Min_X > AET->NextEdge->NextEdge->Min_X) {
        !           403:                        TempEdge = AET->NextEdge;
        !           404:                        AET->NextEdge = AET->NextEdge->NextEdge;
        !           405:                        TempEdge->NextEdge = AET->NextEdge->NextEdge;
        !           406:                        AET->NextEdge->NextEdge = TempEdge;
        !           407:                        SortAgain = 1;
        !           408:                    }
        !           409:                    AET = AET->NextEdge;
        !           410:                }
        !           411:            }while(SortAgain);
        !           412:     }
        !           413:     free((caddr_t) EdgeTable);
        !           414:     free((caddr_t) Edges);
        !           415: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.