home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume20
/
hp2pk
/
part02
/
writetfm.c
< prev
Wrap
C/C++ Source or Header
|
1991-06-02
|
12KB
|
397 lines
/* WRITETFM.C - Write all the data to a TeX TFM font metric file
***************************************************************************
*
* void write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
* FILE *fp;
* struct tfm_top *tpfm;
* struct tfm_header *hdfm;
* struct tfm_chardata chfm[];
* struct tfm_param *pafm;
* fixnum designsize;
*
***************************************************************************
*
* Sources of information for TeX font metric files:
*
* The METAFONTbook by Donald E. Knuth (appendix F)
* PLtoTF.WEB by Donald E. Knuth, Leo Guibas, et al.
*
***************************************************************************
* EDIT HISTORY
* 19-Oct-90 SRMc - split out from HP2PK.C to improve modularity
* 20-Oct-90 SRMc - make write_tfm_data() the only externally
* visible function
***************************************************************************
* Copyright 1990 by the Summer Institute of Linguistics, Inc.
* All rights reserved.
*/
#include <stdio.h>
#include "tfm.h"
#include "bitmap.h"
/************************************************************************/
/* EXTERN DECLARATIONS */
/************************************************************************/
extern void put_halfword(), put_fullword(); /* from BIGENDIO.C */
extern char *fixnum_to_str(); /* from FIXNUM.C */
/************************************************************************/
/* STATIC GLOBAL VARIABLES */
/************************************************************************/
static long tfm_width_table[256];
static long tfm_height_table[256];
static long tfm_depth_table[256];
static long tfm_charic_table[256];
static int num_tfm_width, num_tfm_height, num_tfm_depth, num_tfm_charic;
/****************************************************************************
* NAME
* static insort
* ARGUMENTS
* table - array of long integers
* size - size of the array
* value - value to add to the array if not already there
* DESCRIPTION
* Add a value to an array, in sorted order.
* RETURN VALUE
* size of the array after (possibly) adding the value
*/
static int insort(table, size, value)
long *table;
int size;
long value;
{
int i, j;
if (value == 0L)
return( size ); /* ignore zeros */
for ( i = 0 ; i < size ; ++i )
{
if (table[i] == value)
return(size);
if (table[i] > value)
{
for ( j = size ; j > i ; --j)
table[j] = table[j-1]; /* make room to */
table[i] = value; /* insert the new value */
return(size+1);
}
}
table[size] = value; /* add to end of sorted table */
return( size + 1 );
}
#define labs(a) ((a >= 0) ? a : -a )
/****************************************************************************
* NAME
* static mindelta
* ARGUMENTS
* table - sorted array of long ints
* size - size of the array
* DESCRIPTION
* Find the minimum difference between adjacent entries in the array.
* RETURN VALUE
* the minimum difference found (adjusted slightly for roundoff)
*/
static fixnum mindelta(table, size)
fixnum *table;
int size;
{
int k;
fixnum min_diff;
min_diff = 0x7FFFFFFFL;
for ( k = 0 ; k < size-1 ; ++k )
{
if (labs(table[k+1] - table[k]) < min_diff)
min_diff = labs( table[k+1] - table[k] );
}
return( min_diff+1 ); /* adjust slightly for roundoff */
}
/****************************************************************************
* NAME
* static trim_tfm_table
* ARGUMENTS
* table - array of long integers
* size - size of the array
* max - maximum allowable size of the array
* tabname - character string name of the table for error message
* dsize - designsize of font (in 2**-20 points)
* DESCRIPTION
* If the array is larger than allowed, throw out the minimum number of
* values, trying for minimum impact of the loss of precision.
* RETURN VALUE
* number of entries in the reduced table
*/
static int trim_tfm_table(table, size, max, tabname, dsize)
long *table;
int size;
int max;
char *tabname;
fixnum dsize;
{
long scratch[256];
char fixnumbuf[16];
int i;
int num;
fixnum min_d;
double d;
if (size <= max)
return(size);
do {
min_d = mindelta(table, size);
for ( num = 0, i = 0 ; i < size-1 ; ++i )
{
if ((table[i+1] - table[i]) <= min_d)
{ /* split the difference */
scratch[num++] = (table[i] + table[i+1]) / 2;
++i; /* need to skip ahead in table[] */
}
else
scratch[num++] = table[i]; /* copy the original value */
}
if (i < size)
scratch[num++] = table[i]; /* if needed, store largest value */
size = num;
for ( i = 0 ; i < size ; ++i )
table[i] = scratch[i];
} while (size > max);
d = (min_d / 2.0) * (dsize / TWO_20th);
min_d = d;
printf( "TFM character %s may be rounded off by %s pt.\n",
tabname, fixnum_to_str(min_d, fixnumbuf, 7) );
return(size);
}
/****************************************************************************
* NAME
* static table_index
* ARGUMENTS
* table - array of long integers
* size - size of the array
* value - value to search for
* DESCRIPTION
* Search for the closest fit in the array to the given value.
* RETURN VALUE
* index in the array of the closest fit
*/
static int table_index(table, size, value)
long *table;
int size;
long value;
{
int i;
/*
* first, try for exact matches
*/
for ( i = 0 ; i < size ; ++i )
{
if (value == table[i])
return( i );
}
/*
* now, try for closest fit
*/
for ( i = 1 ; i < size-1 ; ++i )
{
if ((value > table[i]) && (value < table[i+1]))
{
if ((value < 0) && (table[i+1] > 0))
return( ((value - table[i]) < -value) ? i : 0 );
if ((value > 0) && (table[i] < 0))
return( (value < (table[i+1] - value)) ? 0 : i+1 );
return( ((value - table[i]) < (table[i+1] - value)) ? i : i+1 );
}
}
return(size-1); /* largest value in table was rounded down */
}
/****************************************************************************
* NAME
* static fix_tfm_data
* ARGUMENTS
* chfm - pointer to array of TFM character data structures
* tpfm - pointer to TFM file top information structure
* designsize - font design size (used for roundoff messages)
* DESCRIPTION
* Fix the TFM data in preparation for writing the file.
* This involves squeezing the character metric arrays to no more
* than their maximum sizes prior to converting character metric values
* into table indices.
* RETURN VALUE
* none
*/
static void fix_tfm_data(chfm, tpfm, designsize)
struct tfm_chardata chfm[];
struct tfm_top *tpfm;
fixnum designsize;
{
int i;
long idx;
/*
* ensure the character metric tables are no larger than allowed
*/
num_tfm_width = num_tfm_height = num_tfm_depth = num_tfm_charic = 0;
for ( i = 0 ; i < 256 ; ++i )
{
num_tfm_width = insort(&tfm_width_table[1], num_tfm_width,
chfm[i].charwd);
num_tfm_height = insort(&tfm_height_table[1],num_tfm_height,
chfm[i].charht);
num_tfm_depth = insort(&tfm_depth_table[1], num_tfm_depth,
chfm[i].chardp);
num_tfm_charic = insort(&tfm_charic_table[1],num_tfm_charic,
chfm[i].charic);
}
num_tfm_width = trim_tfm_table( &tfm_width_table[1], num_tfm_width,
MAX_TFM_WIDTH-1, "widths", designsize);
num_tfm_height = trim_tfm_table( &tfm_height_table[1], num_tfm_height,
MAX_TFM_HEIGHT-1, "heights", designsize);
num_tfm_depth = trim_tfm_table( &tfm_depth_table[1], num_tfm_depth,
MAX_TFM_DEPTH-1, "depths", designsize );
num_tfm_charic = trim_tfm_table( &tfm_charic_table[1], num_tfm_charic,
MAX_TFM_CHARIC-1, "italic corrections", designsize );
tfm_width_table[0] = 0L; ++num_tfm_width;
tfm_height_table[0] = 0L; ++num_tfm_height;
tfm_depth_table[0] = 0L; ++num_tfm_depth;
tfm_charic_table[0] = 0L; ++num_tfm_charic;
/*
* convert the character data
*/
for ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
{
idx = (long)table_index(tfm_width_table, num_tfm_width, chfm[i].charwd);
chfm[i].char_info = (idx << 24) & 0xFF000000L;
idx = (long)table_index(tfm_height_table,num_tfm_height,chfm[i].charht);
chfm[i].char_info |= (idx << 20) & 0x00F00000L;
idx = (long)table_index(tfm_depth_table, num_tfm_depth, chfm[i].chardp);
chfm[i].char_info |= (idx << 16) & 0x000F0000L;
idx = (long)table_index(tfm_charic_table,num_tfm_charic,chfm[i].charic);
chfm[i].char_info |= (idx << 10) & 0x0000FC00L;
}
/*
* store the TFM file description data
*/
tpfm->tfm_lf = 6 + /* length of the entire file, in words */
(tpfm->tfm_ec - tpfm->tfm_bc + 1) +
num_tfm_width + num_tfm_height + num_tfm_depth +
num_tfm_charic + 18 + 7;
tpfm->tfm_lh = 18; /* length of the header data, in words */
tpfm->tfm_nw = num_tfm_width; /* number of words in the width table */
tpfm->tfm_nh = num_tfm_height; /* number of words in the height table */
tpfm->tfm_nd = num_tfm_depth; /* number of words in the depth table */
tpfm->tfm_ni = num_tfm_charic; /* number of words in the italic corr. table */
tpfm->tfm_nl = 0; /* number of words in the lig/kern table */
tpfm->tfm_nk = 0; /* number of words in the kern table */
tpfm->tfm_ne = 0; /* number of words in the exten. char. table */
tpfm->tfm_np = 7; /* number of font parameter words */
}
/****************************************************************************
* NAME
* write_tfm_data
* ARGUMENTS
* fp - FILE pointer
* tpfm - pointer to TFM file top information structure
* hdfm - pointer to TFM file header structure
* chfm - pointer to array of TFM character data structures
* pafm - pointer to TFM parameter structure
* designsize - font design size (used for roundoff messages)
* DESCRIPTION
* Write the TFM data to a file.
* RETURN VALUE
* none
*/
void write_tfm_data(fp, tpfm, hdfm, chfm, pafm, designsize)
FILE *fp;
struct tfm_top *tpfm;
struct tfm_header *hdfm;
struct tfm_chardata chfm[];
struct tfm_param *pafm;
fixnum designsize;
{
int i;
/*
* fix the TFM character data
*/
fix_tfm_data(chfm, tpfm, designsize);
/*
* write the TFM file description info
*/
put_halfword( tpfm->tfm_lf, fp );
put_halfword( tpfm->tfm_lh, fp );
put_halfword( tpfm->tfm_bc, fp );
put_halfword( tpfm->tfm_ec, fp );
put_halfword( tpfm->tfm_nw, fp );
put_halfword( tpfm->tfm_nh, fp );
put_halfword( tpfm->tfm_nd, fp );
put_halfword( tpfm->tfm_ni, fp );
put_halfword( tpfm->tfm_nl, fp );
put_halfword( tpfm->tfm_nk, fp );
put_halfword( tpfm->tfm_ne, fp );
put_halfword( tpfm->tfm_np, fp );
/*
* write the TFM File Header
*/
put_fullword( hdfm->tfm_checksum, fp );
put_fullword( hdfm->tfm_design_size, fp );
for ( i = 0 ; i < 40 ; ++i )
putc( hdfm->tfm_coding[i], fp );
for ( i = 0 ; i < 20 ; ++i )
putc( hdfm->tfm_fontid[i], fp );
putc( hdfm->tfm_7bitsafe, fp );
putc( hdfm->tfm_unused[0], fp );
putc( hdfm->tfm_unused[1], fp );
putc( hdfm->tfm_face, fp );
/*
* write the TFM Character Data
*/
for ( i = tpfm->tfm_bc ; i <= tpfm->tfm_ec ; ++i )
{
put_fullword( chfm[i].char_info, fp );
}
/*
* write the TFM Character widths table
*/
for ( i = 0 ; i < num_tfm_width ; ++i )
put_fullword( tfm_width_table[i], fp );
/*
* write the TFM Character heights table
*/
for ( i = 0 ; i < num_tfm_height ; ++i )
put_fullword( tfm_height_table[i], fp );
/*
* write the TFM Character depths table
*/
for ( i = 0 ; i < num_tfm_depth ; ++i )
put_fullword( tfm_depth_table[i], fp );
/*
* write the TFM Character italic corrections table
*/
for ( i = 0 ; i < num_tfm_charic ; ++i )
put_fullword( tfm_charic_table[i], fp );
/*
* write the TFM Font Parameters
*/
put_fullword( pafm->tfm_slant, fp );
put_fullword( pafm->tfm_space, fp );
put_fullword( pafm->tfm_space_stretch, fp );
put_fullword( pafm->tfm_space_shrink, fp );
put_fullword( pafm->tfm_x_height, fp );
put_fullword( pafm->tfm_quad, fp );
put_fullword( pafm->tfm_extra_space, fp );
}