Git init
[framework/uifw/xorg/server/xorg-server.git] / mi / migc.c
1 /*
2
3 Copyright 1993, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from 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 */
41 void
42 miChangeGC(GCPtr pGC, unsigned long mask)
43 {
44     return;
45 }
46
47 void
48 miDestroyGC(GCPtr pGC)
49 {
50     if (pGC->pRotatedPixmap)
51         (*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap);
52     if (pGC->freeCompClip)
53         RegionDestroy(pGC->pCompositeClip);
54 }
55
56 void
57 miDestroyClip(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
77 void
78 miChangeClip( 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
104 void
105 miCopyClip(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 */
127 void
128 miCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
129 {
130     return;
131 }
132
133 void
134 miComputeCompositeClip( 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 */