2 * Copyright © 1998 Keith Packard
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.
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
28 #include "scrnintstr.h"
31 #include "pixmapstr.h"
32 #include "windowstr.h"
35 miCopyRegion(DrawablePtr pSrcDrawable
,
36 DrawablePtr pDstDrawable
,
39 int dx
, int dy
, miCopyProc copyProc
, Pixel bitPlane
, void *closure
)
46 BoxPtr pboxNew1
, pboxNew2
, pboxBase
, pboxNext
, pboxTmp
;
48 pbox
= RegionRects(pDstRegion
);
49 nbox
= RegionNumRects(pDstRegion
);
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.
54 careful
= ((pSrcDrawable
== pDstDrawable
) ||
55 ((pSrcDrawable
->type
== DRAWABLE_WINDOW
) &&
56 (pDstDrawable
->type
== DRAWABLE_WINDOW
)));
60 if (careful
&& dy
< 0) {
64 /* keep ordering in each band, reverse order of bands */
65 pboxNew1
= (BoxPtr
) malloc(sizeof(BoxRec
) * nbox
);
68 pboxBase
= pboxNext
= pbox
+ nbox
- 1;
69 while (pboxBase
>= pbox
) {
70 while ((pboxNext
>= pbox
) && (pboxBase
->y1
== pboxNext
->y1
))
72 pboxTmp
= pboxNext
+ 1;
73 while (pboxTmp
<= pboxBase
) {
74 *pboxNew1
++ = *pboxTmp
++;
83 /* walk source top to bottom */
87 if (careful
&& dx
< 0) {
88 /* walk source right to left */
95 /* reverse order of rects in each band */
96 pboxNew2
= (BoxPtr
) malloc(sizeof(BoxRec
) * nbox
);
101 pboxBase
= pboxNext
= pbox
;
102 while (pboxBase
< pbox
+ nbox
) {
103 while ((pboxNext
< pbox
+ nbox
) &&
104 (pboxNext
->y1
== pboxBase
->y1
))
107 while (pboxTmp
!= pboxBase
) {
108 *pboxNew2
++ = *--pboxTmp
;
117 /* walk source left to right */
121 (*copyProc
) (pSrcDrawable
,
124 pbox
, nbox
, dx
, dy
, reverse
, upsidedown
, bitPlane
, closure
);
131 miDoCopy(DrawablePtr pSrcDrawable
,
132 DrawablePtr pDstDrawable
,
138 int xOut
, int yOut
, miCopyProc copyProc
, Pixel bitPlane
, void *closure
)
140 RegionPtr prgnSrcClip
= NULL
; /* may be a new region, or just a copy */
141 Bool freeSrcClip
= FALSE
;
142 RegionPtr prgnExposed
= NULL
;
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 */
155 /* Short cut for unmapped windows */
157 if (pDstDrawable
->type
== DRAWABLE_WINDOW
&&
158 !((WindowPtr
) pDstDrawable
)->realized
) {
162 if (pSrcDrawable
->pScreen
->SourceValidate
) {
163 (*pSrcDrawable
->pScreen
->SourceValidate
) (pSrcDrawable
, xIn
, yIn
,
168 /* Compute source clip region */
169 if (pSrcDrawable
->type
== DRAWABLE_PIXMAP
) {
170 if ((pSrcDrawable
== pDstDrawable
) && (pGC
->clientClipType
== CT_NONE
))
171 prgnSrcClip
= miGetCompositeClip(pGC
);
176 if (pGC
->subWindowMode
== IncludeInferiors
) {
178 * XFree86 DDX empties the border clip when the
179 * VT is inactive, make sure the region isn't empty
181 if (!((WindowPtr
) pSrcDrawable
)->parent
&&
182 RegionNotEmpty(&((WindowPtr
) pSrcDrawable
)->borderClip
)) {
184 * special case bitblt from root window in
185 * IncludeInferiors mode; just like from a pixmap
189 else if ((pSrcDrawable
== pDstDrawable
) &&
190 (pGC
->clientClipType
== CT_NONE
)) {
191 prgnSrcClip
= miGetCompositeClip(pGC
);
194 prgnSrcClip
= NotClippedByChildren((WindowPtr
) pSrcDrawable
);
199 prgnSrcClip
= &((WindowPtr
) pSrcDrawable
)->clipList
;
203 xIn
+= pSrcDrawable
->x
;
204 yIn
+= pSrcDrawable
->y
;
206 xOut
+= pDstDrawable
->x
;
207 yOut
+= pDstDrawable
->y
;
211 box_x2
= xIn
+ widthSrc
;
212 box_y2
= yIn
+ heightSrc
;
217 /* Don't create a source region if we are doing a fast clip */
223 * clip the source; if regions extend beyond the source size,
224 * make sure exposure events get sent
226 if (box_x1
< pSrcDrawable
->x
) {
227 box_x1
= pSrcDrawable
->x
;
230 if (box_y1
< pSrcDrawable
->y
) {
231 box_y1
= pSrcDrawable
->y
;
234 if (box_x2
> pSrcDrawable
->x
+ (int) pSrcDrawable
->width
) {
235 box_x2
= pSrcDrawable
->x
+ (int) pSrcDrawable
->width
;
238 if (box_y2
> pSrcDrawable
->y
+ (int) pSrcDrawable
->height
) {
239 box_y2
= pSrcDrawable
->y
+ (int) pSrcDrawable
->height
;
243 /* Translate and clip the dst to the destination composite clip */
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 */
253 cclip
= miGetCompositeClip(pGC
);
254 if (RegionNumRects(cclip
) == 1) {
255 BoxPtr pBox
= RegionRects(cclip
);
257 if (box_x1
< pBox
->x1
)
259 if (box_x2
> pBox
->x2
)
261 if (box_y1
< pBox
->y1
)
263 if (box_y2
> pBox
->y2
)
269 /* Check to see if the region is empty */
270 if (box_x1
>= box_x2
|| box_y1
>= box_y2
) {
280 RegionInit(&rgnDst
, &box
, 1);
283 /* Clip against complex source if needed */
285 RegionIntersect(&rgnDst
, &rgnDst
, prgnSrcClip
);
286 RegionTranslate(&rgnDst
, -dx
, -dy
);
289 /* Clip against complex dest if needed */
291 RegionIntersect(&rgnDst
, &rgnDst
, miGetCompositeClip(pGC
));
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
);
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
,
306 xOut
- pDstDrawable
->x
,
307 yOut
- pDstDrawable
->y
,
308 (unsigned long) bitPlane
);
309 RegionUninit(&rgnDst
);
311 RegionDestroy(prgnSrcClip
);