1 /* Copyright (C) 1992-2014 Free Software Foundation, Inc.
2 Written by James Clark (jjc@jclark.com)
4 This file is part of groff.
6 groff is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 * convert X font metrics into troff font metrics
29 #define __GETOPT_PREFIX groff_
42 #include "XFontName.h"
45 #define charWidth(fi,c) \
46 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
47 #define charHeight(fi,c) \
48 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
49 #define charDepth(fi,c) \
50 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
51 #define charLBearing(fi,c) \
52 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
53 #define charRBearing(fi,c) \
54 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
56 extern const char *Version_string;
57 static char *program_name;
60 unsigned resolution = 75;
61 unsigned point_size = 10;
63 int charExists(XFontStruct * fi, int c)
67 /* `c' is always >= 0 */
68 if ((unsigned int) c < fi->min_char_or_byte2
69 || (unsigned int) c > fi->max_char_or_byte2)
71 p = fi->per_char + (c - fi->min_char_or_byte2);
72 return p->lbearing != 0 || p->rbearing != 0 || p->width != 0
73 || p->ascent != 0 || p->descent != 0 || p->attributes != 0;
76 /* Canonicalize the font name by replacing scalable parts by *s. */
78 static int CanonicalizeFontName(char *font_name, char *canon_font_name)
80 unsigned int attributes;
83 if (!XParseFontName(font_name, &parsed, &attributes)) {
84 fprintf(stderr, "not a standard name: %s\n", font_name);
88 attributes &= ~(FontNamePixelSize | FontNameAverageWidth
90 | FontNameResolutionX | FontNameResolutionY);
91 XFormatFontName(&parsed, attributes, canon_font_name);
96 FontNamesAmbiguous(const char *font_name, char **names, int count)
98 char name1[2048], name2[2048];
104 for (i = 0; i < count; i++) {
105 if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
106 fprintf(stderr, "bad font name: %s\n", names[i]);
109 if (i > 0 && strcmp(name1, name2) != 0) {
110 fprintf(stderr, "ambiguous font name: %s\n", font_name);
111 fprintf(stderr, " matches %s\n", names[0]);
112 fprintf(stderr, " and %s\n", names[i]);
119 static int MapFont(char *font_name, const char *troff_name)
126 unsigned int attributes;
129 DviCharNameMap *char_map;
133 char name_string[2048];
135 if (!XParseFontName(font_name, &parsed, &attributes)) {
136 fprintf(stderr, "not a standard name: %s\n", font_name);
140 attributes &= ~(FontNamePixelSize | FontNameAverageWidth);
141 attributes |= FontNameResolutionX;
142 attributes |= FontNameResolutionY;
143 attributes |= FontNamePointSize;
144 parsed.ResolutionX = resolution;
145 parsed.ResolutionY = resolution;
146 parsed.PointSize = point_size * 10;
147 XFormatFontName(&parsed, attributes, name_string);
149 names = XListFonts(dpy, name_string, 100000, &count);
151 fprintf(stderr, "bad font name: %s\n", font_name);
155 if (FontNamesAmbiguous(font_name, names, count))
158 XParseFontName(names[0], &parsed, &attributes);
159 sprintf(encoding, "%s-%s", parsed.CharSetRegistry,
160 parsed.CharSetEncoding);
161 for (s = encoding; *s; s++)
164 char_map = DviFindMap(encoding);
166 fprintf(stderr, "not a standard encoding: %s\n", encoding);
170 fi = XLoadQueryFont(dpy, names[0]);
172 fprintf(stderr, "font does not exist: %s\n", names[0]);
176 printf("%s -> %s\n", names[0], troff_name);
178 { /* Avoid race while opening file */
180 (void) unlink(troff_name);
181 fd = open(troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
182 out = fdopen(fd, "w");
189 fprintf(out, "name %s\n", troff_name);
190 if (!strcmp(char_map->encoding, "adobe-fontspecific"))
191 fprintf(out, "special\n");
192 if (charExists(fi, ' ')) {
193 int w = charWidth(fi, ' ');
195 fprintf(out, "spacewidth %d\n", w);
197 fprintf(out, "charset\n");
198 for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
199 const char *name = DviCharName(char_map, c, 0);
200 if (charExists(fi, c)) {
203 wid = charWidth(fi, c);
205 fprintf(out, "%s\t%d", name ? name : "---", wid);
206 param[0] = charHeight(fi, c);
207 param[1] = charDepth(fi, c);
208 param[2] = 0; /* charRBearing (fi, c) - wid */
209 param[3] = 0; /* charLBearing (fi, c) */
210 param[4] = 0; /* XXX */
211 for (j = 0; j < 5; j++)
214 for (j = 4; j >= 0; j--)
217 for (k = 0; k <= j; k++)
218 fprintf(out, ",%d", param[k]);
219 fprintf(out, "\t0\t0%o\n", c);
222 for (k = 1; DviCharName(char_map, c, k); k++) {
223 fprintf(out, "%s\t\"\n", DviCharName(char_map, c, k));
228 XUnloadFont(dpy, fi->fid);
233 static void usage(FILE *stream)
236 "usage: %s [-r resolution] [-s pointsize] FontMap\n",
240 int main(int argc, char **argv)
242 char troff_name[1024];
243 char font_name[1024];
248 static const struct option long_options[] = {
249 { "help", no_argument, 0, CHAR_MAX + 1 },
250 { "version", no_argument, 0, 'v' },
254 program_name = argv[0];
256 while ((opt = getopt_long(argc, argv, "gr:s:v", long_options,
260 /* unused; just for compatibility */
263 sscanf(optarg, "%u", &resolution);
266 sscanf(optarg, "%u", &point_size);
269 printf("xtotroff (groff) version %s\n", Version_string);
272 case CHAR_MAX + 1: /* --help */
282 if (argc - optind != 1) {
287 dpy = XOpenDisplay(0);
289 fprintf(stderr, "Can't connect to the X server.\n");
291 "Make sure the DISPLAY environment variable is set correctly.\n");
295 map = fopen(argv[optind], "r");
297 perror(argv[optind]);
301 while (fgets(line, sizeof(line), map)) {
302 for (a = line, b = troff_name; *a; a++, b++) {
304 if (c == ' ' || c == '\t')
308 while (*a && (*a == ' ' || *a == '\t'))
310 for (b = font_name; *a; a++, b++)
311 if ((*b = *a) == '\n')
314 if (!MapFont(font_name, troff_name))