1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun Copyright 1987, 1998 The Open Group
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun All Rights Reserved
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
48*4882a593Smuzhiyun #include <dix-config.h>
49*4882a593Smuzhiyun #endif
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #include <X11/X.h>
52*4882a593Smuzhiyun #include <X11/Xmd.h>
53*4882a593Smuzhiyun #include <X11/Xproto.h>
54*4882a593Smuzhiyun #include "misc.h"
55*4882a593Smuzhiyun #include "resource.h"
56*4882a593Smuzhiyun #include "gcstruct.h"
57*4882a593Smuzhiyun #include "pixmapstr.h"
58*4882a593Smuzhiyun #include "dixfontstr.h"
59*4882a593Smuzhiyun #include "scrnintstr.h"
60*4882a593Smuzhiyun #include "region.h"
61*4882a593Smuzhiyun #include "dixstruct.h"
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun #include "privates.h"
64*4882a593Smuzhiyun #include "dix.h"
65*4882a593Smuzhiyun #include "xace.h"
66*4882a593Smuzhiyun #include <assert.h>
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun extern FontPtr defaultFont;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun static Bool CreateDefaultTile(GCPtr pGC);
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun static unsigned char DefaultDash[2] = { 4, 4 };
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun void
ValidateGC(DrawablePtr pDraw,GC * pGC)75*4882a593Smuzhiyun ValidateGC(DrawablePtr pDraw, GC * pGC)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw);
78*4882a593Smuzhiyun pGC->stateChanges = 0;
79*4882a593Smuzhiyun pGC->serialNumber = pDraw->serialNumber;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /*
83*4882a593Smuzhiyun * ChangeGC/ChangeGCXIDs:
84*4882a593Smuzhiyun *
85*4882a593Smuzhiyun * The client performing the gc change must be passed so that access
86*4882a593Smuzhiyun * checks can be performed on any tiles, stipples, or fonts that are
87*4882a593Smuzhiyun * specified. ddxen can call this too; they should normally pass
88*4882a593Smuzhiyun * NullClient for the client since any access checking should have
89*4882a593Smuzhiyun * already been done at a higher level.
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * If you have any XIDs, you must use ChangeGCXIDs:
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun * CARD32 v[2];
94*4882a593Smuzhiyun * v[0] = FillTiled;
95*4882a593Smuzhiyun * v[1] = pid;
96*4882a593Smuzhiyun * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v);
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun * However, if you need to pass a pointer to a pixmap or font, you must
99*4882a593Smuzhiyun * use ChangeGC:
100*4882a593Smuzhiyun *
101*4882a593Smuzhiyun * ChangeGCVal v[2];
102*4882a593Smuzhiyun * v[0].val = FillTiled;
103*4882a593Smuzhiyun * v[1].ptr = pPixmap;
104*4882a593Smuzhiyun * ChangeGC(client, pGC, GCFillStyle|GCTile, v);
105*4882a593Smuzhiyun *
106*4882a593Smuzhiyun * If you have neither XIDs nor pointers, you can use either function,
107*4882a593Smuzhiyun * but ChangeGC will do less work.
108*4882a593Smuzhiyun *
109*4882a593Smuzhiyun * ChangeGCVal v[2];
110*4882a593Smuzhiyun * v[0].val = foreground;
111*4882a593Smuzhiyun * v[1].val = background;
112*4882a593Smuzhiyun * ChangeGC(client, pGC, GCForeground|GCBackground, v);
113*4882a593Smuzhiyun */
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun #define NEXTVAL(_type, _var) { \
116*4882a593Smuzhiyun _var = (_type)(pUnion->val); pUnion++; \
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun #define NEXT_PTR(_type, _var) { \
120*4882a593Smuzhiyun _var = (_type)pUnion->ptr; pUnion++; }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun int
ChangeGC(ClientPtr client,GC * pGC,BITS32 mask,ChangeGCValPtr pUnion)123*4882a593Smuzhiyun ChangeGC(ClientPtr client, GC * pGC, BITS32 mask, ChangeGCValPtr pUnion)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun BITS32 index2;
126*4882a593Smuzhiyun int error = 0;
127*4882a593Smuzhiyun PixmapPtr pPixmap;
128*4882a593Smuzhiyun BITS32 maskQ;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun assert(pUnion);
131*4882a593Smuzhiyun pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun maskQ = mask; /* save these for when we walk the GCque */
134*4882a593Smuzhiyun while (mask && !error) {
135*4882a593Smuzhiyun index2 = (BITS32) lowbit(mask);
136*4882a593Smuzhiyun mask &= ~index2;
137*4882a593Smuzhiyun pGC->stateChanges |= index2;
138*4882a593Smuzhiyun switch (index2) {
139*4882a593Smuzhiyun case GCFunction:
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun CARD8 newalu;
142*4882a593Smuzhiyun NEXTVAL(CARD8, newalu);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun if (newalu <= GXset)
145*4882a593Smuzhiyun pGC->alu = newalu;
146*4882a593Smuzhiyun else {
147*4882a593Smuzhiyun if (client)
148*4882a593Smuzhiyun client->errorValue = newalu;
149*4882a593Smuzhiyun error = BadValue;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun break;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun case GCPlaneMask:
154*4882a593Smuzhiyun NEXTVAL(unsigned long, pGC->planemask);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun break;
157*4882a593Smuzhiyun case GCForeground:
158*4882a593Smuzhiyun NEXTVAL(unsigned long, pGC->fgPixel);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /*
161*4882a593Smuzhiyun * this is for CreateGC
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun if (!pGC->tileIsPixel && !pGC->tile.pixmap) {
164*4882a593Smuzhiyun pGC->tileIsPixel = TRUE;
165*4882a593Smuzhiyun pGC->tile.pixel = pGC->fgPixel;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun break;
168*4882a593Smuzhiyun case GCBackground:
169*4882a593Smuzhiyun NEXTVAL(unsigned long, pGC->bgPixel);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun break;
172*4882a593Smuzhiyun case GCLineWidth: /* ??? line width is a CARD16 */
173*4882a593Smuzhiyun NEXTVAL(CARD16, pGC->lineWidth);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun break;
176*4882a593Smuzhiyun case GCLineStyle:
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun unsigned int newlinestyle;
179*4882a593Smuzhiyun NEXTVAL(unsigned int, newlinestyle);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (newlinestyle <= LineDoubleDash)
182*4882a593Smuzhiyun pGC->lineStyle = newlinestyle;
183*4882a593Smuzhiyun else {
184*4882a593Smuzhiyun if (client)
185*4882a593Smuzhiyun client->errorValue = newlinestyle;
186*4882a593Smuzhiyun error = BadValue;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun break;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun case GCCapStyle:
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun unsigned int newcapstyle;
193*4882a593Smuzhiyun NEXTVAL(unsigned int, newcapstyle);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun if (newcapstyle <= CapProjecting)
196*4882a593Smuzhiyun pGC->capStyle = newcapstyle;
197*4882a593Smuzhiyun else {
198*4882a593Smuzhiyun if (client)
199*4882a593Smuzhiyun client->errorValue = newcapstyle;
200*4882a593Smuzhiyun error = BadValue;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun break;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun case GCJoinStyle:
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun unsigned int newjoinstyle;
207*4882a593Smuzhiyun NEXTVAL(unsigned int, newjoinstyle);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (newjoinstyle <= JoinBevel)
210*4882a593Smuzhiyun pGC->joinStyle = newjoinstyle;
211*4882a593Smuzhiyun else {
212*4882a593Smuzhiyun if (client)
213*4882a593Smuzhiyun client->errorValue = newjoinstyle;
214*4882a593Smuzhiyun error = BadValue;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun case GCFillStyle:
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun unsigned int newfillstyle;
221*4882a593Smuzhiyun NEXTVAL(unsigned int, newfillstyle);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (newfillstyle <= FillOpaqueStippled)
224*4882a593Smuzhiyun pGC->fillStyle = newfillstyle;
225*4882a593Smuzhiyun else {
226*4882a593Smuzhiyun if (client)
227*4882a593Smuzhiyun client->errorValue = newfillstyle;
228*4882a593Smuzhiyun error = BadValue;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun break;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun case GCFillRule:
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun unsigned int newfillrule;
235*4882a593Smuzhiyun NEXTVAL(unsigned int, newfillrule);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun if (newfillrule <= WindingRule)
238*4882a593Smuzhiyun pGC->fillRule = newfillrule;
239*4882a593Smuzhiyun else {
240*4882a593Smuzhiyun if (client)
241*4882a593Smuzhiyun client->errorValue = newfillrule;
242*4882a593Smuzhiyun error = BadValue;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun break;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun case GCTile:
247*4882a593Smuzhiyun NEXT_PTR(PixmapPtr, pPixmap);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if ((pPixmap->drawable.depth != pGC->depth) ||
250*4882a593Smuzhiyun (pPixmap->drawable.pScreen != pGC->pScreen)) {
251*4882a593Smuzhiyun error = BadMatch;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun else {
254*4882a593Smuzhiyun pPixmap->refcnt++;
255*4882a593Smuzhiyun if (!pGC->tileIsPixel)
256*4882a593Smuzhiyun (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap);
257*4882a593Smuzhiyun pGC->tileIsPixel = FALSE;
258*4882a593Smuzhiyun pGC->tile.pixmap = pPixmap;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun break;
261*4882a593Smuzhiyun case GCStipple:
262*4882a593Smuzhiyun NEXT_PTR(PixmapPtr, pPixmap);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (pPixmap && ((pPixmap->drawable.depth != 1) ||
265*4882a593Smuzhiyun (pPixmap->drawable.pScreen != pGC->pScreen)))
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun error = BadMatch;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun else {
270*4882a593Smuzhiyun if (pPixmap)
271*4882a593Smuzhiyun pPixmap->refcnt++;
272*4882a593Smuzhiyun if (pGC->stipple)
273*4882a593Smuzhiyun (*pGC->pScreen->DestroyPixmap) (pGC->stipple);
274*4882a593Smuzhiyun pGC->stipple = pPixmap;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun break;
277*4882a593Smuzhiyun case GCTileStipXOrigin:
278*4882a593Smuzhiyun NEXTVAL(INT16, pGC->patOrg.x);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun break;
281*4882a593Smuzhiyun case GCTileStipYOrigin:
282*4882a593Smuzhiyun NEXTVAL(INT16, pGC->patOrg.y);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun break;
285*4882a593Smuzhiyun case GCFont:
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun FontPtr pFont;
288*4882a593Smuzhiyun NEXT_PTR(FontPtr, pFont);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun pFont->refcnt++;
291*4882a593Smuzhiyun if (pGC->font)
292*4882a593Smuzhiyun CloseFont(pGC->font, (Font) 0);
293*4882a593Smuzhiyun pGC->font = pFont;
294*4882a593Smuzhiyun break;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun case GCSubwindowMode:
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun unsigned int newclipmode;
299*4882a593Smuzhiyun NEXTVAL(unsigned int, newclipmode);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (newclipmode <= IncludeInferiors)
302*4882a593Smuzhiyun pGC->subWindowMode = newclipmode;
303*4882a593Smuzhiyun else {
304*4882a593Smuzhiyun if (client)
305*4882a593Smuzhiyun client->errorValue = newclipmode;
306*4882a593Smuzhiyun error = BadValue;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun break;
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun case GCGraphicsExposures:
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun unsigned int newge;
313*4882a593Smuzhiyun NEXTVAL(unsigned int, newge);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (newge <= xTrue)
316*4882a593Smuzhiyun pGC->graphicsExposures = newge;
317*4882a593Smuzhiyun else {
318*4882a593Smuzhiyun if (client)
319*4882a593Smuzhiyun client->errorValue = newge;
320*4882a593Smuzhiyun error = BadValue;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun break;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun case GCClipXOrigin:
325*4882a593Smuzhiyun NEXTVAL(INT16, pGC->clipOrg.x);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun break;
328*4882a593Smuzhiyun case GCClipYOrigin:
329*4882a593Smuzhiyun NEXTVAL(INT16, pGC->clipOrg.y);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun case GCClipMask:
333*4882a593Smuzhiyun NEXT_PTR(PixmapPtr, pPixmap);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (pPixmap) {
336*4882a593Smuzhiyun if ((pPixmap->drawable.depth != 1) ||
337*4882a593Smuzhiyun (pPixmap->drawable.pScreen != pGC->pScreen)) {
338*4882a593Smuzhiyun error = BadMatch;
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun pPixmap->refcnt++;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun (*pGC->funcs->ChangeClip) (pGC, pPixmap ? CT_PIXMAP : CT_NONE,
344*4882a593Smuzhiyun (void *) pPixmap, 0);
345*4882a593Smuzhiyun break;
346*4882a593Smuzhiyun case GCDashOffset:
347*4882a593Smuzhiyun NEXTVAL(INT16, pGC->dashOffset);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun case GCDashList:
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun CARD8 newdash;
353*4882a593Smuzhiyun NEXTVAL(CARD8, newdash);
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (newdash == 4) {
356*4882a593Smuzhiyun if (pGC->dash != DefaultDash) {
357*4882a593Smuzhiyun free(pGC->dash);
358*4882a593Smuzhiyun pGC->numInDashList = 2;
359*4882a593Smuzhiyun pGC->dash = DefaultDash;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun else if (newdash != 0) {
363*4882a593Smuzhiyun unsigned char *dash;
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun dash = malloc(2 * sizeof(unsigned char));
366*4882a593Smuzhiyun if (dash) {
367*4882a593Smuzhiyun if (pGC->dash != DefaultDash)
368*4882a593Smuzhiyun free(pGC->dash);
369*4882a593Smuzhiyun pGC->numInDashList = 2;
370*4882a593Smuzhiyun pGC->dash = dash;
371*4882a593Smuzhiyun dash[0] = newdash;
372*4882a593Smuzhiyun dash[1] = newdash;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun else
375*4882a593Smuzhiyun error = BadAlloc;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun else {
378*4882a593Smuzhiyun if (client)
379*4882a593Smuzhiyun client->errorValue = newdash;
380*4882a593Smuzhiyun error = BadValue;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun break;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun case GCArcMode:
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun unsigned int newarcmode;
387*4882a593Smuzhiyun NEXTVAL(unsigned int, newarcmode);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun if (newarcmode <= ArcPieSlice)
390*4882a593Smuzhiyun pGC->arcMode = newarcmode;
391*4882a593Smuzhiyun else {
392*4882a593Smuzhiyun if (client)
393*4882a593Smuzhiyun client->errorValue = newarcmode;
394*4882a593Smuzhiyun error = BadValue;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun default:
399*4882a593Smuzhiyun if (client)
400*4882a593Smuzhiyun client->errorValue = maskQ;
401*4882a593Smuzhiyun error = BadValue;
402*4882a593Smuzhiyun break;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun } /* end while mask && !error */
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) {
407*4882a593Smuzhiyun if (!CreateDefaultTile(pGC)) {
408*4882a593Smuzhiyun pGC->fillStyle = FillSolid;
409*4882a593Smuzhiyun error = BadAlloc;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun (*pGC->funcs->ChangeGC) (pGC, maskQ);
413*4882a593Smuzhiyun return error;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun #undef NEXTVAL
417*4882a593Smuzhiyun #undef NEXT_PTR
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun static const struct {
420*4882a593Smuzhiyun BITS32 mask;
421*4882a593Smuzhiyun RESTYPE type;
422*4882a593Smuzhiyun Mask access_mode;
423*4882a593Smuzhiyun } xidfields[] = {
424*4882a593Smuzhiyun {GCTile, RT_PIXMAP, DixReadAccess},
425*4882a593Smuzhiyun {GCStipple, RT_PIXMAP, DixReadAccess},
426*4882a593Smuzhiyun {GCFont, RT_FONT, DixUseAccess},
427*4882a593Smuzhiyun {GCClipMask, RT_PIXMAP, DixReadAccess},
428*4882a593Smuzhiyun };
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun int
ChangeGCXIDs(ClientPtr client,GC * pGC,BITS32 mask,CARD32 * pC32)431*4882a593Smuzhiyun ChangeGCXIDs(ClientPtr client, GC * pGC, BITS32 mask, CARD32 *pC32)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun ChangeGCVal vals[GCLastBit + 1];
434*4882a593Smuzhiyun int i;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (mask & ~GCAllBits) {
437*4882a593Smuzhiyun client->errorValue = mask;
438*4882a593Smuzhiyun return BadValue;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun for (i = Ones(mask); i--;)
441*4882a593Smuzhiyun vals[i].val = pC32[i];
442*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(xidfields); ++i) {
443*4882a593Smuzhiyun int offset, rc;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun if (!(mask & xidfields[i].mask))
446*4882a593Smuzhiyun continue;
447*4882a593Smuzhiyun offset = Ones(mask & (xidfields[i].mask - 1));
448*4882a593Smuzhiyun if (xidfields[i].mask == GCClipMask && vals[offset].val == None) {
449*4882a593Smuzhiyun vals[offset].ptr = NullPixmap;
450*4882a593Smuzhiyun continue;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val,
453*4882a593Smuzhiyun xidfields[i].type, client,
454*4882a593Smuzhiyun xidfields[i].access_mode);
455*4882a593Smuzhiyun if (rc != Success) {
456*4882a593Smuzhiyun client->errorValue = vals[offset].val;
457*4882a593Smuzhiyun return rc;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun return ChangeGC(client, pGC, mask, vals);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun static GCPtr
NewGCObject(ScreenPtr pScreen,int depth)464*4882a593Smuzhiyun NewGCObject(ScreenPtr pScreen, int depth)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun GCPtr pGC;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun pGC = dixAllocateScreenObjectWithPrivates(pScreen, GC, PRIVATE_GC);
469*4882a593Smuzhiyun if (!pGC) {
470*4882a593Smuzhiyun return (GCPtr) NULL;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun pGC->pScreen = pScreen;
474*4882a593Smuzhiyun pGC->depth = depth;
475*4882a593Smuzhiyun pGC->alu = GXcopy; /* dst <- src */
476*4882a593Smuzhiyun pGC->planemask = ~0;
477*4882a593Smuzhiyun pGC->serialNumber = 0;
478*4882a593Smuzhiyun pGC->funcs = 0;
479*4882a593Smuzhiyun pGC->fgPixel = 0;
480*4882a593Smuzhiyun pGC->bgPixel = 1;
481*4882a593Smuzhiyun pGC->lineWidth = 0;
482*4882a593Smuzhiyun pGC->lineStyle = LineSolid;
483*4882a593Smuzhiyun pGC->capStyle = CapButt;
484*4882a593Smuzhiyun pGC->joinStyle = JoinMiter;
485*4882a593Smuzhiyun pGC->fillStyle = FillSolid;
486*4882a593Smuzhiyun pGC->fillRule = EvenOddRule;
487*4882a593Smuzhiyun pGC->arcMode = ArcPieSlice;
488*4882a593Smuzhiyun pGC->tile.pixel = 0;
489*4882a593Smuzhiyun pGC->tile.pixmap = NullPixmap;
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun pGC->tileIsPixel = TRUE;
492*4882a593Smuzhiyun pGC->patOrg.x = 0;
493*4882a593Smuzhiyun pGC->patOrg.y = 0;
494*4882a593Smuzhiyun pGC->subWindowMode = ClipByChildren;
495*4882a593Smuzhiyun pGC->graphicsExposures = TRUE;
496*4882a593Smuzhiyun pGC->clipOrg.x = 0;
497*4882a593Smuzhiyun pGC->clipOrg.y = 0;
498*4882a593Smuzhiyun pGC->clientClip = (void *) NULL;
499*4882a593Smuzhiyun pGC->numInDashList = 2;
500*4882a593Smuzhiyun pGC->dash = DefaultDash;
501*4882a593Smuzhiyun pGC->dashOffset = 0;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /* use the default font and stipple */
504*4882a593Smuzhiyun pGC->font = defaultFont;
505*4882a593Smuzhiyun if (pGC->font) /* necessary, because open of default font could fail */
506*4882a593Smuzhiyun pGC->font->refcnt++;
507*4882a593Smuzhiyun pGC->stipple = pGC->pScreen->defaultStipple;
508*4882a593Smuzhiyun if (pGC->stipple)
509*4882a593Smuzhiyun pGC->stipple->refcnt++;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /* this is not a scratch GC */
512*4882a593Smuzhiyun pGC->scratch_inuse = FALSE;
513*4882a593Smuzhiyun return pGC;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun /* CreateGC(pDrawable, mask, pval, pStatus)
517*4882a593Smuzhiyun creates a default GC for the given drawable, using mask to fill
518*4882a593Smuzhiyun in any non-default values.
519*4882a593Smuzhiyun Returns a pointer to the new GC on success, NULL otherwise.
520*4882a593Smuzhiyun returns status of non-default fields in pStatus
521*4882a593Smuzhiyun BUG:
522*4882a593Smuzhiyun should check for failure to create default tile
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun GCPtr
CreateGC(DrawablePtr pDrawable,BITS32 mask,XID * pval,int * pStatus,XID gcid,ClientPtr client)526*4882a593Smuzhiyun CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus,
527*4882a593Smuzhiyun XID gcid, ClientPtr client)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun GCPtr pGC;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun pGC = NewGCObject(pDrawable->pScreen, pDrawable->depth);
532*4882a593Smuzhiyun if (!pGC) {
533*4882a593Smuzhiyun *pStatus = BadAlloc;
534*4882a593Smuzhiyun return (GCPtr) NULL;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
538*4882a593Smuzhiyun if (mask & GCForeground) {
539*4882a593Smuzhiyun /*
540*4882a593Smuzhiyun * magic special case -- ChangeGC checks for this condition
541*4882a593Smuzhiyun * and snags the Foreground value to create a pseudo default-tile
542*4882a593Smuzhiyun */
543*4882a593Smuzhiyun pGC->tileIsPixel = FALSE;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun else {
546*4882a593Smuzhiyun pGC->tileIsPixel = TRUE;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* security creation/labeling check */
550*4882a593Smuzhiyun *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC,
551*4882a593Smuzhiyun RT_NONE, NULL, DixCreateAccess | DixSetAttrAccess);
552*4882a593Smuzhiyun if (*pStatus != Success)
553*4882a593Smuzhiyun goto out;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun pGC->stateChanges = GCAllBits;
556*4882a593Smuzhiyun if (!(*pGC->pScreen->CreateGC) (pGC))
557*4882a593Smuzhiyun *pStatus = BadAlloc;
558*4882a593Smuzhiyun else if (mask)
559*4882a593Smuzhiyun *pStatus = ChangeGCXIDs(client, pGC, mask, pval);
560*4882a593Smuzhiyun else
561*4882a593Smuzhiyun *pStatus = Success;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun out:
564*4882a593Smuzhiyun if (*pStatus != Success) {
565*4882a593Smuzhiyun if (!pGC->tileIsPixel && !pGC->tile.pixmap)
566*4882a593Smuzhiyun pGC->tileIsPixel = TRUE; /* undo special case */
567*4882a593Smuzhiyun FreeGC(pGC, (XID) 0);
568*4882a593Smuzhiyun pGC = (GCPtr) NULL;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun return pGC;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun static Bool
CreateDefaultTile(GCPtr pGC)575*4882a593Smuzhiyun CreateDefaultTile(GCPtr pGC)
576*4882a593Smuzhiyun {
577*4882a593Smuzhiyun ChangeGCVal tmpval[3];
578*4882a593Smuzhiyun PixmapPtr pTile;
579*4882a593Smuzhiyun GCPtr pgcScratch;
580*4882a593Smuzhiyun xRectangle rect;
581*4882a593Smuzhiyun CARD16 w, h;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun w = 1;
584*4882a593Smuzhiyun h = 1;
585*4882a593Smuzhiyun (*pGC->pScreen->QueryBestSize) (TileShape, &w, &h, pGC->pScreen);
586*4882a593Smuzhiyun pTile = (PixmapPtr)
587*4882a593Smuzhiyun (*pGC->pScreen->CreatePixmap) (pGC->pScreen, w, h, pGC->depth, 0);
588*4882a593Smuzhiyun pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
589*4882a593Smuzhiyun if (!pTile || !pgcScratch) {
590*4882a593Smuzhiyun if (pTile)
591*4882a593Smuzhiyun (*pTile->drawable.pScreen->DestroyPixmap) (pTile);
592*4882a593Smuzhiyun if (pgcScratch)
593*4882a593Smuzhiyun FreeScratchGC(pgcScratch);
594*4882a593Smuzhiyun return FALSE;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun tmpval[0].val = GXcopy;
597*4882a593Smuzhiyun tmpval[1].val = pGC->tile.pixel;
598*4882a593Smuzhiyun tmpval[2].val = FillSolid;
599*4882a593Smuzhiyun (void) ChangeGC(NullClient, pgcScratch,
600*4882a593Smuzhiyun GCFunction | GCForeground | GCFillStyle, tmpval);
601*4882a593Smuzhiyun ValidateGC((DrawablePtr) pTile, pgcScratch);
602*4882a593Smuzhiyun rect.x = 0;
603*4882a593Smuzhiyun rect.y = 0;
604*4882a593Smuzhiyun rect.width = w;
605*4882a593Smuzhiyun rect.height = h;
606*4882a593Smuzhiyun (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pTile, pgcScratch, 1,
607*4882a593Smuzhiyun &rect);
608*4882a593Smuzhiyun /* Always remember to free the scratch graphics context after use. */
609*4882a593Smuzhiyun FreeScratchGC(pgcScratch);
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun pGC->tileIsPixel = FALSE;
612*4882a593Smuzhiyun pGC->tile.pixmap = pTile;
613*4882a593Smuzhiyun return TRUE;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun int
CopyGC(GC * pgcSrc,GC * pgcDst,BITS32 mask)617*4882a593Smuzhiyun CopyGC(GC * pgcSrc, GC * pgcDst, BITS32 mask)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun BITS32 index2;
620*4882a593Smuzhiyun BITS32 maskQ;
621*4882a593Smuzhiyun int error = 0;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun if (pgcSrc == pgcDst)
624*4882a593Smuzhiyun return Success;
625*4882a593Smuzhiyun pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
626*4882a593Smuzhiyun pgcDst->stateChanges |= mask;
627*4882a593Smuzhiyun maskQ = mask;
628*4882a593Smuzhiyun while (mask) {
629*4882a593Smuzhiyun index2 = (BITS32) lowbit(mask);
630*4882a593Smuzhiyun mask &= ~index2;
631*4882a593Smuzhiyun switch (index2) {
632*4882a593Smuzhiyun case GCFunction:
633*4882a593Smuzhiyun pgcDst->alu = pgcSrc->alu;
634*4882a593Smuzhiyun break;
635*4882a593Smuzhiyun case GCPlaneMask:
636*4882a593Smuzhiyun pgcDst->planemask = pgcSrc->planemask;
637*4882a593Smuzhiyun break;
638*4882a593Smuzhiyun case GCForeground:
639*4882a593Smuzhiyun pgcDst->fgPixel = pgcSrc->fgPixel;
640*4882a593Smuzhiyun break;
641*4882a593Smuzhiyun case GCBackground:
642*4882a593Smuzhiyun pgcDst->bgPixel = pgcSrc->bgPixel;
643*4882a593Smuzhiyun break;
644*4882a593Smuzhiyun case GCLineWidth:
645*4882a593Smuzhiyun pgcDst->lineWidth = pgcSrc->lineWidth;
646*4882a593Smuzhiyun break;
647*4882a593Smuzhiyun case GCLineStyle:
648*4882a593Smuzhiyun pgcDst->lineStyle = pgcSrc->lineStyle;
649*4882a593Smuzhiyun break;
650*4882a593Smuzhiyun case GCCapStyle:
651*4882a593Smuzhiyun pgcDst->capStyle = pgcSrc->capStyle;
652*4882a593Smuzhiyun break;
653*4882a593Smuzhiyun case GCJoinStyle:
654*4882a593Smuzhiyun pgcDst->joinStyle = pgcSrc->joinStyle;
655*4882a593Smuzhiyun break;
656*4882a593Smuzhiyun case GCFillStyle:
657*4882a593Smuzhiyun pgcDst->fillStyle = pgcSrc->fillStyle;
658*4882a593Smuzhiyun break;
659*4882a593Smuzhiyun case GCFillRule:
660*4882a593Smuzhiyun pgcDst->fillRule = pgcSrc->fillRule;
661*4882a593Smuzhiyun break;
662*4882a593Smuzhiyun case GCTile:
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun if (EqualPixUnion(pgcDst->tileIsPixel,
665*4882a593Smuzhiyun pgcDst->tile,
666*4882a593Smuzhiyun pgcSrc->tileIsPixel, pgcSrc->tile)) {
667*4882a593Smuzhiyun break;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun if (!pgcDst->tileIsPixel)
670*4882a593Smuzhiyun (*pgcDst->pScreen->DestroyPixmap) (pgcDst->tile.pixmap);
671*4882a593Smuzhiyun pgcDst->tileIsPixel = pgcSrc->tileIsPixel;
672*4882a593Smuzhiyun pgcDst->tile = pgcSrc->tile;
673*4882a593Smuzhiyun if (!pgcDst->tileIsPixel)
674*4882a593Smuzhiyun pgcDst->tile.pixmap->refcnt++;
675*4882a593Smuzhiyun break;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun case GCStipple:
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun if (pgcDst->stipple == pgcSrc->stipple)
680*4882a593Smuzhiyun break;
681*4882a593Smuzhiyun if (pgcDst->stipple)
682*4882a593Smuzhiyun (*pgcDst->pScreen->DestroyPixmap) (pgcDst->stipple);
683*4882a593Smuzhiyun pgcDst->stipple = pgcSrc->stipple;
684*4882a593Smuzhiyun if (pgcDst->stipple)
685*4882a593Smuzhiyun pgcDst->stipple->refcnt++;
686*4882a593Smuzhiyun break;
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun case GCTileStipXOrigin:
689*4882a593Smuzhiyun pgcDst->patOrg.x = pgcSrc->patOrg.x;
690*4882a593Smuzhiyun break;
691*4882a593Smuzhiyun case GCTileStipYOrigin:
692*4882a593Smuzhiyun pgcDst->patOrg.y = pgcSrc->patOrg.y;
693*4882a593Smuzhiyun break;
694*4882a593Smuzhiyun case GCFont:
695*4882a593Smuzhiyun if (pgcDst->font == pgcSrc->font)
696*4882a593Smuzhiyun break;
697*4882a593Smuzhiyun if (pgcDst->font)
698*4882a593Smuzhiyun CloseFont(pgcDst->font, (Font) 0);
699*4882a593Smuzhiyun if ((pgcDst->font = pgcSrc->font) != NullFont)
700*4882a593Smuzhiyun (pgcDst->font)->refcnt++;
701*4882a593Smuzhiyun break;
702*4882a593Smuzhiyun case GCSubwindowMode:
703*4882a593Smuzhiyun pgcDst->subWindowMode = pgcSrc->subWindowMode;
704*4882a593Smuzhiyun break;
705*4882a593Smuzhiyun case GCGraphicsExposures:
706*4882a593Smuzhiyun pgcDst->graphicsExposures = pgcSrc->graphicsExposures;
707*4882a593Smuzhiyun break;
708*4882a593Smuzhiyun case GCClipXOrigin:
709*4882a593Smuzhiyun pgcDst->clipOrg.x = pgcSrc->clipOrg.x;
710*4882a593Smuzhiyun break;
711*4882a593Smuzhiyun case GCClipYOrigin:
712*4882a593Smuzhiyun pgcDst->clipOrg.y = pgcSrc->clipOrg.y;
713*4882a593Smuzhiyun break;
714*4882a593Smuzhiyun case GCClipMask:
715*4882a593Smuzhiyun (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
716*4882a593Smuzhiyun break;
717*4882a593Smuzhiyun case GCDashOffset:
718*4882a593Smuzhiyun pgcDst->dashOffset = pgcSrc->dashOffset;
719*4882a593Smuzhiyun break;
720*4882a593Smuzhiyun case GCDashList:
721*4882a593Smuzhiyun if (pgcSrc->dash == DefaultDash) {
722*4882a593Smuzhiyun if (pgcDst->dash != DefaultDash) {
723*4882a593Smuzhiyun free(pgcDst->dash);
724*4882a593Smuzhiyun pgcDst->numInDashList = pgcSrc->numInDashList;
725*4882a593Smuzhiyun pgcDst->dash = pgcSrc->dash;
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun }
728*4882a593Smuzhiyun else {
729*4882a593Smuzhiyun unsigned char *dash;
730*4882a593Smuzhiyun unsigned int i;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char));
733*4882a593Smuzhiyun if (dash) {
734*4882a593Smuzhiyun if (pgcDst->dash != DefaultDash)
735*4882a593Smuzhiyun free(pgcDst->dash);
736*4882a593Smuzhiyun pgcDst->numInDashList = pgcSrc->numInDashList;
737*4882a593Smuzhiyun pgcDst->dash = dash;
738*4882a593Smuzhiyun for (i = 0; i < pgcSrc->numInDashList; i++)
739*4882a593Smuzhiyun dash[i] = pgcSrc->dash[i];
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun else
742*4882a593Smuzhiyun error = BadAlloc;
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun break;
745*4882a593Smuzhiyun case GCArcMode:
746*4882a593Smuzhiyun pgcDst->arcMode = pgcSrc->arcMode;
747*4882a593Smuzhiyun break;
748*4882a593Smuzhiyun default:
749*4882a593Smuzhiyun FatalError("CopyGC: Unhandled mask!\n");
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) {
753*4882a593Smuzhiyun if (!CreateDefaultTile(pgcDst)) {
754*4882a593Smuzhiyun pgcDst->fillStyle = FillSolid;
755*4882a593Smuzhiyun error = BadAlloc;
756*4882a593Smuzhiyun }
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst);
759*4882a593Smuzhiyun return error;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /**
763*4882a593Smuzhiyun * does the diX part of freeing the characteristics in the GC.
764*4882a593Smuzhiyun *
765*4882a593Smuzhiyun * \param value must conform to DeleteType
766*4882a593Smuzhiyun */
767*4882a593Smuzhiyun int
FreeGC(void * value,XID gid)768*4882a593Smuzhiyun FreeGC(void *value, XID gid)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun GCPtr pGC = (GCPtr) value;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun CloseFont(pGC->font, (Font) 0);
773*4882a593Smuzhiyun (*pGC->funcs->DestroyClip) (pGC);
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun if (!pGC->tileIsPixel)
776*4882a593Smuzhiyun (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap);
777*4882a593Smuzhiyun if (pGC->stipple)
778*4882a593Smuzhiyun (*pGC->pScreen->DestroyPixmap) (pGC->stipple);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun (*pGC->funcs->DestroyGC) (pGC);
781*4882a593Smuzhiyun if (pGC->dash != DefaultDash)
782*4882a593Smuzhiyun free(pGC->dash);
783*4882a593Smuzhiyun dixFreeObjectWithPrivates(pGC, PRIVATE_GC);
784*4882a593Smuzhiyun return Success;
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun /* CreateScratchGC(pScreen, depth)
788*4882a593Smuzhiyun like CreateGC, but doesn't do the default tile or stipple,
789*4882a593Smuzhiyun since we can't create them without already having a GC. any code
790*4882a593Smuzhiyun using the tile or stipple has to set them explicitly anyway,
791*4882a593Smuzhiyun since the state of the scratch gc is unknown. This is OK
792*4882a593Smuzhiyun because ChangeGC() has to be able to deal with NULL tiles and
793*4882a593Smuzhiyun stipples anyway (in case the CreateGC() call has provided a
794*4882a593Smuzhiyun value for them -- we can't set the default tile until the
795*4882a593Smuzhiyun client-supplied attributes are installed, since the fgPixel
796*4882a593Smuzhiyun is what fills the default tile. (maybe this comment should
797*4882a593Smuzhiyun go with CreateGC() or ChangeGC().)
798*4882a593Smuzhiyun */
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun static GCPtr
CreateScratchGC(ScreenPtr pScreen,unsigned depth)801*4882a593Smuzhiyun CreateScratchGC(ScreenPtr pScreen, unsigned depth)
802*4882a593Smuzhiyun {
803*4882a593Smuzhiyun GCPtr pGC;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun pGC = NewGCObject(pScreen, depth);
806*4882a593Smuzhiyun if (!pGC)
807*4882a593Smuzhiyun return (GCPtr) NULL;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun pGC->stateChanges = GCAllBits;
810*4882a593Smuzhiyun if (!(*pScreen->CreateGC) (pGC)) {
811*4882a593Smuzhiyun FreeGC(pGC, (XID) 0);
812*4882a593Smuzhiyun pGC = (GCPtr) NULL;
813*4882a593Smuzhiyun }
814*4882a593Smuzhiyun pGC->graphicsExposures = FALSE;
815*4882a593Smuzhiyun return pGC;
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun void
FreeGCperDepth(int screenNum)819*4882a593Smuzhiyun FreeGCperDepth(int screenNum)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun int i;
822*4882a593Smuzhiyun ScreenPtr pScreen;
823*4882a593Smuzhiyun GCPtr *ppGC;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun pScreen = screenInfo.screens[screenNum];
826*4882a593Smuzhiyun ppGC = pScreen->GCperDepth;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun for (i = 0; i <= pScreen->numDepths; i++) {
829*4882a593Smuzhiyun (void) FreeGC(ppGC[i], (XID) 0);
830*4882a593Smuzhiyun ppGC[i] = NULL;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun Bool
CreateGCperDepth(int screenNum)835*4882a593Smuzhiyun CreateGCperDepth(int screenNum)
836*4882a593Smuzhiyun {
837*4882a593Smuzhiyun int i;
838*4882a593Smuzhiyun ScreenPtr pScreen;
839*4882a593Smuzhiyun DepthPtr pDepth;
840*4882a593Smuzhiyun GCPtr *ppGC;
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun pScreen = screenInfo.screens[screenNum];
843*4882a593Smuzhiyun ppGC = pScreen->GCperDepth;
844*4882a593Smuzhiyun /* do depth 1 separately because it's not included in list */
845*4882a593Smuzhiyun if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
846*4882a593Smuzhiyun return FALSE;
847*4882a593Smuzhiyun /* Make sure we don't overflow GCperDepth[] */
848*4882a593Smuzhiyun if (pScreen->numDepths > MAXFORMATS)
849*4882a593Smuzhiyun return FALSE;
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun pDepth = pScreen->allowedDepths;
852*4882a593Smuzhiyun for (i = 0; i < pScreen->numDepths; i++, pDepth++) {
853*4882a593Smuzhiyun if (!(ppGC[i + 1] = CreateScratchGC(pScreen, pDepth->depth))) {
854*4882a593Smuzhiyun for (; i >= 0; i--)
855*4882a593Smuzhiyun (void) FreeGC(ppGC[i], (XID) 0);
856*4882a593Smuzhiyun return FALSE;
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun return TRUE;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun Bool
CreateDefaultStipple(int screenNum)863*4882a593Smuzhiyun CreateDefaultStipple(int screenNum)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun ScreenPtr pScreen;
866*4882a593Smuzhiyun ChangeGCVal tmpval[3];
867*4882a593Smuzhiyun xRectangle rect;
868*4882a593Smuzhiyun CARD16 w, h;
869*4882a593Smuzhiyun GCPtr pgcScratch;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun pScreen = screenInfo.screens[screenNum];
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun w = 16;
874*4882a593Smuzhiyun h = 16;
875*4882a593Smuzhiyun (*pScreen->QueryBestSize) (StippleShape, &w, &h, pScreen);
876*4882a593Smuzhiyun if (!(pScreen->defaultStipple = pScreen->CreatePixmap(pScreen, w, h, 1, 0)))
877*4882a593Smuzhiyun return FALSE;
878*4882a593Smuzhiyun /* fill stipple with 1 */
879*4882a593Smuzhiyun tmpval[0].val = GXcopy;
880*4882a593Smuzhiyun tmpval[1].val = 1;
881*4882a593Smuzhiyun tmpval[2].val = FillSolid;
882*4882a593Smuzhiyun pgcScratch = GetScratchGC(1, pScreen);
883*4882a593Smuzhiyun if (!pgcScratch) {
884*4882a593Smuzhiyun (*pScreen->DestroyPixmap) (pScreen->defaultStipple);
885*4882a593Smuzhiyun return FALSE;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun (void) ChangeGC(NullClient, pgcScratch,
888*4882a593Smuzhiyun GCFunction | GCForeground | GCFillStyle, tmpval);
889*4882a593Smuzhiyun ValidateGC((DrawablePtr) pScreen->defaultStipple, pgcScratch);
890*4882a593Smuzhiyun rect.x = 0;
891*4882a593Smuzhiyun rect.y = 0;
892*4882a593Smuzhiyun rect.width = w;
893*4882a593Smuzhiyun rect.height = h;
894*4882a593Smuzhiyun (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pScreen->defaultStipple,
895*4882a593Smuzhiyun pgcScratch, 1, &rect);
896*4882a593Smuzhiyun FreeScratchGC(pgcScratch);
897*4882a593Smuzhiyun return TRUE;
898*4882a593Smuzhiyun }
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun void
FreeDefaultStipple(int screenNum)901*4882a593Smuzhiyun FreeDefaultStipple(int screenNum)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun ScreenPtr pScreen = screenInfo.screens[screenNum];
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun (*pScreen->DestroyPixmap) (pScreen->defaultStipple);
906*4882a593Smuzhiyun }
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun int
SetDashes(GCPtr pGC,unsigned offset,unsigned ndash,unsigned char * pdash)909*4882a593Smuzhiyun SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun long i;
912*4882a593Smuzhiyun unsigned char *p, *indash;
913*4882a593Smuzhiyun BITS32 maskQ = 0;
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun i = ndash;
916*4882a593Smuzhiyun p = pdash;
917*4882a593Smuzhiyun while (i--) {
918*4882a593Smuzhiyun if (!*p++) {
919*4882a593Smuzhiyun /* dash segment must be > 0 */
920*4882a593Smuzhiyun return BadValue;
921*4882a593Smuzhiyun }
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun if (ndash & 1)
925*4882a593Smuzhiyun p = malloc(2 * ndash * sizeof(unsigned char));
926*4882a593Smuzhiyun else
927*4882a593Smuzhiyun p = malloc(ndash * sizeof(unsigned char));
928*4882a593Smuzhiyun if (!p)
929*4882a593Smuzhiyun return BadAlloc;
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
932*4882a593Smuzhiyun if (offset != pGC->dashOffset) {
933*4882a593Smuzhiyun pGC->dashOffset = offset;
934*4882a593Smuzhiyun pGC->stateChanges |= GCDashOffset;
935*4882a593Smuzhiyun maskQ |= GCDashOffset;
936*4882a593Smuzhiyun }
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (pGC->dash != DefaultDash)
939*4882a593Smuzhiyun free(pGC->dash);
940*4882a593Smuzhiyun pGC->numInDashList = ndash;
941*4882a593Smuzhiyun pGC->dash = p;
942*4882a593Smuzhiyun if (ndash & 1) {
943*4882a593Smuzhiyun pGC->numInDashList += ndash;
944*4882a593Smuzhiyun indash = pdash;
945*4882a593Smuzhiyun i = ndash;
946*4882a593Smuzhiyun while (i--)
947*4882a593Smuzhiyun *p++ = *indash++;
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun while (ndash--)
950*4882a593Smuzhiyun *p++ = *pdash++;
951*4882a593Smuzhiyun pGC->stateChanges |= GCDashList;
952*4882a593Smuzhiyun maskQ |= GCDashList;
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun if (pGC->funcs->ChangeGC)
955*4882a593Smuzhiyun (*pGC->funcs->ChangeGC) (pGC, maskQ);
956*4882a593Smuzhiyun return Success;
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun int
VerifyRectOrder(int nrects,xRectangle * prects,int ordering)960*4882a593Smuzhiyun VerifyRectOrder(int nrects, xRectangle *prects, int ordering)
961*4882a593Smuzhiyun {
962*4882a593Smuzhiyun xRectangle *prectP, *prectN;
963*4882a593Smuzhiyun int i;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun switch (ordering) {
966*4882a593Smuzhiyun case Unsorted:
967*4882a593Smuzhiyun return CT_UNSORTED;
968*4882a593Smuzhiyun case YSorted:
969*4882a593Smuzhiyun if (nrects > 1) {
970*4882a593Smuzhiyun for (i = 1, prectP = prects, prectN = prects + 1;
971*4882a593Smuzhiyun i < nrects; i++, prectP++, prectN++)
972*4882a593Smuzhiyun if (prectN->y < prectP->y)
973*4882a593Smuzhiyun return -1;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun return CT_YSORTED;
976*4882a593Smuzhiyun case YXSorted:
977*4882a593Smuzhiyun if (nrects > 1) {
978*4882a593Smuzhiyun for (i = 1, prectP = prects, prectN = prects + 1;
979*4882a593Smuzhiyun i < nrects; i++, prectP++, prectN++)
980*4882a593Smuzhiyun if ((prectN->y < prectP->y) ||
981*4882a593Smuzhiyun ((prectN->y == prectP->y) && (prectN->x < prectP->x)))
982*4882a593Smuzhiyun return -1;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun return CT_YXSORTED;
985*4882a593Smuzhiyun case YXBanded:
986*4882a593Smuzhiyun if (nrects > 1) {
987*4882a593Smuzhiyun for (i = 1, prectP = prects, prectN = prects + 1;
988*4882a593Smuzhiyun i < nrects; i++, prectP++, prectN++)
989*4882a593Smuzhiyun if ((prectN->y != prectP->y &&
990*4882a593Smuzhiyun prectN->y < prectP->y + (int) prectP->height) ||
991*4882a593Smuzhiyun ((prectN->y == prectP->y) &&
992*4882a593Smuzhiyun (prectN->height != prectP->height ||
993*4882a593Smuzhiyun prectN->x < prectP->x + (int) prectP->width)))
994*4882a593Smuzhiyun return -1;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun return CT_YXBANDED;
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun return -1;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun int
SetClipRects(GCPtr pGC,int xOrigin,int yOrigin,int nrects,xRectangle * prects,int ordering)1002*4882a593Smuzhiyun SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects,
1003*4882a593Smuzhiyun xRectangle *prects, int ordering)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun int newct, size;
1006*4882a593Smuzhiyun xRectangle *prectsNew;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun newct = VerifyRectOrder(nrects, prects, ordering);
1009*4882a593Smuzhiyun if (newct < 0)
1010*4882a593Smuzhiyun return BadMatch;
1011*4882a593Smuzhiyun size = nrects * sizeof(xRectangle);
1012*4882a593Smuzhiyun prectsNew = malloc(size);
1013*4882a593Smuzhiyun if (!prectsNew && size)
1014*4882a593Smuzhiyun return BadAlloc;
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
1017*4882a593Smuzhiyun pGC->clipOrg.x = xOrigin;
1018*4882a593Smuzhiyun pGC->stateChanges |= GCClipXOrigin;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun pGC->clipOrg.y = yOrigin;
1021*4882a593Smuzhiyun pGC->stateChanges |= GCClipYOrigin;
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun if (size)
1024*4882a593Smuzhiyun memmove((char *) prectsNew, (char *) prects, size);
1025*4882a593Smuzhiyun (*pGC->funcs->ChangeClip) (pGC, newct, (void *) prectsNew, nrects);
1026*4882a593Smuzhiyun if (pGC->funcs->ChangeGC)
1027*4882a593Smuzhiyun (*pGC->funcs->ChangeGC) (pGC,
1028*4882a593Smuzhiyun GCClipXOrigin | GCClipYOrigin | GCClipMask);
1029*4882a593Smuzhiyun return Success;
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun /*
1033*4882a593Smuzhiyun sets reasonable defaults
1034*4882a593Smuzhiyun if we can get a pre-allocated one, use it and mark it as used.
1035*4882a593Smuzhiyun if we can't, create one out of whole cloth (The Velveteen GC -- if
1036*4882a593Smuzhiyun you use it often enough it will become real.)
1037*4882a593Smuzhiyun */
1038*4882a593Smuzhiyun GCPtr
GetScratchGC(unsigned depth,ScreenPtr pScreen)1039*4882a593Smuzhiyun GetScratchGC(unsigned depth, ScreenPtr pScreen)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun int i;
1042*4882a593Smuzhiyun GCPtr pGC;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun for (i = 0; i <= pScreen->numDepths; i++) {
1045*4882a593Smuzhiyun pGC = pScreen->GCperDepth[i];
1046*4882a593Smuzhiyun if (pGC && pGC->depth == depth && !pGC->scratch_inuse) {
1047*4882a593Smuzhiyun pGC->scratch_inuse = TRUE;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun pGC->alu = GXcopy;
1050*4882a593Smuzhiyun pGC->planemask = ~0;
1051*4882a593Smuzhiyun pGC->serialNumber = 0;
1052*4882a593Smuzhiyun pGC->fgPixel = 0;
1053*4882a593Smuzhiyun pGC->bgPixel = 1;
1054*4882a593Smuzhiyun pGC->lineWidth = 0;
1055*4882a593Smuzhiyun pGC->lineStyle = LineSolid;
1056*4882a593Smuzhiyun pGC->capStyle = CapButt;
1057*4882a593Smuzhiyun pGC->joinStyle = JoinMiter;
1058*4882a593Smuzhiyun pGC->fillStyle = FillSolid;
1059*4882a593Smuzhiyun pGC->fillRule = EvenOddRule;
1060*4882a593Smuzhiyun pGC->arcMode = ArcChord;
1061*4882a593Smuzhiyun pGC->patOrg.x = 0;
1062*4882a593Smuzhiyun pGC->patOrg.y = 0;
1063*4882a593Smuzhiyun pGC->subWindowMode = ClipByChildren;
1064*4882a593Smuzhiyun pGC->graphicsExposures = FALSE;
1065*4882a593Smuzhiyun pGC->clipOrg.x = 0;
1066*4882a593Smuzhiyun pGC->clipOrg.y = 0;
1067*4882a593Smuzhiyun if (pGC->clientClip)
1068*4882a593Smuzhiyun (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0);
1069*4882a593Smuzhiyun pGC->stateChanges = GCAllBits;
1070*4882a593Smuzhiyun return pGC;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun /* if we make it this far, need to roll our own */
1074*4882a593Smuzhiyun return CreateScratchGC(pScreen, depth);
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun /*
1078*4882a593Smuzhiyun if the gc to free is in the table of pre-existing ones,
1079*4882a593Smuzhiyun mark it as available.
1080*4882a593Smuzhiyun if not, free it for real
1081*4882a593Smuzhiyun */
1082*4882a593Smuzhiyun void
FreeScratchGC(GCPtr pGC)1083*4882a593Smuzhiyun FreeScratchGC(GCPtr pGC)
1084*4882a593Smuzhiyun {
1085*4882a593Smuzhiyun if (pGC->scratch_inuse)
1086*4882a593Smuzhiyun pGC->scratch_inuse = FALSE;
1087*4882a593Smuzhiyun else
1088*4882a593Smuzhiyun FreeGC(pGC, (GContext) 0);
1089*4882a593Smuzhiyun }
1090