Commit faaba717 authored by Albert Astals Cid's avatar Albert Astals Cid

xpdf303: FixedPoint improvements

parent 73efc96e
......@@ -82,28 +82,32 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
}
int FixedPoint::mul(int x, int y) {
#if 1 //~tmp
return ((FixPtInt64)x * y) >> fixptShift;
#else
int ah0, ah, bh, al, bl;
ah0 = x & fixptMaskH;
ah = x >> fixptShift;
al = x - ah0;
bh = y >> fixptShift;
bl = y - (bh << fixptShift);
return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift);
#endif
FixPtInt64 z;
z = ((FixPtInt64)x * y) >> fixptShift;
if (z > 0x7fffffffLL) {
return 0x7fffffff;
} else if (z < -0x80000000LL) {
return 0x80000000;
} else {
return (int)z;
}
}
int FixedPoint::div(int x, int y) {
#if 1 //~tmp
return ((FixPtInt64)x << fixptShift) / y;
#else
#endif
FixPtInt64 z;
z = ((FixPtInt64)x << fixptShift) / y;
if (z > 0x7fffffffLL) {
return 0x7fffffff;
} else if (z < -0x80000000LL) {
return 0x80000000;
} else {
return (int)z;
}
}
GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
#if 1 //~tmp
FixPtInt64 z;
z = ((FixPtInt64)x.val << fixptShift) / y.val;
......@@ -113,8 +117,19 @@ GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
}
result->val = z;
return gTrue;
#else
#endif
}
GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
FixedPoint m21, FixedPoint m22,
FixedPoint epsilon) {
FixPtInt64 det, e;
det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
- (FixPtInt64)m12.val * (FixPtInt64)m21.val;
e = (FixPtInt64)epsilon.val << fixptShift;
// NB: this comparison has to be >= not > because epsilon can be
// truncated to zero as a fixed point value.
return det >= e || det <= -e;
}
#endif // USE_FIXEDPOINT
......@@ -45,7 +45,7 @@ public:
operator int()
{ return val >> fixptShift; }
int getRaw() { return val; }
int get16Dot16() { return val; }
FixedPoint operator =(FixedPoint x) { val = x.val; return *this; }
......@@ -132,6 +132,11 @@ public:
static int round(FixedPoint x)
{ return (x.val + (1 << (fixptShift - 1))) >> fixptShift; }
// Computes (x+y)/2 avoiding overflow and LSbit accuracy issues.
static FixedPoint avg(FixedPoint x, FixedPoint y)
{ return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); }
static FixedPoint sqrt(FixedPoint x);
static FixedPoint pow(FixedPoint x, FixedPoint y);
......@@ -140,6 +145,12 @@ public:
// overflow.
static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
// Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case
// where the multiplications overflow.
static GBool checkDet(FixedPoint m11, FixedPoint m12,
FixedPoint m21, FixedPoint m22,
FixedPoint epsilon);
private:
static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
......@@ -147,7 +158,7 @@ private:
static int mul(int x, int y);
static int div(int x, int y);
int val; // 16.16 fixed point
int val; // fixed point: (n-fixptShift).(fixptShift)
};
#endif // USE_FIXEDPOINT
......
......@@ -1397,7 +1397,11 @@ SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix,
int i;
fPath = new SplashPath();
#if USE_FIXEDPOINT
flatness2 = flatness;
#else
flatness2 = flatness * flatness;
#endif
i = 0;
while (i < path->length) {
flag = path->flags[i];
......@@ -1462,13 +1466,21 @@ void Splash::flattenCurve(SplashCoord x0, SplashCoord y0,
// line)
transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my);
transform(matrix, xx1, yy1, &tx, &ty);
#if USE_FIXEDPOINT
d1 = splashDist(tx, ty, mx, my);
#else
dx = tx - mx;
dy = ty - my;
d1 = dx*dx + dy*dy;
#endif
transform(matrix, xx2, yy2, &tx, &ty);
#if USE_FIXEDPOINT
d2 = splashDist(tx, ty, mx, my);
#else
dx = tx - mx;
dy = ty - my;
d2 = dx*dx + dy*dy;
#endif
// if the curve is flat enough, or no more subdivisions are
// allowed, add the straight line segment
......
......@@ -146,14 +146,14 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
// compute the transform matrix
#if USE_FIXEDPOINT
matrix.xx = (FT_Fixed)((mat[0] / size).getRaw());
matrix.yx = (FT_Fixed)((mat[1] / size).getRaw());
matrix.xy = (FT_Fixed)((mat[2] / size).getRaw());
matrix.yy = (FT_Fixed)((mat[3] / size).getRaw());
textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).getRaw());
textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).getRaw());
textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).getRaw());
textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).getRaw());
matrix.xx = (FT_Fixed)((mat[0] / size).get16Dot16());
matrix.yx = (FT_Fixed)((mat[1] / size).get16Dot16());
matrix.xy = (FT_Fixed)((mat[2] / size).get16Dot16());
matrix.yy = (FT_Fixed)((mat[3] / size).get16Dot16());
textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).get16Dot16());
textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).get16Dot16());
textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).get16Dot16());
textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).get16Dot16());
#else
matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
......
......@@ -97,15 +97,17 @@ static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
#if USE_FIXEDPOINT
// this handles the situation where dx*dx or dy*dy is too large to
// fit in the 16.16 fixed point format
SplashCoord dxa, dya;
SplashCoord dxa, dya, d;
dxa = splashAbs(dx);
dya = splashAbs(dy);
if (dxa == 0 && dya == 0) {
return 0;
} else if (dxa > dya) {
return dxa * FixedPoint::sqrt(dya / dxa + 1);
d = dya / dxa;
return dxa * FixedPoint::sqrt(d*d + 1);
} else {
return dya * FixedPoint::sqrt(dxa / dya + 1);
d = dxa / dya;
return dya * FixedPoint::sqrt(d*d + 1);
}
#else
return splashSqrt(dx * dx + dy * dy);
......
......@@ -289,7 +289,11 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
SplashCoord dx, dy, mx, my, d1, d2, flatness2;
int p1, p2, p3;
#if USE_FIXEDPOINT
flatness2 = flatness;
#else
flatness2 = flatness * flatness;
#endif
// initial segment
p1 = 0;
......@@ -315,12 +319,17 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
// line)
mx = (xl0 + xr3) * 0.5;
my = (yl0 + yr3) * 0.5;
#if USE_FIXEDPOINT
d1 = splashDist(xx1, yy1, mx, my);
d2 = splashDist(xx2, yy2, mx, my);
#else
dx = xx1 - mx;
dy = yy1 - my;
d1 = dx*dx + dy*dy;
dx = xx2 - mx;
dy = yy2 - my;
d2 = dx*dx + dy*dy;
#endif
// if the curve is flat enough, or no more subdivisions are
// allowed, add the straight line segment
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment