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

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