showfont.c revision 0ed7c580
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
24Copyright (c) 1987  X Consortium
25
26Permission is hereby granted, free of charge, to any person obtaining
27a copy of this software and associated documentation files (the
28"Software"), to deal in the Software without restriction, including
29without limitation the rights to use, copy, modify, merge, publish,
30distribute, sublicense, and/or sell copies of the Software, and to
31permit persons to whom the Software is furnished to do so, subject to
32the following conditions:
33
34The above copyright notice and this permission notice shall be included
35in all copies or substantial portions of the Software.
36
37THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
41OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43OTHER DEALINGS IN THE SOFTWARE.
44
45Except as contained in this notice, the name of the X Consortium shall
46not be used in advertising or otherwise to promote the sale, use or
47other dealings in this Software without prior written authorization
48from 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
73static int	   byteorder = MSBFirst; /* -LSB or -MSB */
74static int	   bitorder = MSBFirst; /* -lsb or -msb */
75static int	   bitmap_pad = 0;	/* -bitmap_pad: ImageRect bitmap format */
76static int	   scan_pad = 8;	/* -pad: ScanlinePad */
77static int	   scan_unit = 8;	/* -unit: ScanlineUnit */
78static int	   first_ch = 0;	/* -start: first character*/
79static int	   end_ch = ~0;	/* -end: end character */
80static const char *ProgramName;
81static Bool	   no_props = False;	/* -noprops: don't show font properties */
82static Bool	   extents_only = False; /* -extents_only */
83
84static FSServer	  *svr;
85
86/* set from bitmap_pad to ImageRectMin, ImageMaxWidth, or ImageMax */
87static int	   bitmap_format;
88
89static FSBitmapFormat
90make_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
154static void
155show_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
161static void
162show_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
283static void
284show_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
317static void
318show_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
353static void
354usage(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
367int
368main(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