#include "ppport.h" #include #include "helper.h" /* SV input should be a mortal SV */ SV *create_mortal_rect( SV *rect ) { SV *retval = NULL; if( !SvOK(rect) ) { /* create a new zero sized rectangle */ SDL_Rect* r = safemalloc( sizeof(SDL_Rect) ); r->x = 0; r->y = 0; r->w = 0; r->h = 0; retval = obj2bag( sizeof( SDL_Rect *), (void *)(r), "SDL::Rect" ); sv_2mortal(retval) ; } else if( sv_derived_from(rect, "ARRAY") ) { /* create a new rectangle from the array */ SDL_Rect* r = safemalloc( sizeof(SDL_Rect) ); AV* recta = (AV*)SvRV(rect); int len = av_len(recta); int i; int ra[4]; for(i = 0; i < 4; i++) { SV* iv = i > len ? NULL : AvARRAY(recta)[i]; ra[i] = ( iv == NULL || !SvOK( iv ) || iv == &PL_sv_undef ) ? 0 : SvIV( iv ); } r->x = ra[0]; r->y = ra[1]; r->w = ra[2]; r->h= ra[3]; retval = obj2bag( sizeof( SDL_Rect *), (void *)(r), "SDL::Rect" ); sv_2mortal(retval) ; } else if( sv_isobject(rect) && sv_derived_from(rect, "SDL::Rect") ) { /* we already had a good mortal rect . Just pass it along */ retval = rect; } else croak("Rect must be number or arrayref or SDL::Rect or undef"); return retval; } void assert_surface( SV *surface ) { if( sv_isobject(surface) && sv_derived_from(surface, "SDL::Surface")) return; croak("Surface must be SDL::Surface or SDLx::Surface"); /* does not return */ } char *_color_format( SV *color ) { char *retval = NULL; if( !SvOK(color) || SvIOK(color) ) retval = "number"; else if( sv_derived_from(color, "ARRAY") ) retval = "arrayref"; else if( sv_isobject(color) && sv_derived_from(color, "SDL::Color") ) retval = "SDL::Color"; else croak("Color must be number or arrayref or SDL::Color"); return retval; } SV *_color_number( SV *color, SV *alpha ) { int c = SvIV(color); int a = SvIV(alpha); unsigned int retval = SvUV(color); if( !SvOK(color) || color < 0 ) { if( color < 0 ) warn("Color was a negative number"); retval = a == 1 ? 0x000000FF : 0; } else { if( a == 1 && (c > 0xFFFFFFFF) ) { warn("Color was number greater than maximum expected: 0xFFFFFFFF"); retval = 0xFFFFFFFF; } else if ( a != 1 && ( c > 0xFFFFFF) ) { warn("Color was number greater than maximum expected: 0xFFFFFF"); retval = 0xFFFFFF; } } return newSVuv(retval); } /* returns a new mortal AV* */ AV *_color_arrayref( AV *color, SV *alpha ) { AV *retval = (AV*)sv_2mortal((SV*)newAV()); int length = SvTRUE(alpha) ? 4 : 3; int i = 0; for(i = 0; i < length; i++) { if( av_len(color) < i || !SvOK(AvARRAY(color)[i]) ) av_push(retval, newSVuv(i == 3 ? 0xFF : 0)); else { int c = SvIV(AvARRAY(color)[i]); if( c > 0xFF ) { warn("Number in color arrayref was greater than maximum expected: 0xFF"); av_push(retval, newSVuv(0xFF)); } else if( c < 0 ) { warn("Number in color arrayref was negative"); av_push(retval, newSVuv(0)); } else av_push(retval, newSVuv(c)); } } return retval; } /* returns a mortal AV* */ AV* __list_rgb( SV* color ) { char *format = _color_format(color); AV* RETVAL ; if ( 0 == strcmp("number", format) ) { RETVAL = (AV*)sv_2mortal( (SV *) newAV() ); unsigned int _color = SvUV(sv_2mortal(_color_number(color, newSVuv(0)))); av_push(RETVAL, newSVuv(_color >> 16 & 0xFF)); av_push(RETVAL, newSVuv(_color >> 8 & 0xFF)); av_push(RETVAL, newSVuv(_color & 0xFF)); } else if ( 0 == strcmp("arrayref", format) ) { /* _color_arrayref returns a mortal AV* */ RETVAL = _color_arrayref((AV *)SvRV(color), sv_2mortal(newSVuv(0))); } else if ( 0 == strcmp("SDL::Color", format) ) { RETVAL = (AV*)sv_2mortal((SV *) newAV() ); SDL_Color *_color = (SDL_Color *)bag2obj(color); av_push(RETVAL, newSVuv(_color->r)); av_push(RETVAL, newSVuv(_color->g)); av_push(RETVAL, newSVuv(_color->b)); } else { RETVAL = (AV*)sv_2mortal((SV *) newAV() ); av_push(RETVAL, newSVuv(0)); av_push(RETVAL, newSVuv(0)); av_push(RETVAL, newSVuv(0)); } return RETVAL; } AV* __list_rgba( SV* color ) { char *format = _color_format(color); AV* RETVAL ; if ( 0 == strcmp("number", format) ) { RETVAL = (AV*)sv_2mortal((SV *) newAV() ); unsigned int _color = SvUV(sv_2mortal(_color_number(color, sv_2mortal(newSVuv(1))))); av_push(RETVAL, newSVuv(_color >> 24 & 0xFF)); av_push(RETVAL, newSVuv(_color >> 16 & 0xFF)); av_push(RETVAL, newSVuv(_color >> 8 & 0xFF)); av_push(RETVAL, newSVuv(_color & 0xFF)); } else if ( 0 == strcmp("arrayref", format) ) { RETVAL = _color_arrayref((AV *)SvRV(color), sv_2mortal(newSVuv(1))); } else if ( 0 == strcmp("SDL::Color", format) ) { RETVAL = (AV*)sv_2mortal((SV *) newAV() ); SDL_Color *_color = (SDL_Color*)bag2obj(color); av_push(RETVAL, newSVuv(_color->r)); av_push(RETVAL, newSVuv(_color->g)); av_push(RETVAL, newSVuv(_color->b)); av_push(RETVAL, newSVuv(0xFF)); } else { RETVAL = (AV*)sv_2mortal((SV *) newAV() ); av_push(RETVAL, newSVuv(0)); av_push(RETVAL, newSVuv(0)); av_push(RETVAL, newSVuv(0)); av_push(RETVAL, newSVuv(0xFF)); } return RETVAL; } unsigned int __map_rgb( SV* color, SDL_PixelFormat* format ) { Uint8 r, g, b; AV* a = __list_rgb( color ); r = SvUV(*av_fetch(a, 0, 0)); g = SvUV(*av_fetch(a, 1, 0)); b = SvUV(*av_fetch(a, 2, 0)); return SDL_MapRGB( format, r, g, b ); } unsigned int __map_rgba( SV* color, SDL_PixelFormat* format ) { int r, g, b, a; AV* ar = __list_rgba( color ); r = SvUV(*av_fetch(ar, 0, 0)); g = SvUV(*av_fetch(ar, 1, 0)); b = SvUV(*av_fetch(ar, 2, 0)); a = SvUV(*av_fetch(ar, 3, 0)); return SDL_MapRGBA( format, r, g, b, a ); }