xfonts.c revision 6fc61407a31dc1ea2e00b803c7f6d355f278fb0d
1/* $Id: xfonts.c,v 1.5 1999/12/12 17:04:50 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.3 6 * 7 * Copyright (C) 1999 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 "xmesaP.h" 48 49/* Some debugging info. */ 50 51#ifdef DEBUG 52#undef _R 53#undef _G 54#undef _B 55#include <ctype.h> 56 57int debug_xfonts = 0; 58 59static void 60dump_char_struct (XCharStruct *ch, char *prefix) 61{ 62 printf ("%slbearing = %d, rbearing = %d, width = %d\n", 63 prefix, ch->lbearing, ch->rbearing, ch->width); 64 printf ("%sascent = %d, descent = %d, attributes = %u\n", 65 prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); 66} 67 68static void 69dump_font_struct (XFontStruct *font) 70{ 71 printf ("ascent = %d, descent = %d\n", font->ascent, font->descent); 72 printf ("char_or_byte2 = (%u,%u)\n", 73 font->min_char_or_byte2, font->max_char_or_byte2); 74 printf ("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); 75 printf ("all_chars_exist = %s\n", font->all_chars_exist ? "True" : 76"False"); 77 printf ("default_char = %c (\\%03o)\n", 78 (char) (isprint (font->default_char) ? font->default_char : ' '), 79 font->default_char); 80 dump_char_struct (&font->min_bounds, "min> "); 81 dump_char_struct (&font->max_bounds, "max> "); 82#if 0 83 for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) 84 { 85 char prefix[8]; 86 sprintf (prefix, "%d> ", c); 87 dump_char_struct (&font->per_char[c], prefix); 88 } 89#endif 90} 91 92static void 93dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap) 94{ 95 unsigned int x, y; 96 97 printf (" "); 98 for (x = 0; x < 8*width; x++) 99 printf ("%o", 7 - (x % 8)); 100 putchar ('\n'); 101 for (y = 0; y < height; y++) 102 { 103 printf ("%3o:", y); 104 for (x = 0; x < 8*width; x++) 105 putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x % 1068)))) 107 ? '*' : '.'); 108 printf (" "); 109 for (x = 0; x < width; x++) 110 printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]); 111 putchar ('\n'); 112 } 113} 114#endif /* DEBUG */ 115 116 117/* Implementation. */ 118 119/* Fill a BITMAP with a character C from thew current font 120 in the graphics context GC. WIDTH is the width in bytes 121 and HEIGHT is the height in bits. 122 123 Note that the generated bitmaps must be used with 124 125 glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); 126 glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); 127 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); 128 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); 129 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); 130 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); 131 132 Possible optimizations: 133 134 * use only one reusable pixmap with the maximum dimensions. 135 * draw the entire font into a single pixmap (careful with 136 proportional fonts!). 137*/ 138 139 140/* 141 * Generate OpenGL-compatible bitmap. 142 */ 143static void 144fill_bitmap (Display *dpy, Window win, GC gc, 145 unsigned int width, unsigned int height, 146 int x0, int y0, unsigned int c, GLubyte *bitmap) 147{ 148 XImage *image; 149 unsigned int x, y; 150 Pixmap pixmap; 151 XChar2b char2b; 152 153 pixmap = XCreatePixmap (dpy, win, 8*width, height, 1); 154 XSetForeground(dpy, gc, 0); 155 XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height); 156 XSetForeground(dpy, gc, 1); 157 158 char2b.byte1 = (c >> 8) & 0xff; 159 char2b.byte2 = (c & 0xff); 160 161 XDrawString16 (dpy, pixmap, gc, x0, y0, &char2b, 1); 162 163 image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap); 164 if (image) { 165 /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ 166 for (y = 0; y < height; y++) 167 for (x = 0; x < 8*width; x++) 168 if (XGetPixel (image, x, y)) 169 bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8))); 170 XDestroyImage (image); 171 } 172 173 XFreePixmap (dpy, pixmap); 174} 175 176/* 177 * determine if a given glyph is valid and return the 178 * corresponding XCharStruct. 179 */ 180static XCharStruct *isvalid(XFontStruct *fs, int which) 181{ 182 unsigned int rows,pages; 183 int byte1,byte2; 184 int i,valid = 1; 185 186 rows = fs->max_byte1 - fs->min_byte1 + 1; 187 pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; 188 189 if (rows == 1) { 190 /* "linear" fonts */ 191 if ((fs->min_char_or_byte2 > which) || 192 (fs->max_char_or_byte2 < which)) valid = 0; 193 } else { 194 /* "matrix" fonts */ 195 byte2 = which & 0xff; 196 byte1 = which >> 8; 197 if ((fs->min_char_or_byte2 > byte2) || 198 (fs->max_char_or_byte2 < byte2) || 199 (fs->min_byte1 > byte1) || 200 (fs->max_byte1 < byte1)) valid = 0; 201 } 202 203 if (valid) { 204 if (fs->per_char) { 205 if (rows == 1) { 206 /* "linear" fonts */ 207 return(fs->per_char + (which-fs->min_char_or_byte2) ); 208 } else { 209 /* "matrix" fonts */ 210 i = ((byte1 - fs->min_byte1) * pages) + 211 (byte2 - fs->min_char_or_byte2); 212 return(fs->per_char + i); 213 } 214 } else { 215 return(&fs->min_bounds); 216 } 217 } 218 return(NULL); 219} 220 221 222void Fake_glXUseXFont( Font font, int first, int count, int listbase ) 223{ 224 XMesaContext CC; 225 Display *dpy; 226 Window win; 227 Pixmap pixmap; 228 GC gc; 229 XGCValues values; 230 unsigned long valuemask; 231 XFontStruct *fs; 232 233 GLint swapbytes, lsbfirst, rowlength; 234 GLint skiprows, skippixels, alignment; 235 236 unsigned int max_width, max_height, max_bm_width, max_bm_height; 237 GLubyte *bm; 238 239 int i; 240 241 CC = XMesaGetCurrentContext(); 242 dpy = CC->display; 243 win = CC->xm_buffer->frontbuffer; 244 245 fs = XQueryFont (dpy, font); 246 if (!fs) 247 { 248 gl_error (CC->gl_ctx, GL_INVALID_VALUE, 249 "Couldn't get font structure information"); 250 return; 251 } 252 253 /* Allocate a bitmap that can fit all characters. */ 254 max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; 255 max_height = fs->max_bounds.ascent + fs->max_bounds.descent; 256 max_bm_width = (max_width + 7) / 8; 257 max_bm_height = max_height; 258 259 bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof 260(GLubyte)); 261 if (!bm) { 262 XFreeFontInfo( NULL, fs, 0 ); 263 gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY, 264 "Couldn't allocate bitmap in glXUseXFont()"); 265 return; 266 } 267 268#if 0 269 /* get the page info */ 270 pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; 271 firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; 272 lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; 273 rows = fs->max_byte1 - fs->min_byte1 + 1; 274 unsigned int first_char, last_char, pages, rows; 275#endif 276 277 /* Save the current packing mode for bitmaps. */ 278 glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes); 279 glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst); 280 glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength); 281 glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows); 282 glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels); 283 glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment); 284 285 /* Enforce a standard packing mode which is compatible with 286 fill_bitmap() from above. This is actually the default mode, 287 except for the (non)alignment. */ 288 glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); 289 glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); 290 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); 291 glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); 292 glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); 293 glPixelStorei (GL_UNPACK_ALIGNMENT, 1); 294 295 pixmap = XCreatePixmap (dpy, win, 10, 10, 1); 296 values.foreground = BlackPixel (dpy, DefaultScreen (dpy)); 297 values.background = WhitePixel (dpy, DefaultScreen (dpy)); 298 values.font = fs->fid; 299 valuemask = GCForeground | GCBackground | GCFont; 300 gc = XCreateGC (dpy, pixmap, valuemask, &values); 301 XFreePixmap (dpy, pixmap); 302 303#ifdef DEBUG 304 if (debug_xfonts) 305 dump_font_struct (fs); 306#endif 307 308 for (i = 0; i < count; i++) 309 { 310 unsigned int width, height, bm_width, bm_height; 311 GLfloat x0, y0, dx, dy; 312 XCharStruct *ch; 313 int x, y; 314 unsigned int c = first + i; 315 int list = listbase + i; 316 int valid; 317 318 /* check on index validity and get the bounds */ 319 ch = isvalid(fs, c); 320 if (!ch) { 321 ch = &fs->max_bounds; 322 valid = 0; 323 } else { 324 valid = 1; 325 } 326 327#ifdef DEBUG 328 if (debug_xfonts) { 329 char s[7]; 330 sprintf (s, isprint (c) ? "%c> " : "\\%03o> ", c); 331 dump_char_struct (ch, s); 332 } 333#endif 334 335 /* glBitmap()' parameters: 336 straight from the glXUseXFont(3) manpage. */ 337 width = ch->rbearing - ch->lbearing; 338 height = ch->ascent + ch->descent; 339 x0 = - ch->lbearing; 340 y0 = ch->descent - 0; /* XXX used to subtract 1 here */ 341 /* but that caused a conformace failure */ 342 dx = ch->width; 343 dy = 0; 344 345 /* X11's starting point. */ 346 x = - ch->lbearing; 347 y = ch->ascent; 348 349 /* Round the width to a multiple of eight. We will use this also 350 for the pixmap for capturing the X11 font. This is slightly 351 inefficient, but it makes the OpenGL part real easy. */ 352 bm_width = (width + 7) / 8; 353 bm_height = height; 354 355 glNewList (list, GL_COMPILE); 356 if (valid && (bm_width > 0) && (bm_height > 0)) { 357 358 MEMSET (bm, '\0', bm_width * bm_height); 359 fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm); 360 361 glBitmap (width, height, x0, y0, dx, dy, bm); 362#ifdef DEBUG 363 if (debug_xfonts) { 364 printf ("width/height = %u/%u\n", width, height); 365 printf ("bm_width/bm_height = %u/%u\n", bm_width, 366bm_height); 367 dump_bitmap (bm_width, bm_height, bm); 368 } 369#endif 370 } else { 371 glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL); 372 } 373 glEndList (); 374 } 375 376 free (bm); 377 XFreeFontInfo( NULL, fs, 0 ); 378 XFreeGC (dpy, gc); 379 380 /* Restore saved packing modes. */ 381 glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); 382 glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); 383 glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); 384 glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); 385 glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); 386 glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); 387} 388 389void xmesa_xfonts_dummy( void ) 390{ 391 /* silence unused var warnings */ 392 (void) kernel8; 393 (void) DitherValues; 394 (void) HPCR_DRGB; 395 (void) kernel1; 396} 397 398/* The End. */ 399