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