~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/glut/glx/capturexfont.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

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