Module: Spiro

Defined in:
lib/spiro.rb,
lib/spiro/version.rb,
ext/spiro/spiro.c

Constant Summary collapse

VERSION =
'0.0.2'

Class Method Summary collapse

Class Method Details

.spiros_to_splines(spirosValue, closedValue) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'ext/spiro/spiro.c', line 54

static VALUE spiros_to_splines(VALUE mod, VALUE spirosValue, VALUE closedValue) {
  Check_Type(spirosValue, T_ARRAY);

  // Take Ruby array of points and turn into Spiro C struct array
  spiro_cp spiros[RARRAY_LEN(spirosValue)];
  for (int i = 0; i != RARRAY_LEN(spirosValue); i++) {
    VALUE nodeValue = rb_ary_entry(spirosValue, i);
    // Validate node is an array and length 3 (x, y, type)
    Check_Type(nodeValue, T_ARRAY);
    if (RARRAY_LEN(nodeValue) != 3) rb_raise(rb_eArgError, "%s", "Invalid node");

    // Validate individual node elements
    VALUE xValue = rb_ary_entry(nodeValue, 0);
    if (TYPE(xValue) != T_FIXNUM && TYPE(xValue) != T_FLOAT) {
      rb_raise(rb_eTypeError, "x coord must be float or fixnum");
    }
    VALUE yValue = rb_ary_entry(nodeValue, 1);
    if (TYPE(yValue) != T_FIXNUM && TYPE(yValue) != T_FLOAT) {
      rb_raise(rb_eTypeError, "y coord must be float or fixnum");
    }
    VALUE typeValue = rb_ary_entry(nodeValue, 2);
    Check_Type(typeValue, T_SYMBOL);

    spiros[i].x  = (long)(NUM2DBL(xValue));
    spiros[i].y  = (long)(NUM2DBL(yValue));
    spiros[i].ty = sym_to_spiro_type(typeValue);
  }

  int closed = bool_to_int(closedValue);

  // bezctx_rb is custom, stores the result of running Spiro
  bezctx *bc = new_bezctx_rb();
  // Run Spiro on the Spiros array and populate custom struct with splines array
  int success = SpiroCPsToBezier0(spiros, RARRAY_LEN(spirosValue), closed, bc);

  if (success) {
    // Build Ruby array from Spiro array
    VALUE splinesValue = rb_ary_new();
    // Free memory from the custom struct
    bezctx_rb_close(bc);
    for (int i = 0; i < splines.used; i++) {
      VALUE x = rb_float_new(splines.array[i].x);
      VALUE y = rb_float_new(splines.array[i].y);
      VALUE ty = spline_type_to_sym(splines.array[i].ty);
      VALUE nodeValue = rb_ary_new3(3, x, y, ty);
      rb_ary_push(splinesValue, nodeValue);
    }
    freeSplines(&splines);

    return splinesValue;
  }
  else {
    bezctx_rb_close(bc);
    freeSplines(&splines);
    return Qnil;
  }
}