http://ftp.ksu.edu.tw/FTP/FreeBSD/distfiles/xscreensaver-4.20.tar.gz
[xscreensaver] / hacks / glx / glxfonts.c
diff --git a/hacks/glx/glxfonts.c b/hacks/glx/glxfonts.c
new file mode 100644 (file)
index 0000000..3443e4f
--- /dev/null
@@ -0,0 +1,195 @@
+/* glxfonts, Copyright (c) 2001-2004 Jamie Zawinski <jwz@jwz.org>
+ * Loads X11 fonts for use with OpenGL.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <GL/glx.h>
+#include <GL/glu.h>
+#include "resources.h"
+#include "glxfonts.h"
+
+/* These are in xlock-gl.c */
+extern void clear_gl_error (void);
+extern void check_gl_error (const char *type);
+
+/* screenhack.h */
+extern char *progname;
+
+
+/* Loads the font named by the X resource "res".
+   Returns an XFontStruct.
+   Also converts the font to a set of GL lists and returns the first list.
+*/
+void
+load_font (Display *dpy, char *res, XFontStruct **font_ret, GLuint *dlist_ret)
+{
+  const char *font = get_string_resource (res, "Font");
+  const char *def1 = "-*-times-bold-r-normal-*-180-*";
+  const char *def2 = "fixed";
+  XFontStruct *f;
+  Font id;
+  int first, last;
+
+  if (!res || !*res) abort();
+  if (!font_ret && !dlist_ret) abort();
+
+  if (!font) font = def1;
+
+  f = XLoadQueryFont(dpy, font);
+  if (!f && !!strcmp (font, def1))
+    {
+      fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
+               progname, font, def1);
+      font = def1;
+      f = XLoadQueryFont(dpy, font);
+    }
+
+  if (!f && !!strcmp (font, def2))
+    {
+      fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
+               progname, font, def2);
+      font = def2;
+      f = XLoadQueryFont(dpy, font);
+    }
+
+  if (!f)
+    {
+      fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n",
+               progname, font);
+      exit (1);
+    }
+
+  id = f->fid;
+  first = f->min_char_or_byte2;
+  last = f->max_char_or_byte2;
+  
+  if (dlist_ret)
+    {
+      clear_gl_error ();
+      *dlist_ret = glGenLists ((GLuint) last+1);
+      check_gl_error ("glGenLists");
+      glXUseXFont(id, first, last-first+1, *dlist_ret + first);
+      check_gl_error ("glXUseXFont");
+    }
+
+  if (font_ret)
+    *font_ret = f;
+}
+
+
+/* Width of the string in pixels.
+ */
+int
+string_width (XFontStruct *f, const char *c)
+{
+  int w = 0;
+  while (*c)
+    {
+      int cc = *((unsigned char *) c);
+      w += (f->per_char
+            ? f->per_char[cc-f->min_char_or_byte2].rbearing
+            : f->min_bounds.rbearing);
+      c++;
+    }
+  return w;
+}
+
+
+/* Draws the string on the window at the given pixel position.
+   Newlines and tab stops are honored.
+   Any text inside [] will be rendered as a subscript.
+   Assumes the font has been loaded as with load_font().
+ */
+void
+print_gl_string (Display *dpy,
+                 XFontStruct *font,
+                 GLuint font_dlist,
+                 int window_width, int window_height,
+                 GLfloat x, GLfloat y,
+                 const char *string)
+{
+  GLfloat line_height = font->ascent + font->descent;
+  GLfloat sub_shift = (line_height * 0.3);
+  int cw = string_width (font, "m");
+  int tabs = cw * 7;
+
+  y -= line_height;
+
+  glPushAttrib (GL_TRANSFORM_BIT |  /* for matrix contents */
+                GL_ENABLE_BIT);     /* for various glDisable calls */
+  glDisable (GL_LIGHTING);
+  glDisable (GL_DEPTH_TEST);
+  glDisable (GL_TEXTURE_2D);
+  {
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    {
+      glLoadIdentity();
+
+      glMatrixMode(GL_MODELVIEW);
+      glPushMatrix();
+      {
+        unsigned int i;
+        int x2 = x;
+        Bool sub_p = False;
+        glLoadIdentity();
+
+        gluOrtho2D (0, window_width, 0, window_height);
+
+        glRasterPos2f (x, y);
+        for (i = 0; i < strlen(string); i++)
+          {
+            char c = string[i];
+            if (c == '\n')
+              {
+                glRasterPos2f (x, (y -= line_height));
+                x2 = x;
+              }
+            else if (c == '\t')
+              {
+                x2 -= x;
+                x2 = ((x2 + tabs) / tabs) * tabs;  /* tab to tab stop */
+                x2 += x;
+                glRasterPos2f (x2, y);
+              }
+            else if (c == '[' && (isdigit (string[i+1])))
+              {
+                sub_p = True;
+                glRasterPos2f (x2, (y -= sub_shift));
+              }
+            else if (c == ']' && sub_p)
+              {
+                sub_p = False;
+                glRasterPos2f (x2, (y += sub_shift));
+              }
+            else
+              {
+                glCallList (font_dlist + (int)(c));
+                x2 += (font->per_char
+                       ? font->per_char[c - font->min_char_or_byte2].width
+                       : font->min_bounds.width);
+              }
+          }
+      }
+      glPopMatrix();
+    }
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+  }
+  glPopAttrib();
+
+  glMatrixMode(GL_MODELVIEW);
+}