1 /* $Id: xfonts.c,v 1.9 2000/08/22 13:31:04 joukj Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
28 /* xfonts.c -- glXUseXFont() for Mesa written by
29 * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
33 #include <GL/vms_x_fix.h>
44 #include <X11/Xutil.h>
52 /* Some debugging info. */
63 dump_char_struct (XCharStruct
*ch
, char *prefix
)
65 printf ("%slbearing = %d, rbearing = %d, width = %d\n",
66 prefix
, ch
->lbearing
, ch
->rbearing
, ch
->width
);
67 printf ("%sascent = %d, descent = %d, attributes = %u\n",
68 prefix
, ch
->ascent
, ch
->descent
, (unsigned int) ch
->attributes
);
72 dump_font_struct (XFontStruct
*font
)
74 printf ("ascent = %d, descent = %d\n", font
->ascent
, font
->descent
);
75 printf ("char_or_byte2 = (%u,%u)\n",
76 font
->min_char_or_byte2
, font
->max_char_or_byte2
);
77 printf ("byte1 = (%u,%u)\n", font
->min_byte1
, font
->max_byte1
);
78 printf ("all_chars_exist = %s\n", font
->all_chars_exist
? "True" :
80 printf ("default_char = %c (\\%03o)\n",
81 (char) (isprint (font
->default_char
) ? font
->default_char
: ' '),
83 dump_char_struct (&font
->min_bounds
, "min> ");
84 dump_char_struct (&font
->max_bounds
, "max> ");
86 for (c
= font
->min_char_or_byte2
; c
<= font
->max_char_or_byte2
; c
++)
89 sprintf (prefix
, "%d> ", c
);
90 dump_char_struct (&font
->per_char
[c
], prefix
);
96 dump_bitmap (unsigned int width
, unsigned int height
, GLubyte
*bitmap
)
101 for (x
= 0; x
< 8*width
; x
++)
102 printf ("%o", 7 - (x
% 8));
104 for (y
= 0; y
< height
; y
++)
107 for (x
= 0; x
< 8*width
; x
++)
108 putchar ((bitmap
[width
*(height
- y
- 1) + x
/8] & (1 << (7 - (x
%
112 for (x
= 0; x
< width
; x
++)
113 printf ("0x%02x, ", bitmap
[width
*(height
- y
- 1) + x
]);
120 /* Implementation. */
122 /* Fill a BITMAP with a character C from thew current font
123 in the graphics context GC. WIDTH is the width in bytes
124 and HEIGHT is the height in bits.
126 Note that the generated bitmaps must be used with
128 glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
129 glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
130 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
131 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
132 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
133 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
135 Possible optimizations:
137 * use only one reusable pixmap with the maximum dimensions.
138 * draw the entire font into a single pixmap (careful with
139 proportional fonts!).
144 * Generate OpenGL-compatible bitmap.
147 fill_bitmap (Display
*dpy
, Window win
, GC gc
,
148 unsigned int width
, unsigned int height
,
149 int x0
, int y0
, unsigned int c
, GLubyte
*bitmap
)
156 pixmap
= XCreatePixmap (dpy
, win
, 8*width
, height
, 1);
157 XSetForeground(dpy
, gc
, 0);
158 XFillRectangle (dpy
, pixmap
, gc
, 0, 0, 8*width
, height
);
159 XSetForeground(dpy
, gc
, 1);
161 char2b
.byte1
= (c
>> 8) & 0xff;
162 char2b
.byte2
= (c
& 0xff);
164 XDrawString16 (dpy
, pixmap
, gc
, x0
, y0
, &char2b
, 1);
166 image
= XGetImage (dpy
, pixmap
, 0, 0, 8*width
, height
, 1, XYPixmap
);
168 /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
169 for (y
= 0; y
< height
; y
++)
170 for (x
= 0; x
< 8*width
; x
++)
171 if (XGetPixel (image
, x
, y
))
172 bitmap
[width
*(height
- y
- 1) + x
/8] |= (1 << (7 - (x
% 8)));
173 XDestroyImage (image
);
176 XFreePixmap (dpy
, pixmap
);
180 * determine if a given glyph is valid and return the
181 * corresponding XCharStruct.
183 static XCharStruct
*isvalid(XFontStruct
*fs
, int which
)
185 unsigned int rows
,pages
;
189 rows
= fs
->max_byte1
- fs
->min_byte1
+ 1;
190 pages
= fs
->max_char_or_byte2
- fs
->min_char_or_byte2
+ 1;
194 if ((fs
->min_char_or_byte2
> which
) ||
195 (fs
->max_char_or_byte2
< which
)) valid
= 0;
198 byte2
= which
& 0xff;
200 if ((fs
->min_char_or_byte2
> byte2
) ||
201 (fs
->max_char_or_byte2
< byte2
) ||
202 (fs
->min_byte1
> byte1
) ||
203 (fs
->max_byte1
< byte1
)) valid
= 0;
210 return(fs
->per_char
+ (which
-fs
->min_char_or_byte2
) );
213 i
= ((byte1
- fs
->min_byte1
) * pages
) +
214 (byte2
- fs
->min_char_or_byte2
);
215 return(fs
->per_char
+ i
);
218 return(&fs
->min_bounds
);
225 void Fake_glXUseXFont( Font font
, int first
, int count
, int listbase
)
232 unsigned long valuemask
;
234 GLint swapbytes
, lsbfirst
, rowlength
;
235 GLint skiprows
, skippixels
, alignment
;
236 unsigned int max_width
, max_height
, max_bm_width
, max_bm_height
;
240 dpy
= glXGetCurrentDisplay();
242 return; /* I guess glXMakeCurrent wasn't called */
243 win
= RootWindow(dpy
, DefaultScreen(dpy
));
245 fs
= XQueryFont (dpy
, font
);
247 gl_error(NULL
, GL_INVALID_VALUE
,
248 "Couldn't get font structure information");
252 /* Allocate a bitmap that can fit all characters. */
253 max_width
= fs
->max_bounds
.rbearing
- fs
->min_bounds
.lbearing
;
254 max_height
= fs
->max_bounds
.ascent
+ fs
->max_bounds
.descent
;
255 max_bm_width
= (max_width
+ 7) / 8;
256 max_bm_height
= max_height
;
258 bm
= (GLubyte
*) MALLOC((max_bm_width
* max_bm_height
) * sizeof
261 XFreeFontInfo( NULL
, fs
, 0 );
262 gl_error(NULL
, GL_OUT_OF_MEMORY
,
263 "Couldn't allocate bitmap in glXUseXFont()");
268 /* get the page info */
269 pages
= fs
->max_char_or_byte2
- fs
->min_char_or_byte2
+ 1;
270 firstchar
= (fs
->min_byte1
<< 8) + fs
->min_char_or_byte2
;
271 lastchar
= (fs
->max_byte1
<< 8) + fs
->max_char_or_byte2
;
272 rows
= fs
->max_byte1
- fs
->min_byte1
+ 1;
273 unsigned int first_char
, last_char
, pages
, rows
;
276 /* Save the current packing mode for bitmaps. */
277 glGetIntegerv (GL_UNPACK_SWAP_BYTES
, &swapbytes
);
278 glGetIntegerv (GL_UNPACK_LSB_FIRST
, &lsbfirst
);
279 glGetIntegerv (GL_UNPACK_ROW_LENGTH
, &rowlength
);
280 glGetIntegerv (GL_UNPACK_SKIP_ROWS
, &skiprows
);
281 glGetIntegerv (GL_UNPACK_SKIP_PIXELS
, &skippixels
);
282 glGetIntegerv (GL_UNPACK_ALIGNMENT
, &alignment
);
284 /* Enforce a standard packing mode which is compatible with
285 fill_bitmap() from above. This is actually the default mode,
286 except for the (non)alignment. */
287 glPixelStorei (GL_UNPACK_SWAP_BYTES
, GL_FALSE
);
288 glPixelStorei (GL_UNPACK_LSB_FIRST
, GL_FALSE
);
289 glPixelStorei (GL_UNPACK_ROW_LENGTH
, 0);
290 glPixelStorei (GL_UNPACK_SKIP_ROWS
, 0);
291 glPixelStorei (GL_UNPACK_SKIP_PIXELS
, 0);
292 glPixelStorei (GL_UNPACK_ALIGNMENT
, 1);
294 pixmap
= XCreatePixmap (dpy
, win
, 10, 10, 1);
295 values
.foreground
= BlackPixel (dpy
, DefaultScreen (dpy
));
296 values
.background
= WhitePixel (dpy
, DefaultScreen (dpy
));
297 values
.font
= fs
->fid
;
298 valuemask
= GCForeground
| GCBackground
| GCFont
;
299 gc
= XCreateGC (dpy
, pixmap
, valuemask
, &values
);
300 XFreePixmap (dpy
, pixmap
);
304 dump_font_struct (fs
);
307 for (i
= 0; i
< count
; i
++)
309 unsigned int width
, height
, bm_width
, bm_height
;
310 GLfloat x0
, y0
, dx
, dy
;
313 unsigned int c
= first
+ i
;
314 int list
= listbase
+ i
;
317 /* check on index validity and get the bounds */
320 ch
= &fs
->max_bounds
;
329 sprintf (s
, isprint (c
) ? "%c> " : "\\%03o> ", c
);
330 dump_char_struct (ch
, s
);
334 /* glBitmap()' parameters:
335 straight from the glXUseXFont(3) manpage. */
336 width
= ch
->rbearing
- ch
->lbearing
;
337 height
= ch
->ascent
+ ch
->descent
;
339 y0
= ch
->descent
- 0; /* XXX used to subtract 1 here */
340 /* but that caused a conformace failure */
344 /* X11's starting point. */
348 /* Round the width to a multiple of eight. We will use this also
349 for the pixmap for capturing the X11 font. This is slightly
350 inefficient, but it makes the OpenGL part real easy. */
351 bm_width
= (width
+ 7) / 8;
354 glNewList (list
, GL_COMPILE
);
355 if (valid
&& (bm_width
> 0) && (bm_height
> 0)) {
357 MEMSET (bm
, '\0', bm_width
* bm_height
);
358 fill_bitmap (dpy
, win
, gc
, bm_width
, bm_height
, x
, y
, c
, bm
);
360 glBitmap (width
, height
, x0
, y0
, dx
, dy
, bm
);
363 printf ("width/height = %u/%u\n", width
, height
);
364 printf ("bm_width/bm_height = %u/%u\n", bm_width
,
366 dump_bitmap (bm_width
, bm_height
, bm
);
370 glBitmap (0, 0, 0.0, 0.0, dx
, dy
, NULL
);
376 XFreeFontInfo( NULL
, fs
, 0 );
379 /* Restore saved packing modes. */
380 glPixelStorei(GL_UNPACK_SWAP_BYTES
, swapbytes
);
381 glPixelStorei(GL_UNPACK_LSB_FIRST
, lsbfirst
);
382 glPixelStorei(GL_UNPACK_ROW_LENGTH
, rowlength
);
383 glPixelStorei(GL_UNPACK_SKIP_ROWS
, skiprows
);
384 glPixelStorei(GL_UNPACK_SKIP_PIXELS
, skippixels
);
385 glPixelStorei(GL_UNPACK_ALIGNMENT
, alignment
);