1 /* glxfonts, Copyright (c) 2001-2008 Jamie Zawinski <jwz@jwz.org>
2 * Loads X11 fonts for use with OpenGL.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
24 # include <OpenGL/gl.h>
25 # include <OpenGL/glu.h>
32 #include "resources.h"
35 /* These are in xlock-gl.c */
36 extern void clear_gl_error (void);
37 extern void check_gl_error (const char *type);
40 extern char *progname;
43 #undef DEBUG /* Defining this causes check_gl_error() to be called inside
44 time-critical sections, which could slow things down (since
45 it might result in a round-trip, and stall of the pipeline.)
49 /* Loads the font named by the X resource "res".
50 Returns an XFontStruct.
51 Also converts the font to a set of GL lists and returns the first list.
54 load_font (Display *dpy, char *res, XFontStruct **font_ret, GLuint *dlist_ret)
58 const char *font = get_string_resource (dpy, res, "Font");
59 const char *def1 = "-*-helvetica-medium-r-normal-*-180-*";
60 const char *def2 = "fixed";
64 if (!res || !*res) abort();
65 if (!font_ret && !dlist_ret) abort();
67 if (!font) font = def1;
69 f = XLoadQueryFont(dpy, font);
70 if (!f && !!strcmp (font, def1))
72 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
73 progname, font, def1);
75 f = XLoadQueryFont(dpy, font);
78 if (!f && !!strcmp (font, def2))
80 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
81 progname, font, def2);
83 f = XLoadQueryFont(dpy, font);
88 fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n",
94 first = f->min_char_or_byte2;
95 last = f->max_char_or_byte2;
98 # ifndef HAVE_COCOA /* Xlib version */
103 *dlist_ret = glGenLists ((GLuint) last+1);
104 check_gl_error ("glGenLists");
105 glXUseXFont(id, first, last-first+1, *dlist_ret + first);
106 check_gl_error ("glXUseXFont");
109 # else /* HAVE_COCOA */
112 int afid, face, size;
113 afid = jwxyz_font_info (id, &size, &face);
118 *dlist_ret = glGenLists ((GLuint) last+1);
119 check_gl_error ("glGenLists");
121 AGLContext ctx = aglGetCurrentContext();
122 if (! aglUseFont (ctx, afid, face, size,
123 first, last-first+1, *dlist_ret + first)) {
124 check_gl_error ("aglUseFont");
130 # endif /* HAVE_COCOA */
137 /* Width (and optionally height) of the string in pixels.
140 string_width (XFontStruct *f, const char *c, int *height_ret)
144 int h = f->ascent + f->descent;
147 int cc = *((unsigned char *) c);
150 if (x > max_w) max_w = x;
152 h += f->ascent + f->descent;
156 ? f->per_char[cc-f->min_char_or_byte2].width
157 : f->min_bounds.rbearing);
160 if (x > max_w) max_w = x;
161 if (height_ret) *height_ret = h;
167 /* Draws the string on the window at the given pixel position.
168 Newlines and tab stops are honored.
169 Any text inside [] will be rendered as a subscript.
170 Assumes the font has been loaded as with load_font().
173 print_gl_string (Display *dpy,
176 int window_width, int window_height,
177 GLfloat x, GLfloat y,
179 Bool clear_background_p)
181 GLfloat line_height = font->ascent + font->descent;
182 GLfloat sub_shift = (line_height * 0.3);
183 int cw = string_width (font, "m", 0);
188 /* Sadly, this causes a stall of the graphics pipeline (as would the
189 equivalent calls to glGet*.) But there's no way around this, short
190 of having each caller set up the specific display matrix we need
191 here, which would kind of defeat the purpose of centralizing this
194 glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */
195 GL_ENABLE_BIT | /* for various glDisable calls */
196 GL_CURRENT_BIT | /* for glColor3f() */
197 GL_LIST_BIT); /* for glListBase() */
200 check_gl_error ("glPushAttrib");
203 /* disable lighting and texturing when drawing bitmaps!
204 (glPopAttrib() restores these.)
206 glDisable (GL_TEXTURE_2D);
207 glDisable (GL_LIGHTING);
208 glDisable (GL_BLEND);
209 glDisable (GL_DEPTH_TEST);
210 glDisable (GL_CULL_FACE);
212 /* glPopAttrib() does not restore matrix changes, so we must
213 push/pop the matrix stacks to be non-intrusive there.
215 glMatrixMode(GL_PROJECTION);
219 check_gl_error ("glPushMatrix");
223 /* Each matrix mode has its own stack, so we need to push/pop
225 glMatrixMode(GL_MODELVIEW);
233 check_gl_error ("glPushMatrix");
237 gluOrtho2D (0, window_width, 0, window_height);
239 check_gl_error ("gluOrtho2D");
242 if (clear_background_p)
245 int lh = font->ascent + font->descent;
246 w = string_width (font, string, &h);
248 glRecti (x - font->descent,
250 x + w + 2*font->descent,
251 y + lh - h - font->descent);
256 glRasterPos2f (x, y);
257 /* glListBase (font_dlist);*/
258 for (i = 0; i < strlen(string); i++)
260 unsigned char c = (unsigned char) string[i];
263 glRasterPos2f (x, (y -= line_height));
269 x2 = ((x2 + tabs) / tabs) * tabs; /* tab to tab stop */
271 glRasterPos2f (x2, y);
273 else if (c == '[' && (isdigit (string[i+1])))
276 glRasterPos2f (x2, (y -= sub_shift));
278 else if (c == ']' && sub_p)
281 glRasterPos2f (x2, (y += sub_shift));
285 /* glCallLists (s - string, GL_UNSIGNED_BYTE, string);*/
286 glCallList (font_dlist + (int)(c));
287 x2 += (font->per_char
288 ? font->per_char[c - font->min_char_or_byte2].width
289 : font->min_bounds.width);
293 check_gl_error ("print_gl_string");
298 glMatrixMode(GL_PROJECTION);
303 check_gl_error ("glPopAttrib");
306 glMatrixMode(GL_MODELVIEW);