6 * convert X font metrics into troff font metrics
22 #define __GETOPT_PREFIX groff_
25 #include "XFontName.h"
28 #define charWidth(fi,c) \
29 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
30 #define charHeight(fi,c) \
31 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
32 #define charDepth(fi,c) \
33 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
34 #define charLBearing(fi,c) \
35 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
36 #define charRBearing(fi,c) \
37 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
39 extern const char *Version_string
;
40 static char *program_name
;
43 unsigned resolution
= 75;
44 unsigned point_size
= 10;
46 int charExists(XFontStruct
* fi
, int c
)
50 /* `c' is always >= 0 */
51 if ((unsigned int) c
< fi
->min_char_or_byte2
52 || (unsigned int) c
> fi
->max_char_or_byte2
)
54 p
= fi
->per_char
+ (c
- fi
->min_char_or_byte2
);
55 return p
->lbearing
!= 0 || p
->rbearing
!= 0 || p
->width
!= 0
56 || p
->ascent
!= 0 || p
->descent
!= 0 || p
->attributes
!= 0;
59 /* Canonicalize the font name by replacing scalable parts by *s. */
61 static int CanonicalizeFontName(char *font_name
, char *canon_font_name
)
63 unsigned int attributes
;
66 if (!XParseFontName(font_name
, &parsed
, &attributes
)) {
67 fprintf(stderr
, "not a standard name: %s\n", font_name
);
71 attributes
&= ~(FontNamePixelSize
| FontNameAverageWidth
73 | FontNameResolutionX
| FontNameResolutionY
);
74 XFormatFontName(&parsed
, attributes
, canon_font_name
);
79 FontNamesAmbiguous(const char *font_name
, char **names
, int count
)
81 char name1
[2048], name2
[2048];
87 for (i
= 0; i
< count
; i
++) {
88 if (!CanonicalizeFontName(names
[i
], i
== 0 ? name1
: name2
)) {
89 fprintf(stderr
, "bad font name: %s\n", names
[i
]);
92 if (i
> 0 && strcmp(name1
, name2
) != 0) {
93 fprintf(stderr
, "ambiguous font name: %s\n", font_name
);
94 fprintf(stderr
, " matches %s\n", names
[0]);
95 fprintf(stderr
, " and %s\n", names
[i
]);
102 static int MapFont(char *font_name
, const char *troff_name
)
109 unsigned int attributes
;
112 DviCharNameMap
*char_map
;
116 char name_string
[2048];
118 if (!XParseFontName(font_name
, &parsed
, &attributes
)) {
119 fprintf(stderr
, "not a standard name: %s\n", font_name
);
123 attributes
&= ~(FontNamePixelSize
| FontNameAverageWidth
);
124 attributes
|= FontNameResolutionX
;
125 attributes
|= FontNameResolutionY
;
126 attributes
|= FontNamePointSize
;
127 parsed
.ResolutionX
= resolution
;
128 parsed
.ResolutionY
= resolution
;
129 parsed
.PointSize
= point_size
* 10;
130 XFormatFontName(&parsed
, attributes
, name_string
);
132 names
= XListFonts(dpy
, name_string
, 100000, &count
);
134 fprintf(stderr
, "bad font name: %s\n", font_name
);
138 if (FontNamesAmbiguous(font_name
, names
, count
))
141 XParseFontName(names
[0], &parsed
, &attributes
);
142 sprintf(encoding
, "%s-%s", parsed
.CharSetRegistry
,
143 parsed
.CharSetEncoding
);
144 for (s
= encoding
; *s
; s
++)
147 char_map
= DviFindMap(encoding
);
149 fprintf(stderr
, "not a standard encoding: %s\n", encoding
);
153 fi
= XLoadQueryFont(dpy
, names
[0]);
155 fprintf(stderr
, "font does not exist: %s\n", names
[0]);
159 printf("%s -> %s\n", names
[0], troff_name
);
161 { /* Avoid race while opening file */
163 (void) unlink(troff_name
);
164 fd
= open(troff_name
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600);
165 out
= fdopen(fd
, "w");
172 fprintf(out
, "name %s\n", troff_name
);
173 if (!strcmp(char_map
->encoding
, "adobe-fontspecific"))
174 fprintf(out
, "special\n");
175 if (charExists(fi
, ' ')) {
176 int w
= charWidth(fi
, ' ');
178 fprintf(out
, "spacewidth %d\n", w
);
180 fprintf(out
, "charset\n");
181 for (c
= fi
->min_char_or_byte2
; c
<= fi
->max_char_or_byte2
; c
++) {
182 const char *name
= DviCharName(char_map
, c
, 0);
183 if (charExists(fi
, c
)) {
186 wid
= charWidth(fi
, c
);
188 fprintf(out
, "%s\t%d", name
? name
: "---", wid
);
189 param
[0] = charHeight(fi
, c
);
190 param
[1] = charDepth(fi
, c
);
191 param
[2] = 0; /* charRBearing (fi, c) - wid */
192 param
[3] = 0; /* charLBearing (fi, c) */
193 param
[4] = 0; /* XXX */
194 for (j
= 0; j
< 5; j
++)
197 for (j
= 4; j
>= 0; j
--)
200 for (k
= 0; k
<= j
; k
++)
201 fprintf(out
, ",%d", param
[k
]);
202 fprintf(out
, "\t0\t0%o\n", c
);
205 for (k
= 1; DviCharName(char_map
, c
, k
); k
++) {
206 fprintf(out
, "%s\t\"\n", DviCharName(char_map
, c
, k
));
211 XUnloadFont(dpy
, fi
->fid
);
216 static void usage(FILE *stream
)
219 "usage: %s [-r resolution] [-s pointsize] FontMap\n",
223 int main(int argc
, char **argv
)
225 char troff_name
[1024];
226 char font_name
[1024];
231 static const struct option long_options
[] = {
232 { "help", no_argument
, 0, CHAR_MAX
+ 1 },
233 { "version", no_argument
, 0, 'v' },
237 program_name
= argv
[0];
239 while ((opt
= getopt_long(argc
, argv
, "gr:s:v", long_options
,
243 /* unused; just for compatibility */
246 sscanf(optarg
, "%u", &resolution
);
249 sscanf(optarg
, "%u", &point_size
);
252 printf("xtotroff (groff) version %s\n", Version_string
);
255 case CHAR_MAX
+ 1: /* --help */
265 if (argc
- optind
!= 1) {
270 dpy
= XOpenDisplay(0);
272 fprintf(stderr
, "Can't connect to the X server.\n");
274 "Make sure the DISPLAY environment variable is set correctly.\n");
278 map
= fopen(argv
[optind
], "r");
280 perror(argv
[optind
]);
284 while (fgets(line
, sizeof(line
), map
)) {
285 for (a
= line
, b
= troff_name
; *a
; a
++, b
++) {
287 if (c
== ' ' || c
== '\t')
291 while (*a
&& (*a
== ' ' || *a
== '\t'))
293 for (b
= font_name
; *a
; a
++, b
++)
294 if ((*b
= *a
) == '\n')
297 if (!MapFont(font_name
, troff_name
))