|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.