4 * convert X font metrics into troff font metrics
20 #define __GETOPT_PREFIX groff_
23 #include "XFontName.h"
26 #define charWidth(fi,c) \
27 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
28 #define charHeight(fi,c) \
29 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
30 #define charDepth(fi,c) \
31 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
32 #define charLBearing(fi,c) \
33 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
34 #define charRBearing(fi,c) \
35 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
37 extern const char *Version_string;
38 static char *program_name;
41 unsigned resolution = 75;
42 unsigned point_size = 10;
44 int charExists(XFontStruct * fi, int c)
48 /* `c' is always >= 0 */
49 if ((unsigned int) c < fi->min_char_or_byte2
50 || (unsigned int) c > fi->max_char_or_byte2)
52 p = fi->per_char + (c - fi->min_char_or_byte2);
53 return p->lbearing != 0 || p->rbearing != 0 || p->width != 0
54 || p->ascent != 0 || p->descent != 0 || p->attributes != 0;
57 /* Canonicalize the font name by replacing scalable parts by *s. */
59 static int CanonicalizeFontName(char *font_name, char *canon_font_name)
61 unsigned int attributes;
64 if (!XParseFontName(font_name, &parsed, &attributes)) {
65 fprintf(stderr, "not a standard name: %s\n", font_name);
69 attributes &= ~(FontNamePixelSize | FontNameAverageWidth
71 | FontNameResolutionX | FontNameResolutionY);
72 XFormatFontName(&parsed, attributes, canon_font_name);
77 FontNamesAmbiguous(const char *font_name, char **names, int count)
79 char name1[2048], name2[2048];
85 for (i = 0; i < count; i++) {
86 if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
87 fprintf(stderr, "bad font name: %s\n", names[i]);
90 if (i > 0 && strcmp(name1, name2) != 0) {
91 fprintf(stderr, "ambiguous font name: %s\n", font_name);
92 fprintf(stderr, " matches %s\n", names[0]);
93 fprintf(stderr, " and %s\n", names[i]);
100 static int MapFont(char *font_name, const char *troff_name)
107 unsigned int attributes;
110 DviCharNameMap *char_map;
114 char name_string[2048];
116 if (!XParseFontName(font_name, &parsed, &attributes)) {
117 fprintf(stderr, "not a standard name: %s\n", font_name);
121 attributes &= ~(FontNamePixelSize | FontNameAverageWidth);
122 attributes |= FontNameResolutionX;
123 attributes |= FontNameResolutionY;
124 attributes |= FontNamePointSize;
125 parsed.ResolutionX = resolution;
126 parsed.ResolutionY = resolution;
127 parsed.PointSize = point_size * 10;
128 XFormatFontName(&parsed, attributes, name_string);
130 names = XListFonts(dpy, name_string, 100000, &count);
132 fprintf(stderr, "bad font name: %s\n", font_name);
136 if (FontNamesAmbiguous(font_name, names, count))
139 XParseFontName(names[0], &parsed, &attributes);
140 sprintf(encoding, "%s-%s", parsed.CharSetRegistry,
141 parsed.CharSetEncoding);
142 for (s = encoding; *s; s++)
145 char_map = DviFindMap(encoding);
147 fprintf(stderr, "not a standard encoding: %s\n", encoding);
151 fi = XLoadQueryFont(dpy, names[0]);
153 fprintf(stderr, "font does not exist: %s\n", names[0]);
157 printf("%s -> %s\n", names[0], troff_name);
159 { /* Avoid race while opening file */
161 (void) unlink(troff_name);
162 fd = open(troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
163 out = fdopen(fd, "w");
170 fprintf(out, "name %s\n", troff_name);
171 if (!strcmp(char_map->encoding, "adobe-fontspecific"))
172 fprintf(out, "special\n");
173 if (charExists(fi, ' ')) {
174 int w = charWidth(fi, ' ');
176 fprintf(out, "spacewidth %d\n", w);
178 fprintf(out, "charset\n");
179 for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
180 const char *name = DviCharName(char_map, c, 0);
181 if (charExists(fi, c)) {
184 wid = charWidth(fi, c);
186 fprintf(out, "%s\t%d", name ? name : "---", wid);
187 param[0] = charHeight(fi, c);
188 param[1] = charDepth(fi, c);
189 param[2] = 0; /* charRBearing (fi, c) - wid */
190 param[3] = 0; /* charLBearing (fi, c) */
191 param[4] = 0; /* XXX */
192 for (j = 0; j < 5; j++)
195 for (j = 4; j >= 0; j--)
198 for (k = 0; k <= j; k++)
199 fprintf(out, ",%d", param[k]);
200 fprintf(out, "\t0\t0%o\n", c);
203 for (k = 1; DviCharName(char_map, c, k); k++) {
204 fprintf(out, "%s\t\"\n", DviCharName(char_map, c, k));
209 XUnloadFont(dpy, fi->fid);
214 static void usage(FILE *stream)
217 "usage: %s [-r resolution] [-s pointsize] FontMap\n",
221 int main(int argc, char **argv)
223 char troff_name[1024];
224 char font_name[1024];
229 static const struct option long_options[] = {
230 { "help", no_argument, 0, CHAR_MAX + 1 },
231 { "version", no_argument, 0, 'v' },
235 program_name = argv[0];
237 while ((opt = getopt_long(argc, argv, "gr:s:v", long_options,
241 /* unused; just for compatibility */
244 sscanf(optarg, "%u", &resolution);
247 sscanf(optarg, "%u", &point_size);
250 printf("xtotroff (groff) version %s\n", Version_string);
253 case CHAR_MAX + 1: /* --help */
263 if (argc - optind != 1) {
268 dpy = XOpenDisplay(0);
270 fprintf(stderr, "Can't connect to the X server.\n");
272 "Make sure the DISPLAY environment variable is set correctly.\n");
276 map = fopen(argv[optind], "r");
278 perror(argv[optind]);
282 while (fgets(line, sizeof(line), map)) {
283 for (a = line, b = troff_name; *a; a++, b++) {
285 if (c == ' ' || c == '\t')
289 while (*a && (*a == ' ' || *a == '\t'))
291 for (b = font_name; *a; a++, b++)
292 if ((*b = *a) == '\n')
295 if (!MapFont(font_name, troff_name))