예제 #1
0
파일: standard-path.c 프로젝트: GNOME/dia
static void
_path_transform (StdPath *sp, const DiaMatrix *m)
{
  BezPoint *bezier = sp->points;
  gsize n = sp->num_points;
  guint i;

  for (i = 0; i < n; ++i)
    transform_bezpoint (&bezier[i], m);

  stdpath_update_data (sp);
}
예제 #2
0
파일: standard-path.c 프로젝트: GNOME/dia
/*!
 * \brief Change the object state regarding selection
 * \memberof _StdPath
 */
static gboolean
stdpath_transform(StdPath *stdpath, const DiaMatrix *m)
{
  int i;

  g_return_val_if_fail (m != NULL, FALSE);

  for (i = 0; i < stdpath->num_points; i++)
    transform_bezpoint (&stdpath->points[i], m);

  stdpath_update_data(stdpath);
  return TRUE;
}
예제 #3
0
파일: standard-path.c 프로젝트: UIKit0/dia
/*!
 * \brief Move the whole object to the given position
 * 
 * If the object position does not change the whole object should not either.
 * This is used as a kludge to call the protected update_data() function
 *
 * \memberof StdPath
 */
static ObjectChange* 
stdpath_move (StdPath *stdpath, Point *to)
{
  DiaObject *obj = &stdpath->object;
  Point delta = *to;
  int i;

  point_sub (&delta, &obj->position);
  
  for (i = 0; i < stdpath->num_points; ++i) {
     BezPoint *bp = &stdpath->points[i];

     point_add (&bp->p1, &delta);
     point_add (&bp->p2, &delta);
     point_add (&bp->p3, &delta);
  }
  stdpath_update_data (stdpath);
  return NULL;
}
예제 #4
0
파일: standard-path.c 프로젝트: UIKit0/dia
/*!
 * \brief Set the object state from the given proeprty vector
 * \memberof StdPath
 */
static void 
stdpath_set_props (StdPath *stdpath, GPtrArray *props)
{
  Property *prop;
  stdpath->show_background = (stdpath->stroke_or_fill & PDO_FILL) != 0;
  object_set_props_from_offsets(&stdpath->object, stdpath_offsets, props);
  /* Usually the list wont contain "show_background", but if it
   * it set let it take precedence
   */
  if (   (prop = find_prop_by_name (props, "show_background")) != NULL
      && (prop->experience & PXP_NOTSET) == 0) {
    if (stdpath->show_background)
      stdpath->stroke_or_fill |= PDO_FILL;
    else
      stdpath->stroke_or_fill &= ~PDO_FILL;
  }
  /* now when transfering properties from text we'll loose stroke and fill
   * Instead of drawing nothing maket it just fill.
   */
  if (!stdpath->stroke_or_fill)
    stdpath->stroke_or_fill = PDO_FILL;

  stdpath_update_data (stdpath);
}
예제 #5
0
파일: standard-path.c 프로젝트: UIKit0/dia
/*!
 * \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;
}
예제 #6
0
파일: standard-path.c 프로젝트: UIKit0/dia
/*! Factory function - create default object */
static DiaObject *
stdpath_create (Point *startpoint,
		void *user_data,
		Handle **handle1,
		Handle **handle2)
{
  StdPath *stdpath;
  DiaObject *obj;
  Point sp = {0, 0};
  
  stdpath = g_new0 (StdPath,1);
  obj = &stdpath->object;
  obj->type = &stdpath_type;
  obj->ops = &stdpath_ops;

  object_init (obj, NUM_HANDLES, 0);
  stdpath_init_handles (stdpath);
  if (startpoint)
    sp = *startpoint;

  if (user_data == NULL) {
    /* just to have something to play with 
       <bezpoint type="moveto" p1="0,1"/>
       <bezpoint type="curveto" p1="0,0" p2="2,2" p3="2,1"/>
       <bezpoint type="curveto" p1="2,0" p2="0,2" p3="0,1"/>
     */
    BezPoint *bp;
    stdpath->num_points = 3;
    bp = stdpath->points = g_new (BezPoint, 3);
    bp[0].type = BEZ_MOVE_TO;
    bp[0].p1.x = sp.x + 0; bp[0].p1.y = sp.y + 1;
    bp[0].p3 = bp[0].p2 = bp[0].p1; /* not strictly necessary */
    bp[1].type = BEZ_CURVE_TO;
    bp[1].p1 = sp;
    bp[1].p2.x = sp.x + 2; bp[1].p2.y = sp.y + 2;
    bp[1].p3.x = sp.x + 2; bp[1].p3.y = sp.y + 1;
    bp[2].type = BEZ_CURVE_TO;
    bp[2].p1.x = sp.x + 2; bp[2].p1.y = sp.y + 0;
    bp[2].p2.x = sp.x + 0; bp[2].p2.y = sp.y + 2;
    bp[2].p3.x = sp.x + 0; bp[2].p3.y = sp.y + 1;
  } else {
    BezierCreateData *bcd = (BezierCreateData*)user_data;

    if (bcd->num_points < 2) {
      g_warning ("'Standard - Path' needs at least two points");
      /* this is a stress test - object might not be setup completely */
      object_destroy (obj);
      g_free (stdpath);
      return NULL;
    }
    stdpath->num_points = bcd->num_points;
    stdpath->points = g_memdup(bcd->points, bcd->num_points * sizeof(BezPoint));
  }

  stdpath->stroke_or_fill = PDO_STROKE; /* default: stroke only */
  stdpath->line_width = attributes_get_default_linewidth();
  stdpath->line_color = attributes_get_foreground();
  stdpath->fill_color = attributes_get_background();

  *handle1 = stdpath->object.handles[0];
  *handle2 = stdpath->object.handles[7];

  stdpath_update_data (stdpath);

  return obj;
}
예제 #7
0
파일: standard-path.c 프로젝트: GNOME/dia
/*!
 * \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;
}