1 /*
2 * Copyright 1990 Network Computing Devices;
3 * Portions Copyright 1987 by Digital Equipment Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the names of Network Computing Devices or Digital
10 * not be used in advertising or publicity pertaining to distribution
11 * of the software without specific, written prior permission.
12 *
13 * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH
14 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETWORK COMPUTING DEVICES
16 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
17 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
20 * THIS SOFTWARE.
21 */
22 /*
23
24 Copyright (c) 1987 X Consortium
25
26 Permission is hereby granted, free of charge, to any person obtaining
27 a copy of this software and associated documentation files (the
28 "Software"), to deal in the Software without restriction, including
29 without limitation the rights to use, copy, modify, merge, publish,
30 distribute, sublicense, and/or sell copies of the Software, and to
31 permit persons to whom the Software is furnished to do so, subject to
32 the following conditions:
33
34 The above copyright notice and this permission notice shall be included
35 in all copies or substantial portions of the Software.
36
37 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
41 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43 OTHER DEALINGS IN THE SOFTWARE.
44
45 Except as contained in this notice, the name of the X Consortium shall
46 not be used in advertising or otherwise to promote the sale, use or
47 other dealings in this Software without prior written authorization
48 from the X Consortium.
49
50 */
51
52 #ifdef HAVE_CONFIG_H
53 # include "config.h"
54 #endif
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <ctype.h>
60 #include <X11/fonts/FSlib.h>
61
62 /*
63 * the equivalent of showsnf
64 */
65
66 #define GLWIDTHBYTESPADDED(bits,nbytes) \
67 ((nbytes) == 1 ? (((bits)+7)>>3) /* pad to 1 byte */ \
68 :(nbytes) == 2 ? ((((bits)+15)>>3)&~1) /* pad to 2 bytes */ \
69 :(nbytes) == 4 ? ((((bits)+31)>>3)&~3) /* pad to 4 bytes */ \
70 :(nbytes) == 8 ? ((((bits)+63)>>3)&~7) /* pad to 8 bytes */ \
71 : 0)
72
73 static int byteorder = MSBFirst; /* -LSB or -MSB */
74 static int bitorder = MSBFirst; /* -lsb or -msb */
75 static int bitmap_pad = 0; /* -bitmap_pad: ImageRect bitmap format */
76 static int scan_pad = 8; /* -pad: ScanlinePad */
77 static int scan_unit = 8; /* -unit: ScanlineUnit */
78 static int first_ch = 0; /* -start: first character*/
79 static int end_ch = ~0; /* -end: end character */
80 static const char *ProgramName;
81 static Bool no_props = False; /* -noprops: don't show font properties */
82 static Bool extents_only = False; /* -extents_only */
83
84 static FSServer *svr;
85
86 /* set from bitmap_pad to ImageRectMin, ImageMaxWidth, or ImageMax */
87 static int bitmap_format;
88
89 static FSBitmapFormat
make_format(void)90 make_format(void)
91 {
92 FSBitmapFormat format;
93
94 format = 0;
95 /* set up format */
96 switch (scan_pad) {
97 case 8:
98 format |= BitmapFormatScanlinePad8;
99 break;
100 case 16:
101 format |= BitmapFormatScanlinePad16;
102 break;
103 case 32:
104 format |= BitmapFormatScanlinePad32;
105 break;
106 case 64:
107 format |= BitmapFormatScanlinePad64;
108 break;
109 default:
110 fprintf(stderr, "bogus scanline pad value: %d\n", scan_pad);
111 break;
112 }
113 switch (scan_unit) {
114 case 8:
115 format |= BitmapFormatScanlineUnit8;
116 break;
117 case 16:
118 format |= BitmapFormatScanlineUnit16;
119 break;
120 case 32:
121 format |= BitmapFormatScanlineUnit32;
122 break;
123 case 64:
124 format |= BitmapFormatScanlineUnit64;
125 break;
126 default:
127 fprintf(stderr, "bogus scanline unit value: %d\n", scan_unit);
128 break;
129 }
130 switch (bitmap_pad) {
131 case 0:
132 bitmap_format = BitmapFormatImageRectMin;
133 break;
134 case 1:
135 bitmap_format = BitmapFormatImageRectMaxWidth;
136 break;
137 case 2:
138 bitmap_format = BitmapFormatImageRectMax;
139 break;
140 default:
141 fprintf(stderr, "bogus bitmap pad value: %d\n", bitmap_pad);
142 break;
143 }
144 format |= bitmap_format;
145
146 format |= (bitorder == MSBFirst) ? BitmapFormatBitOrderMSB :
147 BitmapFormatBitOrderLSB;
148 format |= (byteorder == MSBFirst) ? BitmapFormatByteOrderMSB :
149 BitmapFormatByteOrderLSB;
150
151 return format;
152 }
153
154 static void
show_char_info(FSXCharInfo * ci)155 show_char_info(FSXCharInfo *ci)
156 {
157 printf("Left: %-3d Right: %-3d Ascent: %-3d Descent: %-3d Width: %d\n",
158 ci->left, ci->right, ci->ascent, ci->descent, ci->width);
159 }
160
161 static void
show_glyphs(Font fid,FSXFontInfoHeader * hdr,Bool show_all,FSChar2b first,FSChar2b last)162 show_glyphs(
163 Font fid,
164 FSXFontInfoHeader *hdr,
165 Bool show_all,
166 FSChar2b first,
167 FSChar2b last)
168 {
169 FSXCharInfo *extents;
170 int err,
171 ch,
172 start;
173 int offset = 0;
174 unsigned char *glyphs;
175 FSOffset *offsets;
176 int scanpad;
177 int r,
178 b;
179 FSBitmapFormat format;
180 FSChar2b chars[2];
181 int num_chars;
182 int row,
183 col,
184 temp_ch;
185
186 if (show_all) {
187 num_chars = 0;
188 } else {
189 chars[0] = first;
190 chars[1] = last;
191 num_chars = 2;
192 }
193 FSQueryXExtents16(svr, fid, True, chars, num_chars, &extents);
194
195 if (!extents_only) {
196 format = make_format();
197 err = FSQueryXBitmaps16(svr, fid, format, True, chars, num_chars,
198 &offsets, &glyphs);
199
200 if (err != FSSuccess) {
201 fprintf(stderr, "QueryGlyphs failed\n");
202 exit(1);
203 }
204 }
205
206 scanpad = scan_pad >> 3;
207
208 for (row = (int)first.high; row <= (int)last.high; row++) {
209 start = first.low + (row << 8);
210 for (col = (int)first.low; col <= (int)last.low; col++) {
211 int bottom,
212 bpr,
213 charwidth;
214
215 ch = ((row - (int)first.high)
216 * ((int)last.low - (int)first.low + 1))
217 + (col - (int)first.low);
218 temp_ch = start + (col - (int)first.low);
219 printf("char #%d", temp_ch);
220 if ((temp_ch >= 0) && (temp_ch <= 127) && isprint(temp_ch))
221 printf(" '%c'\n", (char) (temp_ch));
222 else
223 printf(" 0x%04x\n", temp_ch);
224 show_char_info(&extents[ch]);
225 if (extents_only)
226 continue;
227 if (offset != offsets[ch].position)
228 fprintf(stderr, "offset mismatch: expected %d, got %d\n",
229 offset, offsets[ch].position);
230 switch (bitmap_format) {
231 case BitmapFormatImageRectMin:
232 bottom = extents[ch].descent + extents[ch].ascent;
233 charwidth = extents[ch].right - extents[ch].left;
234 break;
235 case BitmapFormatImageRectMaxWidth:
236 bottom = extents[ch].descent + extents[ch].ascent;
237 charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
238 break;
239 case BitmapFormatImageRectMax:
240 bottom = hdr->max_bounds.ascent +
241 hdr->max_bounds.descent;
242 charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
243 break;
244 default:
245 bottom = 0;
246 charwidth = 0;
247 }
248
249 if (extents[ch].left == 0 &&
250 extents[ch].right == 0 &&
251 extents[ch].width == 0 &&
252 extents[ch].ascent == 0 &&
253 extents[ch].descent == 0) {
254 printf ("Nonexistent character\n");
255 continue;
256 }
257 bpr = GLWIDTHBYTESPADDED(charwidth, scanpad);
258 if (offsets[ch].length != bottom * bpr) {
259 fprintf (stderr,
260 "length mismatch: expected %d (%dx%d), got %d\n",
261 bottom * bpr, bpr, bottom, offsets[ch].length);
262 }
263 offset = offsets[ch].position;
264 for (r = 0; r < bottom; r++) {
265 unsigned char *rowp = glyphs + offset;
266
267 for (b = 0; b < charwidth; b++) {
268 putchar((rowp[b >> 3] &
269 (1 << (7 - (b & 7)))) ? '#' : '-');
270 }
271 putchar('\n');
272 offset += bpr;
273 }
274 }
275 }
276 FSFree((char *) extents);
277 if (!extents_only) {
278 FSFree((char *) offsets);
279 FSFree((char *) glyphs);
280 }
281 }
282
283 static void
show_props(FSPropInfo * pi,FSPropOffset * po,unsigned char * pd)284 show_props(
285 FSPropInfo *pi,
286 FSPropOffset *po,
287 unsigned char *pd)
288 {
289 int i;
290 char buf[512];
291 int num_props;
292
293 num_props = pi->num_offsets;
294 for (i = 0; i < num_props; i++, po++) {
295 strncpy(buf, (char *) (pd + po->name.position), po->name.length);
296 buf[po->name.length] = '\0';
297 printf("%s\t", buf);
298 switch (po->type) {
299 case PropTypeString:
300 strncpy(buf, (char *)(pd + po->value.position), po->value.length);
301 buf[po->value.length] = '\0';
302 printf("%s\n", buf);
303 break;
304 case PropTypeUnsigned:
305 printf("%lu\n", (unsigned long) po->value.position);
306 break;
307 case PropTypeSigned:
308 printf("%ld\n", (long) po->value.position);
309 break;
310 default:
311 fprintf(stderr, "bogus property\n");
312 break;
313 }
314 }
315 }
316
317 static void
show_info(Font fid,FSXFontInfoHeader * hdr,FSChar2b * first,FSChar2b * last)318 show_info(
319 Font fid,
320 FSXFontInfoHeader *hdr,
321 FSChar2b *first,
322 FSChar2b *last)
323 {
324 FSPropInfo pi;
325 FSPropOffset *po;
326 unsigned char *pd;
327
328 FSQueryXInfo(svr, fid, hdr, &pi, &po, &pd);
329 printf("Direction: %s\n", (hdr->draw_direction == LeftToRightDrawDirection)
330 ? "Left to Right" : "Right to Left");
331 *first = hdr->char_range.min_char;
332 *last = hdr->char_range.max_char;
333 printf("Range: %d to %d\n",
334 first->low + (first->high << 8),
335 last->low + (last->high << 8));
336 if (hdr->flags & FontInfoAllCharsExist)
337 printf("All chars exist\n");
338 printf("Default char: %d\n",
339 hdr->default_char.low + (hdr->default_char.high << 8));
340 printf("Min bounds: \n");
341 show_char_info(&hdr->min_bounds);
342 printf("Max bounds: \n");
343 show_char_info(&hdr->max_bounds);
344 printf("Font Ascent: %d Font Descent: %d\n",
345 hdr->font_ascent, hdr->font_descent);
346
347 if (!no_props)
348 show_props(&pi, po, pd);
349 FSFree((char *) po);
350 FSFree((char *) pd);
351 }
352
353 static void
usage(const char * msg)354 usage(const char *msg)
355 {
356 if (msg)
357 fprintf(stderr, "%s: %s\n", ProgramName, msg);
358 fprintf(stderr,
359 "Usage: %s [-server servername] [-extents_only] [-noprops]\n"
360 " [-lsb] [-msb] [-LSB] [-MSB] [-unit #] [-pad #] [-bitmap_pad value]\n"
361 " [-start first_char] [-end last_char] -fn fontname\n"
362 " or: %s -version\n",
363 ProgramName, ProgramName);
364 exit(1);
365 }
366
367 int
main(int argc,char ** argv)368 main(int argc, char **argv)
369 {
370 const char *servername = "localhost:7100"; /* -server: font server name */
371 char *fontname = NULL; /* -fn: font name */
372 int i;
373 Font fid,
374 dummy;
375 FSBitmapFormat format;
376 FSBitmapFormatMask fmask;
377 FSChar2b first,
378 last;
379 FSXFontInfoHeader hdr;
380 Bool show_all = True;
381
382 ProgramName = argv[0];
383
384 for (i = 1; i < argc; i++) {
385 if (!strncmp(argv[i], "-se", 3)) {
386 if (++i < argc)
387 servername = argv[i];
388 else
389 usage("-server requires an argument");
390 } else if (!strncmp(argv[i], "-ext", 4)) {
391 extents_only = True;
392 } else if (!strncmp(argv[i], "-noprops", 7)) {
393 no_props = True;
394 } else if (!strncmp(argv[i], "-lsb", 4)) {
395 bitorder = LSBFirst;
396 } else if (!strncmp(argv[i], "-msb", 4)) {
397 bitorder = MSBFirst;
398 } else if (!strncmp(argv[i], "-LSB", 4)) {
399 byteorder = LSBFirst;
400 } else if (!strncmp(argv[i], "-MSB", 4)) {
401 byteorder = MSBFirst;
402 } else if (!strncmp(argv[i], "-p", 2)) {
403 if (++i < argc)
404 scan_pad = atoi(argv[i]);
405 else
406 usage("-pad requires an argument");
407 } else if (!strncmp(argv[i], "-u", 2)) {
408 if (++i < argc)
409 scan_unit = atoi(argv[i]);
410 else
411 usage("-unit requires an argument");
412 } else if (!strncmp(argv[i], "-b", 2)) {
413 if (++i < argc)
414 bitmap_pad = atoi(argv[i]);
415 else
416 usage("-bitmap_pad requires an argument");
417 } else if (!strncmp(argv[i], "-st", 3)) {
418 if (++i < argc)
419 first_ch = atoi(argv[i]);
420 else
421 usage("-start requires an argument");
422 } else if (!strncmp(argv[i], "-e", 2)) {
423 if (++i < argc)
424 end_ch = atoi(argv[i]);
425 else
426 usage("-end requires an argument");
427 } else if (!strncmp(argv[i], "-f", 2)) {
428 if (++i < argc)
429 fontname = argv[i];
430 else
431 usage("-fn requires an argument");
432 } else if (!strcmp(argv[i], "-version")) {
433 puts(PACKAGE_STRING);
434 exit(0);
435 } else {
436 char msg[128];
437 snprintf(msg, sizeof(msg), "unrecognized argument: %s", argv[i]);
438 usage(msg);
439 }
440 }
441 if (fontname == NULL)
442 usage("no fontname specified");
443
444 if (first_ch != 0 && end_ch != ~0 && end_ch < first_ch) {
445 fprintf(stderr,
446 "bad character range -- end (%d) is less than start (%d)\n",
447 end_ch, first_ch);
448 exit(1);
449 }
450 if ((svr = FSOpenServer(servername)) == NULL) {
451 if(FSServerName(servername) != NULL)
452 fprintf(stderr, "can't open server \"%s\"\n", FSServerName(servername));
453 else
454 fprintf(stderr, "can't open server \"\"\n");
455 exit(1);
456 }
457 format = make_format();
458 fmask = (BitmapFormatMaskByte | BitmapFormatMaskBit |
459 BitmapFormatMaskImageRectangle | BitmapFormatMaskScanLinePad |
460 BitmapFormatMaskScanLineUnit);
461 fid = FSOpenBitmapFont(svr, format, fmask, fontname, &dummy);
462 if (fid) {
463 printf("opened font %s\n", fontname);
464 show_info(fid, &hdr, &first, &last);
465 if (first_ch != 0 &&
466 ((unsigned)first_ch >= (first.low + (first.high << 8)))) {
467 first.low = first_ch & 0xff;
468 first.high = first_ch >> 8;
469 show_all = False;
470 }
471 if (end_ch != ~0 &&
472 ((unsigned)end_ch <= (last.low + (last.high << 8)))) {
473 last.low = end_ch & 0xff;
474 last.high = end_ch >> 8;
475 show_all = False;
476 }
477 /* make sure the range is legal */
478 if ((first.high > last.high) || (first.high == last.high &&
479 first.low > last.low)) {
480 last = first;
481 fprintf(stderr,
482 "adjusting range -- specifed first char is after end\n");
483 }
484 show_glyphs(fid, &hdr, show_all, first, last);
485 FSCloseFont(svr, fid);
486 } else {
487 fprintf(stderr, "couldn't get font %s\n", fontname);
488 FSCloseServer(svr);
489 exit(1);
490 }
491 FSCloseServer(svr);
492 exit(0);
493 }
494