Back to index

tetex-bin  3.0
parse_ofm.c
Go to the documentation of this file.
00001 /* parse_ofm.h: Checking an existent OFM file 
00002 
00003 This file is part of Omega,
00004 which is based on the web2c distribution of TeX,
00005 
00006 Copyright (c) 1994--2001 John Plaice and Yannis Haralambous
00007 
00008 Omega is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 Omega is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Omega; if not, write to the Free Software Foundation, Inc.,
00020 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00021 
00022 */
00023 
00024 #include "cpascal.h"
00025 #include "list_routines.h"
00026 #include "header_routines.h"
00027 #include "manifests.h"
00028 #include "char_routines.h"
00029 #include "ligkern_routines.h"
00030 #include "out_ofm.h"
00031 #include "extra_routines.h"
00032 #include "param_routines.h"
00033 #include "dimen_routines.h"
00034 #include "error_routines.h"
00035 #include "print_routines.h"
00036 #include "out_routines.h"
00037 #include "font_routines.h"
00038 #include "parse_ofm.h"
00039 #include "omfonts.h"
00040 #include "manifests.h"
00041 
00042 unsigned top_char, top_width, top_height, top_depth, top_italic;
00043 unsigned start_ptr, check_sum_pos, design_size_pos, scheme_pos;
00044 unsigned seven_bit_flag_pos;
00045 unsigned random_word_pos, header_length;
00046 
00047 unsigned ivalues_start,fvalues_start,mvalues_start,
00048     rules_start,glues_start,penalties_start;
00049 unsigned ivalues_base,fvalues_base,mvalues_base,
00050     rules_base,glues_base,penalties_base;
00051 unsigned char_base,width_base,height_base,depth_base,italic_base;
00052 unsigned lig_kern_base,kern_base,exten_base,param_base;
00053   /* base addresses for the subfiles */
00054 unsigned char_start;
00055 unsigned bytes_per_entry;
00056 
00057 unsigned lf;
00058 boolean ofm_on;
00059 unsigned start_pos;
00060 unsigned family_pos;
00061 unsigned ofm_ptr;
00062 unsigned ncw;
00063 unsigned ncl;
00064 unsigned nce;
00065 unsigned nco;
00066 unsigned npc;
00067 
00068 void
00069 eval_two_bytes(unsigned *pos) {
00070   if (ofm[ofm_ptr]>127)
00071       fatal_error_0("One of the subfile sizes (2) is negative");
00072   *pos = ofm[ofm_ptr]*0x100 + ofm[ofm_ptr+1];
00073   ofm_ptr += 2;
00074 }
00075 
00076 void
00077 eval_four_bytes(unsigned *pos) {
00078   if (ofm[ofm_ptr]>127)
00079       fatal_error_0("One of the subfile sizes (4) is negative");
00080   *pos = ofm[ofm_ptr]*0x1000000 + ofm[ofm_ptr+1]*0x10000 +
00081          ofm[ofm_ptr+2]*0x100   + ofm[ofm_ptr+3];
00082   ofm_ptr += 4;
00083 }
00084 
00085 void
00086 parse_ofm(boolean read_ovf)
00087 {
00088     ofm_organize();
00089     if (read_ovf == TRUE) input_ovf_file();
00090     ofm_read_simple();
00091     if (read_ovf == TRUE) input_ovf_fonts();
00092     ofm_read_rest();
00093     if (read_ovf == TRUE) input_ovf_chars();
00094     print_characters(read_ovf);
00095 }
00096 
00097 /* parse_ofm ensures that all of the header entries are consistent.
00098    The file is assumed to have been read in already, with the
00099    contents in the ofm array (length_ofm bytes).
00100 */
00101 
00102 void
00103 ofm_organize(void)
00104 {
00105     unsigned char_ptr,copies,i,j;
00106 
00107     ofm_on = false; ofm_level = OFM_NOLEVEL; lf = 0; lh = 0;
00108     nco = 0; ncw = 0; npc = 0;
00109     bc = 0; ec = 0; nw = 0; nh = 0; nd = 0; ni = 0;
00110     nl = 0; nk = 0; ne = 0; np = 0;
00111     nki = 0; nwi = 0; nkf = 0; nwf = 0;
00112     nkm = 0; nwm = 0; 
00113     nkr = 0; nwr = 0; nkg = 0; nwg = 0;
00114     nkp = 0; nwp = 0; font_dir = 0;
00115 
00116     if (length_ofm < 8)
00117         fatal_error_0("File too short");
00118     lf = ofm[0]*256 + ofm[1];
00119     if (lf==0) { /* This is not a TFM file, it is an OFM-file */
00120         ofm_on = TRUE;
00121 
00122         /* next line edited by Thomas Esser, based on a patch send
00123          * by Hossein Movahhedian. The old code had " + 1"
00124          * instead of "+ 2" and caused lots of segfaults */
00125         ofm_level = ofm[2]*0x100 + ofm[3] + 2;
00126         if (ofm[4]>127)
00127             fatal_error_0("File length is negative");
00128         lf = ofm[4]*0x1000000 + ofm[5]*0x10000 + ofm[6]*0x100 + ofm[7];
00129     } else {
00130         ofm_on = FALSE;
00131         ofm_level  = OFM_TFM;
00132     }
00133     if ((lf*4)!=length_ofm)
00134        fatal_error_2("Stated (%d) and actual (%d) file length do not match",
00135                       lf*4, length_ofm);
00136     
00137     switch(ofm_level) {
00138         case OFM_TFM: { start_pos = 2; check_sum_pos = 24;  break; }
00139         case OFM_LEVEL0: { start_pos = 8; check_sum_pos = 56;  break; }
00140         case OFM_LEVEL1: { start_pos = 8; check_sum_pos = 116; break; }
00141         default: { fatal_error_1("OFMLEVEL %d not supported", ofm_level-1);
00142                    break; }
00143     }
00144     design_size_pos = check_sum_pos+4;
00145     scheme_pos = design_size_pos+4;
00146     family_pos = scheme_pos+40;
00147     random_word_pos = family_pos+20;
00148 
00149     ofm_ptr = start_pos;
00150 
00151     if (ofm_on==FALSE) {
00152         eval_two_bytes(&lh);
00153         eval_two_bytes(&bc);
00154         eval_two_bytes(&ec);
00155         eval_two_bytes(&nw);
00156         eval_two_bytes(&nh);
00157         eval_two_bytes(&nd);
00158         eval_two_bytes(&ni);
00159         eval_two_bytes(&nl);
00160         eval_two_bytes(&nk);
00161         eval_two_bytes(&ne);
00162         eval_two_bytes(&np);
00163         ncw = (ec-bc+1);
00164         ncl = nl;
00165         nce = ne;
00166         header_length = 6;
00167         top_char = 255;
00168         top_width = 255;
00169         top_height = 15;
00170         top_depth = 15;
00171         top_italic = 63;
00172     } else {
00173         eval_four_bytes(&lh);
00174         eval_four_bytes(&bc);
00175         eval_four_bytes(&ec);
00176         eval_four_bytes(&nw);
00177         eval_four_bytes(&nh);
00178         eval_four_bytes(&nd);     
00179         eval_four_bytes(&ni);
00180         eval_four_bytes(&nl);
00181         eval_four_bytes(&nk);
00182         eval_four_bytes(&ne);
00183         eval_four_bytes(&np);
00184         eval_four_bytes(&font_dir);
00185         top_char = 65535;
00186         top_width = 65535;
00187         top_height = 255;
00188         top_depth = 255;
00189         top_italic = 255;
00190         ncl = nl*2;
00191         nce = ne*2;
00192         if (ofm_level==OFM_LEVEL0) {
00193             header_length = 14;
00194             ncw = 2*(ec-bc+1);
00195         } else {
00196             header_length = 29;
00197             eval_four_bytes(&nco);
00198             eval_four_bytes(&ncw);
00199             eval_four_bytes(&npc);
00200             eval_four_bytes(&nki); /* Kinds of font ivalues   */
00201             eval_four_bytes(&nwi); /* Words of font ivalues   */
00202             eval_four_bytes(&nkf); /* Kinds of font fvalues   */
00203             eval_four_bytes(&nwf); /* Words of font fvalues   */
00204             eval_four_bytes(&nkm); /* Kinds of font mvalues   */
00205             eval_four_bytes(&nwm); /* Words of font mvalues   */
00206             eval_four_bytes(&nkr); /* Kinds of font rules     */
00207             eval_four_bytes(&nwr); /* Words of font rules     */
00208             eval_four_bytes(&nkg); /* Kinds of font glues     */
00209             eval_four_bytes(&nwg); /* Words of font glues     */
00210             eval_four_bytes(&nkp); /* Kinds of font penalties */
00211             eval_four_bytes(&nwp); /* Words of font penalties */
00212         }
00213     }
00214     if (lf != (header_length+lh+ncw+nw+nh+nd+ni+ncl+nk+nce+np+
00215                nki+nwi+nkf+nwf+nkm+nwm+nkr+nwr+nkg+nwg+nkp+nwp))
00216         fatal_error_0("Subfile sizes do not add up to the stated total");
00217     if (lh < 2)
00218         fatal_error_1("The header length is only %d", lh);
00219     if ((bc > (ec+1)) || (ec > top_char))
00220         fatal_error_2("The character code range %d .. %d is illegal", bc, ec);
00221     if ((nw==0) || (nh==0) || (nd==0) || (ni==0))
00222         fatal_error_0("Incomplete subfiles for character dimensions");
00223     ivalues_start   = header_length+lh;
00224     fvalues_start   = ivalues_start+nki;
00225     mvalues_start   = fvalues_start+nkf;
00226     rules_start     = mvalues_start+nkm;
00227     glues_start     = rules_start+nkr;
00228     penalties_start = glues_start+nkg;
00229     ivalues_base    = penalties_start+nkp;
00230     fvalues_base    = ivalues_base+nwi;
00231     mvalues_base    = fvalues_base+nwf;
00232     rules_base      = mvalues_base+nwm;
00233     glues_base      = rules_base+nwr;
00234     penalties_base  = glues_base+nwg;
00235     char_base       = penalties_base+nwp;
00236     bytes_per_entry = (12 + 2*npc) / 4 * 4;
00237     init_planes();
00238     no_labels = 0;
00239     switch (ofm_level) {
00240     case OFM_TFM: {
00241       for(i=bc; i<=ec; i++) {
00242         init_character(i,NULL);
00243         char_start = 4*char_base+4*(i-bc);
00244         current_character->index_indices[C_WD] =
00245            ofm[char_start] & 0xff;
00246         current_character->index_indices[C_HT] =
00247            (ofm[char_start+1] & 0xf0) >> 4;
00248         current_character->index_indices[C_DP] =
00249           ofm[char_start+1] & 0xf;
00250         current_character->index_indices[C_IC] =
00251            (ofm[char_start+2] & 0xfc) >> 2;
00252         current_character->tag = 
00253            ofm[char_start+2] & 0x3;
00254         if (current_character->tag == TAG_LIG) no_labels++;
00255         current_character->remainder = 
00256            ofm[char_start+3] & 0xff;
00257       }
00258       break;
00259     }
00260     case OFM_LEVEL0: {
00261       for(i=bc; i<=ec; i++) {
00262         init_character(i,NULL);
00263         char_start = 4*char_base+8*(i-bc);
00264         current_character->index_indices[C_WD] =
00265            ((ofm[char_start] & 0xff) << 8) |
00266            (ofm[char_start+1] & 0xff);
00267         current_character->index_indices[C_HT] =
00268            ofm[char_start+2] & 0xff;
00269         current_character->index_indices[C_DP] =
00270           ofm[char_start+3] & 0xff;
00271         current_character->index_indices[C_IC] =
00272            ofm[char_start+4] & 0xff;
00273         current_character->tag = 
00274            ofm[char_start+5] & 0x3;
00275         if (current_character->tag == TAG_LIG) no_labels++;
00276         current_character->remainder = 
00277            ((ofm[char_start+6] & 0xff) << 8) |
00278            (ofm[char_start+7] & 0xff);
00279       }
00280       break;
00281     }
00282     case OFM_LEVEL1: {
00283       char_ptr = 4*char_base;
00284       i = bc;
00285       while (i<=ec) {
00286         init_character(i,NULL);
00287         copies = 1+256*ofm[char_ptr+8]+ofm[char_ptr+9];
00288         for (j=1; j<=copies; j++) {
00289           char_start = char_ptr;
00290           i++;
00291         }
00292         char_ptr = char_ptr + bytes_per_entry;
00293       }
00294       if (char_ptr != (4*(char_base+ncw)))
00295           fatal_error_0("Length of char info table does not "
00296                         "correspond to specification");
00297       break;
00298     }
00299     default: {
00300       fatal_error_1("Inappropriate font level (%d)", ofm_level-1);
00301     }
00302     }
00303     width_base    = char_base+ncw;
00304     height_base   = width_base+nw;
00305     depth_base    = height_base+nh;
00306     italic_base   = depth_base+nd;
00307     lig_kern_base = italic_base+ni;
00308     if (ofm_level==OFM_TFM) {
00309        kern_base     = lig_kern_base+nl;
00310     } else {
00311        kern_base     = lig_kern_base+2*nl;
00312     }
00313     exten_base    = kern_base+nk;
00314     if (ofm_level==OFM_TFM) {
00315        param_base    = exten_base+ne-1;
00316     } else {
00317        param_base    = exten_base+2*ne-1;
00318     }
00319 }
00320 
00321 void
00322 ofm_read_simple(void)
00323 {
00324 
00325     if (ofm_on==TRUE) {
00326         print_ofm_level(ofm_level-1);
00327         print_font_dir(font_dir);
00328     }
00329     header = (char *) ofm+check_sum_pos;
00330     retrieve_header();
00331     print_family();
00332     print_face();
00333     print_coding_scheme();
00334     print_design_size();
00335     out("(COMMENT DESIGNSIZE IS IN POINTS)"); out_ln();
00336     out("(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE)"); out_ln();
00337     print_check_sum();
00338     if ((seven_bit == TRUE) || (ofm_level != OFM_TFM))
00339       print_seven_bit_safe_flag();
00340     retrieve_parameters(ofm+(4*param_base));
00341     print_parameters();
00342 }
00343 
00344 void
00345 ofm_read_rest(void)
00346 {
00347     retrieve_dimen_tables();
00348     if (verbose_option==TRUE) print_dimen_tables();
00349     retrieve_ligkern_table(ofm+(4*lig_kern_base), ofm+(4*kern_base));
00350     adjust_labels(FALSE);
00351     if (verbose_option==TRUE) print_labels();
00352     print_ligkern_table();
00353     retrieve_exten_table(ofm+(4*exten_base));
00354     if (verbose_option==TRUE) print_extens();
00355 }
00356 
00357 /*
00358 @ Once the input data successfully passes these basic checks,
00359 \.{TFtoPL} believes that it is a \.{TFM} file, and the conversion
00360 to \.{PL} format will take place. Access to the various subfiles
00361 is facilitated by computing the following base addresses. For example,
00362 the |char_info| for character |c| in a \.{TFM} file will start in location
00363 |4*(char_base+c)| of the |tfm| array.
00364 
00365 @<Globals...@>=
00366 
00367 @ Of course we want to define macros that suppress the detail of how the
00368 font information is actually encoded. Each word will be referred to by
00369 the |tfm| index of its first byte. For example, if |c| is a character
00370 code between |bc| and |ec|, then |tfm[char_info(c)]| will be the
00371 first byte of its |char_info|, i.e., the |width_index|; furthermore
00372 |width(c)| will point to the |fix_word| for |c|'s width.
00373 */
00374 
00375 #if 0
00376 #define char_info(c) char_start[c]
00377 #define nonexistent(c)      ((c<bc)or(c>ec)or(width_index(c)=0))
00378 #define width(c)     4*(width_base+width_index(c))
00379 #define height(c)    4*(height_base+height_index(c))
00380 #define depth(c)     4*(depth_base+depth_index(c))
00381 #define italic(c)    4*(italic_base+italic_index(c))
00382 #define kern(i)             4*(kern_base+i) /* i is an index, not a char */
00383 #define param(i)     4*(param_base+i) /* likewise */
00384 #endif
00385 
00386 /*
00387 unsigned
00388 width_index(unsigned c)
00389 {
00390 if (ofm_on==FALSE)
00391   return ofm[char_info(c)];
00392 else
00393   return 256*ofm[char_info(c)]+ofm[char_info(c)+1];
00394 }
00395 
00396 unsigned
00397 height_index(unsigned c)
00398 {
00399 if (ofm_on==FALSE)
00400   return ofm[char_info(c)+1] / 16;
00401 else
00402   return ofm[char_info(c)+2];
00403 }
00404 
00405 unsigned
00406 depth_index(unsigned c)
00407 {
00408 if (ofm_on==FALSE)
00409   return ofm[char_info(c)+1] % 16;
00410 else
00411   return ofm[char_info(c)+3];
00412 }
00413 
00414 unsigned
00415 italic_index(unsigned c)
00416 {
00417 if (ofm_on==FALSE)
00418   return ofm[char_info(c)+2] / 4;
00419 else if (ofm_level == OFM_TFM)
00420   return ofm[char_info(c)+4]*64 + ofm[char_info(c)+5] / 4;
00421 else
00422   return ofm[char_info(c)+4];
00423 }
00424 
00425 unsigned
00426 tag(unsigned c)
00427 {
00428 if (ofm_on==FALSE)
00429   return ofm[char_info(c)+2] % 4;
00430 else
00431   return ofm[char_info(c)+5] % 4;
00432 }
00433 
00434 void
00435 set_no_tag(unsigned c)
00436 {
00437 if (ofm_on==FALSE)
00438   ofm[char_info(c)+2] = (ofm[char_info(c)+2] / 64)*64 + TAG_NONE;
00439 else
00440   ofm[char_info(c)+5] = (ofm[char_info(c)+5] / 64)*64 + TAG_NONE;
00441 }
00442 
00443 boolean
00444 ctag(unsigned c)
00445 {
00446 if (ofm_level != OFM_LEVEL1)
00447   return FALSE;
00448 else
00449   return ofm[char_info(c)+5] / 4 % 2;
00450 }
00451 
00452 void
00453 set_no_ctag(unsigned c)
00454 {
00455 if (ofm_level != OFM_LEVEL1)
00456   ofm[char_info(c)+5]  =  
00457     ofm[char_info(c)+5] / 8 * 8 + ofm[char_info(c)+5] % 4;
00458 }
00459 
00460 unsigned
00461 no_repeats(unsigned c)
00462 {
00463 if (ofm_level == OFM_NOLEVEL)
00464   return 0;
00465 else
00466   return 256*ofm[char_info(c)+8]+ofm[char_info(c)+9];
00467 }
00468 
00469 unsigned 
00470 char_param(unsigned c, unsigned i)
00471 {
00472   return 256*ofm[char_info(c)+2*i+10]+ofm[char_info(c)+2*i+11];
00473 }
00474 
00475 unsigned
00476 rremainder(unsigned c)
00477 {
00478 if (ofm_on==FALSE)
00479   return ofm[char_info(c)+3];
00480 else
00481   return 256*ofm[char_info(c)+6]+ofm[char_info(c)+7];
00482 }
00483 
00484 unsigned
00485 lig_step(unsigned c)
00486 {
00487 if (ofm_on==FALSE)
00488   return 4*(lig_kern_base+c);
00489 else
00490   return 4*(lig_kern_base+2*c);
00491 }
00492 
00493 unsigned
00494 exten(unsigned c)
00495 {
00496 if (ofm_on==FALSE)
00497   return 4*(exten_base+rremainder(c));
00498 else
00499   return 4*(exten_base+2*rremainder(c));
00500 }
00501 
00502 unsigned
00503 l_skip_byte(unsigned c)
00504 {
00505 if (ofm_on==FALSE)
00506   return ofm[c];
00507 else
00508   return 256*ofm[c]+ofm[c+1];
00509 }
00510 
00511 void
00512 set_l_skip_byte(unsigned c, unsigned newc)
00513 {
00514 if (ofm_on==FALSE)
00515   ofm[c] = newc;
00516 else {
00517   ofm[c] = newc / 256;
00518   ofm[c+1] = newc % 256;
00519 }
00520 }
00521 
00522 unsigned
00523 l_next_char(unsigned c)
00524 {
00525 if (ofm_on==FALSE)
00526   return ofm[c+1];
00527 else
00528   return 256*ofm[c+2]+ofm[c+3];
00529 }
00530 
00531 void
00532 set_l_next_char(unsigned c, unsigned newc)
00533 {
00534 if (ofm_on==FALSE)
00535   ofm[c+1] = newc;
00536 else {
00537   ofm[c+2] = newc / 256;
00538   ofm[c+3] = newc % 256;
00539 }
00540 }
00541 
00542 unsigned
00543 l_op_byte(unsigned c)
00544 {
00545 if (ofm_on==FALSE)
00546   return ofm[c+2];
00547 else
00548   return 256*ofm[c+4]+ofm[c+5];
00549 }
00550 
00551 void
00552 set_l_op_byte(unsigned c, unsigned newc)
00553 {
00554 if (ofm_on==FALSE)
00555   ofm[c+2] = newc;
00556 else {
00557   ofm[c+2] = newc / 256;
00558   ofm[c+3] = newc % 256;
00559 }
00560 }
00561 
00562 unsigned
00563 l_remainder(unsigned c)
00564 {
00565 if (ofm_on==FALSE)
00566   return ofm[c+3];
00567 else
00568   return 256*ofm[c+6]+ofm[c+7];
00569 }
00570 
00571 void
00572 set_l_remainder(unsigned c, unsigned newc)
00573 {
00574 if (ofm_on==FALSE)
00575   ofm[c+3] = newc;
00576 else {
00577   ofm[c+6] = newc / 256;
00578   ofm[c+7] = newc % 256;
00579 }
00580 }
00581 
00582 unsigned
00583 ofm_get_4(unsigned c)
00584 {
00585   return (ofm[c]<<24) | (ofm[c+1]<<16) | (ofm[c+2]<<8) | ofm[c+3];
00586 }
00587 
00588 unsigned
00589 ofm_get_1(unsigned c)
00590 {
00591   return ofm[c];
00592 }
00593 
00594 */