Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/miwidedash.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: miwidedash.c,v 1.13 87/08/31 17:01:06 toddb Exp $ */
                     25: /* Author: Todd "Mr. Wide Line" Newman */
                     26: 
                     27: #include "X.h"
                     28: #include "Xprotostr.h"
                     29: #include "miscstruct.h"
                     30: #include "mistruct.h"
                     31: #include "scrnintstr.h"
                     32: #include "windowstr.h"
                     33: #include "gcstruct.h"
                     34: #include "pixmapstr.h"
                     35: #include "mifpoly.h"
                     36: 
                     37: #define GCVALSALU      0
                     38: #define GCVALSFORE     1
                     39: #define GCVALSBACK     2
                     40: #define GCVALSWIDTH    3
                     41: #define GCVALSCAPSTYLE 4
                     42: #define GCVALSARCMODE  5
                     43: static int gcvals[] = {GXcopy, 1, 0, 0, 0, ArcChord};
                     44: 
                     45: /* Neither Fish nor Fowl, it's a Wide Dashed Line. */
                     46: /* Actually, wide, dashed lines Are pretty foul. (You knew that was coming,
                     47:  * didn't you.) */
                     48: 
                     49: /* MIWIDEDASH -- Public entry for PolyLine Requests when the GC speicifies
                     50:  * that we must be dashing (All Hail Errol Flynn)
                     51:  *
                     52:  * We must use the raster op to decide how whether we will draw directly into
                     53:  * the Drawable or squeegee bits through a scratch pixmap to avoid the dash
                     54:  * interfering with itself.
                     55:  * 
                     56:  * miDashLine will convert the poly line we were called with into the
                     57:  * appropriate set of line segments. 
                     58:  * Based on the dash style we then draw the segments. For OnOff dashes we
                     59:  * draw every other segment and cap each segment.  For DoubleDashes, we
                     60:  * draw every other segment starting with the first in the foreground color,
                     61:  * then draw every other segment starting with the second in the background
                     62:  * color.  Then we cap the first and last segments "by hand."
                     63:  */
                     64: void
                     65: miWideDash(pDraw, pGC, mode, npt, pPtsIn)
                     66:     DrawablePtr pDraw;
                     67:     GCPtr      pGC;
                     68:     int                mode;
                     69:     int                npt;
                     70:     DDXPointPtr pPtsIn;
                     71: {
                     72: 
                     73:     SppPointPtr        pPts, ppt;
                     74:     int                nseg, which, whichPrev, i, j, xOrg, yOrg, width,
                     75:                fTricky, arcmode, xMin, xMax, yMin, yMax,
                     76:                dxi, dyi, gcflags;
                     77:     unsigned long oldfore, newfore;
                     78:     miDashPtr  dashes;
                     79:     double     dy, dx, m;
                     80:     Bool       IsDoubleDash = (pGC->lineStyle == LineDoubleDash),
                     81:                fXmajor;
                     82:     SppPointRec pt, PointStash[4], PolyPoints[4];
                     83:     DDXPointPtr pPtIn;
                     84:     DrawablePtr        pDrawTo;
                     85:     GCPtr      pGCTo;
                     86: 
                     87: 
                     88:     m = EPSILON;
                     89:     if (mode == CoordModePrevious)
                     90:     {
                     91:        DDXPointPtr pptT;
                     92:        int nptTmp;
                     93: 
                     94:        pptT = pPtsIn + 1;
                     95:        nptTmp = npt - 1;
                     96:        while (nptTmp--)
                     97:        {
                     98:            pptT->x += (pptT-1)->x;
                     99:            pptT->y += (pptT-1)->y;
                    100:            pptT++;
                    101:        }
                    102:     }
                    103: 
                    104:     width = pGC->lineWidth;
                    105:     switch(pGC->alu)
                    106:     {
                    107:       case GXclear:            /* 0 */
                    108:       case GXcopy:             /* src */
                    109:       case GXcopyInverted:     /* NOT src */
                    110:       case GXset:              /* 1 */
                    111:        fTricky = FALSE;
                    112:         xOrg = yOrg = 0;
                    113:        pDrawTo = pDraw;
                    114:        pGCTo = pGC;
                    115:        if(pGCTo->arcMode != ArcChord)
                    116:        {
                    117:            arcmode = pGCTo->arcMode;
                    118:            DoChangeGC(pGCTo, GCArcMode, &gcvals[GCVALSARCMODE], 0);
                    119:            ValidateGC(pDrawTo, pGCTo);
                    120:        }
                    121:        else
                    122:            arcmode = ArcChord;
                    123: 
                    124:        break;
                    125:       case GXand:              /* src AND dst */
                    126:       case GXandReverse:       /* src AND NOT dst */
                    127:       case GXandInverted:      /* NOT src AND dst */
                    128:       case GXnoop:             /* dst */
                    129:       case GXxor:              /* src XOR dst */
                    130:       case GXor        :               /* src OR dst */
                    131:       case GXnor:              /* NOT src AND NOT dst */
                    132:       case GXequiv:            /* NOT src XOR dst */
                    133:       case GXinvert:           /* NOT dst */
                    134:       case GXorReverse:                /* src OR NOT dst */
                    135:       case GXorInverted:       /* NOT src OR dst */
                    136:       case GXnand:             /* NOT src OR NOT dst */
                    137:        fTricky = TRUE;
                    138:        yMin = yMax = pPtsIn[0].y;
                    139:        xMin = xMax = pPtsIn[0].x;
                    140: 
                    141:        for (i = 1; i < npt; i++)
                    142:        {
                    143:            xMin = min(xMin, pPtsIn[i].x);
                    144:            xMax = max(xMax, pPtsIn[i].x);
                    145:            yMin = min(yMin, pPtsIn[i].y);
                    146:            yMax = max(yMax, pPtsIn[i].y);
                    147:        }
                    148:        xOrg = xMin - (width + 1)/2;
                    149:        yOrg = yMin - (width + 1)/2;
                    150:        dxi = xMax - xMin + width;
                    151:        dyi = yMax - yMin + width;
                    152:        pDrawTo = (DrawablePtr) (*pDraw->pScreen->CreatePixmap)
                    153:          (pDraw->pScreen, dxi, dyi, 1, XYBitmap);
                    154:        pGCTo =  GetScratchGC(1, pDraw->pScreen);
                    155:        gcvals[GCVALSWIDTH] = width;
                    156:        gcvals[GCVALSCAPSTYLE] = pGC->capStyle;
                    157:        gcflags = GCFunction | GCForeground | GCBackground | GCLineWidth |
                    158:                  GCCapStyle;
                    159:        if(pGCTo->arcMode != ArcChord)
                    160:            gcflags |= GCArcMode;
                    161:        DoChangeGC(pGCTo, gcflags, gcvals, 0);
                    162:        ValidateGC(pDrawTo, pGCTo);
                    163:        miClearDrawable(pDrawTo, pGCTo);
                    164: 
                    165:     }
                    166: 
                    167:     dashes = miDashLine(npt, pPtsIn,
                    168:                pGC->numInDashList, pGC->dash, pGC->dashOffset, &nseg);
                    169:     if(!(pPts = (SppPointPtr) Xalloc((nseg + 1) * sizeof(SppPointRec))))
                    170:     {
                    171:        Xfree(dashes);
                    172:        if(fTricky)
                    173:            (*pDraw->pScreen->DestroyPixmap)(pDrawTo);
                    174:        return;
                    175:     }
                    176:     ppt = pPts;
                    177:     pPtIn = pPtsIn;
                    178:     whichPrev = EVEN_DASH;
                    179: 
                    180:     j = 0;
                    181:     for(i = 0; i < nseg + 1; i++)
                    182:     {
                    183:        if(dashes[i].newLine)
                    184:        {
                    185:            /* calculate slope of the line */
                    186:            dx = (double) ((pPtsIn + 1)->x - pPtIn->x);
                    187:            dy = (double) ((pPtsIn + 1)->y - pPtIn->y);
                    188:            pPtIn++;
                    189:            /* use slope of line to figure out how to use error term */
                    190:            fXmajor = (fabs(dx) > fabs(dy));
                    191:            if(fXmajor)
                    192:                m = !ISZERO(dx) ? (dy/dx) : EPSILON;
                    193:            else
                    194:                m = !ISZERO(dy) ? (dx/dy) : EPSILON;
                    195:        }
                    196:        /* Add this point to our list, adjusting the error term as needed */
                    197:        ppt->x = (double) dashes[i].pt.x;
                    198:        ppt->y = (double) dashes[i].pt.y;
                    199: 
                    200:        if(i < 2 || i > nseg - 2)
                    201:        {
                    202:            PointStash[j++] = *ppt;
                    203:        }
                    204:        ppt++;
                    205:        which = dashes[i].which;
                    206:        if(which != whichPrev)
                    207:        {
                    208:            if(which == ODD_DASH)
                    209:            {
                    210:                /* Display the collect line */
                    211:                (*pGC->LineHelper)(pDrawTo, pGCTo, !IsDoubleDash,
                    212:                                   ppt - pPts, pPts, xOrg, yOrg);
                    213:            }
                    214:            /* Reset the line  and start a new dash */
                    215:            pPts[0] = ppt[-1];
                    216:            ppt = &pPts[1];
                    217:            whichPrev = which;
                    218:        }
                    219: 
                    220:     }
                    221:     if(IsDoubleDash)
                    222:     {
                    223:         ppt = pPts;
                    224:         pPtIn = pPtsIn;
                    225:        whichPrev = EVEN_DASH;
                    226: 
                    227:        /* cap the first (and maybe the last) line segment(s)  appropriately */
                    228:        if(pGC->capStyle == CapProjecting)
                    229:        {
                    230:            pt = miExtendSegment(PointStash[0], PointStash[1], width/2);
                    231:            miGetPts(pt, PointStash[0],
                    232:                &PolyPoints[0], &PolyPoints[1], &PolyPoints[2], &PolyPoints[3],
                    233:                width);
                    234:            miFillSppPoly(pDrawTo, pGCTo, 4, PolyPoints, xOrg, yOrg);
                    235:            if(dashes[nseg].which == EVEN_DASH)
                    236:            {
                    237:                pt = miExtendSegment(PointStash[3], PointStash[2], width/2);
                    238:                miGetPts(pt, PointStash[3],
                    239:                    &PolyPoints[0], &PolyPoints[1], &PolyPoints[2],
                    240:                    &PolyPoints[3], width);
                    241:                miFillSppPoly(pDrawTo, pGCTo, 4, PolyPoints, xOrg, yOrg);
                    242:            }
                    243:         
                    244:        }
                    245:        else if (pGC->capStyle == CapRound)
                    246:        {
                    247:            miGetPts(PointStash[0], PointStash[1],
                    248:                &PolyPoints[0], &PolyPoints[1], &PolyPoints[2], &PolyPoints[3],
                    249:                width);
                    250:            miRoundCap(pDrawTo, pGCTo, PointStash[0], PointStash[1],
                    251:                     PolyPoints[0], PolyPoints[3], FirstEnd, xOrg, yOrg);
                    252:            if(dashes[nseg].which == EVEN_DASH)
                    253:            {
                    254:                miGetPts(PointStash[3], PointStash[2],
                    255:                    &PolyPoints[0], &PolyPoints[1], &PolyPoints[2],
                    256:                    &PolyPoints[3], width);
                    257:                miRoundCap(pDrawTo, pGCTo, PointStash[3], PointStash[2],
                    258:                         PolyPoints[3], PolyPoints[0], SecondEnd, xOrg, yOrg);
                    259:            }
                    260:        }
                    261:        oldfore = pGC->fgPixel;
                    262:        newfore = pGC->bgPixel;
                    263:        DoChangeGC(pGCTo, GCForeground, &newfore, 0);
                    264:        ValidateGC(pDrawTo, pGCTo);
                    265: 
                    266:        for(i = 0; i < nseg + 1; i++)
                    267:        {
                    268:            if(dashes[i].newLine)
                    269:            {
                    270:                /* calculate slope of the line */
                    271:                dx = (double) ((pPtIn + 1)->x - pPtIn->x);
                    272:                dy = (double) ((pPtIn + 1)->y - pPtIn->y);
                    273:                /* use slope of line to figure out how to use error term */
                    274:                fXmajor = (fabs(dx) > fabs(dy));
                    275:                if(fXmajor)
                    276:                    m = ISZERO(dx) ? (dy/dx) : EPSILON;
                    277:                else
                    278:                    m = ISZERO(dy) ? (dx/dy) : EPSILON;
                    279:                pPtIn++;
                    280:            }
                    281:            /* Add this point to our list */
                    282:            ppt->x = (double) dashes[i].pt.x +
                    283:                        (fXmajor ? 0.0 : dashes[i].e*m);
                    284:            ppt->y = (double) dashes[i].pt.y +
                    285:                        (fXmajor ? dashes[i].e*m : 0.0);
                    286:            ppt++;
                    287:            which = dashes[i].which;
                    288:            if(which != whichPrev)
                    289:            {
                    290:                if(which == EVEN_DASH)
                    291:                {
                    292:                    /* Display the collected line */
                    293:                    (*pGC->LineHelper)(pDrawTo, pGCTo, FALSE,
                    294:                                       ppt - pPts, pPts, xOrg, yOrg);
                    295:                }
                    296:                /* Reset the line  and start a new dash */
                    297:                pPts[0] = ppt[-1];
                    298:                ppt = &pPts[1];
                    299:                whichPrev = which;
                    300:            }
                    301: 
                    302:        }
                    303: 
                    304:        /* cap the last line segments appropriately */
                    305:        if(dashes[nseg].which == ODD_DASH)
                    306:        {
                    307:            if(pGC->capStyle == CapProjecting)
                    308:            {
                    309:                pt = miExtendSegment(PointStash[3], PointStash[2], width/2);
                    310:                miGetPts(pt, PointStash[3],
                    311:                    &PolyPoints[0], &PolyPoints[1], &PolyPoints[2],
                    312:                    &PolyPoints[3], width);
                    313:                miFillSppPoly(pDrawTo, pGCTo, 4, PolyPoints, xOrg, yOrg);
                    314:             
                    315:            }
                    316:            else if (pGC->capStyle == CapRound)
                    317:            {
                    318:                miGetPts(PointStash[3], PointStash[2],
                    319:                    &PolyPoints[0], &PolyPoints[1], &PolyPoints[2],
                    320:                    &PolyPoints[3], width);
                    321:                miRoundCap(pDrawTo, pGCTo, PointStash[3], PointStash[2],
                    322:                         PolyPoints[3], PolyPoints[0], SecondEnd, xOrg, yOrg);
                    323:            }
                    324:        }
                    325:        DoChangeGC(pGCTo, GCForeground, &oldfore, 0);
                    326:     }
                    327:     if(arcmode != ArcChord)
                    328:     {
                    329:        DoChangeGC(pGCTo, GCArcMode, &gcvals[GCVALSARCMODE], 0);
                    330:     }
                    331:     ValidateGC(pDrawTo, pGCTo);
                    332:     if(fTricky)
                    333:     {
                    334:        if (pGC->miTranslate && (pDraw->type == DRAWABLE_WINDOW) )
                    335:        {
                    336:            xOrg += ((WindowPtr)pDraw)->absCorner.x;
                    337:            yOrg += ((WindowPtr)pDraw)->absCorner.y;
                    338:        }
                    339: 
                    340:        (*pGC->PushPixels)(pGC, pDrawTo, pDraw, dxi, dyi, xOrg, yOrg);
                    341:        (*pDraw->pScreen->DestroyPixmap)(pDrawTo);
                    342:         FreeScratchGC(pGCTo);
                    343:     }
                    344:     Xfree(dashes);
                    345:     Xfree(pPts);
                    346: }

unix.superglobalmegacorp.com

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