Beispiel #1
0
static cairo_bool_t
_cairo_contour_simplify_chain (cairo_contour_t *contour, const double tolerance,
			       const cairo_contour_iter_t *first,
			       const cairo_contour_iter_t *last)
{
    cairo_contour_iter_t iter, furthest;
    uint64_t max_error;
    int x0, y0;
    int nx, ny;
    int count;

    iter = *first;
    iter_next (&iter);
    if (iter_equal (&iter, last))
	return FALSE;

    x0 = first->point->x;
    y0 = first->point->y;
    nx = last->point->y - y0;
    ny = x0 - last->point->x;

    count = 0;
    max_error = 0;
    do {
	cairo_point_t *p = iter.point;
	if (! DELETED(p)) {
	    uint64_t d = (uint64_t)nx * (x0 - p->x) + (uint64_t)ny * (y0 - p->y);
	    if (d * d > max_error) {
		max_error = d * d;
		furthest = iter;
	    }
	    count++;
	}
	iter_next (&iter);
    } while (! iter_equal (&iter, last));
    if (count == 0)
	return FALSE;

    if (max_error > tolerance * ((uint64_t)nx * nx + (uint64_t)ny * ny)) {
	cairo_bool_t simplified;

	simplified = FALSE;
	simplified |= _cairo_contour_simplify_chain (contour, tolerance,
						     first, &furthest);
	simplified |= _cairo_contour_simplify_chain (contour, tolerance,
						     &furthest, last);
	return simplified;
    } else {
	iter = *first;
	iter_next (&iter);
	do {
	    MARK_DELETED (iter.point);
	    iter_next (&iter);
	} while (! iter_equal (&iter, last));

	return TRUE;
    }
}
Beispiel #2
0
int	dirfind (
	int	curfile,
	int	forward,
	DCLARG	*find_spec,
	void	(*each)(int, int *),
	int	must_find,
	int	unfind)
{
#define	FIND_FNB	find_spec->dcl$l_fnb
#define	FIND_TEXT	find_spec->dcl_text

PATHNT	pz;
FILENT	fz;

int	flag	= TRUE,		/* continue-loop unless 'each' quits	*/
	found_any = 0;
int	j, k, tst;
char	Fpath[MAX_PATH],	Fname[MAX_NAME+1],	Ftype[MAX_TYPE+1];

	dirfind_chop (find_spec, &fz, &pz, Fpath, Fname, Ftype);

	/*
	 * If 'forward' is negative, obtain the proper value from the
	 * command decoder:
	 */
	if (forward < 0)
	{
		forward = dircmd_dirflg(-1);
		curfile	= dirfind_nxt (curfile, !forward);
	}

#define	XOR(a,b) ((a && !b) || (!a && b))
#define	if_T	tst = dirfind_tst(FK_(j), &fz, TRUE);\
		if (XOR(tst,unfind))
#define	LOOP	for (j = dirfind_nxt(curfile,forward), k = numfiles; k > 0;\
			j = dirfind_nxt(j,forward), k--)
#define	BIT_1	1		/* Use this bit via 'dirent_misc'	*/

	if (each)		/* Multiple action ?	*/
	{
		dirent_misc (-1, BIT_1);	/* Reset all '.fmisc'	*/
		if (strchr(FIND_TEXT,'*') || strchr(FIND_TEXT,'%')
		||  strchr(Fpath, '*'))
			dds_while (nullC);

		for (j = 0; j < numfiles; j++)
		{
			if_T
				dirent_misc (j, BIT_1);
		}
		LOOP
		{
			if (DELETED(j))		continue;
			dds_while(nullC);
			if (FK(j).fmisc & BIT_1)
			{
				(*each)(j, &flag);
				found_any++;
				if (!flag)		break;
			}
		}
		dirent_misc (-1, BIT_1);	/* cleanup after use	*/
	}
	else
	{
Beispiel #3
0
void
_cairo_contour_simplify (cairo_contour_t *contour, double tolerance)
{
    cairo_contour_chain_t *chain;
    cairo_point_t *last = NULL;
    cairo_contour_iter_t iter, furthest;
    cairo_bool_t simplified;
    uint64_t max = 0;
    int i;

    if (contour->chain.num_points <= 2)
	return;

    tolerance = tolerance * CAIRO_FIXED_ONE;
    tolerance *= tolerance;

    /* stage 1: vertex reduction */
    for (chain = &contour->chain; chain; chain = chain->next) {
	for (i = 0; i < chain->num_points; i++) {
	    if (last == NULL ||
		point_distance_sq (last, &chain->points[i]) > tolerance) {
		last = &chain->points[i];
	    } else {
		MARK_DELETED (&chain->points[i]);
	    }
	}
    }

    /* stage2: polygon simplification using Douglas-Peucker */
    simplified = FALSE;
    do {
	last = &contour->chain.points[0];
	iter_init (&furthest, contour);
	max = 0;
	for (chain = &contour->chain; chain; chain = chain->next) {
	    for (i = 0; i < chain->num_points; i++) {
		uint64_t d;

		if (DELETED (&chain->points[i]))
		    continue;

		d = point_distance_sq (last, &chain->points[i]);
		if (d > max) {
		    furthest.chain = chain;
		    furthest.point = &chain->points[i];
		    max = d;
		}
	    }
	}
	assert (max);

	simplified = FALSE;
	iter_init (&iter, contour);
	simplified |= _cairo_contour_simplify_chain (contour, tolerance,
						     &iter, &furthest);

	iter_init_last (&iter, contour);
	if (! iter_equal (&furthest, &iter))
	    simplified |= _cairo_contour_simplify_chain (contour, tolerance,
							 &furthest, &iter);
    } while (simplified);

    iter_init (&iter, contour);
    for (chain = &contour->chain; chain; chain = chain->next) {
	int num_points = chain->num_points;
	chain->num_points = 0;
	for (i = 0; i < num_points; i++) {
	    if (! DELETED(&chain->points[i])) {
		if (iter.point != &chain->points[i])
		    *iter.point = chain->points[i];
		iter.chain->num_points++;
		iter_next (&iter);
	    }
	}
    }

    if (iter.chain) {
	cairo_contour_chain_t *next;

	for (chain = iter.chain->next; chain; chain = next) {
	    next = chain->next;
	    free (chain);
	}

	iter.chain->next = NULL;
	contour->tail = iter.chain;
    }
}
Beispiel #4
0
/*
  DESCRIPTION
    Search for hashnr/key/keylen in the list starting from 'head' and
    position the cursor. The list is ORDER BY hashnr, key

  RETURN
    0 - not found
    1 - found

  NOTE
    cursor is positioned in either case
    pins[0..2] are used, they are NOT removed on return
*/
static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
                 const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins)
{
  uint32       cur_hashnr;
  const uchar  *cur_key;
  uint         cur_keylen;
  intptr       link;

retry:
  cursor->prev= (intptr *)head;
  do { /* PTR() isn't necessary below, head is a dummy node */
    cursor->curr= (LF_SLIST *)(*cursor->prev);
    _lf_pin(pins, 1, cursor->curr);
  } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF);
  for (;;)
  {
    if (unlikely(!cursor->curr))
      return 0; /* end of the list */
    do {
      /* QQ: XXX or goto retry ? */
      link= cursor->curr->link;
      cursor->next= PTR(link);
      _lf_pin(pins, 0, cursor->next);
    } while (link != cursor->curr->link && LF_BACKOFF);
    cur_hashnr= cursor->curr->hashnr;
    cur_key= cursor->curr->key;
    cur_keylen= cursor->curr->keylen;
    if (*cursor->prev != (intptr)cursor->curr)
    {
      (void)LF_BACKOFF;
      goto retry;
    }
    if (!DELETED(link))
    {
      if (cur_hashnr >= hashnr)
      {
        int r= 1;
        if (cur_hashnr > hashnr ||
            (r= my_strnncoll(cs, (uchar*) cur_key, cur_keylen, (uchar*) key,
                             keylen)) >= 0)
          return !r;
      }
      cursor->prev= &(cursor->curr->link);
      _lf_pin(pins, 2, cursor->curr);
    }
    else
    {
      /*
        we found a deleted node - be nice, help the other thread
        and remove this deleted node
      */
      if (my_atomic_casptr((void **) cursor->prev,
                           (void **)(char*) &cursor->curr, cursor->next))
        _lf_alloc_free(pins, cursor->curr);
      else
      {
        (void)LF_BACKOFF;
        goto retry;
      }
    }
    cursor->curr= cursor->next;
    _lf_pin(pins, 1, cursor->curr);
  }
}
static int lfind_match(LF_SLIST * volatile *head,
                       uint32 first_hashnr, uint32 last_hashnr,
                       lf_hash_match_func *match,
                       CURSOR *cursor, LF_PINS *pins)
{
  uint32       cur_hashnr;
  intptr       link;

retry:
  cursor->prev= (intptr *)head;
  do { /* PTR() isn't necessary below, head is a dummy node */
    cursor->curr= (LF_SLIST *)(*cursor->prev);
    lf_pin(pins, 1, cursor->curr);
  } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF);
  for (;;)
  {
    if (unlikely(!cursor->curr))
      return 0; /* end of the list */
    do {
      /* QQ: XXX or goto retry ? */
      link= cursor->curr->link;
      cursor->next= PTR(link);
      lf_pin(pins, 0, cursor->next);
    } while (link != cursor->curr->link && LF_BACKOFF);
    cur_hashnr= cursor->curr->hashnr;
    if (*cursor->prev != (intptr)cursor->curr)
    {
      (void)LF_BACKOFF;
      goto retry;
    }
    if (!DELETED(link))
    {
      if (cur_hashnr >= first_hashnr)
      {
        if (cur_hashnr > last_hashnr)
          return 0;

        if (cur_hashnr & 1)
        {
          /* Normal node. Check if element matches condition. */
          if ((*match)((uchar *)(cursor->curr + 1)))
            return 1;
        }
        else
        {
          /*
            Dummy node. Nothing to check here.

            Still thanks to the fact that dummy nodes are never deleted we
            can save it as a safe place to restart iteration if ever needed.
          */
          head= (LF_SLIST * volatile *)&(cursor->curr->link);
        }
      }

      cursor->prev= &(cursor->curr->link);
      lf_pin(pins, 2, cursor->curr);
    }
    else
    {
      /*
        we found a deleted node - be nice, help the other thread
        and remove this deleted node
      */
      if (my_atomic_casptr((void **)cursor->prev,
                           (void **)&cursor->curr, cursor->next))
        lf_pinbox_free(pins, cursor->curr);
      else
      {
        (void)LF_BACKOFF;
        goto retry;
      }
    }
    cursor->curr= cursor->next;
    lf_pin(pins, 1, cursor->curr);
  }
}
Beispiel #6
0
/** walk the list, searching for an element or invoking a callback

    Search for hashnr/key/keylen in the list starting from 'head' and
    position the cursor. The list is ORDER BY hashnr, key

    @param head         start walking the list from this node
    @param cs           charset for comparing keys, NULL if callback is used
    @param hashnr       hash number to search for
    @param key          key to search for OR data for the callback
    @param keylen       length of the key to compare, 0 if callback is used
    @param cursor       for returning the found element
    @param pins         see lf_alloc-pin.c
    @param callback     callback action, invoked for every element

  @note
    cursor is positioned in either case
    pins[0..2] are used, they are NOT removed on return
    callback might see some elements twice (because of retries)

  @return
    if find: 0 - not found
             1 - found
    if callback:
             0 - ok
             1 - error (callbck returned 1)
*/
static int l_find(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr,
                 const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins,
                 my_hash_walk_action callback)
{
  uint32       cur_hashnr;
  const uchar  *cur_key;
  uint         cur_keylen;
  intptr       link;

  DBUG_ASSERT(!cs || !callback);        /* should not be set both */
  DBUG_ASSERT(!keylen || !callback);    /* should not be set both */

retry:
  cursor->prev= (intptr *)head;
  do { /* PTR() isn't necessary below, head is a dummy node */
    cursor->curr= (LF_SLIST *)(*cursor->prev);
    lf_pin(pins, 1, cursor->curr);
  } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF);

  for (;;)
  {
    if (unlikely(!cursor->curr))
      return 0; /* end of the list */

    cur_hashnr= cursor->curr->hashnr;
    cur_keylen= cursor->curr->keylen;
    cur_key= cursor->curr->key;

    do {
      link= cursor->curr->link;
      cursor->next= PTR(link);
      lf_pin(pins, 0, cursor->next);
    } while (link != cursor->curr->link && LF_BACKOFF);

    if (!DELETED(link))
    {
      if (unlikely(callback))
      {
        if (cur_hashnr & 1 && callback(cursor->curr + 1, (void*)key))
          return 1;
      }
      else if (cur_hashnr >= hashnr)
      {
        int r= 1;
        if (cur_hashnr > hashnr ||
            (r= my_strnncoll(cs, cur_key, cur_keylen, key, keylen)) >= 0)
          return !r;
      }
      cursor->prev= &(cursor->curr->link);
      if (!(cur_hashnr & 1)) /* dummy node */
        head= (LF_SLIST **)cursor->prev;
      lf_pin(pins, 2, cursor->curr);
    }
    else
    {
      /*
        we found a deleted node - be nice, help the other thread
        and remove this deleted node
      */
      if (my_atomic_casptr((void **) cursor->prev,
                           (void **) &cursor->curr, cursor->next) && LF_BACKOFF)
        lf_alloc_free(pins, cursor->curr);
      else
        goto retry;
    }
    cursor->curr= cursor->next;
    lf_pin(pins, 1, cursor->curr);
  }
}