]> Pileus Git - ~andy/gtk/blob - gtk/gtkgc.c
Updated Arabic translation
[~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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28 #include "gtkgc.h"
29 #include "gtkintl.h"
30 #include "gtkalias.h"
31
32
33 typedef struct _GtkGCKey       GtkGCKey;
34 typedef struct _GtkGCDrawable  GtkGCDrawable;
35
36 struct _GtkGCKey
37 {
38   gint depth;
39   GdkColormap *colormap;
40   GdkGCValues values;
41   GdkGCValuesMask mask;
42 };
43
44 struct _GtkGCDrawable
45 {
46   gint depth;
47   GdkPixmap *drawable;
48 };
49
50
51 static void      gtk_gc_init             (void);
52 static GtkGCKey* gtk_gc_key_dup          (GtkGCKey      *key);
53 static void      gtk_gc_key_destroy      (GtkGCKey      *key);
54 static gpointer  gtk_gc_new              (gpointer       key);
55 static void      gtk_gc_destroy          (gpointer       value);
56 static guint     gtk_gc_key_hash         (gpointer       key);
57 static guint     gtk_gc_value_hash       (gpointer       value);
58 static gint      gtk_gc_key_equal        (gpointer       a,
59                                           gpointer       b);
60 static guint     gtk_gc_drawable_hash    (GtkGCDrawable *d);
61 static gint      gtk_gc_drawable_equal   (GtkGCDrawable *a,
62                                           GtkGCDrawable *b);
63
64
65 static gint initialize = TRUE;
66 static GCache *gc_cache = NULL;
67 static GQuark quark_gtk_gc_drawable_ht = 0;
68
69 GdkGC*
70 gtk_gc_get (gint             depth,
71             GdkColormap     *colormap,
72             GdkGCValues     *values,
73             GdkGCValuesMask  values_mask)
74 {
75   GtkGCKey key;
76   GdkGC *gc;
77
78   if (initialize)
79     gtk_gc_init ();
80
81   key.depth = depth;
82   key.colormap = colormap;
83   key.values = *values;
84   key.mask = values_mask;
85
86   gc = g_cache_insert (gc_cache, &key);
87
88   return gc;
89 }
90
91 void
92 gtk_gc_release (GdkGC *gc)
93 {
94   if (initialize)
95     gtk_gc_init ();
96
97   g_cache_remove (gc_cache, gc);
98 }
99
100 static void 
101 free_gc_drawable (gpointer data)
102 {
103   GtkGCDrawable *drawable = data;
104   g_object_unref (drawable->drawable);
105   g_slice_free (GtkGCDrawable, drawable);
106 }
107
108 static GHashTable*
109 gtk_gc_get_drawable_ht (GdkScreen *screen)
110 {
111   GHashTable *ht = g_object_get_qdata (G_OBJECT (screen), quark_gtk_gc_drawable_ht);
112   if (!ht)
113     {
114       ht = g_hash_table_new_full ((GHashFunc) gtk_gc_drawable_hash,
115                                   (GEqualFunc) gtk_gc_drawable_equal,
116                                   NULL, free_gc_drawable);
117       g_object_set_qdata_full (G_OBJECT (screen), 
118                                quark_gtk_gc_drawable_ht, ht, 
119                                (GDestroyNotify)g_hash_table_destroy);
120     }
121   
122   return ht;
123 }
124
125 static void
126 gtk_gc_init (void)
127 {
128   initialize = FALSE;
129
130   quark_gtk_gc_drawable_ht = g_quark_from_static_string ("gtk-gc-drawable-ht");
131
132   gc_cache = g_cache_new ((GCacheNewFunc) gtk_gc_new,
133                           (GCacheDestroyFunc) gtk_gc_destroy,
134                           (GCacheDupFunc) gtk_gc_key_dup,
135                           (GCacheDestroyFunc) gtk_gc_key_destroy,
136                           (GHashFunc) gtk_gc_key_hash,
137                           (GHashFunc) gtk_gc_value_hash,
138                           (GEqualFunc) gtk_gc_key_equal);
139 }
140
141 static GtkGCKey*
142 gtk_gc_key_dup (GtkGCKey *key)
143 {
144   GtkGCKey *new_key;
145
146   new_key = g_slice_new (GtkGCKey);
147
148   *new_key = *key;
149
150   return new_key;
151 }
152
153 static void
154 gtk_gc_key_destroy (GtkGCKey *key)
155 {
156   g_slice_free (GtkGCKey, key);
157 }
158
159 static gpointer
160 gtk_gc_new (gpointer key)
161 {
162   GtkGCKey *keyval;
163   GtkGCDrawable *drawable;
164   GdkGC *gc;
165   GHashTable *ht;
166   GdkScreen *screen;
167
168   keyval = key;
169   screen = gdk_colormap_get_screen (keyval->colormap);
170   
171   ht = gtk_gc_get_drawable_ht (screen);
172   drawable = g_hash_table_lookup (ht, &keyval->depth);
173   if (!drawable)
174     {
175       drawable = g_slice_new (GtkGCDrawable);
176       drawable->depth = keyval->depth;
177       drawable->drawable = gdk_pixmap_new (gdk_screen_get_root_window (screen), 
178                                            1, 1, drawable->depth);
179       g_hash_table_insert (ht, &drawable->depth, drawable);
180     }
181
182   gc = gdk_gc_new_with_values (drawable->drawable, &keyval->values, keyval->mask);
183   gdk_gc_set_colormap (gc, keyval->colormap);
184
185   return (gpointer) gc;
186 }
187
188 static void
189 gtk_gc_destroy (gpointer value)
190 {
191   g_object_unref (value);
192 }
193
194 static guint
195 gtk_gc_key_hash (gpointer key)
196 {
197   GtkGCKey *keyval;
198   guint hash_val;
199
200   keyval = key;
201   hash_val = 0;
202
203   if (keyval->mask & GDK_GC_FOREGROUND)
204     {
205       hash_val += keyval->values.foreground.pixel;
206     }
207   if (keyval->mask & GDK_GC_BACKGROUND)
208     {
209       hash_val += keyval->values.background.pixel;
210     }
211   if (keyval->mask & GDK_GC_FONT)
212     {
213       hash_val += gdk_font_id (keyval->values.font);
214     }
215   if (keyval->mask & GDK_GC_FUNCTION)
216     {
217       hash_val += (gint) keyval->values.function;
218     }
219   if (keyval->mask & GDK_GC_FILL)
220     {
221       hash_val += (gint) keyval->values.fill;
222     }
223   if (keyval->mask & GDK_GC_TILE)
224     {
225       hash_val += (gintptr) keyval->values.tile;
226     }
227   if (keyval->mask & GDK_GC_STIPPLE)
228     {
229       hash_val += (gintptr) keyval->values.stipple;
230     }
231   if (keyval->mask & GDK_GC_CLIP_MASK)
232     {
233       hash_val += (gintptr) keyval->values.clip_mask;
234     }
235   if (keyval->mask & GDK_GC_SUBWINDOW)
236     {
237       hash_val += (gint) keyval->values.subwindow_mode;
238     }
239   if (keyval->mask & GDK_GC_TS_X_ORIGIN)
240     {
241       hash_val += (gint) keyval->values.ts_x_origin;
242     }
243   if (keyval->mask & GDK_GC_TS_Y_ORIGIN)
244     {
245       hash_val += (gint) keyval->values.ts_y_origin;
246     }
247   if (keyval->mask & GDK_GC_CLIP_X_ORIGIN)
248     {
249       hash_val += (gint) keyval->values.clip_x_origin;
250     }
251   if (keyval->mask & GDK_GC_CLIP_Y_ORIGIN)
252     {
253       hash_val += (gint) keyval->values.clip_y_origin;
254     }
255   if (keyval->mask & GDK_GC_EXPOSURES)
256     {
257       hash_val += (gint) keyval->values.graphics_exposures;
258     }
259   if (keyval->mask & GDK_GC_LINE_WIDTH)
260     {
261       hash_val += (gint) keyval->values.line_width;
262     }
263   if (keyval->mask & GDK_GC_LINE_STYLE)
264     {
265       hash_val += (gint) keyval->values.line_style;
266     }
267   if (keyval->mask & GDK_GC_CAP_STYLE)
268     {
269       hash_val += (gint) keyval->values.cap_style;
270     }
271   if (keyval->mask & GDK_GC_JOIN_STYLE)
272     {
273       hash_val += (gint) keyval->values.join_style;
274     }
275
276   return hash_val;
277 }
278
279 static guint
280 gtk_gc_value_hash (gpointer value)
281 {
282   return (gulong) value;
283 }
284
285 static gboolean
286 gtk_gc_key_equal (gpointer a,
287                   gpointer b)
288 {
289   GtkGCKey *akey;
290   GtkGCKey *bkey;
291   GdkGCValues *avalues;
292   GdkGCValues *bvalues;
293
294   akey = a;
295   bkey = b;
296
297   avalues = &akey->values;
298   bvalues = &bkey->values;
299
300   if (akey->mask != bkey->mask)
301     return FALSE;
302
303   if (akey->depth != bkey->depth)
304     return FALSE;
305
306   if (akey->colormap != bkey->colormap)
307     return FALSE;
308
309   if (akey->mask & GDK_GC_FOREGROUND)
310     {
311       if (avalues->foreground.pixel != bvalues->foreground.pixel)
312         return FALSE;
313     }
314   if (akey->mask & GDK_GC_BACKGROUND)
315     {
316       if (avalues->background.pixel != bvalues->background.pixel)
317         return FALSE;
318     }
319   if (akey->mask & GDK_GC_FONT)
320     {
321       if (!gdk_font_equal (avalues->font, bvalues->font))
322         return FALSE;
323     }
324   if (akey->mask & GDK_GC_FUNCTION)
325     {
326       if (avalues->function != bvalues->function)
327         return FALSE;
328     }
329   if (akey->mask & GDK_GC_FILL)
330     {
331       if (avalues->fill != bvalues->fill)
332         return FALSE;
333     }
334   if (akey->mask & GDK_GC_TILE)
335     {
336       if (avalues->tile != bvalues->tile)
337         return FALSE;
338     }
339   if (akey->mask & GDK_GC_STIPPLE)
340     {
341       if (avalues->stipple != bvalues->stipple)
342         return FALSE;
343     }
344   if (akey->mask & GDK_GC_CLIP_MASK)
345     {
346       if (avalues->clip_mask != bvalues->clip_mask)
347         return FALSE;
348     }
349   if (akey->mask & GDK_GC_SUBWINDOW)
350     {
351       if (avalues->subwindow_mode != bvalues->subwindow_mode)
352         return FALSE;
353     }
354   if (akey->mask & GDK_GC_TS_X_ORIGIN)
355     {
356       if (avalues->ts_x_origin != bvalues->ts_x_origin)
357         return FALSE;
358     }
359   if (akey->mask & GDK_GC_TS_Y_ORIGIN)
360     {
361       if (avalues->ts_y_origin != bvalues->ts_y_origin)
362         return FALSE;
363     }
364   if (akey->mask & GDK_GC_CLIP_X_ORIGIN)
365     {
366       if (avalues->clip_x_origin != bvalues->clip_x_origin)
367         return FALSE;
368     }
369   if (akey->mask & GDK_GC_CLIP_Y_ORIGIN)
370     {
371       if (avalues->clip_y_origin != bvalues->clip_y_origin)
372         return FALSE;
373     }
374   if (akey->mask & GDK_GC_EXPOSURES)
375     {
376       if (avalues->graphics_exposures != bvalues->graphics_exposures)
377         return FALSE;
378     }
379   if (akey->mask & GDK_GC_LINE_WIDTH)
380     {
381       if (avalues->line_width != bvalues->line_width)
382         return FALSE;
383     }
384   if (akey->mask & GDK_GC_LINE_STYLE)
385     {
386       if (avalues->line_style != bvalues->line_style)
387         return FALSE;
388     }
389   if (akey->mask & GDK_GC_CAP_STYLE)
390     {
391       if (avalues->cap_style != bvalues->cap_style)
392         return FALSE;
393     }
394   if (akey->mask & GDK_GC_JOIN_STYLE)
395     {
396       if (avalues->join_style != bvalues->join_style)
397         return FALSE;
398     }
399
400   return TRUE;
401 }
402
403 static guint
404 gtk_gc_drawable_hash (GtkGCDrawable *d)
405 {
406   return d->depth;
407 }
408
409 static gboolean
410 gtk_gc_drawable_equal (GtkGCDrawable *a,
411                        GtkGCDrawable *b)
412 {
413   return (a->depth == b->depth);
414 }
415
416 #define __GTK_GC_C__
417 #include "gtkaliasdef.c"