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; } }
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 {
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; } }
/* 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); } }
/** 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); } }