Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mibitblt.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: mibitblt.c,v 1.52 87/09/13 20:56:01 toddb Exp $ */
        !            25: /* Author: Todd Newman  (aided and abetted by Mr. Drewry) */
        !            26: 
        !            27: #include "X.h"
        !            28: #include "Xprotostr.h"
        !            29: 
        !            30: #include "misc.h"
        !            31: #include "gcstruct.h"
        !            32: #include "pixmapstr.h"
        !            33: #include "windowstr.h"
        !            34: #include "scrnintstr.h"
        !            35: #include "mi.h"
        !            36: #include "regionstr.h"
        !            37: #include "Xmd.h"
        !            38: #include "../mfb/maskbits.h"
        !            39: #include "servermd.h"
        !            40: 
        !            41: 
        !            42: /* MICOPYAREA -- public entry for the CopyArea request 
        !            43:  * For each rectangle in the source region
        !            44:  *     get the pixels with GetSpans
        !            45:  *     set them in the destination with SetSpans
        !            46:  * We let SetSpans worry about clipping to the destination.
        !            47:  */
        !            48: void
        !            49: miCopyArea(pSrcDrawable, pDstDrawable,
        !            50:            pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut)
        !            51:     register DrawablePtr       pSrcDrawable;
        !            52:     register DrawablePtr       pDstDrawable;
        !            53:     GCPtr                      pGC;
        !            54:     int                        xIn, yIn;
        !            55:     int                        widthSrc, heightSrc;
        !            56:     int                        xOut, yOut;
        !            57: {
        !            58:     DDXPointPtr                ppt, pptFirst;
        !            59:     unsigned int       *pwidthFirst, *pwidth, *pbits;
        !            60:     BoxRec             srcBox, *prect;
        !            61:                        /* may be a new region, or just a copy */
        !            62:     RegionPtr          prgnSrcClip;
        !            63:                        /* non-0 if we've created a src clip */
        !            64:     int                realSrcClip = 0;
        !            65:     int                        srcx, srcy, dstx, dsty, i, j, y, width, height,
        !            66:                        xMin, xMax, yMin, yMax;
        !            67:     unsigned int       *ordering;
        !            68: 
        !            69:     /* clip the left and top edges of the source */
        !            70:     if (xIn < 0)
        !            71:     {
        !            72:         widthSrc += xIn;
        !            73:         srcx = 0;
        !            74:     }
        !            75:     else
        !            76:        srcx = xIn;
        !            77:     if (yIn < 0)
        !            78:     {
        !            79:         heightSrc += yIn;
        !            80:         srcy = 0;
        !            81:     }
        !            82:     else
        !            83:        srcy = yIn;
        !            84: 
        !            85: 
        !            86:     /* If the destination isn't realized, this is easy */
        !            87:     if (pDstDrawable->type == DRAWABLE_WINDOW &&
        !            88:        !((WindowPtr)pDstDrawable)->realized)
        !            89:     {
        !            90:        miSendNoExpose(pGC);
        !            91:        return;
        !            92:     }
        !            93: 
        !            94:     /* clip the source */
        !            95:     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
        !            96:     {
        !            97:        BoxRec box;
        !            98: 
        !            99:        box.x1 = 0;
        !           100:        box.y1 = 0;
        !           101:        box.x2 = ((PixmapPtr)pSrcDrawable)->width;
        !           102:        box.y2 = ((PixmapPtr)pSrcDrawable)->height;
        !           103: 
        !           104:        prgnSrcClip = (*pGC->pScreen->RegionCreate)(&box, 1);
        !           105:        realSrcClip = 1;
        !           106:     }
        !           107:     else
        !           108:     {
        !           109:        srcx += ((WindowPtr)pSrcDrawable)->absCorner.x;
        !           110:        srcy += ((WindowPtr)pSrcDrawable)->absCorner.y;
        !           111:        prgnSrcClip = ((WindowPtr)pSrcDrawable)->clipList;
        !           112:     }
        !           113: 
        !           114:     /* If the src drawable is a window, we need to translate the srcBox so
        !           115:      * that we can compare it with the window's clip region later on. */
        !           116:     srcBox.x1 = srcx;
        !           117:     srcBox.y1 = srcy;
        !           118:     srcBox.x2 = srcx  + widthSrc;
        !           119:     srcBox.y2 = srcy  + heightSrc;
        !           120: 
        !           121:     if (pGC->miTranslate && (pDstDrawable->type == DRAWABLE_WINDOW) )
        !           122:     {
        !           123:        dstx = xOut + ((WindowPtr)pDstDrawable)->absCorner.x;
        !           124:        dsty = yOut + ((WindowPtr)pDstDrawable)->absCorner.y;
        !           125:     }
        !           126:     else
        !           127:     {
        !           128:        dstx = xOut;
        !           129:        dsty = yOut;
        !           130:     }
        !           131: 
        !           132: 
        !           133: 
        !           134:     pptFirst = ppt = (DDXPointPtr)
        !           135:         ALLOCATE_LOCAL(heightSrc * sizeof(DDXPointRec));
        !           136:     pwidthFirst = pwidth = (unsigned int *)
        !           137:         ALLOCATE_LOCAL(heightSrc * sizeof(unsigned int));
        !           138:     ordering = (unsigned int *)
        !           139:         ALLOCATE_LOCAL(prgnSrcClip->numRects * sizeof(unsigned int));
        !           140:     if(!pptFirst || !pwidthFirst || !ordering)
        !           141:     {
        !           142:        if (pptFirst)
        !           143:            DEALLOCATE_LOCAL(pptFirst);
        !           144:        if (pwidthFirst)
        !           145:            DEALLOCATE_LOCAL(pwidthFirst);
        !           146:        if (ordering)
        !           147:           DEALLOCATE_LOCAL(ordering);
        !           148:        return;
        !           149:     }
        !           150: 
        !           151:     /* If not the same drawable then order of move doesn't matter.
        !           152:        Following assumes that prgnSrcClip->rects are sorted from top
        !           153:        to bottom and left to right.
        !           154:     */
        !           155:     if (pSrcDrawable != pDstDrawable)
        !           156:       for (i=0; i < prgnSrcClip->numRects; i++)
        !           157:         ordering[i] = i;
        !           158:     else { /* within same drawable, must sequence moves carefully! */
        !           159:       if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
        !           160:                                   Vertical order OK */
        !           161:         if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
        !           162:                                   Horizontal order OK as well */
        !           163:           for (i=0; i < prgnSrcClip->numRects; i++)
        !           164:             ordering[i] = i;
        !           165:         else { /* scroll right. must reverse horizontal banding of rects. */
        !           166:           for (i=0, j=1, xMax=0;
        !           167:                i < prgnSrcClip->numRects;
        !           168:                j=i+1, xMax=i) {
        !           169:             /* find extent of current horizontal band */
        !           170:             y=prgnSrcClip->rects[i].y1; /* band has this y coordinate */
        !           171:             while ((j < prgnSrcClip->numRects) &&
        !           172:                    (prgnSrcClip->rects[j].y1 == y))
        !           173:               j++;
        !           174:             /* reverse the horizontal band in the output ordering */
        !           175:             for (j-- ; j >= xMax; j--, i++)
        !           176:               ordering[i] = j;
        !           177:           }
        !           178:         }
        !           179:       }
        !           180:       else { /* Scroll down. Must reverse vertical banding. */
        !           181:         if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
        !           182:           for (i=prgnSrcClip->numRects-1, j=i-1, yMin=i, yMax=0;
        !           183:               i >= 0;
        !           184:               j=i-1, yMin=i) {
        !           185:             /* find extent of current horizontal band */
        !           186:             y=prgnSrcClip->rects[i].y1; /* band has this y coordinate */
        !           187:             while ((j >= 0) &&
        !           188:                    (prgnSrcClip->rects[j].y1 == y))
        !           189:               j--;
        !           190:             /* reverse the horizontal band in the output ordering */
        !           191:             for (j++ ; j <= yMin; j++, i--, yMax++)
        !           192:               ordering[yMax] = j;
        !           193:           }
        !           194:         }
        !           195:         else /* Scroll right or horizontal stationary.
        !           196:                 Reverse horizontal order as well (if stationary, horizontal
        !           197:                 order can be swapped without penalty and this is faster
        !           198:                 to compute). */
        !           199:           for (i=0, j=prgnSrcClip->numRects-1;
        !           200:                i < prgnSrcClip->numRects;
        !           201:                i++, j--)
        !           202:               ordering[i] = j;
        !           203:       }
        !           204:     }
        !           205:  
        !           206:      for(i = 0;
        !           207:          i < prgnSrcClip->numRects;
        !           208:          i++)
        !           209:      {
        !           210:         prect = &prgnSrcClip->rects[ordering[i]];
        !           211:        xMin = max(prect->x1, srcBox.x1);
        !           212:        xMax = min(prect->x2, srcBox.x2);
        !           213:        yMin = max(prect->y1, srcBox.y1);
        !           214:        yMax = min(prect->y2, srcBox.y2);
        !           215:        /* is there anything visible here? */
        !           216:        if(xMax <= xMin || yMax <= yMin)
        !           217:            continue;
        !           218: 
        !           219:         ppt = pptFirst;
        !           220:        pwidth = pwidthFirst;
        !           221:        y = yMin;
        !           222:        height = yMax - yMin;
        !           223:        width = xMax - xMin;
        !           224: 
        !           225:        for(j = 0; j < height; j++)
        !           226:        {
        !           227:            /* We must untranslate before calling GetSpans */
        !           228:            ppt->x = xMin;
        !           229:            ppt++->y = y++;
        !           230:            *pwidth++ = width;
        !           231:        }
        !           232:        pbits = (*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, 
        !           233:                                               pptFirst, pwidthFirst, height);
        !           234:         ppt = pptFirst;
        !           235:        pwidth = pwidthFirst;
        !           236:        xMin -= (srcx - dstx);
        !           237:        y = yMin - (srcy - dsty);
        !           238:        for(j = 0; j < height; j++)
        !           239:        {
        !           240:            ppt->x = xMin;
        !           241:            ppt++->y = y++;
        !           242:            *pwidth++ = width;
        !           243:        }
        !           244:        
        !           245:         (*pGC->SetSpans)(pDstDrawable, pGC, pbits, pptFirst, pwidthFirst,
        !           246:                         height, TRUE);
        !           247:         Xfree(pbits);
        !           248:     }
        !           249:     miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
        !           250:                      widthSrc, heightSrc, xOut, yOut);
        !           251:     if(realSrcClip)
        !           252:        (*pGC->pScreen->RegionDestroy)(prgnSrcClip);
        !           253:                
        !           254:     DEALLOCATE_LOCAL(pptFirst);
        !           255:     DEALLOCATE_LOCAL(pwidthFirst);
        !           256:     DEALLOCATE_LOCAL(ordering);
        !           257: }
        !           258: 
        !           259: /* MIGETPLANE -- gets a bitmap representing one plane of pDraw
        !           260:  * A helper used for CopyPlane and XY format GetImage 
        !           261:  * No clever strategy here, we grab a scanline at a time, pull out the
        !           262:  * bits and then stuff them in a 1 bit deep map.
        !           263:  */
        !           264: static
        !           265: unsigned long  *
        !           266: miGetPlane(pDraw, planeNum, sx, sy, w, h, result)
        !           267:     DrawablePtr                pDraw;
        !           268:     int                        planeNum;       /* number of the bitPlane */
        !           269:     int                        sx, sy, w, h;
        !           270:     unsigned long      *result;
        !           271: {
        !           272:     int                        i, j, k, depth, width, bitsPerPixel, widthInBytes;
        !           273:     DDXPointRec        pt;
        !           274:     unsigned int       *pline;
        !           275:     unsigned int       bit;
        !           276:     unsigned char      *pCharsOut;
        !           277:     CARD16             *pShortsOut;
        !           278:     CARD32             *pLongsOut;
        !           279: 
        !           280:     depth = pDraw->depth;
        !           281:     if(pDraw->type != DRAWABLE_PIXMAP)
        !           282:     {
        !           283:        sx += ((WindowPtr) pDraw)->absCorner.x;
        !           284:        sy += ((WindowPtr) pDraw)->absCorner.y;
        !           285:     }
        !           286:     widthInBytes = PixmapBytePad(w, 1);
        !           287:     if(!result)
        !           288:         result = (unsigned long *)Xalloc(h * widthInBytes);
        !           289:     bitsPerPixel = GetBitsPerPixel(depth);
        !           290:     bzero(result, h * widthInBytes);
        !           291:     if(BITMAP_SCANLINE_UNIT == 8)
        !           292:        pCharsOut = (unsigned char *) result;
        !           293:     else if(BITMAP_SCANLINE_UNIT == 16)
        !           294:        pShortsOut = (CARD16 *) result;
        !           295:     else if(BITMAP_SCANLINE_UNIT == 32)
        !           296:        pLongsOut = (CARD32 *) result;
        !           297:     if(bitsPerPixel == 1)
        !           298:        pCharsOut = (unsigned char *) result;
        !           299:     for(i = sy; i < sy + h; i++)
        !           300:     {
        !           301:        if(bitsPerPixel == 1)
        !           302:        {
        !           303:            pt.x = sx;
        !           304:            pt.y = i;
        !           305:            width = w;
        !           306:             pline = (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1); 
        !           307:            bcopy(pline, pCharsOut, (w + 7)/8);
        !           308:            pCharsOut += widthInBytes;
        !           309:            Xfree(pline);
        !           310:        }
        !           311:        else
        !           312:        {
        !           313:            k = 0;
        !           314:            for(j = 0; j < w; j++)
        !           315:            {
        !           316:                pt.x = sx + j;
        !           317:                pt.y = i;
        !           318:                width = 1;
        !           319:                /* Fetch the next pixel */
        !           320:                pline = (*pDraw->pScreen->GetSpans)(pDraw, width, &pt,
        !           321:                                                   &width, 1);
        !           322:                bit = (unsigned int) ((*pline >> planeNum) & 1);
        !           323:                /* Now insert that bit into a bitmap in XY format */
        !           324:                if(BITMAP_BIT_ORDER == LSBFirst)
        !           325:                    bit <<= k;
        !           326:                else
        !           327:                    bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
        !           328:                if(BITMAP_SCANLINE_UNIT == 8)
        !           329:                {
        !           330:                    *pCharsOut |= (unsigned char) bit;
        !           331:                    k++;
        !           332:                    if (k == 8)
        !           333:                    {
        !           334:                        pCharsOut++;
        !           335:                        k = 0;
        !           336:                    }
        !           337:                }
        !           338:                else if(BITMAP_SCANLINE_UNIT == 16)
        !           339:                {
        !           340:                    *pShortsOut |= (CARD16) bit;
        !           341:                    k++;
        !           342:                    if (k == 16)
        !           343:                    {
        !           344:                        pShortsOut++;
        !           345:                        k = 0;
        !           346:                    }
        !           347:                }
        !           348:                if(BITMAP_SCANLINE_UNIT == 32)
        !           349:                {
        !           350:                    *pLongsOut |= (CARD32) bit;
        !           351:                    k++;
        !           352:                    if (k == 32)
        !           353:                    {
        !           354:                        pLongsOut++;
        !           355:                        k = 0;
        !           356:                    }
        !           357:                }
        !           358:                Xfree(pline);
        !           359:            }
        !           360: 
        !           361:        }
        !           362:     }
        !           363:     return(result);    
        !           364: 
        !           365: }
        !           366: 
        !           367: /* GETBITSPERPIXEL -- Find out how many bits per pixel are supported at
        !           368:  * this depth -- another helper function 
        !           369:  */
        !           370: static
        !           371: int
        !           372: GetBitsPerPixel(depth)
        !           373:     int                depth;
        !           374: {
        !           375:     int        i;
        !           376: 
        !           377:     for(i = 0; i < screenInfo.numPixmapFormats; i++)
        !           378:     {
        !           379:         if(screenInfo.formats[i].depth == depth)
        !           380:        {
        !           381:            return (screenInfo.formats[i].bitsPerPixel);
        !           382:        }
        !           383:     }
        !           384:     return(1);
        !           385: }
        !           386: 
        !           387: 
        !           388: /* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
        !           389:  * Drawing through the clip mask we SetSpans() the bits into a 
        !           390:  * bitmap and stipple those bits onto the destination drawable by doing a
        !           391:  * PolyFillRect over the whole drawable, 
        !           392:  * then we invert the bitmap by copying it onto itself with an alu of
        !           393:  * GXinvert, invert the foreground/background colors of the gc, and draw
        !           394:  * the background bits.
        !           395:  * Note how the clipped out bits of the bitmap are always the background
        !           396:  * color so that the stipple never causes FillRect to draw them.
        !           397:  */
        !           398: void
        !           399: miOpqStipDrawable(pDraw, pGC, prgnSrc, pbits, srcx, w, h, dstx, dsty)
        !           400:     DrawablePtr pDraw;
        !           401:     GCPtr      pGC;
        !           402:     RegionPtr  prgnSrc;
        !           403:     unsigned long      *pbits;
        !           404:     int                srcx, w, h, dstx, dsty;
        !           405: {
        !           406:     int                oldfill, i;
        !           407:     unsigned long oldfg;
        !           408:     int                *pwidth, *pwidthFirst;
        !           409:     long       gcv[6];
        !           410:     PixmapPtr  pStipple, pPixmap;
        !           411:     DDXPointRec        oldOrg;
        !           412:     GCPtr      pGCT;
        !           413:     DDXPointPtr ppt, pptFirst;
        !           414:     xRectangle rect;
        !           415:     RegionPtr  prgnSrcClip;
        !           416: 
        !           417:     pPixmap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap)
        !           418:                           (pDraw->pScreen, w, h, 1);
        !           419: 
        !           420:     if (!pPixmap)
        !           421:     {
        !           422:        ErrorF( "miOpqStipDrawable can't make temp pixmap\n");
        !           423:        return;
        !           424:     }
        !           425: 
        !           426:     /* Put the image into a 1 bit deep pixmap */
        !           427:     pGCT = GetScratchGC(1, pDraw->pScreen);
        !           428:     /* First set the whole pixmap to 0 */
        !           429:     gcv[0] = 0;
        !           430:     DoChangeGC(pGCT, GCBackground, gcv, 0);
        !           431:     ValidateGC(pPixmap, pGCT);
        !           432:     miClearDrawable(pPixmap, pGCT);
        !           433:     ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec));
        !           434:     pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int));
        !           435:     if(!ppt || !pwidth)
        !           436:     {
        !           437:        DEALLOCATE_LOCAL(pwidthFirst);
        !           438:        DEALLOCATE_LOCAL(pptFirst);
        !           439:        FreeScratchGC(pGCT);
        !           440:        return;
        !           441:     }
        !           442: 
        !           443:     /* we need a temporary region because ChangeClip must be assumed
        !           444:        to destroy what it's sent.  note that this means we don't
        !           445:        have to free prgnSrcClip ourselves.
        !           446:     */
        !           447:     prgnSrcClip = (*pGCT->pScreen->RegionCreate)(NULL, 0);
        !           448:     (*pGCT->pScreen->RegionCopy)(prgnSrcClip, prgnSrc);
        !           449:     (*pGCT->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0);
        !           450:     ValidateGC(pPixmap, pGCT);
        !           451: 
        !           452:     /* Since we know pDraw is always a pixmap, we never need to think
        !           453:      * about translation here */
        !           454:     for(i = 0; i < h; i++)
        !           455:     {
        !           456:        ppt->x = srcx;
        !           457:        ppt++->y = i;
        !           458:        *pwidth++ = w;
        !           459:     }
        !           460: 
        !           461:     (*pGCT->SetSpans)(pPixmap, pGCT, pbits, pptFirst, pwidthFirst, h, TRUE);
        !           462:     DEALLOCATE_LOCAL(pwidthFirst);
        !           463:     DEALLOCATE_LOCAL(pptFirst);
        !           464: 
        !           465: 
        !           466:     /* Save current values from the client GC */
        !           467:     oldfill = pGC->fillStyle;
        !           468:     pStipple = pGC->stipple;
        !           469:     if(pStipple)
        !           470:         pStipple->refcnt++;
        !           471:     oldOrg = pGC->patOrg;
        !           472: 
        !           473:     /* Set a new stipple in the drawable */
        !           474:     gcv[0] = FillStippled;
        !           475:     gcv[1] = (long) pPixmap;
        !           476:     gcv[2] = dstx;
        !           477:     gcv[3] = dsty;
        !           478: 
        !           479:     DoChangeGC(pGC,
        !           480:              GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
        !           481:             gcv, 1);
        !           482:     ValidateGC(pDraw, pGC);
        !           483: 
        !           484:     /* Fill the drawable with the stipple.  This will draw the
        !           485:      * foreground color whereever 1 bits are set, leaving everything
        !           486:      * with 0 bits untouched.  Note that the part outside the clip
        !           487:      * region is all 0s.  */
        !           488:     rect.x = dstx;
        !           489:     rect.y = dsty;
        !           490:     rect.width = w;
        !           491:     rect.height = h;
        !           492:     (*pGC->PolyFillRect)(pDraw, pGC, 1, &rect);
        !           493: 
        !           494:     /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
        !           495:      * within the clipping region, the part outside is still all 0s */
        !           496:     gcv[0] = GXinvert;
        !           497:     DoChangeGC(pGCT, GCFunction, gcv, 0);
        !           498:     ValidateGC(pPixmap, pGCT);
        !           499:     (*pGCT->CopyArea)(pPixmap, pPixmap, pGCT, 0, 0, w, h, 0, 0);
        !           500: 
        !           501:     /* Swap foreground and background colors on the GC for the drawable.
        !           502:      * Now when we fill the drawable, we will fill in the "Background"
        !           503:      * values */
        !           504:     oldfg = pGC->fgPixel;
        !           505:     gcv[0] = (long) pGC->bgPixel;
        !           506:     gcv[1] = (long) oldfg;
        !           507:     gcv[2] = (long) pPixmap;
        !           508:     DoChangeGC(pGC, GCForeground | GCBackground | GCStipple, gcv, 1); 
        !           509:     ValidateGC(pDraw, pGC);
        !           510:     /* PolyFillRect might have bashed the rectangle */
        !           511:     rect.x = dstx;
        !           512:     rect.y = dsty;
        !           513:     rect.width = w;
        !           514:     rect.height = h;
        !           515:     (*pGC->PolyFillRect)(pDraw, pGC, 1, &rect);
        !           516: 
        !           517:     /* Now put things back */
        !           518:     if(pStipple)
        !           519:         pStipple->refcnt--;
        !           520:     gcv[0] = (long) oldfg;
        !           521:     gcv[1] = pGC->fgPixel;
        !           522:     gcv[2] = oldfill;
        !           523:     gcv[3] = (long) pStipple;
        !           524:     gcv[4] = oldOrg.x;
        !           525:     gcv[5] = oldOrg.y;
        !           526:     DoChangeGC(pGC, 
        !           527:         GCForeground | GCBackground | GCFillStyle | GCStipple | 
        !           528:        GCTileStipXOrigin | GCTileStipYOrigin, gcv, 1);
        !           529: 
        !           530:     ValidateGC(pDraw, pGC);
        !           531:     /* put what we hope is a smaller clip region back in the scratch gc */
        !           532:     (*pGCT->ChangeClip)(pGCT, CT_NONE, 0, 0);
        !           533:     FreeScratchGC(pGCT);
        !           534:     (*pDraw->pScreen->DestroyPixmap)(pPixmap);
        !           535: 
        !           536: }
        !           537: 
        !           538: /* MICOPYPLANE -- public entry for the CopyPlane request.
        !           539:  * strategy: 
        !           540:  * First build up a bitmap out of the bits requested 
        !           541:  * build a source clip
        !           542:  * Use the bitmap we've built up as a Stipple for the destination 
        !           543:  */
        !           544: void
        !           545: miCopyPlane(pSrcDrawable, pDstDrawable,
        !           546:            pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
        !           547:     DrawablePtr        pSrcDrawable;
        !           548:     DrawablePtr                pDstDrawable;
        !           549:     GCPtr              pGC;
        !           550:     int                srcx, srcy;
        !           551:     int                width, height;
        !           552:     int                dstx, dsty;
        !           553:     unsigned long      bitPlane;
        !           554: {
        !           555:     unsigned long      *ptile;
        !           556:     BoxRec             box;
        !           557:     RegionPtr          prgnSrc;
        !           558: 
        !           559: 
        !           560: 
        !           561:     /* clip the left and top edges of the source */
        !           562:     if (srcx < 0)
        !           563:     {
        !           564:         width += srcx;
        !           565:         srcx = 0;
        !           566:     }
        !           567:     if (srcy < 0)
        !           568:     {
        !           569:         height += srcy;
        !           570:         srcy = 0;
        !           571:     }
        !           572: 
        !           573:     /* incorporate the source clip */
        !           574: 
        !           575:     if (pSrcDrawable->type != DRAWABLE_PIXMAP)
        !           576:     {
        !           577:         box.x1 = ((WindowPtr)pSrcDrawable)->absCorner.x;
        !           578:         box.y1 = ((WindowPtr)pSrcDrawable)->absCorner.y;
        !           579:         box.x2 = box.x1 + width;
        !           580:         box.y2 = box.y1 + height;
        !           581:         prgnSrc = (*pGC->pScreen->RegionCreate)(&box, 1);
        !           582:        (*pGC->pScreen->Intersect)
        !           583:            (prgnSrc, prgnSrc, ((WindowPtr)pSrcDrawable)->clipList);
        !           584:        (*pGC->pScreen->TranslateRegion)(prgnSrc,
        !           585:                        -((WindowPtr)pSrcDrawable)->absCorner.x,
        !           586:                        -((WindowPtr)pSrcDrawable)->absCorner.y);
        !           587:     }
        !           588:     else
        !           589:     {
        !           590:         box.x1 = 0;
        !           591:         box.y1 = 0;
        !           592:         box.x2 = ((PixmapPtr)pSrcDrawable)->width;
        !           593:         box.y2 = ((PixmapPtr)pSrcDrawable)->height;
        !           594:         prgnSrc = (*pGC->pScreen->RegionCreate)(&box, 1);
        !           595:     }
        !           596: 
        !           597:     /* note that we convert the plane mask bitPlane into a plane number */
        !           598:     ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1, srcx, srcy,
        !           599:                       width, height, (unsigned char *) NULL);
        !           600:     miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
        !           601:                       width, height, dstx, dsty);
        !           602:     miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
        !           603:                      width, height, dstx, dsty);
        !           604:     Xfree(ptile);
        !           605:     (*pGC->pScreen->RegionDestroy)(prgnSrc);
        !           606: }
        !           607: 
        !           608: /* MIGETIMAGE -- public entry for the GetImage Request
        !           609:  * We're getting the image into a memory buffer. While we have to use GetSpans
        !           610:  * to read a line from the device (since we don't know what that looks like),
        !           611:  * we can just write into the destination buffer
        !           612:  *
        !           613:  * two different strategies are used, depending on whether we're getting the
        !           614:  * image in Z format or XY format
        !           615:  * Z format:
        !           616:  * Line at a time, GetSpans a line and bcopy it to the destination
        !           617:  * buffer, except that if the planemask is not all ones, we create a
        !           618:  * temporary pixmap and do a SetSpans into it (to get bits turned off)
        !           619:  * and then another GetSpans to get stuff back (because pixmaps are
        !           620:  * opaque, and we are passed in the memory to write into).  This is
        !           621:  * completely ugly and slow but works, but the interfaces just aren't
        !           622:  * designed for this case.  Life is hard.
        !           623:  * XY format:
        !           624:  * get the single plane specified in planemask
        !           625:  */
        !           626: void
        !           627: miGetImage(pDraw, sx, sy, w, h, format, planeMask, pdstLine)
        !           628:     DrawablePtr        pDraw;
        !           629:     int                        sx, sy, w, h;
        !           630:     unsigned int       format;
        !           631:     unsigned long      planeMask;
        !           632:     pointer             pdstLine;
        !           633: {
        !           634:     int                        depth, i, linelength, width, srcx, srcy;
        !           635:     DDXPointRec                pt;
        !           636:     unsigned long      *pbits;
        !           637:     long               gcv[2];
        !           638:     PixmapPtr          pPixmap = (PixmapPtr)NULL;
        !           639:     GCPtr              pGC;
        !           640:     unsigned long *     pDst = (unsigned long *)pdstLine;
        !           641: 
        !           642:     depth = pDraw->depth;
        !           643:     if(format == ZPixmap)
        !           644:     {
        !           645:        if ( (((1<<pDraw->depth)-1)&planeMask) != 
        !           646:             (1<<pDraw->depth)-1
        !           647:           )
        !           648:        {
        !           649:            pGC = GetScratchGC(depth, pDraw->pScreen);
        !           650:             pPixmap = (PixmapPtr)(*pDraw->pScreen->CreatePixmap)
        !           651:                               (pDraw->pScreen, w, h, depth);
        !           652:            gcv[0] = GXcopy;
        !           653:            gcv[1] = planeMask;
        !           654:            DoChangeGC(pGC, GCPlaneMask | GCFunction, gcv, 0);
        !           655:            ValidateGC(pPixmap, pGC);
        !           656:        }
        !           657: 
        !           658:         linelength = PixmapBytePad(w, depth);
        !           659:        srcx = sx;
        !           660:        srcy = sy;
        !           661:        if(pDraw->type == DRAWABLE_WINDOW)
        !           662:        {
        !           663:            srcx += ((WindowPtr)pDraw)->absCorner.x;
        !           664:            srcy += ((WindowPtr)pDraw)->absCorner.y;
        !           665:        }
        !           666:        for(i = 0; i < h; i++)
        !           667:        {
        !           668:            pt.x = srcx;
        !           669:            pt.y = srcy + i;
        !           670:            width = w;
        !           671:             pbits = (unsigned long *)
        !           672:                (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1);
        !           673:            if (pPixmap)
        !           674:            {
        !           675:               pt.x = 0;
        !           676:               pt.y = 0;
        !           677:               width = w;
        !           678:               (*pGC->SetSpans)(pPixmap, pGC, pbits, &pt, &width, 1, TRUE);
        !           679:               Xfree(pbits);
        !           680:               pbits = (unsigned long *)
        !           681:                  (*pDraw->pScreen->GetSpans)(pPixmap, w, &pt, &width, 1);
        !           682:            }
        !           683:            bcopy(pbits, (char *)pDst, linelength);
        !           684:            pDst += linelength / sizeof(long);
        !           685:            Xfree(pbits);
        !           686:        }
        !           687:        if (pPixmap)
        !           688:        {
        !           689:            (*pGC->pScreen->DestroyPixmap)(pPixmap);
        !           690:            FreeScratchGC(pGC);
        !           691:        }
        !           692:     }
        !           693:     else
        !           694:     {
        !           695:        miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h, pDst);
        !           696:     }
        !           697: }
        !           698: 
        !           699: 
        !           700: /* MIPUTIMAGE -- public entry for the PutImage request
        !           701:  * Here we benefit from knowing the format of the bits pointed to by pImage,
        !           702:  * even if we don't know how pDraw represents them.  
        !           703:  * Three different strategies are used depending on the format 
        !           704:  * XYBitmap Format:
        !           705:  *     we just use the Opaque Stipple helper function to cover the destination
        !           706:  *     Note that this covers all the planes of the drawable with the 
        !           707:  *     foreground color (masked with the GC planemask) where there are 1 bits
        !           708:  *     and the background color (masked with the GC planemask) where there are
        !           709:  *     0 bits
        !           710:  * XYPixmap format:
        !           711:  *     what we're called with is a series of XYBitmaps, but we only want 
        !           712:  *     each XYPixmap to update 1 plane, instead of updating all of them.
        !           713:  *     we set the foreground color to be all 1s and the background to all 0s
        !           714:  *     then for each plane, we set the plane mask to only effect that one
        !           715:  *     plane and recursive call ourself with the format set to XYBitmap
        !           716:  *     (This clever idea courtesy of RGD.)
        !           717:  * ZPixmap format:
        !           718:  *     This part is simple, just call SetSpans
        !           719:  */
        !           720: void
        !           721: miPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage)
        !           722:     DrawablePtr                pDraw;
        !           723:     GCPtr              pGC;
        !           724:     int                depth, x, y, w, h, leftPad;
        !           725:     unsigned int       format;
        !           726:     unsigned char      *pImage;
        !           727: {
        !           728:     DDXPointPtr                pptFirst, ppt;
        !           729:     int                        *pwidthFirst, *pwidth, i;
        !           730:     RegionPtr          prgnSrc;
        !           731:     BoxRec             box;
        !           732:     unsigned long      oldFg, oldBg, gcv[3];
        !           733:     unsigned long      oldPlanemask;
        !           734: 
        !           735:     switch(format)
        !           736:     {
        !           737:       case XYBitmap:
        !           738: 
        !           739:        box.x1 = 0;
        !           740:        box.y1 = 0;
        !           741:        box.x2 = w;
        !           742:        box.y2 = h;
        !           743:        prgnSrc = (*pGC->pScreen->RegionCreate)(&box, 1);
        !           744: 
        !           745:         miOpqStipDrawable(pDraw, pGC, prgnSrc, pImage, leftPad, 
        !           746:                           (w - leftPad), h, x, y);
        !           747:        (*pGC->pScreen->RegionDestroy)(prgnSrc);
        !           748:        break;
        !           749: 
        !           750:       case XYPixmap:
        !           751:        depth = pGC->depth;
        !           752:        oldPlanemask = pGC->planemask;
        !           753:        oldFg = pGC->fgPixel;
        !           754:        oldBg = pGC->bgPixel;
        !           755:        gcv[0] = ~0;
        !           756:        gcv[1] = 0;
        !           757:        DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0);
        !           758: 
        !           759:        for (i = 1 << (depth-1); i > 0; i >>= 1)
        !           760:        {
        !           761:            if (i & oldPlanemask)
        !           762:            {
        !           763:                gcv[0] = i;
        !           764:                DoChangeGC(pGC, GCPlaneMask, gcv, 0);
        !           765:                ValidateGC(pDraw, pGC);
        !           766:                (*pGC->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad,
        !           767:                                 XYBitmap, pImage);
        !           768:                pImage += h * PixmapBytePad(w, 1);
        !           769:            }
        !           770:        }
        !           771:        gcv[0] = oldPlanemask;
        !           772:        gcv[1] = oldFg;
        !           773:        gcv[2] = oldBg;
        !           774:        DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0);
        !           775:        break;
        !           776: 
        !           777:       case ZPixmap:
        !           778:        ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec));
        !           779:        pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int));
        !           780:        if(!ppt || !pwidth)
        !           781:         {
        !           782:            if (ppt)
        !           783:                DEALLOCATE_LOCAL(ppt);
        !           784:            else if (pwidth)
        !           785:                DEALLOCATE_LOCAL(pwidthFirst);
        !           786:            return;
        !           787:         }
        !           788:        if ((pDraw->type == DRAWABLE_WINDOW) &&
        !           789:            (pGC->miTranslate))
        !           790:        {
        !           791:            x += ((WindowPtr)(pDraw))->absCorner.x;
        !           792:            y += ((WindowPtr)(pDraw))->absCorner.y;
        !           793:        }
        !           794: 
        !           795:        for(i = 0; i < h; i++)
        !           796:        {
        !           797:            ppt->x = x;
        !           798:            ppt->y = y + i;
        !           799:            ppt++;
        !           800:            *pwidth++ = w;
        !           801:        }
        !           802: 
        !           803:        (*pGC->SetSpans)(pDraw, pGC, pImage, pptFirst, pwidthFirst, h, TRUE);
        !           804:        DEALLOCATE_LOCAL(pptFirst);
        !           805:        DEALLOCATE_LOCAL(pwidthFirst);
        !           806:        break;
        !           807:     }
        !           808: }
        !           809: 
        !           810: /* MICLEARDRAWABLE -- sets the entire drawable to the background color of
        !           811:  * the GC.  Useful when we have a scratch drawable and need to initialize 
        !           812:  * it. */
        !           813: miClearDrawable(pDraw, pGC)
        !           814:     DrawablePtr        pDraw;
        !           815:     GCPtr      pGC;
        !           816: {
        !           817:     int     fg = pGC->fgPixel;
        !           818:     int            bg = pGC->bgPixel;
        !           819:     xRectangle rect;
        !           820: 
        !           821:     rect.x = 0;
        !           822:     rect.y = 0;
        !           823:     if(pDraw->type == DRAWABLE_PIXMAP)
        !           824:     {
        !           825:        rect.width = ((PixmapPtr) pDraw)->width;
        !           826:        rect.height = ((PixmapPtr) pDraw)->height;
        !           827:     }
        !           828:     else
        !           829:     {
        !           830:        rect.width = ((WindowPtr) pDraw)->clientWinSize.width;
        !           831:        rect.height = ((WindowPtr) pDraw)->clientWinSize.height;
        !           832:     }
        !           833:     DoChangeGC(pGC, GCForeground, &bg, 0);
        !           834:     ValidateGC(pDraw, pGC);
        !           835:     (*pGC->PolyFillRect)(pDraw, pGC, 1, &rect);
        !           836:     DoChangeGC(pGC, GCForeground, &fg, 0);
        !           837:     ValidateGC(pDraw, pGC);
        !           838: }

unix.superglobalmegacorp.com

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