Exemplo n.º 1
0
ObjectChange *
beziershape_move_handle(BezierShape *bezier, Handle *handle,
			Point *to, ConnectionPoint *cp,
			HandleMoveReason reason, ModifierKeys modifiers)
{
  int handle_nr, comp_nr, next_nr, prev_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  next_nr = comp_nr + 1;
  prev_nr = comp_nr - 1;
  if (comp_nr == bezier->numpoints - 1)
    next_nr = 1;
  if (comp_nr == 1)
    prev_nr = bezier->numpoints - 1;
  
  switch(handle->id) {
  case HANDLE_BEZMAJOR:
    if (comp_nr == bezier->numpoints - 1) {
      bezier->points[comp_nr].p3 = *to;
      bezier->points[0].p1 = bezier->points[0].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[1].p1, &delta);
    } else {
      bezier->points[comp_nr].p3 = *to;
      point_add(&bezier->points[comp_nr].p2, &delta);
      point_add(&bezier->points[comp_nr+1].p1, &delta);
    }
    break;
  case HANDLE_LEFTCTRL:
    bezier->points[comp_nr].p2 = *to;
    switch (bezier->corner_types[comp_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[next_nr].p1;
      point_sub(&pt, &bezier->points[comp_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[comp_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p2);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[comp_nr].p3);
      bezier->points[next_nr].p1 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->points[comp_nr].p1 = *to;
    switch (bezier->corner_types[prev_nr]) {
    case BEZ_CORNER_SYMMETRIC:
      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    case BEZ_CORNER_SMOOTH: {
      real len;

      pt = bezier->points[prev_nr].p2;
      point_sub(&pt, &bezier->points[prev_nr].p3);
      len = point_len(&pt);

      pt = bezier->points[prev_nr].p3;
      point_sub(&pt, &bezier->points[comp_nr].p1);
      if (point_len(&pt) > 0)
	point_normalize(&pt);
      else {
	pt.x = 1.0; pt.y = 0.0;
      }
      point_scale(&pt, len);
      point_add(&pt, &bezier->points[prev_nr].p3);
      bezier->points[prev_nr].p2 = pt;
      break;
    }
    case BEZ_CORNER_CUSP:
      /* no mirror point movement required */
      break;
    }
    break;
  default:
    message_error("Internal error in beziershape_move_handle.");
    break;
  }
  return NULL;
}
Exemplo n.º 2
0
/*!
 * \brief Move one of the handles associated with the
 * @param bezier The object whose handle is being moved.
 * @param handle The handle being moved.
 * @param to The position it has been moved to (corrected for
 *   vertical/horizontal only movement).
 * @param cp If non-NULL, the connectionpoint found at this position.
 *   If @a cp is NULL, there may or may not be a connectionpoint.
 * @param reason ignored
 * @param modifiers ignored
 * @return NULL
 * \memberof BezierConn
 */
ObjectChange*
bezierconn_move_handle (BezierConn *bezier,
			Handle *handle,
			Point *to,
			ConnectionPoint *cp,
			HandleMoveReason reason,
			ModifierKeys modifiers)
{
  int handle_nr, comp_nr;
  Point delta, pt;
  
  delta = *to;
  point_sub(&delta, &handle->pos);

  handle_nr = get_handle_nr(bezier, handle);
  comp_nr = get_comp_nr(handle_nr);
  switch(handle->id) {
  case HANDLE_MOVE_STARTPOINT:
    bezier->bezier.points[0].p1 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[1].p1, &delta);
    break;
  case HANDLE_MOVE_ENDPOINT:
    bezier->bezier.points[bezier->bezier.num_points-1].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[bezier->bezier.num_points-1].p2, &delta);
    break;
  case HANDLE_BEZMAJOR:
    bezier->bezier.points[comp_nr].p3 = *to;
    /* shift adjacent point */
    point_add(&bezier->bezier.points[comp_nr].p2, &delta);
    point_add(&bezier->bezier.points[comp_nr+1].p1, &delta);
    break;
  case HANDLE_LEFTCTRL:
    bezier->bezier.points[comp_nr].p2 = *to;
    if (comp_nr < bezier->bezier.num_points - 1) {
      switch (bezier->bezier.corner_types[comp_nr]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p2);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr+1].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr].p3);
	bezier->bezier.points[comp_nr+1].p1 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  case HANDLE_RIGHTCTRL:
    bezier->bezier.points[comp_nr].p1 = *to;
    if (comp_nr > 1) {
      switch (bezier->bezier.corner_types[comp_nr-1]) {
      case BEZ_CORNER_SYMMETRIC:
	pt = bezier->bezier.points[comp_nr - 1].p3;
	point_sub(&pt, &bezier->bezier.points[comp_nr].p1);
	point_add(&pt, &bezier->bezier.points[comp_nr - 1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      case BEZ_CORNER_SMOOTH: {
	real len;
	pt = bezier->bezier.points[comp_nr-1].p2;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	len = point_len(&pt);
	pt = bezier->bezier.points[comp_nr].p1;
	point_sub(&pt, &bezier->bezier.points[comp_nr-1].p3);
	if (point_len(&pt) > 0)
	  point_normalize(&pt);
	else { pt.x = 1.0; pt.y = 0.0; }
	point_scale(&pt, -len);
	point_add(&pt, &bezier->bezier.points[comp_nr-1].p3);
	bezier->bezier.points[comp_nr-1].p2 = pt;
	break;
      }	
      case BEZ_CORNER_CUSP:
	/* Do nothing to the other guy */
	break;
      }
    }
    break;
  default:
    g_warning("Internal error in bezierconn_move_handle.\n");
    break;
  }
  return NULL;
}