home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / TEKST / CMTEX330 / SOURCE / TFM.C < prev    next >
C/C++ Source or Header  |  1992-02-19  |  12KB  |  588 lines

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