1 /* $Id: xfonts.c,v 1.6 2000/04/19 01:44:02 brianp 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
41 #include <X11/Xutil.h>
51 /* Some debugging info. */
62 dump_char_struct (XCharStruct
*ch
, char *prefix
)
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
);
71 dump_font_struct (XFontStruct
*font
)
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" :
79 printf ("default_char = %c (\\%03o)\n",
80 (char) (isprint (font
->default_char
) ? font
->default_char
: ' '),
82 dump_char_struct (&font
->min_bounds
, "min> ");
83 dump_char_struct (&font
->max_bounds
, "max> ");
85 for (c
= font
->min_char_or_byte2
; c
<= font
->max_char_or_byte2
; c
++)
88 sprintf (prefix
, "%d> ", c
);
89 dump_char_struct (&font
->per_char
[c
], prefix
);
95 dump_bitmap (unsigned int width
, unsigned int height
, GLubyte
*bitmap
)
100 for (x
= 0; x
< 8*width
; x
++)
101 printf ("%o", 7 - (x
% 8));
103 for (y
= 0; y
< height
; y
++)
106 for (x
= 0; x
< 8*width
; x
++)
107 putchar ((bitmap
[width
*(height
- y
- 1) + x
/8] & (1 << (7 - (x
%
111 for (x
= 0; x
< width
; x
++)
112 printf ("0x%02x, ", bitmap
[width
*(height
- y
- 1) + x
]);
119 /* Implementation. */
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.
125 Note that the generated bitmaps must be used with
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);
134 Possible optimizations:
136 * use only one reusable pixmap with the maximum dimensions.
137 * draw the entire font into a single pixmap (careful with
138 proportional fonts!).
143 * Generate OpenGL-compatible bitmap.
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
)
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);
160 char2b
.byte1
= (c
>> 8) & 0xff;
161 char2b
.byte2
= (c
& 0xff);
163 XDrawString16 (dpy
, pixmap
, gc
, x0
, y0
, &char2b
, 1);
165 image
= XGetImage (dpy
, pixmap
, 0, 0, 8*width
, height
, 1, XYPixmap
);
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
);
175 XFreePixmap (dpy
, pixmap
);
179 * determine if a given glyph is valid and return the
180 * corresponding XCharStruct.
182 static XCharStruct
*isvalid(XFontStruct
*fs
, int which
)
184 unsigned int rows
,pages
;
188 rows
= fs
->max_byte1
- fs
->min_byte1
+ 1;
189 pages
= fs
->max_char_or_byte2
- fs
->min_char_or_byte2
+ 1;
193 if ((fs
->min_char_or_byte2
> which
) ||
194 (fs
->max_char_or_byte2
< which
)) valid
= 0;
197 byte2
= which
& 0xff;
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;
209 return(fs
->per_char
+ (which
-fs
->min_char_or_byte2
) );
212 i
= ((byte1
- fs
->min_byte1
) * pages
) +
213 (byte2
- fs
->min_char_or_byte2
);
214 return(fs
->per_char
+ i
);
217 return(&fs
->min_bounds
);
224 void Fake_glXUseXFont( Font font
, int first
, int count
, int listbase
)
232 unsigned long valuemask
;
235 GLint swapbytes
, lsbfirst
, rowlength
;
236 GLint skiprows
, skippixels
, alignment
;
238 unsigned int max_width
, max_height
, max_bm_width
, max_bm_height
;
243 CC
= XMesaGetCurrentContext();
245 win
= CC
->xm_buffer
->frontbuffer
;
247 fs
= XQueryFont (dpy
, font
);
250 gl_error (CC
->gl_ctx
, GL_INVALID_VALUE
,
251 "Couldn't get font structure information");
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
;
261 bm
= (GLubyte
*) MALLOC((max_bm_width
* max_bm_height
) * sizeof
264 XFreeFontInfo( NULL
, fs
, 0 );
265 gl_error (CC
->gl_ctx
, GL_OUT_OF_MEMORY
,
266 "Couldn't allocate bitmap in glXUseXFont()");
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
;
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
);
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);
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
);
307 dump_font_struct (fs
);
310 for (i
= 0; i
< count
; i
++)
312 unsigned int width
, height
, bm_width
, bm_height
;
313 GLfloat x0
, y0
, dx
, dy
;
316 unsigned int c
= first
+ i
;
317 int list
= listbase
+ i
;
320 /* check on index validity and get the bounds */
323 ch
= &fs
->max_bounds
;
332 sprintf (s
, isprint (c
) ? "%c> " : "\\%03o> ", c
);
333 dump_char_struct (ch
, s
);
337 /* glBitmap()' parameters:
338 straight from the glXUseXFont(3) manpage. */
339 width
= ch
->rbearing
- ch
->lbearing
;
340 height
= ch
->ascent
+ ch
->descent
;
342 y0
= ch
->descent
- 0; /* XXX used to subtract 1 here */
343 /* but that caused a conformace failure */
347 /* X11's starting point. */
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;
357 glNewList (list
, GL_COMPILE
);
358 if (valid
&& (bm_width
> 0) && (bm_height
> 0)) {
360 MEMSET (bm
, '\0', bm_width
* bm_height
);
361 fill_bitmap (dpy
, win
, gc
, bm_width
, bm_height
, x
, y
, c
, bm
);
363 glBitmap (width
, height
, x0
, y0
, dx
, dy
, bm
);
366 printf ("width/height = %u/%u\n", width
, height
);
367 printf ("bm_width/bm_height = %u/%u\n", bm_width
,
369 dump_bitmap (bm_width
, bm_height
, bm
);
373 glBitmap (0, 0, 0.0, 0.0, dx
, dy
, NULL
);
379 XFreeFontInfo( NULL
, fs
, 0 );
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
);
392 extern void xmesa_xfonts_dummy( void );
393 void xmesa_xfonts_dummy( void )
395 /* silence unused var warnings */