v20i033: hp2pk - HP font conversion tool, Part03/04
Steve McConnel
steve at txsil.sil.org
Mon Jun 3 12:12:27 AEST 1991
Submitted-by: Steve McConnel <steve at 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 at 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 at 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 at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list