/* * Copyright (c) 1987 University of Maryland Department of Computer Science. * All rights reserved. Permission to copy for any purpose is hereby granted * so long as this copyright notice remains intact. */ #ifndef lint static char rcsid[] = "$Header: scaletfm.c,v 2.5 87/06/16 18:28:49 chris Exp $"; #endif #include "types.h" #include "font.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.'' */ /* * Scale the single TFM width t by z. */ i32 ScaleOneWidth(t, z) register i32 t, z; { register i32 alpha, log2beta; /* 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)) 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); } /* * Scale a set of glyphs [l..h) in font f according to f->f_dvimag. */ ScaleGlyphs(f, l, h) register struct font *f; int l, h; { register int i; register i32 t, z, alpha, log2beta; z = f->f_dvimag; alpha = 16 * z; log2beta = 4; while (z >= (1 << 23)) { z >>= 1; log2beta--; } for (i = l; i < h; i++) { if ((t = f->f_gly[i]->g_tfmwidth) == 0) continue; t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta; if (a) { if (a != 255) error(0, 0, "\"%s\", glyph %d: bad TFM width", f->f_path, i); t -= alpha; } f->f_gly[i]->g_tfmwidth = t; } }