re-import the lua bindings c file; build ctangle in non-crosscompilers; build a lua...
[mplib] / src / texk / web2c / mpdir / tfmin.w
1 % $Id: mp.w 597 2008-07-03 15:35:34Z taco $
2 %
3 % Copyright 2008 Taco Hoekwater.
4 %
5 % This program is free software: you can redistribute it and/or modify
6 % it under the terms of the GNU General Public License as published by
7 % the Free Software Foundation, either version 2 of the License, or
8 % (at your option) any later version.
9 %
10 % This program is distributed in the hope that it will be useful,
11 % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 % GNU General Public License for more details.
14 %
15 % You should have received a copy of the GNU General Public License
16 % along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 %
18 % TeX is a trademark of the American Mathematical Society.
19 % METAFONT is a trademark of Addison-Wesley Publishing Company.
20 % PostScript is a trademark of Adobe Systems Incorporated.
21
22 % Here is TeX material that gets inserted after \input webmac
23
24 \font\tenlogo=logo10 % font used for the METAFONT logo
25 \font\logos=logosl10
26 \def\MF{{\tenlogo META}\-{\tenlogo FONT}}
27 \def\MP{{\tenlogo META}\-{\tenlogo POST}}
28
29 \def\title{Reading TEX metrics files}
30 \pdfoutput=1
31
32 @ Introduction.
33
34 @ Needed headers and macros
35
36 @d qi(A) (quarterword)(A) /* to store eight bits in a quarterword */
37 @d null_font 0 /* the |font_number| for an empty font */
38 @d false 0
39 @d true 1
40 @d hlp1(A) mp->help_line[0]=A; }
41 @d hlp2(A,B) mp->help_line[1]=A; hlp1(B)
42 @d hlp3(A,B,C) mp->help_line[2]=A; hlp2(B,C)
43 @d help3  { mp->help_ptr=3; hlp3 /* use this with three help lines */
44
45 @c 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include "mplib.h"
50 #include "mpmp.h" /* internal header */
51 @h
52
53 @ The |font_ps_name| for a built-in font should be what PostScript expects.
54 A preliminary name is obtained here from the \.{TFM} name as given in the
55 |fname| argument.  This gets updated later from an external table if necessary.
56
57 @c
58 font_number mp_read_font_info (MP mp, char *fname) {
59   boolean file_opened; /* has |tfm_infile| been opened? */
60   font_number n; /* the number to return */
61   halfword lf,tfm_lh,bc,ec,nw,nh,nd; /* subfile size parameters */
62   size_t whd_size; /* words needed for heights, widths, and depths */
63   int i,ii; /* |font_info| indices */
64   int jj; /* counts bytes to be ignored */
65   scaled z; /* used to compute the design size */
66   fraction d; /* height, width, or depth as a fraction of design size times $2^{-8}$ */
67   int h_and_d; /* height and depth indices being unpacked */
68   int tfbyte = 0; /* a byte read from the file */
69   n=null_font;
70   @<Open |tfm_infile| for input@>;
71   @<Read data from |tfm_infile|; if there is no room, say so and |goto done|;
72     otherwise |goto bad_tfm| or |goto done| as appropriate@>;
73 BAD_TFM:
74   @<Complain that the \.{TFM} file is bad@>;
75 DONE:
76   if ( file_opened ) (mp->close_file)(mp,mp->tfm_infile);
77   if ( n!=null_font ) { 
78     mp->font_ps_name[n]=mp_xstrdup(mp,fname);
79     mp->font_name[n]=mp_xstrdup(mp,fname);
80   }
81   return n;
82 }
83
84 @ \MP\ doesn't bother to check the entire \.{TFM} file for errors or explain
85 precisely what is wrong if it does find a problem.  Programs called \.{TFtoPL}
86 @.TFtoPL@> @.PLtoTF@>
87 and \.{PLtoTF} can be used to debug \.{TFM} files.
88
89 @<Complain that the \.{TFM} file is bad@>=
90 mp_print_err(mp,"Font ");
91 mp_print(mp, fname);
92 if ( file_opened ) mp_print(mp, " not usable: TFM file is bad");
93 else mp_print(mp, " not usable: TFM file not found");
94 help3("I wasn't able to read the size data for this font so this",
95   "`infont' operation won't produce anything. If the font name",
96   "is right, you might ask an expert to make a TFM file");
97 if ( file_opened )
98   mp->help_line[0]="is right, try asking an expert to fix the TFM file";
99 mp_error(mp)
100
101 @ @<Read data from |tfm_infile|; if there is no room, say so...@>=
102 @<Read the \.{TFM} size fields@>;
103 @<Use the size fields to allocate space in |font_info|@>;
104 @<Read the \.{TFM} header@>;
105 @<Read the character data and the width, height, and depth tables and
106   |goto done|@>
107
108 @ A bad \.{TFM} file can be shorter than it claims to be.  The code given here
109 might try to read past the end of the file if this happens.  Changes will be
110 needed if it causes a system error to refer to |tfm_infile^| or call
111 |get_tfm_infile| when |eof(tfm_infile)| is true.  For example, the definition
112 @^system dependencies@>
113 of |tfget| could be changed to
114 ``|begin get(tfm_infile); if eof(tfm_infile) then goto bad_tfm; end|.''
115
116 @d tfget do { 
117   size_t wanted=1; 
118   void *tfbyte_ptr = &tfbyte;
119   (mp->read_binary_file)(mp,mp->tfm_infile, &tfbyte_ptr,&wanted); 
120   if (wanted==0) goto BAD_TFM; 
121 } while (0)
122 @d read_two(A) { (A)=tfbyte;
123   if ( (A)>127 ) goto BAD_TFM;
124   tfget; (A)=(A)*0400+tfbyte;
125 }
126 @d tf_ignore(A) { for (jj=(A);jj>=1;jj--) tfget; }
127
128 @<Read the \.{TFM} size fields@>=
129 tfget; read_two(lf);
130 tfget; read_two(tfm_lh);
131 tfget; read_two(bc);
132 tfget; read_two(ec);
133 if ( (bc>1+ec)||(ec>255) ) goto BAD_TFM;
134 tfget; read_two(nw);
135 tfget; read_two(nh);
136 tfget; read_two(nd);
137 whd_size=(size_t)((ec+1-bc)+nw+nh+nd);
138 if ( lf<(int)(6+tfm_lh+whd_size) ) goto BAD_TFM;
139 tf_ignore(10)
140
141 @ Offsets are added to |char_base[n]| and |width_base[n]| so that is not
142 necessary to apply the |so|  and |qo| macros when looking up the width of a
143 character in the string pool.  In order to ensure nonnegative |char_base|
144 values when |bc>0|, it may be necessary to reserve a few unused |font_info|
145 elements.
146
147 @<Use the size fields to allocate space in |font_info|@>=
148 if ( mp->next_fmem<(size_t)bc) 
149   mp->next_fmem=(size_t)bc; /* ensure nonnegative |char_base| */
150 if (mp->last_fnum==mp->font_max)
151   mp_reallocate_fonts(mp,(mp->font_max+(mp->font_max/4)));
152 while (mp->next_fmem+whd_size>=mp->font_mem_size) {
153   size_t l = mp->font_mem_size+(mp->font_mem_size/4);
154   memory_word *font_info;
155   font_info = mp_xmalloc (mp,(l+1),sizeof(memory_word));
156   memset (font_info,0,sizeof(memory_word)*(l+1));
157   memcpy (font_info,mp->font_info,sizeof(memory_word)*(mp->font_mem_size+1));
158   mp_xfree(mp->font_info);
159   mp->font_info = font_info;
160   mp->font_mem_size = l;
161 }
162 mp->last_fnum++;
163 n=mp->last_fnum;
164 mp->font_bc[n]=(eight_bits)bc;
165 mp->font_ec[n]=(eight_bits)ec;
166 mp->char_base[n]=(int)(mp->next_fmem-bc);
167 mp->width_base[n]=(int)(mp->next_fmem+ec-bc+1);
168 mp->height_base[n]=mp->width_base[n]+nw;
169 mp->depth_base[n]=mp->height_base[n]+nh;
170 mp->next_fmem=mp->next_fmem+whd_size;
171
172
173 @ @<Read the \.{TFM} header@>=
174 if ( tfm_lh<2 ) goto BAD_TFM;
175 tf_ignore(4);
176 tfget; read_two(z);
177 tfget; z=z*0400+tfbyte;
178 tfget; z=z*0400+tfbyte; /* now |z| is 16 times the design size */
179 mp->font_dsize[n]=mp_take_fraction(mp, z,267432584);
180   /* times ${72\over72.27}2^{28}$ to convert from \TeX\ points */
181 tf_ignore(4*(tfm_lh-2))
182
183 @ @<Read the character data and the width, height, and depth tables...@>=
184 ii=mp->width_base[n];
185 i=mp->char_base[n]+bc;
186 while ( i<ii ) { 
187   tfget; mp->font_info[i].qqqq.b0=qi(tfbyte);
188   tfget; h_and_d=tfbyte;
189   mp->font_info[i].qqqq.b1=qi(h_and_d / 16);
190   mp->font_info[i].qqqq.b2=qi(h_and_d % 16);
191   tfget; tfget;
192   i++;
193 }
194 while ( i<(int)mp->next_fmem ) {
195   @<Read a four byte dimension, scale it by the design size, store it in
196     |font_info[i]|, and increment |i|@>;
197 }
198 goto DONE
199
200 @ The raw dimension read into |d| should have magnitude at most $2^{24}$ when
201 interpreted as an integer, and this includes a scale factor of $2^{20}$.  Thus
202 we can multiply it by sixteen and think of it as a |fraction| that has been
203 divided by sixteen.  This cancels the extra scale factor contained in
204 |font_dsize[n|.
205
206 @<Read a four byte dimension, scale it by the design size, store it in...@>=
207
208 tfget; d=tfbyte;
209 if ( d>=0200 ) d=d-0400;
210 tfget; d=d*0400+tfbyte;
211 tfget; d=d*0400+tfbyte;
212 tfget; d=d*0400+tfbyte;
213 mp->font_info[i].cint=mp_take_fraction(mp, d*16,mp->font_dsize[n]);
214 i++;
215 }
216
217 @ This function does no longer use the file name parser, because |fname| is
218 a C string already.
219
220 @<Open |tfm_infile| for input@>=
221 file_opened=false;
222 mp_ptr_scan_file(mp, fname);
223 if ( strlen(mp->cur_area)==0 ) { mp_xfree(mp->cur_area); mp->cur_area=NULL; }
224 if ( strlen(mp->cur_ext)==0 )  { 
225     mp_xfree(mp->cur_ext); 
226     mp->cur_ext=mp_xstrdup(mp,".tfm"); 
227 }
228 mp_pack_file_name(mp, mp->cur_name,mp->cur_area,mp->cur_ext);
229 mp->tfm_infile = (mp->open_file)(mp, mp->name_of_file, "r",mp_filetype_metrics);
230 if ( !mp->tfm_infile  ) goto BAD_TFM;
231 file_opened=true
232
233
234
235
236
237
238
239