diff --git a/bindings/ruby/sfml-graphics/graphics/Color.cpp b/bindings/ruby/sfml-graphics/graphics/Color.cpp index cdac53e7a..0fc51cb91 100644 --- a/bindings/ruby/sfml-graphics/graphics/Color.cpp +++ b/bindings/ruby/sfml-graphics/graphics/Color.cpp @@ -26,15 +26,46 @@ VALUE globalColorClass; +/* Internal function + * Forces the argument someValue to be a Color. IF it can convert it then it will. + * So you can always safely asume that this function returns a Color object. + * If it fails then an exception will be thrown. + */ +VALUE Color_ForceType( VALUE someValue ) +{ + if( rb_obj_is_kind_of( someValue, rb_cArray ) == Qtrue ) + { + VALUE arg1 = rb_ary_entry( someValue, 0 ); + VALUE arg2 = rb_ary_entry( someValue, 1 ); + VALUE arg3 = rb_ary_entry( someValue, 2 ); + if( FIX2INT( rb_funcall( someValue, rb_intern( "size" ), 0 ) ) == 4 ) + { + VALUE arg4 = rb_ary_entry( someValue, 3 ); + return rb_funcall( globalColorClass, rb_intern( "new" ), 4, arg1, arg2, arg3, arg4 ); + } + + return rb_funcall( globalColorClass, rb_intern( "new" ), 3, arg1, arg2, arg3 ); + } + else if( rb_obj_is_kind_of( someValue, globalColorClass ) == Qtrue ) + { + return someValue; + } + else + { + rb_raise( rb_eRuntimeError, "expected Array or Color" ); + } +} + /* Internal function * Will copy the x and y from aSource to self. */ static void Color_internal_CopyFrom( VALUE self, VALUE aSource ) { - VALUE r = rb_funcall( aSource, rb_intern( "r" ), 0 ); - VALUE g = rb_funcall( aSource, rb_intern( "g" ), 0 ); - VALUE b = rb_funcall( aSource, rb_intern( "b" ), 0 ); - VALUE a = rb_funcall( aSource, rb_intern( "a" ), 0 ); + VALUE sourceVector = Color_ForceType( aSource ); + VALUE r = rb_funcall( sourceVector, rb_intern( "r" ), 0 ); + VALUE g = rb_funcall( sourceVector, rb_intern( "g" ), 0 ); + VALUE b = rb_funcall( sourceVector, rb_intern( "b" ), 0 ); + VALUE a = rb_funcall( sourceVector, rb_intern( "a" ), 0 ); rb_funcall( self, rb_intern( "r=" ), 1, r ); rb_funcall( self, rb_intern( "g=" ), 1, g ); @@ -42,6 +73,73 @@ static void Color_internal_CopyFrom( VALUE self, VALUE aSource ) rb_funcall( self, rb_intern( "a=" ), 1, a ); } +/* */ +static VALUE Color_Add( VALUE self, VALUE aRightOperand ) +{ + VALUE right = Color_ForceType( aRightOperand ); + // Get values + unsigned int leftR = FIX2INT( rb_funcall( self, rb_intern( "r" ), 0 ) ); + unsigned int leftG = FIX2INT( rb_funcall( self, rb_intern( "g" ), 0 ) ); + unsigned int leftB = FIX2INT( rb_funcall( self, rb_intern( "b" ), 0 ) ); + unsigned int leftA = FIX2INT( rb_funcall( self, rb_intern( "a" ), 0 ) ); + unsigned int rightR = FIX2INT( rb_funcall( right, rb_intern( "r" ), 0 ) ); + unsigned int rightG = FIX2INT( rb_funcall( right, rb_intern( "g" ), 0 ) ); + unsigned int rightB = FIX2INT( rb_funcall( right, rb_intern( "b" ), 0 ) ); + unsigned int rightA = FIX2INT( rb_funcall( right, rb_intern( "a" ), 0 ) ); + + // Do calculation + unsigned int newR = MIN( leftR + rightR, 255 ); + unsigned int newG = MIN( leftR + rightG, 255 ); + unsigned int newB = MIN( leftR + rightB, 255 ); + unsigned int newA = MIN( leftR + rightA, 255 ); + + return rb_funcall( globalColorClass, rb_intern( "new" ), 4, newR, newG, newB, newA ); +} + +/* */ +static VALUE Color_Multiply( VALUE self, VALUE aRightOperand ) +{ + VALUE right = Color_ForceType( aRightOperand ); + // Get values + unsigned int leftR = FIX2INT( rb_funcall( self, rb_intern( "r" ), 0 ) ); + unsigned int leftG = FIX2INT( rb_funcall( self, rb_intern( "g" ), 0 ) ); + unsigned int leftB = FIX2INT( rb_funcall( self, rb_intern( "b" ), 0 ) ); + unsigned int leftA = FIX2INT( rb_funcall( self, rb_intern( "a" ), 0 ) ); + unsigned int rightR = FIX2INT( rb_funcall( right, rb_intern( "r" ), 0 ) ); + unsigned int rightG = FIX2INT( rb_funcall( right, rb_intern( "g" ), 0 ) ); + unsigned int rightB = FIX2INT( rb_funcall( right, rb_intern( "b" ), 0 ) ); + unsigned int rightA = FIX2INT( rb_funcall( right, rb_intern( "a" ), 0 ) ); + + // Do calculation + unsigned int newR = ( leftR * rightR ) / 255; + unsigned int newG = ( leftR * rightG ) / 255; + unsigned int newB = ( leftR * rightB ) / 255; + unsigned int newA = ( leftR * rightA ) / 255; + + return rb_funcall( globalColorClass, rb_intern( "new" ), 4, newR, newG, newB, newA ); +} + +/* */ +static VALUE Color_Equal( VALUE self, VALUE anArgument ) +{ + VALUE right = Color_ForceType( anArgument ); + // Get values + unsigned int leftR = FIX2INT( rb_funcall( self, rb_intern( "r" ), 0 ) ); + unsigned int leftG = FIX2INT( rb_funcall( self, rb_intern( "g" ), 0 ) ); + unsigned int leftB = FIX2INT( rb_funcall( self, rb_intern( "b" ), 0 ) ); + unsigned int leftA = FIX2INT( rb_funcall( self, rb_intern( "a" ), 0 ) ); + unsigned int rightR = FIX2INT( rb_funcall( right, rb_intern( "r" ), 0 ) ); + unsigned int rightG = FIX2INT( rb_funcall( right, rb_intern( "g" ), 0 ) ); + unsigned int rightB = FIX2INT( rb_funcall( right, rb_intern( "b" ), 0 ) ); + unsigned int rightA = FIX2INT( rb_funcall( right, rb_intern( "a" ), 0 ) ); + + // Do calculation + if( leftR == rightR && leftG == rightG && leftB == rightB && leftA == rightA ) + { + return Qtrue; + } + return Qfalse; +} static VALUE Color_Initialize( int argc, VALUE * args, VALUE self ) { @@ -89,4 +187,13 @@ void Init_Color( void ) // Instance methods rb_define_method( globalColorClass, "initialize", Color_Initialize, -1 ); + rb_define_method( globalColorClass, "+", Color_Add, 1 ); + rb_define_method( globalColorClass, "*", Color_Multiply, 1 ); + rb_define_method( globalColorClass, "==", Color_Equal, 1 ); + + // Attribute accessors + rb_define_attr( globalColorClass, "r", 1, 1 ); + rb_define_attr( globalColorClass, "g", 1, 1 ); + rb_define_attr( globalColorClass, "b", 1, 1 ); + rb_define_attr( globalColorClass, "a", 1, 1 ); } diff --git a/bindings/ruby/sfml-graphics/graphics/main.hpp b/bindings/ruby/sfml-graphics/graphics/main.hpp index 5dc59fdf3..7583a16a9 100644 --- a/bindings/ruby/sfml-graphics/graphics/main.hpp +++ b/bindings/ruby/sfml-graphics/graphics/main.hpp @@ -30,6 +30,9 @@ extern "C" void Init_graphics( void ); typedef VALUE ( *RubyFunctionPtr )( ... ); +#define MAX( x, y ) ( ( x ) < ( y ) ? ( y ) : ( x ) ) +#define MIN( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) + #define VALIDATE_CLASS( variable, type, name ) \ if( rb_obj_is_kind_of( variable, type ) != Qtrue ) \ { \