1 #include "ppport.h"
2 #include <SDL.h>
3 #include "helper.h"
4
5 /* SV input should be a mortal SV */
create_mortal_rect(SV * rect)6 SV *create_mortal_rect( SV *rect )
7 {
8 SV *retval = NULL;
9
10 if( !SvOK(rect) )
11 {
12 /* create a new zero sized rectangle */
13 SDL_Rect* r = safemalloc( sizeof(SDL_Rect) );
14 r->x = 0;
15 r->y = 0;
16 r->w = 0;
17 r->h = 0;
18 retval = obj2bag( sizeof( SDL_Rect *), (void *)(r), "SDL::Rect" );
19 sv_2mortal(retval) ;
20 }
21 else if( sv_derived_from(rect, "ARRAY") )
22 {
23 /* create a new rectangle from the array */
24 SDL_Rect* r = safemalloc( sizeof(SDL_Rect) );
25 AV* recta = (AV*)SvRV(rect);
26 int len = av_len(recta);
27 int i;
28 int ra[4];
29 for(i = 0; i < 4; i++)
30 {
31 SV* iv = i > len ? NULL : AvARRAY(recta)[i];
32 ra[i] = ( iv == NULL || !SvOK( iv ) || iv == &PL_sv_undef )
33 ? 0
34 : SvIV( iv );
35 }
36
37 r->x = ra[0]; r->y = ra[1]; r->w = ra[2]; r->h= ra[3];
38 retval = obj2bag( sizeof( SDL_Rect *), (void *)(r), "SDL::Rect" );
39 sv_2mortal(retval) ;
40 }
41 else if( sv_isobject(rect) && sv_derived_from(rect, "SDL::Rect") )
42 {
43 /* we already had a good mortal rect . Just pass it along */
44 retval = rect;
45 }
46 else
47 croak("Rect must be number or arrayref or SDL::Rect or undef");
48
49 return retval;
50 }
51
assert_surface(SV * surface)52 void assert_surface( SV *surface )
53 {
54 if( sv_isobject(surface) && sv_derived_from(surface, "SDL::Surface"))
55 return;
56
57 croak("Surface must be SDL::Surface or SDLx::Surface");
58 /* does not return */
59 }
60
_color_format(SV * color)61 char *_color_format( SV *color )
62 {
63 char *retval = NULL;
64 if( !SvOK(color) || SvIOK(color) )
65 retval = "number";
66 else if( sv_derived_from(color, "ARRAY") )
67 retval = "arrayref";
68 else if( sv_isobject(color) && sv_derived_from(color, "SDL::Color") )
69 retval = "SDL::Color";
70 else
71 croak("Color must be number or arrayref or SDL::Color");
72
73 return retval;
74 }
75
_color_number(SV * color,SV * alpha)76 SV *_color_number( SV *color, SV *alpha )
77 {
78 int c = SvIV(color);
79 int a = SvIV(alpha);
80 unsigned int retval = SvUV(color);
81
82 if( !SvOK(color) || color < 0 )
83 {
84 if( color < 0 )
85 warn("Color was a negative number");
86 retval = a == 1
87 ? 0x000000FF
88 : 0;
89 }
90 else
91 {
92 if( a == 1 && (c > 0xFFFFFFFF) )
93 {
94 warn("Color was number greater than maximum expected: 0xFFFFFFFF");
95 retval = 0xFFFFFFFF;
96 }
97 else if ( a != 1 && ( c > 0xFFFFFF) )
98 {
99 warn("Color was number greater than maximum expected: 0xFFFFFF");
100 retval = 0xFFFFFF;
101 }
102 }
103
104 return newSVuv(retval);
105 }
106
107 /* returns a new mortal AV* */
_color_arrayref(AV * color,SV * alpha)108 AV *_color_arrayref( AV *color, SV *alpha )
109 {
110 AV *retval = (AV*)sv_2mortal((SV*)newAV());
111 int length = SvTRUE(alpha) ? 4 : 3;
112 int i = 0;
113 for(i = 0; i < length; i++)
114 {
115 if( av_len(color) < i || !SvOK(AvARRAY(color)[i]) )
116 av_push(retval, newSVuv(i == 3 ? 0xFF : 0));
117 else
118 {
119 int c = SvIV(AvARRAY(color)[i]);
120 if( c > 0xFF )
121 {
122 warn("Number in color arrayref was greater than maximum expected: 0xFF");
123 av_push(retval, newSVuv(0xFF));
124 }
125 else if( c < 0 )
126 {
127 warn("Number in color arrayref was negative");
128 av_push(retval, newSVuv(0));
129 }
130 else
131 av_push(retval, newSVuv(c));
132 }
133 }
134
135 return retval;
136 }
137
138 /* returns a mortal AV* */
__list_rgb(SV * color)139 AV* __list_rgb( SV* color )
140 {
141 char *format = _color_format(color);
142 AV* RETVAL ;
143 if ( 0 == strcmp("number", format) )
144 {
145 RETVAL = (AV*)sv_2mortal( (SV *) newAV() );
146 unsigned int _color = SvUV(sv_2mortal(_color_number(color, newSVuv(0))));
147 av_push(RETVAL, newSVuv(_color >> 16 & 0xFF));
148 av_push(RETVAL, newSVuv(_color >> 8 & 0xFF));
149 av_push(RETVAL, newSVuv(_color & 0xFF));
150 }
151 else if ( 0 == strcmp("arrayref", format) )
152 {
153 /* _color_arrayref returns a mortal AV* */
154 RETVAL = _color_arrayref((AV *)SvRV(color), sv_2mortal(newSVuv(0)));
155 }
156 else if ( 0 == strcmp("SDL::Color", format) )
157 {
158 RETVAL = (AV*)sv_2mortal((SV *) newAV() );
159 SDL_Color *_color = (SDL_Color *)bag2obj(color);
160 av_push(RETVAL, newSVuv(_color->r));
161 av_push(RETVAL, newSVuv(_color->g));
162 av_push(RETVAL, newSVuv(_color->b));
163 }
164 else
165 {
166 RETVAL = (AV*)sv_2mortal((SV *) newAV() );
167 av_push(RETVAL, newSVuv(0));
168 av_push(RETVAL, newSVuv(0));
169 av_push(RETVAL, newSVuv(0));
170 }
171
172 return RETVAL;
173 }
174
__list_rgba(SV * color)175 AV* __list_rgba( SV* color )
176 {
177 char *format = _color_format(color);
178 AV* RETVAL ;
179 if ( 0 == strcmp("number", format) )
180 {
181 RETVAL = (AV*)sv_2mortal((SV *) newAV() );
182 unsigned int _color = SvUV(sv_2mortal(_color_number(color, sv_2mortal(newSVuv(1)))));
183 av_push(RETVAL, newSVuv(_color >> 24 & 0xFF));
184 av_push(RETVAL, newSVuv(_color >> 16 & 0xFF));
185 av_push(RETVAL, newSVuv(_color >> 8 & 0xFF));
186 av_push(RETVAL, newSVuv(_color & 0xFF));
187 }
188 else if ( 0 == strcmp("arrayref", format) )
189 {
190 RETVAL = _color_arrayref((AV *)SvRV(color), sv_2mortal(newSVuv(1)));
191 }
192 else if ( 0 == strcmp("SDL::Color", format) )
193 {
194 RETVAL = (AV*)sv_2mortal((SV *) newAV() );
195 SDL_Color *_color = (SDL_Color*)bag2obj(color);
196 av_push(RETVAL, newSVuv(_color->r));
197 av_push(RETVAL, newSVuv(_color->g));
198 av_push(RETVAL, newSVuv(_color->b));
199 av_push(RETVAL, newSVuv(0xFF));
200 }
201 else
202 {
203 RETVAL = (AV*)sv_2mortal((SV *) newAV() );
204 av_push(RETVAL, newSVuv(0));
205 av_push(RETVAL, newSVuv(0));
206 av_push(RETVAL, newSVuv(0));
207 av_push(RETVAL, newSVuv(0xFF));
208 }
209
210 return RETVAL;
211 }
212
213
__map_rgb(SV * color,SDL_PixelFormat * format)214 unsigned int __map_rgb( SV* color, SDL_PixelFormat* format )
215 {
216 Uint8 r, g, b;
217 AV* a = __list_rgb( color );
218 r = SvUV(*av_fetch(a, 0, 0));
219 g = SvUV(*av_fetch(a, 1, 0));
220 b = SvUV(*av_fetch(a, 2, 0));
221
222 return SDL_MapRGB( format, r, g, b );
223 }
224
__map_rgba(SV * color,SDL_PixelFormat * format)225 unsigned int __map_rgba( SV* color, SDL_PixelFormat* format )
226 {
227 int r, g, b, a;
228 AV* ar = __list_rgba( color );
229 r = SvUV(*av_fetch(ar, 0, 0));
230 g = SvUV(*av_fetch(ar, 1, 0));
231 b = SvUV(*av_fetch(ar, 2, 0));
232 a = SvUV(*av_fetch(ar, 3, 0));
233
234 return SDL_MapRGBA( format, r, g, b, a );
235 }
236