2006-07-17 11:37:28 +08:00
|
|
|
/* -*- Mode: C; c-basic-offset: 4 -*-
|
2009-01-18 06:28:01 +08:00
|
|
|
* Gimp-Python - allows the writing of Gimp plugins in Python.
|
|
|
|
* Copyright (C) 2005-2006 Manish Singh <yosh@gimp.org>
|
|
|
|
*
|
|
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
2006-07-17 11:37:28 +08:00
|
|
|
*/
|
|
|
|
|
2005-06-04 08:17:06 +08:00
|
|
|
#define NO_IMPORT_PYGOBJECT
|
|
|
|
|
2008-07-03 19:39:52 +08:00
|
|
|
#include "pygimp.h"
|
2005-06-04 08:17:06 +08:00
|
|
|
#include "pygimpcolor.h"
|
|
|
|
|
2006-07-17 11:37:28 +08:00
|
|
|
#include <libgimpmath/gimpmath.h>
|
|
|
|
|
2005-06-04 08:17:06 +08:00
|
|
|
static PyObject *
|
|
|
|
rgb_set(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *r = NULL, *g = NULL, *b = NULL, *a = NULL;
|
|
|
|
GimpRGB tmprgb, *rgb;
|
|
|
|
static char *kwlist[] = { "r", "g", "b", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO:set", kwlist,
|
|
|
|
&r, &g, &b, &a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!r && !g && !b && !a) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide r,g,b or a arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((r && (!g || !b)) ||
|
|
|
|
(g && (!r || !b)) ||
|
|
|
|
(b && (!r || !g))) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide all 3 r,g,b arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
tmprgb = *rgb;
|
|
|
|
|
|
|
|
#define SET_MEMBER(m) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
tmprgb.m = (double) PyInt_AS_LONG(m) / 255.0; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
|
|
|
tmprgb.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be an int or a float"); \
|
|
|
|
return NULL; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
if (r) {
|
|
|
|
SET_MEMBER(r);
|
|
|
|
SET_MEMBER(g);
|
|
|
|
SET_MEMBER(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
SET_MEMBER(a);
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
*rgb = tmprgb;
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_set_alpha(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *py_a;
|
|
|
|
GimpRGB *rgb;
|
|
|
|
static char *kwlist[] = { "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"O:set_alpha", kwlist,
|
|
|
|
&py_a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
if (PyInt_Check(py_a))
|
|
|
|
rgb->a = (double) PyInt_AS_LONG(py_a) / 255.0;
|
|
|
|
else if (PyFloat_Check(py_a))
|
|
|
|
rgb->a = PyFloat_AS_DOUBLE(py_a);
|
|
|
|
else {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "a must be an int or a float");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_add(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *color;
|
|
|
|
gboolean with_alpha = FALSE;
|
|
|
|
static char *kwlist[] = { "color", "with_alpha", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|i:add", kwlist,
|
|
|
|
&PyGimpRGB_Type, &color, &with_alpha))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (with_alpha)
|
|
|
|
gimp_rgba_add(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB));
|
|
|
|
else
|
|
|
|
gimp_rgb_add(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB));
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_subtract(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *color;
|
|
|
|
gboolean with_alpha = FALSE;
|
|
|
|
static char *kwlist[] = { "color", "with_alpha", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|i:subtract", kwlist,
|
|
|
|
&PyGimpRGB_Type, &color, &with_alpha))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (with_alpha)
|
|
|
|
gimp_rgba_subtract(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB));
|
|
|
|
else
|
|
|
|
gimp_rgb_subtract(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB));
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_multiply(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
double factor;
|
|
|
|
gboolean with_alpha = FALSE;
|
|
|
|
static char *kwlist[] = { "factor", "with_alpha", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|i:multiply", kwlist,
|
|
|
|
&factor, &with_alpha))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (with_alpha)
|
|
|
|
gimp_rgba_multiply(pyg_boxed_get(self, GimpRGB), factor);
|
|
|
|
else
|
|
|
|
gimp_rgb_multiply(pyg_boxed_get(self, GimpRGB), factor);
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_distance(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *color;
|
|
|
|
gboolean alpha = FALSE;
|
|
|
|
double ret;
|
|
|
|
static char *kwlist[] = { "color", "alpha", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|i:distance", kwlist,
|
|
|
|
&PyGimpRGB_Type, &color, &alpha))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret = gimp_rgb_distance(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB));
|
|
|
|
|
|
|
|
|
|
|
|
return PyFloat_FromDouble(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_max(PyObject *self)
|
|
|
|
{
|
|
|
|
return PyFloat_FromDouble(gimp_rgb_max(pyg_boxed_get(self, GimpRGB)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_min(PyObject *self)
|
|
|
|
{
|
|
|
|
return PyFloat_FromDouble(gimp_rgb_min(pyg_boxed_get(self, GimpRGB)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_clamp(PyObject *self)
|
|
|
|
{
|
|
|
|
gimp_rgb_clamp(pyg_boxed_get(self, GimpRGB));
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_gamma(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
double gamma;
|
|
|
|
static char *kwlist[] = { "gamma", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d:gamma", kwlist, &gamma))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
gimp_rgb_gamma(pyg_boxed_get(self, GimpRGB), gamma);
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
2005-08-03 08:36:41 +08:00
|
|
|
static PyObject *
|
|
|
|
rgb_luminance(PyObject *self)
|
|
|
|
{
|
|
|
|
return PyFloat_FromDouble(gimp_rgb_luminance(pyg_boxed_get(self, GimpRGB)));
|
|
|
|
}
|
|
|
|
|
2005-06-04 08:17:06 +08:00
|
|
|
static PyObject *
|
|
|
|
rgb_composite(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *color;
|
|
|
|
int mode = GIMP_RGB_COMPOSITE_NORMAL;
|
2006-07-20 12:53:47 +08:00
|
|
|
static char *kwlist[] = { "color", "mode", NULL };
|
2005-06-04 08:17:06 +08:00
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"O!|i:composite", kwlist,
|
|
|
|
&PyGimpRGB_Type, &color, &mode))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (mode < GIMP_RGB_COMPOSITE_NONE || mode > GIMP_RGB_COMPOSITE_BEHIND) {
|
2005-08-03 08:36:41 +08:00
|
|
|
PyErr_SetString(PyExc_TypeError, "composite type is not valid");
|
2005-06-04 08:17:06 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_rgb_composite(pyg_boxed_get(self, GimpRGB),
|
|
|
|
pyg_boxed_get(color, GimpRGB),
|
|
|
|
mode);
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_parse_name(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int len;
|
|
|
|
gboolean success;
|
|
|
|
static char *kwlist[] = { "name", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:parse_name", kwlist,
|
|
|
|
&name, &len))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
success = gimp_rgb_parse_name(pyg_boxed_get(self, GimpRGB), name, len);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "unable to parse color name");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_parse_hex(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
char *hex;
|
|
|
|
int len;
|
|
|
|
gboolean success;
|
|
|
|
static char *kwlist[] = { "hex", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:parse_hex", kwlist,
|
|
|
|
&hex, &len))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
success = gimp_rgb_parse_hex(pyg_boxed_get(self, GimpRGB), hex, len);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "unable to parse hex value");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_parse_css(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
char *css;
|
|
|
|
int len;
|
|
|
|
gboolean success, with_alpha = FALSE;
|
|
|
|
static char *kwlist[] = { "css", "with_alpha", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"s#|i:parse_css", kwlist,
|
|
|
|
&css, &len, &with_alpha))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (with_alpha)
|
|
|
|
success = gimp_rgba_parse_css(pyg_boxed_get(self, GimpRGB), css, len);
|
|
|
|
else
|
|
|
|
success = gimp_rgb_parse_css(pyg_boxed_get(self, GimpRGB), css, len);
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
PyErr_SetString(PyExc_ValueError, "unable to parse CSS color");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static PyObject *
|
|
|
|
rgb_to_hsv(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
GimpHSV hsv;
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
gimp_rgb_to_hsv(rgb, &hsv);
|
|
|
|
|
|
|
|
return pygimp_hsv_new(&hsv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_to_hsl(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
GimpHSL hsl;
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
gimp_rgb_to_hsl(rgb, &hsl);
|
|
|
|
|
|
|
|
return pygimp_hsl_new(&hsl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_to_cmyk(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
GimpCMYK cmyk;
|
|
|
|
gdouble pullout = 1.0;
|
|
|
|
static char *kwlist[] = { "pullout", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"|d:to_cmyk", kwlist,
|
|
|
|
&pullout))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
gimp_rgb_to_cmyk(rgb, pullout, &cmyk);
|
|
|
|
|
|
|
|
return pygimp_cmyk_new(&cmyk);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* __getstate__ isn't exposed */
|
|
|
|
static PyObject *
|
|
|
|
rgb_getstate(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
return Py_BuildValue("dddd", rgb->r, rgb->g, rgb->b, rgb->a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_reduce(PyObject *self)
|
|
|
|
{
|
|
|
|
return Py_BuildValue("ON", self->ob_type, rgb_getstate(self));
|
|
|
|
}
|
|
|
|
|
2005-06-04 08:17:06 +08:00
|
|
|
static PyMethodDef rgb_methods[] = {
|
|
|
|
{ "set", (PyCFunction)rgb_set, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "set_alpha", (PyCFunction)rgb_set_alpha, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "add", (PyCFunction)rgb_add, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "subtract", (PyCFunction)rgb_subtract, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "multiply", (PyCFunction)rgb_multiply, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "distance", (PyCFunction)rgb_distance, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "max", (PyCFunction)rgb_max, METH_NOARGS },
|
|
|
|
{ "min", (PyCFunction)rgb_min, METH_NOARGS },
|
|
|
|
{ "clamp", (PyCFunction)rgb_clamp, METH_NOARGS },
|
|
|
|
{ "gamma", (PyCFunction)rgb_gamma, METH_VARARGS|METH_KEYWORDS },
|
2005-08-03 08:36:41 +08:00
|
|
|
{ "luminance", (PyCFunction)rgb_luminance, METH_NOARGS },
|
2005-06-04 08:17:06 +08:00
|
|
|
{ "composite", (PyCFunction)rgb_composite, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "parse_name", (PyCFunction)rgb_parse_name, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "parse_hex", (PyCFunction)rgb_parse_hex, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "parse_css", (PyCFunction)rgb_parse_css, METH_VARARGS|METH_KEYWORDS },
|
2006-07-20 12:53:47 +08:00
|
|
|
{ "to_hsv", (PyCFunction)rgb_to_hsv, METH_NOARGS },
|
|
|
|
{ "to_hsl", (PyCFunction)rgb_to_hsl, METH_NOARGS },
|
|
|
|
{ "to_cmyk", (PyCFunction)rgb_to_cmyk, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "__reduce__", (PyCFunction)rgb_reduce, METH_NOARGS },
|
2005-06-04 08:17:06 +08:00
|
|
|
{ NULL, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MEMBER_ACCESSOR(m) \
|
|
|
|
static PyObject * \
|
|
|
|
rgb_get_ ## m(PyObject *self, void *closure) \
|
|
|
|
{ \
|
|
|
|
return PyFloat_FromDouble(pyg_boxed_get(self, GimpRGB)->m); \
|
|
|
|
} \
|
|
|
|
static int \
|
|
|
|
rgb_set_ ## m(PyObject *self, PyObject *value, void *closure) \
|
|
|
|
{ \
|
|
|
|
GimpRGB *rgb = pyg_boxed_get(self, GimpRGB); \
|
|
|
|
if (value == NULL) { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "cannot delete value"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
else if (PyInt_Check(value)) \
|
|
|
|
rgb->m = (double) PyInt_AS_LONG(value) / 255.0; \
|
|
|
|
else if (PyFloat_Check(value)) \
|
|
|
|
rgb->m = PyFloat_AS_DOUBLE(value); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "type mismatch"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
|
|
|
MEMBER_ACCESSOR(r);
|
|
|
|
MEMBER_ACCESSOR(g);
|
|
|
|
MEMBER_ACCESSOR(b);
|
|
|
|
MEMBER_ACCESSOR(a);
|
|
|
|
|
|
|
|
#undef MEMBER_ACCESSOR
|
|
|
|
|
|
|
|
static PyGetSetDef rgb_getsets[] = {
|
|
|
|
{ "r", (getter)rgb_get_r, (setter)rgb_set_r },
|
|
|
|
{ "g", (getter)rgb_get_g, (setter)rgb_set_g },
|
|
|
|
{ "b", (getter)rgb_get_b, (setter)rgb_set_b },
|
|
|
|
{ "a", (getter)rgb_get_a, (setter)rgb_set_a },
|
|
|
|
{ "red", (getter)rgb_get_r, (setter)rgb_set_r },
|
|
|
|
{ "green", (getter)rgb_get_g, (setter)rgb_set_g },
|
|
|
|
{ "blue", (getter)rgb_get_b, (setter)rgb_set_b },
|
|
|
|
{ "alpha", (getter)rgb_get_a, (setter)rgb_set_a },
|
|
|
|
{ NULL, (getter)0, (setter)0 },
|
|
|
|
};
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
static Py_ssize_t
|
2006-07-17 11:37:28 +08:00
|
|
|
rgb_length(PyObject *self)
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
rgb_getitem(PyObject *self, Py_ssize_t pos)
|
2006-07-17 11:37:28 +08:00
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
double val;
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
2006-07-17 11:37:28 +08:00
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: val = rgb->r; break;
|
|
|
|
case 1: val = rgb->g; break;
|
|
|
|
case 2: val = rgb->b; break;
|
|
|
|
case 3: val = rgb->a; break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PyInt_FromLong(ROUND(CLAMP(val, 0.0, 1.0) * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2008-07-03 19:39:52 +08:00
|
|
|
rgb_setitem(PyObject *self, Py_ssize_t pos, PyObject *value)
|
2006-07-17 11:37:28 +08:00
|
|
|
{
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: return rgb_set_r(self, value, NULL);
|
|
|
|
case 1: return rgb_set_g(self, value, NULL);
|
|
|
|
case 2: return rgb_set_b(self, value, NULL);
|
|
|
|
case 3: return rgb_set_a(self, value, NULL);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
rgb_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end)
|
2006-10-11 14:02:23 +08:00
|
|
|
{
|
|
|
|
PyTupleObject *ret;
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t i;
|
2006-10-11 14:02:23 +08:00
|
|
|
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
if (end > 4)
|
|
|
|
end = 4;
|
|
|
|
if (end < start)
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
ret = (PyTupleObject *)PyTuple_New(end - start);
|
|
|
|
if (ret == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = start; i < end; i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i - start, rgb_getitem(self, i));
|
|
|
|
|
|
|
|
return (PyObject *)ret;
|
|
|
|
}
|
|
|
|
|
2006-07-17 11:37:28 +08:00
|
|
|
static PySequenceMethods rgb_as_sequence = {
|
2008-07-03 19:39:52 +08:00
|
|
|
rgb_length,
|
2006-07-17 11:37:28 +08:00
|
|
|
(binaryfunc)0,
|
2008-07-03 19:39:52 +08:00
|
|
|
0,
|
|
|
|
rgb_getitem,
|
|
|
|
rgb_slice,
|
|
|
|
rgb_setitem,
|
|
|
|
0,
|
2006-07-17 11:37:28 +08:00
|
|
|
(objobjproc)0,
|
|
|
|
};
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
|
|
|
rgb_subscript(PyObject *self, PyObject *item)
|
|
|
|
{
|
|
|
|
if (PyInt_Check(item)) {
|
|
|
|
long i = PyInt_AS_LONG(item);
|
|
|
|
return rgb_getitem(self, i);
|
|
|
|
} else if (PyLong_Check(item)) {
|
|
|
|
long i = PyLong_AsLong(item);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return NULL;
|
|
|
|
return rgb_getitem(self, i);
|
|
|
|
} else if (PySlice_Check(item)) {
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
2006-10-11 14:02:23 +08:00
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, 4,
|
|
|
|
&start, &stop, &step, &slicelength) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (slicelength <= 0) {
|
|
|
|
return PyTuple_New(0);
|
|
|
|
} else {
|
|
|
|
ret = PyTuple_New(slicelength);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i, rgb_getitem(self, cur));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
} else if (PyString_Check(item)) {
|
|
|
|
char *s = PyString_AsString(item);
|
|
|
|
|
|
|
|
if (g_ascii_strcasecmp(s, "r") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "red") == 0)
|
|
|
|
return rgb_get_r(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "g") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "green") == 0)
|
|
|
|
return rgb_get_g(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "b") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "blue") == 0)
|
|
|
|
return rgb_get_b(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "a") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "alpha") == 0)
|
|
|
|
return rgb_get_a(self, NULL);
|
|
|
|
else {
|
|
|
|
PyErr_SetObject(PyExc_KeyError, item);
|
|
|
|
return NULL;
|
2008-09-04 16:37:32 +08:00
|
|
|
}
|
2006-10-11 14:02:23 +08:00
|
|
|
} else {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"indices must be integers");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMappingMethods rgb_as_mapping = {
|
2008-07-03 19:39:52 +08:00
|
|
|
rgb_length,
|
2006-10-11 14:02:23 +08:00
|
|
|
(binaryfunc)rgb_subscript,
|
|
|
|
(objobjargproc)0
|
|
|
|
};
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static long
|
|
|
|
rgb_hash(PyObject *self)
|
|
|
|
{
|
|
|
|
long ret = -1;
|
|
|
|
|
|
|
|
PyObject *temp = rgb_getstate(self);
|
|
|
|
if (temp != NULL) {
|
|
|
|
ret = PyObject_Hash(temp);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_richcompare(PyObject *self, PyObject *other, int op)
|
|
|
|
{
|
|
|
|
GimpRGB *c1, *c2;
|
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (!pygimp_rgb_check(other)) {
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can't compare %s to %s",
|
|
|
|
self->ob_type->tp_name, other->ob_type->tp_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op != Py_EQ && op != Py_NE) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"can't compare color values using <, <=, >, >=");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = pyg_boxed_get(self, GimpRGB);
|
|
|
|
c2 = pyg_boxed_get(other, GimpRGB);
|
|
|
|
|
|
|
|
if ((c1->r == c2->r && c1->g == c2->g && c1->b == c2->b && c1->a == c2->a) == (op == Py_EQ))
|
|
|
|
ret = Py_True;
|
|
|
|
else
|
|
|
|
ret = Py_False;
|
|
|
|
|
|
|
|
Py_INCREF(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_pretty_print(PyObject *self, gboolean inexact)
|
|
|
|
{
|
|
|
|
GimpRGB *rgb;
|
|
|
|
PyObject *ret = NULL;
|
|
|
|
PyObject *r_f = NULL, *g_f = NULL, *b_f = NULL, *a_f = NULL;
|
|
|
|
PyObject *r = NULL, *g = NULL, *b = NULL, *a = NULL;
|
|
|
|
reprfunc repr;
|
2008-08-14 05:10:17 +08:00
|
|
|
const char *prefix;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (inexact) {
|
|
|
|
repr = PyObject_Str;
|
|
|
|
prefix = "RGB ";
|
|
|
|
} else {
|
|
|
|
repr = PyObject_Repr;
|
|
|
|
prefix = self->ob_type->tp_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
rgb = pyg_boxed_get(self, GimpRGB);
|
|
|
|
|
|
|
|
if ((r_f = PyFloat_FromDouble(rgb->r)) == NULL) goto cleanup;
|
|
|
|
if ((g_f = PyFloat_FromDouble(rgb->g)) == NULL) goto cleanup;
|
|
|
|
if ((b_f = PyFloat_FromDouble(rgb->b)) == NULL) goto cleanup;
|
|
|
|
if ((a_f = PyFloat_FromDouble(rgb->a)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
if ((r = repr(r_f)) == NULL) goto cleanup;
|
|
|
|
if ((g = repr(g_f)) == NULL) goto cleanup;
|
|
|
|
if ((b = repr(b_f)) == NULL) goto cleanup;
|
|
|
|
if ((a = repr(a_f)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
ret = PyString_FromFormat("%s(%s, %s, %s, %s)",
|
|
|
|
prefix,
|
|
|
|
PyString_AsString(r),
|
|
|
|
PyString_AsString(g),
|
|
|
|
PyString_AsString(b),
|
|
|
|
PyString_AsString(a));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
Py_XDECREF(r); Py_XDECREF(g); Py_XDECREF(b); Py_XDECREF(a);
|
|
|
|
Py_XDECREF(r_f); Py_XDECREF(g_f); Py_XDECREF(b_f); Py_XDECREF(a_f);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_repr(PyObject *self)
|
|
|
|
{
|
|
|
|
return rgb_pretty_print(self, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
rgb_str(PyObject *self)
|
|
|
|
{
|
|
|
|
return rgb_pretty_print(self, TRUE);
|
|
|
|
}
|
2006-07-17 11:37:28 +08:00
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
static int
|
2005-06-04 08:17:06 +08:00
|
|
|
rgb_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *r, *g, *b, *a = NULL;
|
|
|
|
GimpRGB rgb;
|
|
|
|
static char *kwlist[] = { "r", "g", "b", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"OOO|O:set", kwlist,
|
|
|
|
&r, &g, &b, &a))
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1;
|
2005-06-04 08:17:06 +08:00
|
|
|
|
|
|
|
#define SET_MEMBER(m) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
rgb.m = (double) PyInt_AS_LONG(m) / 255.0; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
|
|
|
rgb.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be an int or a float"); \
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1; \
|
2005-06-04 08:17:06 +08:00
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
SET_MEMBER(r);
|
|
|
|
SET_MEMBER(g);
|
|
|
|
SET_MEMBER(b);
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
SET_MEMBER(a);
|
|
|
|
else
|
|
|
|
rgb.a = 1.0;
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
self->gtype = GIMP_TYPE_RGB;
|
|
|
|
self->free_on_dealloc = TRUE;
|
|
|
|
self->boxed = g_boxed_copy(GIMP_TYPE_RGB, &rgb);
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
return 0;
|
2005-06-04 08:17:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyTypeObject PyGimpRGB_Type = {
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
0, /* ob_size */
|
|
|
|
"gimpcolor.RGB", /* tp_name */
|
|
|
|
sizeof(PyGBoxed), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
|
|
|
/* methods */
|
|
|
|
(destructor)0, /* tp_dealloc */
|
|
|
|
(printfunc)0, /* tp_print */
|
|
|
|
(getattrfunc)0, /* tp_getattr */
|
|
|
|
(setattrfunc)0, /* tp_setattr */
|
|
|
|
(cmpfunc)0, /* tp_compare */
|
2006-07-20 12:53:47 +08:00
|
|
|
(reprfunc)rgb_repr, /* tp_repr */
|
2005-06-04 08:17:06 +08:00
|
|
|
(PyNumberMethods*)0, /* tp_as_number */
|
2006-07-17 11:37:28 +08:00
|
|
|
&rgb_as_sequence, /* tp_as_sequence */
|
2006-10-11 14:02:23 +08:00
|
|
|
&rgb_as_mapping, /* tp_as_mapping */
|
2006-07-20 12:53:47 +08:00
|
|
|
(hashfunc)rgb_hash, /* tp_hash */
|
2005-06-04 08:17:06 +08:00
|
|
|
(ternaryfunc)0, /* tp_call */
|
2006-07-20 12:53:47 +08:00
|
|
|
(reprfunc)rgb_str, /* tp_str */
|
2005-06-04 08:17:06 +08:00
|
|
|
(getattrofunc)0, /* tp_getattro */
|
|
|
|
(setattrofunc)0, /* tp_setattro */
|
|
|
|
(PyBufferProcs*)0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
|
|
NULL, /* Documentation string */
|
|
|
|
(traverseproc)0, /* tp_traverse */
|
|
|
|
(inquiry)0, /* tp_clear */
|
2006-07-20 12:53:47 +08:00
|
|
|
(richcmpfunc)rgb_richcompare, /* tp_richcompare */
|
2005-06-04 08:17:06 +08:00
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
(getiterfunc)0, /* tp_iter */
|
|
|
|
(iternextfunc)0, /* tp_iternext */
|
|
|
|
rgb_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
rgb_getsets, /* tp_getset */
|
|
|
|
NULL, /* tp_base */
|
|
|
|
NULL, /* tp_dict */
|
|
|
|
(descrgetfunc)0, /* tp_descr_get */
|
|
|
|
(descrsetfunc)0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)rgb_init, /* tp_init */
|
|
|
|
(allocfunc)0, /* tp_alloc */
|
|
|
|
(newfunc)0, /* tp_new */
|
|
|
|
(freefunc)0, /* tp_free */
|
|
|
|
(inquiry)0 /* tp_is_gc */
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject *
|
2006-07-20 12:53:47 +08:00
|
|
|
pygimp_rgb_new(const GimpRGB *rgb)
|
|
|
|
{
|
|
|
|
return pyg_boxed_new(GIMP_TYPE_RGB, (gpointer)rgb, TRUE, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_set(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *h = NULL, *s = NULL, *v = NULL, *a = NULL;
|
|
|
|
GimpHSV tmphsv, *hsv;
|
|
|
|
static char *kwlist[] = { "h", "s", "v", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO:set", kwlist,
|
|
|
|
&h, &s, &v, &a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!h && !s && !v && !a) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide h,s,v or a arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((h && (!s || !v)) ||
|
|
|
|
(s && (!h || !v)) ||
|
|
|
|
(v && (!h || !s))) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide all 3 h,s,v arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
|
|
|
tmphsv = *hsv;
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
#define SET_MEMBER(m, s) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
tmphsv.m = (double) PyInt_AS_LONG(m) / s; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
tmphsv.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be a float"); \
|
|
|
|
return NULL; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
if (h) {
|
2006-09-17 15:44:25 +08:00
|
|
|
SET_MEMBER(h, 360.0);
|
|
|
|
SET_MEMBER(s, 100.0);
|
|
|
|
SET_MEMBER(v, 100.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (a)
|
2006-09-17 15:44:25 +08:00
|
|
|
SET_MEMBER(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
*hsv = tmphsv;
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_set_alpha(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *py_a;
|
|
|
|
GimpHSV *hsv;
|
|
|
|
static char *kwlist[] = { "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"O:set_alpha", kwlist,
|
|
|
|
&py_a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
if (PyInt_Check(py_a))
|
|
|
|
hsv->a = (double) PyInt_AS_LONG(py_a) / 255.0;
|
|
|
|
else if (PyFloat_Check(py_a))
|
2006-07-20 12:53:47 +08:00
|
|
|
hsv->a = PyFloat_AS_DOUBLE(py_a);
|
|
|
|
else {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "a must be a float");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_clamp(PyObject *self)
|
|
|
|
{
|
|
|
|
gimp_hsv_clamp(pyg_boxed_get(self, GimpHSV));
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_to_rgb(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpHSV *hsv;
|
|
|
|
GimpRGB rgb;
|
|
|
|
|
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
|
|
|
|
|
|
|
gimp_hsv_to_rgb(hsv, &rgb);
|
|
|
|
|
|
|
|
return pygimp_rgb_new(&rgb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* __getstate__ isn't exposed */
|
|
|
|
static PyObject *
|
|
|
|
hsv_getstate(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpHSV *hsv;
|
|
|
|
|
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
|
|
|
|
|
|
|
return Py_BuildValue("dddd", hsv->h, hsv->s, hsv->v, hsv->a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_reduce(PyObject *self)
|
|
|
|
{
|
|
|
|
return Py_BuildValue("ON", self->ob_type, hsv_getstate(self));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMethodDef hsv_methods[] = {
|
|
|
|
{ "set", (PyCFunction)hsv_set, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "set_alpha", (PyCFunction)hsv_set_alpha, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "clamp", (PyCFunction)hsv_clamp, METH_NOARGS },
|
|
|
|
{ "to_rgb", (PyCFunction)hsv_to_rgb, METH_NOARGS },
|
|
|
|
{ "__reduce__", (PyCFunction)hsv_reduce, METH_NOARGS },
|
|
|
|
{ NULL, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
#define MEMBER_ACCESSOR(m, s) \
|
2006-07-20 12:53:47 +08:00
|
|
|
static PyObject * \
|
|
|
|
hsv_get_ ## m(PyObject *self, void *closure) \
|
|
|
|
{ \
|
|
|
|
return PyFloat_FromDouble(pyg_boxed_get(self, GimpHSV)->m); \
|
|
|
|
} \
|
|
|
|
static int \
|
|
|
|
hsv_set_ ## m(PyObject *self, PyObject *value, void *closure) \
|
|
|
|
{ \
|
|
|
|
GimpHSV *hsv = pyg_boxed_get(self, GimpHSV); \
|
|
|
|
if (value == NULL) { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "cannot delete value"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
2006-09-17 15:44:25 +08:00
|
|
|
else if (PyInt_Check(value)) \
|
|
|
|
hsv->m = (double) PyInt_AS_LONG(value) / s; \
|
|
|
|
else if (PyFloat_Check(value)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
hsv->m = PyFloat_AS_DOUBLE(value); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "type mismatch"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
MEMBER_ACCESSOR(h, 360.0);
|
|
|
|
MEMBER_ACCESSOR(s, 100.0);
|
|
|
|
MEMBER_ACCESSOR(v, 100.0);
|
|
|
|
MEMBER_ACCESSOR(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
#undef MEMBER_ACCESSOR
|
|
|
|
|
|
|
|
static PyGetSetDef hsv_getsets[] = {
|
|
|
|
{ "h", (getter)hsv_get_h, (setter)hsv_set_h },
|
|
|
|
{ "s", (getter)hsv_get_s, (setter)hsv_set_s },
|
|
|
|
{ "v", (getter)hsv_get_v, (setter)hsv_set_v },
|
|
|
|
{ "a", (getter)hsv_get_a, (setter)hsv_set_a },
|
|
|
|
{ "hue", (getter)hsv_get_h, (setter)hsv_set_h },
|
|
|
|
{ "saturation", (getter)hsv_get_s, (setter)hsv_set_s },
|
|
|
|
{ "value", (getter)hsv_get_v, (setter)hsv_set_v },
|
|
|
|
{ "alpha", (getter)hsv_get_a, (setter)hsv_set_a },
|
|
|
|
{ NULL, (getter)0, (setter)0 },
|
|
|
|
};
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
static Py_ssize_t
|
2006-07-20 12:53:47 +08:00
|
|
|
hsv_length(PyObject *self)
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
hsv_getitem(PyObject *self, Py_ssize_t pos)
|
2006-07-20 12:53:47 +08:00
|
|
|
{
|
|
|
|
GimpHSV *hsv;
|
2006-09-17 15:44:25 +08:00
|
|
|
double val, scale_factor;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
switch (pos) {
|
2006-09-17 15:44:25 +08:00
|
|
|
case 0: val = hsv->h; scale_factor = 360.0; break;
|
|
|
|
case 1: val = hsv->s; scale_factor = 100.0; break;
|
|
|
|
case 2: val = hsv->v; scale_factor = 100.0; break;
|
|
|
|
case 3: val = hsv->a; scale_factor = 255.0; break;
|
2006-07-20 12:53:47 +08:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
return PyInt_FromLong(ROUND(CLAMP(val, 0.0, 1.0) * scale_factor));
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
hsv_setitem(PyObject *self, int pos, PyObject *value)
|
|
|
|
{
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: return hsv_set_h(self, value, NULL);
|
|
|
|
case 1: return hsv_set_s(self, value, NULL);
|
|
|
|
case 2: return hsv_set_v(self, value, NULL);
|
|
|
|
case 3: return hsv_set_a(self, value, NULL);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
hsv_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end)
|
2006-10-11 14:02:23 +08:00
|
|
|
{
|
|
|
|
PyTupleObject *ret;
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t i;
|
2006-10-11 14:02:23 +08:00
|
|
|
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
if (end > 4)
|
|
|
|
end = 4;
|
|
|
|
if (end < start)
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
ret = (PyTupleObject *)PyTuple_New(end - start);
|
|
|
|
if (ret == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = start; i < end; i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i - start, hsv_getitem(self, i));
|
|
|
|
|
|
|
|
return (PyObject *)ret;
|
|
|
|
}
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static PySequenceMethods hsv_as_sequence = {
|
2008-07-03 19:39:52 +08:00
|
|
|
hsv_length,
|
2006-07-20 12:53:47 +08:00
|
|
|
(binaryfunc)0,
|
2008-07-03 19:39:52 +08:00
|
|
|
0,
|
|
|
|
hsv_getitem,
|
|
|
|
hsv_slice,
|
|
|
|
hsv_setitem,
|
|
|
|
0,
|
2006-07-20 12:53:47 +08:00
|
|
|
(objobjproc)0,
|
|
|
|
};
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
|
|
|
hsv_subscript(PyObject *self, PyObject *item)
|
|
|
|
{
|
|
|
|
if (PyInt_Check(item)) {
|
|
|
|
long i = PyInt_AS_LONG(item);
|
|
|
|
return hsv_getitem(self, i);
|
|
|
|
} else if (PyLong_Check(item)) {
|
|
|
|
long i = PyLong_AsLong(item);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return NULL;
|
|
|
|
return hsv_getitem(self, i);
|
|
|
|
} else if (PySlice_Check(item)) {
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
2006-10-11 14:02:23 +08:00
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, 4,
|
|
|
|
&start, &stop, &step, &slicelength) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (slicelength <= 0) {
|
|
|
|
return PyTuple_New(0);
|
|
|
|
} else {
|
|
|
|
ret = PyTuple_New(slicelength);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i, hsv_getitem(self, cur));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
} else if (PyString_Check(item)) {
|
|
|
|
char *s = PyString_AsString(item);
|
|
|
|
|
|
|
|
if (g_ascii_strcasecmp(s, "h") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "hue") == 0)
|
|
|
|
return hsv_get_h(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "s") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "saturation") == 0)
|
|
|
|
return hsv_get_s(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "v") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "value") == 0)
|
|
|
|
return hsv_get_v(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "a") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "alpha") == 0)
|
|
|
|
return hsv_get_a(self, NULL);
|
|
|
|
else {
|
|
|
|
PyErr_SetObject(PyExc_KeyError, item);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"indices must be integers");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMappingMethods hsv_as_mapping = {
|
2008-07-03 19:39:52 +08:00
|
|
|
hsv_length,
|
2006-10-11 14:02:23 +08:00
|
|
|
(binaryfunc)hsv_subscript,
|
|
|
|
(objobjargproc)0
|
|
|
|
};
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static long
|
|
|
|
hsv_hash(PyObject *self)
|
|
|
|
{
|
|
|
|
long ret = -1;
|
|
|
|
|
|
|
|
PyObject *temp = hsv_getstate(self);
|
|
|
|
if (temp != NULL) {
|
|
|
|
ret = PyObject_Hash(temp);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_richcompare(PyObject *self, PyObject *other, int op)
|
|
|
|
{
|
|
|
|
GimpHSV *c1, *c2;
|
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (!pygimp_hsv_check(other)) {
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can't compare %s to %s",
|
|
|
|
self->ob_type->tp_name, other->ob_type->tp_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op != Py_EQ && op != Py_NE) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"can't compare color values using <, <=, >, >=");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = pyg_boxed_get(self, GimpHSV);
|
|
|
|
c2 = pyg_boxed_get(other, GimpHSV);
|
|
|
|
|
|
|
|
if ((c1->h == c2->h && c1->s == c2->s && c1->v == c2->v && c1->a == c2->a) == (op == Py_EQ))
|
|
|
|
ret = Py_True;
|
|
|
|
else
|
|
|
|
ret = Py_False;
|
|
|
|
|
|
|
|
Py_INCREF(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_pretty_print(PyObject *self, gboolean inexact)
|
|
|
|
{
|
|
|
|
GimpHSV *hsv;
|
|
|
|
PyObject *ret = NULL;
|
|
|
|
PyObject *h_f = NULL, *s_f = NULL, *v_f = NULL, *a_f = NULL;
|
|
|
|
PyObject *h = NULL, *s = NULL, *v = NULL, *a = NULL;
|
|
|
|
reprfunc repr;
|
2008-08-14 05:10:17 +08:00
|
|
|
const char *prefix;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (inexact) {
|
|
|
|
repr = PyObject_Str;
|
|
|
|
prefix = "HSV ";
|
|
|
|
} else {
|
|
|
|
repr = PyObject_Repr;
|
|
|
|
prefix = self->ob_type->tp_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
hsv = pyg_boxed_get(self, GimpHSV);
|
|
|
|
|
|
|
|
if ((h_f = PyFloat_FromDouble(hsv->h)) == NULL) goto cleanup;
|
|
|
|
if ((s_f = PyFloat_FromDouble(hsv->s)) == NULL) goto cleanup;
|
|
|
|
if ((v_f = PyFloat_FromDouble(hsv->v)) == NULL) goto cleanup;
|
|
|
|
if ((a_f = PyFloat_FromDouble(hsv->a)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
if ((h = repr(h_f)) == NULL) goto cleanup;
|
|
|
|
if ((s = repr(s_f)) == NULL) goto cleanup;
|
|
|
|
if ((v = repr(v_f)) == NULL) goto cleanup;
|
|
|
|
if ((a = repr(a_f)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
ret = PyString_FromFormat("%s(%s, %s, %s, %s)",
|
|
|
|
prefix,
|
|
|
|
PyString_AsString(h),
|
|
|
|
PyString_AsString(s),
|
|
|
|
PyString_AsString(v),
|
|
|
|
PyString_AsString(a));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
Py_XDECREF(h); Py_XDECREF(s); Py_XDECREF(v); Py_XDECREF(a);
|
|
|
|
Py_XDECREF(h_f); Py_XDECREF(s_f); Py_XDECREF(v_f); Py_XDECREF(a_f);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_repr(PyObject *self)
|
|
|
|
{
|
|
|
|
return hsv_pretty_print(self, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsv_str(PyObject *self)
|
|
|
|
{
|
|
|
|
return hsv_pretty_print(self, TRUE);
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
static int
|
2006-07-20 12:53:47 +08:00
|
|
|
hsv_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *h, *s, *v, *a = NULL;
|
|
|
|
GimpHSV hsv;
|
|
|
|
static char *kwlist[] = { "h", "s", "v", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"OOO|O:set", kwlist,
|
|
|
|
&h, &s, &v, &a))
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
#define SET_MEMBER(m, s) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
hsv.m = (double) PyInt_AS_LONG(m) / s; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
hsv.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
2006-09-17 15:05:52 +08:00
|
|
|
#m " must be an int or a float"); \
|
|
|
|
return -1; \
|
2006-07-20 12:53:47 +08:00
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
SET_MEMBER(h, 360.0);
|
|
|
|
SET_MEMBER(s, 100.0);
|
|
|
|
SET_MEMBER(v, 100.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (a)
|
2006-09-17 15:05:52 +08:00
|
|
|
SET_MEMBER(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
else
|
|
|
|
hsv.a = 1.0;
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
self->gtype = GIMP_TYPE_HSV;
|
|
|
|
self->free_on_dealloc = TRUE;
|
|
|
|
self->boxed = g_boxed_copy(GIMP_TYPE_HSV, &hsv);
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
return 0;
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyTypeObject PyGimpHSV_Type = {
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
0, /* ob_size */
|
|
|
|
"gimpcolor.HSV", /* tp_name */
|
|
|
|
sizeof(PyGBoxed), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
|
|
|
/* methods */
|
|
|
|
(destructor)0, /* tp_dealloc */
|
|
|
|
(printfunc)0, /* tp_print */
|
|
|
|
(getattrfunc)0, /* tp_getattr */
|
|
|
|
(setattrfunc)0, /* tp_setattr */
|
|
|
|
(cmpfunc)0, /* tp_compare */
|
|
|
|
(reprfunc)hsv_repr, /* tp_repr */
|
|
|
|
(PyNumberMethods*)0, /* tp_as_number */
|
|
|
|
&hsv_as_sequence, /* tp_as_sequence */
|
2006-10-11 14:02:23 +08:00
|
|
|
&hsv_as_mapping, /* tp_as_mapping */
|
2006-07-20 12:53:47 +08:00
|
|
|
(hashfunc)hsv_hash, /* tp_hash */
|
|
|
|
(ternaryfunc)0, /* tp_call */
|
|
|
|
(reprfunc)hsv_str, /* tp_repr */
|
|
|
|
(getattrofunc)0, /* tp_getattro */
|
|
|
|
(setattrofunc)0, /* tp_setattro */
|
|
|
|
(PyBufferProcs*)0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
|
|
NULL, /* Documentation string */
|
|
|
|
(traverseproc)0, /* tp_traverse */
|
|
|
|
(inquiry)0, /* tp_clear */
|
|
|
|
(richcmpfunc)hsv_richcompare, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
(getiterfunc)0, /* tp_iter */
|
|
|
|
(iternextfunc)0, /* tp_iternext */
|
|
|
|
hsv_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
hsv_getsets, /* tp_getset */
|
|
|
|
NULL, /* tp_base */
|
|
|
|
NULL, /* tp_dict */
|
|
|
|
(descrgetfunc)0, /* tp_descr_get */
|
|
|
|
(descrsetfunc)0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)hsv_init, /* tp_init */
|
|
|
|
(allocfunc)0, /* tp_alloc */
|
|
|
|
(newfunc)0, /* tp_new */
|
|
|
|
(freefunc)0, /* tp_free */
|
|
|
|
(inquiry)0 /* tp_is_gc */
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
pygimp_hsv_new(const GimpHSV *hsv)
|
|
|
|
{
|
|
|
|
return pyg_boxed_new(GIMP_TYPE_HSV, (gpointer)hsv, TRUE, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_set(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *h = NULL, *s = NULL, *l = NULL, *a = NULL;
|
|
|
|
GimpHSL tmphsl, *hsl;
|
|
|
|
static char *kwlist[] = { "h", "s", "l", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOO:set", kwlist,
|
|
|
|
&h, &s, &l, &a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!h && !s && !l && !a) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide h,s,l or a arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((h && (!s || !l)) ||
|
|
|
|
(s && (!h || !l)) ||
|
|
|
|
(l && (!h || !s))) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide all 3 h,s,l arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
|
|
|
tmphsl = *hsl;
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
#define SET_MEMBER(m, s) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
tmphsl.m = (double) PyInt_AS_LONG(m) / s; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
tmphsl.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be a float"); \
|
|
|
|
return NULL; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
if (h) {
|
2006-09-17 15:44:25 +08:00
|
|
|
SET_MEMBER(h, 360.0);
|
|
|
|
SET_MEMBER(s, 100.0);
|
|
|
|
SET_MEMBER(l, 100.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (a)
|
2006-09-17 15:44:25 +08:00
|
|
|
SET_MEMBER(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
*hsl = tmphsl;
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_set_alpha(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *py_a;
|
|
|
|
GimpHSL *hsl;
|
|
|
|
static char *kwlist[] = { "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"O:set_alpha", kwlist,
|
|
|
|
&py_a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
if (PyInt_Check(py_a))
|
|
|
|
hsl->a = (double) PyInt_AS_LONG(py_a) / 255.0;
|
|
|
|
else if (PyFloat_Check(py_a))
|
2006-07-20 12:53:47 +08:00
|
|
|
hsl->a = PyFloat_AS_DOUBLE(py_a);
|
|
|
|
else {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "a must be a float");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_to_rgb(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpHSL *hsl;
|
|
|
|
GimpRGB rgb;
|
|
|
|
|
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
|
|
|
|
|
|
|
gimp_hsl_to_rgb(hsl, &rgb);
|
|
|
|
|
|
|
|
return pygimp_rgb_new(&rgb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* __getstate__ isn't exposed */
|
|
|
|
static PyObject *
|
|
|
|
hsl_getstate(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpHSL *hsl;
|
|
|
|
|
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
|
|
|
|
|
|
|
return Py_BuildValue("dddd", hsl->h, hsl->s, hsl->l, hsl->a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_reduce(PyObject *self)
|
|
|
|
{
|
|
|
|
return Py_BuildValue("ON", self->ob_type, hsl_getstate(self));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMethodDef hsl_methods[] = {
|
|
|
|
{ "set", (PyCFunction)hsl_set, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "set_alpha", (PyCFunction)hsl_set_alpha, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "to_rgb", (PyCFunction)hsl_to_rgb, METH_NOARGS },
|
|
|
|
{ "__reduce__", (PyCFunction)hsl_reduce, METH_NOARGS },
|
|
|
|
{ NULL, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
#define MEMBER_ACCESSOR(m, s) \
|
2006-07-20 12:53:47 +08:00
|
|
|
static PyObject * \
|
|
|
|
hsl_get_ ## m(PyObject *self, void *closure) \
|
|
|
|
{ \
|
|
|
|
return PyFloat_FromDouble(pyg_boxed_get(self, GimpHSL)->m); \
|
|
|
|
} \
|
|
|
|
static int \
|
|
|
|
hsl_set_ ## m(PyObject *self, PyObject *value, void *closure) \
|
|
|
|
{ \
|
|
|
|
GimpHSL *hsl = pyg_boxed_get(self, GimpHSL); \
|
|
|
|
if (value == NULL) { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "cannot delete value"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
2006-09-17 15:44:25 +08:00
|
|
|
else if (PyInt_Check(value)) \
|
|
|
|
hsl->m = (double) PyInt_AS_LONG(value) / s; \
|
|
|
|
else if (PyFloat_Check(value)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
hsl->m = PyFloat_AS_DOUBLE(value); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "type mismatch"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
MEMBER_ACCESSOR(h, 360.0);
|
|
|
|
MEMBER_ACCESSOR(s, 100.0);
|
|
|
|
MEMBER_ACCESSOR(l, 100.0);
|
|
|
|
MEMBER_ACCESSOR(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
#undef MEMBER_ACCESSOR
|
|
|
|
|
|
|
|
static PyGetSetDef hsl_getsets[] = {
|
|
|
|
{ "h", (getter)hsl_get_h, (setter)hsl_set_h },
|
|
|
|
{ "s", (getter)hsl_get_s, (setter)hsl_set_s },
|
|
|
|
{ "l", (getter)hsl_get_l, (setter)hsl_set_l },
|
|
|
|
{ "a", (getter)hsl_get_a, (setter)hsl_set_a },
|
|
|
|
{ "hue", (getter)hsl_get_h, (setter)hsl_set_h },
|
|
|
|
{ "saturation", (getter)hsl_get_s, (setter)hsl_set_s },
|
|
|
|
{ "lightness", (getter)hsl_get_l, (setter)hsl_set_l },
|
|
|
|
{ "alpha", (getter)hsl_get_a, (setter)hsl_set_a },
|
|
|
|
{ NULL, (getter)0, (setter)0 },
|
|
|
|
};
|
|
|
|
|
2008-07-03 19:39:52 +08:00
|
|
|
static Py_ssize_t
|
2006-07-20 12:53:47 +08:00
|
|
|
hsl_length(PyObject *self)
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
hsl_getitem(PyObject *self, Py_ssize_t pos)
|
2006-07-20 12:53:47 +08:00
|
|
|
{
|
|
|
|
GimpHSL *hsl;
|
2006-09-17 15:44:25 +08:00
|
|
|
double val, scale_factor;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
switch (pos) {
|
2006-09-17 15:44:25 +08:00
|
|
|
case 0: val = hsl->h; scale_factor = 360.0; break;
|
|
|
|
case 1: val = hsl->s; scale_factor = 100.0; break;
|
|
|
|
case 2: val = hsl->l; scale_factor = 100.0; break;
|
|
|
|
case 3: val = hsl->a; scale_factor = 255.0; break;
|
2006-07-20 12:53:47 +08:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:44:25 +08:00
|
|
|
return PyInt_FromLong(ROUND(CLAMP(val, 0.0, 1.0) * scale_factor));
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
hsl_setitem(PyObject *self, int pos, PyObject *value)
|
|
|
|
{
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 4) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: return hsl_set_h(self, value, NULL);
|
|
|
|
case 1: return hsl_set_s(self, value, NULL);
|
|
|
|
case 2: return hsl_set_l(self, value, NULL);
|
|
|
|
case 3: return hsl_set_a(self, value, NULL);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
hsl_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end)
|
2006-10-11 14:02:23 +08:00
|
|
|
{
|
|
|
|
PyTupleObject *ret;
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t i;
|
2006-10-11 14:02:23 +08:00
|
|
|
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
if (end > 4)
|
|
|
|
end = 4;
|
|
|
|
if (end < start)
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
ret = (PyTupleObject *)PyTuple_New(end - start);
|
|
|
|
if (ret == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = start; i < end; i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i - start, hsl_getitem(self, i));
|
|
|
|
|
|
|
|
return (PyObject *)ret;
|
|
|
|
}
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static PySequenceMethods hsl_as_sequence = {
|
2008-07-03 19:39:52 +08:00
|
|
|
hsl_length,
|
2006-07-20 12:53:47 +08:00
|
|
|
(binaryfunc)0,
|
2008-07-03 19:39:52 +08:00
|
|
|
0,
|
|
|
|
hsl_getitem,
|
|
|
|
hsl_slice,
|
|
|
|
hsl_setitem,
|
|
|
|
0,
|
2006-07-20 12:53:47 +08:00
|
|
|
(objobjproc)0,
|
|
|
|
};
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
|
|
|
hsl_subscript(PyObject *self, PyObject *item)
|
|
|
|
{
|
|
|
|
if (PyInt_Check(item)) {
|
|
|
|
long i = PyInt_AS_LONG(item);
|
|
|
|
return hsl_getitem(self, i);
|
|
|
|
} else if (PyLong_Check(item)) {
|
|
|
|
long i = PyLong_AsLong(item);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return NULL;
|
|
|
|
return hsl_getitem(self, i);
|
|
|
|
} else if (PySlice_Check(item)) {
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
2006-10-11 14:02:23 +08:00
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, 4,
|
|
|
|
&start, &stop, &step, &slicelength) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (slicelength <= 0) {
|
|
|
|
return PyTuple_New(0);
|
|
|
|
} else {
|
|
|
|
ret = PyTuple_New(slicelength);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i, hsl_getitem(self, cur));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
} else if (PyString_Check(item)) {
|
|
|
|
char *s = PyString_AsString(item);
|
|
|
|
|
|
|
|
if (g_ascii_strcasecmp(s, "h") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "hue") == 0)
|
|
|
|
return hsl_get_h(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "s") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "saturation") == 0)
|
|
|
|
return hsl_get_s(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "l") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "lightness") == 0)
|
|
|
|
return hsl_get_l(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "a") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "alpha") == 0)
|
|
|
|
return hsl_get_a(self, NULL);
|
|
|
|
else {
|
|
|
|
PyErr_SetObject(PyExc_KeyError, item);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"indices must be integers");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMappingMethods hsl_as_mapping = {
|
2008-07-03 19:39:52 +08:00
|
|
|
hsl_length,
|
2006-10-11 14:02:23 +08:00
|
|
|
(binaryfunc)hsl_subscript,
|
|
|
|
(objobjargproc)0
|
|
|
|
};
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static long
|
|
|
|
hsl_hash(PyObject *self)
|
|
|
|
{
|
|
|
|
long ret = -1;
|
|
|
|
|
|
|
|
PyObject *temp = hsl_getstate(self);
|
|
|
|
if (temp != NULL) {
|
|
|
|
ret = PyObject_Hash(temp);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_richcompare(PyObject *self, PyObject *other, int op)
|
|
|
|
{
|
|
|
|
GimpHSL *c1, *c2;
|
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (!pygimp_hsl_check(other)) {
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can't compare %s to %s",
|
|
|
|
self->ob_type->tp_name, other->ob_type->tp_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op != Py_EQ && op != Py_NE) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"can't compare color values using <, <=, >, >=");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = pyg_boxed_get(self, GimpHSL);
|
|
|
|
c2 = pyg_boxed_get(other, GimpHSL);
|
|
|
|
|
|
|
|
if ((c1->h == c2->h && c1->s == c2->s && c1->l == c2->l && c1->a == c2->a) == (op == Py_EQ))
|
|
|
|
ret = Py_True;
|
|
|
|
else
|
|
|
|
ret = Py_False;
|
|
|
|
|
|
|
|
Py_INCREF(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_pretty_print(PyObject *self, gboolean inexact)
|
|
|
|
{
|
|
|
|
GimpHSL *hsl;
|
|
|
|
PyObject *ret = NULL;
|
|
|
|
PyObject *h_f = NULL, *s_f = NULL, *l_f = NULL, *a_f = NULL;
|
|
|
|
PyObject *h = NULL, *s = NULL, *l = NULL, *a = NULL;
|
|
|
|
reprfunc repr;
|
2008-08-14 05:10:17 +08:00
|
|
|
const char *prefix;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (inexact) {
|
|
|
|
repr = PyObject_Str;
|
|
|
|
prefix = "HSL ";
|
|
|
|
} else {
|
|
|
|
repr = PyObject_Repr;
|
|
|
|
prefix = self->ob_type->tp_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
hsl = pyg_boxed_get(self, GimpHSL);
|
|
|
|
|
|
|
|
if ((h_f = PyFloat_FromDouble(hsl->h)) == NULL) goto cleanup;
|
|
|
|
if ((s_f = PyFloat_FromDouble(hsl->s)) == NULL) goto cleanup;
|
|
|
|
if ((l_f = PyFloat_FromDouble(hsl->l)) == NULL) goto cleanup;
|
|
|
|
if ((a_f = PyFloat_FromDouble(hsl->a)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
if ((h = repr(h_f)) == NULL) goto cleanup;
|
|
|
|
if ((s = repr(s_f)) == NULL) goto cleanup;
|
|
|
|
if ((l = repr(l_f)) == NULL) goto cleanup;
|
|
|
|
if ((a = repr(a_f)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
ret = PyString_FromFormat("%s(%s, %s, %s, %s)",
|
|
|
|
prefix,
|
|
|
|
PyString_AsString(h),
|
|
|
|
PyString_AsString(s),
|
|
|
|
PyString_AsString(l),
|
|
|
|
PyString_AsString(a));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
Py_XDECREF(h); Py_XDECREF(s); Py_XDECREF(l); Py_XDECREF(a);
|
|
|
|
Py_XDECREF(h_f); Py_XDECREF(s_f); Py_XDECREF(l_f); Py_XDECREF(a_f);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_repr(PyObject *self)
|
|
|
|
{
|
|
|
|
return hsl_pretty_print(self, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
hsl_str(PyObject *self)
|
|
|
|
{
|
|
|
|
return hsl_pretty_print(self, TRUE);
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
static int
|
2006-07-20 12:53:47 +08:00
|
|
|
hsl_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *h, *s, *l, *a = NULL;
|
|
|
|
GimpHSL hsl;
|
|
|
|
static char *kwlist[] = { "h", "s", "l", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"OOO|O:set", kwlist,
|
|
|
|
&h, &s, &l, &a))
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
#define SET_MEMBER(m, s) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
hsl.m = (double) PyInt_AS_LONG(m) / s; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
2006-07-20 12:53:47 +08:00
|
|
|
hsl.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be a float"); \
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1; \
|
2006-07-20 12:53:47 +08:00
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
SET_MEMBER(h, 360.0);
|
|
|
|
SET_MEMBER(s, 100.0);
|
|
|
|
SET_MEMBER(l, 100.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (a)
|
2006-09-17 15:05:52 +08:00
|
|
|
SET_MEMBER(a, 255.0);
|
2006-07-20 12:53:47 +08:00
|
|
|
else
|
|
|
|
hsl.a = 1.0;
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
self->gtype = GIMP_TYPE_HSL;
|
|
|
|
self->free_on_dealloc = TRUE;
|
|
|
|
self->boxed = g_boxed_copy(GIMP_TYPE_HSL, &hsl);
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
return 0;
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyTypeObject PyGimpHSL_Type = {
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
0, /* ob_size */
|
|
|
|
"gimpcolor.HSL", /* tp_name */
|
|
|
|
sizeof(PyGBoxed), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
|
|
|
/* methods */
|
|
|
|
(destructor)0, /* tp_dealloc */
|
|
|
|
(printfunc)0, /* tp_print */
|
|
|
|
(getattrfunc)0, /* tp_getattr */
|
|
|
|
(setattrfunc)0, /* tp_setattr */
|
|
|
|
(cmpfunc)0, /* tp_compare */
|
|
|
|
(reprfunc)hsl_repr, /* tp_repr */
|
|
|
|
(PyNumberMethods*)0, /* tp_as_number */
|
|
|
|
&hsl_as_sequence, /* tp_as_sequence */
|
2006-10-11 14:02:23 +08:00
|
|
|
&hsl_as_mapping, /* tp_as_mapping */
|
2006-07-20 12:53:47 +08:00
|
|
|
(hashfunc)hsl_hash, /* tp_hash */
|
|
|
|
(ternaryfunc)0, /* tp_call */
|
|
|
|
(reprfunc)hsl_str, /* tp_repr */
|
|
|
|
(getattrofunc)0, /* tp_getattro */
|
|
|
|
(setattrofunc)0, /* tp_setattro */
|
|
|
|
(PyBufferProcs*)0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
|
|
NULL, /* Documentation string */
|
|
|
|
(traverseproc)0, /* tp_traverse */
|
|
|
|
(inquiry)0, /* tp_clear */
|
|
|
|
(richcmpfunc)hsl_richcompare, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
(getiterfunc)0, /* tp_iter */
|
|
|
|
(iternextfunc)0, /* tp_iternext */
|
|
|
|
hsl_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
hsl_getsets, /* tp_getset */
|
|
|
|
NULL, /* tp_base */
|
|
|
|
NULL, /* tp_dict */
|
|
|
|
(descrgetfunc)0, /* tp_descr_get */
|
|
|
|
(descrsetfunc)0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)hsl_init, /* tp_init */
|
|
|
|
(allocfunc)0, /* tp_alloc */
|
|
|
|
(newfunc)0, /* tp_new */
|
|
|
|
(freefunc)0, /* tp_free */
|
|
|
|
(inquiry)0 /* tp_is_gc */
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
pygimp_hsl_new(const GimpHSL *hsl)
|
|
|
|
{
|
|
|
|
return pyg_boxed_new(GIMP_TYPE_HSL, (gpointer)hsl, TRUE, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_set(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *c = NULL, *m = NULL, *y = NULL, *k = NULL, *a = NULL;
|
|
|
|
GimpCMYK tmpcmyk, *cmyk;
|
|
|
|
static char *kwlist[] = { "c", "m", "y", "k", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOOO:set", kwlist,
|
|
|
|
&c, &m, &y, &k, &a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!c && !y && !m && !k && !a) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide c,m,y,k or a arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((c && (!m || !y || !k)) ||
|
|
|
|
(m && (!c || !y || !k)) ||
|
|
|
|
(y && (!c || !m || !k)) ||
|
|
|
|
(k && (!c || !m || !y))) {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "must provide all 4 c,m,y,k arguments");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmyk = pyg_boxed_get(self, GimpCMYK);
|
|
|
|
tmpcmyk = *cmyk;
|
|
|
|
|
|
|
|
#define SET_MEMBER(m) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
tmpcmyk.m = (double) PyInt_AS_LONG(m) / 255.0; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
|
|
|
tmpcmyk.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be an int or a float"); \
|
|
|
|
return NULL; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
if (c) {
|
|
|
|
SET_MEMBER(c);
|
|
|
|
SET_MEMBER(y);
|
|
|
|
SET_MEMBER(m);
|
|
|
|
SET_MEMBER(k);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
SET_MEMBER(a);
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
*cmyk = tmpcmyk;
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_set_alpha(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *py_a;
|
|
|
|
GimpCMYK *cmyk;
|
|
|
|
static char *kwlist[] = { "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"O:set_alpha", kwlist,
|
|
|
|
&py_a))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
cmyk = pyg_boxed_get(self, GimpCMYK);
|
|
|
|
|
|
|
|
if (PyInt_Check(py_a))
|
|
|
|
cmyk->a = (double) PyInt_AS_LONG(py_a) / 255.0;
|
|
|
|
else if (PyFloat_Check(py_a))
|
|
|
|
cmyk->a = PyFloat_AS_DOUBLE(py_a);
|
|
|
|
else {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "a must be an int or a float");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
return Py_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* __getstate__ isn't exposed */
|
|
|
|
static PyObject *
|
|
|
|
cmyk_getstate(PyObject *self)
|
|
|
|
{
|
|
|
|
GimpCMYK *cmyk;
|
|
|
|
|
|
|
|
cmyk = pyg_boxed_get(self, GimpCMYK);
|
|
|
|
|
|
|
|
return Py_BuildValue("ddddd", cmyk->c, cmyk->m, cmyk->y, cmyk->k, cmyk->a);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_reduce(PyObject *self)
|
|
|
|
{
|
|
|
|
return Py_BuildValue("ON", self->ob_type, cmyk_getstate(self));
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMethodDef cmyk_methods[] = {
|
|
|
|
{ "set", (PyCFunction)cmyk_set, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "set_alpha", (PyCFunction)cmyk_set_alpha, METH_VARARGS|METH_KEYWORDS },
|
|
|
|
{ "__reduce__", (PyCFunction)cmyk_reduce, METH_NOARGS },
|
|
|
|
{ NULL, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MEMBER_ACCESSOR(m) \
|
|
|
|
static PyObject * \
|
|
|
|
cmyk_get_ ## m(PyObject *self, void *closure) \
|
|
|
|
{ \
|
|
|
|
return PyFloat_FromDouble(pyg_boxed_get(self, GimpCMYK)->m); \
|
|
|
|
} \
|
|
|
|
static int \
|
|
|
|
cmyk_set_ ## m(PyObject *self, PyObject *value, void *closure) \
|
|
|
|
{ \
|
|
|
|
GimpCMYK *cmyk = pyg_boxed_get(self, GimpCMYK); \
|
|
|
|
if (value == NULL) { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "cannot delete value"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
else if (PyInt_Check(value)) \
|
|
|
|
cmyk->m = (double) PyInt_AS_LONG(value) / 255.0; \
|
|
|
|
else if (PyFloat_Check(value)) \
|
|
|
|
cmyk->m = PyFloat_AS_DOUBLE(value); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, "type mismatch"); \
|
|
|
|
return -1; \
|
|
|
|
} \
|
|
|
|
return 0; \
|
|
|
|
}
|
|
|
|
|
|
|
|
MEMBER_ACCESSOR(c);
|
|
|
|
MEMBER_ACCESSOR(m);
|
|
|
|
MEMBER_ACCESSOR(y);
|
|
|
|
MEMBER_ACCESSOR(k);
|
|
|
|
MEMBER_ACCESSOR(a);
|
|
|
|
|
|
|
|
#undef MEMBER_ACCESSOR
|
|
|
|
|
|
|
|
static PyGetSetDef cmyk_getsets[] = {
|
|
|
|
{ "c", (getter)cmyk_get_c, (setter)cmyk_set_c },
|
|
|
|
{ "m", (getter)cmyk_get_m, (setter)cmyk_set_m },
|
|
|
|
{ "y", (getter)cmyk_get_y, (setter)cmyk_set_y },
|
|
|
|
{ "k", (getter)cmyk_get_k, (setter)cmyk_set_k },
|
|
|
|
{ "a", (getter)cmyk_get_a, (setter)cmyk_set_a },
|
|
|
|
{ "cyan", (getter)cmyk_get_c, (setter)cmyk_set_c },
|
|
|
|
{ "magenta", (getter)cmyk_get_m, (setter)cmyk_set_m },
|
|
|
|
{ "yellow", (getter)cmyk_get_y, (setter)cmyk_set_y },
|
|
|
|
{ "black", (getter)cmyk_get_k, (setter)cmyk_set_k },
|
|
|
|
{ "alpha", (getter)cmyk_get_a, (setter)cmyk_set_a },
|
|
|
|
{ NULL, (getter)0, (setter)0 },
|
|
|
|
};
|
|
|
|
|
2008-07-03 19:39:52 +08:00
|
|
|
static Py_ssize_t
|
2006-07-20 12:53:47 +08:00
|
|
|
cmyk_length(PyObject *self)
|
|
|
|
{
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
cmyk_getitem(PyObject *self, Py_ssize_t pos)
|
2006-07-20 12:53:47 +08:00
|
|
|
{
|
|
|
|
GimpCMYK *cmyk;
|
|
|
|
double val;
|
|
|
|
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 5;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 5) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-04 16:37:32 +08:00
|
|
|
cmyk = pyg_boxed_get(self, GimpCMYK);
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: val = cmyk->c; break;
|
|
|
|
case 1: val = cmyk->m; break;
|
|
|
|
case 2: val = cmyk->y; break;
|
|
|
|
case 3: val = cmyk->k; break;
|
|
|
|
case 4: val = cmyk->a; break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PyInt_FromLong(ROUND(CLAMP(val, 0.0, 1.0) * 255.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmyk_setitem(PyObject *self, int pos, PyObject *value)
|
|
|
|
{
|
|
|
|
if (pos < 0)
|
|
|
|
pos += 5;
|
|
|
|
|
|
|
|
if (pos < 0 || pos >= 5) {
|
|
|
|
PyErr_SetString(PyExc_IndexError, "index out of range");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pos) {
|
|
|
|
case 0: return cmyk_set_c(self, value, NULL);
|
|
|
|
case 1: return cmyk_set_m(self, value, NULL);
|
|
|
|
case 2: return cmyk_set_y(self, value, NULL);
|
|
|
|
case 3: return cmyk_set_k(self, value, NULL);
|
|
|
|
case 4: return cmyk_set_a(self, value, NULL);
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
2008-07-03 19:39:52 +08:00
|
|
|
cmyk_slice(PyObject *self, Py_ssize_t start, Py_ssize_t end)
|
2006-10-11 14:02:23 +08:00
|
|
|
{
|
|
|
|
PyTupleObject *ret;
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t i;
|
2006-10-11 14:02:23 +08:00
|
|
|
|
|
|
|
if (start < 0)
|
|
|
|
start = 0;
|
|
|
|
if (end > 5)
|
|
|
|
end = 5;
|
|
|
|
if (end < start)
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
ret = (PyTupleObject *)PyTuple_New(end - start);
|
|
|
|
if (ret == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = start; i < end; i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i - start, cmyk_getitem(self, i));
|
|
|
|
|
|
|
|
return (PyObject *)ret;
|
|
|
|
}
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static PySequenceMethods cmyk_as_sequence = {
|
2008-07-03 19:39:52 +08:00
|
|
|
cmyk_length,
|
2006-07-20 12:53:47 +08:00
|
|
|
(binaryfunc)0,
|
2008-07-03 19:39:52 +08:00
|
|
|
0,
|
|
|
|
cmyk_getitem,
|
|
|
|
cmyk_slice,
|
|
|
|
cmyk_setitem,
|
|
|
|
0,
|
2006-07-20 12:53:47 +08:00
|
|
|
(objobjproc)0,
|
|
|
|
};
|
|
|
|
|
2006-10-11 14:02:23 +08:00
|
|
|
static PyObject *
|
|
|
|
cmyk_subscript(PyObject *self, PyObject *item)
|
|
|
|
{
|
|
|
|
if (PyInt_Check(item)) {
|
|
|
|
long i = PyInt_AS_LONG(item);
|
|
|
|
return cmyk_getitem(self, i);
|
|
|
|
} else if (PyLong_Check(item)) {
|
|
|
|
long i = PyLong_AsLong(item);
|
|
|
|
if (i == -1 && PyErr_Occurred())
|
|
|
|
return NULL;
|
|
|
|
return cmyk_getitem(self, i);
|
|
|
|
} else if (PySlice_Check(item)) {
|
2008-07-03 19:39:52 +08:00
|
|
|
Py_ssize_t start, stop, step, slicelength, cur, i;
|
2006-10-11 14:02:23 +08:00
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (PySlice_GetIndicesEx((PySliceObject*)item, 5,
|
|
|
|
&start, &stop, &step, &slicelength) < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (slicelength <= 0) {
|
|
|
|
return PyTuple_New(0);
|
|
|
|
} else {
|
|
|
|
ret = PyTuple_New(slicelength);
|
|
|
|
if (!ret)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (cur = start, i = 0; i < slicelength; cur += step, i++)
|
|
|
|
PyTuple_SET_ITEM(ret, i, cmyk_getitem(self, cur));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
} else if (PyString_Check(item)) {
|
|
|
|
char *s = PyString_AsString(item);
|
|
|
|
|
|
|
|
if (g_ascii_strcasecmp(s, "c") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "cyan") == 0)
|
|
|
|
return cmyk_get_c(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "m") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "magenta") == 0)
|
|
|
|
return cmyk_get_m(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "y") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "yellow") == 0)
|
|
|
|
return cmyk_get_y(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "k") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "black") == 0)
|
|
|
|
return cmyk_get_k(self, NULL);
|
|
|
|
else if (g_ascii_strcasecmp(s, "a") == 0 ||
|
|
|
|
g_ascii_strcasecmp(s, "alpha") == 0)
|
|
|
|
return cmyk_get_a(self, NULL);
|
|
|
|
else {
|
|
|
|
PyErr_SetObject(PyExc_KeyError, item);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"indices must be integers");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyMappingMethods cmyk_as_mapping = {
|
2008-07-03 19:39:52 +08:00
|
|
|
cmyk_length,
|
2006-10-11 14:02:23 +08:00
|
|
|
(binaryfunc)cmyk_subscript,
|
|
|
|
(objobjargproc)0
|
|
|
|
};
|
|
|
|
|
2006-07-20 12:53:47 +08:00
|
|
|
static long
|
|
|
|
cmyk_hash(PyObject *self)
|
|
|
|
{
|
|
|
|
long ret = -1;
|
|
|
|
|
|
|
|
PyObject *temp = cmyk_getstate(self);
|
|
|
|
if (temp != NULL) {
|
|
|
|
ret = PyObject_Hash(temp);
|
|
|
|
Py_DECREF(temp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_richcompare(PyObject *self, PyObject *other, int op)
|
|
|
|
{
|
|
|
|
GimpCMYK *c1, *c2;
|
|
|
|
PyObject *ret;
|
|
|
|
|
|
|
|
if (!pygimp_cmyk_check(other)) {
|
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"can't compare %s to %s",
|
|
|
|
self->ob_type->tp_name, other->ob_type->tp_name);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (op != Py_EQ && op != Py_NE) {
|
|
|
|
PyErr_SetString(PyExc_TypeError,
|
|
|
|
"can't compare color values using <, <=, >, >=");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
c1 = pyg_boxed_get(self, GimpCMYK);
|
|
|
|
c2 = pyg_boxed_get(other, GimpCMYK);
|
|
|
|
|
|
|
|
if ((c1->c == c2->c && c1->m == c2->m && c1->y == c2->y && c1->k == c2->k && c1->a == c2->a) == (op == Py_EQ))
|
|
|
|
ret = Py_True;
|
|
|
|
else
|
|
|
|
ret = Py_False;
|
|
|
|
|
|
|
|
Py_INCREF(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_pretty_print(PyObject *self, gboolean inexact)
|
|
|
|
{
|
|
|
|
GimpCMYK *cmyk;
|
|
|
|
PyObject *ret = NULL;
|
|
|
|
PyObject *c_f = NULL, *m_f = NULL, *y_f = NULL, *k_f = NULL, *a_f = NULL;
|
|
|
|
PyObject *c = NULL, *m = NULL, *y = NULL, *k = NULL, *a = NULL;
|
|
|
|
reprfunc repr;
|
2008-08-14 05:10:17 +08:00
|
|
|
const char *prefix;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
if (inexact) {
|
|
|
|
repr = PyObject_Str;
|
|
|
|
prefix = "CMYK ";
|
|
|
|
} else {
|
|
|
|
repr = PyObject_Repr;
|
|
|
|
prefix = self->ob_type->tp_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmyk = pyg_boxed_get(self, GimpCMYK);
|
|
|
|
|
|
|
|
if ((c_f = PyFloat_FromDouble(cmyk->c)) == NULL) goto cleanup;
|
|
|
|
if ((m_f = PyFloat_FromDouble(cmyk->m)) == NULL) goto cleanup;
|
|
|
|
if ((y_f = PyFloat_FromDouble(cmyk->y)) == NULL) goto cleanup;
|
|
|
|
if ((k_f = PyFloat_FromDouble(cmyk->k)) == NULL) goto cleanup;
|
|
|
|
if ((a_f = PyFloat_FromDouble(cmyk->a)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
if ((c = repr(c_f)) == NULL) goto cleanup;
|
|
|
|
if ((m = repr(m_f)) == NULL) goto cleanup;
|
|
|
|
if ((y = repr(y_f)) == NULL) goto cleanup;
|
|
|
|
if ((k = repr(k_f)) == NULL) goto cleanup;
|
|
|
|
if ((a = repr(a_f)) == NULL) goto cleanup;
|
|
|
|
|
|
|
|
ret = PyString_FromFormat("%s(%s, %s, %s, %s, %s)",
|
|
|
|
prefix,
|
|
|
|
PyString_AsString(c),
|
|
|
|
PyString_AsString(m),
|
|
|
|
PyString_AsString(y),
|
|
|
|
PyString_AsString(k),
|
|
|
|
PyString_AsString(a));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
Py_XDECREF(c); Py_XDECREF(m); Py_XDECREF(y); Py_XDECREF(k); Py_XDECREF(a);
|
|
|
|
Py_XDECREF(c_f); Py_XDECREF(m_f); Py_XDECREF(y_f); Py_XDECREF(k_f); Py_XDECREF(a_f);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_repr(PyObject *self)
|
|
|
|
{
|
|
|
|
return cmyk_pretty_print(self, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
cmyk_str(PyObject *self)
|
|
|
|
{
|
|
|
|
return cmyk_pretty_print(self, TRUE);
|
|
|
|
}
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
static int
|
2006-07-20 12:53:47 +08:00
|
|
|
cmyk_init(PyGBoxed *self, PyObject *args, PyObject *kwargs)
|
|
|
|
{
|
|
|
|
PyObject *c, *m, *y, *k, *a = NULL;
|
|
|
|
GimpCMYK cmyk;
|
|
|
|
static char *kwlist[] = { "c", "m", "y", "k", "a", NULL };
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
|
|
|
"OOOO|O:set", kwlist,
|
|
|
|
&c, &m, &y, &k, &a))
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1;
|
2006-07-20 12:53:47 +08:00
|
|
|
|
|
|
|
#define SET_MEMBER(m) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
|
|
|
cmyk.m = (double) PyInt_AS_LONG(m) / 255.0; \
|
|
|
|
else if (PyFloat_Check(m)) \
|
|
|
|
cmyk.m = PyFloat_AS_DOUBLE(m); \
|
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be an int or a float"); \
|
2006-09-17 15:05:52 +08:00
|
|
|
return -1; \
|
2006-07-20 12:53:47 +08:00
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
SET_MEMBER(c);
|
|
|
|
SET_MEMBER(m);
|
|
|
|
SET_MEMBER(y);
|
|
|
|
SET_MEMBER(k);
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
SET_MEMBER(a);
|
|
|
|
else
|
|
|
|
cmyk.a = 1.0;
|
|
|
|
|
|
|
|
#undef SET_MEMBER
|
|
|
|
|
|
|
|
self->gtype = GIMP_TYPE_CMYK;
|
|
|
|
self->free_on_dealloc = TRUE;
|
|
|
|
self->boxed = g_boxed_copy(GIMP_TYPE_CMYK, &cmyk);
|
|
|
|
|
2006-09-17 15:05:52 +08:00
|
|
|
return 0;
|
2006-07-20 12:53:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyTypeObject PyGimpCMYK_Type = {
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
0, /* ob_size */
|
|
|
|
"gimpcolor.CMYK", /* tp_name */
|
|
|
|
sizeof(PyGBoxed), /* tp_basicsize */
|
|
|
|
0, /* tp_itemsize */
|
|
|
|
/* methods */
|
|
|
|
(destructor)0, /* tp_dealloc */
|
|
|
|
(printfunc)0, /* tp_print */
|
|
|
|
(getattrfunc)0, /* tp_getattr */
|
|
|
|
(setattrfunc)0, /* tp_setattr */
|
|
|
|
(cmpfunc)0, /* tp_compare */
|
|
|
|
(reprfunc)cmyk_repr, /* tp_repr */
|
|
|
|
(PyNumberMethods*)0, /* tp_as_number */
|
|
|
|
&cmyk_as_sequence, /* tp_as_sequence */
|
2006-10-11 14:02:23 +08:00
|
|
|
&cmyk_as_mapping, /* tp_as_mapping */
|
2006-07-20 12:53:47 +08:00
|
|
|
(hashfunc)cmyk_hash, /* tp_hash */
|
|
|
|
(ternaryfunc)0, /* tp_call */
|
|
|
|
(reprfunc)cmyk_str, /* tp_repr */
|
|
|
|
(getattrofunc)0, /* tp_getattro */
|
|
|
|
(setattrofunc)0, /* tp_setattro */
|
|
|
|
(PyBufferProcs*)0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
|
|
NULL, /* Documentation string */
|
|
|
|
(traverseproc)0, /* tp_traverse */
|
|
|
|
(inquiry)0, /* tp_clear */
|
|
|
|
(richcmpfunc)cmyk_richcompare, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
(getiterfunc)0, /* tp_iter */
|
|
|
|
(iternextfunc)0, /* tp_iternext */
|
|
|
|
cmyk_methods, /* tp_methods */
|
|
|
|
0, /* tp_members */
|
|
|
|
cmyk_getsets, /* tp_getset */
|
|
|
|
NULL, /* tp_base */
|
|
|
|
NULL, /* tp_dict */
|
|
|
|
(descrgetfunc)0, /* tp_descr_get */
|
|
|
|
(descrsetfunc)0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
(initproc)cmyk_init, /* tp_init */
|
|
|
|
(allocfunc)0, /* tp_alloc */
|
|
|
|
(newfunc)0, /* tp_new */
|
|
|
|
(freefunc)0, /* tp_free */
|
|
|
|
(inquiry)0 /* tp_is_gc */
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject *
|
|
|
|
pygimp_cmyk_new(const GimpCMYK *cmyk)
|
2005-06-04 08:17:06 +08:00
|
|
|
{
|
2006-07-20 12:53:47 +08:00
|
|
|
return pyg_boxed_new(GIMP_TYPE_CMYK, (gpointer)cmyk, TRUE, TRUE);
|
2005-06-04 08:17:06 +08:00
|
|
|
}
|
2007-12-30 23:25:13 +08:00
|
|
|
|
|
|
|
int
|
|
|
|
pygimp_rgb_from_pyobject(PyObject *object, GimpRGB *color)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail(color != NULL, FALSE);
|
|
|
|
|
|
|
|
if (pygimp_rgb_check(object)) {
|
|
|
|
*color = *pyg_boxed_get(object, GimpRGB);
|
|
|
|
return 1;
|
|
|
|
} else if (PyString_Check(object)) {
|
|
|
|
if (gimp_rgb_parse_css (color, PyString_AsString(object), -1)) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
PyErr_SetString(PyExc_TypeError, "unable to parse color string");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (PySequence_Check(object)) {
|
|
|
|
PyObject *r, *g, *b, *a = NULL;
|
|
|
|
|
|
|
|
if (!PyArg_ParseTuple(object, "OOO|O", &r, &g, &b, &a))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#define SET_MEMBER(m) G_STMT_START { \
|
|
|
|
if (PyInt_Check(m)) \
|
2008-01-27 13:09:28 +08:00
|
|
|
color->m = (double) PyInt_AS_LONG(m) / 255.0; \
|
2007-12-30 23:25:13 +08:00
|
|
|
else if (PyFloat_Check(m)) \
|
2008-01-27 13:09:28 +08:00
|
|
|
color->m = PyFloat_AS_DOUBLE(m); \
|
2007-12-30 23:25:13 +08:00
|
|
|
else { \
|
|
|
|
PyErr_SetString(PyExc_TypeError, \
|
|
|
|
#m " must be an int or a float"); \
|
2008-01-27 11:01:50 +08:00
|
|
|
return 0; \
|
2007-12-30 23:25:13 +08:00
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
SET_MEMBER(r);
|
|
|
|
SET_MEMBER(g);
|
|
|
|
SET_MEMBER(b);
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
SET_MEMBER(a);
|
|
|
|
else
|
2008-01-27 13:09:28 +08:00
|
|
|
color->a = 1.0;
|
|
|
|
|
|
|
|
gimp_rgb_clamp(color);
|
2008-01-27 11:01:50 +08:00
|
|
|
|
|
|
|
return 1;
|
2007-12-30 23:25:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "could not convert to GimpRGB");
|
|
|
|
return 0;
|
|
|
|
}
|