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