blob: 20780ecfff41feffb1b19d46571ab1435a27fd47 [file] [log] [blame]
/*
* 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)));
}