/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkgc.c
ViewVC logotype

Annotation of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkgc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 71 - (hide annotations) (download)
Sat Nov 5 11:07:06 2016 UTC (7 years, 6 months ago) by dashley
File MIME type: text/plain
File size: 9817 byte(s)
Set EOL properties appropriately to facilitate simultaneous Linux and Windows development.
1 dashley 71 /* $Header$ */
2    
3     /*
4     * tkGC.c --
5     *
6     * This file maintains a database of read-only graphics contexts
7     * for the Tk toolkit, in order to allow GC's to be shared.
8     *
9     * Copyright (c) 1990-1994 The Regents of the University of California.
10     * Copyright (c) 1994 Sun Microsystems, Inc.
11     *
12     * See the file "license.terms" for information on usage and redistribution
13     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14     *
15     * RCS: @(#) $Id: tkgc.c,v 1.1.1.1 2001/06/13 05:01:12 dtashley Exp $
16     */
17    
18     #include "tkPort.h"
19     #include "tkInt.h"
20    
21     /*
22     * One of the following data structures exists for each GC that is
23     * currently active. The structure is indexed with two hash tables,
24     * one based on the values in the graphics context and the other
25     * based on the display and GC identifier.
26     */
27    
28     typedef struct {
29     GC gc; /* Graphics context. */
30     Display *display; /* Display to which gc belongs. */
31     int refCount; /* Number of active uses of gc. */
32     Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting
33     * this structure). */
34     } TkGC;
35    
36     typedef struct {
37     XGCValues values; /* Desired values for GC. */
38     Display *display; /* Display for which GC is valid. */
39     int screenNum; /* screen number of display */
40     int depth; /* and depth for which GC is valid. */
41     } ValueKey;
42    
43     /*
44     * Forward declarations for procedures defined in this file:
45     */
46    
47     static void GCInit _ANSI_ARGS_((TkDisplay *dispPtr));
48    
49     /*
50     *----------------------------------------------------------------------
51     *
52     * Tk_GetGC --
53     *
54     * Given a desired set of values for a graphics context, find
55     * a read-only graphics context with the desired values.
56     *
57     * Results:
58     * The return value is the X identifer for the desired graphics
59     * context. The caller should never modify this GC, and should
60     * call Tk_FreeGC when the GC is no longer needed.
61     *
62     * Side effects:
63     * The GC is added to an internal database with a reference count.
64     * For each call to this procedure, there should eventually be a call
65     * to Tk_FreeGC, so that the database can be cleaned up when GC's
66     * aren't needed anymore.
67     *
68     *----------------------------------------------------------------------
69     */
70    
71     GC
72     Tk_GetGC(tkwin, valueMask, valuePtr)
73     Tk_Window tkwin; /* Window in which GC will be used. */
74     register unsigned long valueMask;
75     /* 1 bits correspond to values specified
76     * in *valuesPtr; other values are set
77     * from defaults. */
78     register XGCValues *valuePtr;
79     /* Values are specified here for bits set
80     * in valueMask. */
81     {
82     ValueKey valueKey;
83     Tcl_HashEntry *valueHashPtr, *idHashPtr;
84     register TkGC *gcPtr;
85     int new;
86     Drawable d, freeDrawable;
87     TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
88    
89     if (!dispPtr->gcInit) {
90     GCInit(dispPtr);
91     }
92    
93     /*
94     * Must zero valueKey at start to clear out pad bytes that may be
95     * part of structure on some systems.
96     */
97    
98     memset((VOID *) &valueKey, 0, sizeof(valueKey));
99    
100     /*
101     * First, check to see if there's already a GC that will work
102     * for this request (exact matches only, sorry).
103     */
104    
105     if (valueMask & GCFunction) {
106     valueKey.values.function = valuePtr->function;
107     } else {
108     valueKey.values.function = GXcopy;
109     }
110     if (valueMask & GCPlaneMask) {
111     valueKey.values.plane_mask = valuePtr->plane_mask;
112     } else {
113     valueKey.values.plane_mask = (unsigned) ~0;
114     }
115     if (valueMask & GCForeground) {
116     valueKey.values.foreground = valuePtr->foreground;
117     } else {
118     valueKey.values.foreground = 0;
119     }
120     if (valueMask & GCBackground) {
121     valueKey.values.background = valuePtr->background;
122     } else {
123     valueKey.values.background = 1;
124     }
125     if (valueMask & GCLineWidth) {
126     valueKey.values.line_width = valuePtr->line_width;
127     } else {
128     valueKey.values.line_width = 0;
129     }
130     if (valueMask & GCLineStyle) {
131     valueKey.values.line_style = valuePtr->line_style;
132     } else {
133     valueKey.values.line_style = LineSolid;
134     }
135     if (valueMask & GCCapStyle) {
136     valueKey.values.cap_style = valuePtr->cap_style;
137     } else {
138     valueKey.values.cap_style = CapButt;
139     }
140     if (valueMask & GCJoinStyle) {
141     valueKey.values.join_style = valuePtr->join_style;
142     } else {
143     valueKey.values.join_style = JoinMiter;
144     }
145     if (valueMask & GCFillStyle) {
146     valueKey.values.fill_style = valuePtr->fill_style;
147     } else {
148     valueKey.values.fill_style = FillSolid;
149     }
150     if (valueMask & GCFillRule) {
151     valueKey.values.fill_rule = valuePtr->fill_rule;
152     } else {
153     valueKey.values.fill_rule = EvenOddRule;
154     }
155     if (valueMask & GCArcMode) {
156     valueKey.values.arc_mode = valuePtr->arc_mode;
157     } else {
158     valueKey.values.arc_mode = ArcPieSlice;
159     }
160     if (valueMask & GCTile) {
161     valueKey.values.tile = valuePtr->tile;
162     } else {
163     valueKey.values.tile = None;
164     }
165     if (valueMask & GCStipple) {
166     valueKey.values.stipple = valuePtr->stipple;
167     } else {
168     valueKey.values.stipple = None;
169     }
170     if (valueMask & GCTileStipXOrigin) {
171     valueKey.values.ts_x_origin = valuePtr->ts_x_origin;
172     } else {
173     valueKey.values.ts_x_origin = 0;
174     }
175     if (valueMask & GCTileStipYOrigin) {
176     valueKey.values.ts_y_origin = valuePtr->ts_y_origin;
177     } else {
178     valueKey.values.ts_y_origin = 0;
179     }
180     if (valueMask & GCFont) {
181     valueKey.values.font = valuePtr->font;
182     } else {
183     valueKey.values.font = None;
184     }
185     if (valueMask & GCSubwindowMode) {
186     valueKey.values.subwindow_mode = valuePtr->subwindow_mode;
187     } else {
188     valueKey.values.subwindow_mode = ClipByChildren;
189     }
190     if (valueMask & GCGraphicsExposures) {
191     valueKey.values.graphics_exposures = valuePtr->graphics_exposures;
192     } else {
193     valueKey.values.graphics_exposures = True;
194     }
195     if (valueMask & GCClipXOrigin) {
196     valueKey.values.clip_x_origin = valuePtr->clip_x_origin;
197     } else {
198     valueKey.values.clip_x_origin = 0;
199     }
200     if (valueMask & GCClipYOrigin) {
201     valueKey.values.clip_y_origin = valuePtr->clip_y_origin;
202     } else {
203     valueKey.values.clip_y_origin = 0;
204     }
205     if (valueMask & GCClipMask) {
206     valueKey.values.clip_mask = valuePtr->clip_mask;
207     } else {
208     valueKey.values.clip_mask = None;
209     }
210     if (valueMask & GCDashOffset) {
211     valueKey.values.dash_offset = valuePtr->dash_offset;
212     } else {
213     valueKey.values.dash_offset = 0;
214     }
215     if (valueMask & GCDashList) {
216     valueKey.values.dashes = valuePtr->dashes;
217     } else {
218     valueKey.values.dashes = 4;
219     }
220     valueKey.display = Tk_Display(tkwin);
221     valueKey.screenNum = Tk_ScreenNumber(tkwin);
222     valueKey.depth = Tk_Depth(tkwin);
223     valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable,
224     (char *) &valueKey, &new);
225     if (!new) {
226     gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr);
227     gcPtr->refCount++;
228     return gcPtr->gc;
229     }
230    
231     /*
232     * No GC is currently available for this set of values. Allocate a
233     * new GC and add a new structure to the database.
234     */
235    
236     gcPtr = (TkGC *) ckalloc(sizeof(TkGC));
237    
238     /*
239     * Find or make a drawable to use to specify the screen and depth
240     * of the GC. We may have to make a small pixmap, to avoid doing
241     * Tk_MakeWindowExist on the window.
242     */
243    
244     freeDrawable = None;
245     if (Tk_WindowId(tkwin) != None) {
246     d = Tk_WindowId(tkwin);
247     } else if (valueKey.depth ==
248     DefaultDepth(valueKey.display, valueKey.screenNum)) {
249     d = RootWindow(valueKey.display, valueKey.screenNum);
250     } else {
251     d = Tk_GetPixmap(valueKey.display,
252     RootWindow(valueKey.display, valueKey.screenNum),
253     1, 1, valueKey.depth);
254     freeDrawable = d;
255     }
256    
257     gcPtr->gc = XCreateGC(valueKey.display, d, valueMask, &valueKey.values);
258     gcPtr->display = valueKey.display;
259     gcPtr->refCount = 1;
260     gcPtr->valueHashPtr = valueHashPtr;
261     idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable,
262     (char *) gcPtr->gc, &new);
263     if (!new) {
264     panic("GC already registered in Tk_GetGC");
265     }
266     Tcl_SetHashValue(valueHashPtr, gcPtr);
267     Tcl_SetHashValue(idHashPtr, gcPtr);
268     if (freeDrawable != None) {
269     Tk_FreePixmap(valueKey.display, freeDrawable);
270     }
271    
272     return gcPtr->gc;
273     }
274    
275     /*
276     *----------------------------------------------------------------------
277     *
278     * Tk_FreeGC --
279     *
280     * This procedure is called to release a graphics context allocated by
281     * Tk_GetGC.
282     *
283     * Results:
284     * None.
285     *
286     * Side effects:
287     * The reference count associated with gc is decremented, and
288     * gc is officially deallocated if no-one is using it anymore.
289     *
290     *----------------------------------------------------------------------
291     */
292    
293     void
294     Tk_FreeGC(display, gc)
295     Display *display; /* Display for which gc was allocated. */
296     GC gc; /* Graphics context to be released. */
297     {
298     Tcl_HashEntry *idHashPtr;
299     register TkGC *gcPtr;
300     TkDisplay *dispPtr = TkGetDisplay(display);
301    
302     if (!dispPtr->gcInit) {
303     panic("Tk_FreeGC called before Tk_GetGC");
304     }
305    
306     idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc);
307     if (idHashPtr == NULL) {
308     panic("Tk_FreeGC received unknown gc argument");
309     }
310     gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr);
311     gcPtr->refCount--;
312     if (gcPtr->refCount == 0) {
313     Tk_FreeXId(gcPtr->display, (XID) XGContextFromGC(gcPtr->gc));
314     XFreeGC(gcPtr->display, gcPtr->gc);
315     Tcl_DeleteHashEntry(gcPtr->valueHashPtr);
316     Tcl_DeleteHashEntry(idHashPtr);
317     ckfree((char *) gcPtr);
318     }
319     }
320    
321     /*
322     *----------------------------------------------------------------------
323     *
324     * GCInit --
325     *
326     * Initialize the structures used for GC management.
327     *
328     * Results:
329     * None.
330     *
331     * Side effects:
332     * Read the code.
333     *
334     *----------------------------------------------------------------------
335     */
336    
337     static void
338     GCInit(dispPtr)
339     TkDisplay *dispPtr;
340     {
341     dispPtr->gcInit = 1;
342     Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int));
343     Tcl_InitHashTable(&dispPtr->gcIdTable, TCL_ONE_WORD_KEYS);
344     }
345    
346     /* End of tkgc.c */

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25