Beispiel #1
0
/*!
 * \brief Calculate the distance of the whole object to the given point
 * \memberof StdPath
 */
static real
stdpath_distance_from (StdPath *stdpath, Point *point)
{
  real lw = stdpath->stroke_or_fill & PDO_STROKE ? stdpath->line_width : 0.0;

  if (stdpath->stroke_or_fill & PDO_FILL)
    return distance_bez_shape_point (stdpath->points, stdpath->num_points, lw, point);
  else
    return distance_bez_line_point  (stdpath->points, stdpath->num_points, lw, point);
}
Beispiel #2
0
real
beziershape_distance_from(BezierShape *bezier, Point *point, real line_width)
{
  return distance_bez_shape_point(bezier->points, bezier->numpoints,
				  line_width, point);
}
Beispiel #3
0
/*!
 * Given the original segments and splits apply
 * all segment splits and create unique segment index.
 *
 * Split.seg is the index to the segment to split before this function.
 * After the splits are applied every split.seq is unique.
 */
static void
_split_segments (GArray *segs, GArray *splits, const GArray *other)
{
  int i, sofs = 0;
  GArray *pending;

  /* splits must be sorted for the algorithm below */
  g_array_sort (splits, _compare_split);

  for (i = 0; i < splits->len; ++i) {
    int j, to;
    int from = i;
    int from_seg = g_array_index (splits, Split, i).seg;
    BezierSegment bs;
    real t = 0;

    g_return_if_fail (from_seg + sofs < segs->len);
    bs = g_array_index (segs, BezierSegment, from_seg + sofs);
    while (i < splits->len - 1 && from_seg == g_array_index (splits, Split, i+1).seg)
      ++i; /* advance while segment reference is the same */
    to = i;
    for (j = from; j <= to; j++) {
      BezierSegment left, right;
      /* scale t to split the right segment */
      real tL = g_array_index (splits, Split, j).split;
      real tR = (tL - t) / (1.0 - t);
      bezier_split_at (&bs, &left, &right, tR);
      bs = right;
      t = tL;
      /* overwrite the exisiting */
      g_return_if_fail (from_seg + sofs < segs->len);
      g_array_index (segs, BezierSegment, from_seg + sofs) = left;
      sofs += 1; /* increment segment offset for every segment added */
      /* insert a new one behind that ... */
      g_array_insert_val (segs, from_seg + sofs, right); /* ... potentially overwritten */
      /* adjust the segment reference */
      g_array_index (splits, Split, j).seg = from_seg + sofs;
    }
  }
  pending = g_array_new (FALSE, FALSE, sizeof(BezierSegment));
  /* for every sub-path determine if it is inside the full other path */
  for (i = 0; i < splits->len; ++i) {
    Split *sp = &g_array_index (splits, Split, i);
    BezierSegment *bs = &g_array_index (segs, BezierSegment, sp->seg);
    BezierSegment left, right;
    int to, j;

    if (i == 0 && sp->seg > 0)
      g_array_append_vals (pending, &g_array_index (segs, BezierSegment, 0), sp->seg);

    bezier_split (bs, &left, &right);
    sp->outside = distance_bez_shape_point (&g_array_index (other, BezPoint, 0), other->len,
					   0 /* line width */, &right.p0) > 0.0;
    /* also remember the sub-path */
    to = g_array_index (splits, Split, (i+1)%splits->len).seg;
    sp->path = g_array_new (FALSE, FALSE, sizeof(BezierSegment));
    if (to < sp->seg) {
      g_array_append_vals (sp->path, bs, segs->len - sp->seg);
#if 0
      /* XXX: this is only correct if there is no move-to within the segments */
      g_array_append_vals (sp->path, &g_array_index (segs, BezierSegment, 0), to);
#else
      g_array_append_vals (sp->path, &g_array_index (pending, BezierSegment, 0), pending->len);
      g_array_set_size (pending, 0);
#endif
    } else {
      for (j = sp->seg; j < to; ++j) {
	if (_segment_is_moveto (bs)) {
	  g_array_append_vals (sp->path, &g_array_index (pending, BezierSegment, 0), pending->len);
	  g_array_set_size (pending, 0);
	  break;
	}
	g_array_append_val (sp->path, *bs);
	bs++;
      }
      for (/* remains */; j < to; ++j) {
	g_array_append_val (pending, *bs);
	bs++;
      }
    }
  }
  g_array_free (pending, TRUE);
}