capturexfont.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:11k
源码类别:

GIS编程

开发平台:

Visual C++

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