1 /* texfonts, Copyright (c) 2005-2017 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
11 * Renders X11 fonts into textures for use with OpenGL.
27 # include <OpenGL/glu.h>
29 #elif defined(HAVE_ANDROID)
39 #endif /* HAVE_JWZGLES */
41 #ifdef HAVE_XSHM_EXTENSION
43 #endif /* HAVE_XSHM_EXTENSION */
47 #include "resources.h"
49 #include "fps.h" /* for current_device_rotation() */
51 #undef HAVE_XSHM_EXTENSION /* doesn't actually do any good here */
54 /* These are in xlock-gl.c */
55 extern void clear_gl_error (void);
56 extern void check_gl_error (const char *type);
59 extern char *progname;
61 /* LRU cache of textures, to optimize the case where we're drawing the
62 same strings repeatedly.
64 typedef struct texfont_cache texfont_cache;
65 struct texfont_cache {
69 int tex_width, tex_height;
73 struct texture_font_data {
82 #define countof(x) (sizeof((x))/sizeof((*x)))
85 /* Given a Pixmap (of screen depth), converts it to an OpenGL luminance mipmap.
86 RGB are averaged to grayscale, and the resulting value is treated as alpha.
87 Pass in the size of the pixmap; the size of the texture is returned
88 (it may be larger, since GL like powers of 2.)
90 We use a screen-depth pixmap instead of a 1bpp bitmap so that if the fonts
91 were drawn with antialiasing, that is preserved.
94 bitmap_to_texture (Display *dpy, Pixmap p, Visual *visual, int depth,
100 GLsizei w2 = (GLsizei) to_pow2 (ow);
101 GLsizei h2 = (GLsizei) to_pow2 (oh);
102 int x, y, max, scale;
104 unsigned char *data = (unsigned char *) calloc (w2 * 2, (h2 + 1));
105 unsigned char *out = data;
107 /* OpenGLES doesn't support GL_INTENSITY, so instead of using a
108 texture with 1 byte per pixel, the intensity value, we have
109 to use 2 bytes per pixel: solid white, and an alpha value.
115 # ifdef HAVE_XSHM_EXTENSION
116 Bool use_shm = get_boolean_resource (dpy, "useSHM", "Boolean");
117 XShmSegmentInfo shm_info;
118 # endif /* HAVE_XSHM_EXTENSION */
120 /* If either dimension is larger than the supported size, reduce.
121 We still return the old size to keep the caller's math working,
122 but the texture itself will have fewer pixels in it.
124 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max);
126 while (w2 > max || h2 > max)
133 # ifdef HAVE_XSHM_EXTENSION
136 image = create_xshm_image (dpy, visual, depth, ZPixmap, 0, &shm_info,
139 XShmGetImage (dpy, p, image, 0, 0, ~0L);
143 # endif /* HAVE_XSHM_EXTENSION */
146 /* XCreateImage fills in (red|green_blue)_mask. XGetImage only does that
147 when reading from a Window, not when it's a Pixmap.
149 image = XCreateImage (dpy, visual, depth, ZPixmap, 0, NULL, ow, oh,
151 image->data = malloc (image->height * image->bytes_per_line);
152 XGetSubImage (dpy, p, 0, 0, ow, oh, ~0L, ZPixmap, image, 0, 0);
156 /* This would work, but it's wasteful for no benefit. */
161 fprintf (stderr, "\n");
163 for (y = 0; y < h2; y++) {
164 for (x = 0; x < w2; x++) {
165 /* Might be better to average a scale x scale square of source pixels,
166 but at the resolutions we're dealing with, this is probably good
170 unsigned long pixel = (sx >= ow || sy >= oh ? 0 :
171 XGetPixel (image, sx, sy));
172 /* instead of averaging all three channels, let's just use red,
173 and assume it was already grayscale. */
174 unsigned long r = pixel & image->red_mask;
175 /* This goofy trick is to make any of RGBA/ABGR/ARGB work. */
176 pixel = ((r >> 24) | (r >> 16) | (r >> 8) | r) & 0xFF;
179 if (sx < ow && sy < oh)
181 fprintf (stderr, "%c",
182 r >= 0xFF000000 ? '#' :
183 r >= 0x88000000 ? '%' :
186 fprintf (stderr, "%c",
187 r >= 0xFF0000 ? '#' :
188 r >= 0x880000 ? '%' :
193 # if 0 /* Debugging checkerboard */
194 if (sx < ow && sy < oh && (((sx / 4) & 1) ^ ((sy / 4) & 1)))
198 # ifndef GL_INTENSITY
199 *out++ = 0xFF; /* 2 bytes per pixel (luminance, alpha) */
204 fprintf (stderr, "\n");
208 # ifdef HAVE_XSHM_EXTENSION
210 destroy_xshm_image (dpy, image, &shm_info);
212 # endif /* HAVE_XSHM_EXTENSION */
214 /* We malloc'd image->data, so we free it. */
217 XDestroyImage (image);
224 GLuint iformat = GL_INTENSITY;
225 GLuint format = GL_LUMINANCE;
227 GLuint iformat = GL_LUMINANCE_ALPHA;
228 GLuint format = GL_LUMINANCE_ALPHA;
230 GLuint type = GL_UNSIGNED_BYTE;
233 gluBuild2DMipmaps (GL_TEXTURE_2D, iformat, w2, h2, format, type, data);
235 glTexImage2D (GL_TEXTURE_2D, 0, iformat, w2, h2, 0, format, type, data);
240 sprintf (msg, "texture font %s (%d x %d)",
241 mipmap_p ? "gluBuild2DMipmaps" : "glTexImage2D",
243 check_gl_error (msg);
253 /* Loads the font named by the X resource "res" and returns
254 a texture-font object.
257 load_texture_font (Display *dpy, char *res)
259 int screen = DefaultScreen (dpy);
260 char *font = get_string_resource (dpy, res, "Font");
261 const char *def1 = "-*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*";
262 const char *def2 = "-*-helvetica-medium-r-normal-*-*-140-*-*-*-*-*-*";
263 const char *def3 = "fixed";
265 texture_font_data *data;
266 int cache_size = get_integer_resource (dpy, "texFontCacheSize", "Integer");
268 /* Hacks that draw a lot of different strings on the screen simultaneously,
269 like Star Wars, should set this to a larger value for performance. */
273 if (!res || !*res) abort();
275 if (!strcmp (res, "fpsFont")) { /* Kludge. */
276 def1 = "-*-courier-bold-r-normal-*-*-180-*-*-*-*-*-*"; /* also fps.c */
277 cache_size = 0; /* No need for a cache on FPS: already throttled. */
280 if (!font) font = strdup(def1);
282 f = XftFontOpenXlfd (dpy, screen, font);
283 if (!f && !!strcmp (font, def1))
285 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
286 progname, font, def1);
288 font = strdup (def1);
289 f = XftFontOpenXlfd (dpy, screen, font);
292 if (!f && !!strcmp (font, def2))
294 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
295 progname, font, def2);
297 font = strdup (def2);
298 f = XftFontOpenXlfd (dpy, screen, font);
301 if (!f && !!strcmp (font, def3))
303 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
304 progname, font, def3);
306 font = strdup (def3);
307 f = XftFontOpenXlfd (dpy, screen, font);
312 fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n",
320 data = (texture_font_data *) calloc (1, sizeof(*data));
323 data->cache_size = cache_size;
329 /* Measure the string, returning the overall metrics.
330 Newlines and tab stops are honored.
331 Any numbers inside [] will be rendered as a subscript.
333 The origin is at the origin of the first character, so subsequent
334 lines of a multi-line string look like descenders (below baseline).
336 If an XftDraw is supplied, render the string as well, at X,Y.
337 Positive Y is down (X11 style, not OpenGL style).
340 iterate_texture_string (texture_font_data *data,
342 int draw_x, int draw_y,
343 XftDraw *xftdraw, XftColor *xftcolor,
344 XCharStruct *metrics_ret)
346 int line_height = data->xftfont->ascent + data->xftfont->descent;
347 int subscript_offset = line_height * 0.3;
349 Bool sub_p = False, osub_p = False;
350 int cw = 0, tabs = 0;
351 XCharStruct overall = { 0, };
360 (*s == '[' && isdigit(s[1])) ||
361 (*s == ']' && sub_p))
368 if (sub_p) y2 += subscript_offset;
370 XftTextExtentsUtf8 (data->dpy, data->xftfont,
371 (FcChar8 *) os, (int) (s - os),
373 c.lbearing = -e.x; /* XGlyphInfo to XCharStruct */
374 c.rbearing = e.width - e.x;
376 c.descent = e.height - e.y;
381 # define MAX(A,B) ((A)>(B)?(A):(B))
382 # define MIN(A,B) ((A)<(B)?(A):(B))
383 overall.ascent = MAX (overall.ascent, -y2 + c.ascent);
384 overall.descent = MAX (overall.descent, y2 + c.descent);
385 overall.lbearing = MIN (overall.lbearing, (x + c.lbearing));
386 overall.rbearing = MAX (overall.rbearing, x + c.rbearing);
387 overall.width = MAX (overall.width, x + c.width);
403 /* Measure "m" to determine tab width. */
405 XftTextExtentsUtf8 (data->dpy, data->xftfont,
406 (FcChar8 *) "m", 1, &e);
411 x = ((x + tabs) / tabs) * tabs;
413 else if (*s == '[' && isdigit(s[1]))
415 else if (*s == ']' && sub_p)
418 if (xftdraw && s != os)
419 XftDrawStringUtf8 (xftdraw, xftcolor, data->xftfont,
422 oy + (osub_p ? subscript_offset : 0),
423 (FcChar8 *) os, (int) (s - os));
434 *metrics_ret = overall;
438 /* Bounding box of the multi-line string, in pixels,
439 and overall ascent/descent of the font.
442 texture_string_metrics (texture_font_data *data, const char *s,
443 XCharStruct *metrics_ret,
444 int *ascent_ret, int *descent_ret)
447 iterate_texture_string (data, s, 0, 0, 0, 0, metrics_ret);
448 if (ascent_ret) *ascent_ret = data->xftfont->ascent;
449 if (descent_ret) *descent_ret = data->xftfont->descent;
453 /* Returns a cache entry for this string, with a valid texid.
454 If the returned entry has a string in it, the texture is valid.
455 Otherwise it is an empty entry waiting to be rendered.
457 static struct texfont_cache *
458 get_cache (texture_font_data *data, const char *string)
461 texfont_cache *prev = 0, *prev2 = 0, *curr = 0, *next = 0;
464 for (prev2 = 0, prev = 0, curr = data->cache, next = curr->next;
466 prev2 = prev, prev = curr, curr = next,
467 next = (curr ? curr->next : 0), count++)
469 if (!strcmp (string, curr->string))
472 prev->next = next; /* Unlink from list */
473 if (curr != data->cache)
475 curr->next = data->cache; /* Move to front */
482 /* Made it to the end of the list without a hit.
483 If the cache is full, empty out the last one on the list,
484 and move it to the front. Keep the texid.
486 if (count > data->cache_size)
492 prev->tex_height = 0;
493 memset (&prev->extents, 0, sizeof(prev->extents));
496 if (prev != data->cache)
497 prev->next = data->cache;
502 /* Not cached, and cache not full. Add a new entry at the front,
503 and allocate a new texture for it.
505 curr = (struct texfont_cache *) calloc (1, sizeof(*prev));
506 glGenTextures (1, &curr->texid);
508 curr->next = data->cache;
515 /* Renders the given string into the prevailing texture.
516 Returns the metrics of the text, and size of the texture.
519 string_to_texture (texture_font_data *data, const char *string,
520 XCharStruct *extents_ret,
521 int *tex_width_ret, int *tex_height_ret)
523 Window window = RootWindow (data->dpy, 0);
527 XWindowAttributes xgwa;
534 /* Measure the string and create a Pixmap of the proper size.
536 XGetWindowAttributes (data->dpy, window, &xgwa);
537 iterate_texture_string (data, string, 0, 0, 0, 0, &overall);
538 width = overall.rbearing - overall.lbearing;
539 height = overall.ascent + overall.descent;
540 if (width <= 0) width = 1;
541 if (height <= 0) height = 1;
542 p = XCreatePixmap (data->dpy, window, width, height, xgwa.depth);
544 gcv.foreground = BlackPixelOfScreen (xgwa.screen);
545 gc = XCreateGC (data->dpy, p, GCForeground, &gcv);
546 XFillRectangle (data->dpy, p, gc, 0, 0, width, height);
547 XFreeGC (data->dpy, gc);
549 /* Render the string into the pixmap.
551 rcolor.red = rcolor.green = rcolor.blue = rcolor.alpha = 0xFFFF;
552 XftColorAllocValue (data->dpy, xgwa.visual, xgwa.colormap,
554 xftdraw = XftDrawCreate (data->dpy, p, xgwa.visual, xgwa.colormap);
555 iterate_texture_string (data, string,
556 -overall.lbearing, overall.ascent,
557 xftdraw, &xftcolor, 0);
558 XftDrawDestroy (xftdraw);
559 XftColorFree (data->dpy, xgwa.visual, xgwa.colormap, &xftcolor);
561 /* Copy the bits from the Pixmap into a texture, unless it's cached.
563 bitmap_to_texture (data->dpy, p, xgwa.visual, xgwa.depth,
565 XFreePixmap (data->dpy, p);
567 if (extents_ret) *extents_ret = overall;
568 if (tex_width_ret) *tex_width_ret = width;
569 if (tex_height_ret) *tex_height_ret = height;
573 /* Set the various OpenGL parameters for properly rendering things
574 with a texture generated by string_to_texture().
577 enable_texture_string_parameters (void)
579 glEnable (GL_TEXTURE_2D);
581 /* Texture-rendering parameters to make font pixmaps tolerable to look at.
583 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
584 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
585 GL_LINEAR_MIPMAP_LINEAR);
587 /* LOD bias is part of OpenGL 1.4.
588 GL_EXT_texture_lod_bias has been present since the original iPhone.
590 # if !defined(GL_TEXTURE_LOD_BIAS) && defined(GL_TEXTURE_LOD_BIAS_EXT)
591 # define GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS_EXT
593 # ifdef GL_TEXTURE_LOD_BIAS
594 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.25);
596 clear_gl_error(); /* invalid enum on iPad 3 */
598 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
599 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
601 /* Don't write the transparent parts of the quad into the depth buffer. */
602 glAlphaFunc (GL_GREATER, 0.01);
603 glEnable (GL_ALPHA_TEST);
605 glDisable (GL_LIGHTING);
606 glDisable (GL_TEXTURE_GEN_S);
607 glDisable (GL_TEXTURE_GEN_T);
608 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
612 /* Draws the string in the scene at the origin.
613 Newlines and tab stops are honored.
614 Any numbers inside [] will be rendered as a subscript.
615 Assumes the font has been loaded as with load_texture_font().
617 The origin is at the origin of the first character, so subsequent
618 lines of a multi-line string are below that.
621 print_texture_string (texture_font_data *data, const char *string)
624 int tex_width, tex_height;
625 texfont_cache *cache;
628 if (!*string) return;
632 /* Save the prevailing texture ID, and bind ours. Restored at the end. */
633 glGetIntegerv (GL_TEXTURE_BINDING_2D, &old_texture);
635 cache = get_cache (data, string);
637 glBindTexture (GL_TEXTURE_2D, cache->texid);
638 check_gl_error ("texture font binding");
640 /* Measure the string and make a pixmap that will fit it,
645 overall = data->cache->extents;
646 tex_width = data->cache->tex_width;
647 tex_height = data->cache->tex_height;
651 # if defined HAVE_JWXYZ && defined JWXYZ_GL
652 /* TODO, JWXYZ_GL: Mixing Xlib and GL has issues. */
653 memset (&overall, 0, sizeof(overall));
657 string_to_texture (data, string, &overall, &tex_width, &tex_height);
663 Bool alpha_p, blend_p, light_p, gen_s_p, gen_t_p;
665 GLfloat qx0, qy0, qx1, qy1;
666 GLfloat tx0, ty0, tx1, ty1;
668 /* If face culling is not enabled, draw front and back. */
669 Bool draw_back_face_p = !glIsEnabled (GL_CULL_FACE);
671 /* Save the prevailing texture environment, and set up ours.
673 glGetIntegerv (GL_FRONT_FACE, &ofront);
674 glGetIntegerv (GL_BLEND_DST, &oblend);
675 glGetFloatv (GL_TEXTURE_MATRIX, omatrix);
676 blend_p = glIsEnabled (GL_BLEND);
677 alpha_p = glIsEnabled (GL_ALPHA_TEST);
678 light_p = glIsEnabled (GL_LIGHTING);
679 gen_s_p = glIsEnabled (GL_TEXTURE_GEN_S);
680 gen_t_p = glIsEnabled (GL_TEXTURE_GEN_T);
684 glNormal3f (0, 0, 1);
687 glMatrixMode (GL_TEXTURE);
689 glMatrixMode (GL_MODELVIEW);
691 enable_texture_string_parameters();
693 /* Draw a quad with that texture on it, possibly using a cached texture.
694 Position the XCharStruct origin at 0,0 in the scene.
696 qx0 = overall.lbearing;
697 qy0 = -overall.descent;
698 qx1 = overall.rbearing;
699 qy1 = overall.ascent;
703 tx1 = (overall.rbearing - overall.lbearing) / (GLfloat) tex_width;
704 ty0 = (overall.ascent + overall.descent) / (GLfloat) tex_height;
706 glEnable (GL_CULL_FACE);
707 glFrontFace (GL_CCW);
709 glTexCoord2f (tx0, ty0); glVertex3f (qx0, qy0, 0);
710 glTexCoord2f (tx1, ty0); glVertex3f (qx1, qy0, 0);
711 glTexCoord2f (tx1, ty1); glVertex3f (qx1, qy1, 0);
712 glTexCoord2f (tx0, ty1); glVertex3f (qx0, qy1, 0);
715 if (draw_back_face_p)
719 glTexCoord2f (tx0, ty0); glVertex3f (qx0, qy0, 0);
720 glTexCoord2f (tx1, ty0); glVertex3f (qx1, qy0, 0);
721 glTexCoord2f (tx1, ty1); glVertex3f (qx1, qy1, 0);
722 glTexCoord2f (tx0, ty1); glVertex3f (qx0, qy1, 0);
724 glDisable (GL_CULL_FACE);
729 /* Reset to the caller's texture environment.
731 glBindTexture (GL_TEXTURE_2D, old_texture);
732 glFrontFace (ofront);
733 if (!alpha_p) glDisable (GL_ALPHA_TEST);
734 if (!blend_p) glDisable (GL_BLEND);
735 if (light_p) glEnable (GL_LIGHTING);
736 if (gen_s_p) glEnable (GL_TEXTURE_GEN_S);
737 if (gen_t_p) glEnable (GL_TEXTURE_GEN_T);
739 glBlendFunc (GL_SRC_ALPHA, oblend);
741 glMatrixMode (GL_TEXTURE);
742 glMultMatrixf (omatrix);
743 glMatrixMode (GL_MODELVIEW);
745 check_gl_error ("texture font print");
747 /* Store this string into the cache, unless that's where it came from.
751 cache->string = strdup (string);
752 cache->extents = overall;
753 cache->tex_width = tex_width;
754 cache->tex_height = tex_height;
760 /* Draws the string on the window at the given pixel position.
761 Newlines and tab stops are honored.
762 Any numbers inside [] will be rendered as a subscript.
763 Assumes the font has been loaded as with load_texture_font().
765 Position is 0 for center, 1 for top left, 2 for bottom left.
768 print_texture_label (Display *dpy,
769 texture_font_data *data,
770 int window_width, int window_height,
776 Bool tex_p = glIsEnabled (GL_TEXTURE_2D);
777 Bool texs_p = glIsEnabled (GL_TEXTURE_GEN_S);
778 Bool text_p = glIsEnabled (GL_TEXTURE_GEN_T);
779 Bool depth_p = glIsEnabled (GL_DEPTH_TEST);
780 Bool cull_p = glIsEnabled (GL_CULL_FACE);
781 Bool fog_p = glIsEnabled (GL_FOG);
784 # ifndef HAVE_JWZGLES
786 glGetIntegerv (GL_POLYGON_MODE, opoly);
789 glGetIntegerv (GL_VIEWPORT, ovp);
791 glGetFloatv (GL_CURRENT_COLOR, color);
793 glEnable (GL_TEXTURE_2D);
794 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
795 glPolygonMode (GL_FRONT, GL_FILL);
797 glDisable (GL_TEXTURE_GEN_S);
798 glDisable (GL_TEXTURE_GEN_T);
799 glDisable (GL_CULL_FACE);
802 glDisable (GL_DEPTH_TEST);
804 /* Each matrix mode has its own stack, so we need to push/pop
807 glMatrixMode(GL_PROJECTION);
812 glMatrixMode(GL_MODELVIEW);
817 int x, y, w, h, swap;
818 /* int rot = (int) current_device_rotation(); */
819 int rot = 0; /* Since GL hacks rotate now */
822 glViewport (0, 0, window_width, window_height);
823 glOrtho (0, window_width, 0, window_height, -1, 1);
825 while (rot <= -180) rot += 360;
826 while (rot > 180) rot -= 360;
828 texture_string_metrics (data, string, &cs, &ascent, &descent);
829 h = cs.ascent + cs.descent;
834 /* Size of the font is in points, so scale iOS pixels to points. */
835 GLfloat scale = ((window_width > window_height
836 ? window_width : window_height)
838 if (scale < 1) scale = 1;
840 /* jwxyz-XLoadFont has already doubled the font size, to compensate
841 for physically smaller screens. Undo that, since OpenGL hacks
842 use full-resolution framebuffers, unlike X11 hacks. */
845 window_width /= scale;
846 window_height /= scale;
847 glScalef (scale, scale, scale);
849 # endif /* USE_IPHONE */
851 if (rot > 135 || rot < -135) /* 180 */
853 glTranslatef (window_width, window_height, 0);
854 glRotatef (180, 0, 0, 1);
856 else if (rot > 45) /* 90 */
858 glTranslatef (window_width, 0, 0);
859 glRotatef (90, 0, 0, 1);
861 window_width = window_height;
862 window_height = swap;
864 else if (rot < -45) /* 270 */
866 glTranslatef(0, window_height, 0);
867 glRotatef (-90, 0, 0, 1);
869 window_width = window_height;
870 window_height = swap;
875 x = (window_width - w) / 2;
876 y = (window_height + h) / 2 - ascent;
880 y = window_height - ascent*2;
890 glTranslatef (x, y, 0);
892 /* draw the text five times, to give it a border. */
894 const XPoint offsets[] = {{ -1, -1 },
902 for (i = 0; i < countof(offsets); i++)
904 if (offsets[i].x == 0)
907 glTranslatef (offsets[i].x, offsets[i].y, 0);
908 print_texture_string (data, string);
915 glMatrixMode(GL_PROJECTION);
918 if (tex_p) glEnable (GL_TEXTURE_2D); else glDisable (GL_TEXTURE_2D);
919 if (texs_p) glEnable (GL_TEXTURE_GEN_S);/*else glDisable(GL_TEXTURE_GEN_S);*/
920 if (text_p) glEnable (GL_TEXTURE_GEN_T);/*else glDisable(GL_TEXTURE_GEN_T);*/
921 if (depth_p) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST);
922 if (cull_p) glEnable (GL_CULL_FACE); /*else glDisable (GL_CULL_FACE);*/
923 if (fog_p) glEnable (GL_FOG); /*else glDisable (GL_FOG);*/
925 glViewport (ovp[0], ovp[1], ovp[2], ovp[3]);
927 # ifndef HAVE_JWZGLES
928 glPolygonMode (GL_FRONT, opoly[0]);
931 glMatrixMode(GL_MODELVIEW);
937 texfont_unicode_character_name (texture_font_data *data, unsigned long uc)
939 Font fid = data->xftfont->xfont->fid;
940 return jwxyz_unicode_character_name (data->dpy, fid, uc);
942 #endif /* HAVE_JWXYZ */
946 /* Releases the font and texture.
949 free_texture_font (texture_font_data *data)
953 texfont_cache *next = data->cache->next;
954 glDeleteTextures (1, &data->cache->texid);
959 XftFontClose (data->dpy, data->xftfont);