home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume20 / hp2pk / part03 / hp2pk.c next >
C/C++ Source or Header  |  1991-06-02  |  26KB  |  918 lines

  1. /*  HP2PK.C - Convert HP soft font files to TeX PK and TFM (or PL) files
  2.  ***************************************************************************
  3.  *
  4.  *    Sources of information for HP Soft Fonts:
  5.  *
  6.  *        LaserJet Printer Family Technical Reference Manual,
  7.  *        Hewlett-Packard, January 1986.
  8.  *
  9.  *        LaserJet series II Printer Technical Reference Manual,
  10.  *        Hewlett-Packard, May 1987.
  11.  *
  12.  *        LaserJet III Technical Reference Manual, Hewlett-Packard,
  13.  *        March 1990.
  14.  *
  15.  *        HP DeskJet Printer Family Software Developer's Guide,
  16.  *        Hewlett-Packard, August 1990.  (only to interpret values
  17.  *        of some font header fields--font format is much different
  18.  *        in general)
  19.  *
  20.  *    Sources of information for TeX font files:
  21.  *
  22.  *        The METAFONTbook by Donald E. Knuth (appendix F)
  23.  *
  24.  *        PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al.
  25.  *
  26.  *        GFtoPK.WEB by Tomas Rokicki
  27.  *
  28.  ***************************************************************************
  29.  *    EDIT HISTORY
  30.  *     4-Oct-90    SRMc - convert Pascal code left here by Jonathan Kew
  31.  *                into C, start debugging and adding comments
  32.  *     5-Oct-90    SRMc - first successful translation of .SFP file to
  33.  *                .PK and .PL files
  34.  *     6-Oct-90    SRMc - add more comments, convert to dynamic memory
  35.  *                allocation
  36.  *     9-Oct-90    SRMc - add direct output of .TFM file in addition
  37.  *                to .PL file
  38.  *    16-Oct-90    SRMc - fiddle with the user interface
  39.  *    19-Oct-90    SRMc - rewrite code for greater modularity and fewer
  40.  *                global variables (allows for future reuse in
  41.  *                other "Font A to Font B" conversion programs)
  42.  *    20-Oct-90    SRMc - move ctime() call from init_pl_file() to main()
  43.  *            SRMc - add -b command line option
  44.  *    22-Oct-90    SRMc - fight MSDOS cross-compiler code generation bugs
  45.  *                (or are they obscure features of the C language
  46.  *                definition? -- some seem to be definite bugs)
  47.  *    14-Jan-91    SRMc - add TURBO C patches from Thomas B. Ridgeway
  48.  *                (ridgeway@blackbox.hacc.washington.edu)
  49.  *    15-Jan-91    SRMc - fix for Macintosh Lightspeed THINK C
  50.  *    17-Jan-91    SRMc - move version information into PATCHLEVEL.H
  51.  *    28-Jan-91    SRMc - add -s option for specifying the width of space,
  52.  *                as suggested by Chris Paris (cap@cs.cmu.edu)
  53.  *    30-Jan-91    SRMc - add -r option for restricting to 7-bit character
  54.  *                codes in the output file (to support antique
  55.  *                DVI drivers), as suggested by Kevin A. Streater
  56.  *                (ba124@uk.ac.city.cs in JANET syntax)
  57.  *    31-Jan-91    SRMc - add -h option for getting help
  58.  ***************************************************************************
  59.  * Copyright 1990, 1991 by the Summer Institute of Linguistics, Inc.
  60.  * All rights reserved.
  61.  */
  62. /*#define TURBO_C*/        /* uncomment if using MSDOS TURBO C */
  63. #include <stdio.h>
  64. #include <ctype.h>
  65.  
  66. #ifdef BSD
  67. #include <sys/time.h>
  68. typedef long time_t;
  69. extern time_t time();
  70. extern char *memset(), *memcpy();
  71. extern int memcmp();
  72. #include <strings.h>
  73. #define strchr index
  74. #define strrchr rindex
  75. #else
  76. #include <time.h>
  77. #ifdef TURBO_C
  78. #include <mem.h>
  79. #define MSDOS
  80. #else
  81. #ifndef THINK_C        /* THINK C includes memxxx() functions in <string.h> */
  82. #include <memory.h>
  83. #endif
  84. #endif
  85. #include <string.h>
  86. #endif
  87. #ifdef THINK_C
  88. #include <console.h>
  89. #define signed        /* keyword not recognized by this compiler */
  90. #define MACINTOSH
  91. #endif
  92.  
  93. #include "patchlevel.h"
  94. #include "sfp.h"
  95. #include "tfm.h"
  96. #include "pk.h"
  97. #include "bitmap.h"
  98.  
  99. #ifdef MSDOS
  100. #define DIRSEPCHAR '\\'
  101. #endif
  102. #ifdef UNIX
  103. #define DIRSEPCHAR '/'
  104. #endif
  105. #ifdef MACINTOSH
  106. #define DIRSEPCHAR ':'
  107. #endif
  108.  
  109. #define NUL '\0'
  110.  
  111. /************************************************************************/
  112. /*               EXTERN DECLARATIONS                */
  113. /************************************************************************/
  114. extern void exit();
  115. extern long strtol();
  116. extern int getopt(), optind;
  117. extern char *optarg;
  118.  
  119. /* from READSFP.C */
  120. extern void read_sfp_font_descriptor();
  121. extern int read_sfp_character();
  122.  
  123. /* from WRITEPK.C */
  124. extern void init_pk_file(), write_pk_character(), end_pk_file();
  125.  
  126. /* from WRITEPL.C */
  127. extern void init_pl_file(), write_pl_entry(), end_pl_file();
  128.  
  129. /* from WRITETFM.C */
  130. extern void write_tfm_data();
  131.  
  132. /* from MYALLOC.C */
  133. extern char *myalloc(), *myrealloc();
  134. extern void myfree();
  135.  
  136. /* from FIXNUM.C */
  137. extern fixnum str_to_fixnum();
  138.  
  139. /************************************************************************/
  140. /*                GLOBAL VARIABLES                */
  141. /************************************************************************/
  142. /*
  143.  *  data from input HP Soft Font (.SFP) file
  144.  */
  145. struct hp_font_descriptor hp_font;    /* font descriptor */
  146. struct hp_character_descriptor hp_char;    /* current character descriptor */
  147. struct character_bitmap bitmap;        /* current character bitmap */
  148. char *symbol_set_string = NULL;        /* hp_font.symbol_set in English */
  149. /*
  150.  *  data for the PK font file
  151.  */
  152. struct pk_preamble pk_header;        /* font preamble */
  153. struct pk_chardata pk_char;        /* current character descriptor */
  154. /*
  155.  *  data for the TFM and PL files
  156.  */
  157. struct tfm_top      top_fm;        /* TFM file top information */
  158. struct tfm_header   header_fm;        /* font descriptor */
  159. struct tfm_param    param_fm;        /* font parameters */
  160. struct tfm_chardata char_fm[256];    /* array of character metrics */
  161. /*
  162.  *  global variables set by the command line options
  163.  */
  164. fixnum designsize    = 0L;    /* -d = font design size */
  165. fixnum spacewidth    = 0L;    /* -s = width of basic space in font */
  166. long   magnification = 0L;    /* -m = font magnification */
  167. int    verbose       = 0;    /* -v = program talkativity flag */
  168. int    density       = 0;    /* -d = dots per inch of SFP font */
  169. short restrict_7bit = 0;    /* -r = restrict to 128 chars, lower/upper */
  170. #ifdef MACINTOSH
  171. char *fileCreator = NULL;    /* -z = Macintosh file type  */
  172. #endif
  173. char *sfp_filename = NULL;    /* <infile> = input SFP font file's name */
  174. char *pk_filename  = NULL;    /* -p = output PK font file's name */
  175. char *pl_filename  = NULL;    /* -l = output PL font metric file's name */
  176. char *tfm_filename = NULL;    /* -t = output TFM font metric file's name */
  177. /*
  178.  *  conversion factor for SFP dimensions to TFM dimensions
  179.  *  double precision floating point is occasionally useful...
  180.  */
  181. double dot_scale;        /* ratio: SFP font dots -> (2**-20) points */
  182.  
  183. /****************************************************************************
  184.  * NAME
  185.  *    myputs
  186.  * ARGUMENTS
  187.  *    msg - message string
  188.  * DESCRIPTION
  189.  *    Write a string to stdout, inserting linebreaks automatically as needed.
  190.  *    Also, if the verbose flag is zero, don't print anything.
  191.  * RETURN VALUE
  192.  *    none
  193.  */
  194. void myputs(msg)
  195. char *msg;
  196. {
  197. static int screen_col=0; /* screen column (for linewrap of progress report) */
  198.  
  199. if (verbose == 0)
  200.     return;
  201.  
  202. if (strcmp(msg,"\n")==0)
  203.     {
  204.     fputs(msg,stdout);
  205.     screen_col = 0;
  206.     return;
  207.     }
  208. if ((strlen(msg)+screen_col) >= 79)
  209.     {
  210.     putchar('\n');
  211.     screen_col = 0;
  212.     }
  213. fputs(msg,stdout);
  214. fflush(stdout);
  215. screen_col += strlen(msg);
  216. }
  217.  
  218. /****************************************************************************
  219.  * NAME
  220.  *    change_filetype
  221.  * ARGUMENTS
  222.  *    name - pointer to a filename
  223.  *    type - pointer to replacement filetype (includes '.')
  224.  * DESCRIPTION
  225.  *    Create a new filename based on the old name and new type.
  226.  * RETURN VALUE
  227.  *    pointer to new filename (allocated with malloc())
  228.  */
  229. char *change_filetype(name, type)
  230. char *name;
  231. char *type;
  232. {
  233. char *p;
  234. char *newname;    /* pointer to dynamically allocated buffer for result */
  235.  
  236. newname = strcpy( myalloc((unsigned)(strlen(name)+strlen(type)+1)), name);
  237. p = strchr(newname, DIRSEPCHAR);
  238. if (p == (char *)NULL)
  239.     p = newname;
  240. p = strrchr(p, '.');
  241. if (p == (char *)NULL)
  242.     strcat(newname, type);
  243. else
  244.     strcpy(p, type);
  245. return(newname);
  246. }
  247.  
  248. /****************************************************************************
  249.  * NAME
  250.  *    fix_filename
  251.  * ARGUMENTS
  252.  *    name - filename
  253.  *    type - default filename type extension
  254.  *    mode - mode string for fopen()
  255.  * DESCRIPTION
  256.  *    Fix up a filename based on the name and possibly the type.
  257.  *    Input files may or may not have have a type extension.
  258.  *    Output files must have a filetype.
  259.  * RETURN VALUE
  260.  *    FILE pointer to open file
  261.  */
  262. char *fix_filename(name, type, mode)
  263. char *name;
  264. char *type;
  265. char *mode;
  266. {
  267. char *p;
  268. FILE *fp;
  269.  
  270. if (*mode == 'r')
  271.     {
  272.     fp = fopen(name, mode);
  273.     if (fp == (FILE *)NULL)
  274.     {
  275.     /*
  276.      * see if the user was lazy and omitted the filetype
  277.      */
  278.     p = strrchr(name, DIRSEPCHAR);
  279.     if (p == (char *)NULL)
  280.     p = name;
  281.     if (strchr(p, '.') == (char *)NULL)
  282.         name = change_filetype(name, type);
  283.     }
  284.     else
  285.     fclose(fp);
  286.     return( name );
  287.     }
  288. /*
  289.  * see if the user was lazy and omitted the filetype
  290.  */
  291. p = strrchr(name, DIRSEPCHAR);
  292. if (p == (char *)NULL)
  293. p = name;
  294. if (strchr(p, '.') == (char *)NULL)
  295.     name = change_filetype(name, type);
  296. return( name );
  297. }
  298.  
  299. /****************************************************************************
  300.  * NAME
  301.  *    sfp_to_tfm_header
  302.  * ARGUMENTS
  303.  *    hpf     - pointer to SFP font descriptor structure
  304.  *    sym_set - font symbol set string
  305.  *    dsize   - font design size (fixed-point, 20-bit fraction)
  306.  *    tp      - pointer to TeX font metric header structure
  307.  * DESCRIPTION
  308.  *    Fill in the TeX font metric header information, using the SFP font
  309.  *    information already known.
  310.  * RETURN VALUE
  311.  *    none
  312.  */
  313. void sfp_to_tfm_header( hpf, sym_set, dsize, tp )
  314. struct hp_font_descriptor *hpf;
  315. char *sym_set;
  316. fixnum dsize;
  317. struct tfm_header *tp;
  318. {
  319. int i;
  320.  
  321. tp->tfm_checksum = 0L;
  322. tp->tfm_design_size = dsize;
  323. i = strlen(sym_set);
  324. if (i > 39)
  325.     i = 39;
  326. tp->tfm_coding[0] = i;
  327. memcpy( &tp->tfm_coding[1], sym_set, i );
  328. /*
  329.  *  find the actual length of the stored font name
  330.  *  if nonzero, store it; otherwise store a default name
  331.  */
  332. for (    i = 15 ;
  333.     (i >= 0) && isascii(hpf->font_name[i]) && isspace(hpf->font_name[i]) ;
  334.     --i )
  335.     ;
  336. if (i >= 0)
  337.     {
  338.     tp->tfm_fontid[0] = i+1;
  339.     memcpy( &tp->tfm_fontid[1], hpf->font_name, i+1 );
  340.     }
  341. else
  342.     {
  343.     tp->tfm_fontid[0] = 12;
  344.     memcpy( &tp->tfm_fontid[1], "HP SOFT FONT", 12 );
  345.     }
  346.  
  347. tp->tfm_7bitsafe = 0;
  348. tp->tfm_unused[0] = 0;
  349. tp->tfm_unused[1] = 0;
  350.  
  351. tp->tfm_face = 0;
  352. if (hp_font.width_type < 0)
  353.     tp->tfm_face += CONDENSED;
  354. else if (hp_font.width_type > 0)
  355.     tp->tfm_face += EXTENDED;
  356. if (hp_font.style == 1)
  357.     tp->tfm_face += ITALIC;
  358. if (hp_font.stroke_weight < -1)
  359.     tp->tfm_face += LIGHT;
  360. else if (hp_font.stroke_weight > 1)
  361.     tp->tfm_face += BOLD;
  362. }
  363.  
  364. /****************************************************************************
  365.  * NAME
  366.  *    sfp_to_pk
  367.  * ARGUMENTS
  368.  *    cc  - current character code
  369.  *    hpf - pointer to SFP font descriptor structure
  370.  *    hpc - pointer to SFP font character descriptor structure
  371.  *    pkc - pointer to PK font character data structure
  372.  * DESCRIPTION
  373.  *    Compute the TeX character information for this SFP character.
  374.  * RETURN VALUE
  375.  *    none
  376.  */
  377. void sfp_to_pk(cc, hpf, hpc, pkc)
  378. int cc;
  379. struct hp_font_descriptor *hpf;
  380. struct hp_character_descriptor *hpc;
  381. struct pk_chardata *pkc;
  382. {
  383. long qdot_width;
  384. double d_wd;
  385.  
  386. pkc->char_code = cc;
  387. /*
  388.  *  some compilers need to have these computations split out this way
  389.  */
  390. if (hpf->spacing == 1)
  391.     qdot_width = hpc->delta_x;
  392. else
  393.     qdot_width = hpf->pitch;
  394. d_wd = ((dot_scale * qdot_width) / 4.0) * TWO_20th;
  395. pkc->tfm_width = d_wd;
  396. pkc->dx = hpc->delta_x;
  397. pkc->dx <<= 16;            /* need separate for 16-bit int systems */
  398. pkc->dy = 0L;
  399. pkc->pixel_width  = hpc->character_width;
  400. pkc->pixel_height = hpc->character_height;
  401. pkc->hoff = -hpc->left_offset;
  402. pkc->voff = hpc->top_offset;
  403. }
  404.  
  405. /****************************************************************************
  406.  * NAME
  407.  *    sfp_to_tfm
  408.  * ARGUMENTS
  409.  *    hpf - pointer to SFP font descriptor structure
  410.  *    hpc - pointer to SFP font character descriptor structure
  411.  *    pkc - pointer to PK character data structure
  412.  *    tfc - pointer to TFM character data structure
  413.  *    tft - pointer to TFM file top information structure
  414.  * DESCRIPTION
  415.  *    Compute the TeX font metric information for this SFP character.
  416.  * RETURN VALUE
  417.  *    none
  418.  */
  419. void sfp_to_tfm(hpf, hpc, pkc, tfc, tft)
  420. struct hp_font_descriptor *hpf;
  421. struct hp_character_descriptor *hpc;
  422. struct pk_chardata *pkc;
  423. struct tfm_chardata *tfc;
  424. struct tfm_top *tft;
  425. {
  426. long qdot_width;    /* width of character in quarter-dots */
  427. long x;
  428. double d_wd, d_ht, d_dp, d_ic;
  429.  
  430. if (hpf->spacing == 1)
  431.     qdot_width = hpc->delta_x;
  432. else
  433.     qdot_width = hpf->pitch;
  434. /*
  435.  *  some compilers need to have these computations split out this way
  436.  */
  437. d_wd = ((dot_scale * qdot_width) / 4.0) * TWO_20th;
  438. d_ht = dot_scale * hpc->top_offset * TWO_20th;
  439. /*
  440.  *   be extremely careful on conversions involving signed and unsigned short
  441.  *   (this may look paranoid, but some compilers botch the conversions)
  442.  */
  443. x = hpc->character_height;
  444. x -= hpc->top_offset;
  445. if (x > 0L)
  446.     d_dp = dot_scale * x * TWO_20th;
  447. else
  448.     d_dp = 0.0;
  449. x = hpc->character_width;
  450. x *= 4;
  451. x -= qdot_width;
  452. if (x > 0L)
  453.     d_ic = dot_scale * (x / 4.0) * TWO_20th;
  454. else
  455.     d_ic = 0.0;
  456.  
  457. tfc->charwd = d_wd;
  458. tfc->charht = d_ht;
  459. tfc->chardp = d_dp;
  460. tfc->charic = d_ic;
  461.  
  462. if ((tfc->charic != 0L) && (hpf->style != 1))
  463.     {
  464.     myputs(
  465.      "Warning:  character in upright font has nonzero italic correction.");
  466.     myputs("\n");
  467.     }
  468. /*
  469.  *  save the smallest and largest character codes encountered
  470.  */
  471. if (pkc->char_code < tft->tfm_bc)
  472.     tft->tfm_bc = pkc->char_code;
  473. if (pkc->char_code > tft->tfm_ec)
  474.     tft->tfm_ec = pkc->char_code;
  475. }
  476.  
  477. /****************************************************************************
  478.  * NAME
  479.  *    sfp_to_tfm_param
  480.  * ARGUMENTS
  481.  *    tfp - pointer to TFM font parameter structure
  482.  *    hpf - pointer to SFP font descriptor structure
  483.  *    tfc - pointer to array of TFM character data structures
  484.  *    tft - pointer to TFM file top information structure
  485.  * DESCRIPTION
  486.  *    Compute the TFM font spacing parameter values.
  487.  * RETURN VALUE
  488.  *    none
  489.  */
  490. void sfp_to_tfm_param(tfp, hpf, tfc, tft)
  491. struct tfm_param *tfp;
  492. struct hp_font_descriptor *hpf;
  493. struct tfm_chardata *tfc;
  494. struct tfm_top *tft;
  495. {
  496. double d;
  497. /*
  498.  *  first, compute the space parameters
  499.  */
  500. if (hpf->spacing == 1)
  501.     {
  502.     if ((tft->tfm_bc <= ' ')&&(tft->tfm_ec >= ' ')&&(tfc[' '].charwd != 0L))
  503.     {
  504.     /*
  505.      *  use space character's width for font spacing parameters
  506.      */
  507.     tfp->tfm_space = tfc[' '].charwd;
  508.     }
  509.     else if (spacewidth != 0L)
  510.     {
  511.     d = spacewidth;
  512.     d /= designsize;
  513.     tfp->tfm_space = d * TWO_20th;
  514.     }
  515.     else if ((tft->tfm_bc <= 'x')&&(tft->tfm_ec >= 'x')&&(tfc['x'].charwd!=0L))
  516.     {
  517.     /*
  518.      *  if no space character, use 'x' character's width for spacing
  519.      */
  520.     printf("\
  521. Font contains no space; using width of x character for font space.\n");
  522.     tfp->tfm_space = tfc['x'].charwd;
  523.     }
  524.     else
  525.     {
  526.     /*
  527.      *  Neither space nor x was available, so we arbitrarily use
  528.      *  values based on the design size.
  529.      */
  530.     printf("\
  531. Font contains no space or x; using 1/2 design size for font space.\n");
  532.     tfp->tfm_space = 0x00080000;        /* == 0.5 as fixnum */
  533.     }
  534.     tfp->tfm_space_stretch = tfp->tfm_space / 2;
  535.     tfp->tfm_space_shrink  = tfp->tfm_space / 3;
  536.     tfp->tfm_extra_space   = tfp->tfm_space / 3;
  537.     }
  538. else
  539.     {
  540.     /*
  541.      *  mono-space font
  542.      */
  543.     d = ((dot_scale * hpf->pitch) / 4.0) * TWO_20th;
  544.     tfp->tfm_space = d;
  545.     tfp->tfm_space_stretch = 0L;
  546.     tfp->tfm_space_shrink = 0L;
  547.     tfp->tfm_extra_space = tfp->tfm_space;
  548.     }
  549. /*
  550.  *  we always set the quad value to twice the basic space value
  551.  */
  552. tfp->tfm_quad = tfp->tfm_space * 2;        /* em-space */
  553. /*
  554.  *  set the x height (used for accent placement)
  555.  */
  556. if ((tft->tfm_bc <= 'x') && (tft->tfm_ec >= 'x') && (tfc['x'].charwd != 0L))
  557.     param_fm.tfm_x_height = tfc['x'].charht + tfc['x'].chardp;
  558. else
  559.     {
  560.     printf("Font contains no x; using 1/2 design size for x-height.\n");
  561.     tfp->tfm_x_height = 0x00080000;        /* == 0.5 as fixnum */
  562.     }
  563. }
  564.  
  565. #ifdef MACINTOSH
  566. /***************************************************************************
  567.  * NAME
  568.  *    setMacFileType
  569.  * ARGUMENTS
  570.  *    fname   - filename string
  571.  *    type    - file type string (4 chars, allcaps)
  572.  *    creator - file creator string (4 chars, allcaps)
  573.  * DESCRIPTION
  574.  *    For the Macintosh, call the toolbox functions to set the file type and
  575.  *    creator to the desired values.
  576.  * RETURN VALUE
  577.  *    none
  578.  */
  579. void setMacFileType(fname, type, creator)
  580. char *fname;
  581. char *type;
  582. char *creator;
  583. {
  584. char filename[256];
  585. long err;
  586. long refnum;
  587. struct FInfo {
  588.     char fdType[4];
  589.     char fdCreator[4];
  590.     long fdFlags;
  591.     struct { long x; long y; } fdLocation;
  592.     long fdFldr;
  593.     } finderInfo;
  594. int i;
  595.  
  596. strcpy(filename+1,fname);
  597. filename[0] = strlen(fname);
  598. refnum = 0;
  599. err = GetFInfo( filename, refnum, &finderInfo );
  600. for ( i = 0 ; i < 4 ; ++i )
  601.     {
  602.     finderInfo.fdType[i] = ' ';
  603.     finderInfo.fdCreator[i] = ' ';
  604.     }
  605. for ( i = 0 ; i < 4 ; ++i )
  606.     {
  607.     if (type[i] == NUL)
  608.     break;
  609.     finderInfo.fdType[i] = type[i];
  610.     }
  611. for ( i = 0 ; i < 4 ; ++i )
  612.     {
  613.     if (creator[i] == NUL)
  614.     break;
  615.     finderInfo.fdCreator[i] = creator[i];
  616.     }
  617. #ifdef THINK_C
  618. err = SetFInfo( filename, refnum, &finderInfo );
  619. #endif
  620. }
  621. #endif
  622.  
  623. /****************************************************************************
  624.  * NAME
  625.  *    main
  626.  * ARGUMENTS
  627.  *    argc - number of command line arguments
  628.  *    argv - pointer to array of command line arguments
  629.  * DESCRIPTION
  630.  *    main procedure for the HP2PK program
  631.  * RETURN VALUE
  632.  *    0 to indicate success
  633.  */
  634. int main(argc,argv)
  635. int argc;
  636. char **argv;
  637. {
  638. int c;
  639. FILE *sfp_fp = NULL;    /* SFP input FILE pointer */
  640. FILE *pk_fp = NULL;    /* PK  output FILE pointer */
  641. FILE *pl_fp = NULL;    /* PL  output FILE pointer */
  642. FILE *tfm_fp = NULL;    /* TFM output FILE pointer */
  643. double d;        /* used in computing design size */
  644. int errflag;        /* flag errors in command line parsing */
  645. char buffer[80];    /* scratch buffer for sprintf() output */
  646. time_t job_time;    /* time that this job was run, in seconds */
  647. struct tm *tp;        /* decoded time that this job was run */
  648. char *date;        /* time string for when this job was run */
  649. struct tfm_chardata *cfmp;    /* hack for MSDOS compiler bug */
  650.  
  651. fprintf(stderr, "This is HP2PK, Version %d.%d.%d (%s)\n%s\n",
  652.     VERSION, REVISION, PATCHLEVEL, PATCHDATE, COPYRIGHT );
  653.  
  654. #ifdef THINK_C        /* this MUST follow the fprintf() for some reason */
  655.     SetWTitle( FrontWindow(), "\pHP2PK" );
  656.     argc = ccommand( &argv );
  657. #endif
  658.  
  659. time( &job_time );
  660. tp = localtime( &job_time );
  661. /*
  662.  *  parse the command line
  663.  */
  664. errflag = 0;
  665. while ((c = getopt(argc,argv,"b:d:hl:m:p:r:s:t:vz:")) != EOF)
  666.     {
  667.     switch (c)
  668.     {
  669.     case 'b':            /* pixel density (bits per inch) */
  670.         density = (int)strtol(optarg, (char **)NULL, 10);
  671.         break;
  672.     case 'd':            /* design size (in points) */
  673.         designsize = str_to_fixnum(optarg);
  674.         break;
  675.     case 's':            /* width of space char (in points) */
  676.         spacewidth = str_to_fixnum(optarg);
  677.         break;
  678.     case 'm':            /* magnification * 1000 */
  679.         magnification = strtol(optarg, (char **)NULL, 10);
  680.         break;
  681.     case 'r':            /* restrict to lower/upper 128 chars */
  682.         if ((*optarg == 'l') || (*optarg == 'u'))
  683.         restrict_7bit = *optarg;
  684.         else
  685.         {
  686.         fprintf(stderr,
  687.              "The -r option requires either l or u as an argument.\n");
  688.         ++errflag;
  689.         }
  690.         break;
  691.     case 'p':
  692.         pk_filename = optarg;
  693.         break;
  694.     case 'l':
  695.         pl_filename = optarg;
  696.         break;
  697.     case 't':
  698.         tfm_filename = optarg;
  699.         break;
  700.     case 'v':
  701.         verbose = 1;
  702.         break;
  703.     case 'z':
  704. #ifdef MACINTOSH
  705.         fileCreator = optarg;
  706.         break;
  707. #else
  708.         fprintf(stderr,"The -z option is valid only for the Macintosh.\n");
  709.         /* fall through */
  710. #endif
  711.     case 'h':        /* fall through */
  712.     default:
  713.         ++errflag;
  714.         break;
  715.     }
  716.     }
  717. if (errflag || (optind >= argc))
  718.     {
  719.     fputs("\
  720. Usage: hp2pk [options] file.sfp\n\
  721.     -b density   specify pixel density (dots/inch) of the font\n\
  722.     -d size      specify the design size (in points) of the font\n\
  723.     -h           ask for help (this display)\n\
  724.     -l file.pl   specify the output Property List (PL) file\n\
  725.     -m mag       specify the magnification (* 1000) of the font\n\
  726. ", stderr); fputs("\
  727.     -p file.pk   specify the output PacKed font (PK) file\n\
  728.     -r {l|u}     ask for only lower 128 or only upper 128 characters\n\
  729.     -s sp_width  specify the width of a space character (in points)\n\
  730.     -t file.tfm  specify the output TeX Font Metric (TFM) file\n\
  731.     -v           request verbose progress report output\n\
  732. ", stderr);
  733. #ifdef MACINTOSH
  734.     fputs("\
  735.     -z CREA      set the hidden Macintosh Creator type for output files.\n\
  736.                  This is usually four letters.\n\
  737. ", stderr);
  738. #endif
  739.     fputs("\
  740. file.sfp is the input HP Soft Font/Portrait (SFP) file.\n\
  741. \n\
  742. If not specified, hp2pk creates a PK file with the same base name as the\n\
  743. input file, but with a .pk filename extension.\n\
  744. If neither a PL nor a TFM file is specified, hp2pk creates a TFM file with\n\
  745. the same base name as the input file, but with a .tfm filename extension.\n\
  746. ", stderr);
  747.     fputs("\
  748. The default design size is calculated from the font data.\n\
  749. The default magnification is 1000.  The default pixel density is 300 dpi.\n\
  750. If the font contains a space character, its width is always used.  Otherwise,\n\
  751. the default width of a space is the width of the 'x' character.\n\
  752. ", stderr);
  753.     exit(1);
  754.     }
  755. /*
  756.  *  Open the .SFP file
  757.  */
  758. sfp_filename = fix_filename( argv[optind], ".sfp", "rb");
  759. sfp_fp = fopen(sfp_filename, "rb");
  760. if (sfp_fp == (FILE *)NULL)
  761.     {
  762.     fprintf(stderr, "Cannot open HP soft font file %s\n", sfp_filename);
  763.     exit(1);
  764.     }
  765. read_sfp_font_descriptor(sfp_fp, &hp_font, &symbol_set_string, verbose );
  766. if (symbol_set_string == (char *)NULL)
  767.     symbol_set_string = "UNSPECIFIED";
  768. if (magnification == 0L)
  769.     magnification = 1000L;
  770. if (density == 0)
  771.     density = 300;        /* assume 300 dots per inch */
  772. if (designsize == 0L)
  773.     {
  774.     /*
  775.      *  Estimate TeX design size based on font height
  776.      *  Note:  18.0675 = (72.27 points/inch) / 4 quarter-dots/dot
  777.      *           and hp_font.height is measured in quarter-dots
  778.      */
  779.     d = ((18.0675 / density) * hp_font.height) * (1000.0 / magnification) *
  780.                                      TWO_20th;
  781.     designsize = d;
  782.     printf("Estimated font design size is %.2f pt.\n", d/TWO_20th );
  783.     }
  784. /*
  785.  *  dot_scale is used to translate dots (pixels) to (2**-20) points
  786.  */
  787. dot_scale = (72.27 / density) * (1000.0 / magnification) *
  788.                         (TWO_20th / designsize);
  789. sfp_to_tfm_header( &hp_font, symbol_set_string, designsize, &header_fm );
  790. top_fm.tfm_bc = 256;    /* larger than any possible value */
  791. top_fm.tfm_ec = -1;    /* smaller than any possible value */
  792. /*
  793.  *  Open the new .PK file
  794.  */
  795. if (pk_filename == (char *)NULL)
  796.     pk_filename = change_filetype(sfp_filename, ".pk");
  797. pk_filename = fix_filename( pk_filename, ".pk", "wb");
  798. pk_fp = fopen(pk_filename, "wb");
  799. if (pk_fp == (FILE *)NULL)
  800.     {
  801.     fprintf(stderr, "Cannot open output PK font file %s\n", pk_filename );
  802.     exit(1);
  803.     }
  804. /*
  805.  *  if wanted, open the new .PL file
  806.  */
  807. if (pl_filename != (char *)NULL)
  808.     {
  809.     pl_filename = fix_filename(pl_filename, ".pl", "w");
  810.     pl_fp = fopen(pl_filename, "w");
  811.     if (pl_fp == (FILE *)NULL)
  812.     {
  813.     fprintf(stderr, "Cannot open output PL font metric file %s\n",
  814.                             pl_filename );
  815.     exit(1);
  816.     }
  817.     }
  818. else
  819.     pl_fp = (FILE *)NULL;        /* signals that we don't output PL */
  820. /*
  821.  *  if wanted, open the new .TFM file
  822.  */
  823. if ((tfm_filename == (char *)NULL) && (pl_filename == (char *)NULL))
  824.     tfm_filename = change_filetype(sfp_filename, ".tfm");
  825. if (tfm_filename != (char *)NULL)
  826.     {
  827.     tfm_filename = fix_filename(tfm_filename, ".tfm", "wb");
  828.     tfm_fp = fopen(tfm_filename, "wb");
  829.     if (tfm_fp == (FILE *)NULL)
  830.     {
  831.     fprintf(stderr, "Cannot open output TFM font metric file %s\n",
  832.                             tfm_filename );
  833.     exit(1);
  834.     }
  835.     }
  836. sprintf(buffer, "HP2PK %d.%d.%d (%s) output  %4d.%02d.%02d  %2d:%02d:%02d",
  837.     VERSION, REVISION, PATCHLEVEL, PATCHDATE,
  838.     tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday,
  839.     tp->tm_hour, tp->tm_min, tp->tm_sec );
  840. init_pk_file(pk_fp, buffer, designsize, density, &pk_header);
  841. if (pl_fp != (FILE *)NULL)
  842.     {
  843.     date = ctime(&job_time);
  844.     date[24] = '\0';
  845.     init_pl_file(pl_fp, "HP2PK", date, &header_fm );
  846.     }
  847. /*
  848.  *  Process the sfp file to produce the pk file and the pl file
  849.  */
  850. for (;;)
  851.     {
  852.     /*
  853.      *  process the data for one character
  854.      */
  855.     c = read_sfp_character(sfp_fp, &hp_font, &hp_char, &bitmap );
  856.     if (c == -1)
  857.     {
  858.     if (!feof(sfp_fp))
  859.         puts("\nIgnoring junk at the end of the Soft Font/Portrait file.");
  860.     break;
  861.     }
  862.     if (    ((restrict_7bit == 'l') && (c >= 128)) ||
  863.         ((restrict_7bit == 'u') && (c <  128)) )
  864.     continue;
  865.  
  866.     sprintf(buffer, " [%d]", c);
  867.     myputs(buffer);        /* print the character code on the screen */
  868.  
  869.     if ((restrict_7bit == 'u') && (c >= 128))
  870.     c -= 128;        /* fix character code for 7-bit output file */
  871.  
  872.     sfp_to_pk(c, &hp_font, &hp_char, &pk_char);
  873.     write_pk_character(pk_fp, &pk_char, &bitmap);
  874.  
  875.     cfmp = &char_fm[c];    /* need this to get around MSDOS compiler bug */
  876.     sfp_to_tfm(&hp_font, &hp_char, &pk_char, cfmp, &top_fm);
  877.     if (pl_fp != (FILE *)NULL)
  878.     write_pl_entry(pl_fp, c, cfmp);
  879.     }
  880. end_pk_file(pk_fp);
  881. if (verbose)
  882.     {
  883.     putchar('\n');
  884.     printf( "%6ld bytes read from HP soft font file.\n", ftell(sfp_fp) );
  885.     printf( "%6ld bytes written to packed font file.\n", ftell(pk_fp) );
  886.     }
  887. fclose(sfp_fp);
  888. fclose(pk_fp);
  889. #ifdef MACINTOSH    /* set Macintosh file type for PK file */
  890. if (fileCreator != (char *)NULL)
  891.     setMacFileType(pk_filename, "BINA", fileCreator );
  892. #endif
  893. sfp_to_tfm_param(¶m_fm, &hp_font, char_fm, &top_fm );
  894. if (pl_fp != (FILE *)NULL)
  895.     {
  896.     end_pl_file(pl_fp, ¶m_fm);
  897.     fclose(pl_fp);
  898. #ifdef MACINTOSH    /* set Macintosh file type for PL file */
  899.     if (fileCreator != (char *)NULL)
  900.     setMacFileType(pl_filename, "TEXT", fileCreator );
  901. #endif
  902.     }
  903. /*
  904.  *  if wanted, write the .TFM file
  905.  */
  906. if (tfm_fp != (FILE *)NULL)
  907.     {
  908.     write_tfm_data(tfm_fp,&top_fm,&header_fm, char_fm,¶m_fm, designsize);
  909.     fclose(tfm_fp);
  910. #ifdef MACINTOSH    /* set Macintosh file type for TFM file */
  911.     if (fileCreator != (char *)NULL)
  912.     setMacFileType(tfm_filename, "BINA", fileCreator );
  913. #endif
  914.     }
  915.  
  916. return(0);        /* successful execution */
  917. }
  918.