Пример #1
0
/* if 2nd param is Qnil, then create a blank image with 'width' and 'height
   otherwise, try to use the 2nd param (dup) to create a duplicate image
 */
VALUE
create_image(VALUE window, int width, int height)
{
    static VALUE empty_image_stub = 0;
    static VALUE image = 0;

    if (empty_image_stub == 0) {
        VALUE gosu = rb_const_get(rb_cObject, rb_intern("Gosu"));
        VALUE tp = rb_const_get(rb_cObject, rb_intern("TexPlay"));
        empty_image_stub = rb_const_get(tp, rb_intern("EmptyImageStub"));
        image = rb_const_get(gosu, rb_intern("Image"));
    }

    VALUE rmagick_img;
    VALUE new_image;
    VALUE options = rb_hash_new();

    set_hash_value(options, "caching", Qfalse);

    rmagick_img = rb_funcall(empty_image_stub, rb_intern("new"), 2, INT2FIX(width), INT2FIX(height));

    new_image = rb_funcall(image, rb_intern("new"), 3, window, rmagick_img, options);

    return new_image;
}
Пример #2
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);
}
Пример #3
0
trace_match
line_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)
{
    int x, y, W, H, F;
    int xinc, yinc;
    action_struct cur;
    int thickness = 1;

    bool has_trace = false;
    rgba trace_color;
    trace_mode_type trace_mode = no_mode;
    
    if(has_optional_hash_arg(hash_arg, "thickness")) 
        thickness = NUM2INT(get_from_hash(hash_arg, "thickness"));
    
    if(has_optional_hash_arg(hash_arg, "trace") && primary) {
      VALUE trace_hash = get_from_hash(hash_arg, "trace");

      /* we're tracing (not drawing) */
      has_trace = true;

      /* since we're not drawing, no need to sync */
      sync_mode = no_sync;

      if(has_optional_hash_arg(trace_hash, "until_color")) {
        VALUE c = get_from_hash(trace_hash, "until_color");
        trace_color = convert_rb_color_to_rgba(c);
        trace_mode = until_color;
      }
      else if(has_optional_hash_arg(trace_hash, "while_color")) {
        VALUE c = get_from_hash(trace_hash, "while_color");
        trace_color = convert_rb_color_to_rgba(c);
        trace_mode = while_color;
      }
    }

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

    /* clip the line */
    cohen_sutherland_clip(&x1, &y1, &x2, &y2, 0, 0, tex->width - 1, tex->height - 1);
    
    W = ABS(x2 - x1);
    H = ABS(y2 - y1);
    	
    if(x1 < x2)
        xinc = 1;
    else
        xinc = -1;
		
    if(y1 < y2)
        yinc = 1;
    else
        yinc = -1;
		
    x = x1;
    y = y1;
	
    if(W >= H) {
        F = 2 * H - W;
        while(x != x2) {
           if(thickness <= 1) {
             if(!has_trace)
                set_pixel_color_with_style(payload, tex, x, y);
             else {
               rgba c = get_pixel_color(tex, x, y);

               if (is_trace_match(payload, c, trace_color, trace_mode)) 
                 return (trace_match) { x, y, c };
             }
            }
            else {
                set_hash_value(hash_arg, "fill", Qtrue);
                circle_do_action(x, y, thickness / 2, tex, hash_arg, no_sync, false, payload);
            }
           
            if(F < 0)
                F += 2 * H;
            else {
                F += 2 * (H - W);
                y += yinc;
            }
            x += xinc;
        }
    }
    else {
        F = 2 * W - H;
        while(y != y2 ) {

            if(thickness <= 1) {
             if(!has_trace)
                set_pixel_color_with_style(payload, tex, x, y);
             else {
               rgba c = get_pixel_color(tex, x, y);

               if (is_trace_match(payload, c, trace_color, trace_mode)) 
                 return (trace_match) { x, y, c };
             }                
            }
            else {
                set_hash_value(hash_arg, "fill", Qtrue);
                circle_do_action(x, y, thickness / 2, tex, hash_arg, no_sync, false, payload);
            }
            
            if(F < 0)
                F += 2 * W;
            else {
                F += 2 * (W - H);
                x += xinc;
            }
            y += yinc;
        }
    }

    if(thickness <= 1) {
        if(!has_trace)
          set_pixel_color_with_style(payload, tex, x2, y2);
        else {
          rgba c = get_pixel_color(tex, x, y);
          
          if (is_trace_match(payload, c, trace_color, trace_mode)) 
            return (trace_match) { x, y, c };
        }        
    }
    else {
        set_hash_value(hash_arg, "fill", Qtrue);
        circle_do_action(x2, y2, thickness / 2, tex, hash_arg, no_sync, false, payload);
                
    }
    draw_epilogue(&cur, tex, primary);

    return (trace_match) { .x = -9999, .y = -9999, .color = not_a_color_v };
}
/** end line **/

/** polyline algorithm **/

/* used by both polyline and bezier */
#define SIMPLE_FORMAT 0
#define POINT_FORMAT 1

/* calculate a single point */
static void
polyline_point(VALUE points, int k, int * x, int * y, int format, int draw_offset_x,
               int draw_offset_y)
{
    int xy_index;
    
    switch(format) {
    case POINT_FORMAT:
        *x = NUM2INT(point_x(get_from_array(points, k))) + draw_offset_x;
        *y = NUM2INT(point_y(get_from_array(points, k))) + draw_offset_y;
        break;
        
    case SIMPLE_FORMAT:
        xy_index = k * 2;
        *x = NUM2INT(get_from_array(points, xy_index)) + draw_offset_x;
        *y = NUM2INT(get_from_array(points, xy_index + 1)) + draw_offset_y;

        break;
    default:
        rb_raise(rb_eArgError, "pixel format must be either POINT_FORMAT or SIMPLE_FORMAT");
    }
}