summaryrefslogtreecommitdiff
path: root/dviware/umddvi/lib/scaletfm.c
blob: c04fd62c04aa4d40908076c219d41e00fa3747c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * 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;
	}
}