|
|
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.