From 2007a609cc24440473a3092d31708af9f503487b Mon Sep 17 00:00:00 2001 From: Taco Hoekwater Date: Fri, 4 Jul 2008 11:48:58 +0000 Subject: [PATCH] split off tfm reading git-svn-id: svn+ssh://scm.foundry.supelec.fr/svn/metapost/mplib/trunk@599 b0617d17-b707-0410-b22c-fd2634e05cc4 --- src/texk/web2c/mpdir/Makefile.am | 6 +- src/texk/web2c/mpdir/Makefile.in | 10 +- src/texk/web2c/mpdir/mp.w | 236 +++++------------------------- src/texk/web2c/mpdir/tfmin.w | 241 +++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 205 deletions(-) create mode 100644 src/texk/web2c/mpdir/tfmin.w diff --git a/src/texk/web2c/mpdir/Makefile.am b/src/texk/web2c/mpdir/Makefile.am index d55fc5d..a5b174d 100644 --- a/src/texk/web2c/mpdir/Makefile.am +++ b/src/texk/web2c/mpdir/Makefile.am @@ -27,19 +27,19 @@ mpost_DEPENDENCIES = libmplib.a mpost_LDADD = libmplib.a $(KPSELIB) -lm noinst_LIBRARIES = libmplib.a -libmplib_a_SOURCES = avl.c mp.c psout.c +libmplib_a_SOURCES = avl.c mp.c psout.c tfmin.c include_HEADERS = mplib.h CTANGLE=ctangle -mp.c: psout.c mpxout.c +mp.c: psout.c mpxout.c tfmin.c .w.c: $(CTANGLE) $< $@ clean:: - $(RM) mp.c psout.c mplib.h mppsout.h mpmp.h mpxout.c mpxout.h *.o libmplib.a mpost.c mpost + $(RM) mp.c psout.c tfmin.c mptfmin.h mplib.h mppsout.h mpmp.h mpxout.c mpxout.h *.o libmplib.a mpost.c mpost distclean:: clean $(RM) Makefile config.h config.status config.log libtool diff --git a/src/texk/web2c/mpdir/Makefile.in b/src/texk/web2c/mpdir/Makefile.in index 8cce8c6..8340507 100644 --- a/src/texk/web2c/mpdir/Makefile.in +++ b/src/texk/web2c/mpdir/Makefile.in @@ -68,7 +68,8 @@ LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru libmplib_a_AR = $(AR) $(ARFLAGS) libmplib_a_LIBADD = -am_libmplib_a_OBJECTS = avl.$(OBJEXT) mp.$(OBJEXT) psout.$(OBJEXT) +am_libmplib_a_OBJECTS = avl.$(OBJEXT) mp.$(OBJEXT) psout.$(OBJEXT) \ + tfmin.$(OBJEXT) libmplib_a_OBJECTS = $(am_libmplib_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(includedir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -224,7 +225,7 @@ mpost_SOURCES = mpost.c mpxout.c mpost_DEPENDENCIES = libmplib.a mpost_LDADD = libmplib.a $(KPSELIB) -lm noinst_LIBRARIES = libmplib.a -libmplib_a_SOURCES = avl.c mp.c psout.c +libmplib_a_SOURCES = avl.c mp.c psout.c tfmin.c include_HEADERS = mplib.h CTANGLE = ctangle all: config.h @@ -332,6 +333,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpost.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpxout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tfmin.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -666,13 +668,13 @@ uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS uninstall-am uninstall-binPROGRAMS uninstall-includeHEADERS -mp.c: psout.c mpxout.c +mp.c: psout.c mpxout.c tfmin.c .w.c: $(CTANGLE) $< $@ clean:: - $(RM) mp.c psout.c mplib.h mppsout.h mpmp.h mpxout.c mpxout.h *.o libmplib.a mpost.c mpost + $(RM) mp.c psout.c tfmin.c mptfmin.h mplib.h mppsout.h mpmp.h mpxout.c mpxout.h *.o libmplib.a mpost.c mpost distclean:: clean $(RM) Makefile config.h config.status config.log libtool diff --git a/src/texk/web2c/mpdir/mp.w b/src/texk/web2c/mpdir/mp.w index 704043d..4d0f1da 100644 --- a/src/texk/web2c/mpdir/mp.w +++ b/src/texk/web2c/mpdir/mp.w @@ -157,6 +157,7 @@ typedef struct MP_instance { #include "psout.h" /* external header */ #include "mpmp.h" /* internal header */ #include "mppsout.h" /* internal header */ +#include "mptfmin.h" /* mp_read_font_info */ @h @ @ @@ -165,7 +166,6 @@ typedef struct MP_instance { @ Here are the functions that set up the \MP\ instance. @ = -@ MP_options *mp_options (void); MP mp_initialize (MP_options *opt); @@ -181,6 +181,10 @@ MP_options *mp_options (void) { return opt; } +@ @= +@ +@ + @ The whole instance structure is initialized with zeroes, this greatly reduces the number of statements needed in the |Allocate or initialize variables| block. @@ -2478,7 +2482,7 @@ that is used only when the quantity being halved is known to be positive or zero. @d half(A) ((A) / 2) -@d halfp(A) ((unsigned)(A) >> 1) +@d halfp(A) (integer)((unsigned)(A) >> 1) @ A single computation might use several subroutine calls, and it is desirable to avoid producing multiple error messages in case of arithmetic @@ -2554,7 +2558,7 @@ scaled mp_round_decimals (MP mp,quarterword k) { while ( k-->0 ) { a=(a+mp->dig[k]*two) / 10; } - return halfp(a+1); + return (scaled)halfp(a+1); } @ Conversely, here is a procedure analogous to |print_int|. If the output @@ -2770,7 +2774,7 @@ the present implementation consumes almost 20\pct! of \MP's computation time during typical jobs, so a machine-language substitute is advisable. @^inner loop@> @^system dependencies@> -@= +@= integer mp_take_fraction (MP mp,integer q, fraction f) ; @ @c @@ -3125,7 +3129,7 @@ scaled mp_square_rt (MP mp,scaled x) { @; } while (k!=0); - return (halfp(q)); + return (scaled)(halfp(q)); } } @@ -3216,7 +3220,7 @@ integer mp_pyth_sub (MP mp,integer a, integer b) { if ( a; if ( big ) double(a); @@ -3827,10 +3831,10 @@ pointer hi_mem_min; /* the smallest location of one-word memory in use */ @d XREALLOC(a,b,c) a = xrealloc(a,(b+1),sizeof(c)); @= -void mp_xfree (void *x); -void *mp_xrealloc (MP mp, void *p, size_t nmem, size_t size) ; -void *mp_xmalloc (MP mp, size_t nmem, size_t size) ; -char *mp_xstrdup(MP mp, const char *s); +void mp_xfree ( @= /*@@only@@*/ /*@@out@@*/ /*@@null@@*/ @> void *x); +@= /*@@only@@*/ @> void *mp_xrealloc (MP mp, void *p, size_t nmem, size_t size) ; +@= /*@@only@@*/ @> void *mp_xmalloc (MP mp, size_t nmem, size_t size) ; +@= /*@@only@@*/ @> char *mp_xstrdup(MP mp, const char *s); void mp_do_snprintf(char *str, int size, const char *fmt, ...); @ The |max_size_test| guards against overflow, on the assumption that @@ -5376,7 +5380,7 @@ integer st_count; /* total number of known identifiers */ @ Certain entries in the hash table are ``frozen'' and not redefinable, since they are used in error recovery. -@d hash_top (hash_base+mp->hash_size) /* the first location of the frozen area */ +@d hash_top (integer)(hash_base+mp->hash_size) /* the first location of the frozen area */ @d frozen_inaccessible hash_top /* |hash| location to protect the frozen area */ @d frozen_repeat_loop (hash_top+1) /* |hash| location of a loop-repeat token */ @d frozen_right_delimiter (hash_top+2) /* |hash| location of a permanent `\.)' */ @@ -5470,7 +5474,7 @@ pointer mp_id_lookup (MP mp,integer j, integer l) { /* search the hash table */ if ( text(p)>0 ) { do { if ( hash_is_full ) - mp_overflow(mp, "hash size",mp->hash_size); + mp_overflow(mp, "hash size",(integer)mp->hash_size); @:MetaPost capacity exceeded hash size}{\quad hash size@> decr(mp->hash_used); } while (text(mp->hash_used)!=0); /* search for an empty location in |hash| */ @@ -9195,7 +9199,7 @@ scaled mp_sqrt_det (MP mp,scaled a, scaled b, scaled c, scaled d) { s=64; while ( (maxabs1) ){ a+=a; b+=b; c+=c; d+=d; - maxabs+=maxabs; s=halfp(s); + maxabs+=maxabs; s=(unsigned)(halfp(s)); } return (scaled)(s*mp_square_rt(mp, abs(mp_take_fraction(mp, a,d)-mp_take_fraction(mp, b,c)))); } @@ -12129,7 +12133,7 @@ pointer mp_p_plus_fq ( MP mp, pointer p, integer f, { if ( tt==mp_dependent ) v=mp_take_fraction(mp, f,value(q)); else v=mp_take_scaled(mp, f,value(q)); - if ( (unsigned)abs(v)>halfp(threshold) ) { + if ( abs(v)>halfp(threshold) ) { s=mp_get_node(mp, dep_node_size); info(s)=qq; value(s)=v; if ( (abs(v)>=coef_bound) && mp->watch_coefs ) { type(qq)=independent_needing_fix; mp->fix_needed=true; @@ -12422,7 +12426,7 @@ recognized by testing that the returned list pointer is equal to return mp_const_dependency(mp, 0); } else { q=mp_get_node(mp, dep_node_size); - value(q)=two_to_the(28-m); info(q)=p; + value(q)=(integer)two_to_the(28-m); info(q)=p; mp_link(q)=mp_const_dependency(mp, 0); return q; } @@ -15783,6 +15787,11 @@ offsets into |mp->str_pool|. I am not in a great hurry to fix this, because calling |str_room()| just once is more efficient anyway. TODO. @= +void mp_begin_name (MP mp); +boolean mp_more_name (MP mp, ASCII_code c); +void mp_end_name (MP mp); + +@ @c void mp_begin_name (MP mp) { xfree(mp->cur_name); xfree(mp->cur_area); @@ -15795,7 +15804,7 @@ void mp_begin_name (MP mp) { @ And here's the second. @^system dependencies@> -@= +@c boolean mp_more_name (MP mp, ASCII_code c) { if (c==' ') { return false; @@ -15819,7 +15828,7 @@ boolean mp_more_name (MP mp, ASCII_code c) { strncpy(A,(char *)(mp->str_pool+B),C); A[C] = 0;} -@= +@c void mp_end_name (MP mp) { pool_pointer s; /* length of area, name, and extension */ unsigned int len; @@ -15867,6 +15876,9 @@ allows both lowercase and uppercase letters in the file name. } @= +void mp_pack_file_name (MP mp, const char *n, const char *a, const char *e); + +@ @c void mp_pack_file_name (MP mp, const char *n, const char *a, const char *e) { integer k; /* number of positions filled in |name_of_file| */ ASCII_code c; /* character being packed */ @@ -16013,6 +16025,9 @@ includes special characters is ``quoted'' somehow. @ Here is another version that takes its input from a string. @= +void mp_str_scan_file (MP mp, str_number s) ; + +@ @c void mp_str_scan_file (MP mp, str_number s) { pool_pointer p,q; /* current position and stopping point */ mp_begin_name(mp); @@ -16027,6 +16042,9 @@ void mp_str_scan_file (MP mp, str_number s) { @ And one that reads from a |char*|. @= +extern void mp_ptr_scan_file (MP mp, char *s); + +@ @c void mp_ptr_scan_file (MP mp, char *s) { char *p, *q; /* current position and stopping point */ mp_begin_name(mp); @@ -19310,7 +19328,7 @@ that receives eight integers corresponding to the four controlling points, and returns a single angle. Besides those, we have to account for discrete moves at the actual points. -@d mp_floor(a) (a>=0 ? (int)a : -(int)(-a)) +@d mp_floor(a) ((a)>=0 ? (int)(a) : -(int)(-(a))) @d bezier_error (720*(256*256*16))+1 @d mp_sign(v) ((v)>0 ? 1 : ((v)<0 ? -1 : 0 )) @d mp_out(A) (double)((A)/(256*256*16)) @@ -25005,184 +25023,6 @@ $$\hbox{|char_width(f,char_info(f,c)).sc|.}$$ @d char_depth(A,B) mp->font_info[mp->depth_base[(A)]+(B).b2].sc @d ichar_exists(A) ((A).b0>0) -@ The |font_ps_name| for a built-in font should be what PostScript expects. -A preliminary name is obtained here from the \.{TFM} name as given in the -|fname| argument. This gets updated later from an external table if necessary. - -@= -@ -font_number mp_read_font_info (MP mp, char *fname) { - boolean file_opened; /* has |tfm_infile| been opened? */ - font_number n; /* the number to return */ - halfword lf,tfm_lh,bc,ec,nw,nh,nd; /* subfile size parameters */ - size_t whd_size; /* words needed for heights, widths, and depths */ - int i,ii; /* |font_info| indices */ - int jj; /* counts bytes to be ignored */ - scaled z; /* used to compute the design size */ - fraction d; - /* height, width, or depth as a fraction of design size times $2^{-8}$ */ - eight_bits h_and_d; /* height and depth indices being unpacked */ - unsigned char tfbyte; /* a byte read from the file */ - n=null_font; - @; - @; -BAD_TFM: - @; -DONE: - if ( file_opened ) (mp->close_file)(mp,mp->tfm_infile); - if ( n!=null_font ) { - mp->font_ps_name[n]=mp_xstrdup(mp,fname); - mp->font_name[n]=mp_xstrdup(mp,fname); - } - return n; -} - -@ \MP\ doesn't bother to check the entire \.{TFM} file for errors or explain -precisely what is wrong if it does find a problem. Programs called \.{TFtoPL} -@.TFtoPL@> @.PLtoTF@> -and \.{PLtoTF} can be used to debug \.{TFM} files. - -@= -print_err("Font "); -mp_print(mp, fname); -if ( file_opened ) mp_print(mp, " not usable: TFM file is bad"); -else mp_print(mp, " not usable: TFM file not found"); -help3("I wasn't able to read the size data for this font so this", - "`infont' operation won't produce anything. If the font name", - "is right, you might ask an expert to make a TFM file"); -if ( file_opened ) - mp->help_line[0]="is right, try asking an expert to fix the TFM file"; -mp_error(mp) - -@ @= -@; -@; -@; -@ - -@ A bad \.{TFM} file can be shorter than it claims to be. The code given here -might try to read past the end of the file if this happens. Changes will be -needed if it causes a system error to refer to |tfm_infile^| or call -|get_tfm_infile| when |eof(tfm_infile)| is true. For example, the definition -@^system dependencies@> -of |tfget| could be changed to -``|begin get(tfm_infile); if eof(tfm_infile) then goto bad_tfm; end|.'' - -@d tfget do { - size_t wanted=1; - void *tfbyte_ptr = &tfbyte; - (mp->read_binary_file)(mp,mp->tfm_infile,&tfbyte_ptr,&wanted); - if (wanted==0) goto BAD_TFM; -} while (0) -@d read_two(A) { (A)=tfbyte; - if ( (A)>127 ) goto BAD_TFM; - tfget; (A)=(A)*0400+tfbyte; -} -@d tf_ignore(A) { for (jj=(A);jj>=1;jj--) tfget; } - -@= -tfget; read_two(lf); -tfget; read_two(tfm_lh); -tfget; read_two(bc); -tfget; read_two(ec); -if ( (bc>1+ec)||(ec>255) ) goto BAD_TFM; -tfget; read_two(nw); -tfget; read_two(nh); -tfget; read_two(nd); -whd_size=(size_t)((ec+1-bc)+nw+nh+nd); -if ( lf<(int)(6+tfm_lh+whd_size) ) goto BAD_TFM; -tf_ignore(10) - -@ Offsets are added to |char_base[n]| and |width_base[n]| so that is not -necessary to apply the |so| and |qo| macros when looking up the width of a -character in the string pool. In order to ensure nonnegative |char_base| -values when |bc>0|, it may be necessary to reserve a few unused |font_info| -elements. - -@= -if ( mp->next_fmem<(size_t)bc) - mp->next_fmem=(size_t)bc; /* ensure nonnegative |char_base| */ -if (mp->last_fnum==mp->font_max) - mp_reallocate_fonts(mp,(mp->font_max+(mp->font_max/4))); -while (mp->next_fmem+whd_size>=mp->font_mem_size) { - size_t l = mp->font_mem_size+(mp->font_mem_size/4); - memory_word *font_info; - font_info = xmalloc ((l+1),sizeof(memory_word)); - memset (font_info,0,sizeof(memory_word)*(l+1)); - memcpy (font_info,mp->font_info,sizeof(memory_word)*(mp->font_mem_size+1)); - xfree(mp->font_info); - mp->font_info = font_info; - mp->font_mem_size = l; -} -incr(mp->last_fnum); -n=mp->last_fnum; -mp->font_bc[n]=(eight_bits)bc; -mp->font_ec[n]=(eight_bits)ec; -mp->char_base[n]=(int)(mp->next_fmem-bc); -mp->width_base[n]=(int)(mp->next_fmem+ec-bc+1); -mp->height_base[n]=mp->width_base[n]+nw; -mp->depth_base[n]=mp->height_base[n]+nh; -mp->next_fmem=mp->next_fmem+whd_size; - - -@ @= -if ( tfm_lh<2 ) goto BAD_TFM; -tf_ignore(4); -tfget; read_two(z); -tfget; z=z*0400+tfbyte; -tfget; z=z*0400+tfbyte; /* now |z| is 16 times the design size */ -mp->font_dsize[n]=mp_take_fraction(mp, z,267432584); - /* times ${72\over72.27}2^{28}$ to convert from \TeX\ points */ -tf_ignore(4*(tfm_lh-2)) - -@ @= -ii=mp->width_base[n]; -i=mp->char_base[n]+bc; -while ( ifont_info[i].qqqq.b0=qi(tfbyte); - tfget; h_and_d=tfbyte; - mp->font_info[i].qqqq.b1=qi(h_and_d / 16); - mp->font_info[i].qqqq.b2=qi(h_and_d % 16); - tfget; tfget; - incr(i); -} -while ( i<(int)mp->next_fmem ) { - @; -} -goto DONE - -@ The raw dimension read into |d| should have magnitude at most $2^{24}$ when -interpreted as an integer, and this includes a scale factor of $2^{20}$. Thus -we can multiply it by sixteen and think of it as a |fraction| that has been -divided by sixteen. This cancels the extra scale factor contained in -|font_dsize[n|. - -@= -{ -tfget; d=tfbyte; -if ( d>=0200 ) d=d-0400; -tfget; d=d*0400+tfbyte; -tfget; d=d*0400+tfbyte; -tfget; d=d*0400+tfbyte; -mp->font_info[i].sc=mp_take_fraction(mp, d*16,mp->font_dsize[n]); -incr(i); -} - -@ This function does no longer use the file name parser, because |fname| is -a C string already. -@= -file_opened=false; -mp_ptr_scan_file(mp, fname); -if ( strlen(mp->cur_area)==0 ) { xfree(mp->cur_area); } -if ( strlen(mp->cur_ext)==0 ) { xfree(mp->cur_ext); mp->cur_ext=xstrdup(".tfm"); } -pack_cur_name; -mp->tfm_infile = (mp->open_file)(mp, mp->name_of_file, "r",mp_filetype_metrics); -if ( !mp->tfm_infile ) goto BAD_TFM; -file_opened=true - @ When we have a font name and we don't know whether it has been loaded yet, we scan the |font_name| array before calling |read_font_info|. @@ -25992,7 +25832,7 @@ dump/undump macros. @= dump_int(mp->mem_top); -dump_int(mp->hash_size); +dump_int((integer)mp->hash_size); dump_int(mp->hash_prime) dump_int(mp->param_size); dump_int(mp->max_in_open); @@ -26005,7 +25845,7 @@ the same strings. (And it is, of course, a good thing that they do.) @= undump_int(x); mp->mem_top = x; -undump_int(x); mp->hash_size = x; +undump_int(x); mp->hash_size = (unsigned)x; undump_int(x); mp->hash_prime = x; undump_int(x); mp->param_size = x; undump_int(x); mp->max_in_open = x; diff --git a/src/texk/web2c/mpdir/tfmin.w b/src/texk/web2c/mpdir/tfmin.w new file mode 100644 index 0000000..f8466eb --- /dev/null +++ b/src/texk/web2c/mpdir/tfmin.w @@ -0,0 +1,241 @@ +% $Id: mp.w 597 2008-07-03 15:35:34Z taco $ +% +% Copyright 2008 Taco Hoekwater. +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see . +% +% TeX is a trademark of the American Mathematical Society. +% METAFONT is a trademark of Addison-Wesley Publishing Company. +% PostScript is a trademark of Adobe Systems Incorporated. + +% Here is TeX material that gets inserted after \input webmac + +\def\title{Reading TEX metrics files} +\pdfoutput=1 + +@ Introduction. + +@ Needed headers and macros + +@d qi(A) (quarterword)(A) /* to store eight bits in a quarterword */ +@d null_font 0 /* the |font_number| for an empty font */ +@d false 0 +@d true 1 +@d hlp1(A) mp->help_line[0]=A; } +@d hlp2(A,B) mp->help_line[1]=A; hlp1(B) +@d hlp3(A,B,C) mp->help_line[2]=A; hlp2(B,C) +@d help3 { mp->help_ptr=3; hlp3 /* use this with three help lines */ + +@c +#include +#include +#include +#include "mplib.h" +#include "mpmp.h" /* internal header */ +#include "mptfmin.h" +@h + +@ Written header + +@(mptfmin.h@>= +extern font_number mp_read_font_info (MP mp, char *fname); + +@ The |font_ps_name| for a built-in font should be what PostScript expects. +A preliminary name is obtained here from the \.{TFM} name as given in the +|fname| argument. This gets updated later from an external table if necessary. + +@c +font_number mp_read_font_info (MP mp, char *fname) { + boolean file_opened; /* has |tfm_infile| been opened? */ + font_number n; /* the number to return */ + halfword lf,tfm_lh,bc,ec,nw,nh,nd; /* subfile size parameters */ + size_t whd_size; /* words needed for heights, widths, and depths */ + int i,ii; /* |font_info| indices */ + int jj; /* counts bytes to be ignored */ + scaled z; /* used to compute the design size */ + fraction d; /* height, width, or depth as a fraction of design size times $2^{-8}$ */ + int h_and_d; /* height and depth indices being unpacked */ + int tfbyte = 0; /* a byte read from the file */ + n=null_font; + @; + @; +BAD_TFM: + @; +DONE: + if ( file_opened ) (mp->close_file)(mp,mp->tfm_infile); + if ( n!=null_font ) { + mp->font_ps_name[n]=mp_xstrdup(mp,fname); + mp->font_name[n]=mp_xstrdup(mp,fname); + } + return n; +} + +@ \MP\ doesn't bother to check the entire \.{TFM} file for errors or explain +precisely what is wrong if it does find a problem. Programs called \.{TFtoPL} +@.TFtoPL@> @.PLtoTF@> +and \.{PLtoTF} can be used to debug \.{TFM} files. + +@= +mp_print_err(mp,"Font "); +mp_print(mp, fname); +if ( file_opened ) mp_print(mp, " not usable: TFM file is bad"); +else mp_print(mp, " not usable: TFM file not found"); +help3("I wasn't able to read the size data for this font so this", + "`infont' operation won't produce anything. If the font name", + "is right, you might ask an expert to make a TFM file"); +if ( file_opened ) + mp->help_line[0]="is right, try asking an expert to fix the TFM file"; +mp_error(mp) + +@ @= +@; +@; +@; +@ + +@ A bad \.{TFM} file can be shorter than it claims to be. The code given here +might try to read past the end of the file if this happens. Changes will be +needed if it causes a system error to refer to |tfm_infile^| or call +|get_tfm_infile| when |eof(tfm_infile)| is true. For example, the definition +@^system dependencies@> +of |tfget| could be changed to +``|begin get(tfm_infile); if eof(tfm_infile) then goto bad_tfm; end|.'' + +@d tfget do { + size_t wanted=1; + void *tfbyte_ptr = &tfbyte; + (mp->read_binary_file)(mp,mp->tfm_infile, &tfbyte_ptr,&wanted); + if (wanted==0) goto BAD_TFM; +} while (0) +@d read_two(A) { (A)=tfbyte; + if ( (A)>127 ) goto BAD_TFM; + tfget; (A)=(A)*0400+tfbyte; +} +@d tf_ignore(A) { for (jj=(A);jj>=1;jj--) tfget; } + +@= +tfget; read_two(lf); +tfget; read_two(tfm_lh); +tfget; read_two(bc); +tfget; read_two(ec); +if ( (bc>1+ec)||(ec>255) ) goto BAD_TFM; +tfget; read_two(nw); +tfget; read_two(nh); +tfget; read_two(nd); +whd_size=(size_t)((ec+1-bc)+nw+nh+nd); +if ( lf<(int)(6+tfm_lh+whd_size) ) goto BAD_TFM; +tf_ignore(10) + +@ Offsets are added to |char_base[n]| and |width_base[n]| so that is not +necessary to apply the |so| and |qo| macros when looking up the width of a +character in the string pool. In order to ensure nonnegative |char_base| +values when |bc>0|, it may be necessary to reserve a few unused |font_info| +elements. + +@= +if ( mp->next_fmem<(size_t)bc) + mp->next_fmem=(size_t)bc; /* ensure nonnegative |char_base| */ +if (mp->last_fnum==mp->font_max) + mp_reallocate_fonts(mp,(mp->font_max+(mp->font_max/4))); +while (mp->next_fmem+whd_size>=mp->font_mem_size) { + size_t l = mp->font_mem_size+(mp->font_mem_size/4); + memory_word *font_info; + font_info = mp_xmalloc (mp,(l+1),sizeof(memory_word)); + memset (font_info,0,sizeof(memory_word)*(l+1)); + memcpy (font_info,mp->font_info,sizeof(memory_word)*(mp->font_mem_size+1)); + mp_xfree(mp->font_info); + mp->font_info = font_info; + mp->font_mem_size = l; +} +mp->last_fnum++; +n=mp->last_fnum; +mp->font_bc[n]=(eight_bits)bc; +mp->font_ec[n]=(eight_bits)ec; +mp->char_base[n]=(int)(mp->next_fmem-bc); +mp->width_base[n]=(int)(mp->next_fmem+ec-bc+1); +mp->height_base[n]=mp->width_base[n]+nw; +mp->depth_base[n]=mp->height_base[n]+nh; +mp->next_fmem=mp->next_fmem+whd_size; + + +@ @= +if ( tfm_lh<2 ) goto BAD_TFM; +tf_ignore(4); +tfget; read_two(z); +tfget; z=z*0400+tfbyte; +tfget; z=z*0400+tfbyte; /* now |z| is 16 times the design size */ +mp->font_dsize[n]=mp_take_fraction(mp, z,267432584); + /* times ${72\over72.27}2^{28}$ to convert from \TeX\ points */ +tf_ignore(4*(tfm_lh-2)) + +@ @= +ii=mp->width_base[n]; +i=mp->char_base[n]+bc; +while ( ifont_info[i].qqqq.b0=qi(tfbyte); + tfget; h_and_d=tfbyte; + mp->font_info[i].qqqq.b1=qi(h_and_d / 16); + mp->font_info[i].qqqq.b2=qi(h_and_d % 16); + tfget; tfget; + i++; +} +while ( i<(int)mp->next_fmem ) { + @; +} +goto DONE + +@ The raw dimension read into |d| should have magnitude at most $2^{24}$ when +interpreted as an integer, and this includes a scale factor of $2^{20}$. Thus +we can multiply it by sixteen and think of it as a |fraction| that has been +divided by sixteen. This cancels the extra scale factor contained in +|font_dsize[n|. + +@= +{ +tfget; d=tfbyte; +if ( d>=0200 ) d=d-0400; +tfget; d=d*0400+tfbyte; +tfget; d=d*0400+tfbyte; +tfget; d=d*0400+tfbyte; +mp->font_info[i].cint=mp_take_fraction(mp, d*16,mp->font_dsize[n]); +i++; +} + +@ This function does no longer use the file name parser, because |fname| is +a C string already. + +@= +file_opened=false; +mp_ptr_scan_file(mp, fname); +if ( strlen(mp->cur_area)==0 ) { mp_xfree(mp->cur_area); } +if ( strlen(mp->cur_ext)==0 ) { + mp_xfree(mp->cur_ext); + mp->cur_ext=mp_xstrdup(mp,".tfm"); +} +mp_pack_file_name(mp, mp->cur_name,mp->cur_area,mp->cur_ext); +mp_xfree(mp->tfm_infile); +mp->tfm_infile = (mp->open_file)(mp, mp->name_of_file, "r",mp_filetype_metrics); +if ( !mp->tfm_infile ) goto BAD_TFM; +file_opened=true + + + + + + + + -- 2.32.0.93.g670b81a890