1/*
2
3Copyright 1993, 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
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29
30#ifdef HAVE_DIX_CONFIG_H
31#include <dix-config.h>
32#endif
33
34#include "scrnintstr.h"
35#include "gcstruct.h"
36#include "pixmapstr.h"
37#include "windowstr.h"
38#include "migc.h"
39
40/* ARGSUSED */
41void
42miChangeGC(GCPtr pGC, unsigned long mask)
43{
44    return;
45}
46
47void
48miDestroyGC(GCPtr pGC)
49{
50    if (pGC->pRotatedPixmap)
51	(*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap);
52    if (pGC->freeCompClip)
53	RegionDestroy(pGC->pCompositeClip);
54}
55
56void
57miDestroyClip(GCPtr pGC)
58{
59    if (pGC->clientClipType == CT_NONE)
60	return;
61    else if (pGC->clientClipType == CT_PIXMAP)
62    {
63	(*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip));
64    }
65    else
66    {
67	/*
68	 * we know we'll never have a list of rectangles, since ChangeClip
69	 * immediately turns them into a region
70	 */
71	RegionDestroy(pGC->clientClip);
72    }
73    pGC->clientClip = NULL;
74    pGC->clientClipType = CT_NONE;
75}
76
77void
78miChangeClip( GCPtr pGC, int type, pointer pvalue, int nrects)
79{
80    (*pGC->funcs->DestroyClip) (pGC);
81    if (type == CT_PIXMAP)
82    {
83	/* convert the pixmap to a region */
84	pGC->clientClip = (pointer) BitmapToRegion(pGC->pScreen,
85							(PixmapPtr) pvalue);
86	(*pGC->pScreen->DestroyPixmap) (pvalue);
87    }
88    else if (type == CT_REGION)
89    {
90	/* stuff the region in the GC */
91	pGC->clientClip = pvalue;
92    }
93    else if (type != CT_NONE)
94    {
95	pGC->clientClip = (pointer) RegionFromRects(nrects,
96						      (xRectangle *) pvalue,
97								    type);
98	free(pvalue);
99    }
100    pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE;
101    pGC->stateChanges |= GCClipMask;
102}
103
104void
105miCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
106{
107    RegionPtr       prgnNew;
108
109    switch (pgcSrc->clientClipType)
110    {
111      case CT_PIXMAP:
112	((PixmapPtr) pgcSrc->clientClip)->refcnt++;
113	/* Fall through !! */
114      case CT_NONE:
115	(*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType,
116				   pgcSrc->clientClip, 0);
117	break;
118      case CT_REGION:
119	prgnNew = RegionCreate(NULL, 1);
120	RegionCopy(prgnNew, (RegionPtr) (pgcSrc->clientClip));
121	(*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0);
122	break;
123    }
124}
125
126/* ARGSUSED */
127void
128miCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
129{
130    return;
131}
132
133void
134miComputeCompositeClip( GCPtr pGC, DrawablePtr pDrawable)
135{
136    if (pDrawable->type == DRAWABLE_WINDOW)
137    {
138	WindowPtr       pWin = (WindowPtr) pDrawable;
139	RegionPtr       pregWin;
140	Bool            freeTmpClip, freeCompClip;
141
142	if (pGC->subWindowMode == IncludeInferiors)
143	{
144	    pregWin = NotClippedByChildren(pWin);
145	    freeTmpClip = TRUE;
146	}
147	else
148	{
149	    pregWin = &pWin->clipList;
150	    freeTmpClip = FALSE;
151	}
152	freeCompClip = pGC->freeCompClip;
153
154	/*
155	 * if there is no client clip, we can get by with just keeping the
156	 * pointer we got, and remembering whether or not should destroy (or
157	 * maybe re-use) it later.  this way, we avoid unnecessary copying of
158	 * regions.  (this wins especially if many clients clip by children
159	 * and have no client clip.)
160	 */
161	if (pGC->clientClipType == CT_NONE)
162	{
163	    if (freeCompClip)
164		RegionDestroy(pGC->pCompositeClip);
165	    pGC->pCompositeClip = pregWin;
166	    pGC->freeCompClip = freeTmpClip;
167	}
168	else
169	{
170	    /*
171	     * we need one 'real' region to put into the composite clip. if
172	     * pregWin the current composite clip are real, we can get rid of
173	     * one. if pregWin is real and the current composite clip isn't,
174	     * use pregWin for the composite clip. if the current composite
175	     * clip is real and pregWin isn't, use the current composite
176	     * clip. if neither is real, create a new region.
177	     */
178
179	    RegionTranslate(pGC->clientClip,
180					 pDrawable->x + pGC->clipOrg.x,
181					 pDrawable->y + pGC->clipOrg.y);
182
183	    if (freeCompClip)
184	    {
185		RegionIntersect(pGC->pCompositeClip,
186					    pregWin, pGC->clientClip);
187		if (freeTmpClip)
188		    RegionDestroy(pregWin);
189	    }
190	    else if (freeTmpClip)
191	    {
192		RegionIntersect(pregWin, pregWin, pGC->clientClip);
193		pGC->pCompositeClip = pregWin;
194	    }
195	    else
196	    {
197		pGC->pCompositeClip = RegionCreate(NullBox, 0);
198		RegionIntersect(pGC->pCompositeClip,
199				       pregWin, pGC->clientClip);
200	    }
201	    pGC->freeCompClip = TRUE;
202	    RegionTranslate(pGC->clientClip,
203					 -(pDrawable->x + pGC->clipOrg.x),
204					 -(pDrawable->y + pGC->clipOrg.y));
205	}
206    }	/* end of composite clip for a window */
207    else
208    {
209	BoxRec          pixbounds;
210
211	/* XXX should we translate by drawable.x/y here ? */
212	/* If you want pixmaps in offscreen memory, yes */
213	pixbounds.x1 = pDrawable->x;
214	pixbounds.y1 = pDrawable->y;
215	pixbounds.x2 = pDrawable->x + pDrawable->width;
216	pixbounds.y2 = pDrawable->y + pDrawable->height;
217
218	if (pGC->freeCompClip)
219	{
220	    RegionReset(pGC->pCompositeClip, &pixbounds);
221	}
222	else
223	{
224	    pGC->freeCompClip = TRUE;
225	    pGC->pCompositeClip = RegionCreate(&pixbounds, 1);
226	}
227
228	if (pGC->clientClipType == CT_REGION)
229	{
230	    if(pDrawable->x || pDrawable->y) {
231	        RegionTranslate(pGC->clientClip,
232					  pDrawable->x + pGC->clipOrg.x,
233					  pDrawable->y + pGC->clipOrg.y);
234	        RegionIntersect(pGC->pCompositeClip,
235				pGC->pCompositeClip, pGC->clientClip);
236	        RegionTranslate(pGC->clientClip,
237					  -(pDrawable->x + pGC->clipOrg.x),
238					  -(pDrawable->y + pGC->clipOrg.y));
239	    } else {
240	        RegionTranslate(pGC->pCompositeClip,
241					 -pGC->clipOrg.x, -pGC->clipOrg.y);
242	        RegionIntersect(pGC->pCompositeClip,
243				pGC->pCompositeClip, pGC->clientClip);
244	        RegionTranslate(pGC->pCompositeClip,
245					 pGC->clipOrg.x, pGC->clipOrg.y);
246	    }
247	}
248    }	/* end of composite clip for pixmap */
249} /* end miComputeCompositeClip */
250