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 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 274static void 275show_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 307static void 308show_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 344usage(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 357int 358main(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