home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char rcsid[] = "$Header: scaletfm.c,v 1.3 85/09/12 08:51:10 chris Exp $";
- #endif
-
- #include "types.h"
- #include "pxl.h"
-
- /* From DVITYPE.WEB:
-
- ``The most important part of in_TFM is the width computation, which
- involvles multiplying the relative widths in the TFM file by the scaling
- factor in the DVI file. This fixed-point multiplication must be done with
- precisely the same accuracy by all DVI-reading programs, in order to
- validate the assumptions made by DVI-writing programs like \TeX 82.
-
- Let us therefore summarize what needs to be done. Each width in a TFM
- file appears as a four-byte quantity called a fix_word. A fix_word whose
- respective bytes are (a,b,c,d) represents the number
-
- {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 0;
- x = {{
- {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20}, if a = 255.
-
- (No other choices of a are allowed, since the magnitude of a TFM dimension
- must be less than 16.) We want to multiply this quantity by the integer
- z, which is known to be less than 2^{27}. Let \alpha = 16z. If z <
- 2^{23}, the individual multiplications b * z, c * z, d * 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' = z/2^e, let \beta = 2^{4-e}; we shall
- compute
-
- \lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor
-
- if a = 0, or the same quantity minus \alpha if a = 255. This calculation
- must be done exactly, for the reasons stated above; the following program
- does the job in a system-independent way, assuming that arithmetic is
- exact on numbers less than 2^{31} in magnitude.'' */
-
- /* In other words, we are assuming 32-bit (minimum) arithmetic, and take
- pains to ensure that each intermediate result fits within 32 bits.
- This routine converts the TFM widths in the px_info part of a pxltail
- pointer 'px' given the scale factor 'z'. */
- ScaleTFMWidths (px, z)
- struct pxltail *px;
- register i32 z;
- {
- register i32 alpha,
- log2beta,
- t;
- register struct chinfo *ch;
- register int i;
-
- /* First compute \alpha, \beta, and z': */
- alpha = 16 * z;
- log2beta = 4;
- while (z >= (1 << 23)) {
- z >>= 1;
- log2beta--;
- }
-
- /* The four values 'a', 'b', 'c', and 'd' are fields within t: */
- #define a (UnSign8 (t >> 24))
- #define b (UnSign8 (t >> 16))
- #define c (UnSign8 (t >> 8))
- #define d (UnSign8 (t))
-
- ch = px -> px_info;
- for (i = 0; i < 128; i++) {
- if (t = ch -> ch_TFMwidth) {
- t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
- if (a) {
- if (a != 255)
- error (0, 0, "bad TFM width!");
- t -= alpha;
- }
- ch -> ch_TFMwidth = t;
- }
- ch++;
- }
- }
-
- /* Provided in case anyone is not using the standard PXL file formats:
- scale the single TFM width 't' by 'z' */
- i32
- ScaleOneWidth (t, z)
- register i32 t, z;
- {
- register i32 alpha,
- log2beta;
-
- alpha = 16 * z;
- log2beta = 4;
- while (z >= (1 << 23)) {
- z >>= 1;
- log2beta--;
- }
-
- if (t) {
- t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
- if (a) {
- if (a != 255)
- error (0, 0, "bad TFM width! [ScaleOneWidth]");
- t -= alpha;
- }
- }
-
- return t;
- }
-