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