/** * Routines for simple 2D->2D transformations for rotated, flipped screens. * * XXX This code is not intel-specific. Move it into a common/utility * someday. */ #include "intel_rotate.h" #define MIN2(A, B) ( ((A) < (B)) ? (A) : (B) ) #define ABS(A) ( ((A) < 0) ? -(A) : (A) ) void matrix23Set(struct matrix23 *m, int m00, int m01, int m02, int m10, int m11, int m12) { m->m00 = m00; m->m01 = m01; m->m02 = m02; m->m10 = m10; m->m11 = m11; m->m12 = m12; } /* * Transform (x,y) coordinate by the given matrix. */ void matrix23TransformCoordf(const struct matrix23 *m, float *x, float *y) { const float x0 = *x; const float y0 = *y; *x = m->m00 * x0 + m->m01 * y0 + m->m02; *y = m->m10 * x0 + m->m11 * y0 + m->m12; } void matrix23TransformCoordi(const struct matrix23 *m, int *x, int *y) { const int x0 = *x; const int y0 = *y; *x = m->m00 * x0 + m->m01 * y0 + m->m02; *y = m->m10 * x0 + m->m11 * y0 + m->m12; } /* * Transform a width and height by the given matrix. * XXX this could be optimized quite a bit. */ void matrix23TransformDistance(const struct matrix23 *m, int *xDist, int *yDist) { int x0 = 0, y0 = 0; int x1 = *xDist, y1 = 0; int x2 = 0, y2 = *yDist; matrix23TransformCoordi(m, &x0, &y0); matrix23TransformCoordi(m, &x1, &y1); matrix23TransformCoordi(m, &x2, &y2); *xDist = (x1 - x0) + (x2 - x0); *yDist = (y1 - y0) + (y2 - y0); if (*xDist < 0) *xDist = -*xDist; if (*yDist < 0) *yDist = -*yDist; } /** * Transform the rect defined by (x, y, w, h) by m. */ void matrix23TransformRect(const struct matrix23 *m, int *x, int *y, int *w, int *h) { int x0 = *x, y0 = *y; int x1 = *x + *w, y1 = *y; int x2 = *x + *w, y2 = *y + *h; int x3 = *x, y3 = *y + *h; matrix23TransformCoordi(m, &x0, &y0); matrix23TransformCoordi(m, &x1, &y1); matrix23TransformCoordi(m, &x2, &y2); matrix23TransformCoordi(m, &x3, &y3); *w = ABS(x1 - x0) + ABS(x2 - x1); /**w = ABS(*w);*/ *h = ABS(y1 - y0) + ABS(y2 - y1); /**h = ABS(*h);*/ *x = MIN2(x0, x1); *x = MIN2(*x, x2); *y = MIN2(y0, y1); *y = MIN2(*y, y2); } /* * Make rotation matrix for width X height screen. */ void matrix23Rotate(struct matrix23 *m, int width, int height, int angle) { switch (angle) { case 0: matrix23Set(m, 1, 0, 0, 0, 1, 0); break; case 90: matrix23Set(m, 0, 1, 0, -1, 0, width); break; case 180: matrix23Set(m, -1, 0, width, 0, -1, height); break; case 270: matrix23Set(m, 0, -1, height, 1, 0, 0); break; default: /*abort()*/; } } /* * Make flip/reflection matrix for width X height screen. */ void matrix23Flip(struct matrix23 *m, int width, int height, int xflip, int yflip) { if (xflip) { m->m00 = -1; m->m01 = 0; m->m02 = width - 1; } else { m->m00 = 1; m->m01 = 0; m->m02 = 0; } if (yflip) { m->m10 = 0; m->m11 = -1; m->m12 = height - 1; } else { m->m10 = 0; m->m11 = 1; m->m12 = 0; } } /* * result = a * b */ void matrix23Multiply(struct matrix23 *result, const struct matrix23 *a, const struct matrix23 *b) { result->m00 = a->m00 * b->m00 + a->m01 * b->m10; result->m01 = a->m00 * b->m01 + a->m01 * b->m11; result->m02 = a->m00 * b->m02 + a->m01 * b->m12 + a->m02; result->m10 = a->m10 * b->m00 + a->m11 * b->m10; result->m11 = a->m10 * b->m01 + a->m11 * b->m11; result->m12 = a->m10 * b->m02 + a->m11 * b->m12 + a->m12; } #if 000 #include int main(int argc, char *argv[]) { int width = 500, height = 400; int rot; int fx = 0, fy = 0; /* flip x and/or y ? */ int coords[4][2]; /* four corner coords to test with */ coords[0][0] = 0; coords[0][1] = 0; coords[1][0] = width-1; coords[1][1] = 0; coords[2][0] = width-1; coords[2][1] = height-1; coords[3][0] = 0; coords[3][1] = height-1; for (rot = 0; rot < 360; rot += 90) { struct matrix23 rotate, flip, m; int i; printf("Rot %d, xFlip %d, yFlip %d:\n", rot, fx, fy); /* make transformation matrix 'm' */ matrix23Rotate(&rotate, width, height, rot); matrix23Flip(&flip, width, height, fx, fy); matrix23Multiply(&m, &rotate, &flip); /* xform four coords */ for (i = 0; i < 4; i++) { int x = coords[i][0]; int y = coords[i][1]; matrix23TransformCoordi(&m, &x, &y); printf(" %d, %d -> %d %d\n", coords[i][0], coords[i][1], x, y); } /* xform width, height */ { int x = width; int y = height; matrix23TransformDistance(&m, &x, &y); printf(" %d x %d -> %d x %d\n", width, height, x, y); } /* xform rect */ { int x = 50, y = 10, w = 200, h = 100; matrix23TransformRect(&m, &x, &y, &w, &h); printf(" %d,%d %d x %d -> %d, %d %d x %d\n", 50, 10, 200, 100, x, y, w, h); } } return 0; } #endif