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