Пример #1
0
/** rectangle algorithm **/
void
rect_do_action(int x1, int y1, int x2, int y2, texture_info * tex, VALUE hash_arg,
               texplay_sync sync_mode, bool primary, action_struct * payload)
{
    action_struct cur;
    bool fill = false;
    int thickness = 1;

    draw_prologue(&cur, tex, x1, y1,
                  x2, y2, &hash_arg, sync_mode, primary, &payload);

    
    if(is_a_hash(hash_arg)) {

        /* make our private copy of the hash so we can mess with it */
        hash_arg = rb_obj_dup(hash_arg);

        if(RTEST(get_from_hash(hash_arg, "fill")) || RTEST(get_from_hash(hash_arg, "filled"))) {
            fill = true;

            /* since we're filling the rect, line thickness is irrelevant */
            delete_from_hash(hash_arg, "thickness");
        }
        else if(RTEST(get_from_hash(hash_arg, "thickness"))) {
            thickness = NUM2INT(get_from_hash(hash_arg, "thickness"));
            /* TO DO: find a better way of doing this */

            if(thickness > 1) {
                cur.xmin = x1 - thickness / 2;
                cur.ymin = y1 - thickness / 2;
                cur.xmax = x2 + thickness / 2 + 1;
                cur.ymax = y2 + thickness / 2 + 1;
            }
        }
    }
    if(!fill) {
        line_do_action(x1, y1, x2, y1, tex, hash_arg, no_sync, false, payload);
        line_do_action(x1, y1, x1, y2, tex, hash_arg, no_sync, false, payload);
        line_do_action(x1, y2, x2, y2, tex, hash_arg, no_sync, false, payload);
        line_do_action(x2, y1, x2, y2, tex, hash_arg, no_sync, false, payload);
    }
    else {
        if(y1 > y2) SWAP(y1, y2);

        for(int y = y1; y <= y2; y++)
            line_do_action(x1, y, x2, y, tex, hash_arg, no_sync, false, payload);
    }

    draw_epilogue(&cur, tex, primary);
}
Пример #2
0
enum TDB_ERROR tdb_delete(struct tdb_context *tdb, struct tdb_data key)
{
	tdb_off_t off;
	struct tdb_used_record rec;
	struct hash_info h;
	enum TDB_ERROR ecode;

	if (tdb->flags & TDB_VERSION1) {
		if (tdb1_delete(tdb, key) == -1)
			return tdb->last_error;
		return TDB_SUCCESS;
	}

	off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
	if (TDB_OFF_IS_ERR(off)) {
		return tdb->last_error = TDB_OFF_TO_ERR(off);
	}

	if (!off) {
		ecode = TDB_ERR_NOEXIST;
		goto unlock;
	}

	ecode = delete_from_hash(tdb, &h);
	if (ecode != TDB_SUCCESS) {
		goto unlock;
	}

	/* Free the deleted entry. */
	tdb->stats.frees++;
	ecode = add_free_record(tdb, off,
				sizeof(struct tdb_used_record)
				+ rec_key_length(&rec)
				+ rec_data_length(&rec)
				+ rec_extra_padding(&rec),
				TDB_LOCK_WAIT, true);

	if (tdb->flags & TDB_SEQNUM)
		tdb_inc_seqnum(tdb);

unlock:
	tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
	return tdb->last_error = ecode;
}
Пример #3
0
_PUBLIC_ enum NTDB_ERROR ntdb_delete(struct ntdb_context *ntdb, NTDB_DATA key)
{
	ntdb_off_t off;
	struct ntdb_used_record rec;
	struct hash_info h;
	enum NTDB_ERROR ecode;

	off = find_and_lock(ntdb, key, F_WRLCK, &h, &rec, NULL);
	if (NTDB_OFF_IS_ERR(off)) {
		return NTDB_OFF_TO_ERR(off);
	}

	if (!off) {
		ecode = NTDB_ERR_NOEXIST;
		goto unlock;
	}

	ecode = delete_from_hash(ntdb, &h);
	if (ecode != NTDB_SUCCESS) {
		goto unlock;
	}

	/* Free the deleted entry. */
	ntdb->stats.frees++;
	ecode = add_free_record(ntdb, off,
				sizeof(struct ntdb_used_record)
				+ rec_key_length(&rec)
				+ rec_data_length(&rec)
				+ rec_extra_padding(&rec),
				NTDB_LOCK_WAIT, true);

	if (ntdb->flags & NTDB_SEQNUM)
		ntdb_inc_seqnum(ntdb);

unlock:
	ntdb_unlock_hash(ntdb, h.h, F_WRLCK);
	return ecode;
}
Пример #4
0
/*
 * Calculates the threading relationships for a list of messages
 */
Container *calculate_threads(apr_pool_t *p, MBOX_LIST *l)
{
    apr_hash_t *h, *rootSet, *subjectSet;
    apr_hash_index_t *hashIndex;
    MBOX_LIST *current = l;
    const apr_array_header_t *refHdr;
    apr_table_entry_t *refEnt;
    Message *m;
    Container *c, *subjectPair, *realParent, *curParent, *tmp;
    void *hashKey, *hashVal, *subjectVal;
    char *subject;
    int msgIDLen, refLen, i;
    apr_ssize_t hashLen, subjectLen;

    /* FIXME: Use APR_HASH_KEY_STRING instead?  Maybe slower. */
    h = apr_hash_make(p);

    while (current != NULL) {
        m = (Message *) current->value;
        msgIDLen = strlen(m->msgID);
        c = (Container *) apr_hash_get(h, m->msgID, msgIDLen);
        if (c) {
            c->message = m;
        }
        else {
            c = (Container *) apr_pcalloc(p, sizeof(Container));
            c->message = m;
            c->parent = NULL;
            c->child = NULL;
            c->next = NULL;
            apr_hash_set(h, m->msgID, msgIDLen, c);
        }

        realParent = NULL;

        if (m->references) {
            refHdr = apr_table_elts(m->references);
            refEnt = (apr_table_entry_t *) refHdr->elts;

            for (i = 0; i < refHdr->nelts; i++) {

                refLen = strlen(refEnt[i].key);

                curParent =
                    (Container *) apr_hash_get(h, refEnt[i].key, refLen);

                /* Create a dummy node to store the message we haven't
                 * yet seen. */
                if (!curParent) {
                    curParent =
                        (Container *) apr_pcalloc(p, sizeof(Container));
                    apr_hash_set(h, refEnt[i].key, refLen, curParent);
                }

                /* Check to make sure we are not going to create a loop
                 * by adding this parent to our list.
                 */
                if (realParent &&
                    !detect_loop(curParent, realParent) &&
                    !detect_loop(realParent, curParent)) {
                    /* Update the parent */
                    if (curParent->parent)
                        unlink_parent(curParent);

                    curParent->parent = realParent;
                    curParent->next = realParent->child;
                    realParent->child = curParent;
                }

                /* We now have a new parent */
                realParent = curParent;
            }

        }

        /* The last parent we saw is our parent UNLESS it causes a loop. */
        if (realParent && !detect_loop(c, realParent) &&
            !detect_loop(realParent, c)) {
            /* We need to unlink our parent's link to us. */
            if (c->parent)
                unlink_parent(c);

            c->parent = realParent;
            c->next = realParent->child;
            realParent->child = c;
        }

        current = current->next;
    }

    /* Find the root set */
    rootSet = apr_hash_make(p);

    for (hashIndex = apr_hash_first(p, h); hashIndex;
         hashIndex = apr_hash_next(hashIndex)) {
        apr_hash_this(hashIndex, (void *) &hashKey, &hashLen, &hashVal);
        c = (Container *) hashVal;
        if (!c->parent)
            apr_hash_set(rootSet, hashKey, hashLen, c);
    }

    /* Prune empty containers */
    for (hashIndex = apr_hash_first(p, rootSet); hashIndex;
         hashIndex = apr_hash_next(hashIndex)) {
        apr_hash_this(hashIndex, (void *) &hashKey, &hashLen, &hashVal);
        c = (Container *) hashVal;

        prune_container(c);

        if (!c->message && !c->child)
            apr_hash_set(rootSet, hashKey, hashLen, NULL);
    }

    /* Merge root set by subjects */
    subjectSet = apr_hash_make(p);

    for (hashIndex = apr_hash_first(p, rootSet); hashIndex;
         hashIndex = apr_hash_next(hashIndex)) {
        apr_hash_this(hashIndex, (void *) &hashKey, &hashLen, &hashVal);
        c = (Container *) hashVal;

        /* If we don't have a message, our child will. */
        if (!c->message)
            c = c->child;

        subject = strip_subject(p, c->message);
        subjectLen = strlen(subject);

        /* FIXME: Match what JWZ says */
        subjectVal = apr_hash_get(subjectSet, subject, subjectLen);
        if (subjectVal) {
            if (!c->message)
                apr_hash_set(subjectSet, subject, strlen(subject), hashVal);
            else {
                subjectPair = (Container *) subjectVal;
                if (!is_reply(c->message) && is_reply(subjectPair->message))
                    apr_hash_set(subjectSet, subject, strlen(subject),
                                 hashVal);
            }
        }
        else
            apr_hash_set(subjectSet, subject, strlen(subject), hashVal);
    }

    /* Subject table now populated */
    for (hashIndex = apr_hash_first(p, rootSet); hashIndex;
         hashIndex = apr_hash_next(hashIndex)) {
        apr_hash_this(hashIndex, (void *) &hashKey, &hashLen, &hashVal);
        c = (Container *) hashVal;

        /* If we don't have a message, our child will. */
        if (c->message)
            subject = strip_subject(p, c->message);
        else
            subject = strip_subject(p, c->child->message);

        subjectLen = strlen(subject);

        subjectVal = apr_hash_get(subjectSet, subject, subjectLen);
        subjectPair = (Container *) subjectVal;

        /* If we need to merge the tables */
        if (subjectPair && subjectPair != c) {
            if (!c->message || !subjectPair->message) { /* One is dummy */
                if (!c->message && !subjectPair->message)
                    join_container(subjectPair, c);
                else if (c->message && !subjectPair->message) {
                    /* It's possible that we're already a child! */
                    if (c->parent != subjectPair)
                        append_container(subjectPair, c);
                }
                else {          /* (!c->message && subjectPair->message) */

                    append_container(c, subjectPair);
                    apr_hash_set(subjectSet, subject, subjectLen, c);
                    delete_from_hash(p, rootSet, subjectPair);
                }
            }
            else {              /* Both aren't dummies */

                /* We are Reply */
                if (is_reply(c->message) && !is_reply(subjectPair->message))
                    append_container(subjectPair, c);
                else if (!is_reply(c->message) &&
                         is_reply(subjectPair->message)) {
                    append_container(c, subjectPair);
                    apr_hash_set(subjectSet, subject, subjectLen, c);
                    delete_from_hash(p, rootSet, subjectPair);
                }
                else {          /* We are both replies. */

                    c = merge_container(p, c, subjectPair);
                    apr_hash_set(subjectSet, subject, subjectLen, c);
                    delete_from_hash(p, rootSet, subjectPair);
                }
            }
        }
    }

    /* Now, we are done threading.  We want to return a sorted container
     * back to our caller.  All children of the root set need to be in
     * order and then we need to issue an ordering to the root set.
     */
    tmp = NULL;
    /* Sort siblings */
    for (hashIndex = apr_hash_first(p, subjectSet); hashIndex;
         hashIndex = apr_hash_next(hashIndex)) {
        apr_hash_this(hashIndex, (void *) &hashKey, &hashLen, &hashVal);
        c = (Container *) hashVal;

        sort_siblings(c);

        if (tmp)
            c->next = tmp;
        tmp = c;
    }

    return (Container *) mbox_sort_linked_list(tmp, 3, compare_siblings, NULL,
                                               NULL);
}
Пример #5
0
/* TODO: fix this function below, it's too ugly and bulky and weird **/
static void
process_common_hash_args(action_struct * cur, VALUE * hash_arg, sync_ sync_mode, bool primary)
{

    VALUE user_defaults;
    VALUE hash_blend;


    /* if a hash doesn't exist then create one */
    if(!is_a_hash(*hash_arg))
        *hash_arg = rb_hash_new();

    /* init the action to default values */
    initialize_action_struct(cur, *hash_arg, sync_mode);

    /* get the user default options & merge with given options */
    user_defaults = get_image_local(cur->tex->image, USER_DEFAULTS);
    hash_blend = rb_funcall(user_defaults, rb_intern("merge"), 1, *hash_arg);
    rb_funcall(*hash_arg, rb_intern("merge!"), 1, hash_blend);

    if(has_optional_hash_arg(*hash_arg, "color")) {
        VALUE c = get_from_hash(*hash_arg, "color");
        cur->color = convert_rb_color_to_rgba(c);
        if(c == string2sym("random")) {
            set_hash_value(*hash_arg, "color", convert_rgba_to_rb_color(&cur->color));
        }
    }

    /* shadows */
    if(RTEST(get_from_hash(*hash_arg, "shadow"))) {
        cur->pen.color_mult.red = 0.66;
        cur->pen.color_mult.green = 0.66;
        cur->pen.color_mult.blue = 0.66;
        cur->pen.color_mult.alpha = 1;

        cur->pen.has_color_control_transform = true;
    }

    /* tolerance */
    if(RTEST(get_from_hash(*hash_arg, "tolerance"))) {
      cur->pen.tolerance = NUM2DBL(get_from_hash(*hash_arg, "tolerance"));

      /* maximum length of hypotonese extended in 4-space (color space) is sqrt(4) */
      if (cur->pen.tolerance >= 2)
        cur->pen.tolerance = 2;

      if (cur->pen.tolerance < 0)
        cur->pen.tolerance = 0;

      cur->pen.has_tolerance = true;
    }

    /* lerp */
    if(RTEST(get_from_hash(*hash_arg, "lerp"))) {
      cur->pen.lerp = NUM2DBL(get_from_hash(*hash_arg, "lerp"));

      /* bounds */
      if(cur->pen.lerp > 1.0) cur->pen.lerp = 1.0;
      if(cur->pen.lerp < 0.0) cur->pen.lerp = 0.0;
      cur->pen.has_lerp = true;
    }

    /* sync mode */
    if(has_optional_hash_arg(*hash_arg, "sync_mode")) {
        VALUE user_sync_mode = get_from_hash(*hash_arg, "sync_mode");

        Check_Type(user_sync_mode, T_SYMBOL);

        if(user_sync_mode == string2sym("lazy_sync"))
            cur->sync_mode = lazy_sync;
        else if(user_sync_mode == string2sym("eager_sync"))
            cur->sync_mode = eager_sync;
        else if(user_sync_mode == string2sym("no_sync"))
            cur->sync_mode = no_sync;
        else
            rb_raise(rb_eArgError, "unrecognized sync mode: %s\n. Allowable modes are "
                     ":lazy_sync, :eager_sync, :no_sync.",
                     sym2string(user_sync_mode));

        delete_from_hash(*hash_arg, "sync_mode");

    }

    /* prepare color selection */
    prepare_color_select(cur);

    /* process drawing mode */
    prepare_drawing_mode(cur);

    /* process the color_control block or transform (if there is one) */
    prepare_color_control(cur);

    /* process the filling texture (if there is one) */
    prepare_fill_texture(cur);

    /* does the user want to blend alpha values ? */
    prepare_alpha_blend(cur);
}
Пример #6
0
/** midpoint circle algorithm **/
void
circle_do_action(int x1, int y1, int r, texture_info * tex, VALUE hash_arg,
                 texplay_sync sync_mode, bool primary, action_struct * payload)
{

    int x, y;
    float p;
    action_struct cur;
    bool fill = false;

    draw_prologue(&cur, tex, x1 - r, y1 - r, x1 + r, y1 + r, &hash_arg,
                  sync_mode, primary, &payload);


    if(is_a_hash(hash_arg)) {

        /* make our private copy of the hash so we can mess with it */
        hash_arg = rb_obj_dup(hash_arg);

        if(RTEST(get_from_hash(hash_arg, "fill")) || RTEST(get_from_hash(hash_arg, "filled"))) {
            fill = true;

            /* to prevent infinite recursion set line thickness to 1 :D
               NB: a filled circle uses lines and a thick line uses filled circles :D */
            delete_from_hash(hash_arg, "thickness");
        }
    }
    
    x = 0 ; y = r;
    p = 5 / 4 - r;
    if(!fill) {
        while (x <= y) {
            set_pixel_color_with_style(payload, tex, x1 + x, y1 + y);
            set_pixel_color_with_style(payload, tex, x1 + x, y1 - y);
            set_pixel_color_with_style(payload, tex, x1 - x, y1 + y);
            set_pixel_color_with_style(payload, tex, x1 - x, y1 - y);
            set_pixel_color_with_style(payload, tex, x1 + y, y1 + x);
            set_pixel_color_with_style(payload, tex, x1 + y, y1 - x);
            set_pixel_color_with_style(payload, tex, x1 - y, y1 + x);
            set_pixel_color_with_style(payload, tex, x1 - y, y1 - x);

            if (p < 0) {
                p += 2 * x + 3;
            }
            else {
                y--;
                p += 2 * (x - y) + 5;
            }
            x++;
        }
    }
    else {
        while (x <= y) {
            line_do_action(x1 - x, y1 + y, x1 + x, y1 + y, tex, hash_arg, no_sync, false, payload);
            line_do_action(x1 - x, y1 - y, x1 + x, y1 - y, tex, hash_arg, no_sync, false, payload);
            line_do_action(x1 - y, y1 + x, x1 + y, y1 + x, tex, hash_arg, no_sync, false, payload);
            line_do_action(x1 - y, y1 - x, x1 + y, y1 - x, tex, hash_arg, no_sync, false, payload);

            if (p < 0) {
                p += 2 * x + 3;
            }
            else {
                y--;
                p += 2 * (x - y) + 5;
            }
            x++;
        }
    }

    draw_epilogue(&cur, tex, primary);
}