xfonts.c revision 71dea349d2be623b7819389428b0d6a124e8d184
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 59int debug_xfonts = 0; 60 61static void 62dump_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 70static void 71dump_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 94static void 95dump_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 % 1088)))) 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 */ 145static void 146fill_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 */ 182static 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 224void 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, 368bm_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 392extern void xmesa_xfonts_dummy( void ); 393void 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. */ 403