Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/miwidedash.c, revision 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.