Esempio n. 1
0
DiaObject *
create_standard_path_from_text (const Text *text)
{
  DiaObject *obj = NULL;
  GArray *points = g_array_new (FALSE, FALSE, sizeof(BezPoint));

  if (text_to_path (text, points))
    obj = create_standard_path (points->len, &g_array_index (points, BezPoint, 0));

  g_array_free (points, TRUE);

  if (obj) {
    StdPath *path = (StdPath *)obj;
    Rectangle text_box;
    const Rectangle *pbb = &path->object.bounding_box;
    real sx, sy;
    Point pos;

    path->stroke_or_fill = PDO_FILL;
    path->fill_color = text->color;

    /* scale to fit the original size */
    text_calc_boundingbox ((Text *)text, &text_box);
    pos.x = text_box.left; pos.y = text_box.top;
    sx = (text_box.right - text_box.left) / (pbb->right - pbb->left);
    sy = (text_box.bottom - text_box.top) / (pbb->bottom - pbb->top);
    _stdpath_scale (path, sx, sy);

    /* also adjust top left corner - calling update, too */
    stdpath_move (path, &pos);
  }

  return obj;
}
Esempio n. 2
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;
}
Esempio n. 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)
{
  const real EPSILON = 0.01;

  /* move_handle is supposed to be just moving that and related handles (e.g.
   * when N is moved NE and NW will move too). But 'opposite' handles are not
   * to be moved at all. So our transformation is invariant to the opposite
   * point of the path, not the object position.
   *
   * Another issue is limit checking. The path object must not get too small,
   * otherwise it can not be restored by reverse move_handle. So implement a
   * minimum distance between the moving and the opposite handle.
   */
  if (handle->id == HANDLE_RESIZE_NW) {
    Point p0 = stdpath->handles[7].pos; /* SE */
    Point p1 = stdpath->handles[0].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[0].id == handle->id);
    g_assert(stdpath->handles[7].id == HANDLE_RESIZE_SE);

    if (to->x + EPSILON > p0.x)
      sx = 1.0;
    if (to->y + EPSILON > p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, sx, sy, &p0);
  } else if (handle->id == HANDLE_RESIZE_N) {
    Point p0 = stdpath->handles[6].pos; /* S */
    Point p1 = stdpath->handles[1].pos;
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[1].id == handle->id);
    g_assert(stdpath->handles[6].id == HANDLE_RESIZE_S);

    if (to->y + EPSILON > p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, 1.0, sy, &p0);
  } else if (handle->id == HANDLE_RESIZE_NE) {
    Point p0 = stdpath->handles[5].pos; /* SW */
    Point p1 = stdpath->handles[2].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[2].id == handle->id);
    g_assert(stdpath->handles[5].id == HANDLE_RESIZE_SW);

    if (to->x - EPSILON < p0.x)
      sx = 1.0;
    if (to->y + EPSILON > p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, sx, sy, &p0);
  } else if (handle->id == HANDLE_RESIZE_W) {
    /* scale width */
    Point p0 = stdpath->handles[4].pos; /* E */
    Point p1 = stdpath->handles[3].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);

    g_assert(stdpath->handles[3].id == handle->id);
    g_assert(stdpath->handles[4].id == HANDLE_RESIZE_E);

    if (to->x + EPSILON > p0.x)
      sx = 1.0;
    _stdpath_scale (stdpath, sx, 1.0, &p0);
  } else if (handle->id == HANDLE_RESIZE_E) {
    /* scale width */
    Point p0 = stdpath->handles[3].pos; /* W */
    Point p1 = stdpath->handles[4].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);

    g_assert(stdpath->handles[4].id == handle->id);
    g_assert(stdpath->handles[3].id == HANDLE_RESIZE_W);

    if (to->x - EPSILON < p0.x)
      sx = 1.0;
    _stdpath_scale (stdpath, sx, 1.0, &p0);
  } else if (handle->id == HANDLE_RESIZE_SW) {
    Point p0 = stdpath->handles[2].pos; /* NE */
    Point p1 = stdpath->handles[5].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[5].id == handle->id);
    g_assert(stdpath->handles[2].id == HANDLE_RESIZE_NE);

    if (to->x + EPSILON > p0.x)
      sx = 1.0;
    if (to->y - EPSILON < p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, sx, sy, &p0);
  } else if (handle->id == HANDLE_RESIZE_S) {
    /* scale height */
    Point p0 = stdpath->handles[1].pos; /* N */
    Point p1 = stdpath->handles[6].pos;
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[6].id == handle->id);
    g_assert(stdpath->handles[1].id == HANDLE_RESIZE_N);

    if (to->y - EPSILON < p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, 1.0, sy, &p0);
  } else if (handle->id == HANDLE_RESIZE_SE) {
    /* scale both directions - keep aspect ratio? */
    Point p0 = stdpath->handles[0].pos; /* NW */
    Point p1 = stdpath->handles[7].pos;
    real sx = (to->x - p0.x) / (p1.x - p0.x);
    real sy = (to->y - p0.y) / (p1.y - p0.y);

    g_assert(stdpath->handles[7].id == handle->id);
    g_assert(stdpath->handles[0].id == HANDLE_RESIZE_NW);

    if (to->x - EPSILON < p0.x)
      sx = 1.0;
    if (to->y - EPSILON < p0.y)
      sy = 1.0;
    _stdpath_scale (stdpath, sx, sy, &p0);
  } else if (handle->type != HANDLE_NON_MOVABLE) {
    g_warning ("stdpath_move_handle() %d not moving", handle->id);
  }
  stdpath_update_data (stdpath);
  return NULL;
}