/* * $Id$ * * ***** BEGIN GPL/BL DUAL 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. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * 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/BL DUAL LICENSE BLOCK ***** */ #include "charRGBA.h" /* This file is heavily based on the old bpython Constant object code in Blender */ /*****************************************************************************/ /* Python charRGBA_Type callback function prototypes: */ /*****************************************************************************/ static void charRGBA_dealloc (BPy_charRGBA *self); static PyObject *charRGBA_getAttr (BPy_charRGBA *self, char *name); static int charRGBA_setAttr (BPy_charRGBA *self, char *name, PyObject *v); 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); /*****************************************************************************/ /* 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 */ }; /*****************************************************************************/ /* Python charRGBA_Type structure definition: */ /*****************************************************************************/ PyTypeObject charRGBA_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "charRGBA", /* tp_name */ sizeof (BPy_charRGBA), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ (destructor)charRGBA_dealloc, /* tp_dealloc */ 0, /* tp_print */ (getattrfunc)charRGBA_getAttr, /* tp_getattr */ (setattrfunc)charRGBA_setAttr, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)charRGBA_repr, /* tp_repr */ 0, /* tp_as_number */ &charRGBAAsSequence, /* tp_as_sequence */ &charRGBAAsMapping, /* tp_as_mapping */ 0, /* tp_as_hash */ 0,0,0,0,0,0, 0, /* tp_doc */ 0,0,0,0,0,0, 0, /* tp_methods */ 0, /* tp_members */ }; /*****************************************************************************/ /* Function: charRGBA_New */ /*****************************************************************************/ PyObject *charRGBA_New(char *rgba) { BPy_charRGBA *charRGBA; charRGBA_Type.ob_type = &PyType_Type; 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, Py_BuildValue ("b", *(self->rgba[0]) )); PyList_SET_ITEM (list, 1, Py_BuildValue ("b", *(self->rgba[1]) )); PyList_SET_ITEM (list, 2, Py_BuildValue ("b", *(self->rgba[2]) )); PyList_SET_ITEM (list, 3, Py_BuildValue ("b", *(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]) = EXPP_ClampInt (r, 0, 255); *(self->rgba[1]) = EXPP_ClampInt (g, 0, 255); *(self->rgba[2]) = EXPP_ClampInt (b, 0, 255); *(self->rgba[3]) = EXPP_ClampInt (a, 0, 255); return EXPP_incr_ret (Py_None); } /*****************************************************************************/ /* Function: charRGBA_dealloc */ /* Description: This is a callback function for the BPy_charRGBA type. It is */ /* the destructor function. */ /*****************************************************************************/ static void charRGBA_dealloc (BPy_charRGBA *self) { PyObject_DEL (self); } /*****************************************************************************/ /* Function: charRGBA_getAttr */ /* Description: This is a callback function for the BPy_charRGBA type. It is */ /* the function that accesses BPy_charRGBA member variables and */ /* methods. */ /*****************************************************************************/ static PyObject* charRGBA_getAttr (BPy_charRGBA *self, char *name) { int i; if (strcmp(name, "__members__") == 0) return Py_BuildValue("[s,s,s,s]", "R", "G", "B", "A"); else 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, "attribute not found")); return Py_BuildValue("b", *(self->rgba[i])); } /*****************************************************************************/ /* Function: charRGBA_setAttr */ /* Description: This is a callback function for the BPy_charRGBA type. It is */ /* the function that changes BPy_charRGBA member variables. */ /*****************************************************************************/ static int charRGBA_setAttr (BPy_charRGBA *self, char *name, PyObject *v) { char value; if (!PyArg_Parse (v, "b", &value)) return EXPP_ReturnIntError (PyExc_TypeError, "expected char argument"); value = EXPP_ClampInt(value, 0, 255); if (!strcmp(name, "R") || !strcmp(name, "r")) *(self->rgba[0]) = value; else if (!strcmp(name, "G") || !strcmp(name, "g")) *(self->rgba[1]) = value; else if (!strcmp(name, "B") || !strcmp(name, "b")) *(self->rgba[2]) = value; else if (!strcmp(name, "A") || !strcmp(name, "a")) *(self->rgba[3]) = value; else return (EXPP_ReturnIntError (PyExc_AttributeError, "attribute not found")); 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 Py_BuildValue("b", *(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]) = 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 Py_BuildValue("b", *(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]) = 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]) = 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); }