Home

Dokumentation

Impressum

Dokumentation VDR
 

Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

genfontfile.c

Go to the documentation of this file.
00001 /* Copyright (c) Mark J. Kilgard, 1997. */
00002 
00003 /* This program is freely distributable without licensing fees  and is
00004    provided without guarantee or warrantee expressed or  implied. This
00005    program is -not- in the public domain. */
00006 
00007 /* X compile line: cc -o gentexfont gentexfont.c -lX11 */
00008 
00009 /* 2000-10-01: Stripped down the original code to get a simple bitmap C-code generator  */
00010 /*             for use with the VDR project (see http://www.cadsoft.de/people/kls/vdr)  */
00011 /*             Renamed the file 'genfontfile.c' since it no longer generates 'tex' data */
00012 /*             Klaus Schmidinger (kls@cadsoft.de)                                       */
00013 
00014 #include <stdlib.h>
00015 #include <stdio.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018 #include <X11/Xlib.h>
00019 #include <X11/Xutil.h>
00020 #include <math.h>
00021 
00022 typedef struct {
00023   unsigned short c;       /* Potentially support 16-bit glyphs. */
00024   unsigned char width;
00025   unsigned char height;
00026   signed char xoffset;
00027   signed char yoffset;
00028   signed char advance;
00029   char dummy;           /* Space holder for alignment reasons. */
00030   short x;
00031   short y;
00032 } TexGlyphInfo;
00033 
00034 typedef struct {
00035   short width;
00036   short height;
00037   short xoffset;
00038   short yoffset;
00039   short advance;
00040   unsigned char *bitmap;
00041 } PerGlyphInfo, *PerGlyphInfoPtr;
00042 
00043 typedef struct {
00044   int min_char;
00045   int max_char;
00046   int max_ascent;
00047   int max_descent;
00048   PerGlyphInfo glyph[1];
00049 } FontInfo, *FontInfoPtr;
00050 
00051 Display *dpy;
00052 FontInfoPtr fontinfo;
00053 
00054 /* #define REPORT_GLYPHS */
00055 #ifdef REPORT_GLYPHS
00056 #define DEBUG_GLYPH4(msg,a,b,c,d) printf(msg,a,b,c,d)
00057 #define DEBUG_GLYPH(msg) printf(msg)
00058 #else
00059 #define DEBUG_GLYPH4(msg,a,b,c,d) { /* nothing */ }
00060 #define DEBUG_GLYPH(msg) { /* nothing */ }
00061 #endif
00062 
00063 #define MAX_GLYPHS_PER_GRAB 512  /* this is big enough for 2^9 glyph
00064                                     character sets */
00065 
00066 FontInfoPtr
00067 SuckGlyphsFromServer(Display * dpy, Font font)
00068 {
00069   Pixmap offscreen;
00070   XFontStruct *fontinfo;
00071   XImage *image;
00072   GC xgc;
00073   XGCValues values;
00074   int numchars;
00075   int width, height, pixwidth;
00076   int i, j;
00077   XCharStruct *charinfo;
00078   XChar2b character;
00079   unsigned char *bitmapData;
00080   int x, y;
00081   int spanLength;
00082   int charWidth, charHeight, maxSpanLength;
00083   int grabList[MAX_GLYPHS_PER_GRAB];
00084   int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
00085   int numToGrab, thisglyph;
00086   FontInfoPtr myfontinfo;
00087 
00088   fontinfo = XQueryFont(dpy, font);
00089   if (!fontinfo)
00090     return NULL;
00091 
00092   numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
00093   if (numchars < 1)
00094     return NULL;
00095 
00096   myfontinfo = (FontInfoPtr) malloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerGlyphInfo));
00097   if (!myfontinfo)
00098     return NULL;
00099 
00100   myfontinfo->min_char = fontinfo->min_char_or_byte2;
00101   myfontinfo->max_char = fontinfo->max_char_or_byte2;
00102   myfontinfo->max_ascent = fontinfo->max_bounds.ascent;
00103   myfontinfo->max_descent = fontinfo->max_bounds.descent;
00104 
00105   width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing;
00106   height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent;
00107 
00108   maxSpanLength = (width + 7) / 8;
00109   /* Be careful determining the width of the pixmap; the X protocol allows
00110      pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
00111      max out at 2^15-1 (signed short size).  If the width is too large, we
00112      need to limit the glyphs per grab.  */
00113   if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
00114     glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
00115   }
00116   pixwidth = glyphsPerGrab * 8 * maxSpanLength;
00117   offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
00118     pixwidth, height, 1);
00119 
00120   values.font = font;
00121   values.background = 0;
00122   values.foreground = 0;
00123   xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values);
00124 
00125   XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
00126   XSetForeground(dpy, xgc, 1);
00127 
00128   numToGrab = 0;
00129   if (fontinfo->per_char == NULL) {
00130     charinfo = &(fontinfo->min_bounds);
00131     charWidth = charinfo->rbearing - charinfo->lbearing;
00132     charHeight = charinfo->ascent + charinfo->descent;
00133     spanLength = (charWidth + 7) / 8;
00134   }
00135   for (i = 0; i < numchars; i++) {
00136     if (fontinfo->per_char != NULL) {
00137       charinfo = &(fontinfo->per_char[i]);
00138       charWidth = charinfo->rbearing - charinfo->lbearing;
00139       charHeight = charinfo->ascent + charinfo->descent;
00140       if (charWidth == 0 || charHeight == 0) {
00141         /* Still must move raster pos even if empty character */
00142         myfontinfo->glyph[i].width = 0;
00143         myfontinfo->glyph[i].height = 0;
00144         myfontinfo->glyph[i].xoffset = 0;
00145         myfontinfo->glyph[i].yoffset = 0;
00146         myfontinfo->glyph[i].advance = charinfo->width;
00147         myfontinfo->glyph[i].bitmap = NULL;
00148         goto PossiblyDoGrab;
00149       }
00150     }
00151     grabList[numToGrab] = i;
00152 
00153     /* XXX is this right for large fonts? */
00154     character.byte2 = (i + fontinfo->min_char_or_byte2) & 255;
00155     character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8;
00156 
00157     /* XXX we could use XDrawImageString16 which would also paint the backing 
00158 
00159        rectangle but X server bugs in some scalable font rasterizers makes it 
00160 
00161        more effective to do XFillRectangles to clear the pixmap and
00162        XDrawImage16 for the text.  */
00163     XDrawString16(dpy, offscreen, xgc,
00164       -charinfo->lbearing + 8 * maxSpanLength * numToGrab,
00165       charinfo->ascent, &character, 1);
00166 
00167     numToGrab++;
00168 
00169   PossiblyDoGrab:
00170 
00171     if (numToGrab >= glyphsPerGrab || i == numchars - 1) {
00172       image = XGetImage(dpy, offscreen,
00173         0, 0, pixwidth, height, 1, XYPixmap);
00174       for (j = 0; j < numToGrab; j++) {
00175         thisglyph = grabList[j];
00176         if (fontinfo->per_char != NULL) {
00177           charinfo = &(fontinfo->per_char[thisglyph]);
00178           charWidth = charinfo->rbearing - charinfo->lbearing;
00179           charHeight = charinfo->ascent + charinfo->descent;
00180           spanLength = (charWidth + 7) / 8;
00181         }
00182         bitmapData = calloc(height * spanLength, sizeof(char));
00183         if (!bitmapData)
00184           goto FreeFontAndReturn;
00185         DEBUG_GLYPH4("index %d, glyph %d (%d by %d)\n",
00186           j, thisglyph + fontinfo->min_char_or_byte2, charWidth, charHeight);
00187         for (y = 0; y < charHeight; y++) {
00188           for (x = 0; x < charWidth; x++) {
00189             /* XXX The algorithm used to suck across the font ensures that
00190                each glyph begins on a byte boundary.  In theory this would
00191                make it convienent to copy the glyph into a byte oriented
00192                bitmap.  We actually use the XGetPixel function to extract
00193                each pixel from the image which is not that efficient.  We
00194                could either do tighter packing in the pixmap or more
00195                efficient extraction from the image.  Oh well.  */
00196             if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) {
00197               DEBUG_GLYPH("x");
00198               bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
00199             } else {
00200               DEBUG_GLYPH(" ");
00201             }
00202           }
00203           DEBUG_GLYPH("\n");
00204         }
00205         myfontinfo->glyph[thisglyph].width = charWidth;
00206         myfontinfo->glyph[thisglyph].height = charHeight;
00207         myfontinfo->glyph[thisglyph].xoffset = charinfo->lbearing;
00208         myfontinfo->glyph[thisglyph].yoffset = -charinfo->descent;
00209         myfontinfo->glyph[thisglyph].advance = charinfo->width;
00210         myfontinfo->glyph[thisglyph].bitmap = bitmapData;
00211       }
00212       XDestroyImage(image);
00213       numToGrab = 0;
00214       /* do we need to clear the offscreen pixmap to get more? */
00215       if (i < numchars - 1) {
00216         XSetForeground(dpy, xgc, 0);
00217         XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
00218         XSetForeground(dpy, xgc, 1);
00219       }
00220     }
00221   }
00222   XFreeGC(dpy, xgc);
00223   XFreePixmap(dpy, offscreen);
00224   return myfontinfo;
00225 
00226 FreeFontAndReturn:
00227   XDestroyImage(image);
00228   XFreeGC(dpy, xgc);
00229   XFreePixmap(dpy, offscreen);
00230   for (j = i - 1; j >= 0; j--) {
00231     if (myfontinfo->glyph[j].bitmap)
00232       free(myfontinfo->glyph[j].bitmap);
00233   }
00234   free(myfontinfo);
00235   return NULL;
00236 }
00237 
00238 void
00239 printGlyph(FontInfoPtr font, int c)
00240 {
00241   PerGlyphInfoPtr glyph;
00242   unsigned char *bitmapData;
00243   int width, height, spanLength;
00244   int x, y, l;
00245   char buf[1000], *b;
00246 
00247   if (c < font->min_char || c > font->max_char) {
00248     fprintf(stderr, "out of range glyph\n");
00249     exit(1);
00250   }
00251   glyph = &font->glyph[c - font->min_char];
00252   bitmapData = glyph->bitmap;
00253     width = glyph->width;
00254     spanLength = (width + 7) / 8;
00255     height = glyph->height;
00256 
00257     printf("  {             // %d\n", c);
00258     printf("     %d, %d,\n", glyph->advance, font->max_ascent + font->max_descent);
00259     for (y = 0; y < font->max_ascent - glyph->yoffset - height; y++) {
00260         printf("     0x%08X,  // ", 0);
00261         for (x = 0; x < glyph->xoffset + width || x < glyph->advance; x++)
00262             putchar('.');
00263         putchar('\n');
00264         }
00265     for (y = height; y-- > 0;) {
00266         l = 0;
00267         b = buf;
00268         for (x = 0; x < glyph->xoffset; x++)
00269             *b++ = '.';
00270         if (bitmapData) {
00271            for (x = 0; x < width; x++) {
00272                if (bitmapData[y * spanLength + x / 8] & (1 << (x & 7))) {
00273                   *b++ = '*';
00274                   l |= 1;
00275                   }
00276                else
00277                   *b++ = '.';
00278                l <<= 1;
00279                }
00280            for (x = 0; x < glyph->advance - width - glyph->xoffset; x++) {
00281                *b++ = '.';
00282                l <<= 1;
00283                }
00284            }
00285         *b = 0;
00286         printf("     0x%08X,  // %s\n", l, buf);
00287         }
00288     for (y = 0; y < font->max_descent + glyph->yoffset; y++) {
00289         printf("     0x%08X,  // ", 0);
00290         for (x = 0; x < glyph->xoffset + width || x < glyph->advance; x++)
00291             putchar('.');
00292         putchar('\n');
00293         }
00294     printf("  },\n");
00295 }
00296 
00297 void
00298 getMetric(FontInfoPtr font, int c, TexGlyphInfo * tgi)
00299 {
00300   PerGlyphInfoPtr glyph;
00301   unsigned char *bitmapData;
00302 
00303   tgi->c = c;
00304   if (c < font->min_char || c > font->max_char) {
00305     tgi->width = 0;
00306     tgi->height = 0;
00307     tgi->xoffset = 0;
00308     tgi->yoffset = 0;
00309     tgi->dummy = 0;
00310     tgi->advance = 0;
00311     return;
00312   }
00313   glyph = &font->glyph[c - font->min_char];
00314   bitmapData = glyph->bitmap;
00315   if (bitmapData) {
00316     tgi->width = glyph->width;
00317     tgi->height = glyph->height;
00318     tgi->xoffset = glyph->xoffset;
00319     tgi->yoffset = glyph->yoffset;
00320   } else {
00321     tgi->width = 0;
00322     tgi->height = 0;
00323     tgi->xoffset = 0;
00324     tgi->yoffset = 0;
00325   }
00326   tgi->dummy = 0;
00327   tgi->advance = glyph->advance;
00328 }
00329 
00330 int
00331 main(int argc, char *argv[])
00332 {
00333   int c;
00334   TexGlyphInfo tgi;
00335   int usageError = 0;
00336   char *varname, *fontname;
00337   XFontStruct *xfont;
00338   int i;
00339 
00340   if (argc == 3) {
00341      varname  = argv[1];
00342      fontname = argv[2];
00343      }
00344   else
00345      usageError = 1;
00346 
00347   if (usageError) {
00348     fprintf(stderr, "\n");
00349     fprintf(stderr, "usage: genfontfile variable_name X_font_name\n");
00350     fprintf(stderr, "\n");
00351     exit(1);
00352   }
00353 
00354   dpy = XOpenDisplay(NULL);
00355   if (!dpy) {
00356     fprintf(stderr, "could not open display\n");
00357     exit(1);
00358   }
00359   /* find an OpenGL-capable RGB visual with depth buffer */
00360   xfont = XLoadQueryFont(dpy, fontname);
00361   if (!xfont) {
00362     fprintf(stderr, "could not get load X font: %s\n", fontname);
00363     exit(1);
00364   }
00365   fontinfo = SuckGlyphsFromServer(dpy, xfont->fid);
00366   if (!fontinfo) {
00367     fprintf(stderr, "could not get font glyphs\n");
00368     exit(1);
00369   }
00370 
00371   printf("%s[][%d] = {\n", varname, fontinfo->max_ascent + fontinfo->max_descent + 2);
00372   for (c = 32; c < 256; c++) {
00373       getMetric(fontinfo, c, &tgi);
00374       printGlyph(fontinfo, c);
00375       }
00376   printf("  };\n");
00377   return 0;
00378 }

Generated on Wed Feb 5 23:30:09 2003 for VDR by doxygen1.3-rc2