Exemple #1
0
static void
prepare_alpha_blend(action_struct * cur)
{
  if(has_optional_hash_arg(cur->hash_arg, "alpha_blend")) {

    VALUE blend_mode = get_from_hash(cur->hash_arg, "alpha_blend");

    /* true is equivalent to default blend mode, 'source' */
    if(blend_mode == Qtrue)
      blend_mode = string2sym("source");

    /* where false or nil is passed */
    if(!RTEST(blend_mode)) {
      cur->pen.alpha_blend = false;
      return;
    }

    cur->pen.alpha_blend = true;

    Check_Type(blend_mode, T_SYMBOL);

    if(blend_mode == string2sym("source")) {
      cur->pen.alpha_blend_mode = source;
    }
    else if(blend_mode == string2sym("dest")) {
      cur->pen.alpha_blend_mode = dest;
    }
    else if(blend_mode == string2sym("source_with_fixed_alpha")) {
      cur->pen.alpha_blend_mode = source_with_fixed_alpha;
    }
    else if(blend_mode == string2sym("dest_with_fixed_alpha")) {
      cur->pen.alpha_blend_mode = dest_with_fixed_alpha;
    }
    else
      rb_raise(rb_eArgError, "unrecognized blend mode: %s\n.",
               sym2string(blend_mode));

  }


}
Exemple #2
0
static void
prepare_drawing_mode(action_struct * cur)
{
  if(is_a_hash(cur->hash_arg)) {
    /* drawing mode */
    if(has_optional_hash_arg(cur->hash_arg, "mode")) {
      cur->pen.has_drawing_mode = true;

      VALUE draw_mode = get_from_hash(cur->hash_arg, "mode");


      Check_Type(draw_mode, T_SYMBOL);

      if(draw_mode == string2sym("default")) {
        cur->pen.has_drawing_mode = false;

        return;
      }
      else if(draw_mode == string2sym("clear"))
        cur->pen.drawing_mode = clear;

      else if(draw_mode == string2sym("copy"))
        cur->pen.drawing_mode = copy;

      else if(draw_mode == string2sym("noop"))
        cur->pen.drawing_mode = noop;

      else if(draw_mode == string2sym("set"))
        cur->pen.drawing_mode = set;

      else if(draw_mode == string2sym("copy_inverted"))
        cur->pen.drawing_mode = copy_inverted;

      else if(draw_mode == string2sym("invert"))
        cur->pen.drawing_mode = invert;

      else if(draw_mode == string2sym("and_reverse"))
        cur->pen.drawing_mode = and_reverse;

      else if(draw_mode == string2sym("and"))
        cur->pen.drawing_mode = and;

      else if(draw_mode == string2sym("or"))
        cur->pen.drawing_mode = or;

      else if(draw_mode == string2sym("nand"))
        cur->pen.drawing_mode = nand;

      else if(draw_mode == string2sym("nor"))
        cur->pen.drawing_mode = nor;

      else if(draw_mode == string2sym("xor"))
        cur->pen.drawing_mode = xor;

      else if(draw_mode == string2sym("equiv"))
        cur->pen.drawing_mode = equiv;

      else if(draw_mode == string2sym("and_inverted"))
        cur->pen.drawing_mode = and_inverted;

      else if(draw_mode == string2sym("or_inverted"))
        cur->pen.drawing_mode = or_inverted;

      else if(draw_mode == string2sym("additive"))
        cur->pen.drawing_mode = additive;
      else if(draw_mode == string2sym("multiply"))
        cur->pen.drawing_mode = multiply;
      else if(draw_mode == string2sym("screen"))
        cur->pen.drawing_mode = screen;
      else if(draw_mode == string2sym("overlay"))
        cur->pen.drawing_mode = overlay;
      else if(draw_mode == string2sym("darken"))
        cur->pen.drawing_mode = darken;
      else if(draw_mode == string2sym("lighten"))
        cur->pen.drawing_mode = lighten;
      else if(draw_mode == string2sym("color_dodge"))
        cur->pen.drawing_mode = color_dodge;
      else if(draw_mode == string2sym("color_burn"))
        cur->pen.drawing_mode = color_burn;
      else if(draw_mode == string2sym("hard_light"))
        cur->pen.drawing_mode = hard_light;
      else if(draw_mode == string2sym("soft_light"))
        cur->pen.drawing_mode = soft_light;
      else if(draw_mode == string2sym("difference"))
        cur->pen.drawing_mode = difference;
      else if(draw_mode == string2sym("exclusion"))
        cur->pen.drawing_mode = exclusion;
      else
        rb_raise(rb_eArgError, "unrecognized drawing mode: %s\n.",
                 sym2string(draw_mode));
    }
  }
}
Exemple #3
0
/** splice algorithm **/
void
splice_do_action(int x0, int y0, int cx1, int cy1, int cx2, int cy2, texture_info * splice_tex,
                 texture_info * tex, VALUE hash_arg, texplay_sync sync_mode,
                 bool primary, action_struct * payload)
{
    action_struct cur;
    int xbound;
    int ybound;
    rgba chromakey;
    float * image_buf = NULL;
    bool inverse_chroma = false;
    bool same_image = false;
    bool has_chroma = false;

    constrain_boundaries(&cx1, &cy1, &cx2, &cy2, splice_tex->width, splice_tex->height);
    xbound = cx2 - cx1 + 1;
    ybound = cy2 - cy1 + 1;

    draw_prologue(&cur, tex, x0, y0,
                  x0 + xbound, y0 + ybound, &hash_arg, sync_mode, primary, &payload);


    if(has_optional_hash_arg(hash_arg, "chroma_key")) {
        VALUE c = get_from_hash(hash_arg, "chroma_key");
        chromakey = convert_rb_color_to_rgba(c);
        has_chroma = true;
    }
    else if(has_optional_hash_arg(hash_arg, "chroma_key_not")) {
        chromakey = convert_rb_color_to_rgba(get_from_hash(hash_arg, "chroma_key_not"));
        inverse_chroma = true;
        has_chroma = true;
    }

    if(splice_tex->image == tex->image)
        same_image = true;

    /* NB: we do not use this in the general case since it's almost 1.5 times as slow.
       It is necessary for splicing from/to the same region of pixels though.
    */
    if(same_image) 
        image_buf = get_image_chunk(splice_tex, cx1, cy1, cx2, cy2);
    
    for(int y = 0; y < ybound; y++)
        for(int x = 0; x < xbound; x++) {
            
            if(!same_image)
                payload->color = get_pixel_color(splice_tex, cx1 + x, cy1 + y);
            else 
                payload->color = get_pixel_color_from_chunk(image_buf, xbound, ybound, x, y);
                
            if(has_chroma) {
                bool chroma_match = cmp_color(payload->color, chromakey);
                
                /* look at released 0.2.0 code to see how USED to do this.
                   this is now a simplified boolean expression (XOR) */
                if(chroma_match == inverse_chroma)
                    set_pixel_color_with_style(payload, tex, x0 + x, y0 + y);
            }
            else
                set_pixel_color_with_style(payload, tex, x0 + x, y0 + y);
        }

    if(same_image)
        free(image_buf);

    draw_epilogue(&cur, tex, primary);
}
Exemple #4
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);
}
Exemple #5
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");
    }
}