| /* |
| * Twin - A Tiny Window System |
| * Copyright © 2004 Keith Packard <keithp@keithp.com> |
| * All rights reserved. |
| * |
| * This Library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or (at your option) any later version. |
| * |
| * This Library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with the Twin Library; see the file COPYING. If not, |
| * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| * Boston, MA 02111-1307, USA. |
| */ |
| |
| #include "twinint.h" |
| |
| #if 0 |
| #include <stdio.h> |
| #define F(f) (twin_fixed_to_double(f)) |
| #define DBGMSG(x) printf x |
| |
| static void |
| _twin_dump_matrix (char *name, const twin_matrix_t *m) |
| { |
| int row, col; |
| |
| printf ("%-6.6s:", name); |
| for (row = 0; row < 3; row++) |
| { |
| printf ("\t"); |
| for (col = 0; col < 2; col++) |
| printf ("%9.4f ", twin_fixed_to_double (m->m[row][col])); |
| printf ("\n"); |
| } |
| } |
| |
| #else |
| #define DBGMSG(x) |
| #define _twin_dump_matrix(n,m) |
| #endif |
| |
| void |
| twin_matrix_multiply (twin_matrix_t *result, |
| const twin_matrix_t *a, |
| const twin_matrix_t *b) |
| { |
| twin_matrix_t r; |
| int row, col, n; |
| twin_fixed_t t; |
| |
| for (row = 0; row < 3; row++) |
| for (col = 0; col < 2; col++) { |
| if (row == 2) |
| t = b->m[2][col]; |
| else |
| t = 0; |
| for (n = 0; n < 2; n++) |
| t += twin_fixed_mul(a->m[row][n], b->m[n][col]); |
| r.m[row][col] = t; |
| } |
| _twin_dump_matrix ("a", a); |
| _twin_dump_matrix ("b", b); |
| _twin_dump_matrix ("r", &r); |
| |
| *result = r; |
| } |
| |
| void |
| twin_matrix_identity (twin_matrix_t *m) |
| { |
| m->m[0][0] = TWIN_FIXED_ONE; m->m[0][1] = 0; |
| m->m[1][0] = 0; m->m[1][1] = TWIN_FIXED_ONE; |
| m->m[2][0] = 0; m->m[2][1] = 0; |
| } |
| |
| twin_bool_t |
| twin_matrix_is_identity (twin_matrix_t *m) |
| { |
| return m->m[0][0] == TWIN_FIXED_ONE && m->m[0][1] == 0 && |
| m->m[1][0] == 0 && m->m[1][1] == TWIN_FIXED_ONE && |
| m->m[2][0] == 0 && m->m[2][1] == 0; |
| } |
| |
| void |
| twin_matrix_translate (twin_matrix_t *m, twin_fixed_t tx, twin_fixed_t ty) |
| { |
| twin_matrix_t t; |
| |
| t.m[0][0] = TWIN_FIXED_ONE; t.m[0][1] = 0; |
| t.m[1][0] = 0; t.m[1][1] = TWIN_FIXED_ONE; |
| t.m[2][0] = tx; t.m[2][1] = ty; |
| twin_matrix_multiply (m, &t, m); |
| } |
| |
| void |
| twin_matrix_scale (twin_matrix_t *m, twin_fixed_t sx, twin_fixed_t sy) |
| { |
| twin_matrix_t t; |
| |
| t.m[0][0] = sx; t.m[0][1] = 0; |
| t.m[1][0] = 0; t.m[1][1] = sy; |
| t.m[2][0] = 0; t.m[2][1] = 0; |
| twin_matrix_multiply (m, &t, m); |
| } |
| |
| twin_fixed_t |
| _twin_matrix_determinant (twin_matrix_t *matrix) |
| { |
| twin_fixed_t a, b, c, d; |
| twin_fixed_t det; |
| |
| a = matrix->m[0][0]; b = matrix->m[0][1]; |
| c = matrix->m[1][0]; d = matrix->m[1][1]; |
| |
| det = twin_fixed_mul (a, d) - twin_fixed_mul (b, c); |
| |
| return det; |
| } |
| |
| twin_point_t |
| _twin_matrix_expand (twin_matrix_t *matrix) |
| { |
| twin_fixed_t a = matrix->m[0][0]; |
| twin_fixed_t d = matrix->m[1][1]; |
| twin_fixed_t aa = twin_fixed_mul (a,a); |
| twin_fixed_t dd = twin_fixed_mul (d,d); |
| twin_point_t expand; |
| |
| expand.x = twin_fixed_sqrt (aa + dd); |
| expand.y = twin_fixed_div (_twin_matrix_determinant (matrix), |
| expand.x); |
| return expand; |
| } |
| |
| void |
| twin_matrix_rotate (twin_matrix_t *m, twin_angle_t a) |
| { |
| twin_matrix_t t; |
| twin_fixed_t c = twin_cos (a); |
| twin_fixed_t s = twin_sin (a); |
| |
| t.m[0][0] = c; t.m[0][1] = s; |
| t.m[1][0] = -s; t.m[1][1] = c; |
| t.m[2][0] = 0; t.m[2][1] = 0; |
| twin_matrix_multiply (m, &t, m); |
| } |
| |
| twin_sfixed_t |
| _twin_matrix_x (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| twin_sfixed_t s; |
| s = twin_fixed_to_sfixed (twin_fixed_mul (m->m[0][0], x) + |
| twin_fixed_mul (m->m[1][0], y) + |
| m->m[2][0]); |
| DBGMSG (("x: %9.4f,%9.4f -> %9.4f\n", |
| twin_fixed_to_double(x), twin_fixed_to_double(y), |
| twin_sfixed_to_double (s))); |
| return s; |
| } |
| |
| twin_sfixed_t |
| _twin_matrix_y (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| twin_sfixed_t s; |
| s = twin_fixed_to_sfixed (twin_fixed_mul (m->m[0][1], x) + |
| twin_fixed_mul (m->m[1][1], y) + |
| m->m[2][1]); |
| DBGMSG (("y: %9.4f,%9.4f -> %9.4f\n", |
| twin_fixed_to_double(x), twin_fixed_to_double(y), |
| twin_sfixed_to_double (s))); |
| return s; |
| } |
| |
| twin_fixed_t |
| _twin_matrix_fx (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| return twin_fixed_mul (m->m[0][0], x) + |
| twin_fixed_mul (m->m[1][0], y) + |
| m->m[2][0]; |
| } |
| |
| twin_fixed_t |
| _twin_matrix_fy (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| return twin_fixed_mul (m->m[0][1], x) + |
| twin_fixed_mul (m->m[1][1], y) + |
| m->m[2][1]; |
| } |
| |
| twin_sfixed_t |
| _twin_matrix_dx (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| return twin_fixed_to_sfixed (twin_fixed_mul (m->m[0][0], x) + |
| twin_fixed_mul (m->m[1][0], y)); |
| |
| } |
| |
| twin_sfixed_t |
| _twin_matrix_dy (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y) |
| { |
| return twin_fixed_to_sfixed (twin_fixed_mul (m->m[0][1], x) + |
| twin_fixed_mul (m->m[1][1], y)); |
| } |
| |
| twin_sfixed_t |
| _twin_matrix_len (twin_matrix_t *m, twin_fixed_t dx, twin_fixed_t dy) |
| { |
| twin_fixed_t xs = (twin_fixed_mul (m->m[0][0], dx) + |
| twin_fixed_mul (m->m[1][0], dy)); |
| twin_fixed_t ys = (twin_fixed_mul (m->m[0][1], dx) + |
| twin_fixed_mul (m->m[1][1], dy)); |
| twin_fixed_t ds = (twin_fixed_mul (xs, xs) + |
| twin_fixed_mul (ys, ys)); |
| return (twin_fixed_to_sfixed (twin_fixed_sqrt (ds))); |
| } |