steve@txsil.sil.org (Steve McConnel) (06/03/91)
Submitted-by: Steve McConnel <steve@txsil.sil.org> Posting-number: Volume 20, Issue 33 Archive-name: hp2pk/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 4)." # Contents: hp2pk.c writepk.c # Wrapped by steve@txsil on Thu May 30 10:36:56 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'hp2pk.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hp2pk.c'\" else echo shar: Extracting \"'hp2pk.c'\" \(26111 characters\) sed "s/^X//" >'hp2pk.c' <<'END_OF_FILE' X/* HP2PK.C - Convert HP soft font files to TeX PK and TFM (or PL) files X *************************************************************************** X * X * Sources of information for HP Soft Fonts: X * X * LaserJet Printer Family Technical Reference Manual, X * Hewlett-Packard, January 1986. X * X * LaserJet series II Printer Technical Reference Manual, X * Hewlett-Packard, May 1987. X * X * LaserJet III Technical Reference Manual, Hewlett-Packard, X * March 1990. X * X * HP DeskJet Printer Family Software Developer's Guide, X * Hewlett-Packard, August 1990. (only to interpret values X * of some font header fields--font format is much different X * in general) X * X * Sources of information for TeX font files: X * X * The METAFONTbook by Donald E. Knuth (appendix F) X * X * PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al. X * X * GFtoPK.WEB by Tomas Rokicki X * X *************************************************************************** X * EDIT HISTORY X * 4-Oct-90 SRMc - convert Pascal code left here by Jonathan Kew X * into C, start debugging and adding comments X * 5-Oct-90 SRMc - first successful translation of .SFP file to X * .PK and .PL files X * 6-Oct-90 SRMc - add more comments, convert to dynamic memory X * allocation X * 9-Oct-90 SRMc - add direct output of .TFM file in addition X * to .PL file X * 16-Oct-90 SRMc - fiddle with the user interface X * 19-Oct-90 SRMc - rewrite code for greater modularity and fewer X * global variables (allows for future reuse in X * other "Font A to Font B" conversion programs) X * 20-Oct-90 SRMc - move ctime() call from init_pl_file() to main() X * SRMc - add -b command line option X * 22-Oct-90 SRMc - fight MSDOS cross-compiler code generation bugs X * (or are they obscure features of the C language X * definition? -- some seem to be definite bugs) X * 14-Jan-91 SRMc - add TURBO C patches from Thomas B. Ridgeway X * (ridgeway@blackbox.hacc.washington.edu) X * 15-Jan-91 SRMc - fix for Macintosh Lightspeed THINK C X * 17-Jan-91 SRMc - move version information into PATCHLEVEL.H X * 28-Jan-91 SRMc - add -s option for specifying the width of space, X * as suggested by Chris Paris (cap@cs.cmu.edu) X * 30-Jan-91 SRMc - add -r option for restricting to 7-bit character X * codes in the output file (to support antique X * DVI drivers), as suggested by Kevin A. Streater X * (ba124@uk.ac.city.cs in JANET syntax) X * 31-Jan-91 SRMc - add -h option for getting help X *************************************************************************** X * Copyright 1990, 1991 by the Summer Institute of Linguistics, Inc. X * All rights reserved. X */ X/*#define TURBO_C*/ /* uncomment if using MSDOS TURBO C */ X#include <stdio.h> X#include <ctype.h> X X#ifdef BSD X#include <sys/time.h> Xtypedef long time_t; Xextern time_t time(); Xextern char *memset(), *memcpy(); Xextern int memcmp(); X#include <strings.h> X#define strchr index X#define strrchr rindex X#else X#include <time.h> X#ifdef TURBO_C X#include <mem.h> X#define MSDOS X#else X#ifndef THINK_C /* THINK C includes memxxx() functions in <string.h> */ X#include <memory.h> X#endif X#endif X#include <string.h> X#endif X#ifdef THINK_C X#include <console.h> X#define signed /* keyword not recognized by this compiler */ X#define MACINTOSH X#endif X X#include "patchlevel.h" X#include "sfp.h" X#include "tfm.h" X#include "pk.h" X#include "bitmap.h" X X#ifdef MSDOS X#define DIRSEPCHAR '\\' X#endif X#ifdef UNIX X#define DIRSEPCHAR '/' X#endif X#ifdef MACINTOSH X#define DIRSEPCHAR ':' X#endif X X#define NUL '\0' X X/************************************************************************/ X/* EXTERN DECLARATIONS */ X/************************************************************************/ Xextern void exit(); Xextern long strtol(); Xextern int getopt(), optind; Xextern char *optarg; X X/* from READSFP.C */ Xextern void read_sfp_font_descriptor(); Xextern int read_sfp_character(); X X/* from WRITEPK.C */ Xextern void init_pk_file(), write_pk_character(), end_pk_file(); X X/* from WRITEPL.C */ Xextern void init_pl_file(), write_pl_entry(), end_pl_file(); X X/* from WRITETFM.C */ Xextern void write_tfm_data(); X X/* from MYALLOC.C */ Xextern char *myalloc(), *myrealloc(); Xextern void myfree(); X X/* from FIXNUM.C */ Xextern fixnum str_to_fixnum(); X X/************************************************************************/ X/* GLOBAL VARIABLES */ X/************************************************************************/ X/* X * data from input HP Soft Font (.SFP) file X */ Xstruct hp_font_descriptor hp_font; /* font descriptor */ Xstruct hp_character_descriptor hp_char; /* current character descriptor */ Xstruct character_bitmap bitmap; /* current character bitmap */ Xchar *symbol_set_string = NULL; /* hp_font.symbol_set in English */ X/* X * data for the PK font file X */ Xstruct pk_preamble pk_header; /* font preamble */ Xstruct pk_chardata pk_char; /* current character descriptor */ X/* X * data for the TFM and PL files X */ Xstruct tfm_top top_fm; /* TFM file top information */ Xstruct tfm_header header_fm; /* font descriptor */ Xstruct tfm_param param_fm; /* font parameters */ Xstruct tfm_chardata char_fm[256]; /* array of character metrics */ X/* X * global variables set by the command line options X */ Xfixnum designsize = 0L; /* -d = font design size */ Xfixnum spacewidth = 0L; /* -s = width of basic space in font */ Xlong magnification = 0L; /* -m = font magnification */ Xint verbose = 0; /* -v = program talkativity flag */ Xint density = 0; /* -d = dots per inch of SFP font */ Xshort restrict_7bit = 0; /* -r = restrict to 128 chars, lower/upper */ X#ifdef MACINTOSH Xchar *fileCreator = NULL; /* -z = Macintosh file type */ X#endif Xchar *sfp_filename = NULL; /* <infile> = input SFP font file's name */ Xchar *pk_filename = NULL; /* -p = output PK font file's name */ Xchar *pl_filename = NULL; /* -l = output PL font metric file's name */ Xchar *tfm_filename = NULL; /* -t = output TFM font metric file's name */ X/* X * conversion factor for SFP dimensions to TFM dimensions X * double precision floating point is occasionally useful... X */ Xdouble dot_scale; /* ratio: SFP font dots -> (2**-20) points */ X X/**************************************************************************** X * NAME X * myputs X * ARGUMENTS X * msg - message string X * DESCRIPTION X * Write a string to stdout, inserting linebreaks automatically as needed. X * Also, if the verbose flag is zero, don't print anything. X * RETURN VALUE X * none X */ Xvoid myputs(msg) Xchar *msg; X{ Xstatic int screen_col=0; /* screen column (for linewrap of progress report) */ X Xif (verbose == 0) X return; X Xif (strcmp(msg,"\n")==0) X { X fputs(msg,stdout); X screen_col = 0; X return; X } Xif ((strlen(msg)+screen_col) >= 79) X { X putchar('\n'); X screen_col = 0; X } Xfputs(msg,stdout); Xfflush(stdout); Xscreen_col += strlen(msg); X} X X/**************************************************************************** X * NAME X * change_filetype X * ARGUMENTS X * name - pointer to a filename X * type - pointer to replacement filetype (includes '.') X * DESCRIPTION X * Create a new filename based on the old name and new type. X * RETURN VALUE X * pointer to new filename (allocated with malloc()) X */ Xchar *change_filetype(name, type) Xchar *name; Xchar *type; X{ Xchar *p; Xchar *newname; /* pointer to dynamically allocated buffer for result */ X Xnewname = strcpy( myalloc((unsigned)(strlen(name)+strlen(type)+1)), name); Xp = strchr(newname, DIRSEPCHAR); Xif (p == (char *)NULL) X p = newname; Xp = strrchr(p, '.'); Xif (p == (char *)NULL) X strcat(newname, type); Xelse X strcpy(p, type); Xreturn(newname); X} X X/**************************************************************************** X * NAME X * fix_filename X * ARGUMENTS X * name - filename X * type - default filename type extension X * mode - mode string for fopen() X * DESCRIPTION X * Fix up a filename based on the name and possibly the type. X * Input files may or may not have have a type extension. X * Output files must have a filetype. X * RETURN VALUE X * FILE pointer to open file X */ Xchar *fix_filename(name, type, mode) Xchar *name; Xchar *type; Xchar *mode; X{ Xchar *p; XFILE *fp; X Xif (*mode == 'r') X { X fp = fopen(name, mode); X if (fp == (FILE *)NULL) X { X /* X * see if the user was lazy and omitted the filetype X */ X p = strrchr(name, DIRSEPCHAR); X if (p == (char *)NULL) X p = name; X if (strchr(p, '.') == (char *)NULL) X name = change_filetype(name, type); X } X else X fclose(fp); X return( name ); X } X/* X * see if the user was lazy and omitted the filetype X */ Xp = strrchr(name, DIRSEPCHAR); Xif (p == (char *)NULL) Xp = name; Xif (strchr(p, '.') == (char *)NULL) X name = change_filetype(name, type); Xreturn( name ); X} X X/**************************************************************************** X * NAME X * sfp_to_tfm_header X * ARGUMENTS X * hpf - pointer to SFP font descriptor structure X * sym_set - font symbol set string X * dsize - font design size (fixed-point, 20-bit fraction) X * tp - pointer to TeX font metric header structure X * DESCRIPTION X * Fill in the TeX font metric header information, using the SFP font X * information already known. X * RETURN VALUE X * none X */ Xvoid sfp_to_tfm_header( hpf, sym_set, dsize, tp ) Xstruct hp_font_descriptor *hpf; Xchar *sym_set; Xfixnum dsize; Xstruct tfm_header *tp; X{ Xint i; X Xtp->tfm_checksum = 0L; Xtp->tfm_design_size = dsize; Xi = strlen(sym_set); Xif (i > 39) X i = 39; Xtp->tfm_coding[0] = i; Xmemcpy( &tp->tfm_coding[1], sym_set, i ); X/* X * find the actual length of the stored font name X * if nonzero, store it; otherwise store a default name X */ Xfor ( i = 15 ; X (i >= 0) && isascii(hpf->font_name[i]) && isspace(hpf->font_name[i]) ; X --i ) X ; Xif (i >= 0) X { X tp->tfm_fontid[0] = i+1; X memcpy( &tp->tfm_fontid[1], hpf->font_name, i+1 ); X } Xelse X { X tp->tfm_fontid[0] = 12; X memcpy( &tp->tfm_fontid[1], "HP SOFT FONT", 12 ); X } X Xtp->tfm_7bitsafe = 0; Xtp->tfm_unused[0] = 0; Xtp->tfm_unused[1] = 0; X Xtp->tfm_face = 0; Xif (hp_font.width_type < 0) X tp->tfm_face += CONDENSED; Xelse if (hp_font.width_type > 0) X tp->tfm_face += EXTENDED; Xif (hp_font.style == 1) X tp->tfm_face += ITALIC; Xif (hp_font.stroke_weight < -1) X tp->tfm_face += LIGHT; Xelse if (hp_font.stroke_weight > 1) X tp->tfm_face += BOLD; X} X X/**************************************************************************** X * NAME X * sfp_to_pk X * ARGUMENTS X * cc - current character code X * hpf - pointer to SFP font descriptor structure X * hpc - pointer to SFP font character descriptor structure X * pkc - pointer to PK font character data structure X * DESCRIPTION X * Compute the TeX character information for this SFP character. X * RETURN VALUE X * none X */ Xvoid sfp_to_pk(cc, hpf, hpc, pkc) Xint cc; Xstruct hp_font_descriptor *hpf; Xstruct hp_character_descriptor *hpc; Xstruct pk_chardata *pkc; X{ Xlong qdot_width; Xdouble d_wd; X Xpkc->char_code = cc; X/* X * some compilers need to have these computations split out this way X */ Xif (hpf->spacing == 1) X qdot_width = hpc->delta_x; Xelse X qdot_width = hpf->pitch; Xd_wd = ((dot_scale * qdot_width) / 4.0) * TWO_20th; Xpkc->tfm_width = d_wd; Xpkc->dx = hpc->delta_x; Xpkc->dx <<= 16; /* need separate for 16-bit int systems */ Xpkc->dy = 0L; Xpkc->pixel_width = hpc->character_width; Xpkc->pixel_height = hpc->character_height; Xpkc->hoff = -hpc->left_offset; Xpkc->voff = hpc->top_offset; X} X X/**************************************************************************** X * NAME X * sfp_to_tfm X * ARGUMENTS X * hpf - pointer to SFP font descriptor structure X * hpc - pointer to SFP font character descriptor structure X * pkc - pointer to PK character data structure X * tfc - pointer to TFM character data structure X * tft - pointer to TFM file top information structure X * DESCRIPTION X * Compute the TeX font metric information for this SFP character. X * RETURN VALUE X * none X */ Xvoid sfp_to_tfm(hpf, hpc, pkc, tfc, tft) Xstruct hp_font_descriptor *hpf; Xstruct hp_character_descriptor *hpc; Xstruct pk_chardata *pkc; Xstruct tfm_chardata *tfc; Xstruct tfm_top *tft; X{ Xlong qdot_width; /* width of character in quarter-dots */ Xlong x; Xdouble d_wd, d_ht, d_dp, d_ic; X Xif (hpf->spacing == 1) X qdot_width = hpc->delta_x; Xelse X qdot_width = hpf->pitch; X/* X * some compilers need to have these computations split out this way X */ Xd_wd = ((dot_scale * qdot_width) / 4.0) * TWO_20th; Xd_ht = dot_scale * hpc->top_offset * TWO_20th; X/* X * be extremely careful on conversions involving signed and unsigned short X * (this may look paranoid, but some compilers botch the conversions) X */ Xx = hpc->character_height; Xx -= hpc->top_offset; Xif (x > 0L) X d_dp = dot_scale * x * TWO_20th; Xelse X d_dp = 0.0; Xx = hpc->character_width; Xx *= 4; Xx -= qdot_width; Xif (x > 0L) X d_ic = dot_scale * (x / 4.0) * TWO_20th; Xelse X d_ic = 0.0; X Xtfc->charwd = d_wd; Xtfc->charht = d_ht; Xtfc->chardp = d_dp; Xtfc->charic = d_ic; X Xif ((tfc->charic != 0L) && (hpf->style != 1)) X { X myputs( X "Warning: character in upright font has nonzero italic correction."); X myputs("\n"); X } X/* X * save the smallest and largest character codes encountered X */ Xif (pkc->char_code < tft->tfm_bc) X tft->tfm_bc = pkc->char_code; Xif (pkc->char_code > tft->tfm_ec) X tft->tfm_ec = pkc->char_code; X} X X/**************************************************************************** X * NAME X * sfp_to_tfm_param X * ARGUMENTS X * tfp - pointer to TFM font parameter structure X * hpf - pointer to SFP font descriptor structure X * tfc - pointer to array of TFM character data structures X * tft - pointer to TFM file top information structure X * DESCRIPTION X * Compute the TFM font spacing parameter values. X * RETURN VALUE X * none X */ Xvoid sfp_to_tfm_param(tfp, hpf, tfc, tft) Xstruct tfm_param *tfp; Xstruct hp_font_descriptor *hpf; Xstruct tfm_chardata *tfc; Xstruct tfm_top *tft; X{ Xdouble d; X/* X * first, compute the space parameters X */ Xif (hpf->spacing == 1) X { X if ((tft->tfm_bc <= ' ')&&(tft->tfm_ec >= ' ')&&(tfc[' '].charwd != 0L)) X { X /* X * use space character's width for font spacing parameters X */ X tfp->tfm_space = tfc[' '].charwd; X } X else if (spacewidth != 0L) X { X d = spacewidth; X d /= designsize; X tfp->tfm_space = d * TWO_20th; X } X else if ((tft->tfm_bc <= 'x')&&(tft->tfm_ec >= 'x')&&(tfc['x'].charwd!=0L)) X { X /* X * if no space character, use 'x' character's width for spacing X */ X printf("\ XFont contains no space; using width of x character for font space.\n"); X tfp->tfm_space = tfc['x'].charwd; X } X else X { X /* X * Neither space nor x was available, so we arbitrarily use X * values based on the design size. X */ X printf("\ XFont contains no space or x; using 1/2 design size for font space.\n"); X tfp->tfm_space = 0x00080000; /* == 0.5 as fixnum */ X } X tfp->tfm_space_stretch = tfp->tfm_space / 2; X tfp->tfm_space_shrink = tfp->tfm_space / 3; X tfp->tfm_extra_space = tfp->tfm_space / 3; X } Xelse X { X /* X * mono-space font X */ X d = ((dot_scale * hpf->pitch) / 4.0) * TWO_20th; X tfp->tfm_space = d; X tfp->tfm_space_stretch = 0L; X tfp->tfm_space_shrink = 0L; X tfp->tfm_extra_space = tfp->tfm_space; X } X/* X * we always set the quad value to twice the basic space value X */ Xtfp->tfm_quad = tfp->tfm_space * 2; /* em-space */ X/* X * set the x height (used for accent placement) X */ Xif ((tft->tfm_bc <= 'x') && (tft->tfm_ec >= 'x') && (tfc['x'].charwd != 0L)) X param_fm.tfm_x_height = tfc['x'].charht + tfc['x'].chardp; Xelse X { X printf("Font contains no x; using 1/2 design size for x-height.\n"); X tfp->tfm_x_height = 0x00080000; /* == 0.5 as fixnum */ X } X} X X#ifdef MACINTOSH X/*************************************************************************** X * NAME X * setMacFileType X * ARGUMENTS X * fname - filename string X * type - file type string (4 chars, allcaps) X * creator - file creator string (4 chars, allcaps) X * DESCRIPTION X * For the Macintosh, call the toolbox functions to set the file type and X * creator to the desired values. X * RETURN VALUE X * none X */ Xvoid setMacFileType(fname, type, creator) Xchar *fname; Xchar *type; Xchar *creator; X{ Xchar filename[256]; Xlong err; Xlong refnum; Xstruct FInfo { X char fdType[4]; X char fdCreator[4]; X long fdFlags; X struct { long x; long y; } fdLocation; X long fdFldr; X } finderInfo; Xint i; X Xstrcpy(filename+1,fname); Xfilename[0] = strlen(fname); Xrefnum = 0; Xerr = GetFInfo( filename, refnum, &finderInfo ); Xfor ( i = 0 ; i < 4 ; ++i ) X { X finderInfo.fdType[i] = ' '; X finderInfo.fdCreator[i] = ' '; X } Xfor ( i = 0 ; i < 4 ; ++i ) X { X if (type[i] == NUL) X break; X finderInfo.fdType[i] = type[i]; X } Xfor ( i = 0 ; i < 4 ; ++i ) X { X if (creator[i] == NUL) X break; X finderInfo.fdCreator[i] = creator[i]; X } X#ifdef THINK_C Xerr = SetFInfo( filename, refnum, &finderInfo ); X#endif X} X#endif X X/**************************************************************************** X * NAME X * main X * ARGUMENTS X * argc - number of command line arguments X * argv - pointer to array of command line arguments X * DESCRIPTION X * main procedure for the HP2PK program X * RETURN VALUE X * 0 to indicate success X */ Xint main(argc,argv) Xint argc; Xchar **argv; X{ Xint c; XFILE *sfp_fp = NULL; /* SFP input FILE pointer */ XFILE *pk_fp = NULL; /* PK output FILE pointer */ XFILE *pl_fp = NULL; /* PL output FILE pointer */ XFILE *tfm_fp = NULL; /* TFM output FILE pointer */ Xdouble d; /* used in computing design size */ Xint errflag; /* flag errors in command line parsing */ Xchar buffer[80]; /* scratch buffer for sprintf() output */ Xtime_t job_time; /* time that this job was run, in seconds */ Xstruct tm *tp; /* decoded time that this job was run */ Xchar *date; /* time string for when this job was run */ Xstruct tfm_chardata *cfmp; /* hack for MSDOS compiler bug */ X Xfprintf(stderr, "This is HP2PK, Version %d.%d.%d (%s)\n%s\n", X VERSION, REVISION, PATCHLEVEL, PATCHDATE, COPYRIGHT ); X X#ifdef THINK_C /* this MUST follow the fprintf() for some reason */ X SetWTitle( FrontWindow(), "\pHP2PK" ); X argc = ccommand( &argv ); X#endif X Xtime( &job_time ); Xtp = localtime( &job_time ); X/* X * parse the command line X */ Xerrflag = 0; Xwhile ((c = getopt(argc,argv,"b:d:hl:m:p:r:s:t:vz:")) != EOF) X { X switch (c) X { X case 'b': /* pixel density (bits per inch) */ X density = (int)strtol(optarg, (char **)NULL, 10); X break; X case 'd': /* design size (in points) */ X designsize = str_to_fixnum(optarg); X break; X case 's': /* width of space char (in points) */ X spacewidth = str_to_fixnum(optarg); X break; X case 'm': /* magnification * 1000 */ X magnification = strtol(optarg, (char **)NULL, 10); X break; X case 'r': /* restrict to lower/upper 128 chars */ X if ((*optarg == 'l') || (*optarg == 'u')) X restrict_7bit = *optarg; X else X { X fprintf(stderr, X "The -r option requires either l or u as an argument.\n"); X ++errflag; X } X break; X case 'p': X pk_filename = optarg; X break; X case 'l': X pl_filename = optarg; X break; X case 't': X tfm_filename = optarg; X break; X case 'v': X verbose = 1; X break; X case 'z': X#ifdef MACINTOSH X fileCreator = optarg; X break; X#else X fprintf(stderr,"The -z option is valid only for the Macintosh.\n"); X /* fall through */ X#endif X case 'h': /* fall through */ X default: X ++errflag; X break; X } X } Xif (errflag || (optind >= argc)) X { X fputs("\ XUsage: hp2pk [options] file.sfp\n\ X -b density specify pixel density (dots/inch) of the font\n\ X -d size specify the design size (in points) of the font\n\ X -h ask for help (this display)\n\ X -l file.pl specify the output Property List (PL) file\n\ X -m mag specify the magnification (* 1000) of the font\n\ X", stderr); fputs("\ X -p file.pk specify the output PacKed font (PK) file\n\ X -r {l|u} ask for only lower 128 or only upper 128 characters\n\ X -s sp_width specify the width of a space character (in points)\n\ X -t file.tfm specify the output TeX Font Metric (TFM) file\n\ X -v request verbose progress report output\n\ X", stderr); X#ifdef MACINTOSH X fputs("\ X -z CREA set the hidden Macintosh Creator type for output files.\n\ X This is usually four letters.\n\ X", stderr); X#endif X fputs("\ Xfile.sfp is the input HP Soft Font/Portrait (SFP) file.\n\ X\n\ XIf not specified, hp2pk creates a PK file with the same base name as the\n\ Xinput file, but with a .pk filename extension.\n\ XIf neither a PL nor a TFM file is specified, hp2pk creates a TFM file with\n\ Xthe same base name as the input file, but with a .tfm filename extension.\n\ X", stderr); X fputs("\ XThe default design size is calculated from the font data.\n\ XThe default magnification is 1000. The default pixel density is 300 dpi.\n\ XIf the font contains a space character, its width is always used. Otherwise,\n\ Xthe default width of a space is the width of the 'x' character.\n\ X", stderr); X exit(1); X } X/* X * Open the .SFP file X */ Xsfp_filename = fix_filename( argv[optind], ".sfp", "rb"); Xsfp_fp = fopen(sfp_filename, "rb"); Xif (sfp_fp == (FILE *)NULL) X { X fprintf(stderr, "Cannot open HP soft font file %s\n", sfp_filename); X exit(1); X } Xread_sfp_font_descriptor(sfp_fp, &hp_font, &symbol_set_string, verbose ); Xif (symbol_set_string == (char *)NULL) X symbol_set_string = "UNSPECIFIED"; Xif (magnification == 0L) X magnification = 1000L; Xif (density == 0) X density = 300; /* assume 300 dots per inch */ Xif (designsize == 0L) X { X /* X * Estimate TeX design size based on font height X * Note: 18.0675 = (72.27 points/inch) / 4 quarter-dots/dot X * and hp_font.height is measured in quarter-dots X */ X d = ((18.0675 / density) * hp_font.height) * (1000.0 / magnification) * X TWO_20th; X designsize = d; X printf("Estimated font design size is %.2f pt.\n", d/TWO_20th ); X } X/* X * dot_scale is used to translate dots (pixels) to (2**-20) points X */ Xdot_scale = (72.27 / density) * (1000.0 / magnification) * X (TWO_20th / designsize); Xsfp_to_tfm_header( &hp_font, symbol_set_string, designsize, &header_fm ); Xtop_fm.tfm_bc = 256; /* larger than any possible value */ Xtop_fm.tfm_ec = -1; /* smaller than any possible value */ X/* X * Open the new .PK file X */ Xif (pk_filename == (char *)NULL) X pk_filename = change_filetype(sfp_filename, ".pk"); Xpk_filename = fix_filename( pk_filename, ".pk", "wb"); Xpk_fp = fopen(pk_filename, "wb"); Xif (pk_fp == (FILE *)NULL) X { X fprintf(stderr, "Cannot open output PK font file %s\n", pk_filename ); X exit(1); X } X/* X * if wanted, open the new .PL file X */ Xif (pl_filename != (char *)NULL) X { X pl_filename = fix_filename(pl_filename, ".pl", "w"); X pl_fp = fopen(pl_filename, "w"); X if (pl_fp == (FILE *)NULL) X { X fprintf(stderr, "Cannot open output PL font metric file %s\n", X pl_filename ); X exit(1); X } X } Xelse X pl_fp = (FILE *)NULL; /* signals that we don't output PL */ X/* X * if wanted, open the new .TFM file X */ Xif ((tfm_filename == (char *)NULL) && (pl_filename == (char *)NULL)) X tfm_filename = change_filetype(sfp_filename, ".tfm"); Xif (tfm_filename != (char *)NULL) X { X tfm_filename = fix_filename(tfm_filename, ".tfm", "wb"); X tfm_fp = fopen(tfm_filename, "wb"); X if (tfm_fp == (FILE *)NULL) X { X fprintf(stderr, "Cannot open output TFM font metric file %s\n", X tfm_filename ); X exit(1); X } X } Xsprintf(buffer, "HP2PK %d.%d.%d (%s) output %4d.%02d.%02d %2d:%02d:%02d", X VERSION, REVISION, PATCHLEVEL, PATCHDATE, X tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday, X tp->tm_hour, tp->tm_min, tp->tm_sec ); Xinit_pk_file(pk_fp, buffer, designsize, density, &pk_header); Xif (pl_fp != (FILE *)NULL) X { X date = ctime(&job_time); X date[24] = '\0'; X init_pl_file(pl_fp, "HP2PK", date, &header_fm ); X } X/* X * Process the sfp file to produce the pk file and the pl file X */ Xfor (;;) X { X /* X * process the data for one character X */ X c = read_sfp_character(sfp_fp, &hp_font, &hp_char, &bitmap ); X if (c == -1) X { X if (!feof(sfp_fp)) X puts("\nIgnoring junk at the end of the Soft Font/Portrait file."); X break; X } X if ( ((restrict_7bit == 'l') && (c >= 128)) || X ((restrict_7bit == 'u') && (c < 128)) ) X continue; X X sprintf(buffer, " [%d]", c); X myputs(buffer); /* print the character code on the screen */ X X if ((restrict_7bit == 'u') && (c >= 128)) X c -= 128; /* fix character code for 7-bit output file */ X X sfp_to_pk(c, &hp_font, &hp_char, &pk_char); X write_pk_character(pk_fp, &pk_char, &bitmap); X X cfmp = &char_fm[c]; /* need this to get around MSDOS compiler bug */ X sfp_to_tfm(&hp_font, &hp_char, &pk_char, cfmp, &top_fm); X if (pl_fp != (FILE *)NULL) X write_pl_entry(pl_fp, c, cfmp); X } Xend_pk_file(pk_fp); Xif (verbose) X { X putchar('\n'); X printf( "%6ld bytes read from HP soft font file.\n", ftell(sfp_fp) ); X printf( "%6ld bytes written to packed font file.\n", ftell(pk_fp) ); X } Xfclose(sfp_fp); Xfclose(pk_fp); X#ifdef MACINTOSH /* set Macintosh file type for PK file */ Xif (fileCreator != (char *)NULL) X setMacFileType(pk_filename, "BINA", fileCreator ); X#endif Xsfp_to_tfm_param(¶m_fm, &hp_font, char_fm, &top_fm ); Xif (pl_fp != (FILE *)NULL) X { X end_pl_file(pl_fp, ¶m_fm); X fclose(pl_fp); X#ifdef MACINTOSH /* set Macintosh file type for PL file */ X if (fileCreator != (char *)NULL) X setMacFileType(pl_filename, "TEXT", fileCreator ); X#endif X } X/* X * if wanted, write the .TFM file X */ Xif (tfm_fp != (FILE *)NULL) X { X write_tfm_data(tfm_fp,&top_fm,&header_fm, char_fm,¶m_fm, designsize); X fclose(tfm_fp); X#ifdef MACINTOSH /* set Macintosh file type for TFM file */ X if (fileCreator != (char *)NULL) X setMacFileType(tfm_filename, "BINA", fileCreator ); X#endif X } X Xreturn(0); /* successful execution */ X} END_OF_FILE if test 26111 -ne `wc -c <'hp2pk.c'`; then echo shar: \"'hp2pk.c'\" unpacked with wrong size! fi # end of 'hp2pk.c' fi if test -f 'writepk.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'writepk.c'\" else echo shar: Extracting \"'writepk.c'\" \(19349 characters\) sed "s/^X//" >'writepk.c' <<'END_OF_FILE' X/* WRITEPK.C - Write data to a TeX PK font file X *************************************************************************** X * X * void init_pk_file(fp, comment, dsize, density, pkp) X * FILE *fp; X * char *comment; X * fixnum dsize; X * int density; X * struct pk_preamble *pkp; X * X * void write_pk_character(fp, pkc, bmp) X * FILE *fp; X * struct pk_chardata *pkc; X * struct character_bitmap *bmp; X * X * void end_pk_file(fp) X * FILE *fp; X * X *************************************************************************** X * X * Source of information for TeX PK font files: X * X * GFtoPK.WEB by Tomas Rokicki X * X *************************************************************************** X * EDIT HISTORY X * 19-Oct-90 SRMc - split out from HP2PK.C to improve modularity X * 14-Jan-91 SRMc - add TURBO C patches from Thomas B. Ridgeway X * (ridgeway@blackbox.hacc.washington.edu) X *************************************************************************** X * Copyright 1990, 1991 by the Summer Institute of Linguistics, Inc. X * All rights reserved. X */ X/*#define TURBO_C*/ /* uncomment if using MSDOS TURBO C */ X#include <stdio.h> X#ifdef BSD Xextern int memcmp(); Xextern char *memset(), *memcpy(); X#include <strings.h> X#else X#ifdef TURBO_C X#include <mem.h> X#define MSDOS X#else X#ifndef THINK_C /* THINK C includes memxxx() functions in <string.h> */ X#include <memory.h> X#endif X#endif X#include <string.h> X#endif X#include "pk.h" X#include "bitmap.h" X X#define END_OF_BITMAP 2 /* used in write_pk_character() */ X X/************************************************************************/ X/* EXTERN DECLARATIONS */ X/************************************************************************/ X Xextern void exit(); X X/* from MYALLOC.C */ Xextern char *myalloc(), *myrealloc(); Xextern void myfree(); X X/* from BIGENDIO.C */ Xextern void put_halfword(), put_3_bytes(), put_fullword(); X X/************************************************************************/ X/* STATIC GLOBAL VARIABLES */ X/************************************************************************/ X/* X * powers of two (used in various computations) X */ Xstatic unsigned long power[32] = { X 0x00000001L, 0x00000002L, 0x00000004L, 0x00000008L, X 0x00000010L, 0x00000020L, 0x00000040L, 0x00000080L, X 0x00000100L, 0x00000200L, 0x00000400L, 0x00000800L, X 0x00001000L, 0x00002000L, 0x00004000L, 0x00008000L, X 0x00010000L, 0x00020000L, 0x00040000L, 0x00080000L, X 0x00100000L, 0x00200000L, 0x00400000L, 0x00800000L, X 0x01000000L, 0x02000000L, 0x04000000L, 0x08000000L, X 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L X }; X/* X * globals for pk_nyb() output X */ Xstatic short bit_weight; /* either 1 or 16 */ Xstatic unsigned char output_byte; /* current stored value */ X X/**************************************************************************** X * NAME X * init_pk_file X * ARGUMENTS X * fp - output PK FILE pointer X * comment - comment string for PK file X * dsize - font design size (fixed-point, 20-bit fraction) X * density - dots per inch of the font bitmap X * pkp - pointer to PK file preamble structure X * DESCRIPTION X * Fill in and write the header information for a .PK file. X * RETURN VALUE X * none X */ Xvoid init_pk_file(fp, comment, dsize, density, pkp) XFILE *fp; Xchar *comment; Xfixnum dsize; Xint density; Xstruct pk_preamble *pkp; X{ Xint i; Xdouble d; X/* X * fill in the preamble X */ Xpkp->preamble = PK_PRE; Xpkp->ident = PK_ID; Xpkp->comment_size = strlen(comment); Xmemcpy( pkp->comment, comment, pkp->comment_size ); Xpkp->designsize = dsize; Xpkp->checksum = 0L; Xd = (density / 72.27) * 65536.0; Xpkp->hppp = d; Xpkp->vppp = pkp->hppp; /* assumes square pixels */ X/* X * write the preamble X */ Xputc(pkp->preamble, fp); Xputc(pkp->ident, fp); Xputc(pkp->comment_size, fp); Xfor ( i = 0 ; i < pkp->comment_size ; ++i ) /* one byte at a time */ X putc( pkp->comment[i], fp); /* ensures proper byte order */ Xput_fullword(pkp->designsize, fp); Xput_fullword(pkp->checksum, fp); Xput_fullword(pkp->hppp, fp); Xput_fullword(pkp->vppp, fp); X} X X/**************************************************************************** X * MACRO NAME X * ADD_BIT_COUNT X * ARGUMENTS X * x - value to store in the bit_counts array X * DESCRIPTION X * Add a value to the bit_counts array, increasing the array size if X * necessary. X */ X#define ADD_BIT_COUNT(x) \ Xif (current_bit_count == last_bit_count)\ X { \ X bit_counts = (int *)myrealloc((char *)bit_counts,\ X (unsigned)((max_bit_counts_size+(pkc->pixel_height)) * sizeof(int)));\ X current_bit_count = &bit_counts[max_bit_counts_size];\ X max_bit_counts_size += (pkc->pixel_height);\ X last_bit_count = &bit_counts[max_bit_counts_size];\ X } \ X*current_bit_count++ = (x) X X/**************************************************************************** X * NAME X * static pk_nyb X * ARGUMENTS X * a - 4-bit "nybble" for output X * fp - output PK FILE pointer X * DESCRIPTION X * Write a 4-bit "nybble" to the PK file, storing intermediate values in X * output_byte and using bit_weight as a flag. X * RETURN VALUE X * none X */ Xstatic void pk_nyb(a,fp) Xunsigned char a; XFILE *fp; X{ Xif (bit_weight == 16) X { X output_byte = (a << 4) & 0xF0; X bit_weight = 1; X } Xelse X { X putc( (output_byte + (a & 0xF)) & 0xFF, fp);; X bit_weight = 16; X } X} X X/**************************************************************************** X * NAME X * write_pk_character X * ARGUMENTS X * fp - output PK FILE pointer X * pkc - pointer to PK character data structure X * bmp - pointer to character bitmap data X * DESCRIPTION X * Write one character's info to the PK file. X * This function converts a raw bitmap into the dense format used by PK X * files. (algorithms courtesy of PXtoPK and GFtoPK) X * RETURN VALUE X * none X */ Xvoid write_pk_character(fp, pkc, bmp) XFILE *fp; Xstruct pk_chardata *pkc; Xstruct character_bitmap *bmp; X{ X/* (this is largely translated borrowed code from GFtoPK, which is why X * there aren't too many comments at times */ Xlong best_packet_length; Xint i, j, k; Xint count; Xint bit, oldbit; Xlong curr_word = 0L; Xint bit_ptr; Xint bit_mod_32 = 0; Xlong *prast; Xlong *end_raster; Xint dyn_f; Xlong deriv[13+1]; /* array[1..13] of integer */ Xint first_on; Xint state; Xint on; Xint h_bit; Xint p_bit; Xint r_on, s_on; Xint r_count, s_count; Xint max_2; Xlong pred_pk_loc; Xint buff; X Xstatic long *zero_row = NULL; Xstatic long *ones_row = NULL; Xstatic int max_row_size = 0; X Xstatic int *row_repeats = NULL; Xstatic int max_column_size = 0; Xint *cur_repeat; Xint repeat_flag; X Xstatic int *bit_counts = NULL; Xstatic int max_bit_counts_size = 0; Xint *current_bit_count, *first_bit_count, *last_bit_count; Xint *r_bit_count, *s_bit_count; X/* X * set up an all-zeros row and an all-ones row X */ Xif (bmp->raster_width > max_row_size) X { X max_row_size = bmp->raster_width; X if (zero_row) X myfree(zero_row); X zero_row = (long *)myalloc( (unsigned)(4 * max_row_size) ); X memset( zero_row, 0x00, 4 * max_row_size ); X if (ones_row) X myfree(ones_row); X ones_row = (long *)myalloc( (unsigned)(4 * max_row_size) ); X } Xmemset( ones_row, 0xFF, 4 * bmp->raster_width ); Xi = pkc->pixel_width % 32; Xif (i == 1) X ones_row[bmp->raster_width - 1] = power[31]; /* MAXLONGINT */ Xelse if (i > 1) X ones_row[bmp->raster_width - 1] = -power[32-i]; X/* X * set markers for runs of identical rows of bits X */ Xif (((pkc->pixel_height)+1) > max_column_size) X { X if (row_repeats) X myfree(row_repeats); X max_column_size = (pkc->pixel_height) + 1; X row_repeats = (int *)myalloc( (unsigned)(max_column_size * sizeof(int)) ); X } Xfor ( prast = bmp->raster, i = 0 ; X i < (pkc->pixel_height)-1 ; X ++i, prast += bmp->raster_width ) X { X if (memcmp( prast, zero_row, bmp->raster_width * 4) == 0) X row_repeats[i] = 0; /* skip all-zero rows */ X else if (memcmp( prast, ones_row, bmp->raster_width * 4) == 0) X row_repeats[i] = 0; /* skip all-one rows */ X else if (memcmp(prast, prast+bmp->raster_width, bmp->raster_width * 4)==0) X row_repeats[i] = 1; /* mark this equal to next row */ X else X row_repeats[i] = 0; /* not equal to next row... */ X } Xrow_repeats[(pkc->pixel_height)-1] = 0; /* last row can't equal "next" */ X/* X * convert boolean markers of repeated rows into repeat counts X */ Xfor ( i = 0 ; i < (pkc->pixel_height) ; i = k + 1 ) X { X k = i; X while ((row_repeats[k] == 1) && (k < (pkc->pixel_height))) X ++k; X row_repeats[i] = k - i; X } Xrow_repeats[(pkc->pixel_height)] = 0; /* to simplify bookkeepping */ X/* X * create the bit counts for each row X */ Xif (((pkc->pixel_height) * 5) > max_bit_counts_size) X { X if (bit_counts) X myfree(bit_counts); X max_bit_counts_size = (pkc->pixel_height) * 5; X bit_counts = (int *)myalloc((unsigned)(max_bit_counts_size * sizeof(int))); X } Xlast_bit_count = &bit_counts[max_bit_counts_size]; Xprast = bmp->raster; Xcur_repeat = row_repeats; Xcurrent_bit_count = bit_counts; Xrepeat_flag = 0; Xend_raster = &(bmp->raster[(pkc->pixel_height) * bmp->raster_width]); Xcount = 0; Xfor ( bit_ptr = pkc->pixel_width, oldbit = 0 ; oldbit != END_OF_BITMAP ; ++bit_ptr ) X { X if (bit_ptr == pkc->pixel_width) X { X /* X * time to try the next row of this bitmap X */ X if (*cur_repeat > 0) X { X /* X * skip over rows that are repeated X */ X repeat_flag = *cur_repeat; X cur_repeat += repeat_flag; X prast += bmp->raster_width * repeat_flag; X } X ++cur_repeat; X bit_mod_32 = 0; X bit_ptr = 0; X } X --bit_mod_32; X if (bit_mod_32 == -1) X { X /* X * time to get the next longword of this row X */ X bit_mod_32 = 31; X curr_word = *prast++; X } X if (prast > end_raster) X bit = END_OF_BITMAP; /* at end of character bitmap */ X else if (curr_word & power[bit_mod_32]) X { X bit = 1; X curr_word ^= power[bit_mod_32]; X } X else X bit = 0; X if (bit == oldbit) X ++count; X else X { X ADD_BIT_COUNT( count ); X count = 1; X oldbit = bit; X if (repeat_flag > 0) X { X ADD_BIT_COUNT( -repeat_flag ); X repeat_flag = 0; X } X } X } XADD_BIT_COUNT( 0 ); XADD_BIT_COUNT( 0 ); X/* X * Quoting from GFTOPK.WEB, from which the following code was adapted: X * X * Here is another piece of rather intricate code. Here we determine the X * smallest size in which we can pack the data, calculating |dyn_f| in X * the process. To do this, we calculate the size required if |dyn_f| is X * 0, and put this in |pkc->packet_length|. Then, we calculate the changes in the X * size for each increment of |dyn_f|, and stick these values in the X * |deriv| array. Finally, we scan through this array, and find the X * final minimum value, which we then use to send the character data. X */ Xfor ( i = 0 ; i <= 13 ; ++i ) X deriv[i] = 0; Xfirst_on = (bit_counts[0] == 0); Xif (first_on) X first_bit_count = &bit_counts[1]; Xelse X first_bit_count = &bit_counts[0]; Xpkc->packet_length = 0L; Xfor ( current_bit_count = first_bit_count ; *current_bit_count != 0 ; ) X { X /* Quoting again from GFTOPK.WEB, except for changes in variable names: X * X * When we enter this module, we have a count, at X * |*current_bit_count|. First, we add to the |pkc->packet_length| the X * number of nybbles that this count would require, assuming X * |dyn_f| to be zero. Since when |dyn_f| is zero, there are no X * one nybble counts, we simply check the two-nybble counts, and X * then the extensible counts. X * X * Next, we take the count value and determine the value of X * |dyn_f| (if any) that would cause this count to take either X * more or less nybbles. If a valid value for |dyn_f| exists in X * this range, we accumulate this change in the |deriv| array. X * X * We know that a repeat count of one will not change the length X * of the raster representation, no matter what |dyn_f| is, X * because it is always represented by the nybble 15, so we do X * that as a special case. X */ X j = *current_bit_count++; X if (j == -1) X ++pkc->packet_length; /* we have a row repeat count of 1 */ X else X { X if (j < 0) X { X ++pkc->packet_length; X j = -j; /* get positive row count */ X } X if (j < 209) /* 208 = 13 * 16 (13 is max dyn_f) */ X pkc->packet_length += 2; X else X { X k = j - 193; /* 192 = 12 * 16 */ X while (k >= 16) X { X k = k / 16; X pkc->packet_length += 2; X } X ++pkc->packet_length; X } X if (j < 14) X --deriv[j]; X else if (j < 209) X ++deriv[(223-j)/15]; X else X { X k = 16; X while ((k * 16) < (j + 3)) X k = k * 16; X if ((j - k) <= 192) X deriv[(207-j+k)/15] += 2; X } X } X } X/* X * set best_packet_length to the best size for the given value of dyn_f X */ Xbest_packet_length = pkc->packet_length; Xdyn_f = 0; Xfor ( i = 1 ; i <= 13 ; ++i ) X { X pkc->packet_length += deriv[i]; X if (pkc->packet_length <= best_packet_length) X { X best_packet_length = pkc->packet_length; X dyn_f = i; X } X } Xpkc->packet_length = (best_packet_length + 1) / 2; /* convert from nybble to byte size */ Xif ( (pkc->packet_length > (((pkc->pixel_height) * pkc->pixel_width + 7) / 8)) || X (((pkc->pixel_height) * pkc->pixel_width) == 0) ) X { X /* X * raw bitmap is the best we can do -- no compression possible X */ X pkc->packet_length = ((pkc->pixel_height) * pkc->pixel_width + 7) / 8; X dyn_f = 14; X } X/* X * write character preamble X */ Xpkc->flag_byte = dyn_f << 4; Xif (first_on) X pkc->flag_byte |= 0x08; Xif ( (pkc->tfm_width > 0xFFFFFFL) || (pkc->tfm_width < 0L) || X (pkc->dx < 0L) || (pkc->packet_length > 196579L) || X (pkc->pixel_width > 0xFFFFL) || (pkc->pixel_height > 0xFFFFL) || X (pkc->hoff > 32767L) || (pkc->hoff < -32768L) || X (pkc->voff > 32767L) || (pkc->voff < -32768L) ) X { X pkc->packet_length += 28L; X pkc->flag_byte |= 0x07; X /* X * write long character preamble X */ X putc(pkc->flag_byte & 0xFF, fp); X put_fullword(pkc->packet_length, fp); X put_fullword(pkc->char_code, fp); X pred_pk_loc = ftell(fp) + pkc->packet_length; X put_fullword(pkc->tfm_width, fp); X put_fullword(pkc->dx, fp); X put_fullword(pkc->dy, fp); X put_fullword((long)pkc->pixel_width, fp); X put_fullword((long)(pkc->pixel_height), fp); X put_fullword(pkc->hoff, fp); X put_fullword(pkc->voff, fp); X } Xelse if ((pkc->dx > 0xFF0000L) || (pkc->packet_length > 1016) || X (pkc->pixel_width > 255) || (pkc->pixel_height > 255) || X (pkc->hoff > 127) || (pkc->hoff < -128) || X (pkc->voff > 127) || (pkc->voff < -128) ) X { X pkc->packet_length += 13L; X pkc->flag_byte |= (pkc->packet_length >> 16) | 4; X /* X * write two-byte short character preamble X */ X putc(pkc->flag_byte & 0xFF, fp); X put_halfword((unsigned short)(pkc->packet_length & 0xFFFF), fp); X putc((unsigned short)pkc->char_code & 0xFF, fp); X pred_pk_loc = ftell(fp) + pkc->packet_length; X put_3_bytes(pkc->tfm_width, fp); X put_halfword((unsigned short)(pkc->dx >> 16), fp); X put_halfword((unsigned short)pkc->pixel_width, fp); X put_halfword((unsigned short)(pkc->pixel_height), fp); X put_halfword((unsigned short)pkc->hoff, fp); X put_halfword((unsigned short)pkc->voff, fp); X } Xelse X { X pkc->packet_length += 8L; X pkc->flag_byte |= pkc->packet_length >> 8; X /* X * write one-byte short character preamble X */ X putc(pkc->flag_byte & 0xFF, fp); X putc((unsigned char)(pkc->packet_length & 0xFF), fp); X putc((unsigned char)pkc->char_code & 0xFF, fp); X pred_pk_loc = ftell(fp) + pkc->packet_length; X put_3_bytes(pkc->tfm_width, fp); X putc((unsigned char)(pkc->dx >> 16) & 0xFF, fp); X putc((unsigned char)pkc->pixel_width & 0xFF, fp); X putc((unsigned char)(pkc->pixel_height) & 0xFF, fp); X putc((unsigned char)pkc->hoff & 0xFF, fp); X putc((unsigned char)pkc->voff & 0xFF, fp); X } Xif (dyn_f != 14) X { X /* X * send compressed format X */ X bit_weight = 16; X max_2 = 208 - 15 * dyn_f; /* set max value for two nybbles */ X current_bit_count = first_bit_count; X while (*current_bit_count != 0) X { X j = *current_bit_count++; X if (j == -1) X pk_nyb(15,fp); /* send special row repeat count = 1 */ X else X { X if (j < 0) X { X pk_nyb(14,fp); /* send row repeat flag */ X j = -j; /* convert to positive count */ X } X if (j <= dyn_f) X pk_nyb(j,fp); /* small, one-nybble value */ X else if (j <= max_2) X { /* two-nybble value */ X j = j - dyn_f - 1; X pk_nyb(j / 16 + dyn_f + 1, fp); X pk_nyb(j % 16, fp); X } X else X { /* multi-nybble value */ X j = j - max_2 + 15; X k = 16; X while (k <= j) X { X k = k * 16; X pk_nyb(0,fp); X } X while (k > 1) X { X k = k / 16; X pk_nyb(j / k, fp); X j = j % k; X } X } X } X } X if (bit_weight != 16) X putc(output_byte & 0xFF, fp); /* pad to byte boundary */ X } Xelse X { X /* X * send raw bit map X */ X buff = 0; X p_bit = 8; X current_bit_count = first_bit_count; X r_bit_count = s_bit_count = bit_counts; X h_bit = pkc->pixel_width; X on = !first_on; X state = r_on = s_on = 0; X count = r_count = s_count = 0; X repeat_flag = 0; X while ((*current_bit_count != 0) || state || (count > 0)) X { X if (state) X { X count = r_count; X current_bit_count = r_bit_count; X on = r_on; X --repeat_flag; X } X else X { X r_count = count; X r_bit_count = current_bit_count; X r_on = on; X } X /* X * send one row by bits X */ X do { X if (count == 0) X { X if (*current_bit_count < 0) X { X if (!state) X repeat_flag = -(*current_bit_count); X ++current_bit_count; X } X count = *current_bit_count++; X on = !on; X } X if ((count >= p_bit) && (p_bit < h_bit)) X { X if (on) X buff = buff + power[p_bit] - 1; X putc(buff & 0xFF, fp); X buff = 0; X h_bit = h_bit - p_bit; X count = count - p_bit; X p_bit = 8; X } X else if ((count < p_bit) && (count < h_bit)) X { X if (on) X buff = buff + power[p_bit] - power[p_bit-count]; X p_bit = p_bit - count; X h_bit = h_bit - count; X count = 0; X } X else X { X if (on) X buff = buff + power[p_bit] - power[p_bit-h_bit]; X count = count - h_bit; X p_bit = p_bit - h_bit; X h_bit = pkc->pixel_width; X if (p_bit == 0) X { X putc(buff & 0xFF, fp); X buff = 0; X p_bit = 8; X } X } X } while (h_bit != pkc->pixel_width); X if (state && (repeat_flag == 0)) X { X count = s_count; X current_bit_count = s_bit_count; X on = s_on; X state = 0; X } X else if (!state && (repeat_flag > 0)) X { X s_count = count; X s_bit_count = current_bit_count; X s_on = on; X state = 1; X } X } X if (p_bit != 8) X putc(buff & 0xFF, fp); X } Xif (pred_pk_loc != ftell(fp)) X { X fflush(stdout); X fprintf(stderr, "\nERROR: Bad predicted character length.\n"); X exit(1); X } X} X X/**************************************************************************** X * NAME X * end_pk_file X * ARGUMENTS X * fp - output PK FILE pointer X * DESCRIPTION X * Write the postamble for the .PK file. X * RETURN VALUE X * none X */ Xvoid end_pk_file(fp) XFILE *fp; X{ Xputc(PK_POST & 0xFF, fp); Xwhile (ftell(fp) % 4 != 0) X putc(PK_NO_OP & 0xFF, fp); X} END_OF_FILE if test 19349 -ne `wc -c <'writepk.c'`; then echo shar: \"'writepk.c'\" unpacked with wrong size! fi # end of 'writepk.c' fi echo shar: End of archive 3 \(of 4\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.