1 /***********************************************************
3 Copyright (c) 1987 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 ******************************************************************/
48 /* $XConsortium: mibitblt.c /main/55 1996/08/01 19:25:20 dpw $ */
49 /* $XFree86: xc/programs/Xserver/mi/mibitblt.c,v 3.1 1996/12/23 07:09:43 dawes Exp $ */
50 /* Author: Todd Newman (aided and abetted by Mr. Drewry) */
53 #include "Xprotostr.h"
57 #include "pixmapstr.h"
58 #include "windowstr.h"
59 #include "scrnintstr.h"
61 #include "regionstr.h"
65 /* MICOPYAREA -- public entry for the CopyArea request
66 * For each rectangle in the source region
67 * get the pixels with GetSpans
68 * set them in the destination with SetSpans
69 * We let SetSpans worry about clipping to the destination.
72 miCopyArea(pSrcDrawable, pDstDrawable,
73 pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut)
74 register DrawablePtr pSrcDrawable;
75 register DrawablePtr pDstDrawable;
78 int widthSrc, heightSrc;
81 DDXPointPtr ppt, pptFirst;
82 unsigned int *pwidthFirst, *pwidth, *pbits;
83 BoxRec srcBox, *prect;
84 /* may be a new region, or just a copy */
85 RegionPtr prgnSrcClip;
86 /* non-0 if we've created a src clip */
87 RegionPtr prgnExposed;
89 int srcx, srcy, dstx, dsty, i, j, y, width, height,
90 xMin, xMax, yMin, yMax;
91 unsigned int *ordering;
95 srcx = xIn + pSrcDrawable->x;
96 srcy = yIn + pSrcDrawable->y;
98 /* If the destination isn't realized, this is easy */
99 if (pDstDrawable->type == DRAWABLE_WINDOW &&
100 !((WindowPtr)pDstDrawable)->realized)
101 return (RegionPtr)NULL;
103 /* clip the source */
104 if (pSrcDrawable->type == DRAWABLE_PIXMAP)
108 box.x1 = pSrcDrawable->x;
109 box.y1 = pSrcDrawable->y;
110 box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
111 box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
113 prgnSrcClip = REGION_CREATE(pGC->pScreen, &box, 1);
118 if (pGC->subWindowMode == IncludeInferiors) {
119 prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable);
122 prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
125 /* If the src drawable is a window, we need to translate the srcBox so
126 * that we can compare it with the window's clip region later on. */
129 srcBox.x2 = srcx + widthSrc;
130 srcBox.y2 = srcy + heightSrc;
134 if (pGC->miTranslate)
136 dstx += pDstDrawable->x;
137 dsty += pDstDrawable->y;
140 pptFirst = ppt = (DDXPointPtr)
141 ALLOCATE_LOCAL(heightSrc * sizeof(DDXPointRec));
142 pwidthFirst = pwidth = (unsigned int *)
143 ALLOCATE_LOCAL(heightSrc * sizeof(unsigned int));
144 numRects = REGION_NUM_RECTS(prgnSrcClip);
145 boxes = REGION_RECTS(prgnSrcClip);
146 ordering = (unsigned int *)
147 ALLOCATE_LOCAL(numRects * sizeof(unsigned int));
148 if(!pptFirst || !pwidthFirst || !ordering)
151 DEALLOCATE_LOCAL(ordering);
153 DEALLOCATE_LOCAL(pwidthFirst);
155 DEALLOCATE_LOCAL(pptFirst);
156 return (RegionPtr)NULL;
159 /* If not the same drawable then order of move doesn't matter.
160 Following assumes that boxes are sorted from top
161 to bottom and left to right.
163 if ((pSrcDrawable != pDstDrawable) &&
164 ((pGC->subWindowMode != IncludeInferiors) ||
165 (pSrcDrawable->type == DRAWABLE_PIXMAP) ||
166 (pDstDrawable->type == DRAWABLE_PIXMAP)))
167 for (i=0; i < numRects; i++)
169 else { /* within same drawable, must sequence moves carefully! */
170 if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
172 if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
173 Horizontal order OK as well */
174 for (i=0; i < numRects; i++)
176 else { /* scroll right. must reverse horizontal banding of rects. */
177 for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) {
178 /* find extent of current horizontal band */
179 y=boxes[i].y1; /* band has this y coordinate */
180 while ((j < numRects) && (boxes[j].y1 == y))
182 /* reverse the horizontal band in the output ordering */
183 for (j-- ; j >= xMax; j--, i++)
188 else { /* Scroll down. Must reverse vertical banding. */
189 if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
190 for (i=numRects-1, j=i-1, yMin=i, yMax=0;
193 /* find extent of current horizontal band */
194 y=boxes[i].y1; /* band has this y coordinate */
195 while ((j >= 0) && (boxes[j].y1 == y))
197 /* reverse the horizontal band in the output ordering */
198 for (j++ ; j <= yMin; j++, i--, yMax++)
202 else /* Scroll right or horizontal stationary.
203 Reverse horizontal order as well (if stationary, horizontal
204 order can be swapped without penalty and this is faster
206 for (i=0, j=numRects-1; i < numRects; i++, j--)
211 for(i = 0; i < numRects; i++)
213 prect = &boxes[ordering[i]];
214 xMin = max(prect->x1, srcBox.x1);
215 xMax = min(prect->x2, srcBox.x2);
216 yMin = max(prect->y1, srcBox.y1);
217 yMax = min(prect->y2, srcBox.y2);
218 /* is there anything visible here? */
219 if(xMax <= xMin || yMax <= yMin)
223 pwidth = pwidthFirst;
225 height = yMax - yMin;
228 for(j = 0; j < height; j++)
230 /* We must untranslate before calling GetSpans */
235 pbits = (unsigned int *)xalloc(height * PixmapBytePad(width,
236 pSrcDrawable->depth));
239 (*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst,
240 (int *)pwidthFirst, height, (char *)pbits);
242 pwidth = pwidthFirst;
243 xMin -= (srcx - dstx);
244 y = yMin - (srcy - dsty);
245 for(j = 0; j < height; j++)
252 (*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst,
253 (int *)pwidthFirst, height, TRUE);
257 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
258 widthSrc, heightSrc, xOut, yOut, (unsigned long)0);
260 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
262 DEALLOCATE_LOCAL(ordering);
263 DEALLOCATE_LOCAL(pwidthFirst);
264 DEALLOCATE_LOCAL(pptFirst);
268 /* MIGETPLANE -- gets a bitmap representing one plane of pDraw
269 * A helper used for CopyPlane and XY format GetImage
270 * No clever strategy here, we grab a scanline at a time, pull out the
271 * bits and then stuff them in a 1 bit deep map.
275 miGetPlane(pDraw, planeNum, sx, sy, w, h, result)
277 int planeNum; /* number of the bitPlane */
279 unsigned long *result;
281 int i, j, k, width, bitsPerPixel, widthInBytes;
285 unsigned char *pCharsOut;
287 #if BITMAP_SCANLINE_UNIT == 8
288 #define OUT_TYPE unsigned char
290 #if BITMAP_SCANLINE_UNIT == 16
291 #define OUT_TYPE CARD16
293 #if BITMAP_SCANLINE_UNIT == 32
294 #define OUT_TYPE CARD32
296 #if BITMAP_SCANLINE_UNIT == 64
297 #define OUT_TYPE CARD64
305 widthInBytes = BitmapBytePad(w);
307 result = (unsigned long *)xalloc(h * widthInBytes);
309 return (unsigned long *)NULL;
310 bitsPerPixel = pDraw->bitsPerPixel;
311 bzero((char *)result, h * widthInBytes);
312 pOut = (OUT_TYPE *) result;
313 if(bitsPerPixel == 1)
315 pCharsOut = (unsigned char *) result;
320 delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
321 (w / BITMAP_SCANLINE_UNIT);
323 #if IMAGE_BYTE_ORDER == MSBFirst
324 planeNum += (32 - bitsPerPixel);
328 for (i = h; --i >= 0; pt.y++)
331 if(bitsPerPixel == 1)
333 (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
335 pCharsOut += widthInBytes;
340 for(j = w; --j >= 0; pt.x++)
342 /* Fetch the next pixel */
343 (*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
346 * Now get the bit and insert into a bitmap in XY format.
348 bit = (pixel >> planeNum) & 1;
349 /* XXX assuming bit order == byte order */
350 #if BITMAP_BIT_ORDER == LSBFirst
353 bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
355 *pOut |= (OUT_TYPE) bit;
357 if (k == BITMAP_SCANLINE_UNIT)
370 /* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
371 * Drawing through the clip mask we SetSpans() the bits into a
372 * bitmap and stipple those bits onto the destination drawable by doing a
373 * PolyFillRect over the whole drawable,
374 * then we invert the bitmap by copying it onto itself with an alu of
375 * GXinvert, invert the foreground/background colors of the gc, and draw
376 * the background bits.
377 * Note how the clipped out bits of the bitmap are always the background
378 * color so that the stipple never causes FillRect to draw them.
381 miOpqStipDrawable(pDraw, pGC, prgnSrc, pbits, srcx, w, h, dstx, dsty)
385 unsigned long *pbits;
386 int srcx, w, h, dstx, dsty;
390 int *pwidth, *pwidthFirst;
392 PixmapPtr pStipple, pPixmap;
395 DDXPointPtr ppt, pptFirst;
397 RegionPtr prgnSrcClip;
399 pPixmap = (*pDraw->pScreen->CreatePixmap)
400 (pDraw->pScreen, w + srcx, h, 1);
404 /* Put the image into a 1 bit deep pixmap */
405 pGCT = GetScratchGC(1, pDraw->pScreen);
408 (*pDraw->pScreen->DestroyPixmap)(pPixmap);
411 /* First set the whole pixmap to 0 */
413 dixChangeGC(NullClient, pGCT, GCBackground, NULL, gcv);
414 ValidateGC((DrawablePtr)pPixmap, pGCT);
415 miClearDrawable((DrawablePtr)pPixmap, pGCT);
416 ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec));
417 pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int));
418 if(!pptFirst || !pwidthFirst)
420 if (pwidthFirst) DEALLOCATE_LOCAL(pwidthFirst);
421 if (pptFirst) DEALLOCATE_LOCAL(pptFirst);
426 /* we need a temporary region because ChangeClip must be assumed
427 to destroy what it's sent. note that this means we don't
428 have to free prgnSrcClip ourselves.
430 prgnSrcClip = REGION_CREATE(pGCT->pScreen, NULL, 0);
431 REGION_COPY(pGCT->pScreen, prgnSrcClip, prgnSrc);
432 REGION_TRANSLATE(pGCT->pScreen, prgnSrcClip, srcx, 0);
433 (*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0);
434 ValidateGC((DrawablePtr)pPixmap, pGCT);
436 /* Since we know pDraw is always a pixmap, we never need to think
437 * about translation here */
438 for(i = 0; i < h; i++)
442 *pwidth++ = w + srcx;
445 (*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits,
446 pptFirst, pwidthFirst, h, TRUE);
447 DEALLOCATE_LOCAL(pwidthFirst);
448 DEALLOCATE_LOCAL(pptFirst);
451 /* Save current values from the client GC */
452 oldfill = pGC->fillStyle;
453 pStipple = pGC->stipple;
456 oldOrg = pGC->patOrg;
458 /* Set a new stipple in the drawable */
459 gcv[0].val = FillStippled;
460 gcv[1].ptr = pPixmap;
461 gcv[2].val = dstx - srcx;
464 dixChangeGC(NullClient, pGC,
465 GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
467 ValidateGC(pDraw, pGC);
469 /* Fill the drawable with the stipple. This will draw the
470 * foreground color whereever 1 bits are set, leaving everything
471 * with 0 bits untouched. Note that the part outside the clip
472 * region is all 0s. */
477 (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
479 /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
480 * within the clipping region, the part outside is still all 0s */
481 gcv[0].val = GXinvert;
482 dixChangeGC(NullClient, pGCT, GCFunction, NULL, gcv);
483 ValidateGC((DrawablePtr)pPixmap, pGCT);
484 (*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap,
485 pGCT, 0, 0, w + srcx, h, 0, 0);
487 /* Swap foreground and background colors on the GC for the drawable.
488 * Now when we fill the drawable, we will fill in the "Background"
490 oldfg = pGC->fgPixel;
491 gcv[0].val = pGC->bgPixel;
493 gcv[2].ptr = pPixmap;
494 dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple,
496 ValidateGC(pDraw, pGC);
497 /* PolyFillRect might have bashed the rectangle */
502 (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
504 /* Now put things back */
508 gcv[1].val = pGC->fgPixel;
509 gcv[2].val = oldfill;
510 gcv[3].ptr = pStipple;
511 gcv[4].val = oldOrg.x;
512 gcv[5].val = oldOrg.y;
513 dixChangeGC(NullClient, pGC,
514 GCForeground | GCBackground | GCFillStyle | GCStipple |
515 GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv);
517 ValidateGC(pDraw, pGC);
518 /* put what we hope is a smaller clip region back in the scratch gc */
519 (*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0);
521 (*pDraw->pScreen->DestroyPixmap)(pPixmap);
525 /* MICOPYPLANE -- public entry for the CopyPlane request.
527 * First build up a bitmap out of the bits requested
528 * build a source clip
529 * Use the bitmap we've built up as a Stipple for the destination
532 miCopyPlane(pSrcDrawable, pDstDrawable,
533 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
534 DrawablePtr pSrcDrawable;
535 DrawablePtr pDstDrawable;
540 unsigned long bitPlane;
542 unsigned long *ptile;
544 RegionPtr prgnSrc, prgnExposed;
546 /* incorporate the source clip */
548 box.x1 = srcx + pSrcDrawable->x;
549 box.y1 = srcy + pSrcDrawable->y;
550 box.x2 = box.x1 + width;
551 box.y2 = box.y1 + height;
552 /* clip to visible drawable */
553 if (box.x1 < pSrcDrawable->x)
554 box.x1 = pSrcDrawable->x;
555 if (box.y1 < pSrcDrawable->y)
556 box.y1 = pSrcDrawable->y;
557 if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
558 box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
559 if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
560 box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
565 prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1);
567 if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
568 /* clip to visible drawable */
570 if (pGC->subWindowMode == IncludeInferiors)
572 RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable);
573 REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc, clipList);
574 REGION_DESTROY(pGC->pScreen, clipList);
576 REGION_INTERSECT(pGC->pScreen, prgnSrc, prgnSrc,
577 &((WindowPtr)pSrcDrawable)->clipList);
580 box = *REGION_EXTENTS(pGC->pScreen, prgnSrc);
581 REGION_TRANSLATE(pGC->pScreen, prgnSrc, -box.x1, -box.y1);
583 if ((box.x2 > box.x1) && (box.y2 > box.y1))
585 /* minimize the size of the data extracted */
586 /* note that we convert the plane mask bitPlane into a plane number */
587 box.x1 -= pSrcDrawable->x;
588 box.x2 -= pSrcDrawable->x;
589 box.y1 -= pSrcDrawable->y;
590 box.y2 -= pSrcDrawable->y;
591 ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
593 box.x2 - box.x1, box.y2 - box.y1,
594 (unsigned long *) NULL);
597 miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
598 box.x2 - box.x1, box.y2 - box.y1,
599 dstx + box.x1 - srcx, dsty + box.y1 - srcy);
603 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
604 width, height, dstx, dsty, bitPlane);
605 REGION_DESTROY(pGC->pScreen, prgnSrc);
609 /* MIGETIMAGE -- public entry for the GetImage Request
610 * We're getting the image into a memory buffer. While we have to use GetSpans
611 * to read a line from the device (since we don't know what that looks like),
612 * we can just write into the destination buffer
614 * two different strategies are used, depending on whether we're getting the
615 * image in Z format or XY format
617 * Line at a time, GetSpans a line into the destination buffer, then if the
618 * planemask is not all ones, we do a SetSpans into a temporary buffer (to get
619 * bits turned off) and then another GetSpans to get stuff back (because
620 * pixmaps are opaque, and we are passed in the memory to write into). This is
621 * pretty ugly and slow but works. Life is hard.
623 * get the single plane specified in planemask
626 miGetImage(pDraw, sx, sy, w, h, format, planeMask, pDst)
630 unsigned long planeMask;
634 int i, linelength, width, srcx, srcy;
637 PixmapPtr pPixmap = (PixmapPtr)NULL;
640 depth = pDraw->depth;
641 if(format == ZPixmap)
643 if ( (((1<<depth)-1)&planeMask) != (1<<depth)-1 )
647 pGC = GetScratchGC(depth, pDraw->pScreen);
650 pPixmap = (*pDraw->pScreen->CreatePixmap)
651 (pDraw->pScreen, w, 1, depth);
658 * Clear the pixmap before doing anything else
660 ValidateGC((DrawablePtr)pPixmap, pGC);
662 (*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &pt, &width,
665 /* alu is already GXCopy */
666 gcv[0] = (XID)planeMask;
667 DoChangeGC(pGC, GCPlaneMask, gcv, 0);
668 ValidateGC((DrawablePtr)pPixmap, pGC);
671 linelength = PixmapBytePad(w, depth);
672 srcx = sx + pDraw->x;
673 srcy = sy + pDraw->y;
674 for(i = 0; i < h; i++)
679 (*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst);
685 (*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst,
686 &pt, &width, 1, TRUE);
687 (*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt,
694 (*pGC->pScreen->DestroyPixmap)(pPixmap);
700 (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
701 (unsigned long *)pDst);
706 /* MIPUTIMAGE -- public entry for the PutImage request
707 * Here we benefit from knowing the format of the bits pointed to by pImage,
708 * even if we don't know how pDraw represents them.
709 * Three different strategies are used depending on the format
711 * we just use the Opaque Stipple helper function to cover the destination
712 * Note that this covers all the planes of the drawable with the
713 * foreground color (masked with the GC planemask) where there are 1 bits
714 * and the background color (masked with the GC planemask) where there are
717 * what we're called with is a series of XYBitmaps, but we only want
718 * each XYPixmap to update 1 plane, instead of updating all of them.
719 * we set the foreground color to be all 1s and the background to all 0s
720 * then for each plane, we set the plane mask to only effect that one
721 * plane and recursive call ourself with the format set to XYBitmap
722 * (This clever idea courtesy of RGD.)
724 * This part is simple, just call SetSpans
727 miPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage)
730 int depth, x, y, w, h, leftPad;
734 DDXPointPtr pptFirst, ppt;
735 int *pwidthFirst, *pwidth;
738 unsigned long oldFg, oldBg;
740 unsigned long oldPlanemask;
754 prgnSrc = REGION_CREATE(pGC->pScreen, &box, 1);
756 miOpqStipDrawable(pDraw, pGC, prgnSrc, (unsigned long *) pImage,
757 leftPad, w, h, x, y);
758 REGION_DESTROY(pGC->pScreen, prgnSrc);
763 oldPlanemask = pGC->planemask;
764 oldFg = pGC->fgPixel;
765 oldBg = pGC->bgPixel;
768 DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0);
769 bytesPer = (long)h * BitmapBytePad(w + leftPad);
771 for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer)
773 if (i & oldPlanemask)
776 DoChangeGC(pGC, GCPlaneMask, gcv, 0);
777 ValidateGC(pDraw, pGC);
778 (*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad,
779 XYBitmap, (char *)pImage);
782 gcv[0] = (XID)oldPlanemask;
785 DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0);
789 ppt = pptFirst = (DDXPointPtr)ALLOCATE_LOCAL(h * sizeof(DDXPointRec));
790 pwidth = pwidthFirst = (int *)ALLOCATE_LOCAL(h * sizeof(int));
791 if(!pptFirst || !pwidthFirst)
794 DEALLOCATE_LOCAL(pwidthFirst);
796 DEALLOCATE_LOCAL(pptFirst);
799 if (pGC->miTranslate)
805 for(i = 0; i < h; i++)
813 (*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst,
814 pwidthFirst, h, TRUE);
815 DEALLOCATE_LOCAL(pwidthFirst);
816 DEALLOCATE_LOCAL(pptFirst);