1ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/*
2ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * Mesa 3-D graphics library
34a4039e1996a65ebced473fa03a3a970825746ffBrian Paul * Version:  7.6
4ef25c496d52f4f6c45816b64b4c0999321476cd7Brian *
54a4039e1996a65ebced473fa03a3a970825746ffBrian Paul * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
64a4039e1996a65ebced473fa03a3a970825746ffBrian Paul * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
74a4039e1996a65ebced473fa03a3a970825746ffBrian Paul * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
8ef25c496d52f4f6c45816b64b4c0999321476cd7Brian *
9ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * Permission is hereby granted, free of charge, to any person obtaining a
10ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * copy of this software and associated documentation files (the "Software"),
11ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * to deal in the Software without restriction, including without limitation
12ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * and/or sell copies of the Software, and to permit persons to whom the
14ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * Software is furnished to do so, subject to the following conditions:
15ef25c496d52f4f6c45816b64b4c0999321476cd7Brian *
16ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * The above copyright notice and this permission notice shall be included
17ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * in all copies or substantial portions of the Software.
18ef25c496d52f4f6c45816b64b4c0999321476cd7Brian *
19ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25ef25c496d52f4f6c45816b64b4c0999321476cd7Brian */
26ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
27ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
284a4039e1996a65ebced473fa03a3a970825746ffBrian Paul/**
294a4039e1996a65ebced473fa03a3a970825746ffBrian Paul * Fake implementation of glXUseXFont().
30ef25c496d52f4f6c45816b64b4c0999321476cd7Brian */
31ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
324a4039e1996a65ebced473fa03a3a970825746ffBrian Paul
3340fd4323b4be0eee6d4204463737a37011739333Chia-I Wu#include "main/core.h"
3405f8e41b9567695e9b96276d3ac5734ed2b268a8Keith Whitwell#include <GL/glx.h>
35ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
36ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
37ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/* Some debugging info.  */
38ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
39ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#ifdef DEBUG
40ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#include <ctype.h>
41ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
42ef25c496d52f4f6c45816b64b4c0999321476cd7Brianint debug_xfonts = 0;
43ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
44ef25c496d52f4f6c45816b64b4c0999321476cd7Brianstatic void
45ef25c496d52f4f6c45816b64b4c0999321476cd7Briandump_char_struct(XCharStruct * ch, char *prefix)
46ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
47ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("%slbearing = %d, rbearing = %d, width = %d\n",
48ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  prefix, ch->lbearing, ch->rbearing, ch->width);
49ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("%sascent = %d, descent = %d, attributes = %u\n",
50ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
51ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
52ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
53ef25c496d52f4f6c45816b64b4c0999321476cd7Brianstatic void
54ef25c496d52f4f6c45816b64b4c0999321476cd7Briandump_font_struct(XFontStruct * font)
55ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
56ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
57ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("char_or_byte2 = (%u,%u)\n",
58ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  font->min_char_or_byte2, font->max_char_or_byte2);
59ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
60ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
61ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("default_char = %c (\\%03o)\n",
62ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  (char) (isprint(font->default_char) ? font->default_char : ' '),
63ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  font->default_char);
64ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   dump_char_struct(&font->min_bounds, "min> ");
65ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   dump_char_struct(&font->max_bounds, "max> ");
66ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#if 0
67ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
68ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      char prefix[8];
69ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      sprintf(prefix, "%d> ", c);
70ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      dump_char_struct(&font->per_char[c], prefix);
71ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
72ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif
73ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
74ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
75ef25c496d52f4f6c45816b64b4c0999321476cd7Brianstatic void
76ef25c496d52f4f6c45816b64b4c0999321476cd7Briandump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
77ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
78ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int x, y;
79ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
80ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   printf("    ");
81ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   for (x = 0; x < 8 * width; x++)
82ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      printf("%o", 7 - (x % 8));
83ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   putchar('\n');
84ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   for (y = 0; y < height; y++) {
85ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      printf("%3o:", y);
86ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      for (x = 0; x < 8 * width; x++)
87ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
88ef25c496d52f4f6c45816b64b4c0999321476cd7Brian									 8))))
89ef25c496d52f4f6c45816b64b4c0999321476cd7Brian		 ? '*' : '.');
90ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      printf("   ");
91ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      for (x = 0; x < width; x++)
92ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
93ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      putchar('\n');
94ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
95ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
96ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif /* DEBUG */
97ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
98ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
99ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/* Implementation.  */
100ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
101ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/* Fill a BITMAP with a character C from thew current font
102ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   in the graphics context GC.  WIDTH is the width in bytes
103ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   and HEIGHT is the height in bits.
104ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
105ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Note that the generated bitmaps must be used with
106ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
107ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
108ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
109ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
110ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
111ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
112ef25c496d52f4f6c45816b64b4c0999321476cd7Brian        glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
113ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
114ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Possible optimizations:
115ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
116ef25c496d52f4f6c45816b64b4c0999321476cd7Brian     * use only one reusable pixmap with the maximum dimensions.
117ef25c496d52f4f6c45816b64b4c0999321476cd7Brian     * draw the entire font into a single pixmap (careful with
118ef25c496d52f4f6c45816b64b4c0999321476cd7Brian       proportional fonts!).
119ef25c496d52f4f6c45816b64b4c0999321476cd7Brian*/
120ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
121ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
122ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/*
123ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * Generate OpenGL-compatible bitmap.
124ef25c496d52f4f6c45816b64b4c0999321476cd7Brian */
125ef25c496d52f4f6c45816b64b4c0999321476cd7Brianstatic void
126ef25c496d52f4f6c45816b64b4c0999321476cd7Brianfill_bitmap(Display * dpy, Window win, GC gc,
127ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    unsigned int width, unsigned int height,
128ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    int x0, int y0, unsigned int c, GLubyte * bitmap)
129ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
130ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XImage *image;
131ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int x, y;
132ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Pixmap pixmap;
133ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XChar2b char2b;
134ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
135ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
136ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XSetForeground(dpy, gc, 0);
137ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
138ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XSetForeground(dpy, gc, 1);
139ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
140ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   char2b.byte1 = (c >> 8) & 0xff;
141ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   char2b.byte2 = (c & 0xff);
142ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
143ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
144ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
145ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
146ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (image) {
147ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
148ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      for (y = 0; y < height; y++)
149ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 for (x = 0; x < 8 * width; x++)
150ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    if (XGetPixel(image, x, y))
151ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	       bitmap[width * (height - y - 1) + x / 8] |=
152ef25c496d52f4f6c45816b64b4c0999321476cd7Brian		  (1 << (7 - (x % 8)));
153ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      XDestroyImage(image);
154ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
155ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
156ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFreePixmap(dpy, pixmap);
157ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
158ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
159ef25c496d52f4f6c45816b64b4c0999321476cd7Brian/*
160ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * determine if a given glyph is valid and return the
161ef25c496d52f4f6c45816b64b4c0999321476cd7Brian * corresponding XCharStruct.
162ef25c496d52f4f6c45816b64b4c0999321476cd7Brian */
163ef25c496d52f4f6c45816b64b4c0999321476cd7Brianstatic XCharStruct *
164ef25c496d52f4f6c45816b64b4c0999321476cd7Brianisvalid(XFontStruct * fs, unsigned int which)
165ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
166ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int rows, pages;
167ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int byte1 = 0, byte2 = 0;
168ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   int i, valid = 1;
169ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
170ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   rows = fs->max_byte1 - fs->min_byte1 + 1;
171ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
172ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
173ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (rows == 1) {
174ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* "linear" fonts */
175ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
176ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 valid = 0;
177ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
178ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   else {
179ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* "matrix" fonts */
180ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      byte2 = which & 0xff;
181ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      byte1 = which >> 8;
182ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if ((fs->min_char_or_byte2 > byte2) ||
183ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  (fs->max_char_or_byte2 < byte2) ||
184ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	  (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
185ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 valid = 0;
186ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
187ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
188ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (valid) {
189ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if (fs->per_char) {
190ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 if (rows == 1) {
191ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    /* "linear" fonts */
192ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    return (fs->per_char + (which - fs->min_char_or_byte2));
193ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 }
194ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 else {
195ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    /* "matrix" fonts */
196ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    i = ((byte1 - fs->min_byte1) * pages) +
197ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	       (byte2 - fs->min_char_or_byte2);
198ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    return (fs->per_char + i);
199ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 }
200ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
201ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      else {
202ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 return (&fs->min_bounds);
203ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
204ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
205ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   return (NULL);
206ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
207ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
208ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
209cca66dbb59673168d57b4e3499ccc31f4ddc86adChia-I WuPUBLIC void
2104a4039e1996a65ebced473fa03a3a970825746ffBrian PaulglXUseXFont(Font font, int first, int count, int listbase)
211ef25c496d52f4f6c45816b64b4c0999321476cd7Brian{
212ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Display *dpy;
213ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Window win;
214ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   Pixmap pixmap;
215ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   GC gc;
216ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XGCValues values;
217ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned long valuemask;
218ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFontStruct *fs;
219ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   GLint swapbytes, lsbfirst, rowlength;
220ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   GLint skiprows, skippixels, alignment;
221ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int max_width, max_height, max_bm_width, max_bm_height;
222ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   GLubyte *bm;
223ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   int i;
224ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
225ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   dpy = glXGetCurrentDisplay();
226ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (!dpy)
227ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      return;			/* I guess glXMakeCurrent wasn't called */
2284a4039e1996a65ebced473fa03a3a970825746ffBrian Paul   i = DefaultScreen(dpy);
2294a4039e1996a65ebced473fa03a3a970825746ffBrian Paul   win = RootWindow(dpy, i);
230ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
231ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   fs = XQueryFont(dpy, font);
232ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (!fs) {
233ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      _mesa_error(NULL, GL_INVALID_VALUE,
234ef25c496d52f4f6c45816b64b4c0999321476cd7Brian		  "Couldn't get font structure information");
235ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      return;
236ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
237ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
238ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   /* Allocate a bitmap that can fit all characters.  */
239ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
240ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
241ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   max_bm_width = (max_width + 7) / 8;
242ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   max_bm_height = max_height;
243ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
244ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte));
245ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (!bm) {
246ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      XFreeFontInfo(NULL, fs, 1);
247ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      _mesa_error(NULL, GL_OUT_OF_MEMORY,
248ef25c496d52f4f6c45816b64b4c0999321476cd7Brian		  "Couldn't allocate bitmap in glXUseXFont()");
249ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      return;
250ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
251ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
252ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#if 0
253ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   /* get the page info */
254ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
255ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
256ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
257ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   rows = fs->max_byte1 - fs->min_byte1 + 1;
258ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   unsigned int first_char, last_char, pages, rows;
259ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif
260ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
261ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   /* Save the current packing mode for bitmaps.  */
262ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
263ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
264ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
265ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
266ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
267ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
268ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
269ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   /* Enforce a standard packing mode which is compatible with
270ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      fill_bitmap() from above.  This is actually the default mode,
271ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      except for the (non)alignment.  */
272ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
273ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
274ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
275ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
276ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
277ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
278ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
279ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
280ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
281ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   values.background = WhitePixel(dpy, DefaultScreen(dpy));
282ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   values.font = fs->fid;
283ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   valuemask = GCForeground | GCBackground | GCFont;
284ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   gc = XCreateGC(dpy, pixmap, valuemask, &values);
285ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFreePixmap(dpy, pixmap);
286ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
287ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#ifdef DEBUG
288ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   if (debug_xfonts)
289ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      dump_font_struct(fs);
290ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif
291ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
292ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   for (i = 0; i < count; i++) {
293ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      unsigned int width, height, bm_width, bm_height;
294ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      GLfloat x0, y0, dx, dy;
295ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      XCharStruct *ch;
296ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      int x, y;
297ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      unsigned int c = first + i;
298ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      int list = listbase + i;
299ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      int valid;
300ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
301ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* check on index validity and get the bounds */
302ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      ch = isvalid(fs, c);
303ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if (!ch) {
304ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 ch = &fs->max_bounds;
305ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 valid = 0;
306ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
307ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      else {
308ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 valid = 1;
309ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
310ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
311ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#ifdef DEBUG
312ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if (debug_xfonts) {
313ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 char s[7];
314ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
315ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 dump_char_struct(ch, s);
316ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
317ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif
318ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
319ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* glBitmap()' parameters:
320ef25c496d52f4f6c45816b64b4c0999321476cd7Brian         straight from the glXUseXFont(3) manpage.  */
321ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      width = ch->rbearing - ch->lbearing;
322ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      height = ch->ascent + ch->descent;
323ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      x0 = -ch->lbearing;
324ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      y0 = ch->descent - 0;	/* XXX used to subtract 1 here */
325ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* but that caused a conformace failure */
326ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      dx = ch->width;
327ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      dy = 0;
328ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
329ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* X11's starting point.  */
330ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      x = -ch->lbearing;
331ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      y = ch->ascent;
332ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
333ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      /* Round the width to a multiple of eight.  We will use this also
334ef25c496d52f4f6c45816b64b4c0999321476cd7Brian         for the pixmap for capturing the X11 font.  This is slightly
335ef25c496d52f4f6c45816b64b4c0999321476cd7Brian         inefficient, but it makes the OpenGL part real easy.  */
336ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      bm_width = (width + 7) / 8;
337ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      bm_height = height;
338ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
339ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      glNewList(list, GL_COMPILE);
340ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      if (valid && (bm_width > 0) && (bm_height > 0)) {
341ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
3422240ba10f30315410bcff77e372ee71664ac4453Brian Paul	 memset(bm, '\0', bm_width * bm_height);
343ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
344ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
345ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 glBitmap(width, height, x0, y0, dx, dy, bm);
346ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#ifdef DEBUG
347ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 if (debug_xfonts) {
348ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    printf("width/height = %u/%u\n", width, height);
349ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
350ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	    dump_bitmap(bm_width, bm_height, bm);
351ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 }
352ef25c496d52f4f6c45816b64b4c0999321476cd7Brian#endif
353ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
354ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      else {
355ef25c496d52f4f6c45816b64b4c0999321476cd7Brian	 glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
356ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      }
357ef25c496d52f4f6c45816b64b4c0999321476cd7Brian      glEndList();
358ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   }
359ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
360ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   FREE(bm);
361ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFreeFontInfo(NULL, fs, 1);
362ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   XFreeGC(dpy, gc);
363ef25c496d52f4f6c45816b64b4c0999321476cd7Brian
364ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   /* Restore saved packing modes.  */
365ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
366ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
367ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
368ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
369ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
370ef25c496d52f4f6c45816b64b4c0999321476cd7Brian   glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
371ef25c496d52f4f6c45816b64b4c0999321476cd7Brian}
372