Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/misetclip.c, revision 1.1.1.1

1.1       root        1: /***********************************************************
                      2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
                      3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
                      4: 
                      5:                         All Rights Reserved
                      6: 
                      7: Permission to use, copy, modify, and distribute this software and its 
                      8: documentation for any purpose and without fee is hereby granted, 
                      9: provided that the above copyright notice appear in all copies and that
                     10: both that copyright notice and this permission notice appear in 
                     11: supporting documentation, and that the names of Digital or MIT not be
                     12: used in advertising or publicity pertaining to distribution of the
                     13: software without specific, written prior permission.  
                     14: 
                     15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     21: SOFTWARE.
                     22: 
                     23: ******************************************************************/
                     24: /* $Header: misetclip.c,v 1.4 87/09/11 07:20:53 toddb Exp $ */
                     25: /* Author: Todd Newman */
                     26: 
                     27: #include "X.h"
                     28: #include "Xprotostr.h"
                     29: #include "miscstruct.h"
                     30: #include "scrnintstr.h"
                     31: #include "pixmap.h"
                     32: #include "regionstr.h"
                     33: #include "gcstruct.h"
                     34: 
                     35: /* The file name is something of a misnomer. Actually, this just contains 
                     36:  * a routine to convert a set of rectangles into a region 
                     37:  */
                     38: 
                     39: typedef struct _ybucket
                     40: {
                     41:     short      y;
                     42:     short      count;
                     43:     BoxPtr     boxes;
                     44:     short      miny2;
                     45:     short      fdiff;  /* do any have different y2s */
                     46:     struct _ybucket    *next;
                     47: } YBUCKET;
                     48: 
                     49: 
                     50: /* NEWBUCKET -- a private helper to build a bucket for sorting */
                     51: static
                     52: YBUCKET *
                     53: newbucket(y, miny2)
                     54: {
                     55:     YBUCKET    *pb;
                     56: 
                     57:     pb = (YBUCKET *) Xalloc( sizeof(YBUCKET));
                     58:     pb->count = 0;
                     59:     pb->y = y;
                     60:     pb->miny2 = miny2;
                     61:     pb->fdiff = FALSE;
                     62:     pb->boxes = (BoxPtr)Xalloc(sizeof(BoxRec));
                     63:     pb->next = (YBUCKET *) NULL;
                     64:     return(pb);
                     65: }
                     66: 
                     67: /* MIRECTSTOREGION -- helper called by the device private routine called when
                     68:  * the clipmask changes.  Converts the set of rectangles to a region.  
                     69:  * dix/gc/SetClipRects has already checked that the rectangles are sorted as
                     70:  * advertised.
                     71:  * We just take those rectangles and convert to a YX banded region.
                     72:  * First we sort the rectangles by starting Y values. Then we make sure that
                     73:  * all rectangles that start at a given line all end at the same line.  Bits
                     74:  * that hang over fall into the next Y bucket. (Sort of Procrustean, isn't
                     75:  * it?)  Next, we sort within each Y bucket by X starting values. Finally,
                     76:  * we take the resulting set of rectangles and stuff it into a region.
                     77:  */
                     78: RegionPtr
                     79: miRectsToRegion(pGC, nrects, prect, ordering)
                     80:     GCPtr      pGC;
                     81:     int                nrects;
                     82:     xRectangle *prect;
                     83:     int                ordering;
                     84: {
                     85:     register YBUCKET   *pb;
                     86:     register BoxRec    *pbox, *pboxNew;
                     87:     BoxRec              tbox;
                     88:     RegionPtr          pReg;
                     89:     YBUCKET            *pbFirst, *pbNew, *newbucket();
                     90:     int                        count, miny2;
                     91:     Bool               fInserted, fChanged;
                     92:     int                        xMin, xMax, yMin, yMax;
                     93:     BoxRec             b;
                     94: 
                     95:     /* if there's only one rectangle, we don't care about ordering */
                     96:     if (nrects == 1)   
                     97:     {
                     98:         b.x1 = prect->x;
                     99:         b.y1 = prect->y;
                    100:         b.x2 = b.x1 + prect->width;
                    101:         b.y2 = b.y1 + prect->height;
                    102:         return ((* pGC->pScreen->RegionCreate)(&b, 1));
                    103:     }
                    104:     /* setting the number of rectangles to zero stops all output */
                    105:     if (nrects == 0)   
                    106:     {
                    107:         b.x1 = 0;
                    108:         b.y1 = 0;
                    109:         b.x2 = 0;
                    110:         b.y2 = 0;
                    111:         return ((* pGC->pScreen->RegionCreate)(&b, 1));
                    112:     }
                    113: 
                    114:     xMin = yMin = MAXSHORT;
                    115:     xMax = yMax = -1;
                    116:     if ((nrects < 0) ||
                    117:        ((pReg = (* pGC->pScreen->RegionCreate)(NULL, 1)) == NullRegion))
                    118:     {
                    119:        return NullRegion;
                    120:     }
                    121: 
                    122:     if (ordering == YXBanded)
                    123:     {
                    124:        pReg->rects = (BoxPtr)Xrealloc(pReg->rects, nrects * sizeof(BoxRec));
                    125:        pbox = pReg->rects;
                    126:        while(pbox < pReg->rects + nrects)
                    127:        {
                    128:            pbox->x1 = prect->x;
                    129:            pbox->y1 = prect->y;
                    130:            pbox->x2 = prect->x + prect->width;
                    131:            pbox->y2 = prect->y + prect->height;
                    132:            xMin = min(xMin, pbox->x1);
                    133:            xMax = max(xMax, pbox->x2);
                    134:            yMin = min(yMin, pbox->y1);
                    135:            yMax = max(yMax, pbox->y2);
                    136:            prect++;
                    137:            pbox++;
                    138:        }
                    139:        pReg->numRects = nrects;
                    140:        pReg->size = nrects;
                    141:        pReg->extents.x1 = xMin;
                    142:        pReg->extents.y1 = yMin;
                    143:        pReg->extents.x2 = xMax;
                    144:        pReg->extents.y2 = yMax;
                    145:        return (pReg);
                    146:     }
                    147: 
                    148:     pbFirst = (YBUCKET *) newbucket(prect->y, prect->y + prect->height);
                    149:     pb = pbFirst;
                    150:     count = nrects;
                    151: 
                    152:     /* Sort into Y buckets -- everthing in a bucket has the same starting
                    153:      * scanline.  Also note the smallest box in the band and whether any
                    154:      * boxes are of other sizes */
                    155:     while(count--)
                    156:     {
                    157:        if(ordering == Unsorted)
                    158:        {
                    159:            /* We have to search from the top, otherwise we know no
                    160:             * box will be before the current one */
                    161:            pb = pbFirst;
                    162:        }
                    163: 
                    164:        fInserted = FALSE;
                    165:        while(!fInserted)
                    166:        {
                    167:            if(prect->y == pb->y)
                    168:            {
                    169:                /* add rectangle at the end of this bucket */
                    170:                pb->count++;
                    171:                pb->boxes = (BoxPtr)Xrealloc(pb->boxes,
                    172:                                             pb->count * sizeof(BoxRec));
                    173:                pbox = &pb->boxes[pb->count - 1];
                    174: 
                    175:                pbox->x1 = prect->x;
                    176:                pbox->y1 = prect->y;
                    177:                pbox->x2 = prect->x + prect->width;
                    178:                pbox->y2 = prect->y + prect->height;
                    179:                xMin = min(xMin, pbox->x1);
                    180:                xMax = max(xMax, pbox->x2);
                    181:                yMin = min(yMin, pbox->y1);
                    182:                yMax = max(yMax, pbox->y2);
                    183: 
                    184:                if (pbox->y2 != pb->miny2)
                    185:                    pb->fdiff = TRUE;
                    186:                if (pbox->y2 < pb->miny2)
                    187:                    pb->miny2 = pbox->y2;
                    188:                fInserted = TRUE;
                    189:            }
                    190:            else if(prect->y < pbFirst->y)
                    191:            {
                    192:                /* Create a new first record in the list */
                    193:                pbNew = newbucket(prect->y, prect->y + prect->height);
                    194:                pbNew->next = pbFirst;
                    195:                pbFirst = pbNew;
                    196:                pb = pbNew;
                    197:            }
                    198:            else if ((pb->next == (YBUCKET *) NULL) ||
                    199:                     (pb->next->y > prect->y))
                    200:            {
                    201:                /* create a new ybucket linked between this and the next.
                    202:                 * set pb to new bucket */
                    203:                 pbNew = newbucket(prect->y, prect->y + prect->height);
                    204:                 pbNew->next = pb->next;
                    205:                 pb->next = pbNew;
                    206:                 pb = pbNew;
                    207:                
                    208:            }
                    209:            else
                    210:            {
                    211:                /* try with next bucket */
                    212:                pb = pb->next;
                    213:            }
                    214:        }
                    215:        prect++;
                    216:     }
                    217: 
                    218:     /* YBand the buckets */
                    219:     pb = pbFirst;
                    220:     while(pb)
                    221:     {
                    222:        if(pb->fdiff)
                    223:        {
                    224:            miny2 = pb->miny2;
                    225: 
                    226:            /* Figure out which ybucket the lopped-off part of these boxes
                    227:             * will go in */
                    228:            if(pb->next ? (miny2 < pb->next->y) : TRUE)
                    229:            {
                    230:                /* create new y bucket */
                    231:                pbNew = newbucket(miny2, MAXSHORT);
                    232:                pbNew->next = pb->next;
                    233:                pb->next = pbNew;
                    234:            }
                    235:            else
                    236:            {
                    237:                pbNew = pb->next;
                    238:            }
                    239: 
                    240:            /* if any rectangle is longer than the shortest in this ybucket,
                    241:             * drop the rest of the rectangle into the next lowest bucket */
                    242:            pbox = pb->boxes;
                    243:            while(pbox < pb->boxes + pb->count)
                    244:            {
                    245:                if(pbox->y2 > miny2)
                    246:                {
                    247:                    if(pbNew->count == 0)
                    248:                    {
                    249:                        pbNew->miny2 = pbox->y2;
                    250:                    }
                    251:                    pbNew->count++;
                    252:                    pbNew->boxes = (BoxPtr)Xrealloc(pbNew->boxes, pbNew->count *
                    253:                                            sizeof(BoxRec));
                    254:                    pboxNew = &pbNew->boxes[pbNew->count - 1];
                    255:                    pboxNew->x1 = pbox->x1;
                    256:                    pboxNew->y1 = pbNew->y;
                    257:                    pboxNew->x2 = pbox->x2;
                    258:                    pboxNew->y2 = pbox->y2;
                    259:                    if(pboxNew->y2 !=pbNew->miny2)
                    260:                        pbNew->fdiff = TRUE;
                    261:                    if(pboxNew->y2 < pbNew->miny2)
                    262:                        pbNew->miny2 = pboxNew->y2;
                    263:                    
                    264:                }
                    265:                pbox++;
                    266:            }
                    267:        }
                    268:        else
                    269:        {
                    270:           pbNew = pb->next;
                    271:        }
                    272: 
                    273:        pb = pbNew;
                    274:     }
                    275: 
                    276:     /* X sort the buckets, and tally total size */
                    277:     pb = pbFirst;
                    278:     count = 0;
                    279:     while(pb)
                    280:     {
                    281:        count += pb->count;
                    282:        /* Yes, it's a bubble sort.  I wanted something (a) in place,
                    283:         * (b) with a low startup cost, because I expect to find few
                    284:         * rectangles per yband and don't want to spend more effort setting
                    285:         * up the sort than I do performing it.
                    286:         */
                    287:        fChanged = TRUE;
                    288:        while(fChanged)
                    289:        {
                    290:            fChanged = FALSE;
                    291:            pbox = pb->boxes;
                    292:            while(pbox < pb->boxes + pb->count - 1)
                    293:            {
                    294:                if(pbox->x1 > (pbox+1)->x1)
                    295:                {
                    296:                    tbox = *pbox;
                    297:                    *pbox = *(pbox + 1);
                    298:                    *(pbox + 1) = tbox;
                    299:                    fChanged = TRUE;
                    300:                }
                    301:                pbox++;
                    302:            }
                    303:        }
                    304:        pb = pb->next;
                    305:     }
                    306: 
                    307:     /* copy the rectangles into the region and free up the buckets */
                    308:     pReg->rects = (BoxPtr) Xrealloc (pReg->rects, count * sizeof(BoxRec));
                    309:     pReg->numRects = count;
                    310:     pReg->size = count;
                    311:     pboxNew = pReg->rects;
                    312:     pb = pbFirst;
                    313:     while(pb)
                    314:     {
                    315:        for(pbox = pb->boxes; pbox < pb->boxes + pb->count; pbox++)
                    316:        {
                    317:            *pboxNew++ = *pbox;
                    318:        }
                    319:        Xfree((char *)pb->boxes);
                    320: 
                    321:        pb = pb->next;
                    322:        Xfree(pb);
                    323:     }
                    324:     pReg->extents.x1 = xMin;
                    325:     pReg->extents.y1 = yMin;
                    326:     pReg->extents.x2 = xMax;
                    327:     pReg->extents.y2 = yMax;
                    328:     return(pReg);
                    329: 
                    330: }
                    331: 

unix.superglobalmegacorp.com

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