source: libcaca/trunk/ruby/cucul/cucul-canvas.c @ 1944

Last change on this file since 1944 was 1944, checked in by Pascal Terjan, 13 years ago

Import Ruby binding

  • Property svn:eol-style set to native
File size: 16.5 KB
Line 
1/*
2 *  libcucul Ruby bindings
3 *  Copyright (c) 2007 Pascal Terjan <pterjan@linuxfr.org>
4 *
5 *  This library is free software. It comes without any warranty, to
6 *  the extent permitted by applicable law. You can redistribute it
7 *  and/or modify it under the terms of the Do What The Fuck You Want
8 *  To Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12#include <ruby.h>
13#include <cucul.h>
14#include <errno.h>
15
16#define _SELF  (DATA_PTR(self))
17
18#define simple_func(x)                                  \
19static VALUE x (VALUE self)                             \
20{                                                       \
21    if( cucul_##x (_SELF) <0)                           \
22        rb_raise(rb_eRuntimeError, strerror(errno));    \
23                                                        \
24    return self;                                        \
25}
26
27#define get_int(x)                                      \
28static VALUE get_##x (VALUE self)                       \
29{                                                       \
30    return INT2NUM(cucul_get_##x (_SELF));              \
31}
32
33static void canvas_free(void * p)
34{
35    cucul_free_canvas((cucul_canvas_t *)p);
36}
37
38static VALUE canvas_alloc(VALUE klass)
39{
40    cucul_canvas_t *canvas;
41    VALUE obj;
42   
43    canvas = cucul_create_canvas(0, 0);
44    obj = Data_Wrap_Struct(klass, 0, canvas_free, canvas);
45   
46    return obj;
47}
48
49static VALUE canvas_initialize(VALUE self, VALUE width, VALUE height)
50{
51    unsigned int w, h;
52
53    w = NUM2INT(width);
54    h = NUM2INT(height);
55   
56    cucul_set_canvas_size(_SELF, w, h);
57   
58    return self;
59}
60
61get_int(canvas_height)
62get_int(canvas_width)
63
64static VALUE set_canvas_width(VALUE self, VALUE width)
65{
66    cucul_set_canvas_size(_SELF, NUM2INT(width), cucul_get_canvas_height(_SELF));
67    return width;
68}
69
70static VALUE set_canvas_width2(VALUE self, VALUE width)
71{
72    set_canvas_width(self, width);
73    return self;
74}
75
76static VALUE set_canvas_height(VALUE self, VALUE height)
77{
78    cucul_set_canvas_size(_SELF, cucul_get_canvas_width(_SELF), NUM2INT(height));
79    return height;
80}
81
82static VALUE set_canvas_height2(VALUE self, VALUE height)
83{
84    set_canvas_height(self, height);
85    return self;
86}
87
88static VALUE set_canvas_size(VALUE self, VALUE height, VALUE width)
89{
90    cucul_set_canvas_size(_SELF, NUM2INT(width), NUM2INT(height));
91    return self;
92}
93
94/****/
95
96static VALUE gotoxy(VALUE self, VALUE x, VALUE y)
97{
98    if( cucul_gotoxy(_SELF, NUM2INT(x), NUM2INT(y)) <0) {
99        rb_raise(rb_eRuntimeError, strerror(errno));
100    }
101    return self;
102}
103
104get_int(cursor_x)
105get_int(cursor_y)
106
107simple_func(clear_canvas)
108
109static VALUE put_char(VALUE self, VALUE x, VALUE y, VALUE ch)
110{
111    cucul_put_char(_SELF, NUM2INT(x), NUM2INT(y), NUM2ULONG(ch));
112    return self;
113}
114
115static VALUE get_char(VALUE self, VALUE x, VALUE y)
116{
117    unsigned long int ch;
118    ch = cucul_get_char(_SELF, NUM2INT(x), NUM2INT(y));
119    return INT2NUM(ch);
120}
121
122static VALUE put_str(VALUE self, VALUE x, VALUE y, VALUE str)
123{
124    cucul_put_str(_SELF, NUM2INT(x), NUM2INT(y), StringValuePtr(str));
125    return self;
126}
127
128static VALUE get_attr(VALUE self, VALUE x, VALUE y)
129{
130    unsigned long int ch;
131    ch = cucul_get_attr(_SELF, NUM2INT(x), NUM2INT(y));
132    return INT2NUM(ch);
133}
134
135static VALUE set_attr(VALUE self, VALUE attr)
136{
137    if(cucul_set_attr(_SELF, NUM2ULONG(attr)) <0)
138        rb_raise(rb_eRuntimeError, strerror(errno));
139
140    return self;
141}
142
143static VALUE set_attr2(VALUE self, VALUE attr)
144{
145    set_attr(self, attr);
146    return self;
147}
148
149static VALUE put_attr(VALUE self, VALUE x, VALUE y, VALUE attr)
150{
151    if(cucul_put_attr(_SELF, NUM2INT(x), NUM2INT(y), NUM2ULONG(attr)) <0)
152        rb_raise(rb_eRuntimeError, strerror(errno));
153
154    return self;
155}
156
157static VALUE set_color_ansi(VALUE self, VALUE fg, VALUE bg)
158{
159    if(cucul_set_color_ansi(_SELF, NUM2INT(fg), NUM2INT(bg)) <0)
160        rb_raise(rb_eRuntimeError, strerror(errno));
161
162    return self;
163}
164
165static VALUE set_color_argb(VALUE self, VALUE fg, VALUE bg)
166{
167    if(cucul_set_color_argb(_SELF, NUM2UINT(fg), NUM2UINT(bg)) <0) {
168        rb_raise(rb_eRuntimeError, strerror(errno));
169    }
170    return self;
171}
172
173static VALUE cprintf(int argc, VALUE* argv, VALUE self)
174{
175    int x, y;
176    VALUE rx, ry, format, rest, string;
177    rb_scan_args(argc, argv, "3*", &rx, &ry, &format, &rest);
178    x = NUM2INT(rx);
179    y = NUM2INT(ry);
180    string = rb_funcall2(rb_mKernel, rb_intern("sprintf"), argc-2, argv+2);
181    cucul_put_str(_SELF, x, y, StringValuePtr(string));
182    return self;
183}
184
185
186get_int(canvas_handle_x)
187get_int(canvas_handle_y)
188
189static VALUE set_canvas_handle(VALUE self, VALUE x, VALUE y)
190{
191    cucul_set_canvas_handle(_SELF, NUM2INT(x), NUM2INT(y));
192    return self;
193}
194
195static VALUE blit(int argc, VALUE* argv, VALUE self) {
196    VALUE x, y, src, mask;
197    cucul_canvas_t *csrc, *cmask;
198
199    rb_scan_args(argc, argv, "31", &x, &y, &src, &mask);
200
201    Check_Type(x, T_FIXNUM);
202    Check_Type(y, T_FIXNUM);
203    Check_Type(src, TYPE(self));
204    Data_Get_Struct(src, cucul_canvas_t, csrc);
205    if(!NIL_P(mask))
206    {
207        Check_Type(mask, TYPE(self));
208        Data_Get_Struct(mask, cucul_canvas_t, cmask);
209    }
210    else
211        cmask = NULL;
212   
213    if(cucul_blit(_SELF, NUM2INT(x), NUM2INT(y), csrc, cmask)<0)
214        rb_raise(rb_eRuntimeError, strerror(errno));
215
216    return self;
217}
218
219static VALUE set_canvas_boundaries(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h)
220{
221    if(cucul_set_canvas_boundaries(_SELF, NUM2INT(x), NUM2INT(y), NUM2UINT(w), NUM2UINT(h))<0)
222    {
223        rb_raise(rb_eRuntimeError, strerror(errno));
224    }
225    return self;
226}
227
228/****/
229
230simple_func(invert)
231simple_func(flip)
232simple_func(flop)
233simple_func(rotate_180)
234simple_func(rotate_left)
235simple_func(rotate_right)
236simple_func(stretch_left)
237simple_func(stretch_right)
238
239/****/
240
241static VALUE draw_line(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE ch)
242{
243    cucul_draw_line(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2),NUM2ULONG(ch));
244    return self;
245}
246
247static VALUE draw_polyline(VALUE self, VALUE x, VALUE y, VALUE ch)
248{
249    int i, n;
250    int *ax, *ay;
251   
252    n = RARRAY(x)->len;
253
254    /* Ensure x and y have the same number of elements */
255    if(n != RARRAY(y)->len)
256        rb_raise(rb_eArgError, "Arguments do not have the same number of elements");
257
258    ax = (int*)malloc(n*sizeof(int));
259    if(!ax)
260        rb_raise(rb_eNoMemError,"Out of memory");
261
262    ay = (int*)malloc(n*sizeof(int));
263    if(!ay)
264    {
265        free(ax);
266        rb_raise(rb_eNoMemError,"Out of memory");
267    }
268
269    for(i=0; i<n; i++)
270    {
271        ax[i] = NUM2INT(rb_ary_entry(x, i));
272        ay[i] = NUM2INT(rb_ary_entry(y, i));
273    }
274
275    n--;
276
277    cucul_draw_polyline(_SELF, ax, ay, n, NUM2ULONG(ch));
278
279    free(ax);
280    free(ay);
281
282    return self;
283}
284
285static VALUE draw_thin_line(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
286{
287    cucul_draw_thin_line(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2));
288    return self;
289}
290
291
292static VALUE draw_thin_polyline(VALUE self, VALUE x, VALUE y)
293{
294    int i, n;
295    int *ax, *ay;
296   
297    n = RARRAY(x)->len;
298
299    /* Ensure x and y have the same number of elements */
300    if(n != RARRAY(y)->len)
301        rb_raise(rb_eArgError, "Arguments do not have the same number of elements");
302
303    ax = (int*)malloc(n*sizeof(int));
304    if(!ax)
305        rb_raise(rb_eNoMemError,"Out of memory");
306
307    ay = (int*)malloc(n*sizeof(int));
308    if(!ay)
309    {
310        free(ax);
311        rb_raise(rb_eNoMemError,"Out of memory");
312    }
313
314    for(i=0; i<n; i++)
315    {
316        ax[i] = NUM2INT(rb_ary_entry(x, i));
317        ay[i] = NUM2INT(rb_ary_entry(y, i));
318    }
319
320    n--;
321
322    cucul_draw_thin_polyline(_SELF, ax, ay, n);
323
324    free(ax);
325    free(ay);
326
327    return self;
328}
329
330static VALUE draw_circle(VALUE self, VALUE x, VALUE y, VALUE r, VALUE ch)
331{
332    cucul_draw_circle(_SELF, NUM2INT(x), NUM2INT(y), NUM2INT(r), NUM2ULONG(ch));
333    return self;
334}
335
336static VALUE draw_ellipse(VALUE self, VALUE x, VALUE y, VALUE a, VALUE b, VALUE ch)
337{
338    cucul_draw_ellipse(_SELF, NUM2INT(x), NUM2INT(y), NUM2INT(a), NUM2INT(b), NUM2ULONG(ch));
339    return self;
340}
341
342static VALUE draw_thin_ellipse(VALUE self, VALUE x, VALUE y, VALUE a, VALUE b)
343{
344    cucul_draw_thin_ellipse(_SELF, NUM2INT(x), NUM2INT(y), NUM2INT(a), NUM2INT(b));
345    return self;
346}
347
348static VALUE fill_ellipse(VALUE self, VALUE x, VALUE y, VALUE a, VALUE b, VALUE ch)
349{
350    cucul_fill_ellipse(_SELF, NUM2INT(x), NUM2INT(y), NUM2INT(a), NUM2INT(b), NUM2ULONG(ch));
351    return self;
352}
353
354static VALUE draw_box(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE ch)
355{
356    cucul_draw_box(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2), NUM2ULONG(ch));
357    return self;
358}
359
360static VALUE draw_thin_box(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
361{
362    cucul_draw_thin_box(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2));
363    return self;
364}
365
366static VALUE draw_cp437_box(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
367{
368    cucul_draw_cp437_box(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2));
369    return self;
370}
371
372static VALUE fill_box(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE ch)
373{
374    cucul_fill_box(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2), NUM2ULONG(ch));
375    return self;
376}
377
378static VALUE draw_triangle(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3, VALUE ch)
379{
380    cucul_draw_triangle(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2),  NUM2INT(x3), NUM2INT(y3), NUM2ULONG(ch));
381    return self;
382}
383
384static VALUE draw_thin_triangle(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3)
385{
386    cucul_draw_thin_triangle(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2),  NUM2INT(x3), NUM2INT(y3));
387    return self;
388}
389
390static VALUE fill_triangle(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE x3, VALUE y3, VALUE ch)
391{
392    cucul_fill_triangle(_SELF, NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2),  NUM2INT(x3), NUM2INT(y3), NUM2ULONG(ch));
393    return self;
394}
395
396/****/
397
398get_int(frame_count)
399
400static VALUE set_frame(VALUE self, VALUE id)
401{
402    if(cucul_set_frame(_SELF, NUM2INT(id))<0)
403        rb_raise(rb_eArgError, strerror(errno));
404
405    return self;
406}
407
408static VALUE set_frame2(VALUE self, VALUE id)
409{
410    set_frame(self, id);
411    return self;
412}
413
414static VALUE get_frame_name(VALUE self)
415{
416    return rb_str_new2(cucul_get_frame_name(_SELF));
417}
418
419static VALUE set_frame_name(VALUE self, VALUE name)
420{
421    if(cucul_set_frame_name(_SELF, StringValuePtr(name))<0)
422        rb_raise(rb_eRuntimeError, strerror(errno));
423
424    return self;
425}
426
427static VALUE set_frame_name2(VALUE self, VALUE name)
428{
429    set_frame_name(self, name);
430    return self;
431}
432
433static VALUE create_frame(VALUE self, VALUE id)
434{
435    if(cucul_create_frame(_SELF, NUM2INT(id))<0) {
436        rb_raise(rb_eRuntimeError, strerror(errno));
437    }
438    return self;
439}
440
441static VALUE free_frame(VALUE self, VALUE id)
442{
443    if(cucul_free_frame(_SELF, NUM2INT(id))<0) {
444        rb_raise(rb_eArgError, strerror(errno));
445    }
446    return self;
447}
448
449/****/
450
451static VALUE import_memory(VALUE self, VALUE data, VALUE format)
452{
453    long int bytes;
454    bytes = cucul_import_memory (_SELF, StringValuePtr(data), RSTRING(StringValue(data))->len, StringValuePtr(format));
455    if(bytes <= 0)
456        rb_raise(rb_eRuntimeError, strerror(errno));
457
458    return self;
459}
460
461static VALUE import_file(VALUE self, VALUE filename, VALUE format)
462{
463    long int bytes;
464    bytes = cucul_import_file (_SELF, StringValuePtr(filename), StringValuePtr(format));
465    if(bytes <= 0)
466        rb_raise(rb_eRuntimeError, strerror(errno));
467
468    return self;
469}
470
471static VALUE export_memory(VALUE self, VALUE format)
472{
473    unsigned long int bytes;
474    void *result;
475    VALUE ret;
476    result = cucul_export_memory (_SELF, StringValuePtr(format), &bytes);
477    ret = rb_str_new(result, bytes);
478    free(result);
479    return ret;
480}
481
482static VALUE export_list()
483{
484    VALUE ary, ary2;
485   
486    char const* const* list;
487   
488    list = cucul_get_export_list();
489   
490    ary = rb_ary_new();
491   
492    while (*list != NULL)
493    {
494        ary2 = rb_ary_new();
495        rb_ary_push(ary2, rb_str_new2(*list));
496        list++;
497        rb_ary_push(ary2, rb_str_new2(*list));
498        list++;
499        rb_ary_push(ary, ary2);
500    }
501
502    return ary;
503}
504
505static VALUE import_list()
506{
507    VALUE ary, ary2;
508   
509    char const* const* list;
510   
511    list = cucul_get_import_list();
512   
513    ary = rb_ary_new();
514   
515    while (*list != NULL)
516    {
517        ary2 = rb_ary_new();
518        rb_ary_push(ary2, rb_str_new2(*list));
519        list++;
520        rb_ary_push(ary2, rb_str_new2(*list));
521        list++;
522        rb_ary_push(ary, ary2);
523    }
524
525    return ary;
526}
527
528/****/
529
530void Init_cucul_canvas(VALUE mCucul)
531{
532    VALUE cCanvas = rb_define_class_under(mCucul, "Canvas", rb_cObject);
533    rb_define_alloc_func(cCanvas, canvas_alloc);
534
535    rb_define_method(cCanvas, "initialize", canvas_initialize, 2);
536    rb_define_method(cCanvas, "width", get_canvas_width, 0);
537    rb_define_method(cCanvas, "width=", set_canvas_width, 1);
538    rb_define_method(cCanvas, "set_width", set_canvas_width2, 1);
539    rb_define_method(cCanvas, "height", get_canvas_height, 0);
540    rb_define_method(cCanvas, "height=", set_canvas_height, 0);
541    rb_define_method(cCanvas, "set_height", set_canvas_height2, 0);
542    rb_define_method(cCanvas, "set_size", set_canvas_size, 2);
543       
544    rb_define_method(cCanvas, "gotoxy", gotoxy, 2);
545    rb_define_method(cCanvas, "cursor_x", get_cursor_x, 0);
546    rb_define_method(cCanvas, "cursor_y", get_cursor_y, 0);
547    rb_define_method(cCanvas, "handle_x", get_canvas_handle_x, 0);
548    rb_define_method(cCanvas, "handle_y", get_canvas_handle_y, 0);
549    rb_define_method(cCanvas, "set_handle", set_canvas_handle, 2);
550    rb_define_method(cCanvas, "blit", blit, -1);
551    rb_define_method(cCanvas, "set_boundaries", set_canvas_boundaries, 4);
552
553    rb_define_method(cCanvas, "clear", clear_canvas, 0);
554   
555    rb_define_method(cCanvas, "put_char", put_char, 3);
556    rb_define_method(cCanvas, "get_char", get_char, 2);
557    rb_define_method(cCanvas, "put_str", put_str, 3);
558    rb_define_method(cCanvas, "printf", cprintf, -1);
559
560    rb_define_method(cCanvas, "get_attr", get_attr, 3);
561    rb_define_method(cCanvas, "attr=", set_attr, 1);
562    rb_define_method(cCanvas, "set_attr", set_attr2, 1);
563    rb_define_method(cCanvas, "put_attr", put_attr, 3);
564    rb_define_method(cCanvas, "set_color_ansi", set_color_ansi, 2);
565    rb_define_method(cCanvas, "set_color_argb", set_color_argb, 2);
566
567    rb_define_method(cCanvas, "invert", invert, 0);
568    rb_define_method(cCanvas, "flip", flip, 0);
569    rb_define_method(cCanvas, "flop", flop, 0);
570    rb_define_method(cCanvas, "rotate_180", rotate_180, 0);
571    rb_define_method(cCanvas, "rotate_left", rotate_left, 0);
572    rb_define_method(cCanvas, "rotate_right", rotate_right, 0);
573    rb_define_method(cCanvas, "stretch_left", stretch_left, 0);
574    rb_define_method(cCanvas, "stretch_right", stretch_right, 0);
575
576    rb_define_method(cCanvas, "draw_line", draw_line, 5);
577    rb_define_method(cCanvas, "draw_polyline", draw_polyline, 3);
578    rb_define_method(cCanvas, "draw_thin_line", draw_thin_line, 4);
579    rb_define_method(cCanvas, "draw_thin_polyline", draw_thin_polyline, 2);
580    rb_define_method(cCanvas, "draw_circle", draw_circle, 4);
581    rb_define_method(cCanvas, "draw_ellipse", draw_ellipse, 5);
582    rb_define_method(cCanvas, "draw_thin_ellipse", draw_thin_ellipse, 4);
583    rb_define_method(cCanvas, "fill_ellipse", fill_ellipse, 5);
584    rb_define_method(cCanvas, "draw_box", draw_box, 5);
585    rb_define_method(cCanvas, "draw_thin_box", draw_thin_box, 4);
586    rb_define_method(cCanvas, "draw_cp437_box", draw_cp437_box, 4);
587    rb_define_method(cCanvas, "fill_box", fill_box, 5);
588    rb_define_method(cCanvas, "draw_triangle", draw_triangle, 7);
589    rb_define_method(cCanvas, "draw_thin_triangle", draw_thin_triangle, 6);
590    rb_define_method(cCanvas, "fill_triangle", fill_triangle, 7);
591
592    rb_define_method(cCanvas, "frame_count", get_frame_count, 0);
593    rb_define_method(cCanvas, "frame=", set_frame, 1);
594    rb_define_method(cCanvas, "set_frame", set_frame2, 1);
595    rb_define_method(cCanvas, "frame_name", get_frame_name, 0);
596    rb_define_method(cCanvas, "frame_name=", set_frame_name, 1);
597    rb_define_method(cCanvas, "set_frame_name", set_frame_name2, 1);
598    rb_define_method(cCanvas, "create_frame", create_frame, 1);
599    rb_define_method(cCanvas, "free_frame", free_frame, 1);
600
601    rb_define_method(cCanvas, "import_memory", import_memory, 2);
602    rb_define_method(cCanvas, "import_file", import_file, 2);
603    rb_define_method(cCanvas, "export_memory", export_memory, 1);
604    rb_define_singleton_method(cCanvas, "export_list", export_list, 0);
605    rb_define_singleton_method(cCanvas, "import_list", import_list, 0);
606   
607}
608
Note: See TracBrowser for help on using the repository browser.