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#ifdef HAVE_DIX_CONFIG_H
30#include <dix-config.h>
31#endif
32
33#include "scrnintstr.h"
34#include "gcstruct.h"
35#include "pixmapstr.h"
36#include "windowstr.h"
37#include "migc.h"
38
39/* ARGSUSED */
40void
41miChangeGC(GCPtr pGC, unsigned long mask)
42{
43    return;
44}
45
46void
47miDestroyGC(GCPtr pGC)
48{
49    if (pGC->freeCompClip)
50        RegionDestroy(pGC->pCompositeClip);
51}
52
53void
54miDestroyClip(GCPtr pGC)
55{
56    if (pGC->clientClip)
57        RegionDestroy(pGC->clientClip);
58    pGC->clientClip = NULL;
59}
60
61void
62miChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
63{
64    (*pGC->funcs->DestroyClip) (pGC);
65    if (type == CT_PIXMAP) {
66        /* convert the pixmap to a region */
67        pGC->clientClip = BitmapToRegion(pGC->pScreen, (PixmapPtr) pvalue);
68        (*pGC->pScreen->DestroyPixmap) (pvalue);
69    }
70    else if (type == CT_REGION) {
71        /* stuff the region in the GC */
72        pGC->clientClip = pvalue;
73    }
74    else if (type != CT_NONE) {
75        pGC->clientClip = RegionFromRects(nrects, (xRectangle *) pvalue, type);
76        free(pvalue);
77    }
78    pGC->stateChanges |= GCClipMask;
79}
80
81void
82miCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
83{
84    if (pgcSrc->clientClip) {
85        RegionPtr prgnNew = RegionCreate(NULL, 1);
86        RegionCopy(prgnNew, (RegionPtr) (pgcSrc->clientClip));
87        (*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, prgnNew, 0);
88    } else {
89        (*pgcDst->funcs->ChangeClip) (pgcDst, CT_NONE, NULL, 0);
90    }
91}
92
93/* ARGSUSED */
94void
95miCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
96{
97    return;
98}
99
100void
101miComputeCompositeClip(GCPtr pGC, DrawablePtr pDrawable)
102{
103    if (pDrawable->type == DRAWABLE_WINDOW) {
104        WindowPtr pWin = (WindowPtr) pDrawable;
105        RegionPtr pregWin;
106        Bool freeTmpClip, freeCompClip;
107
108        if (pGC->subWindowMode == IncludeInferiors) {
109            pregWin = NotClippedByChildren(pWin);
110            freeTmpClip = TRUE;
111        }
112        else {
113            pregWin = &pWin->clipList;
114            freeTmpClip = FALSE;
115        }
116        freeCompClip = pGC->freeCompClip;
117
118        /*
119         * if there is no client clip, we can get by with just keeping the
120         * pointer we got, and remembering whether or not should destroy (or
121         * maybe re-use) it later.  this way, we avoid unnecessary copying of
122         * regions.  (this wins especially if many clients clip by children
123         * and have no client clip.)
124         */
125        if (!pGC->clientClip) {
126            if (freeCompClip)
127                RegionDestroy(pGC->pCompositeClip);
128            pGC->pCompositeClip = pregWin;
129            pGC->freeCompClip = freeTmpClip;
130        }
131        else {
132            /*
133             * we need one 'real' region to put into the composite clip. if
134             * pregWin the current composite clip are real, we can get rid of
135             * one. if pregWin is real and the current composite clip isn't,
136             * use pregWin for the composite clip. if the current composite
137             * clip is real and pregWin isn't, use the current composite
138             * clip. if neither is real, create a new region.
139             */
140
141            RegionTranslate(pGC->clientClip,
142                            pDrawable->x + pGC->clipOrg.x,
143                            pDrawable->y + pGC->clipOrg.y);
144
145            if (freeCompClip) {
146                RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
147                if (freeTmpClip)
148                    RegionDestroy(pregWin);
149            }
150            else if (freeTmpClip) {
151                RegionIntersect(pregWin, pregWin, pGC->clientClip);
152                pGC->pCompositeClip = pregWin;
153            }
154            else {
155                pGC->pCompositeClip = RegionCreate(NullBox, 0);
156                RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip);
157            }
158            pGC->freeCompClip = TRUE;
159            RegionTranslate(pGC->clientClip,
160                            -(pDrawable->x + pGC->clipOrg.x),
161                            -(pDrawable->y + pGC->clipOrg.y));
162        }
163    }                           /* end of composite clip for a window */
164    else {
165        BoxRec pixbounds;
166
167        /* XXX should we translate by drawable.x/y here ? */
168        /* If you want pixmaps in offscreen memory, yes */
169        pixbounds.x1 = pDrawable->x;
170        pixbounds.y1 = pDrawable->y;
171        pixbounds.x2 = pDrawable->x + pDrawable->width;
172        pixbounds.y2 = pDrawable->y + pDrawable->height;
173
174        if (pGC->freeCompClip) {
175            RegionReset(pGC->pCompositeClip, &pixbounds);
176        }
177        else {
178            pGC->freeCompClip = TRUE;
179            pGC->pCompositeClip = RegionCreate(&pixbounds, 1);
180        }
181
182        if (pGC->clientClip) {
183            if (pDrawable->x || pDrawable->y) {
184                RegionTranslate(pGC->clientClip,
185                                pDrawable->x + pGC->clipOrg.x,
186                                pDrawable->y + pGC->clipOrg.y);
187                RegionIntersect(pGC->pCompositeClip,
188                                pGC->pCompositeClip, pGC->clientClip);
189                RegionTranslate(pGC->clientClip,
190                                -(pDrawable->x + pGC->clipOrg.x),
191                                -(pDrawable->y + pGC->clipOrg.y));
192            }
193            else {
194                RegionTranslate(pGC->pCompositeClip,
195                                -pGC->clipOrg.x, -pGC->clipOrg.y);
196                RegionIntersect(pGC->pCompositeClip,
197                                pGC->pCompositeClip, pGC->clientClip);
198                RegionTranslate(pGC->pCompositeClip,
199                                pGC->clipOrg.x, pGC->clipOrg.y);
200            }
201        }
202    }                           /* end of composite clip for pixmap */
203}                               /* end miComputeCompositeClip */
204