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