1/* 2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation on the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28/* 29 * Authors: 30 * Kevin E. Martin <kem@redhat.com> 31 * 32 */ 33 34/** \file 35 * This file provides support for GC operations. */ 36 37#ifdef HAVE_DMX_CONFIG_H 38#include <dmx-config.h> 39#endif 40 41#include "dmx.h" 42#include "dmxsync.h" 43#include "dmxgc.h" 44#include "dmxgcops.h" 45#include "dmxwindow.h" 46#include "dmxpixmap.h" 47 48#include "mi.h" 49#include "gcstruct.h" 50#include "pixmapstr.h" 51#include "dixfontstr.h" 52 53#ifdef PANORAMIX 54#include "panoramiXsrv.h" 55#endif 56 57#define DMX_GCOPS_SET_DRAWABLE(_pDraw, _draw) \ 58do { \ 59 if ((_pDraw)->type == DRAWABLE_WINDOW) { \ 60 dmxWinPrivPtr pWinPriv = \ 61 DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw)); \ 62 (_draw) = (Drawable)pWinPriv->window; \ 63 } else { \ 64 dmxPixPrivPtr pPixPriv = \ 65 DMX_GET_PIXMAP_PRIV((PixmapPtr)(_pDraw)); \ 66 (_draw) = (Drawable)pPixPriv->pixmap; \ 67 } \ 68} while (0) 69 70#define DMX_GCOPS_OFFSCREEN(_pDraw) \ 71 (!dmxScreens[(_pDraw)->pScreen->myNum].beDisplay || \ 72 (dmxOffScreenOpt && \ 73 (_pDraw)->type == DRAWABLE_WINDOW && \ 74 (DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->offscreen || \ 75 !DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->window))) 76 77/** Fill spans -- this function should never be called. */ 78void dmxFillSpans(DrawablePtr pDrawable, GCPtr pGC, 79 int nInit, DDXPointPtr pptInit, int *pwidthInit, 80 int fSorted) 81{ 82 /* Error -- this should never happen! */ 83} 84 85/** Set spans -- this function should never be called. */ 86void dmxSetSpans(DrawablePtr pDrawable, GCPtr pGC, 87 char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, 88 int fSorted) 89{ 90 /* Error -- this should never happen! */ 91} 92 93/** Transfer \a pBits image to back-end server associated with \a 94 * pDrawable's screen. If primitive subdivision optimization is 95 * enabled, then only transfer the sections of \a pBits that are 96 * visible (i.e., not-clipped) to the back-end server. */ 97void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC, 98 int depth, int x, int y, int w, int h, 99 int leftPad, int format, char *pBits) 100{ 101 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 102 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 103 XImage *img; 104 105 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 106 107 img = XCreateImage(dmxScreen->beDisplay, 108 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, 109 depth, format, leftPad, pBits, w, h, 110 BitmapPad(dmxScreen->beDisplay), 111 (format == ZPixmap) ? 112 PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad)); 113 114 if (img) { 115 Drawable draw; 116 117 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 118 119 if (dmxSubdividePrimitives && pGC->pCompositeClip) { 120 RegionPtr pSubImages; 121 RegionPtr pClip; 122 BoxRec box; 123 BoxPtr pBox; 124 int nBox; 125 126 box.x1 = x; 127 box.y1 = y; 128 box.x2 = x + w; 129 box.y2 = y + h; 130 pSubImages = RegionCreate(&box, 1); 131 132 pClip = RegionCreate(NullBox, 1); 133 RegionCopy(pClip, pGC->pCompositeClip); 134 RegionTranslate(pClip, 135 -pDrawable->x, -pDrawable->y); 136 RegionIntersect(pSubImages, pSubImages, pClip); 137 138 nBox = RegionNumRects(pSubImages); 139 pBox = RegionRects(pSubImages); 140 141 while (nBox--) { 142 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img, 143 pBox->x1 - box.x1, 144 pBox->y1 - box.y1, 145 pBox->x1, 146 pBox->y1, 147 pBox->x2 - pBox->x1, 148 pBox->y2 - pBox->y1); 149 pBox++; 150 } 151 RegionDestroy(pClip); 152 RegionDestroy(pSubImages); 153 } else { 154 XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, 155 img, 0, 0, x, y, w, h); 156 } 157 XFree(img); /* Use XFree instead of XDestroyImage 158 * because pBits is passed in from the 159 * caller. */ 160 161 dmxSync(dmxScreen, FALSE); 162 } else { 163 /* Error -- this should not happen! */ 164 } 165} 166 167/** Copy area from \a pSrc drawable to \a pDst drawable on the back-end 168 * server associated with \a pSrc drawable's screen. If the offscreen 169 * optimization is enabled, only copy when both \a pSrc and \a pDst are 170 * at least partially visible. */ 171RegionPtr dmxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 172 int srcx, int srcy, int w, int h, int dstx, int dsty) 173{ 174 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum]; 175 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 176 Drawable srcDraw, dstDraw; 177 178 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst)) 179 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, 180 dstx, dsty, 0L); 181 182 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw); 183 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw); 184 185 XCopyArea(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc, 186 srcx, srcy, w, h, dstx, dsty); 187 dmxSync(dmxScreen, FALSE); 188 189 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, 190 dstx, dsty, 0L); 191} 192 193/** Copy plane number \a bitPlane from \a pSrc drawable to \a pDst 194 * drawable on the back-end server associated with \a pSrc drawable's 195 * screen. If the offscreen optimization is enabled, only copy when 196 * both \a pSrc and \a pDst are at least partially visible. */ 197RegionPtr dmxCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 198 int srcx, int srcy, int width, int height, 199 int dstx, int dsty, unsigned long bitPlane) 200{ 201 DMXScreenInfo *dmxScreen = &dmxScreens[pSrc->pScreen->myNum]; 202 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 203 Drawable srcDraw, dstDraw; 204 205 if (DMX_GCOPS_OFFSCREEN(pSrc) || DMX_GCOPS_OFFSCREEN(pDst)) 206 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height, 207 dstx, dsty, bitPlane); 208 209 DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw); 210 DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw); 211 212 XCopyPlane(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc, 213 srcx, srcy, width, height, dstx, dsty, bitPlane); 214 dmxSync(dmxScreen, FALSE); 215 216 return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height, 217 dstx, dsty, bitPlane); 218} 219 220/** Render list of points, \a pptInit in \a pDrawable on the back-end 221 * server associated with \a pDrawable's screen. If the offscreen 222 * optimization is enabled, only draw when \a pDrawable is at least 223 * partially visible. */ 224void dmxPolyPoint(DrawablePtr pDrawable, GCPtr pGC, 225 int mode, int npt, DDXPointPtr pptInit) 226{ 227 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 228 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 229 Drawable draw; 230 231 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 232 233 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 234 235 XDrawPoints(dmxScreen->beDisplay, draw, pGCPriv->gc, 236 (XPoint *)pptInit, npt, mode); 237 dmxSync(dmxScreen, FALSE); 238} 239 240/** Render list of connected lines, \a pptInit in \a pDrawable on the 241 * back-end server associated with \a pDrawable's screen. If the 242 * offscreen optimization is enabled, only draw when \a pDrawable is at 243 * least partially visible. */ 244void dmxPolylines(DrawablePtr pDrawable, GCPtr pGC, 245 int mode, int npt, DDXPointPtr pptInit) 246{ 247 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 248 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 249 Drawable draw; 250 251 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 252 253 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 254 255 XDrawLines(dmxScreen->beDisplay, draw, pGCPriv->gc, 256 (XPoint *)pptInit, npt, mode); 257 dmxSync(dmxScreen, FALSE); 258} 259 260/** Render list of disjoint segments, \a pSegs in \a pDrawable on the 261 * back-end server associated with \a pDrawable's screen. If the 262 * offscreen optimization is enabled, only draw when \a pDrawable is at 263 * least partially visible. */ 264void dmxPolySegment(DrawablePtr pDrawable, GCPtr pGC, 265 int nseg, xSegment *pSegs) 266{ 267 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 268 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 269 Drawable draw; 270 271 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 272 273 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 274 275 XDrawSegments(dmxScreen->beDisplay, draw, pGCPriv->gc, 276 (XSegment *)pSegs, nseg); 277 dmxSync(dmxScreen, FALSE); 278} 279 280/** Render list of rectangle outlines, \a pRects in \a pDrawable on the 281 * back-end server associated with \a pDrawable's screen. If the 282 * offscreen optimization is enabled, only draw when \a pDrawable is at 283 * least partially visible. */ 284void dmxPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, 285 int nrects, xRectangle *pRects) 286{ 287 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 288 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 289 Drawable draw; 290 291 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 292 293 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 294 295 XDrawRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc, 296 (XRectangle *)pRects, nrects); 297 298 dmxSync(dmxScreen, FALSE); 299} 300 301/** Render list of arc outlines, \a parcs in \a pDrawable on the 302 * back-end server associated with \a pDrawable's screen. If the 303 * offscreen optimization is enabled, only draw when \a pDrawable is at 304 * least partially visible. */ 305void dmxPolyArc(DrawablePtr pDrawable, GCPtr pGC, 306 int narcs, xArc *parcs) 307{ 308 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 309 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 310 Drawable draw; 311 312 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 313 314 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 315 316 XDrawArcs(dmxScreen->beDisplay, draw, pGCPriv->gc, 317 (XArc *)parcs, narcs); 318 dmxSync(dmxScreen, FALSE); 319} 320 321/** Render a filled polygons in \a pDrawable on the back-end server 322 * associated with \a pDrawable's screen. If the offscreen 323 * optimization is enabled, only draw when \a pDrawable is at least 324 * partially visible. */ 325void dmxFillPolygon(DrawablePtr pDrawable, GCPtr pGC, 326 int shape, int mode, int count, DDXPointPtr pPts) 327{ 328 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 329 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 330 Drawable draw; 331 332 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 333 334 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 335 336 XFillPolygon(dmxScreen->beDisplay, draw, pGCPriv->gc, 337 (XPoint *)pPts, count, shape, mode); 338 dmxSync(dmxScreen, FALSE); 339} 340 341/** Render list of filled rectangles, \a prectInit in \a pDrawable on 342 * the back-end server associated with \a pDrawable's screen. If the 343 * offscreen optimization is enabled, only draw when \a pDrawable is at 344 * least partially visible. */ 345void dmxPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, 346 int nrectFill, xRectangle *prectInit) 347{ 348 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 349 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 350 Drawable draw; 351 352 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 353 354 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 355 356 XFillRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc, 357 (XRectangle *)prectInit, nrectFill); 358 dmxSync(dmxScreen, FALSE); 359} 360 361/** Render list of filled arcs, \a parcs in \a pDrawable on the back-end 362 * server associated with \a pDrawable's screen. If the offscreen 363 * optimization is enabled, only draw when \a pDrawable is at least 364 * partially visible. */ 365void dmxPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, 366 int narcs, xArc *parcs) 367{ 368 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 369 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 370 Drawable draw; 371 372 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 373 374 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 375 376 XFillArcs(dmxScreen->beDisplay, draw, pGCPriv->gc, 377 (XArc *)parcs, narcs); 378 dmxSync(dmxScreen, FALSE); 379} 380 381/** Render string of 8-bit \a chars (foreground only) in \a pDrawable on 382 * the back-end server associated with \a pDrawable's screen. If the 383 * offscreen optimization is enabled, only draw when \a pDrawable is at 384 * least partially visible. */ 385int dmxPolyText8(DrawablePtr pDrawable, GCPtr pGC, 386 int x, int y, int count, char *chars) 387{ 388 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 389 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 390 unsigned long n, i; 391 int w; 392 CharInfoPtr charinfo[255]; 393 Drawable draw; 394 395 GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, 396 Linear8Bit, &n, charinfo); 397 398 /* Calculate text width */ 399 w = 0; 400 for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth; 401 402 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) { 403 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 404 405 XDrawString(dmxScreen->beDisplay, draw, pGCPriv->gc, 406 x, y, chars, count); 407 dmxSync(dmxScreen, FALSE); 408 } 409 410 return x+w; 411} 412 413/** Render string of 16-bit \a chars (foreground only) in \a pDrawable 414 * on the back-end server associated with \a pDrawable's screen. If 415 * the offscreen optimization is enabled, only draw when \a pDrawable 416 * is at least partially visible. */ 417int dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC, 418 int x, int y, int count, unsigned short *chars) 419{ 420 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 421 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 422 unsigned long n, i; 423 int w; 424 CharInfoPtr charinfo[255]; 425 Drawable draw; 426 427 GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars, 428 (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, 429 &n, charinfo); 430 431 /* Calculate text width */ 432 w = 0; 433 for (i = 0; i < n; i++) w += charinfo[i]->metrics.characterWidth; 434 435 if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) { 436 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 437 438 XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc, 439 x, y, (XChar2b *)chars, count); 440 dmxSync(dmxScreen, FALSE); 441 } 442 443 return x+w; 444} 445 446/** Render string of 8-bit \a chars (both foreground and background) in 447 * \a pDrawable on the back-end server associated with \a pDrawable's 448 * screen. If the offscreen optimization is enabled, only draw when \a 449 * pDrawable is at least partially visible. */ 450void dmxImageText8(DrawablePtr pDrawable, GCPtr pGC, 451 int x, int y, int count, char *chars) 452{ 453 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 454 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 455 Drawable draw; 456 457 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 458 459 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 460 461 XDrawImageString(dmxScreen->beDisplay, draw, pGCPriv->gc, 462 x, y, chars, count); 463 dmxSync(dmxScreen, FALSE); 464} 465 466/** Render string of 16-bit \a chars (both foreground and background) in 467 * \a pDrawable on the back-end server associated with \a pDrawable's 468 * screen. If the offscreen optimization is enabled, only draw when \a 469 * pDrawable is at least partially visible. */ 470void dmxImageText16(DrawablePtr pDrawable, GCPtr pGC, 471 int x, int y, int count, unsigned short *chars) 472{ 473 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 474 dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); 475 Drawable draw; 476 477 if (DMX_GCOPS_OFFSCREEN(pDrawable)) return; 478 479 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 480 481 XDrawImageString16(dmxScreen->beDisplay, draw, pGCPriv->gc, 482 x, y, (XChar2b *)chars, count); 483 dmxSync(dmxScreen, FALSE); 484} 485 486/** Image Glyph Blt -- this function should never be called. */ 487void dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, 488 int x, int y, unsigned int nglyph, 489 CharInfoPtr *ppci, pointer pglyphBase) 490{ 491 /* Error -- this should never happen! */ 492} 493 494/** Poly Glyph Blt -- this function should never be called. */ 495void dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, 496 int x, int y, unsigned int nglyph, 497 CharInfoPtr *ppci, pointer pglyphBase) 498{ 499 /* Error -- this should never happen! */ 500} 501 502/** Push Pixels -- this function should never be called. */ 503void dmxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, 504 int w, int h, int x, int y) 505{ 506 /* Error -- this should never happen! */ 507} 508 509/********************************************************************** 510 * Miscellaneous drawing commands 511 */ 512 513/** When Xinerama is active, the client pixmaps are always obtained from 514 * screen 0. When screen 0 is detached, the pixmaps must be obtained 515 * from any other screen that is not detached. Usually, this is screen 516 * 1. */ 517static DMXScreenInfo *dmxFindAlternatePixmap(DrawablePtr pDrawable, XID *draw) 518{ 519#ifdef PANORAMIX 520 PanoramiXRes *pXinPix; 521 int i; 522 DMXScreenInfo *dmxScreen; 523 524 if (noPanoramiXExtension) return NULL; 525 if (pDrawable->type != DRAWABLE_PIXMAP) return NULL; 526 527 if (Success != dixLookupResourceByType((pointer*) &pXinPix, 528 pDrawable->id, XRT_PIXMAP, 529 NullClient, DixUnknownAccess)) 530 return NULL; 531 532 for (i = 1; i < PanoramiXNumScreens; i++) { 533 dmxScreen = &dmxScreens[i]; 534 if (dmxScreen->beDisplay) { 535 PixmapPtr pSrc; 536 dmxPixPrivPtr pSrcPriv; 537 538 dixLookupResourceByType((pointer*) &pSrc, pXinPix->info[i].id, 539 RT_PIXMAP, NullClient, DixUnknownAccess); 540 pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc); 541 if (pSrcPriv->pixmap) { 542 *draw = pSrcPriv->pixmap; 543 return dmxScreen; 544 } 545 } 546 } 547#endif 548 return NULL; 549} 550 551/** Get an image from the back-end server associated with \a pDrawable's 552 * screen. If \a pDrawable is a window, it must be viewable to get an 553 * image from it. If it is not viewable, then get the image from the 554 * first ancestor of \a pDrawable that is viewable. If no viewable 555 * ancestor is found, then simply return without getting an image. */ 556void dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 557 unsigned int format, unsigned long planeMask, char *pdstLine) 558{ 559 DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum]; 560 XImage *img; 561 Drawable draw; 562 563 /* Cannot get image from unviewable window */ 564 if (pDrawable->type == DRAWABLE_WINDOW) { 565 WindowPtr pWindow = (WindowPtr)pDrawable; 566 if (!pWindow->viewable) { 567 while (!pWindow->viewable && pWindow->parent) { 568 sx += pWindow->origin.x - wBorderWidth(pWindow); 569 sx += pWindow->origin.y - wBorderWidth(pWindow); 570 pWindow = pWindow->parent; 571 } 572 if (!pWindow->viewable) { 573 return; 574 } 575 } 576 DMX_GCOPS_SET_DRAWABLE(&pWindow->drawable, draw); 577 if (DMX_GCOPS_OFFSCREEN(&pWindow->drawable)) 578 return; 579 } else { 580 DMX_GCOPS_SET_DRAWABLE(pDrawable, draw); 581 if (DMX_GCOPS_OFFSCREEN(pDrawable)) { 582 /* Try to find the pixmap on a non-detached Xinerama screen */ 583 dmxScreen = dmxFindAlternatePixmap(pDrawable, &draw); 584 if (!dmxScreen) return; 585 } 586 } 587 588 img = XGetImage(dmxScreen->beDisplay, draw, 589 sx, sy, w, h, planeMask, format); 590 if (img) { 591 int len = img->bytes_per_line * img->height; 592 memmove(pdstLine, img->data, len); 593 XDestroyImage(img); 594 } 595 596 dmxSync(dmxScreen, FALSE); 597} 598 599/** Get Spans -- this function should never be called. */ 600void dmxGetSpans(DrawablePtr pDrawable, int wMax, 601 DDXPointPtr ppt, int *pwidth, int nspans, 602 char *pdstStart) 603{ 604 /* Error -- this should never happen! */ 605} 606