1 /*
2 * xtotroff
3 *
4 * convert X font metrics into troff font metrics
5 */
6
7 #include <X11/Xlib.h>
8 #include <stdio.h>
9 #include <ctype.h>
10 #include "XFontName.h"
11 #include "DviChar.h"
12
13 #ifdef X_NOT_STDC_ENV
14 char *malloc();
15 #else
16 #include <stdlib.h>
17 #endif
18
19 #define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
20 #define charHeight(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
21 #define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
22 #define charLBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
23 #define charRBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
24
25 Display *dpy;
26 int groff_flag = 0;
27 unsigned resolution = 75;
28 unsigned point_size = 10;
29
charExists(fi,c)30 int charExists (fi, c)
31 XFontStruct *fi;
32 int c;
33 {
34 XCharStruct *p;
35
36 if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
37 return 0;
38 p = fi->per_char + (c - fi->min_char_or_byte2);
39 return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
40 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
41 }
42
43 /* Canonicalize the font name by replacing scalable parts by *s. */
44
CanonicalizeFontName(font_name,canon_font_name)45 CanonicalizeFontName (font_name, canon_font_name)
46 char *font_name, *canon_font_name;
47 {
48 unsigned int attributes;
49 XFontName parsed;
50
51 if (!XParseFontName(font_name, &parsed, &attributes)) {
52 fprintf (stderr, "not a standard name: %s\n", font_name);
53 return 0;
54 }
55
56 attributes &= ~(FontNamePixelSize|FontNameAverageWidth
57 |FontNamePointSize
58 |FontNameResolutionX|FontNameResolutionY);
59 XFormatFontName(&parsed, attributes, canon_font_name);
60 return 1;
61 }
62
FontNamesAmbiguous(font_name,names,count)63 int FontNamesAmbiguous(font_name, names, count)
64 char *font_name;
65 char **names;
66 int count;
67 {
68 char name1[2048], name2[2048];
69 int i;
70
71 if (count == 1)
72 return 0;
73
74 for (i = 0; i < count; i++) {
75 if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
76 fprintf(stderr, "bad font name: %s\n", names[i]);
77 return 1;
78 }
79 if (i > 0 && strcmp(name1, name2) != 0) {
80 fprintf(stderr, "ambiguous font name: %s\n", font_name);
81 fprintf(stderr, " matches %s\n", names[0]);
82 fprintf(stderr, " and %s\n", names[i]);
83 return 1;
84 }
85
86 }
87 return 0;
88 }
89
MapFont(font_name,troff_name)90 MapFont (font_name, troff_name)
91 char *font_name;
92 char *troff_name;
93 {
94 XFontStruct *fi;
95 int count;
96 char **names;
97 FILE *out;
98 int c;
99 unsigned int attributes;
100 XFontName parsed;
101 int j, k;
102 DviCharNameMap *char_map;
103 char encoding[256];
104 char *s;
105 int wid;
106 char name_string[2048];
107
108 if (!XParseFontName(font_name, &parsed, &attributes)) {
109 fprintf (stderr, "not a standard name: %s\n", font_name);
110 return 0;
111 }
112
113 attributes &= ~(FontNamePixelSize|FontNameAverageWidth);
114 attributes |= FontNameResolutionX;
115 attributes |= FontNameResolutionY;
116 attributes |= FontNamePointSize;
117 parsed.ResolutionX = resolution;
118 parsed.ResolutionY = resolution;
119 parsed.PointSize = point_size*10;
120 XFormatFontName(&parsed, attributes, name_string);
121
122 names = XListFonts (dpy, name_string, 100000, &count);
123 if (count < 1) {
124 fprintf (stderr, "bad font name: %s\n", font_name);
125 return 0;
126 }
127
128 if (FontNamesAmbiguous(font_name, names, count))
129 return 0;
130
131 XParseFontName(names[0], &parsed, &attributes);
132 sprintf (encoding, "%s-%s", parsed.CharSetRegistry,
133 parsed.CharSetEncoding);
134 for (s = encoding; *s; s++)
135 if (isupper (*s))
136 *s = tolower (*s);
137 char_map = DviFindMap (encoding);
138 if (!char_map) {
139 fprintf (stderr, "not a standard encoding: %s\n", encoding);
140 return 0;
141 }
142
143 fi = XLoadQueryFont (dpy, names[0]);
144 if (!fi) {
145 fprintf (stderr, "font does not exist: %s\n", names[0]);
146 return 0;
147 }
148
149 printf ("%s -> %s\n", names[0], troff_name);
150
151 (void) unlink (troff_name);
152 out = fopen (troff_name, "w");
153 if (!out) {
154 perror (troff_name);
155 return 0;
156 }
157 fprintf (out, "name %s\n", troff_name);
158 if (!strcmp (char_map->encoding, "adobe-fontspecific"))
159 fprintf (out, "special\n");
160 if (charExists (fi, ' ')) {
161 int w = charWidth (fi, ' ');
162 if (w > 0)
163 fprintf (out, "spacewidth %d\n", w);
164 }
165 fprintf (out, "charset\n");
166 for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
167 char *name = DviCharName (char_map,c,0);
168 if (charExists (fi, c) && (groff_flag || name)) {
169
170 wid = charWidth (fi, c);
171
172 fprintf (out, "%s\t%d",
173 name ? name : "---",
174 wid);
175 if (groff_flag) {
176 int param[5];
177 param[0] = charHeight (fi, c);
178 param[1] = charDepth (fi, c);
179 param[2] = 0 /* charRBearing (fi, c) - wid */;
180 param[3] = 0 /* charLBearing (fi, c) */;
181 param[4] = 0; /* XXX */
182 for (j = 0; j < 5; j++)
183 if (param[j] < 0)
184 param[j] = 0;
185 for (j = 4; j >= 0; j--)
186 if (param[j] != 0)
187 break;
188 for (k = 0; k <= j; k++)
189 fprintf (out, ",%d", param[k]);
190 }
191 fprintf (out, "\t0\t0%o\n", c);
192
193 if (name) {
194 for (k = 1; DviCharName(char_map,c,k); k++) {
195 fprintf (out, "%s\t\"\n",
196 DviCharName (char_map,c,k));
197 }
198 }
199 }
200 }
201 XUnloadFont (dpy, fi->fid);
202 fclose (out);
203 return 1;
204 }
205
usage(prog)206 static usage(prog)
207 char *prog;
208 {
209 fprintf (stderr,
210 "usage: %s [-g] [-r resolution] [-s pointsize FontMap\n",
211 prog);
212 exit (1);
213 }
214
215
216 /* For use by DviChar.c */
217
xmalloc(n)218 char *xmalloc(n)
219 int n;
220 {
221 char *p = malloc(n);
222 if (!p) {
223 fprintf(stderr, "Out of memory\n");
224 exit(1);
225 }
226 return p;
227 }
228
main(argc,argv)229 main (argc, argv)
230 char **argv;
231 {
232 char troff_name[1024];
233 char font_name[1024];
234 char line[1024];
235 char *a, *b, c;
236 int position;
237 FILE *map;
238 int opt;
239 extern int optind;
240 extern char *optarg;
241
242 while ((opt = getopt(argc, argv, "gr:s:")) != EOF) {
243 switch (opt) {
244 case 'g':
245 groff_flag = 1;
246 break;
247 case 'r':
248 sscanf(optarg, "%u", &resolution);
249 break;
250 case 's':
251 sscanf(optarg, "%u", &point_size);
252 break;
253 default:
254 usage(argv[0]);
255 }
256 }
257 if (argc - optind != 1)
258 usage(argv[0]);
259
260 dpy = XOpenDisplay (0);
261 if (!dpy) {
262 fprintf (stderr, "Can't connect to the X server.\n");
263 fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n");
264 exit (1);
265 }
266 position = 1;
267
268 map = fopen (argv[optind], "r");
269 if (map == NULL) {
270 perror (argv[optind]);
271 exit (1);
272 }
273
274 while (fgets (line, sizeof (line), map)) {
275 for (a=line,b=troff_name; *a; a++,b++) {
276 c = (*b = *a);
277 if (c == ' ' || c == '\t')
278 break;
279 }
280 *b = '\0';
281 while (*a && (*a == ' ' || *a == '\t'))
282 ++a;
283 for (b=font_name; *a; a++,b++)
284 if ((*b = *a) == '\n')
285 break;
286 *b = '\0';
287 if (!MapFont (font_name, troff_name))
288 exit (1);
289 ++position;
290 }
291 exit (0);
292 }
293
294 /*
295 Local Variables:
296 c-indent-level: 8
297 c-continued-statement-offset: 8
298 c-brace-offset: -8
299 c-argdecl-indent: 8
300 c-label-offset: -8
301 c-tab-always-indent: nil
302 End:
303 */
304