+/* Renders the given string into the prevailing texture.
+ Returns the metrics of the text, and size of the texture.
+ */
+void
+string_to_texture (texture_font_data *data, const char *string,
+ XCharStruct *extents_ret,
+ int *tex_width_ret, int *tex_height_ret)
+{
+ Window window = RootWindow (data->dpy, 0);
+ Pixmap p;
+ XGCValues gcv;
+ GC gc;
+ XWindowAttributes xgwa;
+ XRenderColor rcolor;
+ XftColor xftcolor;
+ XftDraw *xftdraw;
+ int width, height;
+ XCharStruct overall;
+
+ /* Measure the string and create a Pixmap of the proper size.
+ */
+ XGetWindowAttributes (data->dpy, window, &xgwa);
+ iterate_texture_string (data, string, 0, 0, 0, 0, &overall);
+ width = overall.rbearing - overall.lbearing;
+ height = overall.ascent + overall.descent;
+ if (width <= 0) width = 1;
+ if (height <= 0) height = 1;
+ p = XCreatePixmap (data->dpy, window, width, height, xgwa.depth);
+
+ gcv.foreground = BlackPixelOfScreen (xgwa.screen);
+ gc = XCreateGC (data->dpy, p, GCForeground, &gcv);
+ XFillRectangle (data->dpy, p, gc, 0, 0, width, height);
+ XFreeGC (data->dpy, gc);
+
+ /* Render the string into the pixmap.
+ */
+ rcolor.red = rcolor.green = rcolor.blue = rcolor.alpha = 0xFFFF;
+ XftColorAllocValue (data->dpy, xgwa.visual, xgwa.colormap,
+ &rcolor, &xftcolor);
+ xftdraw = XftDrawCreate (data->dpy, p, xgwa.visual, xgwa.colormap);
+ iterate_texture_string (data, string,
+ -overall.lbearing, overall.ascent,
+ xftdraw, &xftcolor, 0);
+ XftDrawDestroy (xftdraw);
+ XftColorFree (data->dpy, xgwa.visual, xgwa.colormap, &xftcolor);
+
+ /* Copy the bits from the Pixmap into a texture, unless it's cached.
+ */
+ bitmap_to_texture (data->dpy, p, xgwa.visual, xgwa.depth,
+ &width, &height);
+ XFreePixmap (data->dpy, p);
+
+ if (extents_ret) *extents_ret = overall;
+ if (tex_width_ret) *tex_width_ret = width;
+ if (tex_height_ret) *tex_height_ret = height;
+}
+
+
+/* Set the various OpenGL parameters for properly rendering things
+ with a texture generated by string_to_texture().
+ */
+void
+enable_texture_string_parameters (void)
+{
+ glEnable (GL_TEXTURE_2D);
+
+ /* Texture-rendering parameters to make font pixmaps tolerable to look at.
+ */
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR);
+
+ /* LOD bias is part of OpenGL 1.4.
+ GL_EXT_texture_lod_bias has been present since the original iPhone.
+ */
+# if !defined(GL_TEXTURE_LOD_BIAS) && defined(GL_TEXTURE_LOD_BIAS_EXT)
+# define GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS_EXT
+# endif
+# ifdef GL_TEXTURE_LOD_BIAS
+ glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.25);
+# endif
+ clear_gl_error(); /* invalid enum on iPad 3 */
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ /* Don't write the transparent parts of the quad into the depth buffer. */
+ glAlphaFunc (GL_GREATER, 0.01);
+ glEnable (GL_ALPHA_TEST);
+ glEnable (GL_BLEND);
+ glDisable (GL_LIGHTING);
+ glDisable (GL_TEXTURE_GEN_S);
+ glDisable (GL_TEXTURE_GEN_T);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+