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.
12 * A higher level API is in glxfonts.c.
28 # include <OpenGL/glu.h>
30 #elif defined(HAVE_ANDROID)
40 #endif /* HAVE_JWZGLES */
42 #ifdef HAVE_XSHM_EXTENSION
44 #endif /* HAVE_XSHM_EXTENSION */
48 #include "resources.h"
50 #include "fps.h" /* for current_device_rotation() */
52 #undef HAVE_XSHM_EXTENSION /* doesn't actually do any good here */
55 /* These are in xlock-gl.c */
56 extern void clear_gl_error (void);
57 extern void check_gl_error (const char *type);
60 extern char *progname;
62 /* LRU cache of textures, to optimize the case where we're drawing the
63 same strings repeatedly.
65 typedef struct texfont_cache texfont_cache;
66 struct texfont_cache {
70 int tex_width, tex_height;
74 struct texture_font_data {
83 #define countof(x) (sizeof((x))/sizeof((*x)))
86 /* Given a Pixmap (of screen depth), converts it to an OpenGL luminance mipmap.
87 RGB are averaged to grayscale, and the resulting value is treated as alpha.
88 Pass in the size of the pixmap; the size of the texture is returned
89 (it may be larger, since GL like powers of 2.)
91 We use a screen-depth pixmap instead of a 1bpp bitmap so that if the fonts
92 were drawn with antialiasing, that is preserved.
95 bitmap_to_texture (Display *dpy, Pixmap p, Visual *visual, int depth,
101 GLsizei w2 = (GLsizei) to_pow2 (ow);
102 GLsizei h2 = (GLsizei) to_pow2 (oh);
103 int x, y, max, scale;
105 unsigned char *data = (unsigned char *) calloc (w2 * 2, (h2 + 1));
106 unsigned char *out = data;
108 /* OpenGLES doesn't support GL_INTENSITY, so instead of using a
109 texture with 1 byte per pixel, the intensity value, we have
110 to use 2 bytes per pixel: solid white, and an alpha value.
116 # ifdef HAVE_XSHM_EXTENSION
117 Bool use_shm = get_boolean_resource (dpy, "useSHM", "Boolean");
118 XShmSegmentInfo shm_info;
119 # endif /* HAVE_XSHM_EXTENSION */
121 /* If either dimension is larger than the supported size, reduce.
122 We still return the old size to keep the caller's math working,
123 but the texture itself will have fewer pixels in it.
125 glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max);
127 while (w2 > max || h2 > max)
134 # ifdef HAVE_XSHM_EXTENSION
137 image = create_xshm_image (dpy, visual, depth, ZPixmap, 0, &shm_info,
140 XShmGetImage (dpy, p, image, 0, 0, ~0L);
144 # endif /* HAVE_XSHM_EXTENSION */
147 /* XCreateImage fills in (red|green_blue)_mask. XGetImage only does that
148 when reading from a Window, not when it's a Pixmap.
150 image = XCreateImage (dpy, visual, depth, ZPixmap, 0, NULL, ow, oh,
152 image->data = malloc (image->height * image->bytes_per_line);
153 XGetSubImage (dpy, p, 0, 0, ow, oh, ~0L, ZPixmap, image, 0, 0);
157 /* This would work, but it's wasteful for no benefit. */
162 fprintf (stderr, "\n");
164 for (y = 0; y < h2; y++) {
165 for (x = 0; x < w2; x++) {
166 /* Might be better to average a scale x scale square of source pixels,
167 but at the resolutions we're dealing with, this is probably good
171 unsigned long pixel = (sx >= ow || sy >= oh ? 0 :
172 XGetPixel (image, sx, sy));
173 /* instead of averaging all three channels, let's just use red,
174 and assume it was already grayscale. */
175 unsigned long r = pixel & image->red_mask;
176 /* This goofy trick is to make any of RGBA/ABGR/ARGB work. */
177 pixel = ((r >> 24) | (r >> 16) | (r >> 8) | r) & 0xFF;
180 if (sx < ow && sy < oh)
182 fprintf (stderr, "%c",
183 r >= 0xFF000000 ? '#' :
184 r >= 0x88000000 ? '%' :
187 fprintf (stderr, "%c",
188 r >= 0xFF0000 ? '#' :
189 r >= 0x880000 ? '%' :
194 # if 0 /* Debugging checkerboard */
195 if (sx < ow && sy < oh && (((sx / 4) & 1) ^ ((sy / 4) & 1)))
199 # ifndef GL_INTENSITY
200 *out++ = 0xFF; /* 2 bytes per pixel (luminance, alpha) */
205 fprintf (stderr, "\n");
209 # ifdef HAVE_XSHM_EXTENSION
211 destroy_xshm_image (dpy, image, &shm_info);
213 # endif /* HAVE_XSHM_EXTENSION */
215 /* We malloc'd image->data, so we free it. */
218 XDestroyImage (image);
225 GLuint iformat = GL_INTENSITY;
226 GLuint format = GL_LUMINANCE;
228 GLuint iformat = GL_LUMINANCE_ALPHA;
229 GLuint format = GL_LUMINANCE_ALPHA;
231 GLuint type = GL_UNSIGNED_BYTE;
234 gluBuild2DMipmaps (GL_TEXTURE_2D, iformat, w2, h2, format, type, data);
236 glTexImage2D (GL_TEXTURE_2D, 0, iformat, w2, h2, 0, format, type, data);
241 sprintf (msg, "texture font %s (%d x %d)",
242 mipmap_p ? "gluBuild2DMipmaps" : "glTexImage2D",
244 check_gl_error (msg);
254 /* Loads the font named by the X resource "res" and returns
255 a texture-font object.
258 load_texture_font (Display *dpy, char *res)
260 int screen = DefaultScreen (dpy);
261 char *font = get_string_resource (dpy, res, "Font");
262 const char *def1 = "-*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*";
263 const char *def2 = "-*-helvetica-medium-r-normal-*-*-140-*-*-*-*-*-*";
264 const char *def3 = "fixed";
266 texture_font_data *data;
267 int cache_size = get_integer_resource (dpy, "texFontCacheSize", "Integer");
269 /* Hacks that draw a lot of different strings on the screen simultaneously,
270 like Star Wars, should set this to a larger value for performance. */
274 if (!res || !*res) abort();
276 if (!strcmp (res, "fpsFont")) { /* Kludge. */
277 def1 = "-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*";
278 cache_size = 0; /* No need for a cache on FPS: already throttled. */
281 if (!font) font = strdup(def1);
283 f = XftFontOpenXlfd (dpy, screen, font);
284 if (!f && !!strcmp (font, def1))
286 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
287 progname, font, def1);
289 font = strdup (def1);
290 f = XftFontOpenXlfd (dpy, screen, font);
293 if (!f && !!strcmp (font, def2))
295 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
296 progname, font, def2);
298 font = strdup (def2);
299 f = XftFontOpenXlfd (dpy, screen, font);
302 if (!f && !!strcmp (font, def3))
304 fprintf (stderr, "%s: unable to load font \"%s\", using \"%s\"\n",
305 progname, font, def3);
307 font = strdup (def3);
308 f = XftFontOpenXlfd (dpy, screen, font);
313 fprintf (stderr, "%s: unable to load fallback font \"%s\" either!\n",
321 data = (texture_font_data *) calloc (1, sizeof(*data));
324 data->cache_size = cache_size;
330 /* Measure the string, returning the overall metrics.
331 Newlines and tab stops are honored.
332 Any numbers inside [] will be rendered as a subscript.
334 The origin is at the origin of the first character, so subsequent
335 lines of a multi-line string look like descenders (below baseline).
337 If an XftDraw is supplied, render the string as well, at X,Y.
338 Positive Y is down (X11 style, not OpenGL style).
341 iterate_texture_string (texture_font_data *data,
343 int draw_x, int draw_y,
344 XftDraw *xftdraw, XftColor *xftcolor,
345 XCharStruct *metrics_ret)
347 int line_height = data->xftfont->ascent + data->xftfont->descent;
348 int subscript_offset = line_height * 0.3;
350 Bool sub_p = False, osub_p = False;
351 int cw = 0, tabs = 0;
352 XCharStruct overall = { 0, };
361 (*s == '[' && isdigit(s[1])) ||
362 (*s == ']' && sub_p))
369 if (sub_p) y2 += subscript_offset;
371 XftTextExtentsUtf8 (data->dpy, data->xftfont,
372 (FcChar8 *) os, (int) (s - os),
374 c.lbearing = -e.x; /* XGlyphInfo to XCharStruct */
375 c.rbearing = e.width - e.x;
377 c.descent = e.height - e.y;
382 # define MAX(A,B) ((A)>(B)?(A):(B))
383 # define MIN(A,B) ((A)<(B)?(A):(B))
384 overall.ascent = MAX (overall.ascent, -y2 + c.ascent);
385 overall.descent = MAX (overall.descent, y2 + c.descent);
386 overall.lbearing = MIN (overall.lbearing, (x + c.lbearing));
387 overall.rbearing = MAX (overall.rbearing, x + c.rbearing);
388 overall.width = MAX (overall.width, x + c.width);
404 /* Measure "m" to determine tab width. */
406 XftTextExtentsUtf8 (data->dpy, data->xftfont,
407 (FcChar8 *) "m", 1, &e);
412 x = ((x + tabs) / tabs) * tabs;
414 else if (*s == '[' && isdigit(s[1]))
416 else if (*s == ']' && sub_p)
419 if (xftdraw && s != os)
420 XftDrawStringUtf8 (xftdraw, xftcolor, data->xftfont,
423 oy + (osub_p ? subscript_offset : 0),
424 (FcChar8 *) os, (int) (s - os));
435 *metrics_ret = overall;
439 /* Bounding box of the multi-line string, in pixels,
440 and overall ascent/descent of the font.
443 texture_string_metrics (texture_font_data *data, const char *s,
444 XCharStruct *metrics_ret,
445 int *ascent_ret, int *descent_ret)
448 iterate_texture_string (data, s, 0, 0, 0, 0, metrics_ret);
449 if (ascent_ret) *ascent_ret = data->xftfont->ascent;
450 if (descent_ret) *descent_ret = data->xftfont->descent;
454 /* Returns a cache entry for this string, with a valid texid.
455 If the returned entry has a string in it, the texture is valid.
456 Otherwise it is an empty entry waiting to be rendered.
458 static struct texfont_cache *
459 get_cache (texture_font_data *data, const char *string)
462 texfont_cache *prev = 0, *prev2 = 0, *curr = 0, *next = 0;
465 for (prev2 = 0, prev = 0, curr = data->cache, next = curr->next;
467 prev2 = prev, prev = curr, curr = next,
468 next = (curr ? curr->next : 0), count++)
470 if (!strcmp (string, curr->string))
473 prev->next = next; /* Unlink from list */
474 if (curr != data->cache)
476 curr->next = data->cache; /* Move to front */
483 /* Made it to the end of the list without a hit.
484 If the cache is full, empty out the last one on the list,
485 and move it to the front. Keep the texid.
487 if (count > data->cache_size)
493 prev->tex_height = 0;
494 memset (&prev->extents, 0, sizeof(prev->extents));
497 if (prev != data->cache)
498 prev->next = data->cache;
503 /* Not cached, and cache not full. Add a new entry at the front,
504 and allocate a new texture for it.
506 curr = (struct texfont_cache *) calloc (1, sizeof(*prev));
507 glGenTextures (1, &curr->texid);
509 curr->next = data->cache;
516 /* Renders the given string into the prevailing texture.
517 Returns the metrics of the text, and size of the texture.
520 string_to_texture (texture_font_data *data, const char *string,
521 XCharStruct *extents_ret,
522 int *tex_width_ret, int *tex_height_ret)
524 Window window = RootWindow (data->dpy, 0);
528 XWindowAttributes xgwa;
535 /* Measure the string and create a Pixmap of the proper size.
537 XGetWindowAttributes (data->dpy, window, &xgwa);
538 iterate_texture_string (data, string, 0, 0, 0, 0, &overall);
539 width = overall.rbearing - overall.lbearing;
540 height = overall.ascent + overall.descent;
541 if (width <= 0) width = 1;
542 if (height <= 0) height = 1;
543 p = XCreatePixmap (data->dpy, window, width, height, xgwa.depth);
545 gcv.foreground = BlackPixelOfScreen (xgwa.screen);
546 gc = XCreateGC (data->dpy, p, GCForeground, &gcv);
547 XFillRectangle (data->dpy, p, gc, 0, 0, width, height);
548 XFreeGC (data->dpy, gc);
550 /* Render the string into the pixmap.
552 rcolor.red = rcolor.green = rcolor.blue = rcolor.alpha = 0xFFFF;
553 XftColorAllocValue (data->dpy, xgwa.visual, xgwa.colormap,
555 xftdraw = XftDrawCreate (data->dpy, p, xgwa.visual, xgwa.colormap);
556 iterate_texture_string (data, string,
557 -overall.lbearing, overall.ascent,
558 xftdraw, &xftcolor, 0);
559 XftDrawDestroy (xftdraw);
560 XftColorFree (data->dpy, xgwa.visual, xgwa.colormap, &xftcolor);
562 /* Copy the bits from the Pixmap into a texture, unless it's cached.
564 bitmap_to_texture (data->dpy, p, xgwa.visual, xgwa.depth,
566 XFreePixmap (data->dpy, p);
568 if (extents_ret) *extents_ret = overall;
569 if (tex_width_ret) *tex_width_ret = width;
570 if (tex_height_ret) *tex_height_ret = height;
574 /* Set the various OpenGL parameters for properly rendering things
575 with a texture generated by string_to_texture().
578 enable_texture_string_parameters (void)
580 glEnable (GL_TEXTURE_2D);
582 /* Texture-rendering parameters to make font pixmaps tolerable to look at.
584 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
585 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
586 GL_LINEAR_MIPMAP_LINEAR);
588 /* LOD bias is part of OpenGL 1.4.
589 GL_EXT_texture_lod_bias has been present since the original iPhone.
591 # if !defined(GL_TEXTURE_LOD_BIAS) && defined(GL_TEXTURE_LOD_BIAS_EXT)
592 # define GL_TEXTURE_LOD_BIAS GL_TEXTURE_LOD_BIAS_EXT
594 # ifdef GL_TEXTURE_LOD_BIAS
595 glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.25);
597 clear_gl_error(); /* invalid enum on iPad 3 */
599 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
600 glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
602 /* Don't write the transparent parts of the quad into the depth buffer. */
603 glAlphaFunc (GL_GREATER, 0.01);
604 glEnable (GL_ALPHA_TEST);
606 glDisable (GL_LIGHTING);
607 glDisable (GL_TEXTURE_GEN_S);
608 glDisable (GL_TEXTURE_GEN_T);
609 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
613 /* Draws the string in the scene at the origin.
614 Newlines and tab stops are honored.
615 Any numbers inside [] will be rendered as a subscript.
616 Assumes the font has been loaded as with load_texture_font().
618 The origin is at the origin of the first character, so subsequent
619 lines of a multi-line string are below that.
622 print_texture_string (texture_font_data *data, const char *string)
625 int tex_width, tex_height;
626 texfont_cache *cache;
629 if (!*string) return;
633 /* Save the prevailing texture ID, and bind ours. Restored at the end. */
634 glGetIntegerv (GL_TEXTURE_BINDING_2D, &old_texture);
636 cache = get_cache (data, string);
638 glBindTexture (GL_TEXTURE_2D, cache->texid);
639 check_gl_error ("texture font binding");
641 /* Measure the string and make a pixmap that will fit it,
646 overall = data->cache->extents;
647 tex_width = data->cache->tex_width;
648 tex_height = data->cache->tex_height;
652 # if defined HAVE_JWXYZ && defined JWXYZ_GL
653 /* TODO, JWXYZ_GL: Mixing Xlib and GL has issues. */
654 memset (&overall, 0, sizeof(overall));
658 string_to_texture (data, string, &overall, &tex_width, &tex_height);
664 Bool alpha_p, blend_p, light_p, gen_s_p, gen_t_p;
666 GLfloat qx0, qy0, qx1, qy1;
667 GLfloat tx0, ty0, tx1, ty1;
669 /* If face culling is not enabled, draw front and back. */
670 Bool draw_back_face_p = !glIsEnabled (GL_CULL_FACE);
672 /* Save the prevailing texture environment, and set up ours.
674 glGetIntegerv (GL_FRONT_FACE, &ofront);
675 glGetIntegerv (GL_BLEND_DST, &oblend);
676 glGetFloatv (GL_TEXTURE_MATRIX, omatrix);
677 blend_p = glIsEnabled (GL_BLEND);
678 alpha_p = glIsEnabled (GL_ALPHA_TEST);
679 light_p = glIsEnabled (GL_LIGHTING);
680 gen_s_p = glIsEnabled (GL_TEXTURE_GEN_S);
681 gen_t_p = glIsEnabled (GL_TEXTURE_GEN_T);
685 glNormal3f (0, 0, 1);
688 glMatrixMode (GL_TEXTURE);
690 glMatrixMode (GL_MODELVIEW);
692 enable_texture_string_parameters();
694 /* Draw a quad with that texture on it, possibly using a cached texture.
695 Position the XCharStruct origin at 0,0 in the scene.
697 qx0 = overall.lbearing;
698 qy0 = -overall.descent;
699 qx1 = overall.rbearing;
700 qy1 = overall.ascent;
704 tx1 = (overall.rbearing - overall.lbearing) / (GLfloat) tex_width;
705 ty0 = (overall.ascent + overall.descent) / (GLfloat) tex_height;
707 glEnable (GL_CULL_FACE);
708 glFrontFace (GL_CCW);
710 glTexCoord2f (tx0, ty0); glVertex3f (qx0, qy0, 0);
711 glTexCoord2f (tx1, ty0); glVertex3f (qx1, qy0, 0);
712 glTexCoord2f (tx1, ty1); glVertex3f (qx1, qy1, 0);
713 glTexCoord2f (tx0, ty1); glVertex3f (qx0, qy1, 0);
716 if (draw_back_face_p)
720 glTexCoord2f (tx0, ty0); glVertex3f (qx0, qy0, 0);
721 glTexCoord2f (tx1, ty0); glVertex3f (qx1, qy0, 0);
722 glTexCoord2f (tx1, ty1); glVertex3f (qx1, qy1, 0);
723 glTexCoord2f (tx0, ty1); glVertex3f (qx0, qy1, 0);
725 glDisable (GL_CULL_FACE);
730 /* Reset to the caller's texture environment.
732 glBindTexture (GL_TEXTURE_2D, old_texture);
733 glFrontFace (ofront);
734 if (!alpha_p) glDisable (GL_ALPHA_TEST);
735 if (!blend_p) glDisable (GL_BLEND);
736 if (light_p) glEnable (GL_LIGHTING);
737 if (gen_s_p) glEnable (GL_TEXTURE_GEN_S);
738 if (gen_t_p) glEnable (GL_TEXTURE_GEN_T);
740 glBlendFunc (GL_SRC_ALPHA, oblend);
742 glMatrixMode (GL_TEXTURE);
743 glMultMatrixf (omatrix);
744 glMatrixMode (GL_MODELVIEW);
746 check_gl_error ("texture font print");
748 /* Store this string into the cache, unless that's where it came from.
752 cache->string = strdup (string);
753 cache->extents = overall;
754 cache->tex_width = tex_width;
755 cache->tex_height = tex_height;
761 /* Draws the string on the window at the given pixel position.
762 Newlines and tab stops are honored.
763 Any numbers inside [] will be rendered as a subscript.
764 Assumes the font has been loaded as with load_texture_font().
766 Position is 0 for center, 1 for top left, 2 for bottom left.
769 print_texture_label (Display *dpy,
770 texture_font_data *data,
771 int window_width, int window_height,
777 Bool tex_p = glIsEnabled (GL_TEXTURE_2D);
778 Bool texs_p = glIsEnabled (GL_TEXTURE_GEN_S);
779 Bool text_p = glIsEnabled (GL_TEXTURE_GEN_T);
780 Bool depth_p = glIsEnabled (GL_DEPTH_TEST);
781 Bool cull_p = glIsEnabled (GL_CULL_FACE);
782 Bool fog_p = glIsEnabled (GL_FOG);
785 # ifndef HAVE_JWZGLES
787 glGetIntegerv (GL_POLYGON_MODE, opoly);
790 glGetIntegerv (GL_VIEWPORT, ovp);
792 glGetFloatv (GL_CURRENT_COLOR, color);
794 glEnable (GL_TEXTURE_2D);
795 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
796 glPolygonMode (GL_FRONT, GL_FILL);
798 glDisable (GL_TEXTURE_GEN_S);
799 glDisable (GL_TEXTURE_GEN_T);
800 glDisable (GL_CULL_FACE);
803 glDisable (GL_DEPTH_TEST);
805 /* Each matrix mode has its own stack, so we need to push/pop
808 glMatrixMode(GL_PROJECTION);
813 glMatrixMode(GL_MODELVIEW);
818 int x, y, w, h, swap;
819 /* int rot = (int) current_device_rotation(); */
820 int rot = 0; /* Since GL hacks rotate now */
823 glViewport (0, 0, window_width, window_height);
824 glOrtho (0, window_width, 0, window_height, -1, 1);
826 while (rot <= -180) rot += 360;
827 while (rot > 180) rot -= 360;
829 texture_string_metrics (data, string, &cs, &ascent, &descent);
830 h = cs.ascent + cs.descent;
835 /* Size of the font is in points, so scale iOS pixels to points. */
836 GLfloat scale = ((window_width > window_height
837 ? window_width : window_height)
839 if (scale < 1) scale = 1;
841 /* jwxyz-XLoadFont has already doubled the font size, to compensate
842 for physically smaller screens. Undo that, since OpenGL hacks
843 use full-resolution framebuffers, unlike X11 hacks. */
846 window_width /= scale;
847 window_height /= scale;
848 glScalef (scale, scale, scale);
850 # endif /* USE_IPHONE */
852 if (rot > 135 || rot < -135) /* 180 */
854 glTranslatef (window_width, window_height, 0);
855 glRotatef (180, 0, 0, 1);
857 else if (rot > 45) /* 90 */
859 glTranslatef (window_width, 0, 0);
860 glRotatef (90, 0, 0, 1);
862 window_width = window_height;
863 window_height = swap;
865 else if (rot < -45) /* 270 */
867 glTranslatef(0, window_height, 0);
868 glRotatef (-90, 0, 0, 1);
870 window_width = window_height;
871 window_height = swap;
876 x = (window_width - w) / 2;
877 y = (window_height + h) / 2 - ascent;
881 y = window_height - ascent*2;
891 glTranslatef (x, y, 0);
893 /* draw the text five times, to give it a border. */
895 const XPoint offsets[] = {{ -1, -1 },
903 for (i = 0; i < countof(offsets); i++)
905 if (offsets[i].x == 0)
908 glTranslatef (offsets[i].x, offsets[i].y, 0);
909 print_texture_string (data, string);
916 glMatrixMode(GL_PROJECTION);
919 if (tex_p) glEnable (GL_TEXTURE_2D); else glDisable (GL_TEXTURE_2D);
920 if (texs_p) glEnable (GL_TEXTURE_GEN_S);/*else glDisable(GL_TEXTURE_GEN_S);*/
921 if (text_p) glEnable (GL_TEXTURE_GEN_T);/*else glDisable(GL_TEXTURE_GEN_T);*/
922 if (depth_p) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST);
923 if (cull_p) glEnable (GL_CULL_FACE); /*else glDisable (GL_CULL_FACE);*/
924 if (fog_p) glEnable (GL_FOG); /*else glDisable (GL_FOG);*/
926 glViewport (ovp[0], ovp[1], ovp[2], ovp[3]);
928 # ifndef HAVE_JWZGLES
929 glPolygonMode (GL_FRONT, opoly[0]);
932 glMatrixMode(GL_MODELVIEW);
938 texfont_unicode_character_name (texture_font_data *data, unsigned long uc)
940 Font fid = data->xftfont->xfont->fid;
941 return jwxyz_unicode_character_name (data->dpy, fid, uc);
943 #endif /* HAVE_JWXYZ */
947 /* Releases the font and texture.
950 free_texture_font (texture_font_data *data)
954 texfont_cache *next = data->cache->next;
955 glDeleteTextures (1, &data->cache->texid);
960 XftFontClose (data->dpy, data->xftfont);