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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/*
* This function calculates approximately (whole + num/den) * sf.
* No need for real extreme accuracy; one twenty thousandth of an
* inch should be sufficient.
*
* No `sf' parameter means to use an old one; inches are assumed
* originally.
*
* Assumptions:
*
* 0 <= num < den <= 20000
* 0 <= whole
*/
#include "dvips.h" /* The copyright notice in that file is included too! */
/*
* The external declarations:
*/
#include "protos.h"
static long
scale(long whole, long num, long den, long sf)
{
long v;
v = whole * sf + num * (sf / den);
if (v / sf != whole || v < 0 || v > 0x40000000L)
error("! arithmetic overflow in parameter");
sf = sf % den;
v += (sf * num * 2 + den) / (2 * den);
return(v);
}
/*
* Convert a sequence of digits into a long; return -1 if no digits.
* Advance the passed pointer as well.
*/
static long
myatol(char **s)
{
register char *p;
register long result;
result = 0;
p = *s;
while ('0' <= *p && *p <= '9') {
if (result > 100000000)
error("! arithmetic overflow in parameter");
result = 10 * result + *p++ - '0';
}
if (p == *s && *p == '.') {
return 0;
} else if (p == *s) {
#ifdef KPATHSEA
error(concat3 ("expected number in ", *s, ", returning 10"));
#else
error("expected number! returning 10");
#endif
return 10;
} else {
*s = p;
return(result);
}
}
/*
* Get a dimension, allowing all the various extensions, and
* defaults. Returns a value in scaled points.
*/
static long scalevals[] = { 1864680L, 65536L, 786432L, 186468L,
1L, 65782L, 70124L, 841489L, 4736286L };
static const char *scalenames = "cmptpcmmspbpddccin";
static long
myatodim(char **s)
{
register long w, num, den, sc;
register const char *q;
char *p;
int negative = 0, i;
p = *s;
if (**s == '-') {
p++;
negative = 1;
}
w = myatol(&p);
if (w < 0) {
error("number too large; 1000 used");
w = 1000;
}
num = 0;
den = 1;
if (*p == '.') {
p++;
while ('0' <= *p && *p <= '9') {
if (den <= 1000) {
den *= 10;
num = num * 10 + *p - '0';
} else if (den == 10000) {
den *= 2;
num = num * 2 + (*p - '0') / 5;
}
p++;
}
}
while (*p == ' ')
p++;
for (i=0, q=scalenames;; i++, q += 2)
if (*q == 0) {
#ifdef KPATHSEA
error(concat3 ("expected units in ", *s, ", assuming inches."));
#else
error("expected units! assuming inches.");
#endif
sc = scalevals[8];
break;
} else if (*p == *q && p[1] == q[1]) {
sc = scalevals[i];
p += 2;
break;
}
w = scale(w, num, den, sc);
*s = p;
return(negative?-w:w);
}
/*
* The routine where we handle the paper size special. We need to pass in
* the string after the `papersize=' specification.
*/
void
handlepapersize(char *p, integer *x, integer *y)
{
while (*p == ' ')
p++;
*x = myatodim(&p);
while (*p == ' ' || *p == ',')
p++;
*y = myatodim(&p);
}
|