home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / unix / unix_dra.hqx / scaletfm.c < prev    next >
C/C++ Source or Header  |  1987-02-14  |  3KB  |  110 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: scaletfm.c,v 1.3 85/09/12 08:51:10 chris Exp $";
  3. #endif
  4.  
  5. #include "types.h"
  6. #include "pxl.h"
  7.  
  8. /* From DVITYPE.WEB:
  9.  
  10.  ``The most important part of in_TFM is the width computation, which
  11.    involvles multiplying the relative widths in the TFM file by the scaling
  12.    factor in the DVI file.  This fixed-point multiplication must be done with
  13.    precisely the same accuracy by all DVI-reading programs, in order to
  14.    validate the assumptions made by DVI-writing programs like \TeX 82.
  15.  
  16.    Let us therefore summarize what needs to be done.  Each width in a TFM
  17.    file appears as a four-byte quantity called a fix_word.  A fix_word whose
  18.    respective bytes are (a,b,c,d) represents the number
  19.  
  20.        {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20},        if a = 0;
  21.       x = {{
  22.        {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20},  if a = 255.
  23.  
  24.    (No other choices of a are allowed, since the magnitude of a TFM dimension
  25.    must be less than 16.)  We want to multiply this quantity by the integer
  26.    z, which is known to be less than 2^{27}.  Let \alpha = 16z.  If z <
  27.    2^{23}, the individual multiplications b * z, c * z, d * z cannot
  28.    overflow; otherwise we will divide z by 2, 4, 8, or 16, to obtain a
  29.    multiplier less than 2^{23}, and we can compensate for this later.  If z
  30.    has thereby been replaced by z' = z/2^e, let \beta = 2^{4-e}; we shall
  31.    compute
  32.  
  33.     \lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor
  34.  
  35.    if a = 0, or the same quantity minus \alpha if a = 255.  This calculation
  36.    must be done exactly, for the reasons stated above; the following program
  37.    does the job in a system-independent way, assuming that arithmetic is
  38.    exact on numbers less than 2^{31} in magnitude.'' */
  39.  
  40. /* In other words, we are assuming 32-bit (minimum) arithmetic, and take
  41.    pains to ensure that each intermediate result fits within 32 bits.
  42.    This routine converts the TFM widths in the px_info part of a pxltail
  43.    pointer 'px' given the scale factor 'z'. */
  44. ScaleTFMWidths (px, z)
  45. struct pxltail *px;
  46. register i32 z;
  47. {
  48.     register i32    alpha,
  49.             log2beta,
  50.             t;
  51.     register struct chinfo *ch;
  52.     register int    i;
  53.  
  54.  /* First compute \alpha, \beta, and z': */
  55.     alpha = 16 * z;
  56.     log2beta = 4;
  57.     while (z >= (1 << 23)) {
  58.     z >>= 1;
  59.     log2beta--;
  60.     }
  61.  
  62.  /* The four values 'a', 'b', 'c', and 'd' are fields within t: */
  63. #define a (UnSign8 (t >> 24))
  64. #define b (UnSign8 (t >> 16))
  65. #define c (UnSign8 (t >> 8))
  66. #define d (UnSign8 (t))
  67.  
  68.     ch = px -> px_info;
  69.     for (i = 0; i < 128; i++) {
  70.     if (t = ch -> ch_TFMwidth) {
  71.         t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
  72.         if (a) {
  73.         if (a != 255)
  74.             error (0, 0, "bad TFM width!");
  75.         t -= alpha;
  76.         }
  77.         ch -> ch_TFMwidth = t;
  78.     }
  79.     ch++;
  80.     }
  81. }
  82.  
  83. /* Provided in case anyone is not using the standard PXL file formats:
  84.    scale the single TFM width 't' by 'z' */
  85. i32
  86. ScaleOneWidth (t, z)
  87. register i32 t, z;
  88. {
  89.     register i32    alpha,
  90.             log2beta;
  91.  
  92.     alpha = 16 * z;
  93.     log2beta = 4;
  94.     while (z >= (1 << 23)) {
  95.     z >>= 1;
  96.     log2beta--;
  97.     }
  98.  
  99.     if (t) {
  100.     t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
  101.     if (a) {
  102.         if (a != 255)
  103.         error (0, 0, "bad TFM width! [ScaleOneWidth]");
  104.         t -= alpha;
  105.     }
  106.     }
  107.  
  108.     return t;
  109. }
  110.