aboutsummaryrefslogtreecommitdiff
path: root/src/glut/glx/capturexfont.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/glut/glx/capturexfont.c')
-rw-r--r--src/glut/glx/capturexfont.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/src/glut/glx/capturexfont.c b/src/glut/glx/capturexfont.c
new file mode 100644
index 000000000..b99e79305
--- /dev/null
+++ b/src/glut/glx/capturexfont.c
@@ -0,0 +1,356 @@
+
+/* Copyright (c) Mark J. Kilgard, 1994. */
+
+/* This program is freely distributable without licensing fees
+ and is provided without guarantee or warrantee expressed or
+ implied. This program is -not- in the public domain. */
+
+/* capturexfont.c connects to an X server and downloads a
+ bitmap font from which a C source file is generated,
+ encoding the font for GLUT's use. Example usage:
+ capturexfont.c 9x15 glutBitmap9By15 > glut_9x15.c */
+
+#ifdef __VMS
+#include <GL/vms_x_fix.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <GL/gl.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#define MAX_GLYPHS_PER_GRAB 512 /* This is big enough for 2^9
+ glyph character sets */
+
+static void
+outputChar(int num, int width, int height,
+ int xoff, int yoff, int advance, int data)
+{
+ if (width == 0 || height == 0) {
+ printf("#ifdef _WIN32\n");
+ printf("/* XXX Work around Microsoft OpenGL 1.1 bug where glBitmap with\n");
+ printf(" a height or width of zero does not advance the raster position\n");
+ printf(" as specified by OpenGL. (Cosmo OpenGL does not have this bug.) */\n");
+ printf("static const GLubyte ch%ddata[] = { 0x0 };\n", num);
+ printf("static const BitmapCharRec ch%d = {", num);
+ printf("%d,", 0);
+ printf("%d,", 0);
+ printf("%d,", xoff);
+ printf("%d,", yoff);
+ printf("%d,", advance);
+ printf("ch%ddata", num);
+ printf("};\n");
+ printf("#else\n");
+ }
+ printf("static const BitmapCharRec ch%d = {", num);
+ printf("%d,", width);
+ printf("%d,", height);
+ printf("%d,", xoff);
+ printf("%d,", yoff);
+ printf("%d,", advance);
+ if (data) {
+ printf("ch%ddata", num);
+ } else {
+ printf("0");
+ }
+ printf("};\n");
+ if (width == 0 || height == 0) {
+ printf("#endif\n");
+ }
+ printf("\n");
+}
+
+/* Can't just use isprint because it only works for the range
+ of ASCII characters (ie, TRUE for isascii) and capturexfont
+ might be run on 16-bit fonts. */
+#define PRINTABLE(ch) (isascii(ch) ? isprint(ch) : 0)
+
+void
+captureXFont(Display * dpy, Font font, char *xfont, char *name)
+{
+ int first, last, count;
+ int cnt, len;
+ Pixmap offscreen;
+ Window drawable;
+ XFontStruct *fontinfo;
+ XImage *image;
+ GC xgc;
+ XGCValues values;
+ int width, height;
+ int i, j, k;
+ XCharStruct *charinfo;
+ XChar2b character;
+ GLubyte *bitmapData;
+ int x, y;
+ int spanLength;
+ int charWidth, charHeight, maxSpanLength, pixwidth;
+ int grabList[MAX_GLYPHS_PER_GRAB];
+ int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
+ int numToGrab;
+ int rows, pages, byte1, byte2, index;
+ int nullBitmap;
+
+ drawable = RootWindow(dpy, DefaultScreen(dpy));
+
+ fontinfo = XQueryFont(dpy, font);
+ pages = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
+ first = (fontinfo->min_byte1 << 8) + fontinfo->min_char_or_byte2;
+ last = (fontinfo->max_byte1 << 8) + fontinfo->max_char_or_byte2;
+ count = last - first + 1;
+
+ width = fontinfo->max_bounds.rbearing -
+ fontinfo->min_bounds.lbearing;
+ height = fontinfo->max_bounds.ascent +
+ fontinfo->max_bounds.descent;
+ /* 16-bit fonts have more than one row; indexing into
+ per_char is trickier. */
+ rows = fontinfo->max_byte1 - fontinfo->min_byte1 + 1;
+
+ maxSpanLength = (width + 7) / 8;
+ /* For portability reasons we don't use alloca for
+ bitmapData, but we could. */
+ bitmapData = malloc(height * maxSpanLength);
+ /* Be careful determining the width of the pixmap; the X
+ protocol allows pixmaps of width 2^16-1 (unsigned short
+ size) but drawing coordinates max out at 2^15-1 (signed
+ short size). If the width is too large, we need to limit
+ the glyphs per grab. */
+ if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
+ glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
+ }
+ pixwidth = glyphsPerGrab * 8 * maxSpanLength;
+ offscreen = XCreatePixmap(dpy, drawable, pixwidth, height, 1);
+
+ values.font = font;
+ values.background = 0;
+ values.foreground = 0;
+ xgc = XCreateGC(dpy, offscreen,
+ GCFont | GCBackground | GCForeground, &values);
+ XFillRectangle(dpy, offscreen, xgc, 0, 0,
+ 8 * maxSpanLength * glyphsPerGrab, height);
+ XSetForeground(dpy, xgc, 1);
+
+ numToGrab = 0;
+ if (fontinfo->per_char == NULL) {
+ charinfo = &(fontinfo->min_bounds);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ spanLength = (charWidth + 7) / 8;
+ }
+ printf("\n/* GENERATED FILE -- DO NOT MODIFY */\n\n");
+ printf("#include \"glutbitmap.h\"\n\n");
+ for (i = first; count; i++, count--) {
+ int undefined;
+ if (rows == 1) {
+ undefined = (fontinfo->min_char_or_byte2 > i ||
+ fontinfo->max_char_or_byte2 < i);
+ } else {
+ byte2 = i & 0xff;
+ byte1 = i >> 8;
+ undefined = (fontinfo->min_char_or_byte2 > byte2 ||
+ fontinfo->max_char_or_byte2 < byte2 ||
+ fontinfo->min_byte1 > byte1 ||
+ fontinfo->max_byte1 < byte1);
+
+ }
+ if (undefined) {
+ goto PossiblyDoGrab;
+ }
+ if (fontinfo->per_char != NULL) {
+ if (rows == 1) {
+ index = i - fontinfo->min_char_or_byte2;
+ } else {
+ byte2 = i & 0xff;
+ byte1 = i >> 8;
+ index =
+ (byte1 - fontinfo->min_byte1) * pages +
+ (byte2 - fontinfo->min_char_or_byte2);
+ }
+ charinfo = &(fontinfo->per_char[index]);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ if (charWidth == 0 || charHeight == 0) {
+ if (charinfo->width != 0) {
+ /* Still must move raster pos even if empty character
+
+ */
+ outputChar(i, 0, 0, 0, 0, charinfo->width, 0);
+ }
+ goto PossiblyDoGrab;
+ }
+ }
+ grabList[numToGrab] = i;
+ character.byte2 = i & 255;
+ character.byte1 = i >> 8;
+
+ /* XXX We could use XDrawImageString16 which would also
+ paint the backing rectangle but X server bugs in some
+ scalable font rasterizers makes it more effective to do
+ XFillRectangles to clear the pixmap and then
+ XDrawImage16 for the text. */
+ XDrawString16(dpy, offscreen, xgc,
+ -charinfo->lbearing + 8 * maxSpanLength * numToGrab,
+ charinfo->ascent, &character, 1);
+
+ numToGrab++;
+
+ PossiblyDoGrab:
+
+ if (numToGrab >= glyphsPerGrab || count == 1) {
+ image = XGetImage(dpy, offscreen,
+ 0, 0, pixwidth, height, 1, XYPixmap);
+ for (j = numToGrab - 1; j >= 0; j--) {
+ if (fontinfo->per_char != NULL) {
+ byte2 = grabList[j] & 0xff;
+ byte1 = grabList[j] >> 8;
+ index =
+ (byte1 - fontinfo->min_byte1) * pages +
+ (byte2 - fontinfo->min_char_or_byte2);
+ charinfo = &(fontinfo->per_char[index]);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ spanLength = (charWidth + 7) / 8;
+ }
+ memset(bitmapData, 0, height * spanLength);
+ for (y = 0; y < charHeight; y++) {
+ for (x = 0; x < charWidth; x++) {
+ if (XGetPixel(image, j * maxSpanLength * 8 + x,
+ charHeight - 1 - y)) {
+ /* Little endian machines (such as DEC Alpha)
+ could benefit from reversing the bit order
+ here and changing the GL_UNPACK_LSB_FIRST
+ parameter in glutBitmapCharacter to GL_TRUE. */
+ bitmapData[y * spanLength + x / 8] |=
+ (1 << (7 - (x & 7)));
+ }
+ }
+ }
+ if (PRINTABLE(grabList[j])) {
+ printf("/* char: 0x%x '%c' */\n\n",
+ grabList[j], grabList[j]);
+ } else {
+ printf("/* char: 0x%x */\n\n", grabList[j]);
+ }
+
+ /* Determine if the bitmap is null. */
+ nullBitmap = 1;
+ len = (charinfo->ascent + charinfo->descent) *
+ ((charinfo->rbearing - charinfo->lbearing + 7) / 8);
+ cnt = 0;
+ while (cnt < len) {
+ for (k = 0; k < 16 && cnt < len; k++, cnt++) {
+ if (bitmapData[cnt] != 0) {
+ nullBitmap = 0;
+ }
+ }
+ }
+
+ if (!nullBitmap) {
+ printf("static const GLubyte ch%ddata[] = {\n", grabList[j]);
+ len = (charinfo->ascent + charinfo->descent) *
+ ((charinfo->rbearing - charinfo->lbearing + 7) / 8);
+ cnt = 0;
+ while (cnt < len) {
+ for (k = 0; k < 16 && cnt < len; k++, cnt++) {
+ printf("0x%x,", bitmapData[cnt]);
+ }
+ printf("\n");
+ }
+ printf("};\n\n");
+ } else {
+ charWidth = 0;
+ charHeight = 0;
+ }
+
+ outputChar(grabList[j], charWidth, charHeight,
+ -charinfo->lbearing, charinfo->descent,
+ charinfo->width, !nullBitmap);
+ }
+ XDestroyImage(image);
+ numToGrab = 0;
+ if (count > 0) {
+ XSetForeground(dpy, xgc, 0);
+ XFillRectangle(dpy, offscreen, xgc, 0, 0,
+ 8 * maxSpanLength * glyphsPerGrab, height);
+ XSetForeground(dpy, xgc, 1);
+ }
+ }
+ }
+ XFreeGC(dpy, xgc);
+ XFreePixmap(dpy, offscreen);
+ /* For portability reasons we don't use alloca for
+ bitmapData, but we could. */
+ free(bitmapData);
+
+ printf("static const BitmapCharRec * const chars[] = {\n");
+ for (i = first; i <= last; i++) {
+ int undefined;
+ byte2 = i & 0xff;
+ byte1 = i >> 8;
+ undefined = (fontinfo->min_char_or_byte2 > byte2 ||
+ fontinfo->max_char_or_byte2 < byte2 ||
+ fontinfo->min_byte1 > byte1 ||
+ fontinfo->max_byte1 < byte1);
+ if (undefined) {
+ printf("0,\n");
+ } else {
+ if (fontinfo->per_char != NULL) {
+ if (rows == 1) {
+ index = i - fontinfo->min_char_or_byte2;
+ } else {
+ byte2 = i & 0xff;
+ byte1 = i >> 8;
+ index =
+ (byte1 - fontinfo->min_byte1) * pages +
+ (byte2 - fontinfo->min_char_or_byte2);
+ }
+ charinfo = &(fontinfo->per_char[index]);
+ charWidth = charinfo->rbearing - charinfo->lbearing;
+ charHeight = charinfo->ascent + charinfo->descent;
+ if (charWidth == 0 || charHeight == 0) {
+ if (charinfo->width == 0) {
+ printf("0,\n");
+ continue;
+ }
+ }
+ }
+ printf("&ch%d,\n", i);
+ }
+ }
+ printf("};\n\n");
+ printf("const BitmapFontRec %s = {\n", name);
+ printf("\"%s\",\n", xfont);
+ printf("%d,\n", last - first + 1);
+ printf("%d,\n", first);
+ printf("chars\n");
+ printf("};\n\n");
+ XFreeFont(dpy, fontinfo);
+}
+
+int
+main(int argc, char **argv)
+{
+ Display *dpy;
+ Font font;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: capturexfont XFONT NAME\n");
+ exit(1);
+ }
+ dpy = XOpenDisplay(NULL);
+ if (dpy == NULL) {
+ fprintf(stderr, "capturexfont: could not open X display\n");
+ exit(1);
+ }
+ font = XLoadFont(dpy, argv[1]);
+ if (font == None) {
+ fprintf(stderr, "capturexfont: bad font\n");
+ exit(1);
+ }
+ captureXFont(dpy, font, argv[1], argv[2]);
+ XCloseDisplay(dpy);
+ return 0;
+}