home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume20 / hp2pk / part02 / writetfm.c < prev   
C/C++ Source or Header  |  1991-06-02  |  12KB  |  397 lines

  1. /*  WRITETFM.C - Write all the data to a TeX TFM font metric file
  2.  ***************************************************************************
  3.  *
  4.  *    void write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
  5.  *    FILE *fp;
  6.  *    struct tfm_top      *tpfm;
  7.  *    struct tfm_header   *hdfm;
  8.  *    struct tfm_chardata chfm[];
  9.  *    struct tfm_param    *pafm;
  10.  *    fixnum designsize;
  11.  *
  12.  ***************************************************************************
  13.  *
  14.  *    Sources of information for TeX font metric files:
  15.  *
  16.  *        The METAFONTbook by Donald E. Knuth (appendix F)
  17.  *        PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al.
  18.  *
  19.  ***************************************************************************
  20.  *    EDIT HISTORY
  21.  *    19-Oct-90    SRMc - split out from HP2PK.C to improve modularity
  22.  *    20-Oct-90    SRMc - make write_tfm_data() the only externally
  23.  *                visible function
  24.  ***************************************************************************
  25.  * Copyright 1990 by the Summer Institute of Linguistics, Inc.
  26.  * All rights reserved.
  27.  */
  28. #include <stdio.h>
  29. #include "tfm.h"
  30. #include "bitmap.h"
  31.  
  32. /************************************************************************/
  33. /*               EXTERN DECLARATIONS                */
  34. /************************************************************************/
  35.  
  36. extern void put_halfword(), put_fullword();    /* from BIGENDIO.C */
  37. extern char *fixnum_to_str();            /* from FIXNUM.C */
  38.  
  39. /************************************************************************/
  40. /*            STATIC GLOBAL VARIABLES                */
  41. /************************************************************************/
  42. static long tfm_width_table[256];
  43. static long tfm_height_table[256];
  44. static long tfm_depth_table[256];
  45. static long tfm_charic_table[256];
  46. static int num_tfm_width, num_tfm_height, num_tfm_depth, num_tfm_charic;
  47.  
  48. /****************************************************************************
  49.  * NAME
  50.  *    static insort
  51.  * ARGUMENTS
  52.  *    table - array of long integers
  53.  *    size  - size of the array
  54.  *    value - value to add to the array if not already there
  55.  * DESCRIPTION
  56.  *    Add a value to an array, in sorted order.
  57.  * RETURN VALUE
  58.  *    size of the array after (possibly) adding the value
  59.  */
  60. static int insort(table, size, value)
  61. long *table;
  62. int size;
  63. long value;
  64. {
  65. int i, j;
  66.  
  67. if (value == 0L)
  68.     return( size );        /* ignore zeros */
  69.  
  70. for ( i = 0 ; i < size ; ++i )
  71.     {
  72.     if (table[i] == value)
  73.     return(size);
  74.     if (table[i] > value)
  75.     {
  76.     for ( j = size ; j > i ; --j)
  77.         table[j] = table[j-1];    /* make room to */
  78.     table[i] = value;        /* insert the new value */
  79.     return(size+1);
  80.     }
  81.     }
  82. table[size] = value;    /* add to end of sorted table */
  83. return( size + 1 );
  84. }
  85.  
  86. #define labs(a) ((a >= 0) ? a : -a )
  87.  
  88. /****************************************************************************
  89.  * NAME
  90.  *    static mindelta
  91.  * ARGUMENTS
  92.  *    table    - sorted array of long ints
  93.  *    size     - size of the array
  94.  * DESCRIPTION
  95.  *    Find the minimum difference between adjacent entries in the array.
  96.  * RETURN VALUE
  97.  *    the minimum difference found (adjusted slightly for roundoff)
  98.  */
  99. static fixnum mindelta(table, size)
  100. fixnum *table;
  101. int size;
  102. {
  103. int k;
  104. fixnum min_diff;
  105.  
  106. min_diff = 0x7FFFFFFFL;
  107.  
  108. for ( k = 0 ; k < size-1 ; ++k )
  109.     {
  110.     if (labs(table[k+1] - table[k]) < min_diff)
  111.     min_diff = labs( table[k+1] - table[k] );
  112.     }
  113. return( min_diff+1 );        /* adjust slightly for roundoff */
  114. }
  115.  
  116. /****************************************************************************
  117.  * NAME
  118.  *    static trim_tfm_table
  119.  * ARGUMENTS
  120.  *    table   - array of long integers
  121.  *    size    - size of the array
  122.  *    max     - maximum allowable size of the array
  123.  *    tabname - character string name of the table for error message
  124.  *    dsize   - designsize of font (in 2**-20 points)
  125.  * DESCRIPTION
  126.  *    If the array is larger than allowed, throw out the minimum number of
  127.  *    values, trying for minimum impact of the loss of precision.
  128.  * RETURN VALUE
  129.  *    number of entries in the reduced table
  130.  */
  131. static int trim_tfm_table(table, size, max, tabname, dsize)
  132. long *table;
  133. int size;
  134. int max;
  135. char *tabname;
  136. fixnum dsize;
  137. {
  138. long scratch[256];
  139. char fixnumbuf[16];
  140. int i;
  141. int num;
  142. fixnum min_d;
  143. double d;
  144.  
  145. if (size <= max)
  146.     return(size);
  147.  
  148. do  {
  149.     min_d = mindelta(table, size);
  150.     for ( num = 0, i = 0 ; i < size-1 ; ++i )
  151.     {
  152.     if ((table[i+1] - table[i]) <= min_d)
  153.         {                /* split the difference */
  154.         scratch[num++] = (table[i] + table[i+1]) / 2;
  155.         ++i;            /* need to skip ahead in table[] */
  156.         }
  157.     else
  158.         scratch[num++] = table[i];    /* copy the original value */
  159.     }
  160.     if (i < size)
  161.     scratch[num++] = table[i];    /* if needed, store largest value */
  162.  
  163.     size = num;
  164.     for ( i = 0 ; i < size ; ++i )
  165.     table[i] = scratch[i];
  166.  
  167.     } while (size > max);
  168.  
  169. d = (min_d / 2.0) * (dsize / TWO_20th);
  170. min_d = d;
  171. printf( "TFM character %s may be rounded off by %s pt.\n",
  172.                 tabname, fixnum_to_str(min_d, fixnumbuf, 7) );
  173. return(size);
  174. }
  175.  
  176. /****************************************************************************
  177.  * NAME
  178.  *    static table_index
  179.  * ARGUMENTS
  180.  *    table - array of long integers
  181.  *    size  - size of the array
  182.  *    value - value to search for
  183.  * DESCRIPTION
  184.  *    Search for the closest fit in the array to the given value.
  185.  * RETURN VALUE
  186.  *    index in the array of the closest fit
  187.  */
  188. static int table_index(table, size, value)
  189. long *table;
  190. int size;
  191. long value;
  192. {
  193. int i;
  194. /*
  195.  *  first, try for exact matches
  196.  */
  197. for ( i = 0 ; i < size ; ++i )
  198.     {
  199.     if (value == table[i])
  200.     return( i );
  201.     }
  202. /*
  203.  *  now, try for closest fit
  204.  */
  205. for ( i = 1 ; i < size-1 ; ++i )
  206.     {
  207.     if ((value > table[i]) && (value < table[i+1]))
  208.     {
  209.     if ((value < 0) && (table[i+1] > 0))
  210.         return( ((value - table[i]) < -value) ? i : 0 );
  211.     if ((value > 0) && (table[i] < 0))
  212.         return( (value < (table[i+1] - value)) ? 0 : i+1 );
  213.     return( ((value - table[i]) < (table[i+1] - value)) ? i : i+1 );
  214.     }
  215.     }
  216. return(size-1);        /* largest value in table was rounded down */
  217. }
  218.  
  219. /****************************************************************************
  220.  * NAME
  221.  *    static fix_tfm_data
  222.  * ARGUMENTS
  223.  *    chfm       - pointer to array of TFM character data structures
  224.  *    tpfm       - pointer to TFM file top information structure
  225.  *    designsize - font design size (used for roundoff messages)
  226.  * DESCRIPTION
  227.  *    Fix the TFM data in preparation for writing the file.
  228.  *    This involves squeezing the character metric arrays to no more
  229.  *    than their maximum sizes prior to converting character metric values
  230.  *    into table indices.
  231.  * RETURN VALUE
  232.  *    none
  233.  */
  234. static void fix_tfm_data(chfm, tpfm, designsize)
  235. struct tfm_chardata chfm[];
  236. struct tfm_top *tpfm;
  237. fixnum designsize;
  238. {
  239. int i;
  240. long idx;
  241. /*
  242.  *  ensure the character metric tables are no larger than allowed
  243.  */
  244. num_tfm_width = num_tfm_height = num_tfm_depth = num_tfm_charic = 0;
  245. for ( i = 0 ; i < 256 ; ++i )
  246.     {
  247.     num_tfm_width  = insort(&tfm_width_table[1], num_tfm_width,
  248.                 chfm[i].charwd);
  249.     num_tfm_height = insort(&tfm_height_table[1],num_tfm_height,
  250.                 chfm[i].charht);
  251.     num_tfm_depth  = insort(&tfm_depth_table[1], num_tfm_depth,
  252.                 chfm[i].chardp);
  253.     num_tfm_charic = insort(&tfm_charic_table[1],num_tfm_charic,
  254.                 chfm[i].charic);
  255.     }
  256. num_tfm_width  = trim_tfm_table( &tfm_width_table[1],  num_tfm_width,
  257.             MAX_TFM_WIDTH-1,  "widths", designsize);
  258. num_tfm_height = trim_tfm_table( &tfm_height_table[1], num_tfm_height,
  259.             MAX_TFM_HEIGHT-1, "heights", designsize);
  260. num_tfm_depth  = trim_tfm_table( &tfm_depth_table[1],  num_tfm_depth,
  261.             MAX_TFM_DEPTH-1,  "depths", designsize );
  262. num_tfm_charic = trim_tfm_table( &tfm_charic_table[1], num_tfm_charic,
  263.             MAX_TFM_CHARIC-1, "italic corrections", designsize );
  264. tfm_width_table[0]  = 0L;    ++num_tfm_width;
  265. tfm_height_table[0] = 0L;    ++num_tfm_height;
  266. tfm_depth_table[0]  = 0L;    ++num_tfm_depth;
  267. tfm_charic_table[0] = 0L;    ++num_tfm_charic;
  268. /*
  269.  *  convert the character data
  270.  */
  271. for ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
  272.     {
  273.     idx = (long)table_index(tfm_width_table, num_tfm_width, chfm[i].charwd);
  274.     chfm[i].char_info  = (idx << 24) & 0xFF000000L;
  275.  
  276.     idx = (long)table_index(tfm_height_table,num_tfm_height,chfm[i].charht);
  277.     chfm[i].char_info |= (idx << 20) & 0x00F00000L;
  278.  
  279.     idx = (long)table_index(tfm_depth_table, num_tfm_depth, chfm[i].chardp);
  280.     chfm[i].char_info |= (idx << 16) & 0x000F0000L;
  281.  
  282.     idx = (long)table_index(tfm_charic_table,num_tfm_charic,chfm[i].charic);
  283.     chfm[i].char_info |= (idx << 10) & 0x0000FC00L;
  284.     }
  285. /*
  286.  *  store the TFM file description data
  287.  */
  288. tpfm->tfm_lf = 6 +        /* length of the entire file, in words */
  289.         (tpfm->tfm_ec - tpfm->tfm_bc + 1) +
  290.         num_tfm_width + num_tfm_height + num_tfm_depth +
  291.         num_tfm_charic + 18 + 7;
  292. tpfm->tfm_lh = 18;        /* length of the header data, in words */
  293. tpfm->tfm_nw = num_tfm_width;    /* number of words in the width table */
  294. tpfm->tfm_nh = num_tfm_height;    /* number of words in the height table */
  295. tpfm->tfm_nd = num_tfm_depth;    /* number of words in the depth table */
  296. tpfm->tfm_ni = num_tfm_charic;    /* number of words in the italic corr. table */
  297. tpfm->tfm_nl = 0;        /* number of words in the lig/kern table */
  298. tpfm->tfm_nk = 0;        /* number of words in the kern table */
  299. tpfm->tfm_ne = 0;        /* number of words in the exten. char. table */
  300. tpfm->tfm_np = 7;        /* number of font parameter words */
  301. }
  302.  
  303. /****************************************************************************
  304.  * NAME
  305.  *    write_tfm_data
  306.  * ARGUMENTS
  307.  *    fp - FILE pointer
  308.  *    tpfm - pointer to TFM file top information structure
  309.  *    hdfm - pointer to TFM file header structure
  310.  *    chfm - pointer to array of TFM character data structures
  311.  *    pafm - pointer to TFM parameter structure
  312.  *    designsize - font design size (used for roundoff messages)
  313.  * DESCRIPTION
  314.  *    Write the TFM data to a file.
  315.  * RETURN VALUE
  316.  *    none
  317.  */
  318. void write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
  319. FILE *fp;
  320. struct tfm_top      *tpfm;
  321. struct tfm_header   *hdfm;
  322. struct tfm_chardata chfm[];
  323. struct tfm_param    *pafm;
  324. fixnum designsize;
  325. {
  326. int i;
  327. /*
  328.  *  fix the TFM character data
  329.  */
  330. fix_tfm_data(chfm, tpfm, designsize);
  331. /*
  332.  *  write the TFM file description info
  333.  */
  334. put_halfword( tpfm->tfm_lf, fp );
  335. put_halfword( tpfm->tfm_lh, fp );
  336. put_halfword( tpfm->tfm_bc, fp );
  337. put_halfword( tpfm->tfm_ec, fp );
  338. put_halfword( tpfm->tfm_nw, fp );
  339. put_halfword( tpfm->tfm_nh, fp );
  340. put_halfword( tpfm->tfm_nd, fp );
  341. put_halfword( tpfm->tfm_ni, fp );
  342. put_halfword( tpfm->tfm_nl, fp );
  343. put_halfword( tpfm->tfm_nk, fp );
  344. put_halfword( tpfm->tfm_ne, fp );
  345. put_halfword( tpfm->tfm_np, fp );
  346. /*
  347.  *  write the TFM File Header
  348.  */
  349. put_fullword( hdfm->tfm_checksum, fp );
  350. put_fullword( hdfm->tfm_design_size, fp );
  351. for ( i = 0 ; i < 40 ; ++i )
  352.     putc( hdfm->tfm_coding[i], fp );
  353. for ( i = 0 ; i < 20 ; ++i )
  354.     putc( hdfm->tfm_fontid[i], fp );
  355. putc( hdfm->tfm_7bitsafe, fp );
  356. putc( hdfm->tfm_unused[0], fp );
  357. putc( hdfm->tfm_unused[1], fp );
  358. putc( hdfm->tfm_face, fp );
  359. /*
  360.  *  write the TFM Character Data
  361.  */
  362. for ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
  363.     {
  364.     put_fullword( chfm[i].char_info, fp );
  365.     }
  366. /*
  367.  *  write the TFM Character widths table
  368.  */
  369. for ( i = 0 ; i < num_tfm_width ; ++i )
  370.     put_fullword( tfm_width_table[i], fp );
  371. /*
  372.  *  write the TFM Character heights table
  373.  */
  374. for ( i = 0 ; i < num_tfm_height ; ++i )
  375.     put_fullword( tfm_height_table[i], fp );
  376. /*
  377.  *  write the TFM Character depths table
  378.  */
  379. for ( i = 0 ; i < num_tfm_depth ; ++i )
  380.     put_fullword( tfm_depth_table[i], fp );
  381. /*
  382.  *  write the TFM Character italic corrections table
  383.  */
  384. for ( i = 0 ; i < num_tfm_charic ; ++i )
  385.     put_fullword( tfm_charic_table[i], fp );
  386. /*
  387.  *  write the TFM Font Parameters
  388.  */
  389. put_fullword( pafm->tfm_slant, fp );
  390. put_fullword( pafm->tfm_space, fp );
  391. put_fullword( pafm->tfm_space_stretch, fp );
  392. put_fullword( pafm->tfm_space_shrink, fp );
  393. put_fullword( pafm->tfm_x_height, fp );
  394. put_fullword( pafm->tfm_quad, fp );
  395. put_fullword( pafm->tfm_extra_space, fp );
  396. }
  397.