Imported Upstream version 1.15.1
[deb_xorg-server.git] / mi / micopy.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright © 1998 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include "mi.h"
28#include "scrnintstr.h"
29#include "gcstruct.h"
30#include "pixmap.h"
31#include "pixmapstr.h"
32#include "windowstr.h"
33
34void
35miCopyRegion(DrawablePtr pSrcDrawable,
36 DrawablePtr pDstDrawable,
37 GCPtr pGC,
38 RegionPtr pDstRegion,
39 int dx, int dy, miCopyProc copyProc, Pixel bitPlane, void *closure)
40{
41 int careful;
42 Bool reverse;
43 Bool upsidedown;
44 BoxPtr pbox;
45 int nbox;
46 BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp;
47
48 pbox = RegionRects(pDstRegion);
49 nbox = RegionNumRects(pDstRegion);
50
51 /* XXX we have to err on the side of safety when both are windows,
52 * because we don't know if IncludeInferiors is being used.
53 */
54 careful = ((pSrcDrawable == pDstDrawable) ||
55 ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
56 (pDstDrawable->type == DRAWABLE_WINDOW)));
57
58 pboxNew1 = NULL;
59 pboxNew2 = NULL;
60 if (careful && dy < 0) {
61 upsidedown = TRUE;
62
63 if (nbox > 1) {
64 /* keep ordering in each band, reverse order of bands */
65 pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
66 if (!pboxNew1)
67 return;
68 pboxBase = pboxNext = pbox + nbox - 1;
69 while (pboxBase >= pbox) {
70 while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
71 pboxNext--;
72 pboxTmp = pboxNext + 1;
73 while (pboxTmp <= pboxBase) {
74 *pboxNew1++ = *pboxTmp++;
75 }
76 pboxBase = pboxNext;
77 }
78 pboxNew1 -= nbox;
79 pbox = pboxNew1;
80 }
81 }
82 else {
83 /* walk source top to bottom */
84 upsidedown = FALSE;
85 }
86
87 if (careful && dx < 0) {
88 /* walk source right to left */
89 if (dy <= 0)
90 reverse = TRUE;
91 else
92 reverse = FALSE;
93
94 if (nbox > 1) {
95 /* reverse order of rects in each band */
96 pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox);
97 if (!pboxNew2) {
98 free(pboxNew1);
99 return;
100 }
101 pboxBase = pboxNext = pbox;
102 while (pboxBase < pbox + nbox) {
103 while ((pboxNext < pbox + nbox) &&
104 (pboxNext->y1 == pboxBase->y1))
105 pboxNext++;
106 pboxTmp = pboxNext;
107 while (pboxTmp != pboxBase) {
108 *pboxNew2++ = *--pboxTmp;
109 }
110 pboxBase = pboxNext;
111 }
112 pboxNew2 -= nbox;
113 pbox = pboxNew2;
114 }
115 }
116 else {
117 /* walk source left to right */
118 reverse = FALSE;
119 }
120
121 (*copyProc) (pSrcDrawable,
122 pDstDrawable,
123 pGC,
124 pbox, nbox, dx, dy, reverse, upsidedown, bitPlane, closure);
125
126 free(pboxNew1);
127 free(pboxNew2);
128}
129
130RegionPtr
131miDoCopy(DrawablePtr pSrcDrawable,
132 DrawablePtr pDstDrawable,
133 GCPtr pGC,
134 int xIn,
135 int yIn,
136 int widthSrc,
137 int heightSrc,
138 int xOut, int yOut, miCopyProc copyProc, Pixel bitPlane, void *closure)
139{
140 RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */
141 Bool freeSrcClip = FALSE;
142 RegionPtr prgnExposed = NULL;
143 RegionRec rgnDst;
144 int dx;
145 int dy;
146 int numRects;
147 int box_x1;
148 int box_y1;
149 int box_x2;
150 int box_y2;
151 Bool fastSrc = FALSE; /* for fast clipping with pixmap source */
152 Bool fastDst = FALSE; /* for fast clipping with one rect dest */
153 Bool fastExpose = FALSE; /* for fast exposures with pixmap source */
154
155 /* Short cut for unmapped windows */
156
157 if (pDstDrawable->type == DRAWABLE_WINDOW &&
158 !((WindowPtr) pDstDrawable)->realized) {
159 return NULL;
160 }
161
162 if (pSrcDrawable->pScreen->SourceValidate) {
163 (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn,
164 widthSrc, heightSrc,
165 pGC->subWindowMode);
166 }
167
168 /* Compute source clip region */
169 if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
170 if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE))
171 prgnSrcClip = miGetCompositeClip(pGC);
172 else
173 fastSrc = TRUE;
174 }
175 else {
176 if (pGC->subWindowMode == IncludeInferiors) {
177 /*
178 * XFree86 DDX empties the border clip when the
179 * VT is inactive, make sure the region isn't empty
180 */
181 if (!((WindowPtr) pSrcDrawable)->parent &&
182 RegionNotEmpty(&((WindowPtr) pSrcDrawable)->borderClip)) {
183 /*
184 * special case bitblt from root window in
185 * IncludeInferiors mode; just like from a pixmap
186 */
187 fastSrc = TRUE;
188 }
189 else if ((pSrcDrawable == pDstDrawable) &&
190 (pGC->clientClipType == CT_NONE)) {
191 prgnSrcClip = miGetCompositeClip(pGC);
192 }
193 else {
194 prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
195 freeSrcClip = TRUE;
196 }
197 }
198 else {
199 prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
200 }
201 }
202
203 xIn += pSrcDrawable->x;
204 yIn += pSrcDrawable->y;
205
206 xOut += pDstDrawable->x;
207 yOut += pDstDrawable->y;
208
209 box_x1 = xIn;
210 box_y1 = yIn;
211 box_x2 = xIn + widthSrc;
212 box_y2 = yIn + heightSrc;
213
214 dx = xIn - xOut;
215 dy = yIn - yOut;
216
217 /* Don't create a source region if we are doing a fast clip */
218 if (fastSrc) {
219 RegionPtr cclip;
220
221 fastExpose = TRUE;
222 /*
223 * clip the source; if regions extend beyond the source size,
224 * make sure exposure events get sent
225 */
226 if (box_x1 < pSrcDrawable->x) {
227 box_x1 = pSrcDrawable->x;
228 fastExpose = FALSE;
229 }
230 if (box_y1 < pSrcDrawable->y) {
231 box_y1 = pSrcDrawable->y;
232 fastExpose = FALSE;
233 }
234 if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) {
235 box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
236 fastExpose = FALSE;
237 }
238 if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) {
239 box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
240 fastExpose = FALSE;
241 }
242
243 /* Translate and clip the dst to the destination composite clip */
244 box_x1 -= dx;
245 box_x2 -= dx;
246 box_y1 -= dy;
247 box_y2 -= dy;
248
249 /* If the destination composite clip is one rectangle we can
250 do the clip directly. Otherwise we have to create a full
251 blown region and call intersect */
252
253 cclip = miGetCompositeClip(pGC);
254 if (RegionNumRects(cclip) == 1) {
255 BoxPtr pBox = RegionRects(cclip);
256
257 if (box_x1 < pBox->x1)
258 box_x1 = pBox->x1;
259 if (box_x2 > pBox->x2)
260 box_x2 = pBox->x2;
261 if (box_y1 < pBox->y1)
262 box_y1 = pBox->y1;
263 if (box_y2 > pBox->y2)
264 box_y2 = pBox->y2;
265 fastDst = TRUE;
266 }
267 }
268
269 /* Check to see if the region is empty */
270 if (box_x1 >= box_x2 || box_y1 >= box_y2) {
271 RegionNull(&rgnDst);
272 }
273 else {
274 BoxRec box;
275
276 box.x1 = box_x1;
277 box.y1 = box_y1;
278 box.x2 = box_x2;
279 box.y2 = box_y2;
280 RegionInit(&rgnDst, &box, 1);
281 }
282
283 /* Clip against complex source if needed */
284 if (!fastSrc) {
285 RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip);
286 RegionTranslate(&rgnDst, -dx, -dy);
287 }
288
289 /* Clip against complex dest if needed */
290 if (!fastDst) {
291 RegionIntersect(&rgnDst, &rgnDst, miGetCompositeClip(pGC));
292 }
293
294 /* Do bit blitting */
295 numRects = RegionNumRects(&rgnDst);
296 if (numRects && widthSrc && heightSrc)
297 miCopyRegion(pSrcDrawable, pDstDrawable, pGC,
298 &rgnDst, dx, dy, copyProc, bitPlane, closure);
299
300 /* Pixmap sources generate a NoExposed (we return NULL to do this) */
301 if (!fastExpose && pGC->fExpose)
302 prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
303 xIn - pSrcDrawable->x,
304 yIn - pSrcDrawable->y,
305 widthSrc, heightSrc,
306 xOut - pDstDrawable->x,
307 yOut - pDstDrawable->y,
308 (unsigned long) bitPlane);
309 RegionUninit(&rgnDst);
310 if (freeSrcClip)
311 RegionDestroy(prgnSrcClip);
312 return prgnExposed;
313}