]> Pileus Git - ~andy/gtk/blob - gdk/gdkfont.c
restricted the --g*fatal-* arguments to --g-fatal-warnings again. this
[~andy/gtk] / gdk / gdkfont.c
1 /* GDK - The GIMP Drawing Kit
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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <X11/Xlib.h>
20 #include <X11/Xos.h>
21 #include "gdk.h"
22 #include "gdkprivate.h"
23
24 GdkFont*
25 gdk_font_load (const gchar *font_name)
26 {
27   GdkFont *font;
28   GdkFontPrivate *private;
29
30   private = g_new (GdkFontPrivate, 1);
31   font = (GdkFont*) private;
32
33   private->xdisplay = gdk_display;
34   private->xfont = XLoadQueryFont (private->xdisplay, font_name);
35   private->ref_count = 1;
36
37   if (!private->xfont)
38     {
39       g_free (font);
40       return NULL;
41     }
42   else
43     {
44       font->type = GDK_FONT_FONT;
45       font->ascent =  ((XFontStruct *) private->xfont)->ascent;
46       font->descent = ((XFontStruct *) private->xfont)->descent;
47     }
48
49   gdk_xid_table_insert (&((XFontStruct *) private->xfont)->fid, font);
50
51   return font;
52 }
53
54 GdkFont*
55 gdk_fontset_load (gchar *fontset_name)
56 {
57   GdkFont *font;
58   GdkFontPrivate *private;
59   XFontSet fontset;
60   gint  missing_charset_count;
61   gchar **missing_charset_list;
62   gchar *def_string;
63
64   private = g_new (GdkFontPrivate, 1);
65   font = (GdkFont*) private;
66
67   private->xdisplay = gdk_display;
68   fontset = XCreateFontSet (gdk_display, fontset_name,
69                             &missing_charset_list, &missing_charset_count,
70                             &def_string);
71
72   if (missing_charset_count)
73     {
74       gint i;
75       g_message ("Missing charsets in FontSet creation\n");
76       for (i=0;i<missing_charset_count;i++)
77         g_message ("    %s\n", missing_charset_list[i]);
78       XFreeStringList (missing_charset_list);
79     }
80
81   private->ref_count = 1;
82
83   if (!fontset)
84     {
85       g_free (font);
86       return NULL;
87     }
88   else
89     {
90       gint num_fonts;
91       gint i;
92       XFontStruct **font_structs;
93       gchar **font_names;
94       
95       private->xfont = fontset;
96       font->type = GDK_FONT_FONTSET;
97       num_fonts = XFontsOfFontSet (fontset, &font_structs, &font_names);
98
99       font->ascent = font->descent = 0;
100       
101       for (i = 0; i < num_fonts; i++)
102         {
103           font->ascent = MAX (font->ascent, font_structs[i]->ascent);
104           font->descent = MAX (font->descent, font_structs[i]->descent);
105         }
106     }
107   return font;
108 }
109
110 GdkFont*
111 gdk_font_ref (GdkFont *font)
112 {
113   GdkFontPrivate *private;
114
115   g_return_val_if_fail (font != NULL, NULL);
116
117   private = (GdkFontPrivate*) font;
118   private->ref_count += 1;
119   return font;
120 }
121
122 void
123 gdk_font_unref (GdkFont *font)
124 {
125   GdkFontPrivate *private;
126
127   g_return_if_fail (font != NULL);
128
129   private = (GdkFontPrivate*) font;
130
131   private->ref_count -= 1;
132   if (private->ref_count == 0)
133     {
134       switch (font->type)
135         {
136         case GDK_FONT_FONT:
137           gdk_xid_table_remove (((XFontStruct *) private->xfont)->fid);
138           XFreeFont (private->xdisplay, (XFontStruct *) private->xfont);
139           break;
140         case GDK_FONT_FONTSET:
141           XFreeFontSet (private->xdisplay, (XFontSet) private->xfont);
142           break;
143         default:
144           g_error ("unknown font type.");
145           break;
146         }
147       g_free (font);
148     }
149 }
150
151 gint
152 gdk_font_id (const GdkFont *font)
153 {
154   const GdkFontPrivate *font_private;
155
156   g_return_val_if_fail (font != NULL, 0);
157
158   font_private = (const GdkFontPrivate*) font;
159
160   if (font->type == GDK_FONT_FONT)
161     {
162       return ((XFontStruct *) font_private->xfont)->fid;
163     }
164   else
165     {
166       return 0;
167     }
168 }
169
170 gint
171 gdk_font_equal (const GdkFont *fonta,
172                 const GdkFont *fontb)
173 {
174   const GdkFontPrivate *privatea;
175   const GdkFontPrivate *privateb;
176
177   g_return_val_if_fail (fonta != NULL, FALSE);
178   g_return_val_if_fail (fontb != NULL, FALSE);
179
180   privatea = (const GdkFontPrivate*) fonta;
181   privateb = (const GdkFontPrivate*) fontb;
182
183   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
184     {
185       return (((XFontStruct *) privatea->xfont)->fid ==
186               ((XFontStruct *) privateb->xfont)->fid);
187     }
188   else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
189     {
190       /* how to compare two fontsets ?? by basename or XFontSet ?? */
191       return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont));
192     }
193   else
194     /* fontset != font */
195     return 0;
196 }
197
198 gint
199 gdk_string_width (GdkFont     *font,
200                   const gchar *string)
201 {
202   GdkFontPrivate *font_private;
203   gint width;
204   XFontStruct *xfont;
205   XFontSet fontset;
206
207   g_return_val_if_fail (font != NULL, -1);
208   g_return_val_if_fail (string != NULL, -1);
209
210   font_private = (GdkFontPrivate*) font;
211
212   switch (font->type)
213     {
214     case GDK_FONT_FONT:
215       xfont = (XFontStruct *) font_private->xfont;
216       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
217         {
218           width = XTextWidth (xfont, string, strlen (string));
219         }
220       else
221         {
222           width = XTextWidth16 (xfont, (XChar2b *) string, strlen (string) / 2);
223         }
224       break;
225     case GDK_FONT_FONTSET:
226       fontset = (XFontSet) font_private->xfont;
227       width = XmbTextEscapement (fontset, string, strlen(string));
228       break;
229     default:
230       width = 0;
231     }
232
233   return width;
234 }
235
236 gint
237 gdk_text_width (GdkFont      *font,
238                 const gchar  *text,
239                 gint          text_length)
240 {
241   GdkFontPrivate *private;
242   gint width;
243   XFontStruct *xfont;
244   XFontSet fontset;
245
246   g_return_val_if_fail (font != NULL, -1);
247   g_return_val_if_fail (text != NULL, -1);
248
249   private = (GdkFontPrivate*) font;
250
251   switch (font->type)
252     {
253     case GDK_FONT_FONT:
254       xfont = (XFontStruct *) private->xfont;
255       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
256         {
257           width = XTextWidth (xfont, text, text_length);
258         }
259       else
260         {
261           width = XTextWidth16 (xfont, (XChar2b *) text, text_length / 2);
262         }
263       break;
264     case GDK_FONT_FONTSET:
265       fontset = (XFontSet) private->xfont;
266       width = XmbTextEscapement (fontset, text, text_length);
267       break;
268     default:
269       width = 0;
270     }
271   return width;
272 }
273
274 /* Problem: What if a character is a 16 bits character ?? */
275 gint
276 gdk_char_width (GdkFont *font,
277                 gchar    character)
278 {
279   GdkFontPrivate *private;
280   XCharStruct *chars;
281   gint width;
282   guint ch = character & 0xff;  /* get rid of sign-extension */
283   XFontStruct *xfont;
284   XFontSet fontset;
285
286   g_return_val_if_fail (font != NULL, -1);
287
288   private = (GdkFontPrivate*) font;
289
290   switch (font->type)
291     {
292     case GDK_FONT_FONT:
293       /* only 8 bits characters are considered here */
294       xfont = (XFontStruct *) private->xfont;
295       if ((xfont->min_byte1 == 0) &&
296           (xfont->max_byte1 == 0) &&
297           (ch >= xfont->min_char_or_byte2) &&
298           (ch <= xfont->max_char_or_byte2))
299         {
300           chars = xfont->per_char;
301           if (chars)
302             width = chars[ch - xfont->min_char_or_byte2].width;
303           else
304             width = xfont->min_bounds.width;
305         }
306       else
307         {
308           width = XTextWidth (xfont, &character, 1);
309         }
310       break;
311     case GDK_FONT_FONTSET:
312       fontset = (XFontSet) private->xfont;
313       width = XmbTextEscapement (fontset, &character, 1) ;
314       break;
315     default:
316       width = 0;
317     }
318   return width;
319 }
320
321 gint
322 gdk_string_measure (GdkFont     *font,
323                     const gchar *string)
324 {
325   g_return_val_if_fail (font != NULL, -1);
326   g_return_val_if_fail (string != NULL, -1);
327
328   return gdk_text_measure (font, string, strlen (string));
329 }
330
331 void
332 gdk_text_extents (GdkFont     *font,
333                   const gchar *text,
334                   gint         text_length,
335                   gint        *lbearing,
336                   gint        *rbearing,
337                   gint        *width,
338                   gint        *ascent,
339                   gint        *descent)
340 {
341   GdkFontPrivate *private;
342   XCharStruct overall;
343   XFontStruct *xfont;
344   XFontSet    fontset;
345   XRectangle  ink, logical;
346   int direction;
347   int font_ascent;
348   int font_descent;
349
350   g_return_if_fail (font != NULL);
351   g_return_if_fail (text != NULL);
352
353   private = (GdkFontPrivate*) font;
354
355   switch (font->type)
356     {
357     case GDK_FONT_FONT:
358       xfont = (XFontStruct *) private->xfont;
359       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
360         {
361           XTextExtents (xfont, text, text_length,
362                         &direction, &font_ascent, &font_descent,
363                         &overall);
364         }
365       else
366         {
367           XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
368                           &direction, &font_ascent, &font_descent,
369                           &overall);
370         }
371       if (lbearing)
372         *lbearing = overall.lbearing;
373       if (rbearing)
374         *rbearing = overall.rbearing;
375       if (width)
376         *width = overall.width;
377       if (ascent)
378         *ascent = overall.ascent;
379       if (descent)
380         *descent = overall.descent;
381       break;
382     case GDK_FONT_FONTSET:
383       fontset = (XFontSet) private->xfont;
384       XmbTextExtents (fontset, text, text_length, &ink, &logical);
385       if (lbearing)
386         *lbearing = -ink.x;
387       if (rbearing)
388         *rbearing = ink.y;
389       if (width)
390         *width = logical.width;
391       if (ascent)
392         *ascent = ink.height;
393       if (descent)
394         *descent = -ink.y;
395       break;
396     }
397
398 }
399
400 void
401 gdk_string_extents (GdkFont     *font,
402                     const gchar *string,
403                     gint        *lbearing,
404                     gint        *rbearing,
405                     gint        *width,
406                     gint        *ascent,
407                     gint        *descent)
408 {
409   g_return_if_fail (font != NULL);
410   g_return_if_fail (string != NULL);
411
412   gdk_text_extents (font, string, strlen (string),
413                     lbearing, rbearing, width, ascent, descent);
414 }
415
416
417 gint
418 gdk_text_measure (GdkFont     *font,
419                   const gchar *text,
420                   gint         text_length)
421 {
422   GdkFontPrivate *private;
423   XCharStruct overall;
424   XFontStruct *xfont;
425   XFontSet    fontset;
426   XRectangle  ink, log;
427   int direction;
428   int font_ascent;
429   int font_descent;
430   gint width;
431
432   g_return_val_if_fail (font != NULL, -1);
433   g_return_val_if_fail (text != NULL, -1);
434
435   private = (GdkFontPrivate*) font;
436
437   switch (font->type)
438     {
439     case GDK_FONT_FONT:
440       xfont = (XFontStruct *) private->xfont;
441       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
442         {
443           XTextExtents (xfont, text, text_length,
444                         &direction, &font_ascent, &font_descent,
445                         &overall);
446         }
447       else
448         {
449           XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
450                           &direction, &font_ascent, &font_descent,
451                           &overall);
452         }
453       width = overall.rbearing;
454       break;
455     case GDK_FONT_FONTSET:
456       fontset = (XFontSet) private->xfont;
457       XmbTextExtents (fontset, text, text_length, &ink, &log);
458       width = log.width;
459       break;
460     default:
461       width = 0;
462     }
463   return width;
464 }
465
466 gint
467 gdk_char_measure (GdkFont *font,
468                   gchar    character)
469 {
470   g_return_val_if_fail (font != NULL, -1);
471
472   return gdk_text_measure (font, &character, 1);
473 }
474
475 gint
476 gdk_string_height (GdkFont     *font,
477                    const gchar *string)
478 {
479   g_return_val_if_fail (font != NULL, -1);
480   g_return_val_if_fail (string != NULL, -1);
481
482   return gdk_text_height (font, string, strlen (string));
483 }
484
485 gint
486 gdk_text_height (GdkFont     *font,
487                  const gchar *text,
488                  gint         text_length)
489 {
490   GdkFontPrivate *private;
491   XCharStruct overall;
492   XFontStruct *xfont;
493   XFontSet    fontset;
494   XRectangle  ink, log;
495   int direction;
496   int font_ascent;
497   int font_descent;
498   gint height;
499
500   g_return_val_if_fail (font != NULL, -1);
501   g_return_val_if_fail (text != NULL, -1);
502
503   private = (GdkFontPrivate*) font;
504
505   switch (font->type)
506     {
507     case GDK_FONT_FONT:
508       xfont = (XFontStruct *) private->xfont;
509       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
510         {
511           XTextExtents (xfont, text, text_length,
512                         &direction, &font_ascent, &font_descent,
513                         &overall);
514         }
515       else
516         {
517           XTextExtents16 (xfont, (XChar2b *) text, text_length / 2,
518                           &direction, &font_ascent, &font_descent,
519                           &overall);
520         }
521       height = overall.ascent + overall.descent;
522       break;
523     case GDK_FONT_FONTSET:
524       fontset = (XFontSet) private->xfont;
525       XmbTextExtents (fontset, text, text_length, &ink, &log);
526       height = log.height;
527       break;
528     default:
529       height = 0;
530     }
531   return height;
532 }
533
534 gint
535 gdk_char_height (GdkFont *font,
536                  gchar    character)
537 {
538   g_return_val_if_fail (font != NULL, -1);
539
540   return gdk_text_height (font, &character, 1);
541 }