summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/font/tfmofm.w
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/font/tfmofm.w')
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tfmofm.w1117
1 files changed, 1117 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/font/tfmofm.w b/Build/source/texk/web2c/luatexdir/font/tfmofm.w
new file mode 100644
index 00000000000..842af38b405
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tfmofm.w
@@ -0,0 +1,1117 @@
+% tfmofm.w
+%
+% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
+
+% This file is part of LuaTeX.
+
+% LuaTeX 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.
+
+% LuaTeX 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 Lesser General Public
+% License for more details.
+
+% You should have received a copy of the GNU General Public License along
+% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+@ @c
+#include "ptexlib.h"
+
+static const char _svn_version[] =
+ "$Id: tfmofm.w 3584 2010-04-02 17:45:55Z hhenkel $ "
+"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/font/tfmofm.w $";
+
+@ Here are some macros that help process ligatures and kerns
+@c
+#define lig_kern_start(f,c) char_remainder(f,c)
+#define stop_flag 128 /* value indicating `\.{STOP}' in a lig/kern program */
+#define kern_flag 128 /* op code for a kern step */
+
+#define skip_byte(z) lig_kerns[z].b0
+#define next_char(z) lig_kerns[z].b1
+#define op_byte(z) lig_kerns[z].b2
+#define rem_byte(z) lig_kerns[z].b3
+#define lig_kern_restart(c) (256*op_byte(c)+rem_byte(c))
+
+
+@
+The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
+Since the number of bytes is always a multiple of 4, we could
+also regard the file as a sequence of 32-bit words, but \TeX\ uses the
+byte interpretation. The format of \.{TFM} files was designed by
+Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds
+@^Ramshaw, Lyle Harold@>
+of information in a compact but useful form.
+
+$\Omega$ is capable of reading not only \.{TFM} files, but also
+\.{OFM} files, which can describe fonts with up to 65536 characters
+and with huge lig/kern tables. These fonts will often be virtual
+fonts built up from real fonts with 256 characters, but $\Omega$
+is not aware of this.
+
+The documentation below describes \.{TFM} files, with slight additions
+to show where \.{OFM} files differ.
+
+@
+The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
+integers that give the lengths of the various subsequent portions
+of the file. These twelve integers are, in order:
+$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
+|lf|&length of the entire file, in words;\cr
+|lh|&length of the header data, in words;\cr
+|bc|&smallest character code in the font;\cr
+|ec|&largest character code in the font;\cr
+|nw|&number of words in the width table;\cr
+|nh|&number of words in the height table;\cr
+|nd|&number of words in the depth table;\cr
+|ni|&number of words in the italic correction table;\cr
+|nl|&number of words in the lig/kern table;\cr
+|nk|&number of words in the kern table;\cr
+|ne|&number of words in the extensible character table;\cr
+|np|&number of font parameter words.\cr}}$$
+They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
+and
+$$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that a \.{TFM} font may contain as many as 256 characters
+(if |bc=0| and |ec=255|), and as few as 0 characters (if |bc=ec+1|).
+
+Incidentally, when two or more 8-bit bytes are combined to form an integer of
+16 or more bits, the most significant bytes appear first in the file.
+This is called BigEndian order.
+@!@^BigEndian order@>
+
+The first 52 bytes (13 words) of an \.{OFM} file contains thirteen
+32-bit integers that give the lengths of the various subsequent
+portions of the file. The first word is 0 (future versions of
+\.{OFM} files could have different values; what is important is that
+the first two bytes be 0 to differentiate \.{TFM} and \.{OFM} files).
+The next twelve integers are as above, all nonegative and less
+than~$2^{31}$. We must have |bc-1<=ec<=65535|, and
+$$\hbox{|lf=13+lh+2*(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that an \.{OFM} font may contain as many as 65536 characters
+(if |bc=0| and |ec=65535|), and as few as 0 characters (if |bc=ec+1|).
+
+The rest of the \.{TFM} file may be regarded as a sequence of ten data
+arrays having the informal specification
+$$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2}
+\def\doarr\PB#1{\arr#1}
+\vbox{\halign{\hfil\\{#}&$\,:\,$\doarr#\hfil\cr
+header&|[0..lh-1]stuff|\cr
+char\_info&|[bc..ec]char_info_word|\cr
+width&|[0..nw-1]fix_word|\cr
+height&|[0..nh-1]fix_word|\cr
+depth&|[0..nd-1]fix_word|\cr
+italic&|[0..ni-1]fix_word|\cr
+lig\_kern&|[0..nl-1]lig_kern_command|\cr
+kern&|[0..nk-1]fix_word|\cr
+exten&|[0..ne-1]extensible_recipe|\cr
+param&\omit |[1..np]fix_word|\cr}}$$
+The most important data type used here is a |@!fix_word|, which is
+a 32-bit representation of a binary fraction. A |fix_word| is a signed
+quantity, with the two's complement of the entire word used to represent
+negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
+binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
+the smallest is $-2048$. We will see below, however, that all but two of
+the |fix_word| values must lie between $-16$ and $+16$.
+
+The first data array is a block of header information, which contains
+general facts about the font. The header must contain at least two words,
+|header[0]| and |header[1]|, whose meaning is explained below.
+Additional header information of use to other software routines might
+also be included, but \TeX82 does not need to know about such details.
+For example, 16 more words of header information are in use at the Xerox
+Palo Alto Research Center; the first ten specify the character coding
+scheme used (e.g., `\.{XEROX text}' or `\.{TeX math symbols}'), the next five
+give the font identifier (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the
+last gives the ``face byte.'' The program that converts \.{DVI} files
+to Xerox printing format gets this information by looking at the \.{TFM}
+file, which it needs to read anyway because of other information that
+is not explicitly repeated in \.{DVI}~format.
+
+\yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into
+the \.{DVI} output file. Later on when the \.{DVI} file is printed,
+possibly on another computer, the actual font that gets used is supposed
+to have a check sum that agrees with the one in the \.{TFM} file used by
+\TeX. In this way, users will be warned about potential incompatibilities.
+(However, if the check sum is zero in either the font file or the \.{TFM}
+file, no check is made.) The actual relation between this check sum and
+the rest of the \.{TFM} file is not important; the check sum is simply an
+identification number with the property that incompatible fonts almost
+always have distinct check sums.
+@^check sum@>
+
+\yskip\hang|header[1]| is a |fix_word| containing the design size of
+the font, in units of \TeX\ points. This number must be at least 1.0; it is
+fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
+font, i.e., a font that was designed to look best at a 10-point size,
+whatever that really means. When a \TeX\ user asks for a font
+`\.{at} $\delta$ \.{pt}', the effect is to override the design size
+and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates
+of the points in the font image by a factor of $\delta$ divided by the
+design size. {\sl All other dimensions in the\/ \.{TFM} file are
+|fix_word|\kern-1pt\ numbers in design-size units}, with the exception of
+|param[1]| (which denotes the slant ratio). Thus, for example, the value
+of |param[6]|, which defines the \.{em} unit, is often the |fix_word| value
+$2^{20}=1.0$, since many fonts have a design size equal to one em.
+The other dimensions must be less than 16 design-size units in absolute
+value; thus, |header[1]| and |param[1]| are the only |fix_word|
+entries in the whole \.{TFM} file whose first byte might be something
+besides 0 or 255.
+
+Next comes the |char_info| array, which contains one |@!char_info_word|
+per character. Each word in this part of a \.{TFM} file contains six fields
+packed into four bytes as follows.
+
+\yskip\hang first byte: |@!width_index| (8 bits)\par
+\hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index|
+ (4~bits)\par
+\hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag|
+ (2~bits)\par
+\hang fourth byte: |@!remainder| (8 bits)\par
+\yskip\noindent
+The actual width of a character is \\{width}|[width_index]|, in design-size
+units; this is a device for compressing information, since many characters
+have the same width. Since it is quite common for many characters
+to have the same height, depth, or italic correction, the \.{TFM} format
+imposes a limit of 16 different heights, 16 different depths, and
+64 different italic corrections.
+
+For \.{OFM} files, two words (eight bytes) are used.
+The arrangement is as follows.
+
+\yskip\hang first and second bytes: |@!width_index| (16 bits)\par
+\hang third byte: |@!height_index| (8 bits)\par
+\hang fourth byte: |@!depth_index| (8~bits)\par
+\hang fifth and sixth bytes:
+|@!italic_index| (14 bits) times 4, plus |@!tag| (2~bits)\par
+\hang seventh and eighth bytes: |@!remainder| (16 bits)\par
+\yskip\noindent
+Therefore the \.{OFM} format imposes a limit of 256 different heights,
+256 different depths, and 16384 different italic corrections.
+
+@!@^italic correction@>
+The italic correction of a character has two different uses.
+(a)~In ordinary text, the italic correction is added to the width only if
+the \TeX\ user specifies `\.{\\/}' after the character.
+(b)~In math formulas, the italic correction is always added to the width,
+except with respect to the positioning of subscripts.
+
+Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
+\\{italic}[0]=0$ should always hold, so that an index of zero implies a
+value of zero. The |width_index| should never be zero unless the
+character does not exist in the font, since a character is valid if and
+only if it lies between |bc| and |ec| and has a nonzero |width_index|.
+
+
+@ \TeX\ checks the information of a \.{TFM} file for validity as the
+file is being read in, so that no further checks will be needed when
+typesetting is going on. The somewhat tedious subroutine that does this
+is called |read_font_info|. It has four parameters: the user font
+identifier~|u|, the file name and area strings |nom| and |aire|, and the
+``at'' size~|s|. If |s|~is negative, it's the negative of a scale factor
+to be applied to the design size; |s=-1000| is the normal case.
+Otherwise |s| will be substituted for the design size; in this
+case, |s| must be positive and less than $2048\rm\,pt$
+(i.e., it must be less than $2^{27}$ when considered as an integer).
+
+The subroutine opens and closes a global file variable called |tfm_file|.
+It returns the value of the internal font number that was just loaded.
+If an error is detected, an error message is issued and no font
+information is stored; |null_font| is returned in this case.
+
+@
+The |tag| field in a |char_info_word| has four values that explain how to
+interpret the |remainder| field.
+
+\yskip\hang|tag=0| (|no_tag|) means that |remainder| is unused.\par
+\hang|tag=1| (|lig_tag|) means that this character has a ligature/kerning
+program starting at position |remainder| in the |lig_kern| array.\par
+\hang|tag=2| (|list_tag|) means that this character is part of a chain of
+characters of ascending sizes, and not the largest in the chain. The
+|remainder| field gives the character code of the next larger character.\par
+\hang|tag=3| (|ext_tag|) means that this character code represents an
+extensible character, i.e., a character that is built up of smaller pieces
+so that it can be made arbitrarily large. The pieces are specified in
+|@!exten[remainder]|.\par
+\yskip\noindent
+Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
+unless they are used in special circumstances in math formulas. For example,
+the \.{\\sum} operation looks for a |list_tag|, and the \.{\\left}
+operation looks for both |list_tag| and |ext_tag|.
+
+
+@ The |lig_kern| array contains instructions in a simple programming language
+that explains what to do for special letter pairs. Each word in this array,
+in a \.{TFM} file, is a |@!lig_kern_command| of four bytes.
+
+\yskip\hang first byte: |skip_byte|, indicates that this is the final program
+ step if the byte is 128 or more, otherwise the next step is obtained by
+ skipping this number of intervening steps.\par
+\hang second byte: |next_char|, ``if |next_char| follows the current character,
+ then perform the operation and stop, otherwise continue.''\par
+\hang third byte: |op_byte|, indicates a ligature step if less than~128,
+ a kern step otherwise.\par
+\hang fourth byte: |remainder|.\par
+\yskip\noindent
+In an \.{OFM} file, eight bytes are used, two bytes for each field.
+
+In a kern step, an
+additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
+between the current character and |next_char|. This amount is
+often negative, so that the characters are brought closer together
+by kerning; but it might be positive.
+
+There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
+$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
+|remainder| is inserted between the current character and |next_char|;
+then the current character is deleted if $b=0$, and |next_char| is
+deleted if $c=0$; then we pass over $a$~characters to reach the next
+current character (which may have a ligature/kerning program of its own).
+
+If the very first instruction of the |lig_kern| array has |skip_byte=255|,
+the |next_char| byte is the so-called right boundary character of this font;
+the value of |next_char| need not lie between |bc| and~|ec|.
+If the very last instruction of the |lig_kern| array has |skip_byte=255|,
+there is a special ligature/kerning program for a left boundary character,
+beginning at location |256*op_byte+remainder|.
+The interpretation is that \TeX\ puts implicit boundary characters
+before and after each consecutive string of characters from the same font.
+These implicit characters do not appear in the output, but they can affect
+ligatures and kerning.
+
+If the very first instruction of a character's |lig_kern| program has
+|skip_byte>128|, the program actually begins in location
+|256*op_byte+remainder|. This feature allows access to large |lig_kern|
+arrays, because the first instruction must otherwise
+appear in a location |<=255| in a \.{TFM} file, |<=65535| in an \.{OFM} file.
+
+Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
+the condition
+$$\hbox{|256*op_byte+remainder<nl|.}$$
+If such an instruction is encountered during
+normal program execution, it denotes an unconditional halt; no ligature
+or kerning command is performed.
+
+
+@ Extensible characters are specified by an |@!extensible_recipe|, which
+consists of four bytes in a \.{TFM} file,
+called |@!top|, |@!mid|, |@!bot|, and |@!rep| (in this order).
+In an \.{OFM} file, each field takes two bytes, for eight in total.
+These bytes are the character codes of individual pieces used to
+build up a large symbol. If |top|, |mid|, or |bot| are zero, they are not
+present in the built-up result. For example, an extensible vertical line is
+like an extensible bracket, except that the top and bottom pieces are missing.
+
+Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
+if the piece isn't present. Then the extensible characters have the form
+$TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
+in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
+The width of the extensible character is the width of $R$; and the
+height-plus-depth is the sum of the individual height-plus-depths of the
+components used, since the pieces are butted together in a vertical list.
+
+
+@
+The final portion of a \.{TFM} file is the |param| array, which is another
+sequence of |fix_word| values.
+
+\yskip\hang|param[1]=slant| is the amount of italic slant, which is used
+to help position accents. For example, |slant=.25| means that when you go
+up one unit, you also go .25 units to the right. The |slant| is a pure
+number; it's the only |fix_word| other than the design size itself that is
+not scaled by the design size.
+
+\hang|param[2]=space| is the normal spacing between words in text.
+Note that character |" "| in the font need not have anything to do with
+blank spaces.
+
+\hang|param[3]=space_stretch| is the amount of glue stretching between words.
+
+\hang|param[4]=space_shrink| is the amount of glue shrinking between words.
+
+\hang|param[5]=x_height| is the size of one ex in the font; it is also
+the height of letters for which accents don't have to be raised or lowered.
+
+\hang|param[6]=quad| is the size of one em in the font.
+
+\hang|param[7]=extra_space| is the amount added to |param[2]| at the
+ends of sentences.
+
+\yskip\noindent
+If fewer than seven parameters are present, \TeX\ sets the missing parameters
+to zero. Fonts used for math symbols are required to have
+additional parameter information, which is explained later.
+
+
+@
+ There are programs called \.{TFtoPL} and \.{PLtoTF} that convert
+ between the \.{TFM} format and a symbolic property-list format
+ that can be easily edited. These programs contain extensive
+ diagnostic information, so \TeX\ does not have to bother giving
+ precise details about why it rejects a particular \.{TFM} file.
+
+@c
+#define tfm_abort { font_tables[f]->_font_name = NULL; \
+ font_tables[f]->_font_area = NULL; \
+ xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); \
+ return 0; }
+
+#define tfm_success { xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); return 1; }
+
+@ @c
+static int open_tfm_file(const char *nom, unsigned char **tfm_buf, int *tfm_siz)
+{
+ boolean res; /* was the callback successful? */
+ boolean opened; /* was |tfm_file| successfully opened? */
+ int callback_id;
+ FILE *tfm_file;
+ char *fname = luatex_find_file(nom, find_font_file_callback);
+ if (!fname)
+ return -1;
+ callback_id = callback_defined(read_font_file_callback);
+ if (callback_id > 0) {
+ res =
+ run_callback(callback_id, "S->bSd", fname, &opened, tfm_buf,
+ tfm_siz);
+ if (res && opened && (*tfm_siz > 0)) {
+ return 1;
+ }
+ if (!opened)
+ return -1;
+ } else {
+ if (luatex_open_input
+ (&(tfm_file), fname, kpse_ofm_format, FOPEN_RBIN_MODE, true)) {
+ res = read_tfm_file(tfm_file, tfm_buf, tfm_siz);
+ close_file(tfm_file);
+ if (res) {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+@
+ Note: A malformed \.{TFM} file might be shorter than it claims to be;
+ thus |eof(tfm_file)| might be true when |read_font_info| refers to
+ |tfm_file^| or when it says |get(tfm_file)|. If such circumstances
+ cause system error messages, you will have to defeat them somehow,
+ for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);|
+ |if eof(tfm_file) then abort; end|\unskip'.
+ @^system dependencies@>
+@c
+
+#define fget tfm_byte++
+#define fbyte tfm_buffer[tfm_byte]
+
+#define read_sixteen(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_sixteen_unsigned(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_thirtytwo(a) \
+ { a=tfm_buffer[++tfm_byte]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; }
+
+#define store_four_bytes(z) \
+ { a=tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ z = a; }
+
+#define store_char_info(z) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); \
+ ci._width_index=a; \
+ fget; read_sixteen_unsigned(b); \
+ ci._height_index=b>>8; \
+ ci._depth_index=b%256; \
+ fget; read_sixteen_unsigned(c); \
+ ci._italic_index=c>>8; \
+ ci._tag=(unsigned char)(c%4); \
+ fget; read_sixteen_unsigned(d); \
+ ci._remainder=d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; \
+ ci._width_index=a; \
+ b=tfm_buffer[++tfm_byte]; \
+ ci._height_index=b>>4; \
+ ci._depth_index=b%16; \
+ c=tfm_buffer[++tfm_byte]; \
+ ci._italic_index=c>>2; \
+ ci._tag=(unsigned char)(c%4); \
+ d=tfm_buffer[++tfm_byte]; \
+ ci._remainder=d; \
+ } }
+
+#define read_four_quarters(q) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); q.b0=(quarterword)a; \
+ fget; read_sixteen_unsigned(b); q.b1=(quarterword)b; \
+ fget; read_sixteen_unsigned(c); q.b2=(quarterword)c; \
+ fget; read_sixteen_unsigned(d); q.b3=(quarterword)d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; q.b0=(quarterword)a; \
+ b=tfm_buffer[++tfm_byte]; q.b1=(quarterword)b; \
+ c=tfm_buffer[++tfm_byte]; q.b2=(quarterword)c; \
+ d=tfm_buffer[++tfm_byte]; q.b3=(quarterword)d; \
+ } }
+
+#define check_byte_range(z) { if ((z<bc)||(z>ec)) tfm_abort ; }
+
+
+@ A |fix_word| whose four bytes are $(a,b,c,d)$ from left to right represents
+ the number
+ $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
+ b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
+ -16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
+ (No other choices of |a| are allowed, since the magnitude of a number in
+ design-size units must be less than 16.) We want to multiply this
+ quantity by the integer~|z|, which is known to be less than $2^{27}$.
+ If $|z|<2^{23}$, the individual multiplications $b\cdot z$,
+ $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2,
+ 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can
+ compensate for this later. If |z| has thereby been replaced by
+ $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute
+ $$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$
+ if $a=0$, or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$.
+ This calculation must be done exactly, in order to guarantee portability
+ of \TeX\ between computers.
+
+@c
+#define store_scaled(zz) \
+ { fget; a=fbyte; fget; b=fbyte; \
+ fget; c=fbyte; fget; d=fbyte; \
+ sw=(((((d*z)>>8)+(c*z))>>8)+(b*z)) / beta; \
+ if (a==0) { zz=sw; } else if (a==255) { zz=sw-alpha; } else tfm_abort; \
+ }
+
+scaled store_scaled_f(scaled sq, scaled z_in)
+{
+ eight_bits a, b, c, d;
+ scaled sw;
+ static int alpha, beta; /* beta:1..16 */
+ static scaled z, z_prev = 0;
+ /* Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$ */
+ if (z_in != z_prev || z_prev == 0) {
+ z = z_prev = z_in;
+ alpha = 16;
+ while (z >= 0x800000) {
+ z /= 2;
+ alpha += alpha;
+ }
+ beta = 256 / alpha;
+ alpha *= z;
+ };
+ if (sq >= 0) {
+ d = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ c = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ b = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ a = (eight_bits) (sq % 256);
+ } else {
+ sq = (sq + 1073741824) + 1073741824; /* braces for optimizing compiler */
+ d = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ c = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ b = (eight_bits) (sq % 256);
+ sq = sq / 256;
+ a = (eight_bits) ((sq + 128) % 256);
+ }
+ sw = (((((d * z) >> 8) + (c * z)) >> 8) + (b * z)) / beta;
+ if (a == 0)
+ return sw;
+ else if (a == 255)
+ return (sw - alpha);
+ else
+ pdf_error("vf", "vf scaling");
+ return sw; /* not reached, just to make the compiler happy */
+}
+
+@ @c
+#define check_existence(z) \
+ { check_byte_range(z); \
+ if (!char_exists(f,z)) tfm_abort; \
+ }
+
+typedef struct tfmcharacterinfo {
+ int _kern_index;
+ int _lig_index;
+ int _width_index;
+ int _height_index;
+ int _depth_index;
+ int _italic_index;
+ int _remainder;
+ unsigned char _tag;
+} tfmcharacterinfo;
+
+@ @c
+int read_tfm_info(internal_font_number f, const char *cnom, scaled s)
+{
+ int k; /* index into |font_info| */
+ halfword lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np, slh; /* sizes of subfiles */
+ scaled *widths, *heights, *depths, *italics, *kerns;
+ halfword font_dir;
+ int a, b, c, d; /* byte variables */
+ int i; /* counter */
+ int font_level, header_length;
+ int nco, ncw, npc, nlw, neew;
+ tfmcharacterinfo ci;
+ charinfo *co;
+ four_quarters qw;
+ four_quarters *lig_kerns, *extens;
+ scaled sw; /* accumulators */
+ int bch_label; /* left boundary start location, or infinity */
+ int bchar; /* |:0..too_big_char;| *//* right boundary character, or |too_big_char| */
+ int first_two;
+ scaled z; /* the design size or the ``at'' size */
+ int alpha;
+ char beta; /* :1..16 */
+ int *xligs, *xkerns; /* aux. for ligkern processing */
+ liginfo *cligs;
+ kerninfo *ckerns;
+ int fligs, fkerns;
+ char *tmpnam;
+ int tfm_byte = 0; /* index into |tfm_buffer| */
+ int saved_tfm_byte = 0; /* saved index into |tfm_buffer| */
+ unsigned char *tfm_buffer = NULL; /* byte buffer for tfm files */
+ int tfm_size = 0; /* total size of the tfm file */
+ int tmp;
+
+ widths = NULL;
+ heights = NULL;
+ depths = NULL;
+ italics = NULL;
+ kerns = NULL;
+ lig_kerns = NULL;
+ extens = NULL;
+ xkerns = NULL;
+ ckerns = NULL;
+ xligs = NULL;
+ cligs = NULL;
+
+ font_dir = 0;
+
+ memset(&ci, 0, sizeof(tfmcharacterinfo));
+
+ if (open_tfm_file(cnom, &tfm_buffer, &tfm_size) != 1)
+ tfm_abort;
+
+ /* cnom can be an absolute filename, xbasename() fixes that. */
+
+ tmpnam = strdup(xbasename(cnom));
+ if (strcmp(tmpnam + strlen(tmpnam) - 4, ".tfm") == 0) {
+ *(tmpnam + strlen(tmpnam) - 4) = 0;
+ }
+ set_font_name(f, tmpnam);
+ set_font_area(f, NULL);
+
+ /* Read the {\.{TFM}} size fields */
+ nco = 0;
+ ncw = 0;
+ npc = 0;
+ read_sixteen(first_two);
+ if (first_two != 0) {
+ font_level = -1;
+ lf = first_two;
+ fget;
+ read_sixteen(lh);
+ fget;
+ read_sixteen(bc);
+ fget;
+ read_sixteen(ec);
+ if ((bc > ec + 1) || (ec > 255))
+ tfm_abort;
+ if (bc > 255) { /* |bc=256| and |ec=255| */
+ bc = 1;
+ ec = 0;
+ };
+ fget;
+ read_sixteen(nw);
+ fget;
+ read_sixteen(nh);
+ fget;
+ read_sixteen(nd);
+ fget;
+ read_sixteen(ni);
+ fget;
+ read_sixteen(nl);
+ fget;
+ read_sixteen(nk);
+ fget;
+ read_sixteen(ne);
+ fget;
+ read_sixteen(np);
+ header_length = 6;
+ ncw = (ec - bc + 1);
+ nlw = nl;
+ neew = ne;
+ } else {
+ fget;
+ read_sixteen(font_level);
+ if (font_level != 0)
+ tfm_abort;
+ read_thirtytwo(lf);
+ read_thirtytwo(lh);
+ read_thirtytwo(bc);
+ read_thirtytwo(ec);
+ if ((bc > ec + 1) || (ec > 65535))
+ tfm_abort;
+ if (bc > 65535) { /* |bc=65536| and |ec=65535| */
+ bc = 1;
+ ec = 0;
+ };
+ read_thirtytwo(nw);
+ read_thirtytwo(nh);
+ read_thirtytwo(nd);
+ read_thirtytwo(ni);
+ read_thirtytwo(nl);
+ read_thirtytwo(nk);
+ read_thirtytwo(ne);
+ read_thirtytwo(np);
+ read_thirtytwo(font_dir); /* junk */
+ nlw = 2 * nl;
+ neew = 2 * ne;
+ header_length = 14;
+ ncw = 2 * (ec - bc + 1);
+ };
+ if (lf !=
+ (header_length + lh + ncw + nw + nh + nd + ni + nlw + nk + neew + np))
+ tfm_abort;
+ if ((nw == 0) || (nh == 0) || (nd == 0) || (ni == 0))
+ tfm_abort;
+
+ /*
+ We check to see that the \.{TFM} file doesn't end prematurely; but
+ no error message is given for files having more than |lf| words.
+ */
+ if (lf * 4 > tfm_size)
+ tfm_abort;
+
+ /* Use size fields to allocate font information */
+
+ set_font_natural_dir(f, font_dir);
+ set_font_bc(f, bc);
+ set_font_ec(f, ec);
+
+ /* read the arrays first */
+ widths = xmalloc((unsigned) ((unsigned) nw * sizeof(scaled)));
+ heights = xmalloc((unsigned) ((unsigned) nh * sizeof(scaled)));
+ depths = xmalloc((unsigned) ((unsigned) nd * sizeof(scaled)));
+ italics = xmalloc((unsigned) ((unsigned) ni * sizeof(scaled)));
+ extens = xmalloc((unsigned) ((unsigned) ne * sizeof(four_quarters)));
+ lig_kerns = xmalloc((unsigned) ((unsigned) nl * sizeof(four_quarters)));
+ kerns = xmalloc((unsigned) ((unsigned) nk * sizeof(scaled)));
+
+ /* Read the {\.{TFM}} header */
+
+ /* Only the first two words of the header are needed by \TeX82. */
+ slh = lh;
+ if (lh < 2)
+ tfm_abort;
+ store_four_bytes(tmp);
+ font_checksum(f) = (unsigned) tmp;
+ fget;
+ read_sixteen(z); /* this rejects a negative design size */
+ fget;
+ z = z * 256 + fbyte;
+ fget;
+ z = (z * 16) + (fbyte >> 4);
+ if (z < unity)
+ tfm_abort;
+ while (lh > 2) {
+ fget;
+ fget;
+ fget;
+ fget;
+ lh--; /* ignore the rest of the header */
+ };
+
+ /* read the arrays before the character info */
+
+ set_font_dsize(f, z);
+ if (s != -1000) {
+ z = (s >= 0 ? s : xn_over_d(z, -s, 1000));
+ }
+ set_font_size(f, z);
+
+ if (np > 7)
+ set_font_params(f, np);
+
+ saved_tfm_byte = tfm_byte;
+ tfm_byte = (header_length + slh + ncw) * 4 - 1;
+
+ /* Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$ */
+
+ alpha = 16;
+ while (z >= 040000000) {
+ z = z >> 1;
+ alpha = alpha + alpha;
+ };
+ beta = (char) (256 / alpha);
+ alpha = alpha * z;
+
+ /* Read box dimensions */
+
+ for (k = 0; k < nw; k++) {
+ store_scaled(sw);
+ widths[k] = sw;
+ }
+ if (widths[0] != 0) /* \\{width}[0] must be zero */
+ tfm_abort;
+ for (k = 0; k < nh; k++) {
+ store_scaled(sw);
+ heights[k] = sw;
+ }
+ if (heights[0] != 0)
+ tfm_abort; /* \\{height}[0] must be zero */
+ for (k = 0; k < nd; k++) {
+ store_scaled(sw);
+ depths[k] = sw;
+ }
+ if (depths[0] != 0)
+ tfm_abort; /* \\{depth}[0] must be zero */
+ for (k = 0; k < ni; k++) {
+ store_scaled(sw);
+ italics[k] = sw;
+ }
+ if (italics[0] != 0)
+ tfm_abort; /* \\{italic}[0] must be zero */
+
+
+ /* Read ligature/kern program */
+
+ bch_label = nl; /* infinity */
+ bchar = 65536;
+ if (nl > 0) {
+ for (k = 0; k < nl; k++) {
+ read_four_quarters(qw);
+ lig_kerns[k] = qw;
+ if (a > 128) {
+ if (256 * c + d >= nl)
+ tfm_abort;
+ if (a == 255 && k == 0)
+ bchar = b;
+ } else {
+#if 0
+ if (b!=bchar) check_existence(b);
+#endif
+ if (c < 128) {
+#if 0
+ check_existence(d); /* check ligature */
+#endif
+ } else if (256 * (c - 128) + d >= nk) {
+ tfm_abort; /* check kern */
+ }
+ if ((a < 128) && (k - 0 + a + 1 >= nl))
+ tfm_abort;
+ };
+ };
+ if (a == 255)
+ bch_label = 256 * c + d;
+ };
+
+ /* the actual kerns */
+ for (k = 0; k < nk; k++) {
+ store_scaled(sw);
+ kerns[k] = sw;
+ }
+
+ /* Read extensible character recipes */
+ for (k = 0; k < ne; k++) {
+ read_four_quarters(qw);
+ extens[k] = qw;
+ }
+
+ /* Read font parameters */
+
+ if (np > 7) {
+ set_font_params(f, np);
+ }
+ for (k = 1; k <= np; k++) {
+ if (k == 1) { /* the |slant| parameter is a pure number */
+ fget;
+ sw = fbyte;
+ if (sw > 127)
+ sw = sw - 256;
+ fget;
+ sw = sw * 256 + fbyte;
+ fget;
+ sw = sw * 256 + fbyte;
+ fget;
+ sw = (sw * 16) + (fbyte >> 4);
+ set_font_param(f, k, sw);
+ } else {
+ store_scaled(font_param(f, k));
+ }
+ }
+
+ tfm_byte = saved_tfm_byte;
+
+ /* fix up the left boundary character */
+ fligs = 0;
+ fkerns = 0;
+ if (bch_label != nl) {
+ k = bch_label;
+#if 0
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+#endif
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if (op_byte(k) >= kern_flag) { /* kern */
+ fkerns++;
+ } else { /* lig */
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ if (fkerns > 0 || fligs > 0) {
+ if (fligs > 0)
+ cligs = xcalloc((unsigned) (fligs + 1), sizeof(liginfo));
+ if (fkerns > 0)
+ ckerns = xcalloc((unsigned) (fkerns + 1), sizeof(kerninfo));
+ fligs = 0;
+ fkerns = 0;
+ k = bch_label;
+#if 0
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+#endif
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if (op_byte(k) >= kern_flag) { /* kern */
+ set_kern_item(ckerns[fkerns], next_char(k),
+ kerns[256 * (op_byte(k) - 128) +
+ rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ set_ligature_item(cligs[fligs], (char) (op_byte(k) * 2 + 1),
+ next_char(k), rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns > 0 || fligs > 0) {
+ co = get_charinfo(f, left_boundarychar);
+ if (fkerns > 0) {
+ set_kern_item(ckerns[fkerns], end_kern, 0);
+ fkerns++;
+ set_charinfo_kerns(co, ckerns);
+ }
+ if (fligs > 0) {
+ set_ligature_item(cligs[fligs], 0, end_ligature, 0);
+ fligs++;
+ set_charinfo_ligatures(co, cligs);
+ }
+ set_charinfo_remainder(co, 0);
+ }
+ }
+
+ /* Read character data */
+ for (k = bc; k <= ec; k++) {
+ store_char_info(k);
+ if (ci._width_index == 0)
+ continue;
+ if (ci._width_index >= nw || ci._height_index >= nh ||
+ ci._depth_index >= nd || ci._italic_index >= ni)
+ tfm_abort;
+ d = ci._remainder;
+ switch (ci._tag) {
+ case lig_tag:
+ if (d >= nl)
+ tfm_abort;
+ break;
+ case ext_tag:
+ if (d >= ne)
+ tfm_abort;
+ break;
+ case list_tag:
+ /* We want to make sure that there is no cycle of characters linked together
+ by |list_tag| entries, since such a cycle would get \TeX\ into an endless
+ loop. If such a cycle exists, the routine here detects it when processing
+ the largest character code in the cycle.
+ */
+ check_byte_range(d);
+ while (d < k) { /* |current_character == k| */
+ if (char_tag(f, d) != list_tag)
+ goto NOT_FOUND; /* not a cycle */
+ d = char_remainder(f, d); /* next character on the list */
+ };
+ if (d == k)
+ tfm_abort; /* yes, there's a cycle */
+ NOT_FOUND:
+ break;
+ }
+ /* put it in the actual font */
+ co = get_charinfo(f, k);
+ set_charinfo_index(co, k);
+ set_charinfo_tag(co, ci._tag);
+ if (ci._tag == ext_tag) {
+ set_charinfo_extensible(co, extens[ci._remainder].b0, /* top */
+ extens[ci._remainder].b2, /* bot */
+ extens[ci._remainder].b1, /* mid */
+ extens[ci._remainder].b3); /* rep */
+ set_charinfo_remainder(co, 0);
+ } else {
+ set_charinfo_remainder(co, ci._remainder);
+ }
+ set_charinfo_width(co, widths[ci._width_index]);
+ set_charinfo_height(co, heights[ci._height_index]);
+ set_charinfo_depth(co, depths[ci._depth_index]);
+ set_charinfo_italic(co, italics[ci._italic_index]);
+ };
+
+ /* first pass: count ligs and kerns */
+
+ xligs = xcalloc((unsigned) (ec + 1), sizeof(int));
+ xkerns = xcalloc((unsigned) (ec + 1), sizeof(int));
+
+ for (i = bc; i <= ec; i++) {
+ if (char_tag(f, i) == lig_tag) {
+ k = lig_kern_start(f, i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if (op_byte(k) >= kern_flag) { /* kern */
+ xkerns[i]++;
+ if (next_char(k) == bchar)
+ xkerns[i]++;
+ } else { /* lig */
+ xligs[i]++;
+ if (next_char(k) == bchar)
+ xligs[i]++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ }
+
+ cligs = NULL;
+ ckerns = NULL;
+
+ for (i = bc; i <= ec; i++) {
+ fligs = 0;
+ fkerns = 0;
+ if (char_tag(f, i) == lig_tag) {
+ k = lig_kern_start(f, i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ if (xligs[i] > 0)
+ cligs = xcalloc((unsigned) (xligs[i] + 1), sizeof(liginfo));
+ if (xkerns[i] > 0)
+ ckerns = xcalloc((unsigned) (xkerns[i] + 1), sizeof(kerninfo));
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if (op_byte(k) >= kern_flag) { /* kern */
+ if (next_char(k) == bchar) {
+ set_kern_item(ckerns[fkerns], right_boundarychar,
+ kerns[256 * (op_byte(k) - 128) +
+ rem_byte(k)]);
+ fkerns++;
+ }
+ set_kern_item(ckerns[fkerns], next_char(k),
+ kerns[256 * (op_byte(k) - 128) +
+ rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ if (next_char(k) == bchar) {
+ set_ligature_item(cligs[fligs],
+ (char) (op_byte(k) * 2 + 1),
+ right_boundarychar, rem_byte(k));
+ fligs++;
+ }
+ set_ligature_item(cligs[fligs],
+ (char) (op_byte(k) * 2 + 1),
+ next_char(k), rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns > 0 || fligs > 0) {
+ co = get_charinfo(f, i);
+ if (fkerns > 0) {
+ set_kern_item(ckerns[fkerns], end_kern, 0);
+ fkerns++;
+ set_charinfo_kerns(co, ckerns);
+ }
+ if (fligs > 0) {
+ set_ligature_item(cligs[fligs], 0, end_ligature, 0);
+ fligs++;
+ set_charinfo_ligatures(co, cligs);
+ }
+ set_charinfo_remainder(co, 0);
+ }
+ }
+ }
+
+
+ /* Make final adjustments and |goto done| */
+
+ /* Now to wrap it up, we have checked all the necessary things about the \.{TFM}
+ file, and all we need to do is put the finishing touches on the data for
+ the new font.
+ */
+
+ if (bchar != 65536) {
+ co = copy_charinfo(char_info(f, bchar));
+ set_right_boundary(f, co);
+ }
+
+ tfm_success;
+}