home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / lib / glut / capturexfont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  9.5 KB  |  312 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994. */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. /* capturexfont.c connects to an X server and downloads a
  9.    bitmap font from which a C source file is generated,
  10.    encoding  the font for GLUT's use. Example usage:
  11.    capturexfont.c 9x15 glutBitmap9By15 > glut_9x15.c */
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <GL/gl.h>
  18. #include <X11/Xlib.h>
  19. #include <X11/Xutil.h>
  20.  
  21. #define MAX_GLYPHS_PER_GRAB 512  /* this is big enough for 2^9
  22.                                     glyph character sets */
  23.  
  24. static void
  25. outputChar(int num, int width, int height,
  26.   int xoff, int yoff, int advance, int data)
  27. {
  28.   printf("static BitmapCharRec ch%d = {", num);
  29.   printf("%d,", width);
  30.   printf("%d,", height);
  31.   printf("%d,", xoff);
  32.   printf("%d,", yoff);
  33.   printf("%d,", advance);
  34.   if (data) {
  35.     printf("ch%ddata", num);
  36.   } else {
  37.     printf("0");
  38.   }
  39.   printf("};\n\n");
  40. }
  41.  
  42. /* Can't just use isprint because it only works for the range
  43.    of ASCII characters (ie, TRUE for isascii) and capturexfont
  44.    might be run on 16-bit fonts. */
  45. #define PRINTABLE(ch)  (isascii(ch) ? isprint(ch) : 0)
  46.  
  47. void
  48. captureXFont(Display * dpy, Font font, char *xfont, char *name)
  49. {
  50.   int first, last, count;
  51.   int cnt, len;
  52.   Pixmap offscreen;
  53.   Window drawable;
  54.   XFontStruct *fontinfo;
  55.   XImage *image;
  56.   GC xgc;
  57.   XGCValues values;
  58.   int width, height;
  59.   int i, j, k;
  60.   XCharStruct *charinfo;
  61.   XChar2b character;
  62.   GLubyte *bitmapData;
  63.   int x, y;
  64.   int spanLength;
  65.   int charWidth, charHeight, maxSpanLength, pixwidth;
  66.   int grabList[MAX_GLYPHS_PER_GRAB];
  67.   int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
  68.   int numToGrab;
  69.   int rows, pages, byte1, byte2, index;
  70.  
  71.   drawable = RootWindow(dpy, DefaultScreen(dpy));
  72.  
  73.   fontinfo = XQueryFont(dpy, font);
  74.   pages = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
  75.   first = (fontinfo->min_byte1 << 8) + fontinfo->min_char_or_byte2;
  76.   last = (fontinfo->max_byte1 << 8) + fontinfo->max_char_or_byte2;
  77.   count = last - first + 1;
  78.  
  79.   width = fontinfo->max_bounds.rbearing -
  80.     fontinfo->min_bounds.lbearing;
  81.   height = fontinfo->max_bounds.ascent +
  82.     fontinfo->max_bounds.descent;
  83.   /* 16-bit fonts have more than one row; indexing into
  84.      per_char is trickier. */
  85.   rows = fontinfo->max_byte1 - fontinfo->min_byte1 + 1;
  86.  
  87.   maxSpanLength = (width + 7) / 8;
  88.   /* For portability reasons we don't use alloca for
  89.      bitmapData, but we could. */
  90.   bitmapData = malloc(height * maxSpanLength);
  91.   /* Be careful determining the width of the pixmap; the X
  92.      protocol allows pixmaps of width 2^16-1 (unsigned short
  93.      size) but drawing coordinates max out at 2^15-1 (signed
  94.      short size).  If the width is too large, we need to limit
  95.      the glyphs per grab. */
  96.   if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
  97.     glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
  98.   }
  99.   pixwidth = glyphsPerGrab * 8 * maxSpanLength;
  100.   offscreen = XCreatePixmap(dpy, drawable, pixwidth, height, 1);
  101.  
  102.   values.font = font;
  103.   values.background = 0;
  104.   values.foreground = 0;
  105.   xgc = XCreateGC(dpy, offscreen,
  106.     GCFont | GCBackground | GCForeground, &values);
  107.   XFillRectangle(dpy, offscreen, xgc, 0, 0,
  108.     8 * maxSpanLength * glyphsPerGrab, height);
  109.   XSetForeground(dpy, xgc, 1);
  110.  
  111.   numToGrab = 0;
  112.   if (fontinfo->per_char == NULL) {
  113.     charinfo = &(fontinfo->min_bounds);
  114.     charWidth = charinfo->rbearing - charinfo->lbearing;
  115.     charHeight = charinfo->ascent + charinfo->descent;
  116.     spanLength = (charWidth + 7) / 8;
  117.   }
  118.   printf("\n/* GENERATED FILE -- DO NOT MODIFY */\n\n");
  119.   printf("#include \"glutbitmap.h\"\n\n");
  120.   for (i = first; count; i++, count--) {
  121.     int undefined;
  122.     if (rows == 1) {
  123.       undefined = (fontinfo->min_char_or_byte2 > i ||
  124.         fontinfo->max_char_or_byte2 < i);
  125.     } else {
  126.       byte2 = i & 0xff;
  127.       byte1 = i >> 8;
  128.       undefined = (fontinfo->min_char_or_byte2 > byte2 ||
  129.         fontinfo->max_char_or_byte2 < byte2 ||
  130.         fontinfo->min_byte1 > byte1 ||
  131.         fontinfo->max_byte1 < byte1);
  132.  
  133.     }
  134.     if (undefined) {
  135.       goto PossiblyDoGrab;
  136.     }
  137.     if (fontinfo->per_char != NULL) {
  138.       if (rows == 1) {
  139.         index = i - fontinfo->min_char_or_byte2;
  140.       } else {
  141.         byte2 = i & 0xff;
  142.         byte1 = i >> 8;
  143.         index =
  144.           (byte1 - fontinfo->min_byte1) * pages +
  145.           (byte2 - fontinfo->min_char_or_byte2);
  146.       }
  147.       charinfo = &(fontinfo->per_char[index]);
  148.       charWidth = charinfo->rbearing - charinfo->lbearing;
  149.       charHeight = charinfo->ascent + charinfo->descent;
  150.       if (charWidth == 0 || charHeight == 0) {
  151.         if (charinfo->width != 0) {
  152.           /* Still must move raster pos even if empty character 
  153.  
  154.            */
  155.           outputChar(i, 0, 0, 0, 0, charinfo->width, 0);
  156.         }
  157.         goto PossiblyDoGrab;
  158.       }
  159.     }
  160.     grabList[numToGrab] = i;
  161.     character.byte2 = i & 255;
  162.     character.byte1 = i >> 8;
  163.  
  164.     /* XXX We could use XDrawImageString16 which would also
  165.        paint the backing rectangle but X server bugs in some
  166.        scalable font rasterizers makes it more effective to do
  167.        XFillRectangles to clear the pixmap and then
  168.        XDrawImage16 for the text.  */
  169.     XDrawString16(dpy, offscreen, xgc,
  170.       -charinfo->lbearing + 8 * maxSpanLength * numToGrab,
  171.       charinfo->ascent, &character, 1);
  172.  
  173.     numToGrab++;
  174.  
  175.   PossiblyDoGrab:
  176.  
  177.     if (numToGrab >= glyphsPerGrab || count == 1) {
  178.       image = XGetImage(dpy, offscreen,
  179.         0, 0, pixwidth, height, 1, XYPixmap);
  180.       for (j = numToGrab - 1; j >= 0; j--) {
  181.         if (fontinfo->per_char != NULL) {
  182.           byte2 = grabList[j] & 0xff;
  183.           byte1 = grabList[j] >> 8;
  184.           index =
  185.             (byte1 - fontinfo->min_byte1) * pages +
  186.             (byte2 - fontinfo->min_char_or_byte2);
  187.           charinfo = &(fontinfo->per_char[index]);
  188.           charWidth = charinfo->rbearing - charinfo->lbearing;
  189.           charHeight = charinfo->ascent + charinfo->descent;
  190.           spanLength = (charWidth + 7) / 8;
  191.         }
  192.         memset(bitmapData, 0, height * spanLength);
  193.         for (y = 0; y < charHeight; y++) {
  194.           for (x = 0; x < charWidth; x++) {
  195.             if (XGetPixel(image, j * maxSpanLength * 8 + x,
  196.                 charHeight - 1 - y)) {
  197.               /* Little endian machines (such as DEC Alpha)
  198.                  could  benefit from reversing the bit order
  199.                  here and changing the GL_UNPACK_LSB_FIRST
  200.                  parameter in glutBitmapCharacter to GL_TRUE. */
  201.               bitmapData[y * spanLength + x / 8] |=
  202.                 (1 << (7 - (x & 7)));
  203.             }
  204.           }
  205.         }
  206.         if (PRINTABLE(grabList[j])) {
  207.           printf("/* char: 0x%x '%c' */\n\n",
  208.             grabList[j], grabList[j]);
  209.         } else {
  210.           printf("/* char: 0x%x */\n\n", grabList[j]);
  211.         }
  212.         printf("static GLubyte ch%ddata[] = {\n", grabList[j]);
  213.         len = (charinfo->ascent + charinfo->descent) *
  214.           ((charinfo->rbearing - charinfo->lbearing + 7) / 8);
  215.         cnt = 0;
  216.         while (cnt < len) {
  217.           for (k = 0; k < 16 && cnt < len; k++, cnt++) {
  218.             printf("0x%x,", bitmapData[cnt]);
  219.           }
  220.           printf("\n");
  221.         }
  222.         printf("};\n\n");
  223.         outputChar(grabList[j], charWidth, charHeight,
  224.           -charinfo->lbearing, charinfo->descent,
  225.           charinfo->width, 1);
  226.       }
  227.       XDestroyImage(image);
  228.       numToGrab = 0;
  229.       if (count > 0) {
  230.         XSetForeground(dpy, xgc, 0);
  231.         XFillRectangle(dpy, offscreen, xgc, 0, 0,
  232.           8 * maxSpanLength * glyphsPerGrab, height);
  233.         XSetForeground(dpy, xgc, 1);
  234.       }
  235.     }
  236.   }
  237.   XFreeGC(dpy, xgc);
  238.   XFreePixmap(dpy, offscreen);
  239.   /* For portability reasons we don't use alloca for
  240.      bitmapData, but we could. */
  241.   free(bitmapData);
  242.  
  243.   printf("static BitmapCharPtr chars[] = {\n");
  244.   for (i = first; i <= last; i++) {
  245.     int undefined;
  246.     byte2 = i & 0xff;
  247.     byte1 = i >> 8;
  248.     undefined = (fontinfo->min_char_or_byte2 > byte2 ||
  249.       fontinfo->max_char_or_byte2 < byte2 ||
  250.       fontinfo->min_byte1 > byte1 ||
  251.       fontinfo->max_byte1 < byte1);
  252.     if (undefined) {
  253.       printf("0,\n");
  254.     } else {
  255.       if (fontinfo->per_char != NULL) {
  256.         if (rows == 1) {
  257.           index = i - fontinfo->min_char_or_byte2;
  258.         } else {
  259.           byte2 = i & 0xff;
  260.           byte1 = i >> 8;
  261.           index =
  262.             (byte1 - fontinfo->min_byte1) * pages +
  263.             (byte2 - fontinfo->min_char_or_byte2);
  264.         }
  265.         charinfo = &(fontinfo->per_char[index]);
  266.         charWidth = charinfo->rbearing - charinfo->lbearing;
  267.         charHeight = charinfo->ascent + charinfo->descent;
  268.         if (charWidth == 0 || charHeight == 0) {
  269.           if (charinfo->width == 0) {
  270.             printf("0,\n");
  271.             continue;
  272.           }
  273.         }
  274.       }
  275.       printf("&ch%d,\n", i);
  276.     }
  277.   }
  278.   printf("};\n\n");
  279.   printf("BitmapFontRec %s = {\n", name);
  280.   printf("\"%s\",\n", xfont);
  281.   printf("%d,\n", last - first + 1);
  282.   printf("%d,\n", first);
  283.   printf("chars\n");
  284.   printf("};\n\n");
  285.   XFreeFont(dpy, fontinfo);
  286. }
  287.  
  288. int
  289. main(int argc, char **argv)
  290. {
  291.   Display *dpy;
  292.   Font font;
  293.  
  294.   if (argc != 3) {
  295.     fprintf(stderr, "usage: bagxfont XFONT NAME\n");
  296.     exit(1);
  297.   }
  298.   dpy = XOpenDisplay(NULL);
  299.   if (dpy == NULL) {
  300.     fprintf(stderr, "bagxfont: could not open X display\n");
  301.     exit(1);
  302.   }
  303.   font = XLoadFont(dpy, argv[1]);
  304.   if (font == None) {
  305.     fprintf(stderr, "bagxfont: bad font\n");
  306.     exit(1);
  307.   }
  308.   captureXFont(dpy, font, argv[1], argv[2]);
  309.   XCloseDisplay(dpy);
  310.   return 0;
  311. }
  312.