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

Contents of /projs/trunk/shared_source/tk_base/tkgc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations) (download)
Fri Oct 14 01:50:00 2016 UTC (7 years, 5 months ago) by dashley
File MIME type: text/plain
File size: 10477 byte(s)
Move shared source code to commonize.
1 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkgc.c,v 1.1.1.1 2001/06/13 05:01:12 dtashley Exp $ */
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
347 /* $History: tkGC.c $
348 *
349 * ***************** Version 1 *****************
350 * User: Dtashley Date: 1/02/01 Time: 2:47a
351 * Created in $/IjuScripter, IjuConsole/Source/Tk Base
352 * Initial check-in.
353 */
354
355 /* End of TKGC.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25