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;
}
}
|