micopy.c revision 6747b715
16747b715Smrg/* 26747b715Smrg * Copyright © 1998 Keith Packard 36747b715Smrg * 46747b715Smrg * Permission to use, copy, modify, distribute, and sell this software and its 56747b715Smrg * documentation for any purpose is hereby granted without fee, provided that 66747b715Smrg * the above copyright notice appear in all copies and that both that 76747b715Smrg * copyright notice and this permission notice appear in supporting 86747b715Smrg * documentation, and that the name of Keith Packard not be used in 96747b715Smrg * advertising or publicity pertaining to distribution of the software without 106747b715Smrg * specific, written prior permission. Keith Packard makes no 116747b715Smrg * representations about the suitability of this software for any purpose. It 126747b715Smrg * is provided "as is" without express or implied warranty. 136747b715Smrg * 146747b715Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 156747b715Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 166747b715Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 176747b715Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 186747b715Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 196747b715Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 206747b715Smrg * PERFORMANCE OF THIS SOFTWARE. 216747b715Smrg */ 226747b715Smrg 236747b715Smrg#ifdef HAVE_DIX_CONFIG_H 246747b715Smrg#include <dix-config.h> 256747b715Smrg#endif 266747b715Smrg 276747b715Smrg#include "mi.h" 286747b715Smrg#include "scrnintstr.h" 296747b715Smrg#include "gcstruct.h" 306747b715Smrg#include "pixmap.h" 316747b715Smrg#include "pixmapstr.h" 326747b715Smrg#include "windowstr.h" 336747b715Smrg 346747b715Smrgvoid 356747b715SmrgmiCopyRegion (DrawablePtr pSrcDrawable, 366747b715Smrg DrawablePtr pDstDrawable, 376747b715Smrg GCPtr pGC, 386747b715Smrg RegionPtr pDstRegion, 396747b715Smrg int dx, 406747b715Smrg int dy, 416747b715Smrg miCopyProc copyProc, 426747b715Smrg Pixel bitPlane, 436747b715Smrg void *closure) 446747b715Smrg{ 456747b715Smrg int careful; 466747b715Smrg Bool reverse; 476747b715Smrg Bool upsidedown; 486747b715Smrg BoxPtr pbox; 496747b715Smrg int nbox; 506747b715Smrg BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp; 516747b715Smrg 526747b715Smrg pbox = RegionRects(pDstRegion); 536747b715Smrg nbox = RegionNumRects(pDstRegion); 546747b715Smrg 556747b715Smrg /* XXX we have to err on the side of safety when both are windows, 566747b715Smrg * because we don't know if IncludeInferiors is being used. 576747b715Smrg */ 586747b715Smrg careful = ((pSrcDrawable == pDstDrawable) || 596747b715Smrg ((pSrcDrawable->type == DRAWABLE_WINDOW) && 606747b715Smrg (pDstDrawable->type == DRAWABLE_WINDOW))); 616747b715Smrg 626747b715Smrg pboxNew1 = NULL; 636747b715Smrg pboxNew2 = NULL; 646747b715Smrg if (careful && dy < 0) 656747b715Smrg { 666747b715Smrg upsidedown = TRUE; 676747b715Smrg 686747b715Smrg if (nbox > 1) 696747b715Smrg { 706747b715Smrg /* keep ordering in each band, reverse order of bands */ 716747b715Smrg pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); 726747b715Smrg if(!pboxNew1) 736747b715Smrg return; 746747b715Smrg pboxBase = pboxNext = pbox+nbox-1; 756747b715Smrg while (pboxBase >= pbox) 766747b715Smrg { 776747b715Smrg while ((pboxNext >= pbox) && 786747b715Smrg (pboxBase->y1 == pboxNext->y1)) 796747b715Smrg pboxNext--; 806747b715Smrg pboxTmp = pboxNext+1; 816747b715Smrg while (pboxTmp <= pboxBase) 826747b715Smrg { 836747b715Smrg *pboxNew1++ = *pboxTmp++; 846747b715Smrg } 856747b715Smrg pboxBase = pboxNext; 866747b715Smrg } 876747b715Smrg pboxNew1 -= nbox; 886747b715Smrg pbox = pboxNew1; 896747b715Smrg } 906747b715Smrg } 916747b715Smrg else 926747b715Smrg { 936747b715Smrg /* walk source top to bottom */ 946747b715Smrg upsidedown = FALSE; 956747b715Smrg } 966747b715Smrg 976747b715Smrg if (careful && dx < 0) 986747b715Smrg { 996747b715Smrg /* walk source right to left */ 1006747b715Smrg if (dy <= 0) 1016747b715Smrg reverse = TRUE; 1026747b715Smrg else 1036747b715Smrg reverse = FALSE; 1046747b715Smrg 1056747b715Smrg if (nbox > 1) 1066747b715Smrg { 1076747b715Smrg /* reverse order of rects in each band */ 1086747b715Smrg pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); 1096747b715Smrg if(!pboxNew2) 1106747b715Smrg { 1116747b715Smrg free(pboxNew1); 1126747b715Smrg return; 1136747b715Smrg } 1146747b715Smrg pboxBase = pboxNext = pbox; 1156747b715Smrg while (pboxBase < pbox+nbox) 1166747b715Smrg { 1176747b715Smrg while ((pboxNext < pbox+nbox) && 1186747b715Smrg (pboxNext->y1 == pboxBase->y1)) 1196747b715Smrg pboxNext++; 1206747b715Smrg pboxTmp = pboxNext; 1216747b715Smrg while (pboxTmp != pboxBase) 1226747b715Smrg { 1236747b715Smrg *pboxNew2++ = *--pboxTmp; 1246747b715Smrg } 1256747b715Smrg pboxBase = pboxNext; 1266747b715Smrg } 1276747b715Smrg pboxNew2 -= nbox; 1286747b715Smrg pbox = pboxNew2; 1296747b715Smrg } 1306747b715Smrg } 1316747b715Smrg else 1326747b715Smrg { 1336747b715Smrg /* walk source left to right */ 1346747b715Smrg reverse = FALSE; 1356747b715Smrg } 1366747b715Smrg 1376747b715Smrg (*copyProc) (pSrcDrawable, 1386747b715Smrg pDstDrawable, 1396747b715Smrg pGC, 1406747b715Smrg pbox, 1416747b715Smrg nbox, 1426747b715Smrg dx, dy, 1436747b715Smrg reverse, upsidedown, bitPlane, closure); 1446747b715Smrg 1456747b715Smrg free(pboxNew1); 1466747b715Smrg free(pboxNew2); 1476747b715Smrg} 1486747b715Smrg 1496747b715SmrgRegionPtr 1506747b715SmrgmiDoCopy (DrawablePtr pSrcDrawable, 1516747b715Smrg DrawablePtr pDstDrawable, 1526747b715Smrg GCPtr pGC, 1536747b715Smrg int xIn, 1546747b715Smrg int yIn, 1556747b715Smrg int widthSrc, 1566747b715Smrg int heightSrc, 1576747b715Smrg int xOut, 1586747b715Smrg int yOut, 1596747b715Smrg miCopyProc copyProc, 1606747b715Smrg Pixel bitPlane, 1616747b715Smrg void *closure) 1626747b715Smrg{ 1636747b715Smrg RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ 1646747b715Smrg Bool freeSrcClip = FALSE; 1656747b715Smrg RegionPtr prgnExposed = NULL; 1666747b715Smrg RegionRec rgnDst; 1676747b715Smrg int dx; 1686747b715Smrg int dy; 1696747b715Smrg int numRects; 1706747b715Smrg int box_x1; 1716747b715Smrg int box_y1; 1726747b715Smrg int box_x2; 1736747b715Smrg int box_y2; 1746747b715Smrg Bool fastSrc = FALSE; /* for fast clipping with pixmap source */ 1756747b715Smrg Bool fastDst = FALSE; /* for fast clipping with one rect dest */ 1766747b715Smrg Bool fastExpose = FALSE; /* for fast exposures with pixmap source */ 1776747b715Smrg 1786747b715Smrg /* Short cut for unmapped windows */ 1796747b715Smrg 1806747b715Smrg if (pDstDrawable->type == DRAWABLE_WINDOW && 1816747b715Smrg !((WindowPtr)pDstDrawable)->realized) 1826747b715Smrg { 1836747b715Smrg return NULL; 1846747b715Smrg } 1856747b715Smrg 1866747b715Smrg if ((pSrcDrawable != pDstDrawable) && 1876747b715Smrg pSrcDrawable->pScreen->SourceValidate) 1886747b715Smrg { 1896747b715Smrg (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc); 1906747b715Smrg } 1916747b715Smrg 1926747b715Smrg /* Compute source clip region */ 1936747b715Smrg if (pSrcDrawable->type == DRAWABLE_PIXMAP) 1946747b715Smrg { 1956747b715Smrg if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) 1966747b715Smrg prgnSrcClip = miGetCompositeClip(pGC); 1976747b715Smrg else 1986747b715Smrg fastSrc = TRUE; 1996747b715Smrg } 2006747b715Smrg else 2016747b715Smrg { 2026747b715Smrg if (pGC->subWindowMode == IncludeInferiors) 2036747b715Smrg { 2046747b715Smrg /* 2056747b715Smrg * XFree86 DDX empties the border clip when the 2066747b715Smrg * VT is inactive, make sure the region isn't empty 2076747b715Smrg */ 2086747b715Smrg if (!((WindowPtr) pSrcDrawable)->parent && 2096747b715Smrg RegionNotEmpty(&((WindowPtr) pSrcDrawable)->borderClip)) 2106747b715Smrg { 2116747b715Smrg /* 2126747b715Smrg * special case bitblt from root window in 2136747b715Smrg * IncludeInferiors mode; just like from a pixmap 2146747b715Smrg */ 2156747b715Smrg fastSrc = TRUE; 2166747b715Smrg } 2176747b715Smrg else if ((pSrcDrawable == pDstDrawable) && 2186747b715Smrg (pGC->clientClipType == CT_NONE)) 2196747b715Smrg { 2206747b715Smrg prgnSrcClip = miGetCompositeClip(pGC); 2216747b715Smrg } 2226747b715Smrg else 2236747b715Smrg { 2246747b715Smrg prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); 2256747b715Smrg freeSrcClip = TRUE; 2266747b715Smrg } 2276747b715Smrg } 2286747b715Smrg else 2296747b715Smrg { 2306747b715Smrg prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; 2316747b715Smrg } 2326747b715Smrg } 2336747b715Smrg 2346747b715Smrg xIn += pSrcDrawable->x; 2356747b715Smrg yIn += pSrcDrawable->y; 2366747b715Smrg 2376747b715Smrg xOut += pDstDrawable->x; 2386747b715Smrg yOut += pDstDrawable->y; 2396747b715Smrg 2406747b715Smrg box_x1 = xIn; 2416747b715Smrg box_y1 = yIn; 2426747b715Smrg box_x2 = xIn + widthSrc; 2436747b715Smrg box_y2 = yIn + heightSrc; 2446747b715Smrg 2456747b715Smrg dx = xIn - xOut; 2466747b715Smrg dy = yIn - yOut; 2476747b715Smrg 2486747b715Smrg /* Don't create a source region if we are doing a fast clip */ 2496747b715Smrg if (fastSrc) 2506747b715Smrg { 2516747b715Smrg RegionPtr cclip; 2526747b715Smrg 2536747b715Smrg fastExpose = TRUE; 2546747b715Smrg /* 2556747b715Smrg * clip the source; if regions extend beyond the source size, 2566747b715Smrg * make sure exposure events get sent 2576747b715Smrg */ 2586747b715Smrg if (box_x1 < pSrcDrawable->x) 2596747b715Smrg { 2606747b715Smrg box_x1 = pSrcDrawable->x; 2616747b715Smrg fastExpose = FALSE; 2626747b715Smrg } 2636747b715Smrg if (box_y1 < pSrcDrawable->y) 2646747b715Smrg { 2656747b715Smrg box_y1 = pSrcDrawable->y; 2666747b715Smrg fastExpose = FALSE; 2676747b715Smrg } 2686747b715Smrg if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) 2696747b715Smrg { 2706747b715Smrg box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width; 2716747b715Smrg fastExpose = FALSE; 2726747b715Smrg } 2736747b715Smrg if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) 2746747b715Smrg { 2756747b715Smrg box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height; 2766747b715Smrg fastExpose = FALSE; 2776747b715Smrg } 2786747b715Smrg 2796747b715Smrg /* Translate and clip the dst to the destination composite clip */ 2806747b715Smrg box_x1 -= dx; 2816747b715Smrg box_x2 -= dx; 2826747b715Smrg box_y1 -= dy; 2836747b715Smrg box_y2 -= dy; 2846747b715Smrg 2856747b715Smrg /* If the destination composite clip is one rectangle we can 2866747b715Smrg do the clip directly. Otherwise we have to create a full 2876747b715Smrg blown region and call intersect */ 2886747b715Smrg 2896747b715Smrg cclip = miGetCompositeClip(pGC); 2906747b715Smrg if (RegionNumRects(cclip) == 1) 2916747b715Smrg { 2926747b715Smrg BoxPtr pBox = RegionRects(cclip); 2936747b715Smrg 2946747b715Smrg if (box_x1 < pBox->x1) box_x1 = pBox->x1; 2956747b715Smrg if (box_x2 > pBox->x2) box_x2 = pBox->x2; 2966747b715Smrg if (box_y1 < pBox->y1) box_y1 = pBox->y1; 2976747b715Smrg if (box_y2 > pBox->y2) box_y2 = pBox->y2; 2986747b715Smrg fastDst = TRUE; 2996747b715Smrg } 3006747b715Smrg } 3016747b715Smrg 3026747b715Smrg /* Check to see if the region is empty */ 3036747b715Smrg if (box_x1 >= box_x2 || box_y1 >= box_y2) 3046747b715Smrg { 3056747b715Smrg RegionNull(&rgnDst); 3066747b715Smrg } 3076747b715Smrg else 3086747b715Smrg { 3096747b715Smrg BoxRec box; 3106747b715Smrg box.x1 = box_x1; 3116747b715Smrg box.y1 = box_y1; 3126747b715Smrg box.x2 = box_x2; 3136747b715Smrg box.y2 = box_y2; 3146747b715Smrg RegionInit(&rgnDst, &box, 1); 3156747b715Smrg } 3166747b715Smrg 3176747b715Smrg /* Clip against complex source if needed */ 3186747b715Smrg if (!fastSrc) 3196747b715Smrg { 3206747b715Smrg RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip); 3216747b715Smrg RegionTranslate(&rgnDst, -dx, -dy); 3226747b715Smrg } 3236747b715Smrg 3246747b715Smrg /* Clip against complex dest if needed */ 3256747b715Smrg if (!fastDst) 3266747b715Smrg { 3276747b715Smrg RegionIntersect(&rgnDst, &rgnDst, 3286747b715Smrg miGetCompositeClip(pGC)); 3296747b715Smrg } 3306747b715Smrg 3316747b715Smrg /* Do bit blitting */ 3326747b715Smrg numRects = RegionNumRects(&rgnDst); 3336747b715Smrg if (numRects && widthSrc && heightSrc) 3346747b715Smrg miCopyRegion (pSrcDrawable, pDstDrawable, pGC, 3356747b715Smrg &rgnDst, dx, dy, copyProc, bitPlane, closure); 3366747b715Smrg 3376747b715Smrg /* Pixmap sources generate a NoExposed (we return NULL to do this) */ 3386747b715Smrg if (!fastExpose && pGC->fExpose) 3396747b715Smrg prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, 3406747b715Smrg xIn - pSrcDrawable->x, 3416747b715Smrg yIn - pSrcDrawable->y, 3426747b715Smrg widthSrc, heightSrc, 3436747b715Smrg xOut - pDstDrawable->x, 3446747b715Smrg yOut - pDstDrawable->y, 3456747b715Smrg (unsigned long) bitPlane); 3466747b715Smrg RegionUninit(&rgnDst); 3476747b715Smrg if (freeSrcClip) 3486747b715Smrg RegionDestroy(prgnSrcClip); 3496747b715Smrg return prgnExposed; 3506747b715Smrg} 351