Home | History | Annotate | Line # | Download | only in dist
      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
     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
    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
    162 show_glyphs(
    163     Font        fid,
    164     FSXFontInfoHeader *hdr,
    165     Bool        show_all,
    166     FSChar2b    first,
    167     FSChar2b    last)
    168 {
    169     FSXCharInfo *extents;
    170     unsigned int   offset = 0;
    171     unsigned char *glyphs;
    172     FSOffset   *offsets;
    173     int         scanpad;
    174     FSChar2b    chars[2];
    175     int         num_chars;
    176 
    177     if (show_all) {
    178 	num_chars = 0;
    179     } else {
    180 	chars[0] = first;
    181 	chars[1] = last;
    182 	num_chars = 2;
    183     }
    184     FSQueryXExtents16(svr, fid, True, chars, num_chars, &extents);
    185 
    186     if (!extents_only) {
    187 	FSBitmapFormat format = make_format();
    188 	int err = FSQueryXBitmaps16(svr, fid, format, True, chars, num_chars,
    189 				    &offsets, &glyphs);
    190 
    191 	if (err != FSSuccess) {
    192 	    fprintf(stderr, "QueryGlyphs failed\n");
    193 	    exit(1);
    194 	}
    195     }
    196 
    197     scanpad = scan_pad >> 3;
    198 
    199     for (int row = (int)first.high; row <= (int)last.high; row++) {
    200 	int start = first.low + (row << 8);
    201 	for (int col = (int)first.low; col <= (int)last.low; col++) {
    202 	    int		bottom,
    203 			bpr,
    204 	        	charwidth;
    205 
    206 	    int ch = ((row - (int)first.high)
    207                       * ((int)last.low - (int)first.low + 1))
    208 		+ (col - (int)first.low);
    209 	    int temp_ch = start + (col - (int)first.low);
    210 	    printf("char #%d", temp_ch);
    211 	    if ((temp_ch >= 0) && (temp_ch <= 127) && isprint(temp_ch))
    212 		printf(" '%c'\n", (char) (temp_ch));
    213 	    else
    214 		printf(" 0x%04x\n", temp_ch);
    215 	    show_char_info(&extents[ch]);
    216 	    if (extents_only)
    217 		continue;
    218 	    if (offset != offsets[ch].position)
    219 		fprintf(stderr, "offset mismatch: expected %d, got %d\n",
    220 			offset, offsets[ch].position);
    221 	    switch (bitmap_format) {
    222 	    case BitmapFormatImageRectMin:
    223 		bottom = extents[ch].descent + extents[ch].ascent;
    224 		charwidth = extents[ch].right - extents[ch].left;
    225 		break;
    226 	    case BitmapFormatImageRectMaxWidth:
    227 		bottom = extents[ch].descent + extents[ch].ascent;
    228 		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
    229 		break;
    230 	    case BitmapFormatImageRectMax:
    231 		bottom = hdr->max_bounds.ascent +
    232 		    hdr->max_bounds.descent;
    233 		charwidth = hdr->max_bounds.right - hdr->min_bounds.left;
    234 		break;
    235 	    default:
    236 		bottom = 0;
    237 		charwidth = 0;
    238 	    }
    239 
    240 	    if (extents[ch].left == 0 &&
    241 		extents[ch].right == 0 &&
    242 		extents[ch].width == 0 &&
    243 		extents[ch].ascent == 0 &&
    244 		extents[ch].descent == 0) {
    245 		printf ("Nonexistent character\n");
    246 		continue;
    247 	    }
    248 	    bpr = GLWIDTHBYTESPADDED(charwidth, scanpad);
    249 	    if (offsets[ch].length != (unsigned)(bottom * bpr)) {
    250 		fprintf (stderr,
    251 			 "length mismatch: expected %d (%dx%d), got %d\n",
    252 			 bottom * bpr, bpr, bottom, offsets[ch].length);
    253 	    }
    254 	    offset = offsets[ch].position;
    255 	    for (int r = 0; r < bottom; r++) {
    256 		unsigned char *rowp = glyphs + offset;
    257 
    258 		for (int b = 0; b < charwidth; b++) {
    259 		    putchar((rowp[b >> 3] &
    260 			     (1 << (7 - (b & 7)))) ? '#' : '-');
    261 		}
    262 		putchar('\n');
    263 		offset += bpr;
    264 	    }
    265 	}
    266     }
    267     FSFree((char *) extents);
    268     if (!extents_only) {
    269 	FSFree((char *) offsets);
    270 	FSFree((char *) glyphs);
    271     }
    272 }
    273 
    274 static void
    275 show_props(
    276     FSPropInfo *pi,
    277     FSPropOffset *po,
    278     unsigned char *pd)
    279 {
    280     char        buf[512];
    281     int         num_props;
    282 
    283     num_props = pi->num_offsets;
    284     for (int i = 0; i < num_props; i++, po++) {
    285 	strncpy(buf, (char *) (pd + po->name.position), po->name.length);
    286 	buf[po->name.length] = '\0';
    287 	printf("%s\t", buf);
    288 	switch (po->type) {
    289 	case PropTypeString:
    290 	    strncpy(buf, (char *)(pd + po->value.position), po->value.length);
    291 	    buf[po->value.length] = '\0';
    292 	    printf("%s\n", buf);
    293 	    break;
    294 	case PropTypeUnsigned:
    295 	    printf("%lu\n", (unsigned long) po->value.position);
    296 	    break;
    297 	case PropTypeSigned:
    298 	    printf("%ld\n", (long) po->value.position);
    299 	    break;
    300 	default:
    301 	    fprintf(stderr, "bogus property\n");
    302 	    break;
    303 	}
    304     }
    305 }
    306 
    307 static void
    308 show_info(
    309     Font        fid,
    310     FSXFontInfoHeader *hdr,
    311     FSChar2b   *first,
    312     FSChar2b   *last)
    313 {
    314     FSPropInfo  pi;
    315     FSPropOffset *po;
    316     unsigned char *pd;
    317 
    318     FSQueryXInfo(svr, fid, hdr, &pi, &po, &pd);
    319     printf("Direction: %s\n", (hdr->draw_direction == LeftToRightDrawDirection)
    320 	   ? "Left to Right" : "Right to Left");
    321     *first = hdr->char_range.min_char;
    322     *last = hdr->char_range.max_char;
    323     printf("Range:	%d to %d\n",
    324 	   first->low + (first->high << 8),
    325 	   last->low + (last->high << 8));
    326     if (hdr->flags & FontInfoAllCharsExist)
    327 	printf("All chars exist\n");
    328     printf("Default char: %d\n",
    329 	   hdr->default_char.low + (hdr->default_char.high << 8));
    330     printf("Min bounds: \n");
    331     show_char_info(&hdr->min_bounds);
    332     printf("Max bounds: \n");
    333     show_char_info(&hdr->max_bounds);
    334     printf("Font Ascent: %d  Font Descent: %d\n",
    335 	   hdr->font_ascent, hdr->font_descent);
    336 
    337     if (!no_props)
    338 	show_props(&pi, po, pd);
    339     FSFree((char *) po);
    340     FSFree((char *) pd);
    341 }
    342 
    343  _X_NORETURN static void
    344 usage(const char *msg, int exitval)
    345 {
    346     if (msg)
    347 	fprintf(stderr, "%s: %s\n", ProgramName, msg);
    348     fprintf(stderr,
    349 	    "Usage: %s [-server servername] [-extents_only] [-noprops]\n"
    350 	    "       [-lsb] [-msb] [-LSB] [-MSB] [-unit #] [-pad #] [-bitmap_pad value]\n"
    351 	    "       [-start first_char] [-end last_char] -fn fontname\n"
    352 	    "   or: %s -version\n",
    353 	    ProgramName, ProgramName);
    354     exit(exitval);
    355 }
    356 
    357 int
    358 main(int argc, char **argv)
    359 {
    360     const char *servername = "localhost:7100"; /* -server: font server name */
    361     char *fontname = NULL; /* -fn: font name */
    362     Font        fid,
    363                 dummy;
    364     FSBitmapFormat format;
    365     FSBitmapFormatMask fmask;
    366 
    367     ProgramName = argv[0];
    368 
    369     for (int i = 1; i < argc; i++) {
    370 	if (!strncmp(argv[i], "-se", 3)) {
    371 	    if (++i < argc)
    372 		servername = argv[i];
    373 	    else
    374 		usage("-server requires an argument", 1);
    375 	} else if (!strncmp(argv[i], "-ext", 4)) {
    376 	    extents_only = True;
    377 	} else if (!strncmp(argv[i], "-noprops", 7)) {
    378 	    no_props = True;
    379 	} else if (!strncmp(argv[i], "-lsb", 4)) {
    380 	    bitorder = LSBFirst;
    381 	} else if (!strncmp(argv[i], "-msb", 4)) {
    382 	    bitorder = MSBFirst;
    383 	} else if (!strncmp(argv[i], "-LSB", 4)) {
    384 	    byteorder = LSBFirst;
    385 	} else if (!strncmp(argv[i], "-MSB", 4)) {
    386 	    byteorder = MSBFirst;
    387 	} else if (!strncmp(argv[i], "-p", 2)) {
    388 	    if (++i < argc)
    389 		scan_pad = atoi(argv[i]);
    390 	    else
    391 		usage("-pad requires an argument", 1);
    392 	} else if (!strncmp(argv[i], "-u", 2)) {
    393 	    if (++i < argc)
    394 		scan_unit = atoi(argv[i]);
    395 	    else
    396 		usage("-unit requires an argument", 1);
    397 	} else if (!strncmp(argv[i], "-b", 2)) {
    398 	    if (++i < argc)
    399 		bitmap_pad = atoi(argv[i]);
    400 	    else
    401 		usage("-bitmap_pad requires an argument", 1);
    402 	} else if (!strncmp(argv[i], "-st", 3)) {
    403 	    if (++i < argc)
    404 		first_ch = atoi(argv[i]);
    405 	    else
    406 		usage("-start requires an argument", 1);
    407 	} else if (!strncmp(argv[i], "-e", 2)) {
    408 	    if (++i < argc)
    409 		end_ch = atoi(argv[i]);
    410 	    else
    411 		usage("-end requires an argument", 1);
    412 	} else if (!strncmp(argv[i], "-f", 2)) {
    413 	    if (++i < argc)
    414 		fontname = argv[i];
    415 	    else
    416 		usage("-fn requires an argument", 1);
    417 	} else if (!strcmp(argv[i], "-version") ||
    418 		   !strcmp(argv[i], "--version")) {
    419 	    puts(PACKAGE_STRING);
    420 	    exit(0);
    421 	} else if (!strcmp(argv[i], "-help") ||
    422 		   !strcmp(argv[i], "--help")) {
    423 	    usage(NULL, 0);
    424 	} else {
    425 	    char msg[128];
    426 	    snprintf(msg, sizeof(msg), "unrecognized argument: %s", argv[i]);
    427 	    usage(msg, 1);
    428 	}
    429     }
    430     if (fontname == NULL)
    431 	usage("no fontname specified", 1);
    432 
    433     if (first_ch != 0 && end_ch != ~0 && end_ch < first_ch) {
    434 	fprintf(stderr,
    435 		"bad character range -- end (%d) is less than start (%d)\n",
    436 		end_ch, first_ch);
    437 	exit(1);
    438     }
    439     if ((svr = FSOpenServer(servername)) == NULL) {
    440 	if(FSServerName(servername) != NULL)
    441 		fprintf(stderr, "can't open server \"%s\"\n", FSServerName(servername));
    442 	else
    443 		fprintf(stderr, "can't open server \"\"\n");
    444 	exit(1);
    445     }
    446     format = make_format();
    447     fmask = (BitmapFormatMaskByte | BitmapFormatMaskBit |
    448 	     BitmapFormatMaskImageRectangle | BitmapFormatMaskScanLinePad |
    449 	     BitmapFormatMaskScanLineUnit);
    450     fid = FSOpenBitmapFont(svr, format, fmask, fontname, &dummy);
    451     if (fid) {
    452 	Bool	    show_all = True;
    453 	FSChar2b    first,
    454 		    last;
    455 	FSXFontInfoHeader hdr;
    456 
    457 	printf("opened font %s\n", fontname);
    458 	show_info(fid, &hdr, &first, &last);
    459 	if (first_ch != 0 &&
    460             ((unsigned)first_ch >= (first.low + ((unsigned)first.high << 8)))) {
    461 	    first.low = first_ch & 0xff;
    462 	    first.high = first_ch >> 8;
    463 	    show_all = False;
    464 	}
    465 	if (end_ch != ~0 &&
    466             ((unsigned)end_ch <= (last.low + ((unsigned)last.high << 8)))) {
    467 	    last.low = end_ch & 0xff;
    468 	    last.high = end_ch >> 8;
    469 	    show_all = False;
    470 	}
    471 	/* make sure the range is legal */
    472 	if ((first.high > last.high) || (first.high == last.high &&
    473 					 first.low > last.low)) {
    474 	    last = first;
    475 	    fprintf(stderr,
    476 		    "adjusting range -- specified first char is after end\n");
    477 	}
    478 	show_glyphs(fid, &hdr, show_all, first, last);
    479 	FSCloseFont(svr, fid);
    480     } else {
    481 	fprintf(stderr, "couldn't get font %s\n", fontname);
    482 	FSCloseServer(svr);
    483 	exit(1);
    484     }
    485     FSCloseServer(svr);
    486     exit(0);
    487 }
    488