返回目录
基本理论参见:【计算机图形学】3-1 二维几何变换基本理论
注:这里不考虑插值的问题。
全部的代码都在https://github.com/CyberZHG/ZPIC 上,欢迎各位前来围观和提出意见。
效果截图:
移动:
缩放:
旋转:
错切 :
改变旋转中心后的旋转:
transform_matrix.h
#ifndef TRANSFORM_MATRIX_H_INCLUDED #define TRANSFORM_MATRIX_H_INCLUDED #include <math.h> #include "define.h" typedef struct Transform_Matrix_9d { double m[3][3]; }Transform_Matrix_9d; void transform_matrix_init(Transform_Matrix_9d *matrix); void transform_matrix_clear(Transform_Matrix_9d *matrix); void transform_matrix_add(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2); void transform_matrix_substract(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2); void transform_matrix_multiply(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2); void transform_matrix_copy(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2); void transform_matrix_transformPoint(const Transform_Matrix_9d matrix, int32 *x, int32 *y); void transform_matrix_move(Transform_Matrix_9d *matrix, double tx, double ty); void transform_matrix_scale(Transform_Matrix_9d *matrix, double sx, double sy); void transform_matrix_rotate(Transform_Matrix_9d *matrix, double angle); void transform_matrix_shear(Transform_Matrix_9d *matrix, double b, double d); #endif // TRANSFORM_MATRIX_H_INCLUDED
transform_matrix.c
#include "transform_matrix.h" void transform_matrix_init(Transform_Matrix_9d *matrix) { int32 i, j; for(i=0;i<3;++i) { for(j=0;j<3;++j) { matrix->m[i][j] = 0.0; } matrix->m[i][i] = 1.0; } } void transform_matrix_clear(Transform_Matrix_9d *matrix) { int32 i, j; for(i=0;i<3;++i) { for(j=0;j<3;++j) { matrix->m[i][j] = 0.0; } } } void transform_matrix_add(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2) { int32 i, j; for(i=0;i<3;++i) { for(j=0;j<3;++j) { m1->m[i][j] += m2.m[i][j]; } } } void transform_matrix_substract(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2) { int32 i, j; for(i=0;i<3;++i) { for(j=0;j<3;++j) { m1->m[i][j] -= m2.m[i][j]; } } } void transform_matrix_multiply(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2) { int32 i, j, k; Transform_Matrix_9d temp; transform_matrix_clear(&temp); for(i=0;i<3;++i) { for(j=0;j<3;++j) { for(k=0;k<3;++k) { temp.m[i][j] += m1->m[i][k] * m2.m[k][j]; } } } for(i=0;i<3;++i) { for(j=0;j<3;++j) { m1->m[i][j] = temp.m[i][j]; } } } void transform_matrix_copy(Transform_Matrix_9d *m1, const Transform_Matrix_9d m2) { int32 i, j; for(i=0;i<3;++i) { for(j=0;j<3;++j) { m1->m[i][j] = m2.m[i][j]; } } } void transform_matrix_transformPoint(const Transform_Matrix_9d matrix, int32 *x, int32 *y) { int32 tx, ty; tx = (int)(*x * matrix.m[0][0] + *y * matrix.m[1][0] + matrix.m[2][0]); ty = (int)(*x * matrix.m[0][1] + *y * matrix.m[1][1] + matrix.m[2][1]); *x = tx; *y = ty; } void transform_matrix_move(Transform_Matrix_9d *matrix, double tx, double ty) { Transform_Matrix_9d moveMatrix; transform_matrix_init(&moveMatrix); moveMatrix.m[2][0] = tx; moveMatrix.m[2][1] = ty; transform_matrix_multiply(matrix, moveMatrix); } void transform_matrix_scale(Transform_Matrix_9d *matrix, double sx, double sy) { Transform_Matrix_9d scaleMatrix; transform_matrix_init(&scaleMatrix); scaleMatrix.m[0][0] = sx; scaleMatrix.m[1][1] = sy; transform_matrix_multiply(matrix, scaleMatrix); } void transform_matrix_rotate(Transform_Matrix_9d *matrix, double angle) { Transform_Matrix_9d rotateMatrix; transform_matrix_init(&rotateMatrix); rotateMatrix.m[0][0] = rotateMatrix.m[1][1] = cos(angle); rotateMatrix.m[1][0] = - (rotateMatrix.m[0][1] = sin(angle)); transform_matrix_multiply(matrix, rotateMatrix); } void transform_matrix_shear(Transform_Matrix_9d *matrix, double b, double d) { Transform_Matrix_9d shearMatrix; transform_matrix_init(&shearMatrix); shearMatrix.m[0][1] = b; shearMatrix.m[1][0] = d; transform_matrix_multiply(matrix, shearMatrix); }
transform_selection.h
#ifndef TRANSFORM_SELECTION_H_INCLUDED #define TRANSFORM_SELECTION_H_INCLUDED #include <stdlib.h> #include <math.h> #include "define.h" #include "gui.h" #include "draw.h" #include "transform_matrix.h" typedef struct Transform_Selection_10i2f1m { int32 x[4], y[4]; float cx, cy; draw_color **color; int32 **px; int32 **py; Transform_Matrix_9d transMatrix; }Transform_Selection_10i2f1m; void transform_selection_display(void); void transform_selection_mouseEvent(int32 state, int32 x, int32 y); void transform_selection_keyboardEvent(int32 key, int32 state); #endif // TRANSFORM_SELECTION_H_INCLUDED
transform_selection.c
#include "transform_selection.h" static Transform_Selection_10i2f1m transform_default_selection; int32 isMovingCenter; int32 isSelecting; int32 isSelected; int32 isMoving; int32 isResizing; int32 isRotating; int32 isShearing; int32 isMouseDown; int32 isFinshed; int32 startX, startY; int32 endX, endY; int32 lastEdgeX, lastEdgeY; Transform_Matrix_9d startMatrix; int32 isShiftDown; void transform_selection_display(void) { int32 i, j, w, h; int32 x[4], y[4], mx, my; float cx, cy; int32 edgeL, edgeR, edgeB, edgeT; draw_color **color; int32 **px, **py; int32 tx, ty; Transform_Matrix_9d *matrix = &transform_default_selection.transMatrix; draw_color penColor = draw_pen_getColor(); draw_color brushColor = draw_brush_getColor(); draw_pen_setColor(DRAW_COLOR_WHITE); draw_brush_setColor(DRAW_COLOR_BLACK); for(i=0;i<4;++i) { x[i] = transform_default_selection.x[i]; y[i] = transform_default_selection.y[i]; transform_matrix_transformPoint(*matrix, &x[i], &y[i]); } edgeL = min(min(x[0], x[1]), min(x[2], x[3])); edgeR = max(max(x[0], x[1]), max(x[2], x[3])); edgeB = min(min(y[0], y[1]), min(y[2], y[3])); edgeT = max(max(y[0], y[1]), max(y[2], y[3])); mx = (edgeL + edgeR) >> 1; my = (edgeB + edgeT) >> 1; cx = transform_default_selection.cx; cy = transform_default_selection.cy; w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1; h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1; color = transform_default_selection.color; px = transform_default_selection.px; py = transform_default_selection.py; if(isSelecting) { if(isSelected) { for(i=0;i<h;++i) { for(j=0;j<w;++j) { gui_setPixel_2i1u(px[i][j], py[i][j], DRAW_COLOR_BLACK); } } for(i=0;i<h;++i) { for(j=0;j<w;++j) { tx = px[i][j], ty = py[i][j]; transform_matrix_transformPoint(*matrix, &tx, &ty); gui_setPixel_2i1u(tx, ty, color[i][j]); } } if(isFinshed) { gui_saveCurrentImage(); isSelecting = 0; isSelected = 0; isMoving = 0; isResizing = 0; isRotating = 0; isShearing = 0; isFinshed = 0; isMouseDown = 0; w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1; h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1; for(i=0;i<h;++i) { free(transform_default_selection.color[i]); free(transform_default_selection.px[i]); free(transform_default_selection.py[i]); } free(transform_default_selection.color); free(transform_default_selection.px); free(transform_default_selection.py); } else { draw_line_4i(edgeL, edgeT, edgeR, edgeT); draw_line_4i(edgeL, edgeB, edgeR, edgeB); draw_line_4i(edgeL, edgeT, edgeL, edgeB); draw_line_4i(edgeR, edgeT, edgeR, edgeB); draw_dotted_line_4i(x[0], y[0], x[1], y[1]); draw_dotted_line_4i(x[1], y[1], x[2], y[2]); draw_dotted_line_4i(x[2], y[2], x[3], y[3]); draw_dotted_line_4i(x[3], y[3], x[0], y[0]); draw_rectangle_4i(edgeL - 3, edgeT - 3, edgeL + 3, edgeT + 3); draw_rectangle_4i(edgeL - 3, edgeB - 3, edgeL + 3, edgeB + 3); draw_rectangle_4i(edgeR - 3, edgeT - 3, edgeR + 3, edgeT + 3); draw_rectangle_4i(edgeR - 3, edgeB - 3, edgeR + 3, edgeB + 3); draw_rectangle_4i(edgeL - 3, my - 3, edgeL + 3, my + 3); draw_rectangle_4i(mx - 3, edgeB - 3, mx + 3, edgeB + 3); draw_rectangle_4i(edgeR - 3, my - 3, edgeR + 3, my + 3); draw_rectangle_4i(mx - 3, edgeT - 3, mx + 3, edgeT + 3); draw_circle_3i(cx, cy, 3); if(isMoving) { gui_setMainWindowCursor(CURSOR_SIZEALL); } else if(isResizing) { switch(isResizing) { case POSITION_LEFT: gui_setMainWindowCursor(CURSOR_SIZEWE); break; case POSITION_RIGHT: gui_setMainWindowCursor(CURSOR_SIZEWE); break; case POSITION_TOP: gui_setMainWindowCursor(CURSOR_SIZENS); break; case POSITION_BOTTOM: gui_setMainWindowCursor(CURSOR_SIZENS); break; case POSITION_TOPLEFT: gui_setMainWindowCursor(CURSOR_SIZENESW); break; case POSITION_TOPRIGHT: gui_setMainWindowCursor(CURSOR_SIZENWSE); break; case POSITION_BOTTOMLEFT: gui_setMainWindowCursor(CURSOR_SIZENWSE); break; case POSITION_BOTTOMRIGHT: gui_setMainWindowCursor(CURSOR_SIZENESW); break; } } else if(isRotating) { gui_setMainWindowCursor(CURSOR_NO); } else if(isShearing) { switch(isShearing) { case POSITION_BOTTOM: case POSITION_TOP: gui_setMainWindowCursor(CURSOR_SIZEWE); break; case POSITION_LEFT: case POSITION_RIGHT: gui_setMainWindowCursor(CURSOR_SIZENS); break; } } } } else { gui_setMainWindowCursor(CURSOR_CROSS); draw_dotted_line_4i(x[0], y[0], x[2], y[0]); draw_dotted_line_4i(x[0], y[2], x[2], y[2]); draw_dotted_line_4i(x[0], y[0], x[0], y[2]); draw_dotted_line_4i(x[2], y[0], x[2], y[2]); } } else { gui_setMainWindowCursor(CURSOR_CROSS); } draw_pen_setColor(penColor); draw_brush_setColor(brushColor); } void transform_selection_mouseEvent(int32 state, int32 x, int32 y) { int32 i, j, w, h; int32 rx[4], ry[4], mx, my, cx, cy; int32 edgeL, edgeR, edgeB, edgeT; double angle; Transform_Matrix_9d *matrix = &transform_default_selection.transMatrix; for(i=0;i<4;++i) { rx[i] = transform_default_selection.x[i]; ry[i] = transform_default_selection.y[i]; transform_matrix_transformPoint(*matrix, &rx[i], &ry[i]); } edgeL = min(min(rx[0], rx[1]), min(rx[2], rx[3])); edgeR = max(max(rx[0], rx[1]), max(rx[2], rx[3])); edgeB = min(min(ry[0], ry[1]), min(ry[2], ry[3])); edgeT = max(max(ry[0], ry[1]), max(ry[2], ry[3])); mx = (edgeL + edgeR) >> 1; my = (edgeB + edgeT) >> 1; cx = transform_default_selection.cx; cy = transform_default_selection.cy; switch(state) { case MOUSE_DOWN_LEFT: isMouseDown = 1; if(isSelected) { startX = x; startY = y; endX = x; endY = y; transform_matrix_copy(&startMatrix, *matrix); if(isResizing) { switch(isResizing) { case POSITION_LEFT: lastEdgeX = edgeR; break; case POSITION_RIGHT: lastEdgeX = edgeL; break; case POSITION_BOTTOM: lastEdgeY = edgeT; break; case POSITION_TOP: lastEdgeY = edgeB; break; case POSITION_BOTTOMLEFT: lastEdgeX = edgeR; lastEdgeY = edgeT; break; case POSITION_BOTTOMRIGHT: lastEdgeX = edgeL; lastEdgeY = edgeT; break; case POSITION_TOPLEFT: lastEdgeX = edgeR; lastEdgeY = edgeB; break; case POSITION_TOPRIGHT: lastEdgeX = edgeL; lastEdgeY = edgeB; break; } } else if(isShearing) { switch(isShearing) { case POSITION_BOTTOM: case POSITION_RIGHT: lastEdgeX = edgeL; lastEdgeY = edgeT; break; case POSITION_TOP: case POSITION_LEFT: lastEdgeX = edgeR; lastEdgeY = edgeB; break; } } } else { isSelecting = 1; transform_default_selection.x[0] = x; transform_default_selection.y[0] = y; transform_default_selection.x[2] = x; transform_default_selection.y[2] = y; transform_matrix_init(&transform_default_selection.transMatrix); } break; case MOUSE_UP_LEFT: isMouseDown = 0; if(isSelecting) { if(isSelected) { if(isMovingCenter || isMoving || isResizing || isRotating || isShearing) { return; } if(x < edgeL - 10 || x > edgeR + 10 || y < edgeB - 10 || y > edgeT + 10) { isFinshed = 1; } } else { transform_default_selection.x[1] = x; transform_default_selection.y[1] = ry[0]; transform_default_selection.x[3] = rx[0]; transform_default_selection.y[3] = y; transform_default_selection.x[2] = x; transform_default_selection.y[2] = y; transform_default_selection.cx = (transform_default_selection.x[0] + transform_default_selection.x[2]) >> 1; transform_default_selection.cy = (transform_default_selection.y[0] + transform_default_selection.y[2]) >> 1; isSelected = 1; w = abs(transform_default_selection.x[0] - transform_default_selection.x[2]) - 1; h = abs(transform_default_selection.y[0] - transform_default_selection.y[2]) - 1; transform_default_selection.color = (draw_color**)malloc(sizeof(draw_color*) * h); transform_default_selection.px = (int32**)malloc(sizeof(int32*) * h); transform_default_selection.py = (int32**)malloc(sizeof(int32*) * h); for(i=0;i<h;++i) { transform_default_selection.color[i] = (draw_color*)malloc(sizeof(draw_color) * w); transform_default_selection.px[i] = (int32*)malloc(sizeof(int32) * w); transform_default_selection.py[i] = (int32*)malloc(sizeof(int32) * w); for(j=0;j<w;++j) { transform_default_selection.color[i][j] = gui_getPixel(min(transform_default_selection.x[0], transform_default_selection.x[2]) + j + 1, min(transform_default_selection.y[0], transform_default_selection.y[2]) + i + 1); transform_default_selection.px[i][j] = min(transform_default_selection.x[0], transform_default_selection.x[2]) + j + 1; transform_default_selection.py[i][j] = min(transform_default_selection.y[0], transform_default_selection.y[2]) + i + 1; } } } } break; case MOUSE_MOVE: if(isSelecting) { if(isSelected) { if(isMouseDown) { if(isMovingCenter) { transform_default_selection.cx += x - endX; transform_default_selection.cy += y - endY; endX = x; endY = y; } else if(isMoving) { transform_matrix_move(matrix, x - startX, y - startY); transform_default_selection.cx += x - startX; transform_default_selection.cy += y - startY; startX = x; startY = y; } else if(isResizing) { transform_matrix_copy(matrix, startMatrix); switch(isResizing) { case POSITION_LEFT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, 0); if(x > lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } transform_matrix_move(matrix, lastEdgeX, 0); } transform_default_selection.cx += (x - endX) * 0.5; endX = x; break; case POSITION_RIGHT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, 0); if(x < lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } transform_matrix_move(matrix, lastEdgeX, 0); } transform_default_selection.cx += (x - endX) * 0.5; endX = x; break; case POSITION_BOTTOM: if(startY != lastEdgeY && endY != lastEdgeY) { transform_matrix_move(matrix, 0, - lastEdgeY); if(y > lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, 0, lastEdgeY); } transform_default_selection.cy += (y - endY) * 0.5; endY = y; break; case POSITION_TOP: if(startY != lastEdgeY && endY != lastEdgeY) { transform_matrix_move(matrix, 0, - lastEdgeY); if(y < lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, 0, lastEdgeY); } transform_default_selection.cy += (y - endY) * 0.5; endY = y; break; case POSITION_BOTTOMLEFT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY); if(x > lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } if(y > lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); } transform_default_selection.cx += (x - endX) * 0.5; transform_default_selection.cy += (y - endY) * 0.5; endX = x; endY = y; break; case POSITION_BOTTOMRIGHT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY); if(x < lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } if(y > lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); } transform_default_selection.cx += (x - endX) * 0.5; transform_default_selection.cy += (y - endY) * 0.5; endX = x; endY = y; break; case POSITION_TOPLEFT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY); if(x > lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } if(y < lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); } transform_default_selection.cx += (x - endX) * 0.5; transform_default_selection.cy += (y - endY) * 0.5; endX = x; endY = y; break; case POSITION_TOPRIGHT: if(startX != lastEdgeX && endX != lastEdgeX) { transform_matrix_move(matrix, - lastEdgeX, -lastEdgeY); if(x < lastEdgeX) { transform_matrix_scale(matrix, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } else { transform_matrix_scale(matrix, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX), 1.0); } if(y < lastEdgeY) { transform_matrix_scale(matrix, 1.0, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } else { transform_matrix_scale(matrix, 1.0, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY)); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); } transform_default_selection.cx += (x - endX) * 0.5; transform_default_selection.cy += (y - endY) * 0.5; endX = x; endY = y; break; } } else if(isRotating) { transform_matrix_copy(matrix, startMatrix); angle = atan2(y - cx, x - cy) - atan2(startY - cy, startX - cx); transform_matrix_move(matrix, -cx, -cy); transform_matrix_rotate(matrix, angle); transform_matrix_move(matrix, cx, cy); } else if(isShearing) { switch(isShearing) { case POSITION_BOTTOM: transform_matrix_copy(matrix, startMatrix); transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY); if(x > lastEdgeX) { transform_matrix_shear(matrix, 0.0, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0); } else { transform_matrix_shear(matrix, 0.0, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); transform_default_selection.cx += x - endX; endX = x; break; case POSITION_RIGHT: transform_matrix_copy(matrix, startMatrix); transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY); if(y < lastEdgeY) { transform_matrix_shear(matrix, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0); } else { transform_matrix_shear(matrix, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); transform_default_selection.cy += y - endY; endY = y; break; case POSITION_TOP: transform_matrix_copy(matrix, startMatrix); transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY); if(x < lastEdgeX) { transform_matrix_shear(matrix, 0.0, - 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0); } else { transform_matrix_shear(matrix, 0.0, 1.0 * abs(x - lastEdgeX) / abs(startX - lastEdgeX) + 1.0); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); transform_default_selection.cx += x - endX; endX = x; break; case POSITION_LEFT: transform_matrix_copy(matrix, startMatrix); transform_matrix_move(matrix, -lastEdgeX, -lastEdgeY); if(y > lastEdgeY) { transform_matrix_shear(matrix, - 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0); } else { transform_matrix_shear(matrix, 1.0 * abs(y - lastEdgeY) / abs(startY - lastEdgeY) + 1.0, 0.0); } transform_matrix_move(matrix, lastEdgeX, lastEdgeY); transform_default_selection.cy += y - endY; endY = y; break; } } } else { if(abs(x - cx) <= 4 && abs(y - cy) <= 4) { isMovingCenter = 1; isMoving = 0; isResizing = 0; isRotating = 0; isShearing = 0; return; } if(abs(x - edgeL) <= 4 && abs(y - my) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_LEFT; return; } if(abs(x - edgeR) <= 4 && abs(y - my) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_RIGHT; return; } if(abs(x - mx) <= 4 && abs(y - edgeB) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_BOTTOM; return; } if(abs(x - mx) <= 4 && abs(y - edgeT) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_TOP; return; } if(abs(x - edgeL) <= 4 && abs(y - edgeT) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_TOPLEFT; return; } if(abs(x - edgeL) <= 4 && abs(y - edgeB) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_BOTTOMLEFT; return; } if(abs(x - edgeR) <= 4 && abs(y - edgeT) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_TOPRIGHT; return; } if(abs(x - edgeR) <= 4 && abs(y - edgeB) <= 4) { isMovingCenter = 0; isMoving = 0; isRotating = 0; isShearing = 0; isResizing = POSITION_BOTTOMRIGHT; return; } if(x > edgeL + 4 && x < edgeR - 4 && y > edgeB + 4 && y < edgeT - 4) { isMovingCenter = 0; isResizing = 0; isRotating = 0; isShearing = 0; isMoving = 1; return; } if((x > edgeR + 4 && x <= edgeR + 8 && y < edgeB - 4 && y >= edgeB - 8)) { isMovingCenter = 0; isResizing = 0; isRotating = 1; isShearing = 0; isMoving = 0; return; } if(x >= edgeR - 4 && x < edgeR && y < edgeB - 4 && y >= edgeB - 8) { isMovingCenter = 0; isResizing = 0; isRotating = 0; isShearing = POSITION_BOTTOM; isMoving = 0; return; } if(x > edgeR + 4 && x <= edgeR + 8 && y <= edgeB + 4 && y > edgeB) { isMovingCenter = 0; isResizing = 0; isRotating = 0; isShearing = POSITION_RIGHT; isMoving = 0; return; } if(x > edgeL && x <= edgeL + 4 && y > edgeT + 4 && y <= edgeT + 8) { isMovingCenter = 0; isResizing = 0; isRotating = 0; isShearing = POSITION_TOP; isMoving = 0; return; } if(x > edgeL - 8 && x <= edgeL - 4 && y >= edgeT - 4 && y < edgeT) { isMovingCenter = 0; isResizing = 0; isRotating = 0; isShearing = POSITION_LEFT; isMoving = 0; return; } isMovingCenter = 0; isMoving = 0; isResizing = 0; isRotating = 0; isShearing = 0; } } else { transform_default_selection.x[2] = x; transform_default_selection.y[2] = y; } } break; case MOUSE_DOWN_RIGHT: if(isSelecting) { isSelecting = 0; } break; } } void transform_selection_keyboardEvent(int32 key, int32 state) { switch(state) { case KEY_STATE_DOWN: switch(key) { case KEY_VALUE_SHIFT: isShiftDown = 1; } break; case KEY_STATE_UP: switch(key) { case KEY_VALUE_SHIFT: isShiftDown = 0; } break; } }