1 /*
2 
3 Copyright 1986, 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 in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24 
25 */
26 
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include "Xlibint.h"
31 #include "Cr.h"
32 
33 static XGCValues const initial_GC = {
34     GXcopy, 	/* function */
35     AllPlanes,	/* plane_mask */
36     0L,		/* foreground */
37     1L,		/* background */
38     0,		/* line_width */
39     LineSolid,	/* line_style */
40     CapButt,	/* cap_style */
41     JoinMiter,	/* join_style */
42     FillSolid,	/* fill_style */
43     EvenOddRule,/* fill_rule */
44     ArcPieSlice,/* arc_mode */
45     (Pixmap)~0L,/* tile, impossible (unknown) resource */
46     (Pixmap)~0L,/* stipple, impossible (unknown) resource */
47     0,		/* ts_x_origin */
48     0,		/* ts_y_origin */
49     (Font)~0L,	/* font, impossible (unknown) resource */
50     ClipByChildren, /* subwindow_mode */
51     True,	/* graphics_exposures */
52     0,		/* clip_x_origin */
53     0,		/* clip_y_origin */
54     None,	/* clip_mask */
55     0,		/* dash_offset */
56     4		/* dashes (list [4,4]) */
57 };
58 
59 static void _XGenerateGCList(
60     register Display *dpy,
61     GC gc,
62     xReq *req);
63 
XCreateGC(register Display * dpy,Drawable d,unsigned long valuemask,XGCValues * values)64 GC XCreateGC (
65      register Display *dpy,
66      Drawable d,		/* Window or Pixmap for which depth matches */
67      unsigned long valuemask,	/* which ones to set initially */
68      XGCValues *values)		/* the values themselves */
69 {
70     register GC gc;
71     register xCreateGCReq *req;
72     register _XExtension *ext;
73 
74     LockDisplay(dpy);
75     if ((gc = Xmalloc (sizeof(struct _XGC))) == NULL) {
76 	UnlockDisplay(dpy);
77 	SyncHandle();
78 	return (NULL);
79     }
80     gc->rects = 0;
81     gc->dashes = 0;
82     gc->ext_data = NULL;
83     gc->values = initial_GC;
84     gc->dirty = 0L;
85 
86     valuemask &= (1L << (GCLastBit + 1)) - 1;
87     if (valuemask) _XUpdateGCCache (gc, valuemask, values);
88 
89     GetReq(CreateGC, req);
90     req->drawable = d;
91     req->gc = gc->gid = XAllocID(dpy);
92 
93     if ((req->mask = gc->dirty))
94         _XGenerateGCList (dpy, gc, (xReq *) req);
95     /* call out to any extensions interested */
96     for (ext = dpy->ext_procs; ext; ext = ext->next)
97 	if (ext->create_GC) (*ext->create_GC)(dpy, gc, &ext->codes);
98     gc->dirty = 0L; /* allow extensions to see dirty bits */
99     UnlockDisplay(dpy);
100     SyncHandle();
101     return (gc);
102     }
103 
104 /*
105  * GenerateGCList looks at the GC dirty bits, and appends all the required
106  * long words to the request being generated.
107  */
108 
109 static void
_XGenerateGCList(register Display * dpy,GC gc,xReq * req)110 _XGenerateGCList (
111     register Display *dpy,
112     GC gc,
113     xReq *req)
114     {
115     unsigned long values[32];
116     register unsigned long *value = values;
117     long nvalues;
118     register XGCValues *gv = &gc->values;
119     register unsigned long dirty = gc->dirty;
120 
121     /*
122      * Note: The order of these tests are critical; the order must be the
123      * same as the GC mask bits in the word.
124      */
125     if (dirty & GCFunction)          *value++ = gv->function;
126     if (dirty & GCPlaneMask)         *value++ = gv->plane_mask;
127     if (dirty & GCForeground)        *value++ = gv->foreground;
128     if (dirty & GCBackground)        *value++ = gv->background;
129     if (dirty & GCLineWidth)         *value++ = gv->line_width;
130     if (dirty & GCLineStyle)         *value++ = gv->line_style;
131     if (dirty & GCCapStyle)          *value++ = gv->cap_style;
132     if (dirty & GCJoinStyle)         *value++ = gv->join_style;
133     if (dirty & GCFillStyle)         *value++ = gv->fill_style;
134     if (dirty & GCFillRule)          *value++ = gv->fill_rule;
135     if (dirty & GCTile)              *value++ = gv->tile;
136     if (dirty & GCStipple)           *value++ = gv->stipple;
137     if (dirty & GCTileStipXOrigin)   *value++ = gv->ts_x_origin;
138     if (dirty & GCTileStipYOrigin)   *value++ = gv->ts_y_origin;
139     if (dirty & GCFont)              *value++ = gv->font;
140     if (dirty & GCSubwindowMode)     *value++ = gv->subwindow_mode;
141     if (dirty & GCGraphicsExposures) *value++ = gv->graphics_exposures;
142     if (dirty & GCClipXOrigin)       *value++ = gv->clip_x_origin;
143     if (dirty & GCClipYOrigin)       *value++ = gv->clip_y_origin;
144     if (dirty & GCClipMask)          *value++ = gv->clip_mask;
145     if (dirty & GCDashOffset)        *value++ = gv->dash_offset;
146     if (dirty & GCDashList)          *value++ = gv->dashes;
147     if (dirty & GCArcMode)           *value++ = gv->arc_mode;
148 
149     req->length += (nvalues = value - values);
150 
151     /*
152      * note: Data is a macro that uses its arguments multiple
153      * times, so "nvalues" is changed in a separate assignment
154      * statement
155      */
156 
157     nvalues <<= 2;
158     Data32 (dpy, (long *) values, nvalues);
159 
160     }
161 
162 
163 int
_XUpdateGCCache(register GC gc,register unsigned long mask,register XGCValues * attr)164 _XUpdateGCCache (
165     register GC gc,
166     register unsigned long mask,
167     register XGCValues *attr)
168 {
169     register XGCValues *gv = &gc->values;
170 
171     if (mask & GCFunction)
172         if (gv->function != attr->function) {
173 	  gv->function = attr->function;
174 	  gc->dirty |= GCFunction;
175 	}
176 
177     if (mask & GCPlaneMask)
178         if (gv->plane_mask != attr->plane_mask) {
179             gv->plane_mask = attr->plane_mask;
180 	    gc->dirty |= GCPlaneMask;
181 	  }
182 
183     if (mask & GCForeground)
184         if (gv->foreground != attr->foreground) {
185             gv->foreground = attr->foreground;
186 	    gc->dirty |= GCForeground;
187 	  }
188 
189     if (mask & GCBackground)
190         if (gv->background != attr->background) {
191             gv->background = attr->background;
192 	    gc->dirty |= GCBackground;
193 	  }
194 
195     if (mask & GCLineWidth)
196         if (gv->line_width != attr->line_width) {
197             gv->line_width = attr->line_width;
198 	    gc->dirty |= GCLineWidth;
199 	  }
200 
201     if (mask & GCLineStyle)
202         if (gv->line_style != attr->line_style) {
203             gv->line_style = attr->line_style;
204 	    gc->dirty |= GCLineStyle;
205 	  }
206 
207     if (mask & GCCapStyle)
208         if (gv->cap_style != attr->cap_style) {
209             gv->cap_style = attr->cap_style;
210 	    gc->dirty |= GCCapStyle;
211 	  }
212 
213     if (mask & GCJoinStyle)
214         if (gv->join_style != attr->join_style) {
215             gv->join_style = attr->join_style;
216 	    gc->dirty |= GCJoinStyle;
217 	  }
218 
219     if (mask & GCFillStyle)
220         if (gv->fill_style != attr->fill_style) {
221             gv->fill_style = attr->fill_style;
222 	    gc->dirty |= GCFillStyle;
223 	  }
224 
225     if (mask & GCFillRule)
226         if (gv->fill_rule != attr->fill_rule) {
227     	    gv->fill_rule = attr->fill_rule;
228 	    gc->dirty |= GCFillRule;
229 	  }
230 
231     if (mask & GCArcMode)
232         if (gv->arc_mode != attr->arc_mode) {
233 	    gv->arc_mode = attr->arc_mode;
234 	    gc->dirty |= GCArcMode;
235 	  }
236 
237     /* always write through tile change, since client may have changed pixmap contents */
238     if (mask & GCTile) {
239 	    gv->tile = attr->tile;
240 	    gc->dirty |= GCTile;
241 	  }
242 
243     /* always write through stipple change, since client may have changed pixmap contents */
244     if (mask & GCStipple) {
245 	    gv->stipple = attr->stipple;
246 	    gc->dirty |= GCStipple;
247 	  }
248 
249     if (mask & GCTileStipXOrigin)
250         if (gv->ts_x_origin != attr->ts_x_origin) {
251     	    gv->ts_x_origin = attr->ts_x_origin;
252 	    gc->dirty |= GCTileStipXOrigin;
253 	  }
254 
255     if (mask & GCTileStipYOrigin)
256         if (gv->ts_y_origin != attr->ts_y_origin) {
257 	    gv->ts_y_origin = attr->ts_y_origin;
258 	    gc->dirty |= GCTileStipYOrigin;
259 	  }
260 
261     if (mask & GCFont)
262         if (gv->font != attr->font) {
263 	    gv->font = attr->font;
264 	    gc->dirty |= GCFont;
265 	  }
266 
267     if (mask & GCSubwindowMode)
268         if (gv->subwindow_mode != attr->subwindow_mode) {
269 	    gv->subwindow_mode = attr->subwindow_mode;
270 	    gc->dirty |= GCSubwindowMode;
271 	  }
272 
273     if (mask & GCGraphicsExposures)
274         if (gv->graphics_exposures != attr->graphics_exposures) {
275 	    gv->graphics_exposures = attr->graphics_exposures;
276 	    gc->dirty |= GCGraphicsExposures;
277 	  }
278 
279     if (mask & GCClipXOrigin)
280         if (gv->clip_x_origin != attr->clip_x_origin) {
281 	    gv->clip_x_origin = attr->clip_x_origin;
282 	    gc->dirty |= GCClipXOrigin;
283 	  }
284 
285     if (mask & GCClipYOrigin)
286         if (gv->clip_y_origin != attr->clip_y_origin) {
287 	    gv->clip_y_origin = attr->clip_y_origin;
288 	    gc->dirty |= GCClipYOrigin;
289 	  }
290 
291     /* always write through mask change, since client may have changed pixmap contents */
292     if (mask & GCClipMask) {
293 	    gv->clip_mask = attr->clip_mask;
294 	    gc->dirty |= GCClipMask;
295 	    gc->rects = 0;
296 	  }
297 
298     if (mask & GCDashOffset)
299         if (gv->dash_offset != attr->dash_offset) {
300 	    gv->dash_offset = attr->dash_offset;
301 	    gc->dirty |= GCDashOffset;
302 	  }
303 
304     if (mask & GCDashList)
305         if ((gv->dashes != attr->dashes) || (gc->dashes == True)) {
306             gv->dashes = attr->dashes;
307 	    gc->dirty |= GCDashList;
308 	    gc->dashes = 0;
309 	    }
310     return 0;
311 }
312 
313 /* can only call when display is already locked. */
314 
_XFlushGCCache(Display * dpy,GC gc)315 void _XFlushGCCache(
316      Display *dpy,
317      GC gc)
318 {
319     register xChangeGCReq *req;
320     register _XExtension *ext;
321 
322     if (gc->dirty) {
323         GetReq(ChangeGC, req);
324         req->gc = gc->gid;
325 	req->mask = gc->dirty;
326         _XGenerateGCList (dpy, gc, (xReq *) req);
327 	/* call out to any extensions interested */
328 	for (ext = dpy->ext_procs; ext; ext = ext->next)
329 	    if (ext->flush_GC) (*ext->flush_GC)(dpy, gc, &ext->codes);
330 	gc->dirty = 0L; /* allow extensions to see dirty bits */
331     }
332 }
333 
334 void
XFlushGC(Display * dpy,GC gc)335 XFlushGC(
336     Display *dpy,
337     GC gc)
338 {
339     FlushGC(dpy, gc);
340 }
341 
XGContextFromGC(GC gc)342 GContext XGContextFromGC(GC gc)
343 {
344     return (gc->gid);
345 }
346