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