示例#1
0
文件: textobj.c 项目: GNOME/dia
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);
}
示例#2
0
文件: standard-path.c 项目: GNOME/dia
/*!
 * \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);
}
示例#3
0
/*!
 * \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;
}