static void _textobj_get_poly (const Textobj *textobj, Point poly[4]) { Point ul, lr; Point pt = textobj->text_handle.pos; Rectangle box; DiaMatrix m = { 1, 0, 0, 1, pt.x, pt.y }; DiaMatrix t = { 1, 0, 0, 1, -pt.x, -pt.y }; int i; dia_matrix_set_angle_and_scales (&m, G_PI * textobj->text_angle / 180.0, 1.0, 1.0); dia_matrix_multiply (&m, &t, &m); text_calc_boundingbox (textobj->text, &box); ul.x = box.left - textobj->margin; ul.y = box.top - textobj->margin; lr.x = box.right + textobj->margin; lr.y = box.bottom + textobj->margin; poly[0].x = ul.x; poly[0].y = ul.y; poly[1].x = lr.x; poly[1].y = ul.y; poly[2].x = lr.x; poly[2].y = lr.y; poly[3].x = ul.x; poly[3].y = lr.y; for (i = 0; i < 4; ++i) transform_point (&poly[i], &m); }
/*! * \brief Rotate path towards clicked point * * Rotate the given path around it's center with the angle given by * the top center handle and the clicked point. This function is * available with the context menu of the 'Standard - Path' object. * @return Undo information * * \relates _StdPath */ static ObjectChange * _path_rotate_callback (DiaObject *obj, Point *clicked, gpointer data) { StdPath *sp = (StdPath *)obj; real cx = (sp->object.bounding_box.left + sp->object.bounding_box.right) / 2; real cy = (sp->object.bounding_box.top + sp->object.bounding_box.bottom) / 2; DiaMatrix m = {1, 0, 0, 1, 0, 0 }; DiaMatrix translate = {1, 0, 0, 1, 0, 0 }; Point d; d.x = clicked->x - cx; d.y = clicked->y - cy; point_normalize (&d); /* to make the top, center handle clicked no rotation we subtract -PI/2 */ dia_matrix_set_angle_and_scales (&m, atan2 (d.y, d.x) + M_PI/2.0, 1.0, 1.0); /* rotate around center */ translate.x0 = cx; translate.y0 = cy; dia_matrix_multiply (&m, &m, &translate); translate.x0 = -cx; translate.y0 = -cy; dia_matrix_multiply (&m, &translate, &m); _path_transform (sp, &m); return _path_object_transform_change_create (obj, &m); }
/*! * \brief Move one of the objects handles * \memberof StdPath */ static ObjectChange* stdpath_move_handle (StdPath *stdpath, Handle *handle, Point *to, ConnectionPoint *cp, HandleMoveReason reason, ModifierKeys modifiers) { DiaObject *obj = &stdpath->object; Point p0 = obj->position; if (stdpath->move_reason != reason) { if (HANDLE_MOVE_USER == reason) g_print ("move-user"); else if (HANDLE_MOVE_USER_FINAL == reason) g_print ("move-user-final\n"); else if (HANDLE_MOVE_CONNECTED == reason) g_print ("move-connected\n"); else g_print ("move-?reason?\n"); stdpath->move_reason = reason; } else { g_print ("*"); } if (handle->id == HANDLE_RESIZE_SE) { /* scale both directions - keep aspect ratio? */ Point p1 = stdpath->handles[7].pos; real sx, sy; g_assert(stdpath->handles[7].id == handle->id); sx = (to->x - p0.x) / (p1.x - p0.x); sy = (to->y - p0.y) / (p1.y - p0.y); _stdpath_scale (stdpath, sx, sy); stdpath_update_data (stdpath); } else if (handle->id == HANDLE_RESIZE_S) { /* scale height */ Point p1 = stdpath->handles[6].pos; real sy; int i; g_assert(stdpath->handles[6].id == handle->id); sy = (to->y - p0.y) / (p1.y - p0.y); for (i = 0; i < stdpath->num_points; ++i) { BezPoint *bp = &stdpath->points[i]; bp->p1.y = p0.y + (bp->p1.y - p0.y) * sy; bp->p2.y = p0.y + (bp->p2.y - p0.y) * sy; bp->p3.y = p0.y + (bp->p3.y - p0.y) * sy; } stdpath_update_data (stdpath); } else if (handle->id == HANDLE_RESIZE_E) { /* scale width */ Point p1 = stdpath->handles[4].pos; real sx; int i; g_assert(stdpath->handles[4].id == handle->id); sx = (to->x - p0.x) / (p1.x - p0.x); for (i = 0; i < stdpath->num_points; ++i) { BezPoint *bp = &stdpath->points[i]; bp->p1.x = p0.x + (bp->p1.x - p0.x) * sx; bp->p2.x = p0.x + (bp->p2.x - p0.x) * sx; bp->p3.x = p0.x + (bp->p3.x - p0.x) * sx; } stdpath_update_data (stdpath); } else if (handle->id == _HANDLE_SHEAR) { /* apply horizontal shear weighted by the vertical distance */ Point p1 = stdpath->handles[2].pos; Point pr = stdpath->handles[5].pos; real dx; /* delta x */ real rd = (pr.y - p0.y); /* reference distance */ int i; gboolean revert = FALSE; g_assert(stdpath->handles[2].id == handle->id); g_assert(stdpath->handles[3].id == _HANDLE_REF_POS); g_return_val_if_fail(rd > 0, NULL); dx = to->x - p1.x; /* move_handle needs to be reversible, so do not move more than * the sheared bounding box allows */ do { for (i = 0; i < stdpath->num_points; ++i) { BezPoint *bp = &stdpath->points[i]; real sw; /* scaling weight [0..1] to not move the left boundary */ sw = (pr.y - bp->p1.y) / rd; bp->p1.x += dx * sw; sw = (pr.y - bp->p2.y) / rd; bp->p2.x += dx * sw; sw = (pr.y - bp->p3.y) / rd; bp->p3.x += dx * sw; } stdpath_update_data (stdpath); if (!revert && (fabs(stdpath->handles[2].pos.x - (p1.x + dx)) > 0.05)) { dx = -dx; revert = TRUE; } else { revert = FALSE; } } while (revert); } else if (handle->id == _HANDLE_ROTATE) { Point p1 = stdpath->handles[1].pos; Point pr = stdpath->handles[3].pos; Point pc = {stdpath->handles[1].pos.x, stdpath->handles[3].pos.y }; real dx = to->x - p1.x; real dy = pr.y - p1.y; DiaMatrix m; int i; g_assert(stdpath->handles[1].id == handle->id); if (fabs(dx) < 0.001) return NULL; dia_matrix_set_angle_and_scales (&m, -atan2 (dy, dx), 1.0, 1.0); for (i = 0; i < stdpath->num_points; ++i) { BezPoint *bp = &stdpath->points[i]; int j; for (j = 0; j < 3; ++j) { Point *p = j == 0 ? &bp->p1 : (j == 1 ? &bp->p2 : &bp->p3); real w, h; w = p->x - pc.x; h = p->y - pc.y; p->x = pc.x + w * m.xx + h * m.xy; p->y = pc.y + w * m.yx + h * m.yy; } } stdpath_update_data (stdpath); } else if (handle->id == _HANDLE_PERSPECTIVE) { Point p1 = stdpath->handles[5].pos; Point pr = stdpath->handles[3].pos; Point cp = { stdpath->handles[1].pos.x, pr.y }; real h2 = p1.y - pr.y; /* relative movement against center and original pos */ real td = (cp.x - to->x) / (cp.x - p1.x) - 1.0; int i; g_assert(stdpath->handles[5].id == handle->id); for (i = 0; i < stdpath->num_points; ++i) { BezPoint *bp = &stdpath->points[i]; Point *p; for (p = &bp->p1; p <= &bp->p3; ++p) { /* the vertical distance from the center point decides about the strength */ real vd = (p->y - cp.y) / h2; /* normalized */ /* the horizontal distance from center gets modified */ real hd = (p->x - cp.x); p->x += (hd * vd * td); } } stdpath_update_data (stdpath); } else if (handle->type != HANDLE_NON_MOVABLE) { g_warning ("stdpath_move_handle() %d not moving", handle->id); } return NULL; }