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