diff options
author | Keith Packard <keithp@keithp.com> | 2008-03-17 23:03:56 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2008-11-24 13:24:38 -0800 |
commit | 160252d94f04acc95f0a4e0f884ff565a5aa0744 (patch) | |
tree | 4f9a12e03b2b8bf77379807ab17c2720f5edee5f | |
parent | 8fd82c88e3f2060fda4ba30376900ece77668c63 (diff) |
Add matrix inversion function (uses doubles)
The obvious matrix inversion function, coded using doubles to avoid fiddling
with fixed point precision adventures.
-rw-r--r-- | render/matrix.c | 80 | ||||
-rw-r--r-- | render/picturestr.h | 3 |
2 files changed, 83 insertions, 0 deletions
diff --git a/render/matrix.c b/render/matrix.c index a97630473..6e502057c 100644 --- a/render/matrix.c +++ b/render/matrix.c @@ -262,6 +262,86 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix) } } +static const int a[3] = { 3, 3, 2 }; +static const int b[3] = { 2, 1, 1 }; + +static void +to_doubles (double m[3][3], const PictTransformPtr t) +{ + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + m[j][i] = pixman_fixed_to_double (t->matrix[j][i]); +} + +static Bool +from_doubles (PictTransformPtr t, double m[3][3]) +{ + int i, j; + + for (j = 0; j < 3; j++) + for (i = 0; i < 3; i++) + { + double d = m[j][i]; + if (d < -32767.0 || d > 32767.0) + return FALSE; + t->matrix[j][i] = pixman_double_to_fixed (d); + } + return TRUE; +} + +static Bool +invert (double r[3][3], double m[3][3]) +{ + double det, norm; + int i, j; + static int a[3] = { 2, 2, 1 }; + static int b[3] = { 1, 0, 0 }; + + det = 0; + for (i = 0; i < 3; i++) { + double p; + int ai = a[i]; + int bi = b[i]; + p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]); + if (i == 1) + p = -p; + det += p; + } + if (det == 0) + return FALSE; + det = 1/det; + for (j = 0; j < 3; j++) { + for (i = 0; i < 3; i++) { + double p; + int ai = a[i]; + int aj = a[j]; + int bi = b[i]; + int bj = b[j]; + + p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj]; + if (((i + j) & 1) != 0) + p = -p; + r[j][i] = det * p; + } + } + return TRUE; +} + +_X_EXPORT Bool +PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src) +{ + double m[3][3], r[3][3]; + + to_doubles (m, src); + if (!invert (r, m)) + return FALSE; + if (!from_doubles (dst, r)) + return FALSE; + return TRUE; +} + static Bool within_epsilon (xFixed a, xFixed b, xFixed epsilon) { diff --git a/render/picturestr.h b/render/picturestr.h index 60be68ab8..658e221b4 100644 --- a/render/picturestr.h +++ b/render/picturestr.h @@ -720,6 +720,9 @@ void PictureTransformBounds (BoxPtr b, PictTransformPtr matrix); Bool +PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src); + +Bool PictureTransformIsIdentity(PictTransform *t); Bool |