1/* -*- Mode: C; c-basic-offset: 4 -*-
2 * pygtk- Python bindings for the GTK toolkit.
3 * Copyright (C) 1998-2003  James Henstridge
4 *
5 *   gdkpixbuf.override: gtk.gdk.Pixbuf and gtk.gdk.PixbufLoader overrides
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20 * USA
21 */
22%%
23override gdk_pixbuf_render_pixmap_and_mask kwargs
24static PyObject *
25_wrap_gdk_pixbuf_render_pixmap_and_mask(PyGObject *self, PyObject *args,
26                                        PyObject *kwargs)
27{
28    static char *kwlist[] = { "alpha_threshold", NULL};
29    int alpha_threshold = 127;
30    GdkPixmap *pixmap;
31    GdkBitmap *mask;
32    PyObject *pypixmap, *pymask, *ret;
33
34    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
35                                     "|i:GdkPixbuf.render_pixmap_and_mask", kwlist,
36                                     &alpha_threshold))
37        return NULL;
38    gdk_pixbuf_render_pixmap_and_mask(GDK_PIXBUF(self->obj), &pixmap, &mask,
39                                      alpha_threshold);
40
41    if (pixmap) {
42        pypixmap = pygobject_new((GObject *) pixmap);
43        g_object_unref(pixmap);
44    } else {
45        Py_INCREF(Py_None);
46        pypixmap = Py_None;
47    }
48
49    if (mask) {
50        pymask = pygobject_new((GObject *) mask);
51        gdk_bitmap_unref(mask);
52    } else {
53        Py_INCREF(Py_None);
54        pymask = Py_None;
55    }
56
57    ret = Py_BuildValue("(NN)", pypixmap, pymask);
58    return ret;
59}
60%%
61override-attr GdkPixbuf.pixel_array
62#ifdef HAVE_NUMPY
63static int
64have_numpy(void)
65{
66    /* Return 1 if Numeric is available,
67       return 0 and set and exception if it is not. */
68    static int import_done = 0;
69    static PyObject *exc_type=NULL, *exc_value=NULL;
70    PyObject *exc_tb=NULL;
71
72    if (exc_type != NULL) {
73	PyErr_Restore(exc_type, exc_value, NULL);
74	return 0;
75    }
76    if (!import_done) {
77	import_done = 1;
78	import_array1(1);
79	if (PyErr_Occurred()) {
80	    PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
81	    Py_INCREF(exc_type);
82	    Py_XINCREF(exc_value);
83	    PyErr_Restore(exc_type, exc_value, exc_tb);
84	    return 0;
85	}
86    }
87    return 1;
88}
89#endif
90static PyObject *
91_wrap_gdk_pixbuf__get_pixel_array(PyGObject *self, void *closure)
92{
93    PyErr_Warn(PyExc_DeprecationWarning, "use pixbuf.get_pixels_array() instead of the pixbuf.pixel_array attribute");
94    return _wrap_gdk_pixbuf_get_pixels_array(self);
95}
96%%
97define GdkPixbuf.get_pixels_array noargs
98static PyObject *
99_wrap_gdk_pixbuf_get_pixels_array(PyGObject *self)
100{
101
102
103#ifdef HAVE_NUMPY
104    GdkPixbuf *pixbuf = GDK_PIXBUF(self->obj);
105    PyArrayObject *array;
106    int dims[3] = { 0, 0, 3 };
107
108    if (!have_numpy())
109	return NULL;
110
111    dims[0] = gdk_pixbuf_get_height(pixbuf);
112    dims[1] = gdk_pixbuf_get_width(pixbuf);
113    if (gdk_pixbuf_get_has_alpha(pixbuf))
114        dims[2] = 4;
115    array = (PyArrayObject *)PyArray_FromDimsAndData(3, dims, PyArray_UBYTE,
116                                        (char *)gdk_pixbuf_get_pixels(pixbuf));
117    if (array == NULL)
118        return NULL;
119
120    array->strides[0] = gdk_pixbuf_get_rowstride(pixbuf);
121    /* the array holds a ref to the pixbuf pixels through this wrapper*/
122    Py_INCREF(self);
123    array->base = (PyObject *)self;
124    return PyArray_Return(array);
125#else
126    PyErr_SetString(PyExc_RuntimeError, "pygtk was not compiled with Numeric Python support");
127    return NULL;
128#endif
129}
130%%
131override gdk_pixbuf_get_pixels noargs
132static PyObject *
133_wrap_gdk_pixbuf_get_pixels(PyGObject *self)
134{
135    GdkPixbuf *pixbuf;
136    guchar *pixels;
137    gint rowstride, height;
138
139    pixbuf = GDK_PIXBUF(self->obj);
140    pixels = gdk_pixbuf_get_pixels(pixbuf);
141    rowstride = gdk_pixbuf_get_rowstride(pixbuf);
142    height = gdk_pixbuf_get_height(pixbuf);
143
144    if (pixels == NULL) {
145        PyErr_SetString(PyExc_ValueError, "could not get pixel data");
146        return NULL;
147    }
148
149    return PyString_FromStringAndSize((char*)pixels, rowstride*height);
150}
151%%
152override gdk_pixbuf_save kwargs
153static PyObject *
154_wrap_gdk_pixbuf_save(PyGObject *self, PyObject *args,
155                      PyObject *kwargs)
156{
157    static char *kwlist[] = {"filename", "type", "options", NULL};
158    gchar *filename, *type, **option_keys = NULL, **option_values = NULL;
159    PyObject *py_options = NULL;
160    GError *error = NULL;
161
162    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
163                                     "ss|O!:GdkPixbuf.save", kwlist,
164                                     &filename, &type,
165                                     &PyDict_Type, &py_options))
166        return NULL;
167
168    if (py_options != NULL) {
169        guint len;
170        Py_ssize_t pos = 0, i = 0;
171        PyObject *key, *value;
172
173        len = PyDict_Size(py_options);
174        option_keys = g_new(gchar *, len + 1);
175        option_values = g_new(gchar *, len + 1);
176
177        while (PyDict_Next(py_options, &pos, &key, &value)) {
178            if (!PyString_Check(key) || !PyString_Check(value)) {
179                g_free(option_keys);
180                g_free(option_values);
181                PyErr_SetString(PyExc_TypeError,
182                                "keys and values must be strings");
183                return NULL;
184            }
185
186            option_keys[i]   = PyString_AsString(key);
187            option_values[i] = PyString_AsString(value);
188            i++;
189        }
190
191        option_keys[len] = NULL;
192        option_values[len] = NULL;
193    }
194
195    pyg_begin_allow_threads;
196    gdk_pixbuf_savev(GDK_PIXBUF(self->obj), filename, type,
197                     option_keys, option_values, &error);
198    pyg_end_allow_threads;
199
200    g_free(option_keys);
201    g_free(option_values);
202
203    if (pyg_error_check(&error))
204        return NULL;
205
206    Py_INCREF(Py_None);
207    return Py_None;
208}
209
210%%
211override gdk_pixbuf_save_to_callback kwargs
212
213typedef struct {
214    PyObject *callback;
215    PyObject *user_data;
216} py_pixbuf_save_callback_data_t;
217
218static gboolean
219pixbuf_save_func(const gchar *buf,
220                 gsize count,
221                 GError **error,
222                 py_pixbuf_save_callback_data_t *data)
223{
224    PyObject *ret;
225
226    if (data->user_data)
227        ret = PyObject_CallFunction(data->callback, "s#O", buf, (Py_ssize_t) count, data->user_data);
228
229    else
230        ret = PyObject_CallFunction(data->callback, "s#", buf, (Py_ssize_t) count);
231
232    if (ret == NULL) {
233        PyErr_Print();
234        return FALSE;
235    }
236    Py_DECREF(ret);
237    return TRUE;
238}
239
240static PyObject *
241_wrap_gdk_pixbuf_save_to_callback(PyGObject *self, PyObject *args,
242                                  PyObject *kwargs)
243{
244    static char *kwlist[] = {"save_func", "type", "options", "user_data", NULL};
245    gchar *type, **option_keys = NULL, **option_values = NULL;
246    PyObject *py_options = NULL;
247    GError *error = NULL;
248    py_pixbuf_save_callback_data_t data = { NULL, NULL };
249
250    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
251                                     "Os|O!O:GdkPixbuf.save", kwlist,
252                                     &data.callback, &type,
253                                     &PyDict_Type, &py_options, &data.user_data))
254        return NULL;
255
256    if (!PyCallable_Check(data.callback)) {
257        PyErr_SetString(PyExc_TypeError, "first argument must be callable");
258        return NULL;
259    }
260
261    if (py_options != NULL) {
262        Py_ssize_t len;
263        Py_ssize_t pos = 0, i = 0;
264        PyObject *key, *value;
265
266        len = PyDict_Size(py_options);
267        option_keys = g_new(gchar *, len + 1);
268        option_values = g_new(gchar *, len + 1);
269
270        while (PyDict_Next(py_options, &pos, &key, &value)) {
271            if (!PyString_Check(key) || !PyString_Check(value)) {
272                g_free(option_keys);
273                g_free(option_values);
274                PyErr_SetString(PyExc_TypeError,
275                                "keys and values must be strings");
276                return NULL;
277            }
278
279            option_keys[i]   = PyString_AsString(key);
280            option_values[i] = PyString_AsString(value);
281            i++;
282        }
283
284        option_keys[len] = NULL;
285        option_values[len] = NULL;
286    }
287    gdk_pixbuf_save_to_callbackv(GDK_PIXBUF(self->obj),
288                                 (GdkPixbufSaveFunc) pixbuf_save_func, &data,
289                                 type, option_keys, option_values, &error);
290    g_free(option_keys);
291    g_free(option_values);
292
293    if (pyg_error_check(&error))
294        return NULL;
295
296    Py_INCREF(Py_None);
297    return Py_None;
298}
299%%
300override gdk_pixbuf_new_from_data kwargs
301static PyObject *
302_wrap_gdk_pixbuf_new_from_data(PyObject *self, PyObject *args,
303			       PyObject *kwargs)
304{
305    static char *kwlist[] = { "data", "colorspace", "has_alpha",
306			      "bits_per_sample", "width", "height",
307			      "rowstride", NULL };
308    const gchar *data;
309    GdkColorspace colorspace;
310    gboolean has_alpha;
311    Py_ssize_t data_len;
312    gint bits_per_sample, width, height, rowstride;
313    Py_ssize_t required_len;
314    guchar *data_copy;
315    GdkPixbuf *pixbuf;
316    PyObject *ret;
317
318    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
319				     "s#iiiiii:pixbuf_new_from_data", kwlist,
320				     &data, &data_len, &colorspace,
321				     &has_alpha, &bits_per_sample,
322				     &width, &height, &rowstride))
323	return NULL;
324    required_len = height*rowstride;
325    if (data_len < required_len) {
326	PyErr_Format(PyExc_ValueError,
327		      "data length (%ld) is less then required by the other parameters (%ld)",
328		      (long int) data_len, (long int) required_len);
329	return NULL;
330    }
331    data_copy = g_try_malloc(required_len);
332    if (!data_copy)
333	return PyErr_NoMemory();
334    memcpy(data_copy, data, required_len);
335    pixbuf = gdk_pixbuf_new_from_data(data_copy, colorspace, has_alpha,
336				      bits_per_sample, width, height,
337				      rowstride,
338				      (GdkPixbufDestroyNotify )g_free, NULL);
339    ret = pygobject_new((GObject *)pixbuf);
340    g_object_unref(pixbuf);
341    return ret;
342}
343%%
344override gdk_pixbuf_new_from_array kwargs
345static PyObject *
346_wrap_gdk_pixbuf_new_from_array(PyObject *self, PyObject *args,
347				PyObject *kwargs)
348{
349#ifdef HAVE_NUMPY
350    static char *kwlist[] = { "array", "colorspace", "bits_per_sample", NULL };
351    PyArrayObject *array;
352    GdkColorspace colorspace;
353    gint bits_per_sample ;
354    GdkPixbuf *pixbuf;
355    PyObject *ret;
356    gboolean has_alpha;
357    gint width, height;
358    gint i, j, nc, rs, st0, st1, st2;
359    guchar *src, *dst;
360
361    if (!have_numpy())
362	return NULL;
363
364    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
365				      "O!ii:pixbuf_new_from_array", kwlist,
366				      &PyArray_Type, &array, &colorspace,
367				      &bits_per_sample))
368	return NULL;
369    if (array->descr->type_num != PyArray_CHAR
370	&& array->descr->type_num != PyArray_UBYTE) {
371	PyErr_SetString(PyExc_TypeError, "array type must be 'c' or 'b'");
372	return NULL;
373    }
374    if (array->nd != 3 || array->dimensions[2] < 3 || array->dimensions[2] > 4) {
375	PyErr_SetString(PyExc_TypeError, "array shape must be (n,m,3) or (n,m,4)");
376	return NULL;
377    }
378    height = array->dimensions[0];
379    width = array->dimensions[1];
380    has_alpha = array->dimensions[2] == 4;
381    pixbuf = gdk_pixbuf_new(colorspace, has_alpha, bits_per_sample,
382			    width, height);
383    src = (guchar*) array->data;
384    dst = gdk_pixbuf_get_pixels(pixbuf);
385    nc = gdk_pixbuf_get_n_channels(pixbuf);
386    rs = gdk_pixbuf_get_rowstride(pixbuf);
387    st0 = array->strides[0];
388    st1 = array->strides[1];
389    st2 = array->strides[2];
390    if (has_alpha) {
391	for (j = 0; j < height; j++) {
392	    for (i = 0; i < width; i++) {
393		dst[j*rs + i*4 + 0] = src[j*st0 + i*st1 + 0*st2];
394		dst[j*rs + i*4 + 1] = src[j*st0 + i*st1 + 1*st2];
395		dst[j*rs + i*4 + 2] = src[j*st0 + i*st1 + 2*st2];
396		dst[j*rs + i*4 + 3] = src[j*st0 + i*st1 + 3*st2];
397	    }
398	}
399    } else {
400	for (j = 0; j < height; j++) {
401	    for (i = 0; i < width; i++) {
402		dst[j*rs + i*3 + 0] = src[j*st0 + i*st1 + 0*st2];
403		dst[j*rs + i*3 + 1] = src[j*st0 + i*st1 + 1*st2];
404		dst[j*rs + i*3 + 2] = src[j*st0 + i*st1 + 2*st2];
405	    }
406	}
407    }
408    ret = pygobject_new((GObject *)pixbuf);
409    g_object_unref(pixbuf);
410    return ret;
411
412#else
413    PyErr_SetString(PyExc_RuntimeError, "pygtk was not compiled with Numeric Python support");
414    return NULL;
415#endif
416}
417%%
418override gdk_pixbuf_new_from_xpm_data kwargs
419static PyObject *
420_wrap_gdk_pixbuf_new_from_xpm_data(PyObject *self, PyObject *args,
421                                   PyObject *kwargs)
422{
423    static char *kwlist[] = { "data", NULL };
424    PyObject *py_data, *ret;
425    gchar **data;
426    int len, i;
427    GdkPixbuf *pixbuf;
428
429    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
430                                     "O!:pixbuf_new_from_xpm_data", kwlist,
431                                     &PyList_Type, &py_data))
432        return NULL;
433    len = PyList_Size(py_data);
434    data = g_new(gchar *, len);
435    for (i = 0; i < len; i ++) {
436        PyObject *item = PyList_GetItem(py_data, i);
437        if (!PyString_Check(item)) {
438            PyErr_SetString(PyExc_TypeError, "data items must be strings");
439            g_free(data);
440            return NULL;
441        }
442        data[i] = PyString_AsString(item);
443    }
444    pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)data);
445    g_free(data);
446    if (pixbuf == NULL) {
447        PyErr_SetString(PyExc_IOError, "can't load pixbuf");
448        return NULL;
449    }
450    ret = pygobject_new((GObject *)pixbuf);
451    g_object_unref(pixbuf);
452    return ret;
453}
454%%
455override gdk_pixbuf_loader_new_with_type kwargs
456static int
457_wrap_gdk_pixbuf_loader_new_with_type(PyGObject *self,
458                                      PyObject *args,
459                                      PyObject *kwargs)
460{
461    static char *kwlist[] = { "image_type", NULL };
462    char *image_type = NULL;
463
464    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
465				     "|s:GdkPixbufLoader.__init__",
466				     kwlist, &image_type))
467        return -1;
468
469    if (image_type == NULL) {
470	self->obj = (GObject *)gdk_pixbuf_loader_new();
471    } else {
472	GError *error = NULL;
473	self->obj = (GObject *)gdk_pixbuf_loader_new_with_type(image_type,
474							       &error);
475	if (pyg_error_check(&error))
476	    return -1;
477    }
478
479    if (!self->obj) {
480        PyErr_SetString(PyExc_RuntimeError,
481			"could not create GdkPixbufLoader object");
482        return -1;
483    }
484    pygobject_register_wrapper((PyObject *)self);
485    return 0;
486}
487%%
488override gdk_pixbuf_loader_write kwargs
489static PyObject *
490_wrap_gdk_pixbuf_loader_write(PyGObject *self,
491                              PyObject *args,
492                              PyObject *kwargs)
493{
494    static char *kwlist[] = { "buf", "count", NULL };
495    Py_ssize_t buf_len;
496    int count = -1, ret;
497    guchar *buf;
498    GError *error = NULL;
499
500    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
501                                     "s#|i:GdkPixbufLoader.write",
502                                     kwlist, &buf, &buf_len, &count))
503        return NULL;
504
505    if (count < 0 || count > buf_len) {
506        count = buf_len;
507    }
508
509    ret = gdk_pixbuf_loader_write(GDK_PIXBUF_LOADER(self->obj),
510                                  buf, count, &error);
511
512    if (pyg_error_check(&error))
513        return NULL;
514
515    return PyBool_FromLong(ret);
516}
517%%
518override gdk_pixbuf_animation_get_iter kwargs
519static PyObject *
520_wrap_gdk_pixbuf_animation_get_iter(PyGObject *self, PyObject *args,
521				    PyObject *kwargs)
522{
523    static char *kwlist[] = { "start_time", NULL };
524    GdkPixbufAnimationIter *ret;
525    double start_time = 0.0;
526    GTimeVal starttime, *starttimep;
527    PyObject *pyretval;
528
529    if (!PyArg_ParseTupleAndKeywords(
530	    args, kwargs, "|d:GdkPixbufAnimation.get_iter",
531	    kwlist, &start_time))
532        return NULL;
533
534    if (start_time > 0.0) {
535	starttime.tv_sec = (glong) start_time;
536	starttime.tv_usec = (glong)((start_time - starttime.tv_sec)
537				    * G_USEC_PER_SEC);
538	starttimep = &starttime;
539    } else if (start_time == 0.0) {
540	starttimep = NULL;
541    } else {
542        PyErr_SetString(PyExc_ValueError, "start_time must be >= 0.0");
543        return NULL;
544    }
545
546    ret = gdk_pixbuf_animation_get_iter(GDK_PIXBUF_ANIMATION(self->obj),
547					starttimep);
548    /* pygobject_new handles NULL checking */
549    pyretval = pygobject_new((GObject *)ret);
550    if (ret)
551        g_object_unref(ret);
552    return pyretval;
553}
554%%
555override gdk_pixbuf_animation_iter_advance kwargs
556static PyObject *
557_wrap_gdk_pixbuf_animation_iter_advance(PyGObject *self, PyObject *args,
558				    PyObject *kwargs)
559{
560    static char *kwlist[] = { "current_time", NULL };
561    gboolean ret;
562    double current_time = 0.0;
563    GTimeVal currenttime, *currenttimep;
564
565    if (!PyArg_ParseTupleAndKeywords(
566	    args, kwargs, "|d:GdkPixbufAnimationIter.advance",
567	    kwlist, &current_time))
568        return NULL;
569
570    if (current_time > 0.0) {
571	currenttime.tv_sec = (glong) current_time;
572	currenttime.tv_usec = (glong)((current_time - currenttime.tv_sec)
573				    * G_USEC_PER_SEC);
574	currenttimep = &currenttime;
575    } else if (current_time == 0.0) {
576	currenttimep = NULL;
577    } else {
578        PyErr_SetString(PyExc_ValueError, "current_time must be >= 0.0");
579        return NULL;
580    }
581
582    ret = gdk_pixbuf_animation_iter_advance(GDK_PIXBUF_ANIMATION_ITER(self->obj),
583					    currenttimep);
584
585    return PyBool_FromLong(ret);
586}
587%%
588override gdk_pixbuf_get_formats noargs
589static PyObject *
590pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format)
591{
592    PyObject *item, *value;
593    gchar *sval, **aval;
594    gint i;
595
596    item = PyDict_New();
597
598    sval = gdk_pixbuf_format_get_name(format);
599    value = PyString_FromString(sval);
600    PyDict_SetItemString(item, "name", value);
601    Py_DECREF(value);
602    g_free(sval);
603
604    sval = gdk_pixbuf_format_get_description(format);
605    value = PyString_FromString(sval);
606    PyDict_SetItemString(item, "description", value);
607    Py_DECREF(value);
608    g_free(sval);
609
610    aval = gdk_pixbuf_format_get_mime_types(format);
611    value = PyList_New(0);
612    for (i = 0; aval[i] != NULL; i++) {
613	PyObject *string_item = PyString_FromString(aval[i]);
614
615	PyList_Append(value, string_item);
616	Py_DECREF(string_item);
617    }
618    PyDict_SetItemString(item, "mime_types", value);
619    Py_DECREF(value);
620    g_strfreev(aval);
621
622    aval = gdk_pixbuf_format_get_extensions(format);
623    value = PyList_New(0);
624    for (i = 0; aval[i] != NULL; i++) {
625	PyObject *string_item = PyString_FromString(aval[i]);
626
627	PyList_Append(value, string_item);
628	Py_DECREF(string_item);
629    }
630    PyDict_SetItemString(item, "extensions", value);
631    Py_DECREF(value);
632    g_strfreev(aval);
633
634    PyDict_SetItemString(item, "is_writable",
635			 PyBool_FromLong(gdk_pixbuf_format_is_writable(format)));
636
637    return item;
638}
639static PyObject *
640_wrap_gdk_pixbuf_get_formats(PyObject *self)
641{
642    GSList *list, *tmp;
643    PyObject *ret;
644
645    list = gdk_pixbuf_get_formats();
646    ret = PyList_New(0);
647    for (tmp = list; tmp != NULL; tmp = tmp->next) {
648	PyObject *item;
649	item = pygtk_make_pixbuf_format_dict((GdkPixbufFormat *)(tmp->data));
650
651	PyList_Append(ret, item);
652	Py_DECREF(item);
653    }
654
655    g_slist_free(list);
656
657    return ret;
658}
659%%
660override gdk_pixbuf_fill kwargs
661static PyObject *
662_wrap_gdk_pixbuf_fill(PyGObject *self, PyObject *args, PyObject *kwargs)
663{
664    static char *kwlist[] = { "pixel", NULL };
665    PyObject *py_pixel = NULL;
666
667    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:GdkPixbuf.fill", kwlist, &py_pixel))
668        return NULL;
669
670    if (PyInt_Check(py_pixel))
671	gdk_pixbuf_fill(GDK_PIXBUF(self->obj), PyInt_AsLong(py_pixel));
672    else if (PyLong_Check(py_pixel))
673	gdk_pixbuf_fill(GDK_PIXBUF(self->obj), PyLong_AsUnsignedLong(py_pixel));
674    else {
675	PyErr_SetString(PyExc_TypeError, "pixel must be an int or a long");
676	return NULL;
677    }
678
679    Py_INCREF(Py_None);
680    return Py_None;
681}
682%%
683override gdk_pixbuf_get_file_info kwargs
684static PyObject *
685_wrap_gdk_pixbuf_get_file_info(PyObject *self, PyObject *args,
686			       PyObject *kwargs)
687{
688    PyObject *pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format);
689    static char *kwlist[] = { "filename", NULL };
690    gint width, height;
691    GdkPixbufFormat *format;
692    gchar *filename;
693
694    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
695				     "s:gtk.gdk.pixbuf_get_file_info", kwlist,
696				     &filename))
697	return NULL;
698
699    format = gdk_pixbuf_get_file_info(filename, &width, &height);
700
701    if (format) {
702	PyObject *py_format;
703
704	py_format = pygtk_make_pixbuf_format_dict(format);
705	return Py_BuildValue("(Nii)", py_format, width, height);
706    }
707
708    Py_INCREF(Py_None);
709    return Py_None;
710}
711%%
712override gdk_pixbuf_loader_get_format noargs
713static PyObject *pygtk_make_pixbuf_format_dict(GdkPixbufFormat *format);
714static PyObject *
715_wrap_gdk_pixbuf_loader_get_format(PyGObject *self)
716{
717    GdkPixbufFormat *format;
718
719    format = gdk_pixbuf_loader_get_format(GDK_PIXBUF_LOADER(self->obj));
720
721    if (format)
722	return pygtk_make_pixbuf_format_dict(format);
723
724    Py_INCREF(Py_None);
725    return Py_None;
726}
727%%
728override gdk_pixbuf_get_from_drawable2 kwargs
729static PyObject *
730_wrap_gdk_pixbuf_get_from_drawable2(PyObject *self,
731				    PyObject *args,
732				    PyObject *kwargs)
733{
734    static char *kwlist[] = { "pixbuf", "src", "cmap",
735			      "src_x", "src_y",
736			      "dest_x", "dest_y",
737			      "width", "height", NULL };
738    PyGObject *py_pixbuf, *src, *cmap;
739    int src_x, src_y, dest_x, dest_y, width, height;
740    GdkPixbuf *pixbuf = NULL, *ret;
741
742    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
743				     "OO!O!iiiiii:pixbuf_get_from_drawable",
744				     kwlist,
745				     &py_pixbuf,
746				     &PyGdkDrawable_Type, &src,
747				     &PyGdkColormap_Type, &cmap,
748				     &src_x, &src_y,
749				     &dest_x, &dest_y,
750				     &width, &height))
751        return NULL;
752
753    if (py_pixbuf && pygobject_check(py_pixbuf, &PyGdkPixbuf_Type))
754        pixbuf = GDK_PIXBUF(py_pixbuf->obj);
755    else if ((PyObject *)py_pixbuf != Py_None) {
756        PyErr_SetString(PyExc_TypeError,
757			"pixbuf should be a GdkPixbuf or None");
758        return NULL;
759    }
760
761    ret = gdk_pixbuf_get_from_drawable(pixbuf,
762				       GDK_DRAWABLE(src->obj),
763				       GDK_COLORMAP(cmap->obj),
764				       src_x, src_y,
765				       dest_x, dest_y,
766				       width, height);
767
768    /* pygobject_new handles NULL checking */
769    return pygobject_new((GObject *)ret);
770}
771%%
772override gdk_pixbuf_add_alpha kwargs
773/* Old declaration accepted characters as 'r', 'g' and 'b' arguments.
774 * However, that is flawed, as GTK+ in this case meant '8-bit
775 * integers', not 'characters'.  Override is needed to provide
776 * backward compatibility for already existing uses. */
777static PyObject *
778_wrap_gdk_pixbuf_add_alpha(PyGObject *self, PyObject *args, PyObject *kwargs)
779{
780    static char *kwlist[] = { "substitute_color", "r", "g", "b", NULL };
781    int substitute_color, r, g, b;
782    PyObject *py_ret;
783    GdkPixbuf *ret;
784
785    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iiii:gdk.Pixbuf.add_alpha", kwlist,
786                                     &substitute_color, &r, &g, &b)) {
787        /* Backward compatibility. */
788        PyObject *exc_type, *exc_value, *exc_traceback;
789
790        PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
791
792        if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iccc:gdk.Pixbuf.add_alpha", kwlist,
793                                         &substitute_color, &r, &g, &b)) {
794            PyErr_Restore(exc_type, exc_value, exc_traceback);
795            return NULL;
796        }
797
798        Py_XDECREF(exc_type);
799        Py_XDECREF(exc_value);
800        Py_XDECREF(exc_traceback);
801    }
802
803    ret = gdk_pixbuf_add_alpha(GDK_PIXBUF(self->obj), substitute_color, r, g, b);
804
805    py_ret = pygobject_new((GObject *)ret);
806    if (ret != NULL)
807        g_object_unref(ret);
808    return py_ret;
809}
810