Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mibitblt.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: 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.