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 1327ec681f3Smrgfill_bitmap(Display * dpy, int screen, 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 1417ec681f3Smrg pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen), 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; 2187ec681f3Smrg int screen; 219cdc920a0Smrg Pixmap pixmap; 220cdc920a0Smrg GC gc; 221cdc920a0Smrg XGCValues values; 222cdc920a0Smrg unsigned long valuemask; 223cdc920a0Smrg XFontStruct *fs; 22401e04c3fSmrg 225cdc920a0Smrg GLint swapbytes, lsbfirst, rowlength; 226cdc920a0Smrg GLint skiprows, skippixels, alignment; 227cdc920a0Smrg 228cdc920a0Smrg unsigned int max_width, max_height, max_bm_width, max_bm_height; 229cdc920a0Smrg GLubyte *bm; 230cdc920a0Smrg 231cdc920a0Smrg int i; 232cdc920a0Smrg 233cdc920a0Smrg dpy = CC->currentDpy; 2347ec681f3Smrg screen = CC->screen; 235af69d88dSmrg 236cdc920a0Smrg fs = XQueryFont(dpy, font); 237cdc920a0Smrg if (!fs) { 238cdc920a0Smrg __glXSetError(CC, GL_INVALID_VALUE); 239cdc920a0Smrg return; 240cdc920a0Smrg } 241cdc920a0Smrg 242cdc920a0Smrg /* Allocate a bitmap that can fit all characters. */ 243cdc920a0Smrg max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; 244cdc920a0Smrg max_height = fs->max_bounds.ascent + fs->max_bounds.descent; 245cdc920a0Smrg max_bm_width = (max_width + 7) / 8; 246cdc920a0Smrg max_bm_height = max_height; 247cdc920a0Smrg 248af69d88dSmrg bm = malloc((max_bm_width * max_bm_height) * sizeof(GLubyte)); 249cdc920a0Smrg if (!bm) { 250cdc920a0Smrg XFreeFontInfo(NULL, fs, 1); 251cdc920a0Smrg __glXSetError(CC, GL_OUT_OF_MEMORY); 252cdc920a0Smrg return; 253cdc920a0Smrg } 254cdc920a0Smrg 255cdc920a0Smrg#if 0 256cdc920a0Smrg /* get the page info */ 257cdc920a0Smrg pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; 258cdc920a0Smrg firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; 259cdc920a0Smrg lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; 260cdc920a0Smrg rows = fs->max_byte1 - fs->min_byte1 + 1; 261cdc920a0Smrg unsigned int first_char, last_char, pages, rows; 262cdc920a0Smrg#endif 263cdc920a0Smrg 264cdc920a0Smrg /* Save the current packing mode for bitmaps. */ 265cdc920a0Smrg glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); 266cdc920a0Smrg glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); 267cdc920a0Smrg glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); 268cdc920a0Smrg glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); 269cdc920a0Smrg glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); 270cdc920a0Smrg glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); 271cdc920a0Smrg 272cdc920a0Smrg /* Enforce a standard packing mode which is compatible with 273cdc920a0Smrg fill_bitmap() from above. This is actually the default mode, 274cdc920a0Smrg except for the (non)alignment. */ 275cdc920a0Smrg glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); 276cdc920a0Smrg glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); 277cdc920a0Smrg glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 278cdc920a0Smrg glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); 279cdc920a0Smrg glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); 280cdc920a0Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 281cdc920a0Smrg 2827ec681f3Smrg pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen), 10, 10, 1); 283cdc920a0Smrg values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); 284cdc920a0Smrg values.background = WhitePixel(dpy, DefaultScreen(dpy)); 285cdc920a0Smrg values.font = fs->fid; 286cdc920a0Smrg valuemask = GCForeground | GCBackground | GCFont; 287cdc920a0Smrg gc = XCreateGC(dpy, pixmap, valuemask, &values); 288cdc920a0Smrg XFreePixmap(dpy, pixmap); 289cdc920a0Smrg 290cdc920a0Smrg#ifdef DEBUG 291cdc920a0Smrg if (debug_xfonts) 292cdc920a0Smrg dump_font_struct(fs); 293cdc920a0Smrg#endif 294cdc920a0Smrg 295cdc920a0Smrg for (i = 0; i < count; i++) { 296cdc920a0Smrg unsigned int width, height, bm_width, bm_height; 297cdc920a0Smrg GLfloat x0, y0, dx, dy; 298cdc920a0Smrg XCharStruct *ch; 299cdc920a0Smrg int x, y; 300cdc920a0Smrg unsigned int c = first + i; 301cdc920a0Smrg int list = listbase + i; 302cdc920a0Smrg int valid; 303cdc920a0Smrg 304cdc920a0Smrg /* check on index validity and get the bounds */ 305cdc920a0Smrg ch = isvalid(fs, c); 306cdc920a0Smrg if (!ch) { 307cdc920a0Smrg ch = &fs->max_bounds; 308cdc920a0Smrg valid = 0; 309cdc920a0Smrg } 310cdc920a0Smrg else { 311cdc920a0Smrg valid = 1; 312cdc920a0Smrg } 313cdc920a0Smrg 314cdc920a0Smrg#ifdef DEBUG 315cdc920a0Smrg if (debug_xfonts) { 316cdc920a0Smrg char s[7]; 317cdc920a0Smrg sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); 318cdc920a0Smrg dump_char_struct(ch, s); 319cdc920a0Smrg } 320cdc920a0Smrg#endif 321cdc920a0Smrg 322cdc920a0Smrg /* glBitmap()' parameters: 323cdc920a0Smrg straight from the glXUseXFont(3) manpage. */ 324cdc920a0Smrg width = ch->rbearing - ch->lbearing; 325cdc920a0Smrg height = ch->ascent + ch->descent; 326cdc920a0Smrg x0 = -ch->lbearing; 327cdc920a0Smrg y0 = ch->descent - 1; 328cdc920a0Smrg dx = ch->width; 329cdc920a0Smrg dy = 0; 330cdc920a0Smrg 331cdc920a0Smrg /* X11's starting point. */ 332cdc920a0Smrg x = -ch->lbearing; 333cdc920a0Smrg y = ch->ascent; 334cdc920a0Smrg 335cdc920a0Smrg /* Round the width to a multiple of eight. We will use this also 336cdc920a0Smrg for the pixmap for capturing the X11 font. This is slightly 337cdc920a0Smrg inefficient, but it makes the OpenGL part real easy. */ 338cdc920a0Smrg bm_width = (width + 7) / 8; 339cdc920a0Smrg bm_height = height; 340cdc920a0Smrg 341cdc920a0Smrg glNewList(list, GL_COMPILE); 342cdc920a0Smrg if (valid && (bm_width > 0) && (bm_height > 0)) { 343cdc920a0Smrg 344cdc920a0Smrg memset(bm, '\0', bm_width * bm_height); 3457ec681f3Smrg fill_bitmap(dpy, screen, gc, bm_width, bm_height, x, y, c, bm); 346cdc920a0Smrg 347cdc920a0Smrg glBitmap(width, height, x0, y0, dx, dy, bm); 348cdc920a0Smrg#ifdef DEBUG 349cdc920a0Smrg if (debug_xfonts) { 350cdc920a0Smrg printf("width/height = %u/%u\n", width, height); 351cdc920a0Smrg printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height); 352cdc920a0Smrg dump_bitmap(bm_width, bm_height, bm); 353cdc920a0Smrg } 354cdc920a0Smrg#endif 355cdc920a0Smrg } 356cdc920a0Smrg else { 357cdc920a0Smrg glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); 358cdc920a0Smrg } 359cdc920a0Smrg glEndList(); 360cdc920a0Smrg } 361cdc920a0Smrg 362af69d88dSmrg free(bm); 363cdc920a0Smrg XFreeFontInfo(NULL, fs, 1); 364cdc920a0Smrg XFreeGC(dpy, gc); 365cdc920a0Smrg 366cdc920a0Smrg /* Restore saved packing modes. */ 367cdc920a0Smrg glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); 368cdc920a0Smrg glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); 369cdc920a0Smrg glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); 370cdc920a0Smrg glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); 371cdc920a0Smrg glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); 372cdc920a0Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); 373cdc920a0Smrg} 374cdc920a0Smrg 375cdc920a0Smrg#endif 376