1 /* $XConsortium: migc.c,v 1.4 94/04/17 20:27:36 dpw Exp $ */
4 Copyright (c) 1993 X Consortium
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 the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of the X Consortium shall
26 not be used in advertising or otherwise to promote the sale, use or
27 other dealings in this Software without prior written authorization
28 from the X Consortium.
33 #include "scrnintstr.h"
35 #include "pixmapstr.h"
36 #include "windowstr.h"
39 /* This structure has to line up with the mfb and cfb gc private structures so
40 * that when it is superimposed on them, the three fields that migc.c needs to
41 * see will be accessed correctly. I know this is not beautiful, but it seemed
42 * better than all the code duplication in cfb and mfb.
49 unsigned freeCompClip:1;
50 PixmapPtr pRotatedPixmap;
51 RegionPtr pCompositeClip;
54 static int miGCPrivateIndex;
57 miRegisterGCPrivateIndex(gcindex)
60 miGCPrivateIndex = gcindex;
78 pPriv = (miPrivGC *) (pGC->devPrivates[miGCPrivateIndex].ptr);
79 if (pPriv->pRotatedPixmap)
80 (*pGC->pScreen->DestroyPixmap) (pPriv->pRotatedPixmap);
81 if (pPriv->freeCompClip)
82 REGION_DESTROY(pGC->pScreen, pPriv->pCompositeClip);
83 miDestroyGCOps(pGC->ops);
87 * create a private op array for a gc
91 miCreateGCOps(prototype)
95 extern Bool Must_have_memory;
97 /* XXX */ Must_have_memory = TRUE;
98 ret = (GCOpsPtr) xalloc(sizeof(GCOps));
99 /* XXX */ Must_have_memory = FALSE;
103 ret->devPrivate.val = 1;
111 if (ops->devPrivate.val)
120 if (pGC->clientClipType == CT_NONE)
122 else if (pGC->clientClipType == CT_PIXMAP)
124 (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip));
129 * we know we'll never have a list of rectangles, since ChangeClip
130 * immediately turns them into a region
132 REGION_DESTROY(pGC->pScreen, pGC->clientClip);
134 pGC->clientClip = NULL;
135 pGC->clientClipType = CT_NONE;
139 miChangeClip(pGC, type, pvalue, nrects)
145 (*pGC->funcs->DestroyClip) (pGC);
146 if (type == CT_PIXMAP)
148 /* convert the pixmap to a region */
149 pGC->clientClip = (pointer) BITMAP_TO_REGION(pGC->pScreen,
151 (*pGC->pScreen->DestroyPixmap) (pvalue);
153 else if (type == CT_REGION)
155 /* stuff the region in the GC */
156 pGC->clientClip = pvalue;
158 else if (type != CT_NONE)
160 pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nrects,
161 (xRectangle *) pvalue,
165 pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE;
166 pGC->stateChanges |= GCClipMask;
170 miCopyClip(pgcDst, pgcSrc)
171 GCPtr pgcDst, pgcSrc;
175 switch (pgcSrc->clientClipType)
178 ((PixmapPtr) pgcSrc->clientClip)->refcnt++;
179 /* Fall through !! */
181 (*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType,
182 pgcSrc->clientClip, 0);
185 prgnNew = REGION_CREATE(pgcSrc->pScreen, NULL, 1);
186 REGION_COPY(pgcDst->pScreen, prgnNew,
187 (RegionPtr) (pgcSrc->clientClip));
188 (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (pointer) prgnNew, 0);
195 miCopyGC(pGCSrc, changes, pGCDst)
197 unsigned long changes;
204 miComputeCompositeClip(pGC, pDrawable)
206 DrawablePtr pDrawable;
208 ScreenPtr pScreen = pGC->pScreen;
209 miPrivGC *devPriv = (miPrivGC *) (pGC->devPrivates[miGCPrivateIndex].ptr);
211 if (pDrawable->type == DRAWABLE_WINDOW)
213 WindowPtr pWin = (WindowPtr) pDrawable;
215 Bool freeTmpClip, freeCompClip;
217 if (pGC->subWindowMode == IncludeInferiors)
219 pregWin = NotClippedByChildren(pWin);
224 pregWin = &pWin->clipList;
227 freeCompClip = devPriv->freeCompClip;
230 * if there is no client clip, we can get by with just keeping the
231 * pointer we got, and remembering whether or not should destroy (or
232 * maybe re-use) it later. this way, we avoid unnecessary copying of
233 * regions. (this wins especially if many clients clip by children
234 * and have no client clip.)
236 if (pGC->clientClipType == CT_NONE)
239 REGION_DESTROY(pScreen, devPriv->pCompositeClip);
240 devPriv->pCompositeClip = pregWin;
241 devPriv->freeCompClip = freeTmpClip;
246 * we need one 'real' region to put into the composite clip. if
247 * pregWin the current composite clip are real, we can get rid of
248 * one. if pregWin is real and the current composite clip isn't,
249 * use pregWin for the composite clip. if the current composite
250 * clip is real and pregWin isn't, use the current composite
251 * clip. if neither is real, create a new region.
254 REGION_TRANSLATE(pScreen, pGC->clientClip,
255 pDrawable->x + pGC->clipOrg.x,
256 pDrawable->y + pGC->clipOrg.y);
260 REGION_INTERSECT(pGC->pScreen, devPriv->pCompositeClip,
261 pregWin, pGC->clientClip);
263 REGION_DESTROY(pScreen, pregWin);
265 else if (freeTmpClip)
267 REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
268 devPriv->pCompositeClip = pregWin;
272 devPriv->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
273 REGION_INTERSECT(pScreen, devPriv->pCompositeClip,
274 pregWin, pGC->clientClip);
276 devPriv->freeCompClip = TRUE;
277 REGION_TRANSLATE(pScreen, pGC->clientClip,
278 -(pDrawable->x + pGC->clipOrg.x),
279 -(pDrawable->y + pGC->clipOrg.y));
281 } /* end of composite clip for a window */
286 /* XXX should we translate by drawable.x/y here ? */
289 pixbounds.x2 = pDrawable->width;
290 pixbounds.y2 = pDrawable->height;
292 if (devPriv->freeCompClip)
294 REGION_RESET(pScreen, devPriv->pCompositeClip, &pixbounds);
298 devPriv->freeCompClip = TRUE;
299 devPriv->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
302 if (pGC->clientClipType == CT_REGION)
304 REGION_TRANSLATE(pScreen, devPriv->pCompositeClip,
305 -pGC->clipOrg.x, -pGC->clipOrg.y);
306 REGION_INTERSECT(pScreen, devPriv->pCompositeClip,
307 devPriv->pCompositeClip, pGC->clientClip);
308 REGION_TRANSLATE(pScreen, devPriv->pCompositeClip,
309 pGC->clipOrg.x, pGC->clipOrg.y);
311 } /* end of composite clip for pixmap */
312 } /* end miComputeCompositeClip */