1 /*
2  *  libcaca Ruby bindings
3  *  Copyright (c) 2007-2012 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://www.wtfpl.net/ for more details.
10  */
11 
12 #include <ruby.h>
13 #include <caca.h>
14 #include <errno.h>
15 #include "common.h"
16 
17 VALUE cDither;
18 
dither_free(void * dither)19 void dither_free(void *dither)
20 {
21     caca_free_dither((caca_dither_t *)dither);
22 }
23 
dither_alloc(VALUE klass)24 static VALUE dither_alloc(VALUE klass)
25 {
26     VALUE obj;
27     obj = Data_Wrap_Struct(klass, 0, dither_free, NULL);
28     return obj;
29 }
30 
dither_initialize(VALUE self,VALUE bpp,VALUE w,VALUE h,VALUE pitch,VALUE rmask,VALUE gmask,VALUE bmask,VALUE amask)31 static VALUE dither_initialize(VALUE self, VALUE bpp, VALUE w, VALUE h, VALUE pitch, VALUE rmask, VALUE gmask, VALUE bmask, VALUE amask)
32 {
33     caca_dither_t *dither;
34 
35     dither = caca_create_dither(NUM2UINT(bpp), NUM2UINT(w), NUM2UINT(h), NUM2UINT(pitch), NUM2ULONG(rmask), NUM2ULONG(gmask), NUM2ULONG(bmask), NUM2ULONG(amask));
36     if(dither == NULL)
37     {
38         rb_raise(rb_eRuntimeError, "%s", strerror(errno));
39     }
40     _SELF = dither;
41     return self;
42 }
43 
set_dither_palette(VALUE self,VALUE palette)44 static VALUE set_dither_palette(VALUE self, VALUE palette)
45 {
46     int i;
47     unsigned int *red, *blue, *green, *alpha;
48     VALUE v, r, g, b, a;
49     int error = 0;
50 
51     if(RARRAY_LEN(palette) != 256)
52     {
53         rb_raise(rb_eArgError, "Palette must contain 256 elements");
54     }
55 
56     red = ALLOC_N(unsigned int, 256);
57     if(!red)
58         rb_raise(rb_eNoMemError,"Out of memory");
59 
60     green = ALLOC_N(unsigned int, 256);
61     if(!green)
62     {
63         free(red);
64         rb_raise(rb_eNoMemError,"Out of memory");
65     }
66 
67     blue = ALLOC_N(unsigned int, 256);
68     if(!blue)
69     {
70         free(red);
71         free(green);
72         rb_raise(rb_eNoMemError,"Out of memory");
73     }
74 
75     alpha = ALLOC_N(unsigned int, 256);
76     if(!alpha)
77     {
78         free(red);
79         free(green);
80         free(blue);
81         rb_raise(rb_eNoMemError,"Out of memory");
82     }
83 
84     for(i=0; i<256; i++)
85     {
86         v = rb_ary_entry(palette, i);
87         if((TYPE(v) == T_ARRAY) && (RARRAY_LEN(v) == 4))
88         {
89             r = rb_ary_entry(v,0);
90             g = rb_ary_entry(v,1);
91             b = rb_ary_entry(v,2);
92             a = rb_ary_entry(v,3);
93             if(rb_obj_is_kind_of(r, rb_cInteger) &&
94                rb_obj_is_kind_of(g, rb_cInteger) &&
95                rb_obj_is_kind_of(b, rb_cInteger) &&
96                rb_obj_is_kind_of(a, rb_cInteger))
97             {
98                 red[i]   = NUM2INT(r);
99                 green[i] = NUM2INT(g);
100                 blue[i]  = NUM2INT(b);
101                 alpha[i] = NUM2INT(a);
102             } else
103                 error = 1;
104         }
105         else
106             error = 1;
107     }
108 
109     if(error)
110     {
111         free(red);
112         free(green);
113         free(blue);
114         free(alpha);
115         rb_raise(rb_eArgError, "Invalid palette");
116     }
117 
118     if(caca_set_dither_palette(_SELF, red, green, blue, alpha)<0)
119     {
120         free(red);
121         free(green);
122         free(blue);
123         free(alpha);
124         rb_raise(rb_eRuntimeError, "%s", strerror(errno));
125     }
126 
127     free(red);
128     free(green);
129     free(blue);
130     free(alpha);
131 
132     return palette;
133 }
134 
set_dither_palette2(VALUE self,VALUE palette)135 static VALUE set_dither_palette2(VALUE self, VALUE palette)
136 {
137     set_dither_palette(self, palette);
138     return self;
139 }
140 
141 #define set_float(x)                                    \
142 static VALUE set_##x(VALUE self, VALUE x)               \
143 {                                                       \
144     if(caca_set_dither_##x(_SELF, (float)NUM2DBL(x))<0) \
145         rb_raise(rb_eRuntimeError, "%s", strerror(errno));    \
146                                                         \
147     return x;                                           \
148 }                                                       \
149                                                         \
150 static VALUE set_##x##2(VALUE self, VALUE x)            \
151 {                                                       \
152     set_##x(self, x);                                   \
153     return self;                                        \
154 }
155 
156 set_float(brightness)
set_float(gamma)157 set_float(gamma)
158 set_float(contrast)
159 
160 #define get_set_str_from_list(x)                         \
161 get_double_list(dither_##x)                              \
162 static VALUE set_dither_##x(VALUE self, VALUE x)         \
163 {                                                        \
164     if(caca_set_dither_##x(_SELF, StringValuePtr(x))<0)  \
165     {                                                    \
166         rb_raise(rb_eRuntimeError, "%s", strerror(errno));     \
167     }                                                    \
168     return x;                                            \
169 }                                                        \
170                                                          \
171 static VALUE set_dither_##x##2(VALUE self, VALUE x)      \
172 {                                                        \
173      set_dither_##x(self, x);                            \
174      return self;                                        \
175 }
176 
177 get_set_str_from_list(antialias)
178 get_set_str_from_list(color)
179 get_set_str_from_list(charset)
180 get_set_str_from_list(algorithm)
181 
182 void Init_caca_dither(VALUE mCaca)
183 {
184     cDither = rb_define_class_under(mCaca, "Dither", rb_cObject);
185     rb_define_alloc_func(cDither, dither_alloc);
186 
187     rb_define_method(cDither, "initialize", dither_initialize, 8);
188     rb_define_method(cDither, "palette=", set_dither_palette, 1);
189     rb_define_method(cDither, "set_palette", set_dither_palette2, 1);
190     rb_define_method(cDither, "brightness=", set_brightness, 1);
191     rb_define_method(cDither, "set_brightness", set_brightness2, 1);
192     rb_define_method(cDither, "gamma=", set_gamma, 1);
193     rb_define_method(cDither, "set_gamma", set_gamma2, 1);
194     rb_define_method(cDither, "contrast=", set_contrast, 1);
195     rb_define_method(cDither, "set_contrast", set_contrast2, 1);
196     rb_define_method(cDither, "antialias_list", dither_antialias_list, 0);
197     rb_define_method(cDither, "antialias=", set_dither_antialias, 1);
198     rb_define_method(cDither, "set_antialias", set_dither_antialias2, 1);
199     rb_define_method(cDither, "color_list", dither_color_list, 0);
200     rb_define_method(cDither, "color=", set_dither_color, 1);
201     rb_define_method(cDither, "set_color", set_dither_color2, 1);
202     rb_define_method(cDither, "charset_list", dither_charset_list, 0);
203     rb_define_method(cDither, "charset=", set_dither_charset, 1);
204     rb_define_method(cDither, "set_charset", set_dither_charset2, 1);
205     rb_define_method(cDither, "algorithm_list", dither_algorithm_list, 0);
206     rb_define_method(cDither, "algorithm=", set_dither_algorithm, 1);
207     rb_define_method(cDither, "set_algorithm", set_dither_algorithm2, 1);
208 }
209 
210