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