home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Tex29 / StTeXsrc.zoo / src / tfm.c < prev    next >
C/C++ Source or Header  |  1988-03-13  |  12KB  |  485 lines

  1.  
  2. /*
  3.  * @(#)tfm.c 2.7 EPA
  4.  *
  5.  * Copyright 1987,1988 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  * 
  11.  */
  12.  
  13. #include "tex.h"
  14. #include "box.h"
  15. #include "scan.h"
  16. #include "token.h"
  17. #include "tokenstack.h"
  18. #include "file.h"
  19. #include "tfm.h"
  20.  
  21. /*
  22.  *  Read and check the font data;
  23.  *  If the TFM file is malformed, goto bad_tfm;
  24.  *  If there is no room for this font, say so and goto done;
  25.  *  otherwise, incr(font_ptr) and goto done
  26.  */
  27.  
  28. byte_file   tfm_file;
  29.  
  30. qqqq    null_character;
  31.  
  32. ptr     fmem_ptr;
  33. mword   font_info[FONT_MEM_SIZE];
  34.  
  35. fnt     font_ptr = FONT_BASE;
  36. qqqq    font_check[FONT_MAX];
  37. scal    font_size[FONT_MAX];
  38. scal    font_dsize[FONT_MAX];
  39. hword   font_params[FONT_MAX];
  40. str     font_name[FONT_MAX];
  41. str     font_area[FONT_MAX];
  42. byte    font_bc[FONT_MAX];
  43. byte    font_ec[FONT_MAX];
  44. ptr     font_glue[FONT_MAX];
  45. bool    font_used[FONT_MAX];
  46. int     hyphen_char[FONT_MAX];
  47. int     skew_char[FONT_MAX];
  48. ptr     char_base[FONT_MAX];
  49. ptr     width_base[FONT_MAX];
  50. ptr     height_base[FONT_MAX];
  51. ptr     depth_base[FONT_MAX];
  52. ptr     italic_base[FONT_MAX];
  53. ptr     lig_kern_base[FONT_MAX];
  54. ptr     kern_base[FONT_MAX];
  55. ptr     exten_base[FONT_MAX];
  56. ptr     param_base[FONT_MAX];
  57.  
  58. #define start_font_error_message() \
  59.     {print_err("Font "); sprint_cs(u); \
  60.     print_char('='); print_file_name(nom, aire, null_str); \
  61.     if (s >= 0) {print(" at "); print_scaled(s); print("pt");} \
  62.     else if (s != -1000) {print(" scaled "); print_int(-s);}}
  63.  
  64. #define get_font_byte() \
  65.     (font_byte = getc(tfm_file))
  66.  
  67. #define read_sixteen(X) \
  68.     {get_font_byte(); X = font_byte; \
  69.     if (X > 127) goto bad_tfm; \
  70.     get_font_byte(); X = (X) * 0400 + font_byte;}
  71.  
  72. #define store_four_quarters(Q) \
  73.     {a = get_font_byte(); b = get_font_byte(); \
  74.     c = get_font_byte(); d = get_font_byte(); \
  75.     qw.b0 = qi(a); qw.b1 = qi(b); \
  76.     qw.b2 = qi(c); qw.b3 = qi(d); Q = qw;}
  77.  
  78. #define store_scaled(S) \
  79.     {a = get_font_byte(); b = get_font_byte(); \
  80.     c = get_font_byte(); d = get_font_byte(); \
  81.     sw = ((((d * z) / 0400) + (c * z)) / 0400 + (b * z)) / beta; \
  82.     if (a == 0) S = sw; else if (a == 255) S = sw - alpha; \
  83.     else goto bad_tfm;}
  84.  
  85. #define check_byte_range(C)     {if (C < bc || C > ec) goto bad_tfm;}
  86. #define ccbwo                   (k + bc - fmem_ptr)
  87. #define adjust(I)               (I[f] = qo(I[f]))
  88.  
  89. fnt
  90. read_font_info (u, nom, aire, s)
  91.     fnt     u;
  92.     str     nom;
  93.     str     aire;
  94.     scal    s;
  95. {
  96.     byte    a;
  97.     byte    b;
  98.     byte    c;
  99.     byte    d;
  100.     fnt     f;
  101.     fnt     g;
  102.     int     k;
  103.     scal    z;
  104.     hword   bc;
  105.     hword   ec;
  106.     hword   lf;
  107.     hword   lh;
  108.     hword   nd;
  109.     hword   ne;
  110.     hword   nh;
  111.     hword   ni;
  112.     hword   nk;
  113.     hword   nl;
  114.     hword   np;
  115.     hword   nw;
  116.     qqqq    qw;
  117.     scal    sw;
  118.     val     alpha;
  119.     hword   beta;
  120.     bool    file_opened;
  121.     byte    font_byte;
  122.     qqqq    dev_null;
  123. /*
  124.  *  Open tfm_file for input
  125.  */
  126.     g = null_font;
  127.     file_opened = FALSE;
  128.     pack_file_name(nom, aire, str_tfm);
  129.     if ((tfm_file = b_open_in()) == NULL)
  130.         goto bad_tfm;
  131.     file_opened = TRUE;
  132. /*
  133.  *  Read the TFM size fields
  134.  */
  135.     read_sixteen(lf);
  136.     read_sixteen(lh);
  137.     read_sixteen(bc);
  138.     read_sixteen(ec);
  139.     if (bc > ec + 1 || ec > 255) goto bad_tfm;
  140.     read_sixteen(nw);
  141.     read_sixteen(nh);
  142.     read_sixteen(nd);
  143.     read_sixteen(ni);
  144.     read_sixteen(nl);
  145.     read_sixteen(nk);
  146.     read_sixteen(ne);
  147.     read_sixteen(np);
  148.     if (lf != 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np) 
  149.         goto bad_tfm;
  150. /*
  151.  *  Use size fields to allocate font information
  152.  */
  153.     lf = lf - 6 - lh;
  154.     if (np < 7) lf += 7 - np;
  155.     if (font_ptr == FONT_MAX-1 || fmem_ptr + lf >= FONT_MEM_SIZE) {
  156.         start_font_error_message();
  157.         print(" not loaded: No more room.");
  158.         help_font();
  159.         error();
  160.         goto done;
  161.     }
  162.  
  163.     f = font_ptr + 1;
  164.     char_base[f] = fmem_ptr - bc;
  165.     width_base[f] = char_base[f] + ec + 1;
  166.     height_base[f] = width_base[f] + nw;
  167.     depth_base[f] = height_base[f] + nh;
  168.     italic_base[f] = depth_base[f] + nd;
  169.     lig_kern_base[f] = italic_base[f] + ni;
  170.     kern_base[f] = lig_kern_base[f] + nl;
  171.     exten_base[f] = kern_base[f] + nk;
  172.     param_base[f] = exten_base[f] + ne;
  173. /*
  174.  *  Read the TFM header
  175.  */
  176.     if (lh < 2) goto bad_tfm;
  177.     store_four_quarters(font_check[f]);
  178.     read_sixteen(z);
  179.     get_font_byte();
  180.     z = z * 0400 + font_byte;
  181.     get_font_byte();
  182.     z = z * 020 + font_byte / 020;
  183.     if (z < UNITY) goto bad_tfm;
  184.     while (lh > 2) {
  185.         store_four_quarters(dev_null);
  186.         decr(lh);
  187.     }
  188.     font_dsize[f] = z;
  189.     if (s != -1000) {
  190.         if (s >= 0)
  191.             z = s;
  192.         else z = xn_over_d(z, -s, 1000L);
  193.     }
  194.     font_size[f] = z;
  195. /*
  196.  *  Read  character data
  197.  */
  198.     for (k = fmem_ptr; k < width_base[f]; incr(k)) {
  199.         store_four_quarters(font_info[k].qqqq);
  200.         if (a >= nw || b / 020 >= nh || b % 020 >= nd || c / 4 > ni) 
  201.             goto bad_tfm;
  202.         switch (c % 4)
  203.         {
  204.         case LIG_TAG:
  205.             if (d >= nl) goto bad_tfm;
  206.             break;
  207.         
  208.         case EXT_TAG:
  209.             if (d >= ne) goto bad_tfm;
  210.             break;
  211.         
  212.         case LIST_TAG:
  213.             check_byte_range(d);
  214.             while (d < ccbwo) {
  215.                 qw = char_info(f, d);
  216.                 if (char_tag(qw) != LIST_TAG)
  217.                     goto not_found;
  218.                 d = qo(rem_byte(qw));
  219.             }
  220.             if (d == ccbwo) goto bad_tfm;
  221.             break;
  222.  
  223.         not_found:
  224.             break;
  225.         }
  226.     }
  227. /*
  228.  *  Read box dimensions
  229.  */
  230.     alpha = 16;
  231.     while (z >= 040000000) {
  232.         z >>= 1;
  233.         alpha <<= 1;
  234.     }
  235.     beta = 256 / alpha;
  236.     alpha *= z;
  237.     for (k = width_base[f]; k < lig_kern_base[f]; incr(k))
  238.         store_scaled(font_info[k].sc);
  239.     if (font_info[width_base[f]].sc != 0) 
  240.         goto bad_tfm;
  241.     if (font_info[height_base[f]].sc != 0) 
  242.         goto bad_tfm;
  243.     if (font_info[depth_base[f]].sc != 0) 
  244.         goto bad_tfm;
  245.     if (font_info[italic_base[f]].sc != 0) 
  246.         goto bad_tfm;
  247. /*
  248.  *  Read ligature/kern programs
  249.  */
  250.     for (k = lig_kern_base[f]; k < kern_base[f]; incr(k)) {
  251.         store_four_quarters(font_info[k].qqqq);
  252.         check_byte_range(b);
  253.         if (c < KERN_FLAG) { 
  254.             check_byte_range(d);
  255.         } else if (d >= nk)
  256.             goto bad_tfm;
  257.     }
  258.     if (nl > 0 && a < STOP_FLAG)
  259.         goto bad_tfm;
  260.  
  261.     for (k = kern_base[f]; k < exten_base[f]; incr(k))
  262.         store_scaled(font_info[k].sc);
  263. /*
  264.  *  Read extensible character recipes
  265.  */
  266.     for (k = exten_base[f]; k < param_base[f]; incr(k)) {
  267.         store_four_quarters(font_info[k].qqqq);
  268.         if (a != 0)
  269.             check_byte_range(a);
  270.         if (b != 0)
  271.             check_byte_range(b);
  272.         if (c != 0)
  273.             check_byte_range(c);
  274.         check_byte_range(d);
  275.     }
  276. /*
  277.  *  Read font parameters
  278.  */
  279.     for (k = 1; k <= np; incr(k)) {
  280.         if (k == 1) {
  281.             get_font_byte();
  282.             sw = font_byte;
  283.             if (sw > 127)
  284.                 sw -= 256;
  285.             get_font_byte();
  286.             sw = sw * 0400 + font_byte;
  287.             get_font_byte();
  288.             sw = sw * 0400 + font_byte;
  289.             get_font_byte();
  290.             font_info[param_base[f]].sc = sw * 020 + font_byte / 020;
  291.         } else {
  292.             store_scaled(font_info[param_base[f] + k - 1].sc);
  293.         }
  294.     }
  295.     if (feof(tfm_file))
  296.         goto bad_tfm;
  297.  
  298.     for (k = np + 1; k <= 7; incr(k))
  299.         font_info[param_base[f] + k - 1].sc = 0;
  300. /*
  301.  *  Make final adjustments and done
  302.  */
  303.     font_params[f] = (np >= 7) ? np : 7;
  304.     hyphen_char[f] = default_hyphen_char;
  305.     skew_char[f] = default_skew_char;
  306.     font_name[f] = nom;
  307.     font_area[f] = aire;
  308.     font_bc[f] = bc;
  309.     font_ec[f] = ec;
  310.     font_glue[f] = NULL;
  311.     adjust(char_base);
  312.     adjust(width_base);
  313.     adjust(lig_kern_base);
  314.     adjust(kern_base);
  315.     adjust(exten_base);
  316.     decr(param_base[f]);
  317.     fmem_ptr += lf;
  318.     font_ptr = f;
  319.     g = f;
  320.     goto done;
  321.  
  322. bad_tfm:
  323.     start_font_error_message();
  324.     if (file_opened)
  325.         print(" not loadable: Bad metric (TFM) file");
  326.     else print(" not loadable: Metric (TFM) file not found");
  327.     help_tfm();
  328.     error();
  329.     return null_font;
  330.  
  331. done:
  332.     b_close(tfm_file);
  333.     return g;
  334. }
  335.  
  336. scan_font_ident ()
  337. {   
  338.     fnt     f;
  339.     int     m;
  340.  
  341.     get_nbx_token();
  342.     if (cur_cmd == DEF_FONT) {
  343.         f = cur_font;
  344.     } else if (cur_cmd == SET_FONT) {
  345.         f = cur_chr;
  346.     } else if (cur_cmd == DEF_FAMILY) {
  347.         m = cur_chr;
  348.         scan_four_bit_int();
  349.         f = equiv(m + cur_val);
  350.     } else {
  351.         print_err("Missing font identifier");
  352.         help_font_cs();
  353.         back_error();
  354.         f = null_font;
  355.     }
  356.     cur_val = f;
  357. }
  358.  
  359. find_font_dimen (writing)
  360.     bool    writing;
  361. {
  362.     fnt     f;
  363.     int     n;
  364.  
  365.     scan_int();
  366.     n = cur_val;
  367.     scan_font_ident();
  368.     f = cur_val;
  369.     if (n <= 0) {
  370.         cur_val = fmem_ptr;
  371.     } else {
  372.         if (writing &&
  373.             n <= SPACE_SHRINK_CODE &&
  374.             n >= SPACE_CODE &&
  375.             font_glue[f] != NULL) {
  376.             delete_glue_ref(font_glue[f]);
  377.             font_glue[f] = NULL;
  378.         }
  379.         if (n > font_params[f]) {
  380.             if (f < font_ptr) {
  381.                 cur_val = fmem_ptr;
  382.             } else {
  383.                 do {
  384.                     if (fmem_ptr == FONT_MEM_SIZE)
  385.                         overflow("font_memory", FONT_MEM_SIZE);
  386.                     font_info[fmem_ptr].sc = 0;
  387.                     incr(fmem_ptr);
  388.                     incr(font_params[f]);
  389.                 } while (n != font_params[f]);
  390.                 cur_val = fmem_ptr - 1;
  391.             }
  392.         } else {
  393.             cur_val = n + param_base[f];
  394.         }
  395.     }
  396.     if (cur_val == fmem_ptr) {
  397.         print_nl("! Font ");
  398.         print_esc("");
  399.         print_str(font_id_text(f));
  400.         print(" has only ");
  401.         print_int(font_params[f]);
  402.         print(" fontdimen parameters");
  403.         help_font_param();
  404.         error();
  405.     }
  406. }
  407.  
  408. char_warning (f, c)
  409.     fnt     f;
  410.     byte    c;
  411. {
  412.     if (tracing_lost_chars > 0) {
  413.         begin_diagnostic();
  414.         print_nl("Missing character: There is no ");
  415.         print_ASCII(c);
  416.         print(" in font ");
  417.         print_str(font_name[f]);
  418.         print_char('!');
  419.         end_diagnostic(FALSE);
  420.     }
  421. }
  422.  
  423. ptr
  424. new_character (f, c)
  425.     fnt     f;
  426.     byte    c;
  427. {
  428.     ptr     p;
  429.  
  430.     if (font_bc[f] <= c && font_ec[f] >= c) {
  431.         if (char_exists(char_info(f, qi(c)))) {
  432.             p = get_avail();
  433.             font(p) = f;
  434.             character(p) = qi(c);
  435.             return p;
  436.         }
  437.     }
  438.     char_warning(f, c);
  439.     return NULL;
  440. }
  441.  
  442. init_tfm ()
  443. {
  444.     fmem_ptr = 7;
  445.     font_params[0] = 7;
  446.     font_bc[0] = 1;
  447.     font_glue[0] = zero_glue;
  448.     hyphen_char[0] = '-';
  449.     skew_char[0] = -1;
  450.     param_base[0] = -1;
  451. }
  452.  
  453. /*
  454.  *  Help text
  455.  */
  456.  
  457. help_font ()
  458. {
  459.     help4("I'm afraid I won't be able to make use of this font,",
  460.     "because my memory for character-size data is too small.",
  461.     "If you're really stuck, ask a wizard to enlarge me.",
  462.     "Or maybe try `I\\font<same font id>=<name of loaded font>'.");
  463. }
  464.  
  465. help_tfm ()
  466. {
  467.     help5("I wasn't able to read the size data for this font,",
  468.     "so I will ignore the font specification.",
  469.     "[Wizards can fix TFM files using TFtoPL/PLtoTF.]",
  470.     "You might try inserting a different font spec;",
  471.     "e.g., type `I\\font<same font id>=<substitute font name>'.");
  472. }
  473.  
  474. help_font_param ()
  475. {
  476.     help2("To increase the number of font parameters, you must",
  477.     "use \\fontdimen immediately after the \\font is loaded.");
  478. }
  479.  
  480. help_font_cs ()
  481. {
  482.     help2("I was looking for a control sequence whose",
  483.     "current meaning has been defined by \\font.");
  484. }
  485.