/* * xtotroff * * convert X font metrics into troff font metrics */ #include #include #include #include #include #include #include #include "XFontName.h" #include "DviChar.h" #ifdef X_NOT_STDC_ENV char *malloc(); #else #include #endif /* XFontName.c */ extern Bool XParseFontName(); extern Bool XFormatFontName(); #define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width) #define charHeight(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent) #define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent) #define charLBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing) #define charRBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing) Display *dpy; int groff_flag = 0; unsigned resolution = 75; unsigned point_size = 10; int charExists (fi, c) XFontStruct *fi; int c; { XCharStruct *p; if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2) return 0; p = fi->per_char + (c - fi->min_char_or_byte2); return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0 || p->ascent != 0 || p->descent != 0 || p->attributes != 0); } /* Canonicalize the font name by replacing scalable parts by *s. */ static int CanonicalizeFontName (font_name, canon_font_name) char *font_name, *canon_font_name; { unsigned int attributes; XFontName parsed; if (!XParseFontName(font_name, &parsed, &attributes)) { fprintf (stderr, "not a standard name: %s\n", font_name); return 0; } attributes &= ~(FontNamePixelSize|FontNameAverageWidth |FontNamePointSize |FontNameResolutionX|FontNameResolutionY); XFormatFontName(&parsed, attributes, canon_font_name); return 1; } static int FontNamesAmbiguous(font_name, names, count) char *font_name; char **names; int count; { char name1[2048], name2[2048]; int i; if (count == 1) return 0; for (i = 0; i < count; i++) { if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) { fprintf(stderr, "bad font name: %s\n", names[i]); return 1; } if (i > 0 && strcmp(name1, name2) != 0) { fprintf(stderr, "ambiguous font name: %s\n", font_name); fprintf(stderr, " matches %s\n", names[0]); fprintf(stderr, " and %s\n", names[i]); return 1; } } return 0; } static int MapFont (font_name, troff_name) char *font_name; char *troff_name; { XFontStruct *fi; int count; char **names; FILE *out; int c; unsigned int attributes; XFontName parsed; int j, k; DviCharNameMap *char_map; char encoding[256]; char *s; int wid; char name_string[2048]; if (!XParseFontName(font_name, &parsed, &attributes)) { fprintf (stderr, "not a standard name: %s\n", font_name); return 0; } attributes &= ~(FontNamePixelSize|FontNameAverageWidth); attributes |= FontNameResolutionX; attributes |= FontNameResolutionY; attributes |= FontNamePointSize; parsed.ResolutionX = resolution; parsed.ResolutionY = resolution; parsed.PointSize = point_size*10; XFormatFontName(&parsed, attributes, name_string); names = XListFonts (dpy, name_string, 100000, &count); if (count < 1) { fprintf (stderr, "bad font name: %s\n", font_name); return 0; } if (FontNamesAmbiguous(font_name, names, count)) return 0; XParseFontName(names[0], &parsed, &attributes); sprintf (encoding, "%s-%s", parsed.CharSetRegistry, parsed.CharSetEncoding); for (s = encoding; *s; s++) if (isupper (*s)) *s = tolower (*s); char_map = DviFindMap (encoding); if (!char_map) { fprintf (stderr, "not a standard encoding: %s\n", encoding); return 0; } fi = XLoadQueryFont (dpy, names[0]); if (!fi) { fprintf (stderr, "font does not exist: %s\n", names[0]); return 0; } printf ("%s -> %s\n", names[0], troff_name); { /* Avoid race while opening file */ int fd; (void) unlink (troff_name); fd = open (troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600); out = fdopen (fd, "w"); } if (!out) { perror (troff_name); return 0; } fprintf (out, "name %s\n", troff_name); if (!strcmp (char_map->encoding, "adobe-fontspecific")) fprintf (out, "special\n"); if (charExists (fi, ' ')) { int w = charWidth (fi, ' '); if (w > 0) fprintf (out, "spacewidth %d\n", w); } fprintf (out, "charset\n"); for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) { char *name = DviCharName (char_map,c,0); if (charExists (fi, c) && (groff_flag || name)) { wid = charWidth (fi, c); fprintf (out, "%s\t%d", name ? name : "---", wid); if (groff_flag) { int param[5]; param[0] = charHeight (fi, c); param[1] = charDepth (fi, c); param[2] = 0 /* charRBearing (fi, c) - wid */; param[3] = 0 /* charLBearing (fi, c) */; param[4] = 0; /* XXX */ for (j = 0; j < 5; j++) if (param[j] < 0) param[j] = 0; for (j = 4; j >= 0; j--) if (param[j] != 0) break; for (k = 0; k <= j; k++) fprintf (out, ",%d", param[k]); } fprintf (out, "\t0\t0%o\n", c); if (name) { for (k = 1; DviCharName(char_map,c,k); k++) { fprintf (out, "%s\t\"\n", DviCharName (char_map,c,k)); } } } } XUnloadFont (dpy, fi->fid); fclose (out); return 1; } static void usage(prog) char *prog; { fprintf (stderr, "usage: %s [-g] [-r resolution] [-s pointsize] FontMap\n", prog); exit (1); } /* For use by DviChar.c */ char *xmalloc(n) int n; { char *p = malloc(n); if (!p) { fprintf(stderr, "Out of memory\n"); exit(1); } return p; } int main (argc, argv) char **argv; { char troff_name[1024]; char font_name[1024]; char line[1024]; char *a, *b, c; int position; FILE *map; int opt; extern int optind; extern char *optarg; while ((opt = getopt(argc, argv, "gr:s:")) != EOF) { switch (opt) { case 'g': groff_flag = 1; break; case 'r': sscanf(optarg, "%u", &resolution); break; case 's': sscanf(optarg, "%u", &point_size); break; default: usage(argv[0]); } } if (argc - optind != 1) usage(argv[0]); dpy = XOpenDisplay (0); if (!dpy) { fprintf (stderr, "Can't connect to the X server.\n"); fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n"); exit (1); } position = 1; map = fopen (argv[optind], "r"); if (map == NULL) { perror (argv[optind]); exit (1); } while (fgets (line, sizeof (line), map)) { for (a=line,b=troff_name; *a; a++,b++) { c = (*b = *a); if (c == ' ' || c == '\t') break; } *b = '\0'; while (*a && (*a == ' ' || *a == '\t')) ++a; for (b=font_name; *a; a++,b++) if ((*b = *a) == '\n') break; *b = '\0'; if (!MapFont (font_name, troff_name)) exit (1); ++position; } exit (0); } /* Local Variables: c-indent-level: 8 c-continued-statement-offset: 8 c-brace-offset: -8 c-argdecl-indent: 8 c-label-offset: -8 c-tab-always-indent: nil End: */