home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / libtex / scaletfm.c < prev    next >
C/C++ Source or Header  |  1990-07-10  |  3KB  |  121 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/lib/RCS/scaletfm.c,v 3.2 89/11/23 16:34:43 chris Exp $";
  10. #endif
  11.  
  12. #include "types.h"
  13. #include "error.h"
  14. #include "font.h"
  15.  
  16. /*
  17.  * From DVITYPE.WEB:
  18.  *
  19.  * ``The most important part of in_TFM is the width computation, which
  20.  *   involvles multiplying the relative widths in the TFM file by the scaling
  21.  *   factor in the DVI file.  This fixed-point multiplication must be done with
  22.  *   precisely the same accuracy by all DVI-reading programs, in order to
  23.  *   validate the assumptions made by DVI-writing programs like \TeX 82.
  24.  *
  25.  *   Let us therefore summarize what needs to be done.  Each width in a TFM
  26.  *   file appears as a four-byte quantity called a fix_word.  A fix_word whose
  27.  *   respective bytes are (a,b,c,d) represents the number
  28.  *
  29.  *       {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20},        if a = 0;
  30.  *    x = {{
  31.  *       {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20},  if a = 255.
  32.  *
  33.  *   (No other choices of a are allowed, since the magnitude of a TFM dimension
  34.  *   must be less than 16.)  We want to multiply this quantity by the integer
  35.  *   z, which is known to be less than 2^{27}.  Let \alpha = 16z.  If z <
  36.  *   2^{23}, the individual multiplications b * z, c * z, d * z cannot
  37.  *   overflow; otherwise we will divide z by 2, 4, 8, or 16, to obtain a
  38.  *   multiplier less than 2^{23}, and we can compensate for this later.  If z
  39.  *   has thereby been replaced by z' = z/2^e, let \beta = 2^{4-e}; we shall
  40.  *   compute
  41.  *
  42.  *    \lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor
  43.  *
  44.  *   if a = 0, or the same quantity minus \alpha if a = 255.  This calculation
  45.  *   must be done exactly, for the reasons stated above; the following program
  46.  *   does the job in a system-independent way, assuming that arithmetic is
  47.  *   exact on numbers less than 2^{31} in magnitude.''
  48.  */
  49. #define    ZLIM    ((i32)1 << 23)    /* z must be < zlim */
  50.  
  51. /*
  52.  * Scale the single TFM width t by z.
  53.  */
  54. i32
  55. ScaleOneWidth(t, z)
  56.     register i32 t, z;
  57. {
  58.     register i32 alpha, log2beta;
  59.     register int a0;
  60.  
  61.     /* First compute \alpha, \beta, and z': */
  62.     alpha = 16 * z;
  63.     log2beta = 4;
  64.     while (z >= ZLIM) {
  65.         z >>= 1;
  66.         log2beta--;
  67.     }
  68.  
  69.     /* The four values 'a', 'b', 'c', and 'd' are fields within t: */
  70. #define    a    (UnSign8(t >> 24))
  71. #define    b    (UnSign8(t >> 16))
  72. #define    c    (UnSign8(t >> 8))
  73. #define    d    (UnSign8(t))
  74.     if (t) {
  75.         a0 = a;
  76.         t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
  77.         if (a0) {
  78.             if (a0 != 255)
  79.                 error(0, 0, "bad TFM width! [ScaleOneWidth]");
  80.             t -= alpha;
  81.         }
  82.     }
  83.     return (t);
  84. }
  85.  
  86. /*
  87.  * Scale a set of glyphs [l..h) in font f according to f->f_dvimag
  88.  * (that is, set g_tfmwidth from g_rawtfmwidth).
  89.  */
  90. ScaleGlyphs(f, l, h)
  91.     register struct font *f;
  92.     int l, h;
  93. {
  94.     register int i, a0;
  95.     register i32 t, z, alpha, log2beta;
  96.  
  97.     z = f->f_dvimag;
  98.     alpha = 16 * z;
  99.     log2beta = 4;
  100.     while (z >= ZLIM) {
  101.         z >>= 1;
  102.         log2beta--;
  103.     }
  104.  
  105.     for (i = l; i < h; i++) {
  106.         if ((t = f->f_gly[i]->g_rawtfmwidth) != 0) {
  107.             a0 = a;
  108.             t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >>
  109.                 log2beta;
  110.             if (a0) {
  111.                 if (a0 != 255)
  112.                     error(0, 0,
  113.                         "\"%s\", glyph %d: bad TFM width",
  114.                         f->f_path, i);
  115.                 t -= alpha;
  116.             }
  117.         }
  118.         f->f_gly[i]->g_tfmwidth = t;
  119.     }
  120. }
  121.