xref: /OK3568_Linux_fs/external/xserver/mi/mibitblt.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun                         All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun /* Author: Todd Newman  (aided and abetted by Mr. Drewry) */
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
49*4882a593Smuzhiyun #include <dix-config.h>
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #include <X11/X.h>
53*4882a593Smuzhiyun #include <X11/Xprotostr.h>
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #include "misc.h"
56*4882a593Smuzhiyun #include "gcstruct.h"
57*4882a593Smuzhiyun #include "pixmapstr.h"
58*4882a593Smuzhiyun #include "windowstr.h"
59*4882a593Smuzhiyun #include "scrnintstr.h"
60*4882a593Smuzhiyun #include "mi.h"
61*4882a593Smuzhiyun #include "regionstr.h"
62*4882a593Smuzhiyun #include <X11/Xmd.h>
63*4882a593Smuzhiyun #include "servermd.h"
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* MICOPYAREA -- public entry for the CopyArea request
66*4882a593Smuzhiyun  * For each rectangle in the source region
67*4882a593Smuzhiyun  *     get the pixels with GetSpans
68*4882a593Smuzhiyun  *     set them in the destination with SetSpans
69*4882a593Smuzhiyun  * We let SetSpans worry about clipping to the destination.
70*4882a593Smuzhiyun  */
71*4882a593Smuzhiyun _X_COLD RegionPtr
miCopyArea(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,GCPtr pGC,int xIn,int yIn,int widthSrc,int heightSrc,int xOut,int yOut)72*4882a593Smuzhiyun miCopyArea(DrawablePtr pSrcDrawable,
73*4882a593Smuzhiyun            DrawablePtr pDstDrawable,
74*4882a593Smuzhiyun            GCPtr pGC,
75*4882a593Smuzhiyun            int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     DDXPointPtr ppt, pptFirst;
78*4882a593Smuzhiyun     unsigned int *pwidthFirst, *pwidth, *pbits;
79*4882a593Smuzhiyun     BoxRec srcBox, *prect;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun     /* may be a new region, or just a copy */
82*4882a593Smuzhiyun     RegionPtr prgnSrcClip;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     /* non-0 if we've created a src clip */
85*4882a593Smuzhiyun     RegionPtr prgnExposed;
86*4882a593Smuzhiyun     int realSrcClip = 0;
87*4882a593Smuzhiyun     int srcx, srcy, dstx, dsty, i, j, y, width, height, xMin, xMax, yMin, yMax;
88*4882a593Smuzhiyun     unsigned int *ordering;
89*4882a593Smuzhiyun     int numRects;
90*4882a593Smuzhiyun     BoxPtr boxes;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun     srcx = xIn + pSrcDrawable->x;
93*4882a593Smuzhiyun     srcy = yIn + pSrcDrawable->y;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun     /* If the destination isn't realized, this is easy */
96*4882a593Smuzhiyun     if (pDstDrawable->type == DRAWABLE_WINDOW &&
97*4882a593Smuzhiyun         !((WindowPtr) pDstDrawable)->realized)
98*4882a593Smuzhiyun         return NULL;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun     /* clip the source */
101*4882a593Smuzhiyun     if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
102*4882a593Smuzhiyun         BoxRec box;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun         box.x1 = pSrcDrawable->x;
105*4882a593Smuzhiyun         box.y1 = pSrcDrawable->y;
106*4882a593Smuzhiyun         box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
107*4882a593Smuzhiyun         box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun         prgnSrcClip = RegionCreate(&box, 1);
110*4882a593Smuzhiyun         realSrcClip = 1;
111*4882a593Smuzhiyun     }
112*4882a593Smuzhiyun     else {
113*4882a593Smuzhiyun         if (pGC->subWindowMode == IncludeInferiors) {
114*4882a593Smuzhiyun             prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
115*4882a593Smuzhiyun             realSrcClip = 1;
116*4882a593Smuzhiyun         }
117*4882a593Smuzhiyun         else
118*4882a593Smuzhiyun             prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
119*4882a593Smuzhiyun     }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun     /* If the src drawable is a window, we need to translate the srcBox so
122*4882a593Smuzhiyun      * that we can compare it with the window's clip region later on. */
123*4882a593Smuzhiyun     srcBox.x1 = srcx;
124*4882a593Smuzhiyun     srcBox.y1 = srcy;
125*4882a593Smuzhiyun     srcBox.x2 = srcx + widthSrc;
126*4882a593Smuzhiyun     srcBox.y2 = srcy + heightSrc;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     dstx = xOut;
129*4882a593Smuzhiyun     dsty = yOut;
130*4882a593Smuzhiyun     if (pGC->miTranslate) {
131*4882a593Smuzhiyun         dstx += pDstDrawable->x;
132*4882a593Smuzhiyun         dsty += pDstDrawable->y;
133*4882a593Smuzhiyun     }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun     pptFirst = ppt = xallocarray(heightSrc, sizeof(DDXPointRec));
136*4882a593Smuzhiyun     pwidthFirst = pwidth = xallocarray(heightSrc, sizeof(unsigned int));
137*4882a593Smuzhiyun     numRects = RegionNumRects(prgnSrcClip);
138*4882a593Smuzhiyun     boxes = RegionRects(prgnSrcClip);
139*4882a593Smuzhiyun     ordering = xallocarray(numRects, sizeof(unsigned int));
140*4882a593Smuzhiyun     if (!pptFirst || !pwidthFirst || !ordering) {
141*4882a593Smuzhiyun         free(ordering);
142*4882a593Smuzhiyun         free(pwidthFirst);
143*4882a593Smuzhiyun         free(pptFirst);
144*4882a593Smuzhiyun         if (realSrcClip)
145*4882a593Smuzhiyun             RegionDestroy(prgnSrcClip);
146*4882a593Smuzhiyun         return NULL;
147*4882a593Smuzhiyun     }
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     /* If not the same drawable then order of move doesn't matter.
150*4882a593Smuzhiyun        Following assumes that boxes are sorted from top
151*4882a593Smuzhiyun        to bottom and left to right.
152*4882a593Smuzhiyun      */
153*4882a593Smuzhiyun     if ((pSrcDrawable != pDstDrawable) &&
154*4882a593Smuzhiyun         ((pGC->subWindowMode != IncludeInferiors) ||
155*4882a593Smuzhiyun          (pSrcDrawable->type == DRAWABLE_PIXMAP) ||
156*4882a593Smuzhiyun          (pDstDrawable->type == DRAWABLE_PIXMAP)))
157*4882a593Smuzhiyun         for (i = 0; i < numRects; i++)
158*4882a593Smuzhiyun             ordering[i] = i;
159*4882a593Smuzhiyun     else {                      /* within same drawable, must sequence moves carefully! */
160*4882a593Smuzhiyun         if (dsty <= srcBox.y1) {        /* Scroll up or stationary vertical.
161*4882a593Smuzhiyun                                            Vertical order OK */
162*4882a593Smuzhiyun             if (dstx <= srcBox.x1)      /* Scroll left or stationary horizontal.
163*4882a593Smuzhiyun                                            Horizontal order OK as well */
164*4882a593Smuzhiyun                 for (i = 0; i < numRects; i++)
165*4882a593Smuzhiyun                     ordering[i] = i;
166*4882a593Smuzhiyun             else {              /* scroll right. must reverse horizontal banding of rects. */
167*4882a593Smuzhiyun                 for (i = 0, j = 1, xMax = 0; i < numRects; j = i + 1, xMax = i) {
168*4882a593Smuzhiyun                     /* find extent of current horizontal band */
169*4882a593Smuzhiyun                     y = boxes[i].y1;    /* band has this y coordinate */
170*4882a593Smuzhiyun                     while ((j < numRects) && (boxes[j].y1 == y))
171*4882a593Smuzhiyun                         j++;
172*4882a593Smuzhiyun                     /* reverse the horizontal band in the output ordering */
173*4882a593Smuzhiyun                     for (j--; j >= xMax; j--, i++)
174*4882a593Smuzhiyun                         ordering[i] = j;
175*4882a593Smuzhiyun                 }
176*4882a593Smuzhiyun             }
177*4882a593Smuzhiyun         }
178*4882a593Smuzhiyun         else {                  /* Scroll down. Must reverse vertical banding. */
179*4882a593Smuzhiyun             if (dstx < srcBox.x1) {     /* Scroll left. Horizontal order OK. */
180*4882a593Smuzhiyun                 for (i = numRects - 1, j = i - 1, yMin = i, yMax = 0;
181*4882a593Smuzhiyun                      i >= 0; j = i - 1, yMin = i) {
182*4882a593Smuzhiyun                     /* find extent of current horizontal band */
183*4882a593Smuzhiyun                     y = boxes[i].y1;    /* band has this y coordinate */
184*4882a593Smuzhiyun                     while ((j >= 0) && (boxes[j].y1 == y))
185*4882a593Smuzhiyun                         j--;
186*4882a593Smuzhiyun                     /* reverse the horizontal band in the output ordering */
187*4882a593Smuzhiyun                     for (j++; j <= yMin; j++, i--, yMax++)
188*4882a593Smuzhiyun                         ordering[yMax] = j;
189*4882a593Smuzhiyun                 }
190*4882a593Smuzhiyun             }
191*4882a593Smuzhiyun             else                /* Scroll right or horizontal stationary.
192*4882a593Smuzhiyun                                    Reverse horizontal order as well (if stationary, horizontal
193*4882a593Smuzhiyun                                    order can be swapped without penalty and this is faster
194*4882a593Smuzhiyun                                    to compute). */
195*4882a593Smuzhiyun                 for (i = 0, j = numRects - 1; i < numRects; i++, j--)
196*4882a593Smuzhiyun                     ordering[i] = j;
197*4882a593Smuzhiyun         }
198*4882a593Smuzhiyun     }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     for (i = 0; i < numRects; i++) {
201*4882a593Smuzhiyun         prect = &boxes[ordering[i]];
202*4882a593Smuzhiyun         xMin = max(prect->x1, srcBox.x1);
203*4882a593Smuzhiyun         xMax = min(prect->x2, srcBox.x2);
204*4882a593Smuzhiyun         yMin = max(prect->y1, srcBox.y1);
205*4882a593Smuzhiyun         yMax = min(prect->y2, srcBox.y2);
206*4882a593Smuzhiyun         /* is there anything visible here? */
207*4882a593Smuzhiyun         if (xMax <= xMin || yMax <= yMin)
208*4882a593Smuzhiyun             continue;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun         ppt = pptFirst;
211*4882a593Smuzhiyun         pwidth = pwidthFirst;
212*4882a593Smuzhiyun         y = yMin;
213*4882a593Smuzhiyun         height = yMax - yMin;
214*4882a593Smuzhiyun         width = xMax - xMin;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun         for (j = 0; j < height; j++) {
217*4882a593Smuzhiyun             /* We must untranslate before calling GetSpans */
218*4882a593Smuzhiyun             ppt->x = xMin;
219*4882a593Smuzhiyun             ppt++->y = y++;
220*4882a593Smuzhiyun             *pwidth++ = width;
221*4882a593Smuzhiyun         }
222*4882a593Smuzhiyun         pbits = xallocarray(height, PixmapBytePad(width, pSrcDrawable->depth));
223*4882a593Smuzhiyun         if (pbits) {
224*4882a593Smuzhiyun             (*pSrcDrawable->pScreen->GetSpans) (pSrcDrawable, width, pptFirst,
225*4882a593Smuzhiyun                                                 (int *) pwidthFirst, height,
226*4882a593Smuzhiyun                                                 (char *) pbits);
227*4882a593Smuzhiyun             ppt = pptFirst;
228*4882a593Smuzhiyun             pwidth = pwidthFirst;
229*4882a593Smuzhiyun             xMin -= (srcx - dstx);
230*4882a593Smuzhiyun             y = yMin - (srcy - dsty);
231*4882a593Smuzhiyun             for (j = 0; j < height; j++) {
232*4882a593Smuzhiyun                 ppt->x = xMin;
233*4882a593Smuzhiyun                 ppt++->y = y++;
234*4882a593Smuzhiyun                 *pwidth++ = width;
235*4882a593Smuzhiyun             }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun             (*pGC->ops->SetSpans) (pDstDrawable, pGC, (char *) pbits, pptFirst,
238*4882a593Smuzhiyun                                    (int *) pwidthFirst, height, TRUE);
239*4882a593Smuzhiyun             free(pbits);
240*4882a593Smuzhiyun         }
241*4882a593Smuzhiyun     }
242*4882a593Smuzhiyun     prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
243*4882a593Smuzhiyun                                     widthSrc, heightSrc, xOut, yOut);
244*4882a593Smuzhiyun     if (realSrcClip)
245*4882a593Smuzhiyun         RegionDestroy(prgnSrcClip);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     free(ordering);
248*4882a593Smuzhiyun     free(pwidthFirst);
249*4882a593Smuzhiyun     free(pptFirst);
250*4882a593Smuzhiyun     return prgnExposed;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun /* MIGETPLANE -- gets a bitmap representing one plane of pDraw
254*4882a593Smuzhiyun  * A helper used for CopyPlane and XY format GetImage
255*4882a593Smuzhiyun  * No clever strategy here, we grab a scanline at a time, pull out the
256*4882a593Smuzhiyun  * bits and then stuff them in a 1 bit deep map.
257*4882a593Smuzhiyun  */
258*4882a593Smuzhiyun /*
259*4882a593Smuzhiyun  * This should be replaced with something more general.  mi shouldn't have to
260*4882a593Smuzhiyun  * care about such things as scanline padding et alia.
261*4882a593Smuzhiyun  */
262*4882a593Smuzhiyun _X_COLD static MiBits *
miGetPlane(DrawablePtr pDraw,int planeNum,int sx,int sy,int w,int h,MiBits * result)263*4882a593Smuzhiyun miGetPlane(DrawablePtr pDraw, int planeNum,     /* number of the bitPlane */
264*4882a593Smuzhiyun            int sx, int sy, int w, int h, MiBits * result)
265*4882a593Smuzhiyun {
266*4882a593Smuzhiyun     int i, j, k, width, bitsPerPixel, widthInBytes;
267*4882a593Smuzhiyun     DDXPointRec pt = { 0, 0 };
268*4882a593Smuzhiyun     MiBits pixel;
269*4882a593Smuzhiyun     MiBits bit;
270*4882a593Smuzhiyun     unsigned char *pCharsOut = NULL;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun #if BITMAP_SCANLINE_UNIT == 8
273*4882a593Smuzhiyun #define OUT_TYPE unsigned char
274*4882a593Smuzhiyun #endif
275*4882a593Smuzhiyun #if BITMAP_SCANLINE_UNIT == 16
276*4882a593Smuzhiyun #define OUT_TYPE CARD16
277*4882a593Smuzhiyun #endif
278*4882a593Smuzhiyun #if BITMAP_SCANLINE_UNIT == 32
279*4882a593Smuzhiyun #define OUT_TYPE CARD32
280*4882a593Smuzhiyun #endif
281*4882a593Smuzhiyun #if BITMAP_SCANLINE_UNIT == 64
282*4882a593Smuzhiyun #define OUT_TYPE CARD64
283*4882a593Smuzhiyun #endif
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun     OUT_TYPE *pOut;
286*4882a593Smuzhiyun     int delta = 0;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun     sx += pDraw->x;
289*4882a593Smuzhiyun     sy += pDraw->y;
290*4882a593Smuzhiyun     widthInBytes = BitmapBytePad(w);
291*4882a593Smuzhiyun     if (!result)
292*4882a593Smuzhiyun         result = calloc(h, widthInBytes);
293*4882a593Smuzhiyun     if (!result)
294*4882a593Smuzhiyun         return NULL;
295*4882a593Smuzhiyun     bitsPerPixel = pDraw->bitsPerPixel;
296*4882a593Smuzhiyun     pOut = (OUT_TYPE *) result;
297*4882a593Smuzhiyun     if (bitsPerPixel == 1) {
298*4882a593Smuzhiyun         pCharsOut = (unsigned char *) result;
299*4882a593Smuzhiyun         width = w;
300*4882a593Smuzhiyun     }
301*4882a593Smuzhiyun     else {
302*4882a593Smuzhiyun         delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
303*4882a593Smuzhiyun             (w / BITMAP_SCANLINE_UNIT);
304*4882a593Smuzhiyun         width = 1;
305*4882a593Smuzhiyun #if IMAGE_BYTE_ORDER == MSBFirst
306*4882a593Smuzhiyun         planeNum += (32 - bitsPerPixel);
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun     }
309*4882a593Smuzhiyun     pt.y = sy;
310*4882a593Smuzhiyun     for (i = h; --i >= 0; pt.y++) {
311*4882a593Smuzhiyun         pt.x = sx;
312*4882a593Smuzhiyun         if (bitsPerPixel == 1) {
313*4882a593Smuzhiyun             (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
314*4882a593Smuzhiyun                                          (char *) pCharsOut);
315*4882a593Smuzhiyun             pCharsOut += widthInBytes;
316*4882a593Smuzhiyun         }
317*4882a593Smuzhiyun         else {
318*4882a593Smuzhiyun             k = 0;
319*4882a593Smuzhiyun             for (j = w; --j >= 0; pt.x++) {
320*4882a593Smuzhiyun                 /* Fetch the next pixel */
321*4882a593Smuzhiyun                 (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
322*4882a593Smuzhiyun                                              (char *) &pixel);
323*4882a593Smuzhiyun                 /*
324*4882a593Smuzhiyun                  * Now get the bit and insert into a bitmap in XY format.
325*4882a593Smuzhiyun                  */
326*4882a593Smuzhiyun                 bit = (pixel >> planeNum) & 1;
327*4882a593Smuzhiyun #if 0
328*4882a593Smuzhiyun                 /* XXX assuming bit order == byte order */
329*4882a593Smuzhiyun #if BITMAP_BIT_ORDER == LSBFirst
330*4882a593Smuzhiyun                 bit <<= k;
331*4882a593Smuzhiyun #else
332*4882a593Smuzhiyun                 bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
333*4882a593Smuzhiyun #endif
334*4882a593Smuzhiyun #else
335*4882a593Smuzhiyun                 /* XXX assuming byte order == LSBFirst */
336*4882a593Smuzhiyun                 if (screenInfo.bitmapBitOrder == LSBFirst)
337*4882a593Smuzhiyun                     bit <<= k;
338*4882a593Smuzhiyun                 else
339*4882a593Smuzhiyun                     bit <<= ((screenInfo.bitmapScanlineUnit - 1) -
340*4882a593Smuzhiyun                              (k % screenInfo.bitmapScanlineUnit)) +
341*4882a593Smuzhiyun                         ((k / screenInfo.bitmapScanlineUnit) *
342*4882a593Smuzhiyun                          screenInfo.bitmapScanlineUnit);
343*4882a593Smuzhiyun #endif
344*4882a593Smuzhiyun                 *pOut |= (OUT_TYPE) bit;
345*4882a593Smuzhiyun                 k++;
346*4882a593Smuzhiyun                 if (k == BITMAP_SCANLINE_UNIT) {
347*4882a593Smuzhiyun                     pOut++;
348*4882a593Smuzhiyun                     k = 0;
349*4882a593Smuzhiyun                 }
350*4882a593Smuzhiyun             }
351*4882a593Smuzhiyun             pOut += delta;
352*4882a593Smuzhiyun         }
353*4882a593Smuzhiyun     }
354*4882a593Smuzhiyun     return result;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun /* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
359*4882a593Smuzhiyun  * Drawing through the clip mask we SetSpans() the bits into a
360*4882a593Smuzhiyun  * bitmap and stipple those bits onto the destination drawable by doing a
361*4882a593Smuzhiyun  * PolyFillRect over the whole drawable,
362*4882a593Smuzhiyun  * then we invert the bitmap by copying it onto itself with an alu of
363*4882a593Smuzhiyun  * GXinvert, invert the foreground/background colors of the gc, and draw
364*4882a593Smuzhiyun  * the background bits.
365*4882a593Smuzhiyun  * Note how the clipped out bits of the bitmap are always the background
366*4882a593Smuzhiyun  * color so that the stipple never causes FillRect to draw them.
367*4882a593Smuzhiyun  */
368*4882a593Smuzhiyun _X_COLD static void
miOpqStipDrawable(DrawablePtr pDraw,GCPtr pGC,RegionPtr prgnSrc,MiBits * pbits,int srcx,int w,int h,int dstx,int dsty)369*4882a593Smuzhiyun miOpqStipDrawable(DrawablePtr pDraw, GCPtr pGC, RegionPtr prgnSrc,
370*4882a593Smuzhiyun                   MiBits * pbits, int srcx, int w, int h, int dstx, int dsty)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun     int oldfill, i;
373*4882a593Smuzhiyun     unsigned long oldfg;
374*4882a593Smuzhiyun     int *pwidth, *pwidthFirst;
375*4882a593Smuzhiyun     ChangeGCVal gcv[6];
376*4882a593Smuzhiyun     PixmapPtr pStipple, pPixmap;
377*4882a593Smuzhiyun     DDXPointRec oldOrg;
378*4882a593Smuzhiyun     GCPtr pGCT;
379*4882a593Smuzhiyun     DDXPointPtr ppt, pptFirst;
380*4882a593Smuzhiyun     xRectangle rect;
381*4882a593Smuzhiyun     RegionPtr prgnSrcClip;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun     pPixmap = (*pDraw->pScreen->CreatePixmap)
384*4882a593Smuzhiyun         (pDraw->pScreen, w + srcx, h, 1, CREATE_PIXMAP_USAGE_SCRATCH);
385*4882a593Smuzhiyun     if (!pPixmap)
386*4882a593Smuzhiyun         return;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun     /* Put the image into a 1 bit deep pixmap */
389*4882a593Smuzhiyun     pGCT = GetScratchGC(1, pDraw->pScreen);
390*4882a593Smuzhiyun     if (!pGCT) {
391*4882a593Smuzhiyun         (*pDraw->pScreen->DestroyPixmap) (pPixmap);
392*4882a593Smuzhiyun         return;
393*4882a593Smuzhiyun     }
394*4882a593Smuzhiyun     /* First set the whole pixmap to 0 */
395*4882a593Smuzhiyun     gcv[0].val = 0;
396*4882a593Smuzhiyun     ChangeGC(NullClient, pGCT, GCBackground, gcv);
397*4882a593Smuzhiyun     ValidateGC((DrawablePtr) pPixmap, pGCT);
398*4882a593Smuzhiyun     miClearDrawable((DrawablePtr) pPixmap, pGCT);
399*4882a593Smuzhiyun     ppt = pptFirst = xallocarray(h, sizeof(DDXPointRec));
400*4882a593Smuzhiyun     pwidth = pwidthFirst = xallocarray(h, sizeof(int));
401*4882a593Smuzhiyun     if (!pptFirst || !pwidthFirst) {
402*4882a593Smuzhiyun         free(pwidthFirst);
403*4882a593Smuzhiyun         free(pptFirst);
404*4882a593Smuzhiyun         FreeScratchGC(pGCT);
405*4882a593Smuzhiyun         return;
406*4882a593Smuzhiyun     }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun     /* we need a temporary region because ChangeClip must be assumed
409*4882a593Smuzhiyun        to destroy what it's sent.  note that this means we don't
410*4882a593Smuzhiyun        have to free prgnSrcClip ourselves.
411*4882a593Smuzhiyun      */
412*4882a593Smuzhiyun     prgnSrcClip = RegionCreate(NULL, 0);
413*4882a593Smuzhiyun     RegionCopy(prgnSrcClip, prgnSrc);
414*4882a593Smuzhiyun     RegionTranslate(prgnSrcClip, srcx, 0);
415*4882a593Smuzhiyun     (*pGCT->funcs->ChangeClip) (pGCT, CT_REGION, prgnSrcClip, 0);
416*4882a593Smuzhiyun     ValidateGC((DrawablePtr) pPixmap, pGCT);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun     /* Since we know pDraw is always a pixmap, we never need to think
419*4882a593Smuzhiyun      * about translation here */
420*4882a593Smuzhiyun     for (i = 0; i < h; i++) {
421*4882a593Smuzhiyun         ppt->x = 0;
422*4882a593Smuzhiyun         ppt++->y = i;
423*4882a593Smuzhiyun         *pwidth++ = w + srcx;
424*4882a593Smuzhiyun     }
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun     (*pGCT->ops->SetSpans) ((DrawablePtr) pPixmap, pGCT, (char *) pbits,
427*4882a593Smuzhiyun                             pptFirst, pwidthFirst, h, TRUE);
428*4882a593Smuzhiyun     free(pwidthFirst);
429*4882a593Smuzhiyun     free(pptFirst);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun     /* Save current values from the client GC */
432*4882a593Smuzhiyun     oldfill = pGC->fillStyle;
433*4882a593Smuzhiyun     pStipple = pGC->stipple;
434*4882a593Smuzhiyun     if (pStipple)
435*4882a593Smuzhiyun         pStipple->refcnt++;
436*4882a593Smuzhiyun     oldOrg = pGC->patOrg;
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun     /* Set a new stipple in the drawable */
439*4882a593Smuzhiyun     gcv[0].val = FillStippled;
440*4882a593Smuzhiyun     gcv[1].ptr = pPixmap;
441*4882a593Smuzhiyun     gcv[2].val = dstx - srcx;
442*4882a593Smuzhiyun     gcv[3].val = dsty;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun     ChangeGC(NullClient, pGC,
445*4882a593Smuzhiyun              GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
446*4882a593Smuzhiyun              gcv);
447*4882a593Smuzhiyun     ValidateGC(pDraw, pGC);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun     /* Fill the drawable with the stipple.  This will draw the
450*4882a593Smuzhiyun      * foreground color whereever 1 bits are set, leaving everything
451*4882a593Smuzhiyun      * with 0 bits untouched.  Note that the part outside the clip
452*4882a593Smuzhiyun      * region is all 0s.  */
453*4882a593Smuzhiyun     rect.x = dstx;
454*4882a593Smuzhiyun     rect.y = dsty;
455*4882a593Smuzhiyun     rect.width = w;
456*4882a593Smuzhiyun     rect.height = h;
457*4882a593Smuzhiyun     (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun     /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
460*4882a593Smuzhiyun      * within the clipping region, the part outside is still all 0s */
461*4882a593Smuzhiyun     gcv[0].val = GXinvert;
462*4882a593Smuzhiyun     ChangeGC(NullClient, pGCT, GCFunction, gcv);
463*4882a593Smuzhiyun     ValidateGC((DrawablePtr) pPixmap, pGCT);
464*4882a593Smuzhiyun     (*pGCT->ops->CopyArea) ((DrawablePtr) pPixmap, (DrawablePtr) pPixmap,
465*4882a593Smuzhiyun                             pGCT, 0, 0, w + srcx, h, 0, 0);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun     /* Swap foreground and background colors on the GC for the drawable.
468*4882a593Smuzhiyun      * Now when we fill the drawable, we will fill in the "Background"
469*4882a593Smuzhiyun      * values */
470*4882a593Smuzhiyun     oldfg = pGC->fgPixel;
471*4882a593Smuzhiyun     gcv[0].val = pGC->bgPixel;
472*4882a593Smuzhiyun     gcv[1].val = oldfg;
473*4882a593Smuzhiyun     gcv[2].ptr = pPixmap;
474*4882a593Smuzhiyun     ChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, gcv);
475*4882a593Smuzhiyun     ValidateGC(pDraw, pGC);
476*4882a593Smuzhiyun     /* PolyFillRect might have bashed the rectangle */
477*4882a593Smuzhiyun     rect.x = dstx;
478*4882a593Smuzhiyun     rect.y = dsty;
479*4882a593Smuzhiyun     rect.width = w;
480*4882a593Smuzhiyun     rect.height = h;
481*4882a593Smuzhiyun     (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun     /* Now put things back */
484*4882a593Smuzhiyun     if (pStipple)
485*4882a593Smuzhiyun         pStipple->refcnt--;
486*4882a593Smuzhiyun     gcv[0].val = oldfg;
487*4882a593Smuzhiyun     gcv[1].val = pGC->fgPixel;
488*4882a593Smuzhiyun     gcv[2].val = oldfill;
489*4882a593Smuzhiyun     gcv[3].ptr = pStipple;
490*4882a593Smuzhiyun     gcv[4].val = oldOrg.x;
491*4882a593Smuzhiyun     gcv[5].val = oldOrg.y;
492*4882a593Smuzhiyun     ChangeGC(NullClient, pGC,
493*4882a593Smuzhiyun              GCForeground | GCBackground | GCFillStyle | GCStipple |
494*4882a593Smuzhiyun              GCTileStipXOrigin | GCTileStipYOrigin, gcv);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun     ValidateGC(pDraw, pGC);
497*4882a593Smuzhiyun     /* put what we hope is a smaller clip region back in the scratch gc */
498*4882a593Smuzhiyun     (*pGCT->funcs->ChangeClip) (pGCT, CT_NONE, NULL, 0);
499*4882a593Smuzhiyun     FreeScratchGC(pGCT);
500*4882a593Smuzhiyun     (*pDraw->pScreen->DestroyPixmap) (pPixmap);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun /* MICOPYPLANE -- public entry for the CopyPlane request.
505*4882a593Smuzhiyun  * strategy:
506*4882a593Smuzhiyun  * First build up a bitmap out of the bits requested
507*4882a593Smuzhiyun  * build a source clip
508*4882a593Smuzhiyun  * Use the bitmap we've built up as a Stipple for the destination
509*4882a593Smuzhiyun  */
510*4882a593Smuzhiyun _X_COLD RegionPtr
miCopyPlane(DrawablePtr pSrcDrawable,DrawablePtr pDstDrawable,GCPtr pGC,int srcx,int srcy,int width,int height,int dstx,int dsty,unsigned long bitPlane)511*4882a593Smuzhiyun miCopyPlane(DrawablePtr pSrcDrawable,
512*4882a593Smuzhiyun             DrawablePtr pDstDrawable,
513*4882a593Smuzhiyun             GCPtr pGC,
514*4882a593Smuzhiyun             int srcx,
515*4882a593Smuzhiyun             int srcy,
516*4882a593Smuzhiyun             int width, int height, int dstx, int dsty, unsigned long bitPlane)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun     MiBits *ptile;
519*4882a593Smuzhiyun     BoxRec box;
520*4882a593Smuzhiyun     RegionPtr prgnSrc, prgnExposed;
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun     /* incorporate the source clip */
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     box.x1 = srcx + pSrcDrawable->x;
525*4882a593Smuzhiyun     box.y1 = srcy + pSrcDrawable->y;
526*4882a593Smuzhiyun     box.x2 = box.x1 + width;
527*4882a593Smuzhiyun     box.y2 = box.y1 + height;
528*4882a593Smuzhiyun     /* clip to visible drawable */
529*4882a593Smuzhiyun     if (box.x1 < pSrcDrawable->x)
530*4882a593Smuzhiyun         box.x1 = pSrcDrawable->x;
531*4882a593Smuzhiyun     if (box.y1 < pSrcDrawable->y)
532*4882a593Smuzhiyun         box.y1 = pSrcDrawable->y;
533*4882a593Smuzhiyun     if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
534*4882a593Smuzhiyun         box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
535*4882a593Smuzhiyun     if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
536*4882a593Smuzhiyun         box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
537*4882a593Smuzhiyun     if (box.x1 > box.x2)
538*4882a593Smuzhiyun         box.x2 = box.x1;
539*4882a593Smuzhiyun     if (box.y1 > box.y2)
540*4882a593Smuzhiyun         box.y2 = box.y1;
541*4882a593Smuzhiyun     prgnSrc = RegionCreate(&box, 1);
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun     if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
544*4882a593Smuzhiyun         /* clip to visible drawable */
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun         if (pGC->subWindowMode == IncludeInferiors) {
547*4882a593Smuzhiyun             RegionPtr clipList = NotClippedByChildren((WindowPtr) pSrcDrawable);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun             RegionIntersect(prgnSrc, prgnSrc, clipList);
550*4882a593Smuzhiyun             RegionDestroy(clipList);
551*4882a593Smuzhiyun         }
552*4882a593Smuzhiyun         else
553*4882a593Smuzhiyun             RegionIntersect(prgnSrc, prgnSrc,
554*4882a593Smuzhiyun                             &((WindowPtr) pSrcDrawable)->clipList);
555*4882a593Smuzhiyun     }
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun     box = *RegionExtents(prgnSrc);
558*4882a593Smuzhiyun     RegionTranslate(prgnSrc, -box.x1, -box.y1);
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun     if ((box.x2 > box.x1) && (box.y2 > box.y1)) {
561*4882a593Smuzhiyun         /* minimize the size of the data extracted */
562*4882a593Smuzhiyun         /* note that we convert the plane mask bitPlane into a plane number */
563*4882a593Smuzhiyun         box.x1 -= pSrcDrawable->x;
564*4882a593Smuzhiyun         box.x2 -= pSrcDrawable->x;
565*4882a593Smuzhiyun         box.y1 -= pSrcDrawable->y;
566*4882a593Smuzhiyun         box.y2 -= pSrcDrawable->y;
567*4882a593Smuzhiyun         ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
568*4882a593Smuzhiyun                            box.x1, box.y1,
569*4882a593Smuzhiyun                            box.x2 - box.x1, box.y2 - box.y1, (MiBits *) NULL);
570*4882a593Smuzhiyun         if (ptile) {
571*4882a593Smuzhiyun             miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
572*4882a593Smuzhiyun                               box.x2 - box.x1, box.y2 - box.y1,
573*4882a593Smuzhiyun                               dstx + box.x1 - srcx, dsty + box.y1 - srcy);
574*4882a593Smuzhiyun             free(ptile);
575*4882a593Smuzhiyun         }
576*4882a593Smuzhiyun     }
577*4882a593Smuzhiyun     prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
578*4882a593Smuzhiyun                                     width, height, dstx, dsty);
579*4882a593Smuzhiyun     RegionDestroy(prgnSrc);
580*4882a593Smuzhiyun     return prgnExposed;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun /* MIGETIMAGE -- public entry for the GetImage Request
584*4882a593Smuzhiyun  * We're getting the image into a memory buffer. While we have to use GetSpans
585*4882a593Smuzhiyun  * to read a line from the device (since we don't know what that looks like),
586*4882a593Smuzhiyun  * we can just write into the destination buffer
587*4882a593Smuzhiyun  *
588*4882a593Smuzhiyun  * two different strategies are used, depending on whether we're getting the
589*4882a593Smuzhiyun  * image in Z format or XY format
590*4882a593Smuzhiyun  * Z format:
591*4882a593Smuzhiyun  * Line at a time, GetSpans a line into the destination buffer, then if the
592*4882a593Smuzhiyun  * planemask is not all ones, we do a SetSpans into a temporary buffer (to get
593*4882a593Smuzhiyun  * bits turned off) and then another GetSpans to get stuff back (because
594*4882a593Smuzhiyun  * pixmaps are opaque, and we are passed in the memory to write into).  This is
595*4882a593Smuzhiyun  * pretty ugly and slow but works.  Life is hard.
596*4882a593Smuzhiyun  * XY format:
597*4882a593Smuzhiyun  * get the single plane specified in planemask
598*4882a593Smuzhiyun  */
599*4882a593Smuzhiyun _X_COLD void
miGetImage(DrawablePtr pDraw,int sx,int sy,int w,int h,unsigned int format,unsigned long planeMask,char * pDst)600*4882a593Smuzhiyun miGetImage(DrawablePtr pDraw, int sx, int sy, int w, int h,
601*4882a593Smuzhiyun            unsigned int format, unsigned long planeMask, char *pDst)
602*4882a593Smuzhiyun {
603*4882a593Smuzhiyun     unsigned char depth;
604*4882a593Smuzhiyun     int i, linelength, width, srcx, srcy;
605*4882a593Smuzhiyun     DDXPointRec pt = { 0, 0 };
606*4882a593Smuzhiyun     PixmapPtr pPixmap = NULL;
607*4882a593Smuzhiyun     GCPtr pGC = NULL;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun     depth = pDraw->depth;
610*4882a593Smuzhiyun     if (format == ZPixmap) {
611*4882a593Smuzhiyun         if ((((1LL << depth) - 1) & planeMask) != (1LL << depth) - 1) {
612*4882a593Smuzhiyun             ChangeGCVal gcv;
613*4882a593Smuzhiyun             xPoint xpt;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun             pGC = GetScratchGC(depth, pDraw->pScreen);
616*4882a593Smuzhiyun             if (!pGC)
617*4882a593Smuzhiyun                 return;
618*4882a593Smuzhiyun             pPixmap = (*pDraw->pScreen->CreatePixmap)
619*4882a593Smuzhiyun                 (pDraw->pScreen, w, 1, depth, CREATE_PIXMAP_USAGE_SCRATCH);
620*4882a593Smuzhiyun             if (!pPixmap) {
621*4882a593Smuzhiyun                 FreeScratchGC(pGC);
622*4882a593Smuzhiyun                 return;
623*4882a593Smuzhiyun             }
624*4882a593Smuzhiyun             /*
625*4882a593Smuzhiyun              * Clear the pixmap before doing anything else
626*4882a593Smuzhiyun              */
627*4882a593Smuzhiyun             ValidateGC((DrawablePtr) pPixmap, pGC);
628*4882a593Smuzhiyun             xpt.x = xpt.y = 0;
629*4882a593Smuzhiyun             width = w;
630*4882a593Smuzhiyun             (*pGC->ops->FillSpans) ((DrawablePtr) pPixmap, pGC, 1, &xpt, &width,
631*4882a593Smuzhiyun                                     TRUE);
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun             /* alu is already GXCopy */
634*4882a593Smuzhiyun             gcv.val = (XID) planeMask;
635*4882a593Smuzhiyun             ChangeGC(NullClient, pGC, GCPlaneMask, &gcv);
636*4882a593Smuzhiyun             ValidateGC((DrawablePtr) pPixmap, pGC);
637*4882a593Smuzhiyun         }
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun         linelength = PixmapBytePad(w, depth);
640*4882a593Smuzhiyun         srcx = sx + pDraw->x;
641*4882a593Smuzhiyun         srcy = sy + pDraw->y;
642*4882a593Smuzhiyun         for (i = 0; i < h; i++) {
643*4882a593Smuzhiyun             pt.x = srcx;
644*4882a593Smuzhiyun             pt.y = srcy + i;
645*4882a593Smuzhiyun             width = w;
646*4882a593Smuzhiyun             (*pDraw->pScreen->GetSpans) (pDraw, w, &pt, &width, 1, pDst);
647*4882a593Smuzhiyun             if (pPixmap) {
648*4882a593Smuzhiyun                 pt.x = 0;
649*4882a593Smuzhiyun                 pt.y = 0;
650*4882a593Smuzhiyun                 width = w;
651*4882a593Smuzhiyun                 (*pGC->ops->SetSpans) ((DrawablePtr) pPixmap, pGC, pDst,
652*4882a593Smuzhiyun                                        &pt, &width, 1, TRUE);
653*4882a593Smuzhiyun                 (*pDraw->pScreen->GetSpans) ((DrawablePtr) pPixmap, w, &pt,
654*4882a593Smuzhiyun                                              &width, 1, pDst);
655*4882a593Smuzhiyun             }
656*4882a593Smuzhiyun             pDst += linelength;
657*4882a593Smuzhiyun         }
658*4882a593Smuzhiyun         if (pPixmap) {
659*4882a593Smuzhiyun             (*pGC->pScreen->DestroyPixmap) (pPixmap);
660*4882a593Smuzhiyun             FreeScratchGC(pGC);
661*4882a593Smuzhiyun         }
662*4882a593Smuzhiyun     }
663*4882a593Smuzhiyun     else {
664*4882a593Smuzhiyun         (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
665*4882a593Smuzhiyun                           (MiBits *) pDst);
666*4882a593Smuzhiyun     }
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun /* MIPUTIMAGE -- public entry for the PutImage request
670*4882a593Smuzhiyun  * Here we benefit from knowing the format of the bits pointed to by pImage,
671*4882a593Smuzhiyun  * even if we don't know how pDraw represents them.
672*4882a593Smuzhiyun  * Three different strategies are used depending on the format
673*4882a593Smuzhiyun  * XYBitmap Format:
674*4882a593Smuzhiyun  * 	we just use the Opaque Stipple helper function to cover the destination
675*4882a593Smuzhiyun  * 	Note that this covers all the planes of the drawable with the
676*4882a593Smuzhiyun  *	foreground color (masked with the GC planemask) where there are 1 bits
677*4882a593Smuzhiyun  *	and the background color (masked with the GC planemask) where there are
678*4882a593Smuzhiyun  *	0 bits
679*4882a593Smuzhiyun  * XYPixmap format:
680*4882a593Smuzhiyun  *	what we're called with is a series of XYBitmaps, but we only want
681*4882a593Smuzhiyun  *	each XYPixmap to update 1 plane, instead of updating all of them.
682*4882a593Smuzhiyun  * 	we set the foreground color to be all 1s and the background to all 0s
683*4882a593Smuzhiyun  *	then for each plane, we set the plane mask to only effect that one
684*4882a593Smuzhiyun  *	plane and recursive call ourself with the format set to XYBitmap
685*4882a593Smuzhiyun  *	(This clever idea courtesy of RGD.)
686*4882a593Smuzhiyun  * ZPixmap format:
687*4882a593Smuzhiyun  *	This part is simple, just call SetSpans
688*4882a593Smuzhiyun  */
689*4882a593Smuzhiyun _X_COLD void
miPutImage(DrawablePtr pDraw,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * pImage)690*4882a593Smuzhiyun miPutImage(DrawablePtr pDraw, GCPtr pGC, int depth,
691*4882a593Smuzhiyun            int x, int y, int w, int h, int leftPad, int format, char *pImage)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun     DDXPointPtr pptFirst, ppt;
694*4882a593Smuzhiyun     int *pwidthFirst, *pwidth;
695*4882a593Smuzhiyun     RegionPtr prgnSrc;
696*4882a593Smuzhiyun     BoxRec box;
697*4882a593Smuzhiyun     unsigned long oldFg, oldBg;
698*4882a593Smuzhiyun     ChangeGCVal gcv[3];
699*4882a593Smuzhiyun     unsigned long oldPlanemask;
700*4882a593Smuzhiyun     unsigned long i;
701*4882a593Smuzhiyun     long bytesPer;
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun     if (!w || !h)
704*4882a593Smuzhiyun         return;
705*4882a593Smuzhiyun     switch (format) {
706*4882a593Smuzhiyun     case XYBitmap:
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun         box.x1 = 0;
709*4882a593Smuzhiyun         box.y1 = 0;
710*4882a593Smuzhiyun         box.x2 = w;
711*4882a593Smuzhiyun         box.y2 = h;
712*4882a593Smuzhiyun         prgnSrc = RegionCreate(&box, 1);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun         miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBits *) pImage,
715*4882a593Smuzhiyun                           leftPad, w, h, x, y);
716*4882a593Smuzhiyun         RegionDestroy(prgnSrc);
717*4882a593Smuzhiyun         break;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun     case XYPixmap:
720*4882a593Smuzhiyun         depth = pGC->depth;
721*4882a593Smuzhiyun         oldPlanemask = pGC->planemask;
722*4882a593Smuzhiyun         oldFg = pGC->fgPixel;
723*4882a593Smuzhiyun         oldBg = pGC->bgPixel;
724*4882a593Smuzhiyun         gcv[0].val = (XID) ~0;
725*4882a593Smuzhiyun         gcv[1].val = (XID) 0;
726*4882a593Smuzhiyun         ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcv);
727*4882a593Smuzhiyun         bytesPer = (long) h *BitmapBytePad(w + leftPad);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun         for (i = (unsigned long) 1 << (depth - 1); i != 0; i >>= 1, pImage += bytesPer) {
730*4882a593Smuzhiyun             if (i & oldPlanemask) {
731*4882a593Smuzhiyun                 gcv[0].val = (XID) i;
732*4882a593Smuzhiyun                 ChangeGC(NullClient, pGC, GCPlaneMask, gcv);
733*4882a593Smuzhiyun                 ValidateGC(pDraw, pGC);
734*4882a593Smuzhiyun                 (*pGC->ops->PutImage) (pDraw, pGC, 1, x, y, w, h, leftPad,
735*4882a593Smuzhiyun                                        XYBitmap, (char *) pImage);
736*4882a593Smuzhiyun             }
737*4882a593Smuzhiyun         }
738*4882a593Smuzhiyun         gcv[0].val = (XID) oldPlanemask;
739*4882a593Smuzhiyun         gcv[1].val = (XID) oldFg;
740*4882a593Smuzhiyun         gcv[2].val = (XID) oldBg;
741*4882a593Smuzhiyun         ChangeGC(NullClient, pGC, GCPlaneMask | GCForeground | GCBackground,
742*4882a593Smuzhiyun                  gcv);
743*4882a593Smuzhiyun         ValidateGC(pDraw, pGC);
744*4882a593Smuzhiyun         break;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun     case ZPixmap:
747*4882a593Smuzhiyun         ppt = pptFirst = xallocarray(h, sizeof(DDXPointRec));
748*4882a593Smuzhiyun         pwidth = pwidthFirst = xallocarray(h, sizeof(int));
749*4882a593Smuzhiyun         if (!pptFirst || !pwidthFirst) {
750*4882a593Smuzhiyun             free(pwidthFirst);
751*4882a593Smuzhiyun             free(pptFirst);
752*4882a593Smuzhiyun             return;
753*4882a593Smuzhiyun         }
754*4882a593Smuzhiyun         if (pGC->miTranslate) {
755*4882a593Smuzhiyun             x += pDraw->x;
756*4882a593Smuzhiyun             y += pDraw->y;
757*4882a593Smuzhiyun         }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun         for (i = 0; i < h; i++) {
760*4882a593Smuzhiyun             ppt->x = x;
761*4882a593Smuzhiyun             ppt->y = y + i;
762*4882a593Smuzhiyun             ppt++;
763*4882a593Smuzhiyun             *pwidth++ = w;
764*4882a593Smuzhiyun         }
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun         (*pGC->ops->SetSpans) (pDraw, pGC, (char *) pImage, pptFirst,
767*4882a593Smuzhiyun                                pwidthFirst, h, TRUE);
768*4882a593Smuzhiyun         free(pwidthFirst);
769*4882a593Smuzhiyun         free(pptFirst);
770*4882a593Smuzhiyun         break;
771*4882a593Smuzhiyun     }
772*4882a593Smuzhiyun }
773