xfonts.c

Go to the documentation of this file.
00001 
00002 /*
00003  * Mesa 3-D graphics library
00004  * Version:  3.5
00005  *
00006  * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this software and associated documentation files (the "Software"),
00010  * to deal in the Software without restriction, including without limitation
00011  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00012  * and/or sell copies of the Software, and to permit persons to whom the
00013  * Software is furnished to do so, subject to the following conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be included
00016  * in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00021  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00022  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00023  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00024  */
00025 
00026 
00027 /* xfonts.c -- glXUseXFont() for Mesa written by
00028  * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
00029  */
00030 
00031 #ifdef __VMS
00032 #include <GL/vms_x_fix.h>
00033 #endif
00034 
00035 #include "glxheader.h"
00036 #include "context.h"
00037 #include "imports.h"
00038 #include "xfonts.h"
00039 
00040 
00041 /* Some debugging info.  */
00042 
00043 #ifdef DEBUG
00044 #undef _R
00045 #undef _G
00046 #undef _B
00047 #include <ctype.h>
00048 
00049 int debug_xfonts = 0;
00050 
00051 static void
00052 dump_char_struct(XCharStruct * ch, char *prefix)
00053 {
00054    printf("%slbearing = %d, rbearing = %d, width = %d\n",
00055           prefix, ch->lbearing, ch->rbearing, ch->width);
00056    printf("%sascent = %d, descent = %d, attributes = %u\n",
00057           prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
00058 }
00059 
00060 static void
00061 dump_font_struct(XFontStruct * font)
00062 {
00063    printf("ascent = %d, descent = %d\n", font->ascent, font->descent);
00064    printf("char_or_byte2 = (%u,%u)\n",
00065           font->min_char_or_byte2, font->max_char_or_byte2);
00066    printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
00067    printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False");
00068    printf("default_char = %c (\\%03o)\n",
00069           (char) (isprint(font->default_char) ? font->default_char : ' '),
00070           font->default_char);
00071    dump_char_struct(&font->min_bounds, "min> ");
00072    dump_char_struct(&font->max_bounds, "max> ");
00073 #if 0
00074    for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) {
00075       char prefix[8];
00076       sprintf(prefix, "%d> ", c);
00077       dump_char_struct(&font->per_char[c], prefix);
00078    }
00079 #endif
00080 }
00081 
00082 static void
00083 dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap)
00084 {
00085    unsigned int x, y;
00086 
00087    printf("    ");
00088    for (x = 0; x < 8 * width; x++)
00089       printf("%o", 7 - (x % 8));
00090    putchar('\n');
00091    for (y = 0; y < height; y++) {
00092       printf("%3o:", y);
00093       for (x = 0; x < 8 * width; x++)
00094          putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x %
00095                                                                          8))))
00096                  ? '*' : '.');
00097       printf("   ");
00098       for (x = 0; x < width; x++)
00099          printf("0x%02x, ", bitmap[width * (height - y - 1) + x]);
00100       putchar('\n');
00101    }
00102 }
00103 #endif /* DEBUG */
00104 
00105 
00106 /* Implementation.  */
00107 
00108 /* Fill a BITMAP with a character C from thew current font
00109    in the graphics context GC.  WIDTH is the width in bytes
00110    and HEIGHT is the height in bits.
00111 
00112    Note that the generated bitmaps must be used with
00113 
00114         glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
00115         glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
00116         glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
00117         glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
00118         glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
00119         glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
00120 
00121    Possible optimizations:
00122 
00123      * use only one reusable pixmap with the maximum dimensions.
00124      * draw the entire font into a single pixmap (careful with
00125        proportional fonts!).
00126 */
00127 
00128 
00129 /*
00130  * Generate OpenGL-compatible bitmap.
00131  */
00132 static void
00133 fill_bitmap(Display * dpy, Window win, GC gc,
00134             unsigned int width, unsigned int height,
00135             int x0, int y0, unsigned int c, GLubyte * bitmap)
00136 {
00137    XImage *image;
00138    unsigned int x, y;
00139    Pixmap pixmap;
00140    XChar2b char2b;
00141 
00142    pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1);
00143    XSetForeground(dpy, gc, 0);
00144    XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height);
00145    XSetForeground(dpy, gc, 1);
00146 
00147    char2b.byte1 = (c >> 8) & 0xff;
00148    char2b.byte2 = (c & 0xff);
00149 
00150    XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1);
00151 
00152    image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap);
00153    if (image) {
00154       /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
00155       for (y = 0; y < height; y++)
00156          for (x = 0; x < 8 * width; x++)
00157             if (XGetPixel(image, x, y))
00158                bitmap[width * (height - y - 1) + x / 8] |=
00159                   (1 << (7 - (x % 8)));
00160       XDestroyImage(image);
00161    }
00162 
00163    XFreePixmap(dpy, pixmap);
00164 }
00165 
00166 /*
00167  * determine if a given glyph is valid and return the
00168  * corresponding XCharStruct.
00169  */
00170 static XCharStruct *
00171 isvalid(XFontStruct * fs, unsigned int which)
00172 {
00173    unsigned int rows, pages;
00174    unsigned int byte1 = 0, byte2 = 0;
00175    int i, valid = 1;
00176 
00177    rows = fs->max_byte1 - fs->min_byte1 + 1;
00178    pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
00179 
00180    if (rows == 1) {
00181       /* "linear" fonts */
00182       if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which))
00183          valid = 0;
00184    }
00185    else {
00186       /* "matrix" fonts */
00187       byte2 = which & 0xff;
00188       byte1 = which >> 8;
00189       if ((fs->min_char_or_byte2 > byte2) ||
00190           (fs->max_char_or_byte2 < byte2) ||
00191           (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1))
00192          valid = 0;
00193    }
00194 
00195    if (valid) {
00196       if (fs->per_char) {
00197          if (rows == 1) {
00198             /* "linear" fonts */
00199             return (fs->per_char + (which - fs->min_char_or_byte2));
00200          }
00201          else {
00202             /* "matrix" fonts */
00203             i = ((byte1 - fs->min_byte1) * pages) +
00204                (byte2 - fs->min_char_or_byte2);
00205             return (fs->per_char + i);
00206          }
00207       }
00208       else {
00209          return (&fs->min_bounds);
00210       }
00211    }
00212    return (NULL);
00213 }
00214 
00215 
00216 void
00217 Fake_glXUseXFont(Font font, int first, int count, int listbase)
00218 {
00219    Display *dpy;
00220    Window win;
00221    Pixmap pixmap;
00222    GC gc;
00223    XGCValues values;
00224    unsigned long valuemask;
00225    XFontStruct *fs;
00226    GLint swapbytes, lsbfirst, rowlength;
00227    GLint skiprows, skippixels, alignment;
00228    unsigned int max_width, max_height, max_bm_width, max_bm_height;
00229    GLubyte *bm;
00230    int i;
00231 
00232    dpy = glXGetCurrentDisplay();
00233    if (!dpy)
00234       return;                   /* I guess glXMakeCurrent wasn't called */
00235    win = RootWindow(dpy, DefaultScreen(dpy));
00236 
00237    fs = XQueryFont(dpy, font);
00238    if (!fs) {
00239       _mesa_error(NULL, GL_INVALID_VALUE,
00240                   "Couldn't get font structure information");
00241       return;
00242    }
00243 
00244    /* Allocate a bitmap that can fit all characters.  */
00245    max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
00246    max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
00247    max_bm_width = (max_width + 7) / 8;
00248    max_bm_height = max_height;
00249 
00250    bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte));
00251    if (!bm) {
00252       XFreeFontInfo(NULL, fs, 1);
00253       _mesa_error(NULL, GL_OUT_OF_MEMORY,
00254                   "Couldn't allocate bitmap in glXUseXFont()");
00255       return;
00256    }
00257 
00258 #if 0
00259    /* get the page info */
00260    pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
00261    firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
00262    lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
00263    rows = fs->max_byte1 - fs->min_byte1 + 1;
00264    unsigned int first_char, last_char, pages, rows;
00265 #endif
00266 
00267    /* Save the current packing mode for bitmaps.  */
00268    glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes);
00269    glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst);
00270    glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength);
00271    glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows);
00272    glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels);
00273    glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
00274 
00275    /* Enforce a standard packing mode which is compatible with
00276       fill_bitmap() from above.  This is actually the default mode,
00277       except for the (non)alignment.  */
00278    glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
00279    glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
00280    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00281    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
00282    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00283    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00284 
00285    pixmap = XCreatePixmap(dpy, win, 10, 10, 1);
00286    values.foreground = BlackPixel(dpy, DefaultScreen(dpy));
00287    values.background = WhitePixel(dpy, DefaultScreen(dpy));
00288    values.font = fs->fid;
00289    valuemask = GCForeground | GCBackground | GCFont;
00290    gc = XCreateGC(dpy, pixmap, valuemask, &values);
00291    XFreePixmap(dpy, pixmap);
00292 
00293 #ifdef DEBUG
00294    if (debug_xfonts)
00295       dump_font_struct(fs);
00296 #endif
00297 
00298    for (i = 0; i < count; i++) {
00299       unsigned int width, height, bm_width, bm_height;
00300       GLfloat x0, y0, dx, dy;
00301       XCharStruct *ch;
00302       int x, y;
00303       unsigned int c = first + i;
00304       int list = listbase + i;
00305       int valid;
00306 
00307       /* check on index validity and get the bounds */
00308       ch = isvalid(fs, c);
00309       if (!ch) {
00310          ch = &fs->max_bounds;
00311          valid = 0;
00312       }
00313       else {
00314          valid = 1;
00315       }
00316 
00317 #ifdef DEBUG
00318       if (debug_xfonts) {
00319          char s[7];
00320          sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c);
00321          dump_char_struct(ch, s);
00322       }
00323 #endif
00324 
00325       /* glBitmap()' parameters:
00326          straight from the glXUseXFont(3) manpage.  */
00327       width = ch->rbearing - ch->lbearing;
00328       height = ch->ascent + ch->descent;
00329       x0 = -ch->lbearing;
00330       y0 = ch->descent - 0;     /* XXX used to subtract 1 here */
00331       /* but that caused a conformace failure */
00332       dx = ch->width;
00333       dy = 0;
00334 
00335       /* X11's starting point.  */
00336       x = -ch->lbearing;
00337       y = ch->ascent;
00338 
00339       /* Round the width to a multiple of eight.  We will use this also
00340          for the pixmap for capturing the X11 font.  This is slightly
00341          inefficient, but it makes the OpenGL part real easy.  */
00342       bm_width = (width + 7) / 8;
00343       bm_height = height;
00344 
00345       glNewList(list, GL_COMPILE);
00346       if (valid && (bm_width > 0) && (bm_height > 0)) {
00347 
00348          MEMSET(bm, '\0', bm_width * bm_height);
00349          fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm);
00350 
00351          glBitmap(width, height, x0, y0, dx, dy, bm);
00352 #ifdef DEBUG
00353          if (debug_xfonts) {
00354             printf("width/height = %u/%u\n", width, height);
00355             printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height);
00356             dump_bitmap(bm_width, bm_height, bm);
00357          }
00358 #endif
00359       }
00360       else {
00361          glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL);
00362       }
00363       glEndList();
00364    }
00365 
00366    FREE(bm);
00367    XFreeFontInfo(NULL, fs, 1);
00368    XFreeGC(dpy, gc);
00369 
00370    /* Restore saved packing modes.  */
00371    glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
00372    glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
00373    glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
00374    glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
00375    glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
00376    glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
00377 }

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4