1/*********************************************************** 2 3Copyright 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25 26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30Permission to use, copy, modify, and distribute this software and its 31documentation for any purpose and without fee is hereby granted, 32provided that the above copyright notice appear in all copies and that 33both that copyright notice and this permission notice appear in 34supporting documentation, and that the name of Digital not be 35used in advertising or publicity pertaining to distribution of the 36software without specific, written prior permission. 37 38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44SOFTWARE. 45 46******************************************************************/ 47/***************************************************************** 48 49Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 50 51Permission is hereby granted, free of charge, to any person obtaining a copy 52of this software and associated documentation files (the "Software"), to deal 53in the Software without restriction, including without limitation the rights 54to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 55copies of the Software. 56 57The above copyright notice and this permission notice shall be included in 58all copies or substantial portions of the Software. 59 60THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 63DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 64BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 65WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 66IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 67 68Except as contained in this notice, the name of Digital Equipment Corporation 69shall not be used in advertising or otherwise to promote the sale, use or other 70dealings in this Software without prior written authorization from Digital 71Equipment Corporation. 72 73******************************************************************/ 74 75 76#ifdef HAVE_DIX_CONFIG_H 77#include <dix-config.h> 78#endif 79 80#include <X11/X.h> 81#include <X11/Xproto.h> 82#include <X11/Xprotostr.h> 83 84#include "misc.h" 85#include "regionstr.h" 86#include "scrnintstr.h" 87#include "gcstruct.h" 88#include "windowstr.h" 89#include "pixmap.h" 90#include "input.h" 91 92#include "dixstruct.h" 93#include "mi.h" 94#include <X11/Xmd.h> 95 96#include "globals.h" 97 98#ifdef PANORAMIX 99#include "panoramiX.h" 100#include "panoramiXsrv.h" 101#endif 102 103/* 104 machine-independent graphics exposure code. any device that uses 105the region package can call this. 106*/ 107 108#ifndef RECTLIMIT 109#define RECTLIMIT 25 /* pick a number, any number > 8 */ 110#endif 111 112/* miHandleExposures 113 generate a region for exposures for areas that were copied from obscured or 114non-existent areas to non-obscured areas of the destination. Paint the 115background for the region, if the destination is a window. 116 117NOTE: 118 this should generally be called, even if graphicsExposures is false, 119because this is where bits get recovered from backing store. 120 121NOTE: 122 added argument 'plane' is used to indicate how exposures from backing 123store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea 124should be used, else a CopyPlane of the indicated plane will be used. The 125exposing is done by the backing store's GraphicsExpose function, of course. 126 127*/ 128 129RegionPtr 130miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 131 GCPtr pGC, int srcx, int srcy, int width, int height, 132 int dstx, int dsty, unsigned long plane) 133{ 134 RegionPtr prgnSrcClip; /* drawable-relative source clip */ 135 RegionRec rgnSrcRec; 136 RegionPtr prgnDstClip; /* drawable-relative dest clip */ 137 RegionRec rgnDstRec; 138 BoxRec srcBox; /* unclipped source */ 139 RegionRec rgnExposed; /* exposed region, calculated source- 140 relative, made dst relative to 141 intersect with visible parts of 142 dest and send events to client, 143 and then screen relative to paint 144 the window background 145 */ 146 WindowPtr pSrcWin; 147 BoxRec expBox; 148 Bool extents; 149 150 /* avoid work if we can */ 151 if (!pGC->graphicsExposures && 152 (pDstDrawable->type == DRAWABLE_PIXMAP) && 153 ((pSrcDrawable->type == DRAWABLE_PIXMAP) || 154 (((WindowPtr)pSrcDrawable)->backStorage == NULL))) 155 return NULL; 156 157 srcBox.x1 = srcx; 158 srcBox.y1 = srcy; 159 srcBox.x2 = srcx+width; 160 srcBox.y2 = srcy+height; 161 162 if (pSrcDrawable->type != DRAWABLE_PIXMAP) 163 { 164 BoxRec TsrcBox; 165 166 TsrcBox.x1 = srcx + pSrcDrawable->x; 167 TsrcBox.y1 = srcy + pSrcDrawable->y; 168 TsrcBox.x2 = TsrcBox.x1 + width; 169 TsrcBox.y2 = TsrcBox.y1 + height; 170 pSrcWin = (WindowPtr) pSrcDrawable; 171 if (pGC->subWindowMode == IncludeInferiors) 172 { 173 prgnSrcClip = NotClippedByChildren (pSrcWin); 174 if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) 175 { 176 RegionDestroy(prgnSrcClip); 177 return NULL; 178 } 179 } 180 else 181 { 182 if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN) 183 return NULL; 184 prgnSrcClip = &rgnSrcRec; 185 RegionNull(prgnSrcClip); 186 RegionCopy(prgnSrcClip, &pSrcWin->clipList); 187 } 188 RegionTranslate(prgnSrcClip, 189 -pSrcDrawable->x, -pSrcDrawable->y); 190 } 191 else 192 { 193 BoxRec box; 194 195 if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) && 196 (srcBox.x2 <= pSrcDrawable->width) && 197 (srcBox.y2 <= pSrcDrawable->height)) 198 return NULL; 199 200 box.x1 = 0; 201 box.y1 = 0; 202 box.x2 = pSrcDrawable->width; 203 box.y2 = pSrcDrawable->height; 204 prgnSrcClip = &rgnSrcRec; 205 RegionInit(prgnSrcClip, &box, 1); 206 pSrcWin = NULL; 207 } 208 209 if (pDstDrawable == pSrcDrawable) 210 { 211 prgnDstClip = prgnSrcClip; 212 } 213 else if (pDstDrawable->type != DRAWABLE_PIXMAP) 214 { 215 if (pGC->subWindowMode == IncludeInferiors) 216 { 217 prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable); 218 } 219 else 220 { 221 prgnDstClip = &rgnDstRec; 222 RegionNull(prgnDstClip); 223 RegionCopy(prgnDstClip, 224 &((WindowPtr)pDstDrawable)->clipList); 225 } 226 RegionTranslate(prgnDstClip, 227 -pDstDrawable->x, -pDstDrawable->y); 228 } 229 else 230 { 231 BoxRec box; 232 233 box.x1 = 0; 234 box.y1 = 0; 235 box.x2 = pDstDrawable->width; 236 box.y2 = pDstDrawable->height; 237 prgnDstClip = &rgnDstRec; 238 RegionInit(prgnDstClip, &box, 1); 239 } 240 241 /* drawable-relative source region */ 242 RegionInit(&rgnExposed, &srcBox, 1); 243 244 /* now get the hidden parts of the source box*/ 245 RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip); 246 247 /* move them over the destination */ 248 RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy); 249 250 /* intersect with visible areas of dest */ 251 RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip); 252 253 /* intersect with client clip region. */ 254 if (pGC->clientClipType == CT_REGION) 255 RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip); 256 257 /* 258 * If we have LOTS of rectangles, we decide to take the extents 259 * and force an exposure on that. This should require much less 260 * work overall, on both client and server. This is cheating, but 261 * isn't prohibited by the protocol ("spontaneous combustion" :-) 262 * for windows. 263 */ 264 extents = pGC->graphicsExposures && 265 (RegionNumRects(&rgnExposed) > RECTLIMIT) && 266 (pDstDrawable->type != DRAWABLE_PIXMAP); 267 if (pSrcWin) 268 { 269 RegionPtr region; 270 if (!(region = wClipShape (pSrcWin))) 271 region = wBoundingShape (pSrcWin); 272 /* 273 * If you try to CopyArea the extents of a shaped window, compacting the 274 * exposed region will undo all our work! 275 */ 276 if (extents && pSrcWin && region && 277 (RegionContainsRect(region, &srcBox) != rgnIN)) 278 extents = FALSE; 279 } 280 if (extents) 281 { 282 expBox = *RegionExtents(&rgnExposed); 283 RegionReset(&rgnExposed, &expBox); 284 } 285 if ((pDstDrawable->type != DRAWABLE_PIXMAP) && 286 (((WindowPtr)pDstDrawable)->backgroundState != None)) 287 { 288 WindowPtr pWin = (WindowPtr)pDstDrawable; 289 290 /* make the exposed area screen-relative */ 291 RegionTranslate(&rgnExposed, 292 pDstDrawable->x, pDstDrawable->y); 293 294 if (extents) 295 { 296 /* miPaintWindow doesn't clip, so we have to */ 297 RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList); 298 } 299 miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND); 300 301 if (extents) 302 { 303 RegionReset(&rgnExposed, &expBox); 304 } 305 else 306 RegionTranslate(&rgnExposed, 307 -pDstDrawable->x, -pDstDrawable->y); 308 } 309 if (prgnDstClip == &rgnDstRec) 310 { 311 RegionUninit(prgnDstClip); 312 } 313 else if (prgnDstClip != prgnSrcClip) 314 { 315 RegionDestroy(prgnDstClip); 316 } 317 318 if (prgnSrcClip == &rgnSrcRec) 319 { 320 RegionUninit(prgnSrcClip); 321 } 322 else 323 { 324 RegionDestroy(prgnSrcClip); 325 } 326 327 if (pGC->graphicsExposures) 328 { 329 /* don't look */ 330 RegionPtr exposed = RegionCreate(NullBox, 0); 331 *exposed = rgnExposed; 332 return exposed; 333 } 334 else 335 { 336 RegionUninit(&rgnExposed); 337 return NULL; 338 } 339} 340 341/* send GraphicsExpose events, or a NoExpose event, based on the region */ 342 343void 344miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable, 345 int major, int minor) 346{ 347 if (pRgn && !RegionNil(pRgn)) 348 { 349 xEvent *pEvent; 350 xEvent *pe; 351 BoxPtr pBox; 352 int i; 353 int numRects; 354 355 numRects = RegionNumRects(pRgn); 356 pBox = RegionRects(pRgn); 357 if(!(pEvent = malloc(numRects * sizeof(xEvent)))) 358 return; 359 pe = pEvent; 360 361 for (i=1; i<=numRects; i++, pe++, pBox++) 362 { 363 pe->u.u.type = GraphicsExpose; 364 pe->u.graphicsExposure.drawable = drawable; 365 pe->u.graphicsExposure.x = pBox->x1; 366 pe->u.graphicsExposure.y = pBox->y1; 367 pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; 368 pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; 369 pe->u.graphicsExposure.count = numRects - i; 370 pe->u.graphicsExposure.majorEvent = major; 371 pe->u.graphicsExposure.minorEvent = minor; 372 } 373 /* GraphicsExpose is a "critical event", which TryClientEvents 374 * handles specially. */ 375 TryClientEvents(client, NULL, pEvent, numRects, 376 (Mask)0, NoEventMask, NullGrab); 377 free(pEvent); 378 } 379 else 380 { 381 xEvent event; 382 memset(&event, 0, sizeof(xEvent)); 383 event.u.u.type = NoExpose; 384 event.u.noExposure.drawable = drawable; 385 event.u.noExposure.majorEvent = major; 386 event.u.noExposure.minorEvent = minor; 387 WriteEventsToClient(client, 1, &event); 388 } 389} 390 391 392void 393miSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy) 394{ 395 BoxPtr pBox; 396 int numRects; 397 xEvent *pEvent, *pe; 398 int i; 399 400 pBox = RegionRects(pRgn); 401 numRects = RegionNumRects(pRgn); 402 if(!(pEvent = calloc(1, numRects * sizeof(xEvent)))) 403 return; 404 405 for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++) 406 { 407 pe->u.u.type = Expose; 408 pe->u.expose.window = pWin->drawable.id; 409 pe->u.expose.x = pBox->x1 - dx; 410 pe->u.expose.y = pBox->y1 - dy; 411 pe->u.expose.width = pBox->x2 - pBox->x1; 412 pe->u.expose.height = pBox->y2 - pBox->y1; 413 pe->u.expose.count = i; 414 } 415 416#ifdef PANORAMIX 417 if(!noPanoramiXExtension) { 418 int scrnum = pWin->drawable.pScreen->myNum; 419 int x = 0, y = 0; 420 XID realWin = 0; 421 422 if(!pWin->parent) { 423 x = screenInfo.screens[scrnum]->x; 424 y = screenInfo.screens[scrnum]->y; 425 pWin = screenInfo.screens[0]->root; 426 realWin = pWin->drawable.id; 427 } else if (scrnum) { 428 PanoramiXRes *win; 429 win = PanoramiXFindIDByScrnum(XRT_WINDOW, 430 pWin->drawable.id, scrnum); 431 if(!win) { 432 free(pEvent); 433 return; 434 } 435 realWin = win->info[0].id; 436 dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess); 437 } 438 if(x || y || scrnum) 439 for (i = 0; i < numRects; i++) { 440 pEvent[i].u.expose.window = realWin; 441 pEvent[i].u.expose.x += x; 442 pEvent[i].u.expose.y += y; 443 } 444 } 445#endif 446 447 DeliverEvents(pWin, pEvent, numRects, NullWindow); 448 449 free(pEvent); 450} 451 452void 453miWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed) 454{ 455 RegionPtr exposures = prgn; 456 if ((prgn && !RegionNil(prgn)) || 457 (exposures && !RegionNil(exposures)) || other_exposed) 458 { 459 RegionRec expRec; 460 int clientInterested; 461 462 /* 463 * Restore from backing-store FIRST. 464 */ 465 clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask; 466 if (other_exposed) 467 { 468 if (exposures) 469 { 470 RegionUnion(other_exposed, 471 exposures, 472 other_exposed); 473 if (exposures != prgn) 474 RegionDestroy(exposures); 475 } 476 exposures = other_exposed; 477 } 478 if (clientInterested && exposures && (RegionNumRects(exposures) > RECTLIMIT)) 479 { 480 /* 481 * If we have LOTS of rectangles, we decide to take the extents 482 * and force an exposure on that. This should require much less 483 * work overall, on both client and server. This is cheating, but 484 * isn't prohibited by the protocol ("spontaneous combustion" :-). 485 */ 486 BoxRec box; 487 488 box = *RegionExtents(exposures); 489 if (exposures == prgn) { 490 exposures = &expRec; 491 RegionInit(exposures, &box, 1); 492 RegionReset(prgn, &box); 493 } else { 494 RegionReset(exposures, &box); 495 RegionUnion(prgn, prgn, exposures); 496 } 497 /* miPaintWindow doesn't clip, so we have to */ 498 RegionIntersect(prgn, prgn, &pWin->clipList); 499 } 500 if (prgn && !RegionNil(prgn)) 501 miPaintWindow(pWin, prgn, PW_BACKGROUND); 502 if (clientInterested && exposures && !RegionNil(exposures)) 503 miSendExposures(pWin, exposures, 504 pWin->drawable.x, pWin->drawable.y); 505 if (exposures == &expRec) 506 { 507 RegionUninit(exposures); 508 } 509 else if (exposures && exposures != prgn && exposures != other_exposed) 510 RegionDestroy(exposures); 511 if (prgn) 512 RegionEmpty(prgn); 513 } 514 else if (exposures && exposures != prgn) 515 RegionDestroy(exposures); 516} 517 518#ifdef ROOTLESS 519/* Ugly, ugly, but we lost our hooks into miPaintWindow... =/ */ 520void RootlessSetPixmapOfAncestors(WindowPtr pWin); 521void RootlessStartDrawing(WindowPtr pWin); 522void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn); 523Bool IsFramedWindow(WindowPtr pWin); 524#endif 525 526void 527miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) 528{ 529 ScreenPtr pScreen = pWin->drawable.pScreen; 530 ChangeGCVal gcval[6]; 531 BITS32 gcmask; 532 GCPtr pGC; 533 int i; 534 BoxPtr pbox; 535 xRectangle *prect; 536 int numRects; 537 /* 538 * Distance from screen to destination drawable, use this 539 * to adjust rendering coordinates which come in in screen space 540 */ 541 int draw_x_off, draw_y_off; 542 /* 543 * Tile offset for drawing; these need to align the tile 544 * to the appropriate window origin 545 */ 546 int tile_x_off, tile_y_off; 547 PixUnion fill; 548 Bool solid = TRUE; 549 DrawablePtr drawable = &pWin->drawable; 550 551#ifdef ROOTLESS 552 if(!drawable || drawable->type == UNDRAWABLE_WINDOW) 553 return; 554 555 if(IsFramedWindow(pWin)) { 556 RootlessStartDrawing(pWin); 557 RootlessDamageRegion(pWin, prgn); 558 559 if(pWin->backgroundState == ParentRelative) { 560 if((what == PW_BACKGROUND) || 561 (what == PW_BORDER && !pWin->borderIsPixel)) 562 RootlessSetPixmapOfAncestors(pWin); 563 } 564 } 565#endif 566 567 if (what == PW_BACKGROUND) 568 { 569 while (pWin->backgroundState == ParentRelative) 570 pWin = pWin->parent; 571 572 draw_x_off = drawable->x; 573 draw_y_off = drawable->y; 574 575 tile_x_off = pWin->drawable.x - draw_x_off; 576 tile_y_off = pWin->drawable.y - draw_y_off; 577 fill = pWin->background; 578 switch (pWin->backgroundState) { 579 case None: 580 return; 581 case BackgroundPixmap: 582 solid = FALSE; 583 break; 584 } 585 } 586 else 587 { 588 PixmapPtr pixmap; 589 590 tile_x_off = drawable->x; 591 tile_y_off = drawable->y; 592 593 /* servers without pixmaps draw their own borders */ 594 if (!pScreen->GetWindowPixmap) 595 return; 596 pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable); 597 drawable = &pixmap->drawable; 598#ifdef COMPOSITE 599 draw_x_off = pixmap->screen_x; 600 draw_y_off = pixmap->screen_y; 601 tile_x_off -= draw_x_off; 602 tile_y_off -= draw_y_off; 603#else 604 draw_x_off = 0; 605 draw_y_off = 0; 606#endif 607 fill = pWin->border; 608 solid = pWin->borderIsPixel; 609 } 610 611 gcval[0].val = GXcopy; 612 gcmask = GCFunction; 613 614#ifdef ROOTLESS_SAFEALPHA 615/* Bit mask for alpha channel with a particular number of bits per 616 * pixel. Note that we only care for 32bpp data. Mac OS X uses planar 617 * alpha for 16bpp. 618 */ 619#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0) 620#endif 621 622 if (solid) 623 { 624#ifdef ROOTLESS_SAFEALPHA 625 gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel); 626#else 627 gcval[1].val = fill.pixel; 628#endif 629 gcval[2].val = FillSolid; 630 gcmask |= GCForeground | GCFillStyle; 631 } 632 else 633 { 634 int c=1; 635#ifdef ROOTLESS_SAFEALPHA 636 gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel); 637 gcmask |= GCPlaneMask; 638#endif 639 gcval[c++].val = FillTiled; 640 gcval[c++].ptr = (pointer)fill.pixmap; 641 gcval[c++].val = tile_x_off; 642 gcval[c++].val = tile_y_off; 643 gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; 644 } 645 646 prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle)); 647 if (!prect) 648 return; 649 650 pGC = GetScratchGC(drawable->depth, drawable->pScreen); 651 if (!pGC) 652 { 653 free(prect); 654 return; 655 } 656 657 ChangeGC (NullClient, pGC, gcmask, gcval); 658 ValidateGC (drawable, pGC); 659 660 numRects = RegionNumRects(prgn); 661 pbox = RegionRects(prgn); 662 for (i= numRects; --i >= 0; pbox++, prect++) 663 { 664 prect->x = pbox->x1 - draw_x_off; 665 prect->y = pbox->y1 - draw_y_off; 666 prect->width = pbox->x2 - pbox->x1; 667 prect->height = pbox->y2 - pbox->y1; 668 } 669 prect -= numRects; 670 (*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect); 671 free(prect); 672 673 FreeScratchGC(pGC); 674} 675 676 677/* MICLEARDRAWABLE -- sets the entire drawable to the background color of 678 * the GC. Useful when we have a scratch drawable and need to initialize 679 * it. */ 680void 681miClearDrawable(DrawablePtr pDraw, GCPtr pGC) 682{ 683 ChangeGCVal fg, bg; 684 xRectangle rect; 685 686 fg.val = pGC->fgPixel; 687 bg.val = pGC->bgPixel; 688 rect.x = 0; 689 rect.y = 0; 690 rect.width = pDraw->width; 691 rect.height = pDraw->height; 692 ChangeGC(NullClient, pGC, GCForeground, &bg); 693 ValidateGC(pDraw, pGC); 694 (*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect); 695 ChangeGC(NullClient, pGC, GCForeground, &fg); 696 ValidateGC(pDraw, pGC); 697} 698