Chapter 10
Font Information from TeX Font Metric (tfm) Files

   10.1 Memory and Initialization
      Storage for New Font
      Get Data
      Script lg-font-fmt
   10.2 XeLaTeX: Scan Xdv Font Entry (Native Font Def)
      Font Definition
      Within IVD
      ????????????????
   10.3 Connecting to the Font Table
      Verify that Font has not been Already Defined
      Access to Fonts
   10.4 Opening a Font File
   10.5 Scanning a Font File
      Layout
      Breakdown
      Header Information
      Character Information
      Width Table
      Height Table
      Depth Table
      Italic Correction Table
      Ligature Table
      kern table
      Extensible Table
      Font Dimension Parameters
   10.6 Computing Font Info
      Characters’ Width
      Characters’ Height
      Characters’ Depth
      Other Sizes

Managed by load-font (font 0font 63, font 1-bytefont int) and activate-font (def 1-byte fontdef 4 byte font) commands.

10.1 Memory and Initialization

A font def looks like:

FNT_DEF1...FNT_DEF4 
            1,2,3 ubytes or 4 bytes     font number 
                           4 ubytes     checksum 
                           4 ubytes     scale 
                           4 ubytes     design size 
                             1 byte     length of directory name 
                             1 byte     length of file name 
             dir-ln + file-ln bytes     fontname 

Checksums are used to verify consistency between tfm and gf font files.

000284: FNT_DEF1: 29 
000286:           checksum         : -538297224 
000290:           scale            : 655360 
000294:           design           : 655360 
000298:           name             : cmtt10 
000306: FNT_DEF1: .... 

<..types..>+
 struct font_entry {
  INTEGER num;
  INTEGER scale;
  INTEGER design_sz;
  <.mag of font.>
  <.family+size of font.>
  <.entries from font file into font-tbl.>
  <.entries for html chars in font-tbl.>
  <.entries for math classes.>
  <.entries for xetex.>
 };
 -_-_-

<..defines..>+
 #define design_size_to_pt(n)    ((double)n / (double)(1L<<20))
 -_-_-

<..vars..>+
 static struct font_entry*  font_tbl;
 static int font_tbl_size = 0;
 -_-_-

Storage for New Font

The standard fonts of Knuth have design size of 0x90000 for fonts of size 9, 0xa0000 for size 10, etc.

<..scan font entry..>
 #ifdef MAXFONTS
 if( (font_tbl_size + 1) < MAXFONTS )
 #endif
 {
               INTEGER new_font_checksum;
               int font_name_n;
    font_tbl = font_tbl_size?
               (struct font_entry *) r_alloc((void *) font_tbl,
                  (size_t) ((font_tbl_size+1)
                            * sizeof(struct font_entry)))
             : m_alloc(struct font_entry, 1);
    if(       (version_id == <.version xdv.>)
          &&  (ch == <.xdv-native-font-def op.>)
    ){
       <.scan xdv font entry.>
    } else {
       <.scan dvi font entry.>
    }
    <.get html characters.>
    <.get css entries.>
    free((void *)  new_font_name);   font_tbl_size++;
 }
 #ifdef MAXFONTS
  else err_i_int(17, MAXFONTS);
 #endif
 -_-_-

<..scan dvi font entry..>
 <.scan font id.>
 new_font_checksum  = (INTEGER) get_int(4);
 new_font.scale     = (INTEGER) get_unt(4);
 new_font.design_sz = (INTEGER) get_unt(4);
 <.get font name.>
 <.get font info.>
 -_-_-

<..vars..>+
 static char*  new_font_name;
 -_-_-

<..defines..>+
 #define new_font   font_tbl[font_tbl_size]
 -_-_-

Get Data

<..scan font id..>
 switch( ch ){
   case <.def 1 byte font.>:
   case <.def 2 byte font.>:
   case <.def 3 byte font.>: {
      new_font.num = (INTEGER)
                       get_unt(ch - <.def 1 byte font.> + 1); break; }
   case <.def 4 byte font.>: {
      new_font.num = (INTEGER) get_int(4);  break; }
   default: err_i(8);
 }
 -_-_-

<..get font name..>
 {    int  n, area_ln;
      U_CHAR *ch;
   area_ln = (int) get_unt(1);
   font_name_n = (int) get_unt(1);
   n =  area_ln + font_name_n + 1;
   ch = new_font_name = m_alloc(char, n);
   while( --n ){  *ch = (int) get_unt(1); ch++; }
   *ch = ’\0’;
 }
 -_-_-

<..get font info..>
 <.first definition of font?.>
 <.open font file.>
 new_font_name[font_name_n] = ’\0’;
 new_font.name = m_alloc(char, font_name_n + 1);
 (IGNORED) strcpy((char *)  new_font.name, (char *) new_font_name );
 <.family and size of font.>
 <.compute mag of font.>
 -_-_-

The following is computed from ‘scale’ and ‘design_sz’. We take it here relative to 100.

<..compute mag of font..>
 new_font.mag = new_font.scale / (new_font.design_sz / 100);
 -_-_-

<..mag of font..>
 INTEGER mag;
 -_-_-

<..family+size of font..>
 char *family_name, *font_size;
 -_-_-

<..family and size of font..>
 {    int n, i;
    for( n=0; n<font_name_n; n++ ){
      if(  ( ’0’ <= new_font_name[n] ) && ( new_font_name[n] <= ’9’ )){
        break;
      }
    }
    <.real size?.>
    new_font.family_name = m_alloc(char, n + 2);
    new_font.font_size  = m_alloc(char, font_name_n - n + 1 );
    for( i=0; i<n; i++ ){
      new_font.family_name[i] = new_font_name[i];
    }
    new_font.family_name[i] = ’\0’;   i = 0;
    while(  n<font_name_n ){
      new_font.font_size[i++] = new_font_name[n++];
    }
    new_font.font_size[i] = ’\0’;
 }
 -_-_-

<..real size?..>
 {                       int m;
    for( m=n; m<font_name_n; m++ ){
      if(  ( new_font_name[m] < ’0’ ) || ( new_font_name[m] > ’9’ )){
        n=font_name_n;
        break;
 }  } }
 -_-_-

When the size is not zero, n+2 can be reduced to n+1.

<..output to lg file..>
 (IGNORED) fprintf(log_file, lg_font_fmt,
   font_tbl[cur_fnt].family_name,
   font_tbl[cur_fnt].font_size,
   (int)( font_tbl[cur_fnt].design_sz * 100 / 655360 / 10),
   font_tbl[cur_fnt].mag);
 -_-_-

Fosome font names (e.g., Chinese: gbkhei65) we don’t want the number to be treated as font-size:

<..check name decomposition..>
 if( (strlen((char *) new_font.family_name) +
      strlen((char *) new_font.font_size) + 4) == strlen((char *) name) ){
   new_font.family_name = (char *) r_alloc((void *) new_font.family_name,
                          (size_t) (strlen((char *) name)+1));
   (IGNORED) strcat((char *) new_font.family_name, (char *) new_font.font_size);
   *(new_font.font_size)=’\0’;
 }
 -_-_-

Script lg-font-fmt

Font information to decorate characters, e.g., for style files.

<..h-defines..>
 #ifndef LGFNT
 #define LGFNT "Font(\"%s\",\"%s\",\"%d\",\"%d\")\n"
 #endif
 -_-_-

<..vars..>+
 static U_CHAR *lg_font_fmt = NULL;
 -_-_-

<..get from tex4ht.env file..>+
 lg_font_fmt = (char *) get_script(lg_font_fmt,LGFNT,’f’);
 -_-_-

10.2 XeLaTeX: Scan Xdv Font Entry (Native Font Def)

‘xelatex -no-pdf example’

XeTeX

The xetex code is at http://scripts.sil.org/svn-public/xetex/TRUNK/ and xdvipdfmx is found under the texk directory.

Font Definition

<..scan xdv font entry..>
    unsigned short flags;
 new_font.num       = (INTEGER) get_unt(4);
 new_font.scale     = (INTEGER) get_unt(4);
 new_font.design_sz = new_font.scale;
 flags = (INTEGER) get_unt(2);
 <.get xdv font name.>
 new_font.layout_dir = (flags & <.xdv flag vertical.>) ? 1 : 0;
 new_font.rgba_color = (flags & <.xdv flag colored.>)?
                                    (unsigned long) get_unt(4)
                                    :
                                    0xffffffff;
 if( flags & <.xdv flag variations.> ){
    int n =  (INTEGER) get_unt(2);  number of variations
    int i;
    for (i = 0; i < n; ++i) {       ignore axis
          (void) get_unt(4);
    }
    for (i = 0; i < n; ++i) {       ignore value of variation
       (void) get_int(4);
 }  }
 (IGNORED) printf("(--- xdv font = %s (not implemented) ---)\n", new_font_name);
 <.get xdv font info.>
 -_-_-

<..get xdv font name..>
 {    int  n, family_name_n, style_name_n;
      U_CHAR *ch;
      char* family_name;
      char* style_name;

   font_name_n =  (INTEGER) get_unt(1);
   family_name_n = (INTEGER) get_unt(1);
   style_name_n  = (INTEGER) get_unt(1);
   n =  font_name_n + 1;
   ch = new_font_name = m_alloc(char, n);
   while( --n ){  *ch = (int) get_unt(1); ch++; }
   *ch = ’\0’;
   n =  family_name_n + 1;
   ch = family_name = m_alloc(char, n);
   while( --n ){ *ch = (int) (void) get_unt(1); ch++; }
   *ch = ’\0’;
   n =  style_name_n + 1;
   ch = style_name = m_alloc(char, n);
   while( --n ){ *ch = (int) (void) get_unt(1); ch++; }
   *ch = ’\0’;
 }
 -_-_-

REMOVE allocated mem at end of usage!!

<..entries for xetex..>
 INTEGER layout_dir;
 unsigned long rgba_color;
 -_-_-

<..xdv flag vertical..>
 0x0100
 -_-_-

<..xdv flag colored..>
 0x0200
 -_-_-

<..xdv flag variations..>
 0x0800
 -_-_-

Within IVD

<..font defs for xdv’s idv?..>
 (version_id == <.version xdv.>)
 &&
 (
   (ch == <.xdv-pic-file op.>)
   ||
   (ch == <.xdv-native-font-def op.>)
   ||
   (ch == <.xdv-glyph-array op.>)
   ||
   (ch == <.xdv-glyph-string op.>)
 )
 -_-_-

<..xdv flag fonttype icu..>
 0x0002
 -_-_-

<..xdv flag fonttype atsui..>
 0x0001
 -_-_-

<..xdv font def for idv..>
 switch( ch ){
   case <.xdv-native-font-def op.>:
      <.xdv/ivd native font def.>
      break;
   case <.xdv-glyph-string op.>:
      <.xdv/idv glyph string.>
      break;
   default:
     printf(" ===> ---------- xdv’s idv ------------ <====  %d\n" , ch);
 }
 -_-_-

<..xdv/idv glyph string..>
 {
            int i, glyphCount;
    (void) get_unt(4);
    glyphCount = (INTEGER) get_unt(2);
    for( i = 0; i < glyphCount; ++i ){
      (void) get_int(4);
    }
    for (i = 0; i < glyphCount; ++i){
      (void) get_unt(2);
    }
 }
 -_-_-

<..xdv/ivd native font def..>
 {      int i, flags;
 
 (void) get_unt(4);  tex_id
 (void) get_unt(4);  scale
 
     flags = (INTEGER) get_unt(2);
 
 
 
 if ((flags & <.xdv flag fonttype icu.>) || (flags & <.xdv flag fonttype atsui.>)) {
 
 for (
 i =
   (INTEGER) get_unt(1)     font name 
 +  (INTEGER) get_unt(1)       family name 
  + (INTEGER) get_unt(1)     style name 
 ;
 i>0;
 i--
 ){ (void) get_unt(1); }
 
 
 
 
 
         if( flags & <.xdv flag colored.> ){
            (void) get_unt(4);
         }
 
 if( flags & <.xdv flag variations.> ){
    int n =  (INTEGER) get_unt(2);  number of variations
    for (i = 0; i < n; ++i) {       ignore axis
          (void) get_unt(4);
    }
    for (i = 0; i < n; ++i) {       ignore value of variation
       (void) get_int(4);
 }  }
 
 }
 
 }
 -_-_-

????????????????

<..get xdv font info..>
 <.first definition of font?.>
 <.open xdv font file.>
 new_font_name[font_name_n] = ’\0’;
 new_font.name = m_alloc(char, font_name_n + 1);
 (IGNORED) strcpy((char *)  new_font.name, (char *) new_font_name );
 <.family and size of font.>
 <.compute mag of xdv font.>
 -_-_-

<..compute mag of xdv font..>
 new_font.mag = new_font.scale / (new_font.design_sz / 100);
 -_-_-

<..open xdv font file..>
 {       FILE *font_file;
         U_CHAR  file_name[256]; 

    <.search dirs for xdv font.>
 /*
    if( font_file == NULL ){
       dump_env();      err_i_str(1,file_name);
       missing_fonts = TRUE;
       new_font.char_f = 2;
       new_font.char_l = 1;
    } else {
 */
       <.get xdv chars dimensions.>
 /*
       (IGNORED) fclose(font_file);
    }
 */
 }
 -_-_-

<..get xdv chars dimensions..>
 {       <.vars for reading xdv font file.>
    <.scan xdv dimension of components of font file.>
    <.scan XDV header of font file.>
    <.scan xdv char info words.>
    <.scan xdv width table.>
    <.scan xdv height table.>
    <.scan XDV depth table.>
    <.scan XDV italic correction table.>
    <.scan XDV lig/kern table.>
    <.scan XDV kern table.>
    <.scan XDV extensible character table.>
    <./xdv fontdimen parameters.>
 }
 -_-_-

<../xdv fontdimen parameters..>
 <.xdv font slant.>             all need design_size_to_pt(n)
 <.xdv interword space.>
 <.XDV interword stretch.>
 <.XDV interword shrink.>
 <.xdv ex height.>
 <.XDV em width (=quad width).>
 <.XDV extra space.>
 -_-_-

<..xdv font slant..>
 new_font.it = 0;
 -_-_-

<..xdv interword space..>
 new_font.word_sp = 350000;
 <.adjust inter-word space.>
 -_-_-

<..ex height..>
 new_font.ex = 450000;
 -_-_-

<..scan xdv dimension of components of font file..>
 new_font.char_f = 0;
 new_font.char_l = 255;
 new_font.wtbl_n = 0;
 new_font.htbl_n = 0;
 new_font.dtbl_n = 0;
 -_-_-

it˙correction˙table˙length = 0; lig˙kern˙table˙length = 0; kern˙table˙length = 0; extensible˙char˙table˙length = 0; num˙font˙parameters = 0;

<..vars for reading xdv font file ..>
  int
      it_correction_table_length,
      lig_kern_table_length,
      kern_table_length,
      extensible_char_table_length,     <= 256
      num_font_parameters;
 -_-_-

<..scan xdv char info words..>
 {      U_CHAR *ch, *hidp;
        int i;
    ch = new_font.char_wi = m_alloc(char, new_font.char_l
                                        - new_font.char_f + 1);
    hidp = new_font.char_hidp = m_alloc(char, new_font.char_l
                                        - new_font.char_f + 1);
    for( i = new_font.char_f; i <= new_font.char_l; i++ ){
       *(ch++) = 10;
       *(hidp++) = 26;
 }  }
 -_-_-

<..scan xdv width table..>
 {       INTEGER *p;         needs design_size_to_pt(n)
             int  i;
    p = new_font.wtbl = m_alloc( INTEGER, new_font.wtbl_n);
    for( i = 0; i < new_font.wtbl_n; i++ ){
       *(p++) = 600000;
 }  }
 -_-_-

<..scan xdv height table..>
 {       INTEGER *p;         needs design_size_to_pt(n)
             int  i;
    p = new_font.htbl = m_alloc( INTEGER, new_font.htbl_n);
    for( i = 0; i < new_font.htbl_n; i++ ){
       *(p++) = 600000;
 }  }
 -_-_-

<..skip font xdv def..>
         unsigned short flags;
 for( i=0; i<8; i++ ){ ch = get_char(); }
 flags = (INTEGER) get_unt(2);
 for( i = (INTEGER) get_unt(1)  font name 
        + (INTEGER) get_unt(1)  font family name
        + (INTEGER) get_unt(1)  font style name 
     ; i>0
     ; i-- ){ ch = get_char(); }
 if( flags & <.xdv flag colored.> ){ (INTEGER) get_unt(4); }
 if( flags & <.xdv flag variations.> ){
    int n =  (INTEGER) get_unt(2);
    int i;
    for (i = 0; i < n; ++i) {
          (void) get_unt(4);
    }
    for (i = 0; i < n; ++i) {
       (void) get_int(4);
 }  }
 -_-_-

<..do glyph array..>
 doGlyphArray(TRUE);
 -_-_-

<..do glyph string..>
 doGlyphArray(FALSE);
 -_-_-

<..header functions..>+
 static void doGlyphArray( ARG_I(BOOL) );
 -_-_-

<..functions..>+
 
 static void doGlyphArray(yLocs)
      BOOL yLocs
 ;{         int i, glyphCount;
    (void) get_unt(4);
    glyphCount = (INTEGER) get_unt(2);
    for( i = 0; i < glyphCount; ++i ){
      (void) get_int(4);
      if( yLocs ){  (void) get_int(4);   }
    }
    for (i = 0; i < glyphCount; ++i){
      (void) get_unt(2);
    }
 }
 -_-_-

10.3 Connecting to the Font Table

Verify that Font has not been Already Defined

<..first definition of font?..>
 {        int i;
    for( i=font_tbl_size-1; i>0;  i-- )
      if( new_font.num == font_tbl[i].num )  warn_i(10);   }
 -_-_-

Access to Fonts

<..search font in font-tbl..>
 cur_fnt = search_font_tbl( cur_fnt );
 word_sp = <.size of space.>;
 -_-_-

<..header functions..>+
 static int search_font_tbl( ARG_I(int) );
 -_-_-

<..functions..>+
 
 static int search_font_tbl( cur_fnt )
         int cur_fnt
 ;{      int i;
    for( i=0; i<font_tbl_size; i++){
      if( font_tbl[i].num == cur_fnt ){ return i; }
    }
    err_i_int( 6,cur_fnt );
    return 0;
 }
 -_-_-

10.4 Opening a Font File

<..open font file..>
 {       FILE *font_file;
         U_CHAR  file_name[256];
    <.search dirs for font.>
    if( font_file == NULL ){
       dump_env();      err_i_str(1,file_name);
       missing_fonts = TRUE;
       new_font.char_f = 2;
       new_font.char_l = 1;
    } else {
       <.get chars dimensions.>
       (IGNORED) fclose(font_file);
 }  }
 -_-_-

Some TeX systems provide virtual fonts without tfm files. Instead, they provide file of aliases with records of the form ‘virtual font name=actual font name’. In such a case, the location of a file of aliases can be provided within an a-record in tex4ht.env.

The tex4ht program ignores records having form different than ‘virtual font name=actual font name’.

The full names should be provided, without the .tfm extensions (e.g., gbksong33=GBKSONG33).

10.5 Scanning a Font File

TFM = TeX font metric

Layout

Dimensions are expressed in printers’ point units.

<..get chars dimensions..>
 {       <.vars for reading font file.>
    <.scan dimension of components of font file.>
    <.scan header of font file.>
    <.scan char info words.>
    <.scan width table.>
    <.scan height table.>
    <.scan depth table.>
    <.scan italic correction table.>
    <.scan lig/kern table.>
    <.scan kern table.>
    <.scan extensible character table.>
    <./fontdimen parameters.>
 }
 -_-_-

Breakdown

<..scan dimension of components of font file..>
 file_length                    = (INTEGER) fget_int(font_file,2);
 header_length                  = (int) fget_int(font_file,2);
 new_font.char_f = (int) fget_int(font_file,2);
 new_font.char_l = (int) fget_int(font_file,2);
 new_font.wtbl_n = (int) fget_int(font_file,2);
 new_font.htbl_n = (int) fget_int(font_file,2);
 new_font.dtbl_n = (int) fget_int(font_file,2);
 it_correction_table_length     = (int) fget_int(font_file,2);
 lig_kern_table_length          = (int) fget_int(font_file,2);
 kern_table_length              = (int) fget_int(font_file,2);
 extensible_char_table_length   = (int) fget_int(font_file,2);
 num_font_parameters            = (int) fget_int(font_file,2);
 if( file_length != ( 6                + header_length
      - new_font.char_f              + new_font.char_l + 1
      + new_font.wtbl_n              + new_font.htbl_n
      + new_font.dtbl_n              + it_correction_table_length
      + lig_kern_table_length        + kern_table_length
      + extensible_char_table_length + num_font_parameters  )
   ){ err_i_str(15,file_name); }
 -_-_-

Shouldn’t the hight table be of the same dim of the width and depth table?

<..vars for reading font file..>
  INTEGER  file_length;     all lengths are in words
  int    header_length,
      it_correction_table_length,
      lig_kern_table_length,
      kern_table_length,
      extensible_char_table_length,     <= 256
      num_font_parameters;
 -_-_-

<..entries from font file into font-tbl..>
  INTEGER design_pt;     needs design_size_to_pt(n)
  int char_f, char_l;    0 --- 255
  U_CHAR *char_wi;
  U_CHAR *char_hidp;
  int  wtbl_n;
  int  htbl_n;
  int  dtbl_n;
  INTEGER  *wtbl;              needs design_size_to_pt(n)
  INTEGER  *htbl;              needs design_size_to_pt(n)
  INTEGER  *dtbl;              needs design_size_to_pt(n)
  INTEGER  word_sp;            needs design_size_to_pt(n)
  INTEGER  it;                 needs design_size_to_pt(n)
  INTEGER  ex;                 needs design_size_to_pt(n)
 -_-_-

Character codes beyond 255 assume the same width as their counterpart modulo 256 characters.

  header : array [0  -- lh - 1]  of stuff 
char_info: array [bc -- ec]      of char_info_word 
   width : array [0  -- nw - 1]  of fix_word 
   height: array [0  -- nh - 1]  of fix_word 
   depth : array [0  -- nd - 1]  of fix_word 
   italic: array [0  -- ni - 1]  of fix_word 
 lig_kern: array [0  -- nl - 1]  of lig_kern_command 
     kern: array [0  -- nk - 1]  of fix_word 
    exten: array [0  -- ne - 1]  of extensible_recipe 
   param : array [1  -- np]      of fix_word 

Header Information

<..scan header of font file..>
 <.scan checksum in font file.>
 <.scan design size in font file.>
 (IGNORED) fseek(font_file, (long) ((header_length - 2) * 4), <.relative file addr.>);
 -_-_-

Incompatible fonts shouldn’t agree in their check sum. A zero check sum should be disregarded.

<..scan checksum in font file..>
 {      INTEGER checksum;
    checksum = ( INTEGER) fget_int(font_file,4);
    if( checksum && new_font_checksum
                 && (checksum  != new_font_checksum) )
     {   warn_i(16);
         (IGNORED) fprintf(stderr,"%s: %d\ndvi file: %d\n",file_name,
                      checksum, new_font_checksum);
 }   }
 -_-_-

The design size of a font is represented in point units of TEX, and it must be greater than 1.0. The representation uses 32-bit words, with the leading 12 bits providing the integer part and the two-complement of a word providing negative values. The allowed values are in the range of 2048 220 to 2048.

<..scan design size in font file..>
 new_font.design_pt = ( INTEGER) fget_int(font_file,4); needs design_size_to_pt(n)
 -_-_-

Skipped optional identification of coding scheme (40 bytes), identification of font family (20 bytes), etc.

Character Information

<..scan char info words..>
 {      U_CHAR *ch, *hidp;
        int i;
    ch = new_font.char_wi = m_alloc(char, new_font.char_l
                                        - new_font.char_f + 1);
    hidp = new_font.char_hidp = m_alloc(char, new_font.char_l
                                        - new_font.char_f + 1);
    for( i = new_font.char_f; i <= new_font.char_l; i++ ){
       *(ch++) = (int) fget_unt(font_file,1);
       *(hidp++) = (int) fget_unt(font_file,1);
       (IGNORED) fseek(font_file, 2L, <.relative file addr.>);
 }  }
 -_-_-

Next comes the ‘char_info’ array, in which each word contains the following information for one character.

The width of a character is ‘width[width index] * design_pt’, etc. This compression scheme allows characters of a font to choose from 256 width-values, 16 height-values, etc. Since ‘width[0]=height[0]=depth[0]=italic[0]=0’, a character in the font should never have a zero index.

Width Table

<..scan width table..>
 {       INTEGER *p;         needs design_size_to_pt(n)
             int  i;
    p = new_font.wtbl = m_alloc( INTEGER, new_font.wtbl_n);
    for( i = 0; i < new_font.wtbl_n; i++ ){
       *(p++) = ( INTEGER) fget_int(font_file,4);
 }  }
 -_-_-

The above fits with measurements made for the fixed-sized font cmtt10, but not with the following measurements made for cmsy10.

182045, 327681, 509726, 509726, 436908, 436908, 436908, 509726, 
509726, 655361, 327681, 327681, 509726, 509726, 655361, 400498, 
509726, 509726, 436908, 436908, 364090, 364090, 509726, 655361, 
655361, 655361, 473316, 327681, 509726, 509726, 509726, 436908, 
344061, 655361, 327681, 327681, 655361, 655361, 655361, 212991, 
655361, 655361, 327681, 400498, 327681, 509726, 436908, 473316, 
180223, 655361, 436908, 436908, 582543, 582543, 344061, 344061, 
364090, 364090, 436908, 327681, 473316, 473316, 509726, 509726, 
400498, 523286, 450377, 383297, 523745, 404502, 536119, 428716, 
559789, 405233, 565248, 508817, 452018, 787021, 634289, 539946, 
509726, 535213, 555420, 446006, 523509, 475226, 455478, 701238, 
563429, 491886, 527019, 436908, 327681, 436908, 436908, 247723, 
400498, 400498, 291271, 291271, 291271, 291271, 327681, 327681, 
254863, 254863, 182045, 327681, 327681, 400498, 671742, 182045, 
546135, 491521, 546135, 345886, 436908, 436908, 509726, 509726, 
291273, 291271, 291271, 327681, 182045, 327681, 509726, 345886 

Height Table

<..scan height table..>
 {       INTEGER *p;         needs design_size_to_pt(n)
             int  i;
    p = new_font.htbl = m_alloc( INTEGER, new_font.htbl_n);
    for( i = 0; i < new_font.htbl_n; i++ ){
       *(p++) = ( INTEGER) fget_int(font_file,4);
 }  }
 -_-_-

For instance, the following table for cmr10

0,      110683, 384696, 451470, 524288, 553416, 595357, 611670, 
644958, 659002, 675749, 700301, 716526, 728178, 767499, 786432 

Depth Table

<..scan height table..>+
 {       INTEGER *p;         needs design_size_to_pt(n)
             int  i;
    p = new_font.dtbl = m_alloc( INTEGER, new_font.dtbl_n);
    for( i = 0; i < new_font.dtbl_n; i++ ){
       *(p++) = ( INTEGER) fget_int(font_file,4);
 }  }
 -_-_-

<..scan depth tableNO..>
                   needs design_size_to_pt(n)
 (IGNORED) fseek(font_file, (long) (depth_table_length * 4),
                            <.relative file addr.>);
 -_-_-

Italic Correction Table

Used for italic correction explicitly requested with ‘\/’, and for isolated character in math mode (MetaFont 315–316).

<..scan italic correction table..>
                                                    needs design_size_to_pt(n)
 (IGNORED) fseek(font_file, (long) (it_correction_table_length * 4),
             <.relative file addr.>);
 -_-_-

Ligature Table

Substitutions for specified runs of chrarcters

<..scan lig/kern table..>
 (IGNORED) fseek(font_file, (long) (lig_kern_table_length * 4),
              <.relative file addr.>);
 -_-_-

kern table

Space to add between specified pairs of characters.

<..scan kern table..>
                           needs design_size_to_pt(n)
 (IGNORED) fseek(font_file, (long) (kern_table_length * 4),
              <.relative file addr.>);
 -_-_-

Extensible Table

<..scan extensible character table..>
 (IGNORED) fseek(font_file, (long) (extensible_char_table_length * 4),
              <.relative file addr.>);
 -_-_-

Font Dimension Parameters

At least seven parameters used in \fontdimen, each occupying four bytes (= one word). With the exception of the first parameter, all the other parameters should be magnified for a font that is magnified with ‘at’ or ‘scaled’.

<../fontdimen parameters..>
 <.font slant.>             all need design_size_to_pt(n)
 <.interword space.>
 <.interword stretch.>
 <.interword shrink.>
 <.ex height.>
 <.em width (=quad width).>
 <.extra space.>
 -_-_-

10.6 Computing Font Info

Characters’ Width

<..return char width..>
 return (INTEGER)(
     <.(double) char_width( ch ).>
   );
 -_-_-

<..(double) char_width( chr )..>
 design_size_to_pt( *(font_tbl[cur_fnt].wtbl +
                   (int) <.chr width of.>) )
 * (double) font_tbl[cur_fnt].scale
 -_-_-

<..chr width of..>
 *(font_tbl[cur_fnt].char_wi +
        (chr - font_tbl[cur_fnt].char_f)% 256)
 -_-_-

<..(double) char_width( design_ch? design_ch : ch )..>
 design_size_to_pt( *(font_tbl[cur_fnt].wtbl
                  +  (int) (<.design-ch / ch width of.>)) )
    * (double) font_tbl[cur_fnt].scale
 -_-_-

<..design-ch / ch width of..>
 *(font_tbl[cur_fnt].char_wi +  (int)
    ( (design_ch? design_ch : ch) - font_tbl[cur_fnt].char_f)% 256)
 -_-_-

<..(double) char_width( ch )..>
 design_size_to_pt( *(font_tbl[cur_fnt].wtbl
                      +  (int) (<.ch of width.>) )
                  )
 * (double) font_tbl[cur_fnt].scale
 -_-_-

<..ch of width..>
 *(font_tbl[cur_fnt].char_wi +  (int)
    ( ch - font_tbl[cur_fnt].char_f)% 256)
 -_-_-

<..ch width..>
 (int)(<.(double) char_width( ch ).>)
 -_-_-

Characters’ Height

<..(double) char_height( ch )..>
 design_size_to_pt( *(font_tbl[cur_fnt].htbl
                  +  (int) (<.ch of height.>)) )
    * (double) font_tbl[cur_fnt].scale
 -_-_-

<..ch of height..>
 ( *(font_tbl[cur_fnt].char_hidp +  (int)
    ( ch - font_tbl[cur_fnt].char_f)% 256)
   >>  4
 ) & 0x0F
 -_-_-

<..ch height..>
 (int)(<.(double) char_height( ch ).>)
 -_-_-

Characters’ Depth

<..(double) char_depth( ch )..>
 design_size_to_pt( *(font_tbl[cur_fnt].dtbl
                  +  (int) (<.ch of depth.>)) )
 * (double) font_tbl[cur_fnt].scale
 -_-_-

<..ch of depth..>
 ( *(font_tbl[cur_fnt].char_hidp +  (int)
    ( ch - font_tbl[cur_fnt].char_f)% 256)
 ) & 0x0F
 -_-_-

<..ch depth..>
 (int)(<.(double) char_depth( ch ).>)
 -_-_-

Other Sizes

<..size of ex..>
 design_size_to_pt( 1.7 * (double) font_tbl[cur_fnt].ex )
 * (double) font_tbl[cur_fnt].scale
 -_-_-

<..size of space..>
 design_size_to_pt( font_tbl[cur_fnt].word_sp )
                    * (double) font_tbl[cur_fnt].scale
 -_-_-