]> Pileus Git - ~andy/gtk/blob - gtk/gtkgc.c
Initial revision
[~andy/gtk] / gtk / gtkgc.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include "gtkgc.h"
19
20
21 typedef struct _GtkGCKey       GtkGCKey;
22 typedef struct _GtkGCDrawable  GtkGCDrawable;
23
24 struct _GtkGCKey
25 {
26   gint depth;
27   GdkColormap *colormap;
28   GdkGCValues values;
29   GdkGCValuesMask mask;
30 };
31
32 struct _GtkGCDrawable
33 {
34   gint depth;
35   GdkPixmap *drawable;
36 };
37
38
39 static void      gtk_gc_init             (void);
40 static GtkGCKey* gtk_gc_key_dup          (GtkGCKey      *key);
41 static void      gtk_gc_key_destroy      (GtkGCKey      *key);
42 static gpointer  gtk_gc_new              (gpointer       key);
43 static void      gtk_gc_destroy          (gpointer       value);
44 static guint     gtk_gc_key_hash         (gpointer       key);
45 static guint     gtk_gc_value_hash       (gpointer       value);
46 static gint      gtk_gc_key_compare      (gpointer       a,
47                                           gpointer       b);
48 static guint     gtk_gc_drawable_hash    (GtkGCDrawable *d);
49 static gint      gtk_gc_drawable_compare (GtkGCDrawable *a,
50                                           GtkGCDrawable *b);
51
52
53 static gint initialize = TRUE;
54 static GCache *gc_cache = NULL;
55 static GHashTable *gc_drawable_ht = NULL;
56
57 static GMemChunk *key_mem_chunk = NULL;
58
59
60 GdkGC*
61 gtk_gc_get (gint             depth,
62             GdkColormap     *colormap,
63             GdkGCValues     *values,
64             GdkGCValuesMask  values_mask)
65 {
66   GtkGCKey key;
67   GdkGC *gc;
68
69   if (initialize)
70     gtk_gc_init ();
71
72   key.depth = depth;
73   key.colormap = colormap;
74   key.values = *values;
75   key.mask = values_mask;
76
77   gc = g_cache_insert (gc_cache, &key);
78
79   return gc;
80 }
81
82 void
83 gtk_gc_release (GdkGC *gc)
84 {
85   if (initialize)
86     gtk_gc_init ();
87
88   g_cache_remove (gc_cache, gc);
89 }
90
91
92 static void
93 gtk_gc_init ()
94 {
95   initialize = FALSE;
96
97   gc_cache = g_cache_new ((GCacheNewFunc) gtk_gc_new,
98                           (GCacheDestroyFunc) gtk_gc_destroy,
99                           (GCacheDupFunc) gtk_gc_key_dup,
100                           (GCacheDestroyFunc) gtk_gc_key_destroy,
101                           (GHashFunc) gtk_gc_key_hash,
102                           (GHashFunc) gtk_gc_value_hash,
103                           (GCompareFunc) gtk_gc_key_compare);
104
105   gc_drawable_ht = g_hash_table_new ((GHashFunc) gtk_gc_drawable_hash,
106                                      (GCompareFunc) gtk_gc_drawable_compare);
107 }
108
109 static GtkGCKey*
110 gtk_gc_key_dup (GtkGCKey *key)
111 {
112   GtkGCKey *new_key;
113
114   if (!key_mem_chunk)
115     key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkGCKey),
116                                      1024, G_ALLOC_AND_FREE);
117
118   new_key = g_chunk_new (GtkGCKey, key_mem_chunk);
119
120   *new_key = *key;
121
122   return new_key;
123 }
124
125 static void
126 gtk_gc_key_destroy (GtkGCKey *key)
127 {
128   g_mem_chunk_free (key_mem_chunk, key);
129 }
130
131 static gpointer
132 gtk_gc_new (gpointer key)
133 {
134   GtkGCKey *keyval;
135   GtkGCDrawable *drawable;
136   GdkGC *gc;
137
138   keyval = key;
139
140   drawable = g_hash_table_lookup (gc_drawable_ht, &keyval->depth);
141   if (!drawable)
142     {
143       drawable = g_new (GtkGCDrawable, 1);
144       drawable->depth = keyval->depth;
145       drawable->drawable = gdk_pixmap_new (NULL, 1, 1, drawable->depth);
146
147       g_hash_table_insert (gc_drawable_ht, &drawable->depth, drawable);
148     }
149
150   gc = gdk_gc_new_with_values (drawable->drawable, &keyval->values, keyval->mask);
151
152   return (gpointer) gc;
153 }
154
155 static void
156 gtk_gc_destroy (gpointer value)
157 {
158   gdk_gc_destroy ((GdkGC*) value);
159 }
160
161 static guint
162 gtk_gc_key_hash (gpointer key)
163 {
164   GtkGCKey *keyval;
165   guint hash_val;
166
167   keyval = key;
168   hash_val = 0;
169
170   if (keyval->mask & GDK_GC_FOREGROUND)
171     {
172       hash_val += keyval->values.foreground.pixel;
173     }
174   if (keyval->mask & GDK_GC_BACKGROUND)
175     {
176       hash_val += keyval->values.background.pixel;
177     }
178   if (keyval->mask & GDK_GC_FONT)
179     {
180       hash_val += gdk_font_id (keyval->values.font);
181     }
182   if (keyval->mask & GDK_GC_FUNCTION)
183     {
184       hash_val += (gint) keyval->values.function;
185     }
186   if (keyval->mask & GDK_GC_FILL)
187     {
188       hash_val += (gint) keyval->values.fill;
189     }
190   if (keyval->mask & GDK_GC_TILE)
191     {
192       hash_val += (glong) keyval->values.tile;
193     }
194   if (keyval->mask & GDK_GC_STIPPLE)
195     {
196       hash_val += (glong) keyval->values.stipple;
197     }
198   if (keyval->mask & GDK_GC_CLIP_MASK)
199     {
200       hash_val += (glong) keyval->values.clip_mask;
201     }
202   if (keyval->mask & GDK_GC_SUBWINDOW)
203     {
204       hash_val += (gint) keyval->values.subwindow_mode;
205     }
206   if (keyval->mask & GDK_GC_TS_X_ORIGIN)
207     {
208       hash_val += (gint) keyval->values.ts_x_origin;
209     }
210   if (keyval->mask & GDK_GC_TS_Y_ORIGIN)
211     {
212       hash_val += (gint) keyval->values.ts_y_origin;
213     }
214   if (keyval->mask & GDK_GC_CLIP_X_ORIGIN)
215     {
216       hash_val += (gint) keyval->values.clip_x_origin;
217     }
218   if (keyval->mask & GDK_GC_CLIP_Y_ORIGIN)
219     {
220       hash_val += (gint) keyval->values.clip_y_origin;
221     }
222   if (keyval->mask & GDK_GC_EXPOSURES)
223     {
224       hash_val += (gint) keyval->values.graphics_exposures;
225     }
226   if (keyval->mask & GDK_GC_LINE_WIDTH)
227     {
228       hash_val += (gint) keyval->values.line_width;
229     }
230   if (keyval->mask & GDK_GC_LINE_STYLE)
231     {
232       hash_val += (gint) keyval->values.line_style;
233     }
234   if (keyval->mask & GDK_GC_CAP_STYLE)
235     {
236       hash_val += (gint) keyval->values.cap_style;
237     }
238   if (keyval->mask & GDK_GC_JOIN_STYLE)
239     {
240       hash_val += (gint) keyval->values.join_style;
241     }
242
243   return hash_val;
244 }
245
246 static guint
247 gtk_gc_value_hash (gpointer value)
248 {
249   return (gulong) value;
250 }
251
252 static gint
253 gtk_gc_key_compare (gpointer a,
254                     gpointer b)
255 {
256   GtkGCKey *akey;
257   GtkGCKey *bkey;
258   GdkGCValues *avalues;
259   GdkGCValues *bvalues;
260
261   akey = a;
262   bkey = b;
263
264   avalues = &akey->values;
265   bvalues = &bkey->values;
266
267   if (akey->mask != bkey->mask)
268     return FALSE;
269
270   if (akey->depth != bkey->depth)
271     return FALSE;
272
273   if (akey->colormap != bkey->colormap)
274     return FALSE;
275
276   if (akey->mask & GDK_GC_FOREGROUND)
277     {
278       if (avalues->foreground.pixel != bvalues->foreground.pixel)
279         return FALSE;
280     }
281   if (akey->mask & GDK_GC_BACKGROUND)
282     {
283       if (avalues->background.pixel != bvalues->background.pixel)
284         return FALSE;
285     }
286   if (akey->mask & GDK_GC_FONT)
287     {
288       if (!gdk_font_equal (avalues->font, bvalues->font))
289         return FALSE;
290     }
291   if (akey->mask & GDK_GC_FUNCTION)
292     {
293       if (avalues->function != bvalues->function)
294         return FALSE;
295     }
296   if (akey->mask & GDK_GC_FILL)
297     {
298       if (avalues->fill != bvalues->fill)
299         return FALSE;
300     }
301   if (akey->mask & GDK_GC_TILE)
302     {
303       if (avalues->tile != bvalues->tile)
304         return FALSE;
305     }
306   if (akey->mask & GDK_GC_STIPPLE)
307     {
308       if (avalues->stipple != bvalues->stipple)
309         return FALSE;
310     }
311   if (akey->mask & GDK_GC_CLIP_MASK)
312     {
313       if (avalues->clip_mask != bvalues->clip_mask)
314         return FALSE;
315     }
316   if (akey->mask & GDK_GC_SUBWINDOW)
317     {
318       if (avalues->subwindow_mode != bvalues->subwindow_mode)
319         return FALSE;
320     }
321   if (akey->mask & GDK_GC_TS_X_ORIGIN)
322     {
323       if (avalues->ts_x_origin != bvalues->ts_x_origin)
324         return FALSE;
325     }
326   if (akey->mask & GDK_GC_TS_Y_ORIGIN)
327     {
328       if (avalues->ts_y_origin != bvalues->ts_y_origin)
329         return FALSE;
330     }
331   if (akey->mask & GDK_GC_CLIP_X_ORIGIN)
332     {
333       if (avalues->clip_x_origin != bvalues->clip_x_origin)
334         return FALSE;
335     }
336   if (akey->mask & GDK_GC_CLIP_Y_ORIGIN)
337     {
338       if (avalues->clip_y_origin != bvalues->clip_y_origin)
339         return FALSE;
340     }
341   if (akey->mask & GDK_GC_EXPOSURES)
342     {
343       if (avalues->graphics_exposures != bvalues->graphics_exposures)
344         return FALSE;
345     }
346   if (akey->mask & GDK_GC_LINE_WIDTH)
347     {
348       if (avalues->line_width != bvalues->line_width)
349         return FALSE;
350     }
351   if (akey->mask & GDK_GC_LINE_STYLE)
352     {
353       if (avalues->line_style != bvalues->line_style)
354         return FALSE;
355     }
356   if (akey->mask & GDK_GC_CAP_STYLE)
357     {
358       if (avalues->cap_style != bvalues->cap_style)
359         return FALSE;
360     }
361   if (akey->mask & GDK_GC_JOIN_STYLE)
362     {
363       if (avalues->join_style != bvalues->join_style)
364         return FALSE;
365     }
366
367   return TRUE;
368 }
369
370
371 static guint
372 gtk_gc_drawable_hash (GtkGCDrawable *d)
373 {
374   return d->depth;
375 }
376
377 static gint
378 gtk_gc_drawable_compare (GtkGCDrawable *a,
379                          GtkGCDrawable *b)
380 {
381   return (a->depth == b->depth);
382 }