/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * This is a new part of Blender. * * Contributor(s): Willian P. Germano * * ***** END GPL LICENSE BLOCK ***** */ #include "charRGBA.h" /*This must come first */ #include "gen_utils.h" /* This file is heavily based on the old bpython Constant object code in Blender */ /*****************************************************************************/ /* Python charRGBA_Type callback function prototypes: */ /*****************************************************************************/ static PyObject *charRGBA_repr( BPy_charRGBA * self ); static int charRGBALength( BPy_charRGBA * self ); static PyObject *charRGBASubscript( BPy_charRGBA * self, PyObject * key ); static int charRGBAAssSubscript( BPy_charRGBA * self, PyObject * who, PyObject * cares ); static PyObject *charRGBAItem( BPy_charRGBA * self, int i ); static int charRGBAAssItem( BPy_charRGBA * self, int i, PyObject * ob ); static PyObject *charRGBASlice( BPy_charRGBA * self, int begin, int end ); static int charRGBAAssSlice( BPy_charRGBA * self, int begin, int end, PyObject * seq ); static PyObject *charRGBA_getColor( BPy_charRGBA * self, void * type); static int charRGBA_setColor( BPy_charRGBA * self, PyObject * value, void * type); /*****************************************************************************/ /* Python charRGBA_Type Mapping Methods table: */ /*****************************************************************************/ static PyMappingMethods charRGBAAsMapping = { ( inquiry ) charRGBALength, /* mp_length */ ( binaryfunc ) charRGBASubscript, /* mp_subscript */ ( objobjargproc ) charRGBAAssSubscript, /* mp_ass_subscript */ }; /*****************************************************************************/ /* Python charRGBA_Type Sequence Methods table: */ /*****************************************************************************/ static PySequenceMethods charRGBAAsSequence = { ( inquiry ) charRGBALength, /* sq_length */ ( binaryfunc ) 0, /* sq_concat */ ( intargfunc ) 0, /* sq_repeat */ ( intargfunc ) charRGBAItem, /* sq_item */ ( intintargfunc ) charRGBASlice, /* sq_slice */ ( intobjargproc ) charRGBAAssItem, /* sq_ass_item */ ( intintobjargproc ) charRGBAAssSlice, /* sq_ass_slice */ }; static PyGetSetDef charRGBA_getseters[] = { {"R", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the red component", (void *) 0}, {"r", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the red component", (void *) 0}, {"G", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the green component", (void *) 1}, {"g", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the green component", (void *) 1}, {"B", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the blue component", (void *) 2}, {"b", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the blue component", (void *) 2}, {"A", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the alpha component", (void *) 3}, {"a", (getter)charRGBA_getColor, (setter)charRGBA_setColor, "the alpha component", (void *) 3}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; /*****************************************************************************/ /* Python charRGBA_Type structure definition: */ /*****************************************************************************/ PyTypeObject charRGBA_Type = { PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /* ob_size */ /* For printing, in format "." */ "charRGBA", /* tp_name */ sizeof( BPy_charRGBA ), /* tp_basicsize */ 0, /* tp_itemsize; For allocation */ /* Methods to implement standard operations */ NULL, /* destructor tp_dealloc; */ NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ NULL, /* cmpfunc tp_compare; */ ( reprfunc ) charRGBA_repr, /* reprfunc tp_repr; */ /* Method suites for standard classes */ NULL, /* PyNumberMethods *tp_as_number; */ &charRGBAAsSequence, /* PySequenceMethods *tp_as_sequence; */ &charRGBAAsMapping, /* PyMappingMethods *tp_as_mapping; */ /* More standard operations (here for binary compatibility) */ NULL, /* hashfunc tp_hash; */ NULL, /* ternaryfunc tp_call; */ NULL, /* reprfunc tp_str; */ NULL, /* getattrofunc tp_getattro; */ NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ NULL, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ Py_TPFLAGS_DEFAULT, /* long tp_flags; */ NULL, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ NULL, /* traverseproc tp_traverse; */ /* delete references to contained objects */ NULL, /* inquiry tp_clear; */ /*** Assigned meaning in release 2.1 ***/ /*** rich comparisons ***/ NULL, /* richcmpfunc tp_richcompare; */ /*** weak reference enabler ***/ 0, /* long tp_weaklistoffset; */ /*** Added in release 2.2 ***/ /* Iterators */ NULL, /* getiterfunc tp_iter; */ NULL, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ NULL, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ charRGBA_getseters, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ NULL, /* descrsetfunc tp_descr_set; */ 0, /* long tp_dictoffset; */ NULL, /* initproc tp_init; */ NULL, /* allocfunc tp_alloc; */ NULL, /* newfunc tp_new; */ /* Low-level free-memory routine */ NULL, /* freefunc tp_free; */ /* For PyObject_IS_GC */ NULL, /* inquiry tp_is_gc; */ NULL, /* PyObject *tp_bases; */ /* method resolution order */ NULL, /* PyObject *tp_mro; */ NULL, /* PyObject *tp_cache; */ NULL, /* PyObject *tp_subclasses; */ NULL, /* PyObject *tp_weaklist; */ NULL }; /*****************************************************************************/ /* Function: charRGBA_New */ /*****************************************************************************/ PyObject *charRGBA_New( char *rgba ) { BPy_charRGBA *charRGBA = NULL; /* * When called the first time, charRGBA_Type.tp_dealloc will be NULL. * If that's the case, initialize the PyTypeObject. If the * initialization succeeds, then create a new object. */ if( charRGBA_Type.tp_dealloc || PyType_Ready( &charRGBA_Type ) >= 0 ) { charRGBA = ( BPy_charRGBA * ) PyObject_NEW( BPy_charRGBA, &charRGBA_Type ); } if( charRGBA == NULL ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create charRGBA object" ); /* rgba is a pointer to the first item of a char[4] array */ charRGBA->rgba[0] = &rgba[0]; charRGBA->rgba[1] = &rgba[1]; charRGBA->rgba[2] = &rgba[2]; charRGBA->rgba[3] = &rgba[3]; return ( PyObject * ) charRGBA; } /*****************************************************************************/ /* Functions: charRGBA_getCol and charRGBA_setCol */ /* Description: These functions get/set rgba color triplet values. The */ /* get function returns a tuple, the set one accepts three */ /* chars (separated or in a tuple) as arguments. */ /*****************************************************************************/ PyObject *charRGBA_getCol( BPy_charRGBA * self ) { PyObject *list = PyList_New( 4 ); if( !list ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyList" ); PyList_SET_ITEM( list, 0, PyInt_FromLong( *(self->rgba[0])) ); PyList_SET_ITEM( list, 1, PyInt_FromLong( *(self->rgba[1])) ); PyList_SET_ITEM( list, 2, PyInt_FromLong( *(self->rgba[2])) ); PyList_SET_ITEM( list, 3, PyInt_FromLong( *(self->rgba[3])) ); return list; } PyObject *charRGBA_setCol( BPy_charRGBA * self, PyObject * args ) { int ok; char r = 0, g = 0, b = 0, a = 0; if( PyObject_Length( args ) == 4 ) ok = PyArg_ParseTuple( args, "bbbb", &r, &g, &b, &a ); else ok = PyArg_ParseTuple( args, "|(bbbb)", &r, &g, &b, &a ); if( !ok ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 1-byte ints [b,b,b,b] or b,b,b,b as arguments (or nothing)" ); *( self->rgba[0] ) = (char)EXPP_ClampInt( r, 0, 255 ); *( self->rgba[1] ) = (char)EXPP_ClampInt( g, 0, 255 ); *( self->rgba[2] ) = (char)EXPP_ClampInt( b, 0, 255 ); *( self->rgba[3] ) = (char)EXPP_ClampInt( a, 0, 255 ); return EXPP_incr_ret( Py_None ); } /* return color value for one of the components */ static PyObject *charRGBA_getColor( BPy_charRGBA * self, void * type) { int index = ((long)type) & 3; return PyInt_FromLong ( *self->rgba[index] ); } /* sets the color value of one of the components */ static int charRGBA_setColor( BPy_charRGBA * self, PyObject * value, void * type) { int index = ((long)type) & 3; PyObject *num = PyNumber_Int( value ); /* argument must be a number */ if( !num ) return EXPP_ReturnIntError( PyExc_TypeError, "expected char argument" ); /* clamp valut to 0..255 then assign */ *self->rgba[index] = (char)EXPP_ClampInt( (int)PyInt_AS_LONG(value), 0, 255 ); Py_DECREF( num ); return 0; } /*****************************************************************************/ /* Section: charRGBA as Mapping */ /* These functions provide code to access charRGBA objects as */ /* mappings. */ /*****************************************************************************/ static int charRGBALength( BPy_charRGBA * self ) { return 4; } static PyObject *charRGBASubscript( BPy_charRGBA * self, PyObject * key ) { char *name = NULL; int i; if( PyNumber_Check( key ) ) return charRGBAItem( self, ( int ) PyInt_AsLong( key ) ); if( !PyArg_ParseTuple( key, "s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected int or string argument" ); if( !strcmp( name, "R" ) || !strcmp( name, "r" ) ) i = 0; else if( !strcmp( name, "G" ) || !strcmp( name, "g" ) ) i = 1; else if( !strcmp( name, "B" ) || !strcmp( name, "b" ) ) i = 2; else if( !strcmp( name, "A" ) || !strcmp( name, "a" ) ) i = 3; else return EXPP_ReturnPyObjError( PyExc_AttributeError, name ); return PyInt_FromLong( (long)(*self->rgba[i]) ); } static int charRGBAAssSubscript( BPy_charRGBA * self, PyObject * key, PyObject * v ) { char *name = NULL; int i; if( !PyNumber_Check( v ) ) return EXPP_ReturnIntError( PyExc_TypeError, "value to assign must be a number" ); if( PyNumber_Check( key ) ) return charRGBAAssItem( self, ( int ) PyInt_AsLong( key ), v ); if( !PyArg_Parse( key, "s", &name ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected int or string argument" ); if( !strcmp( name, "R" ) || !strcmp( name, "r" ) ) i = 0; else if( !strcmp( name, "G" ) || !strcmp( name, "g" ) ) i = 1; else if( !strcmp( name, "B" ) || !strcmp( name, "b" ) ) i = 2; else if( !strcmp( name, "A" ) || !strcmp( name, "a" ) ) i = 3; else return EXPP_ReturnIntError( PyExc_AttributeError, name ); *( self->rgba[i] ) = (char)EXPP_ClampInt( PyInt_AsLong( v ), 0, 255 ); return 0; } /*****************************************************************************/ /* Section: charRGBA as Sequence */ /* These functions provide code to access charRGBA objects as */ /* sequences. */ /*****************************************************************************/ static PyObject *charRGBAItem( BPy_charRGBA * self, int i ) { if( i < 0 || i >= 4 ) return EXPP_ReturnPyObjError( PyExc_IndexError, "array index out of range" ); return PyInt_FromLong( *(self->rgba[i]) ); } static PyObject *charRGBASlice( BPy_charRGBA * self, int begin, int end ) { PyObject *list; int count; if( begin < 0 ) begin = 0; if( end > 4 ) end = 4; if( begin > end ) begin = end; list = PyList_New( end - begin ); for( count = begin; count < end; count++ ) PyList_SetItem( list, count - begin, PyInt_FromLong( *( self->rgba[count] ) ) ); return list; } static int charRGBAAssItem( BPy_charRGBA * self, int i, PyObject * ob ) { if( i < 0 || i >= 4 ) return EXPP_ReturnIntError( PyExc_IndexError, "array assignment index out of range" ); if( !PyNumber_Check( ob ) ) return EXPP_ReturnIntError( PyExc_IndexError, "color component must be a number" ); *( self->rgba[i] ) = (char)EXPP_ClampInt( PyInt_AsLong( ob ), 0, 255 ); return 0; } static int charRGBAAssSlice( BPy_charRGBA * self, int begin, int end, PyObject * seq ) { int count; if( begin < 0 ) begin = 0; if( end > 4 ) end = 4; if( begin > end ) begin = end; if( !PySequence_Check( seq ) ) return EXPP_ReturnIntError( PyExc_TypeError, "illegal argument type for built-in operation" ); if( PySequence_Length( seq ) != ( end - begin ) ) return EXPP_ReturnIntError( PyExc_TypeError, "size mismatch in slice assignment" ); for( count = begin; count < end; count++ ) { char value; PyObject *ob = PySequence_GetItem( seq, count ); if( !PyArg_Parse( ob, "b", &value ) ) { Py_DECREF( ob ); return -1; } *( self->rgba[count] ) = (char)EXPP_ClampInt( value, 0, 255 ); Py_DECREF( ob ); } return 0; } /*****************************************************************************/ /* Function: charRGBA_repr */ /* Description: This is a callback function for the BPy_charRGBA type. It */ /* builds a meaninful string to represent charRGBA objects. */ /*****************************************************************************/ static PyObject *charRGBA_repr( BPy_charRGBA * self ) { char r, g, b, a; r = *( self->rgba[0] ); g = *( self->rgba[1] ); b = *( self->rgba[2] ); a = *( self->rgba[3] ); return PyString_FromFormat( "[%d, %d, %d, %d]", r, g, b, a ); }