|
|
1.1 ! root 1: /* ! 2: * tkGC.c -- ! 3: * ! 4: * This file maintains a database of read-only graphics contexts ! 5: * for the Tk toolkit, in order to allow GC's to be shared. ! 6: * ! 7: * Copyright 1990 Regents of the University of California ! 8: * Permission to use, copy, modify, and distribute this ! 9: * software and its documentation for any purpose and without ! 10: * fee is hereby granted, provided that the above copyright ! 11: * notice appear in all copies. The University of California ! 12: * makes no representations about the suitability of this ! 13: * software for any purpose. It is provided "as is" without ! 14: * express or implied warranty. ! 15: */ ! 16: ! 17: #ifndef lint ! 18: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkGC.c,v 1.9 92/05/13 08:48:45 ouster Exp $ SPRITE (Berkeley)"; ! 19: #endif /* not lint */ ! 20: ! 21: #include "tkconfig.h" ! 22: #include "tk.h" ! 23: ! 24: /* ! 25: * One of the following data structures exists for each GC that is ! 26: * currently active. The structure is indexed with two hash tables, ! 27: * one based on font name and one based on XFontStruct address. ! 28: */ ! 29: ! 30: typedef struct { ! 31: GC gc; /* Graphics context. */ ! 32: Display *display; /* Display to which gc belongs. */ ! 33: int refCount; /* Number of active uses of gc. */ ! 34: Tcl_HashEntry *valueHashPtr;/* Entry in valueTable (needed when deleting ! 35: * this structure). */ ! 36: } TkGC; ! 37: ! 38: /* ! 39: * Hash table to map from a GC's values to a TkGC structure describing ! 40: * a GC with those values (used by Tk_GetGC). ! 41: */ ! 42: ! 43: static Tcl_HashTable valueTable; ! 44: typedef struct { ! 45: XGCValues values; /* Desired values for GC. */ ! 46: Screen *screen; /* Screen for which GC is valid. */ ! 47: } ValueKey; ! 48: ! 49: /* ! 50: * Hash table for GC -> TkGC mapping. This table is indexed by the ! 51: * GC identifier, and is used by Tk_FreeGC. ! 52: */ ! 53: ! 54: static Tcl_HashTable idTable; ! 55: ! 56: static int initialized = 0; /* 0 means static structures haven't been ! 57: * initialized yet. */ ! 58: ! 59: /* ! 60: * Forward declarations for procedures defined in this file: ! 61: */ ! 62: ! 63: static void GCInit _ANSI_ARGS_((void)); ! 64: ! 65: /* ! 66: *---------------------------------------------------------------------- ! 67: * ! 68: * Tk_GetGC -- ! 69: * ! 70: * Given a desired set of values for a graphics context, find ! 71: * a read-only graphics context with the desired values. ! 72: * ! 73: * Results: ! 74: * The return value is the X identifer for the desired graphics ! 75: * context. The caller should never modify this GC, and should ! 76: * call Tk_FreeGC when the GC is no longer needed. ! 77: * ! 78: * Side effects: ! 79: * The GC is added to an internal database with a reference count. ! 80: * For each call to this procedure, there should eventually be a call ! 81: * to Tk_FreeGC, so that the database can be cleaned up when GC's ! 82: * aren't needed anymore. ! 83: * ! 84: *---------------------------------------------------------------------- ! 85: */ ! 86: ! 87: GC ! 88: Tk_GetGC(tkwin, valueMask, valuePtr) ! 89: Tk_Window tkwin; /* Window in which GC will be used. */ ! 90: register unsigned long valueMask; ! 91: /* 1 bits correspond to values specified ! 92: * in *valuesPtr; other values are set ! 93: * from defaults. */ ! 94: register XGCValues *valuePtr; ! 95: /* Values are specified here for bits set ! 96: * in valueMask. */ ! 97: { ! 98: ValueKey key; ! 99: Tcl_HashEntry *valueHashPtr, *idHashPtr; ! 100: register TkGC *gcPtr; ! 101: int new; ! 102: ! 103: if (!initialized) { ! 104: GCInit(); ! 105: } ! 106: ! 107: /* ! 108: * Must zero key at start to clear out pad bytes that may be ! 109: * part of structure on some systems. ! 110: */ ! 111: ! 112: memset((VOID *) &key, 0, sizeof(key)); ! 113: ! 114: /* ! 115: * First, check to see if there's already a GC that will work ! 116: * for this request (exact matches only, sorry). ! 117: */ ! 118: ! 119: if (valueMask & GCFunction) { ! 120: key.values.function = valuePtr->function; ! 121: } else { ! 122: key.values.function = GXcopy; ! 123: } ! 124: if (valueMask & GCPlaneMask) { ! 125: key.values.plane_mask = valuePtr->plane_mask; ! 126: } else { ! 127: key.values.plane_mask = ~0; ! 128: } ! 129: if (valueMask & GCForeground) { ! 130: key.values.foreground = valuePtr->foreground; ! 131: } else { ! 132: key.values.foreground = 0; ! 133: } ! 134: if (valueMask & GCBackground) { ! 135: key.values.background = valuePtr->background; ! 136: } else { ! 137: key.values.background = 1; ! 138: } ! 139: if (valueMask & GCLineWidth) { ! 140: key.values.line_width = valuePtr->line_width; ! 141: } else { ! 142: key.values.line_width = 0; ! 143: } ! 144: if (valueMask & GCLineStyle) { ! 145: key.values.line_style = valuePtr->line_style; ! 146: } else { ! 147: key.values.line_style = LineSolid; ! 148: } ! 149: if (valueMask & GCCapStyle) { ! 150: key.values.cap_style = valuePtr->cap_style; ! 151: } else { ! 152: key.values.cap_style = CapButt; ! 153: } ! 154: if (valueMask & GCJoinStyle) { ! 155: key.values.join_style = valuePtr->join_style; ! 156: } else { ! 157: key.values.join_style = JoinMiter; ! 158: } ! 159: if (valueMask & GCFillStyle) { ! 160: key.values.fill_style = valuePtr->fill_style; ! 161: } else { ! 162: key.values.fill_style = FillSolid; ! 163: } ! 164: if (valueMask & GCFillRule) { ! 165: key.values.fill_rule = valuePtr->fill_rule; ! 166: } else { ! 167: key.values.fill_rule = EvenOddRule; ! 168: } ! 169: if (valueMask & GCArcMode) { ! 170: key.values.arc_mode = valuePtr->arc_mode; ! 171: } else { ! 172: key.values.arc_mode = ArcPieSlice; ! 173: } ! 174: if (valueMask & GCTile) { ! 175: key.values.tile = valuePtr->tile; ! 176: } else { ! 177: key.values.tile = None; ! 178: } ! 179: if (valueMask & GCStipple) { ! 180: key.values.stipple = valuePtr->stipple; ! 181: } else { ! 182: key.values.stipple = None; ! 183: } ! 184: if (valueMask & GCTileStipXOrigin) { ! 185: key.values.ts_x_origin = valuePtr->ts_x_origin; ! 186: } else { ! 187: key.values.ts_x_origin = 0; ! 188: } ! 189: if (valueMask & GCTileStipYOrigin) { ! 190: key.values.ts_y_origin = valuePtr->ts_y_origin; ! 191: } else { ! 192: key.values.ts_y_origin = 0; ! 193: } ! 194: if (valueMask & GCFont) { ! 195: key.values.font = valuePtr->font; ! 196: } else { ! 197: key.values.font = None; ! 198: } ! 199: if (valueMask & GCSubwindowMode) { ! 200: key.values.subwindow_mode = valuePtr->subwindow_mode; ! 201: } else { ! 202: key.values.subwindow_mode = ClipByChildren; ! 203: } ! 204: if (valueMask & GCGraphicsExposures) { ! 205: key.values.graphics_exposures = valuePtr->graphics_exposures; ! 206: } else { ! 207: key.values.graphics_exposures = True; ! 208: } ! 209: if (valueMask & GCClipXOrigin) { ! 210: key.values.clip_x_origin = valuePtr->clip_x_origin; ! 211: } else { ! 212: key.values.clip_x_origin = 0; ! 213: } ! 214: if (valueMask & GCClipYOrigin) { ! 215: key.values.clip_y_origin = valuePtr->clip_y_origin; ! 216: } else { ! 217: key.values.clip_y_origin = 0; ! 218: } ! 219: if (valueMask & GCClipMask) { ! 220: key.values.clip_mask = valuePtr->clip_mask; ! 221: } else { ! 222: key.values.clip_mask = None; ! 223: } ! 224: if (valueMask & GCDashOffset) { ! 225: key.values.dash_offset = valuePtr->dash_offset; ! 226: } else { ! 227: key.values.dash_offset = 0; ! 228: } ! 229: if (valueMask & GCDashList) { ! 230: key.values.dashes = valuePtr->dashes; ! 231: } else { ! 232: key.values.dashes = 4; ! 233: } ! 234: key.screen = Tk_Screen(tkwin); ! 235: valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &key, &new); ! 236: if (!new) { ! 237: gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr); ! 238: gcPtr->refCount++; ! 239: return gcPtr->gc; ! 240: } ! 241: ! 242: /* ! 243: * No GC is currently available for this set of values. Allocate a ! 244: * new GC and add a new structure to the database. ! 245: */ ! 246: ! 247: gcPtr = (TkGC *) ckalloc(sizeof(TkGC)); ! 248: #if 0 ! 249: gcPtr->gc = XCreateGC(Tk_Display(tkwin), ! 250: RootWindowOfScreen(Tk_Screen(tkwin)), ! 251: valueMask, &key.values); ! 252: #else ! 253: gcPtr->gc = XCreateGC(Tk_Display(tkwin), ! 254: Tk_DefaultPixmap(Tk_Screen(tkwin)), ! 255: valueMask, &key.values); ! 256: #endif ! 257: gcPtr->display = Tk_Display(tkwin); ! 258: gcPtr->refCount = 1; ! 259: gcPtr->valueHashPtr = valueHashPtr; ! 260: idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) gcPtr->gc, &new); ! 261: if (!new) { ! 262: panic("GC already registered in Tk_GetGC"); ! 263: } ! 264: Tcl_SetHashValue(valueHashPtr, gcPtr); ! 265: Tcl_SetHashValue(idHashPtr, gcPtr); ! 266: return gcPtr->gc; ! 267: } ! 268: ! 269: /* ! 270: *---------------------------------------------------------------------- ! 271: * ! 272: * Tk_FreeGC -- ! 273: * ! 274: * This procedure is called to release a font allocated by ! 275: * Tk_GetGC. ! 276: * ! 277: * Results: ! 278: * None. ! 279: * ! 280: * Side effects: ! 281: * The reference count associated with gc is decremented, and ! 282: * gc is officially deallocated if no-one is using it anymore. ! 283: * ! 284: *---------------------------------------------------------------------- ! 285: */ ! 286: ! 287: void ! 288: Tk_FreeGC(gc) ! 289: GC gc; /* Graphics context to be released. */ ! 290: { ! 291: Tcl_HashEntry *idHashPtr; ! 292: register TkGC *gcPtr; ! 293: ! 294: if (!initialized) { ! 295: panic("Tk_FreeGC called before Tk_GetGC"); ! 296: } ! 297: ! 298: idHashPtr = Tcl_FindHashEntry(&idTable, (char *) gc); ! 299: if (idHashPtr == NULL) { ! 300: panic("Tk_FreeGC received unknown gc argument"); ! 301: } ! 302: gcPtr = (TkGC *) Tcl_GetHashValue(idHashPtr); ! 303: gcPtr->refCount--; ! 304: if (gcPtr->refCount == 0) { ! 305: XFreeGC(gcPtr->display, gcPtr->gc); ! 306: Tcl_DeleteHashEntry(gcPtr->valueHashPtr); ! 307: Tcl_DeleteHashEntry(idHashPtr); ! 308: ckfree((char *) gcPtr); ! 309: } ! 310: } ! 311: ! 312: /* ! 313: *---------------------------------------------------------------------- ! 314: * ! 315: * GCInit -- ! 316: * ! 317: * Initialize the structures used for GC management. ! 318: * ! 319: * Results: ! 320: * None. ! 321: * ! 322: * Side effects: ! 323: * Read the code. ! 324: * ! 325: *---------------------------------------------------------------------- ! 326: */ ! 327: ! 328: static void ! 329: GCInit() ! 330: { ! 331: initialized = 1; ! 332: Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int)); ! 333: Tcl_InitHashTable(&idTable, TCL_ONE_WORD_KEYS); ! 334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.