1/* -*- Mode: C; c-basic-offset: 4 -*-
2 * pygtk- Python bindings for the GTK toolkit.
3 * Copyright (C) 1998-2003  James Henstridge
4 *
5 *   gdkdraw.override: gtk.gdk.draw_* 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%%
23ignore
24  gdk_draw_layout_line_with_colors
25
26%%
27override gdk_draw_polygon kwargs
28static PyObject *
29_wrap_gdk_draw_polygon(PyGObject *self, PyObject *args, PyObject *kwargs)
30{
31    static char *kwlist[] = { "gc", "filled", "points", NULL };
32    PyGObject *gc;
33    PyObject *py_points;
34    gint filled, npoints, i;
35    GdkPoint *points;
36
37    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
38                                     "O!iO:GdkDrawable.draw_polygon", kwlist,
39                                     &PyGdkGC_Type, &gc, &filled, &py_points))
40        return NULL;
41    if (!PySequence_Check(py_points)) {
42        PyErr_SetString(PyExc_TypeError, "points must be a sequence");
43        return NULL;
44    }
45    npoints = PySequence_Length(py_points);
46    points = g_new(GdkPoint, npoints);
47    for (i = 0; i < npoints; i++) {
48        PyObject *item = PySequence_GetItem(py_points, i);
49        Py_DECREF(item);
50        if (!PyArg_ParseTuple(item, "ii", &points[i].x, &points[i].y)) {
51            PyErr_Clear();
52            PyErr_SetString(PyExc_TypeError,
53                            "sequence members must be 2-tuples");
54            g_free(points);
55            return NULL;
56        }
57    }
58    gdk_draw_polygon(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), filled,
59                     points, npoints);
60    g_free(points);
61    Py_INCREF(Py_None);
62    return Py_None;
63}
64%%
65override gdk_draw_text kwargs
66static PyObject *
67_wrap_gdk_draw_text(PyGObject *self, PyObject *args, PyObject *kwargs)
68{
69    static char *kwlist[] = { "font", "gc", "x", "y", "text",NULL};
70    PyGObject *gc;
71    PyObject *font;
72    int x, y;
73    Py_ssize_t len;
74    char *text;
75    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
76                                     "OO!iis#:GdkDrawable.draw_text", kwlist,
77                                     &font, &PyGdkGC_Type, &gc,
78                                     &x, &y, &text, &len))
79        return NULL;
80    if (!pyg_boxed_check(font, GDK_TYPE_FONT)) {
81        PyErr_SetString(PyExc_TypeError, "font must be a GdkFont");
82        return NULL;
83    }
84    gdk_draw_text(GDK_DRAWABLE(self->obj), pyg_boxed_get(font, GdkFont),
85                  GDK_GC(gc->obj), x, y, text, len);
86    Py_INCREF(Py_None);
87    return Py_None;
88}
89%%
90override gdk_draw_points kwargs
91static PyObject *
92_wrap_gdk_draw_points(PyGObject *self, PyObject *args, PyObject *kwargs)
93{
94    static char *kwlist[] = { "gc", "points", NULL };
95    PyGObject *gc;
96    PyObject *py_points;
97    gint npoints, i;
98    GdkPoint *points;
99
100    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
101                                     "O!O:GdkDrawable.draw_points", kwlist,
102                                     &PyGdkGC_Type, &gc, &py_points))
103        return NULL;
104    if (!PySequence_Check(py_points)) {
105        PyErr_SetString(PyExc_TypeError, "points must be a sequence");
106        return NULL;
107    }
108    npoints = PySequence_Length(py_points);
109    points = g_new(GdkPoint, npoints);
110    for (i = 0; i < npoints; i++) {
111        PyObject *item = PySequence_GetItem(py_points, i);
112        Py_DECREF(item);
113        if (!PyArg_ParseTuple(item, "ii", &points[i].x, &points[i].y)) {
114            PyErr_Clear();
115            PyErr_SetString(PyExc_TypeError,
116                            "sequence members must be 2-tuples");
117            g_free(points);
118            return NULL;
119        }
120    }
121    gdk_draw_points(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), points, npoints);
122    g_free(points);
123    Py_INCREF(Py_None);
124    return Py_None;
125}
126%%
127override gdk_draw_segments kwargs
128static PyObject *
129_wrap_gdk_draw_segments(PyGObject *self, PyObject *args, PyObject *kwargs)
130{
131    static char *kwlist[] = { "gc", "segs", NULL };
132    PyGObject *gc;
133    PyObject *py_segs;
134    gint nsegs, i;
135    GdkSegment *segs;
136
137    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
138                                     "O!O:GdkDrawable.draw_segments", kwlist,
139                                     &PyGdkGC_Type, &gc, &py_segs))
140        return NULL;
141    if (!PySequence_Check(py_segs)) {
142        PyErr_SetString(PyExc_TypeError, "segs must be a sequence");
143        return NULL;
144    }
145    nsegs = PySequence_Length(py_segs);
146    segs = g_new(GdkSegment, nsegs);
147    for (i = 0; i < nsegs; i++) {
148        PyObject *item = PySequence_GetItem(py_segs, i);
149        Py_DECREF(item);
150        if (!PyArg_ParseTuple(item, "iiii", &segs[i].x1, &segs[i].y1,
151                              &segs[i].x2, &segs[i].y2)) {
152            PyErr_Clear();
153            PyErr_SetString(PyExc_TypeError,
154                            "sequence members must be 4-tuples");
155            g_free(segs);
156            return NULL;
157        }
158    }
159    gdk_draw_segments(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), segs, nsegs);
160    g_free(segs);
161    Py_INCREF(Py_None);
162    return Py_None;
163}
164%%
165override gdk_draw_lines kwargs
166static PyObject *
167_wrap_gdk_draw_lines(PyGObject *self, PyObject *args, PyObject *kwargs)
168{
169    static char *kwlist[] = { "gc", "points", NULL };
170    PyGObject *gc;
171    PyObject *py_points;
172    gint npoints, i;
173    GdkPoint *points;
174
175    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
176                                     "O!O:GdkDrawable.draw_lines", kwlist,
177                                     &PyGdkGC_Type, &gc, &py_points))
178        return NULL;
179    if (!PySequence_Check(py_points)) {
180        PyErr_SetString(PyExc_TypeError, "points must be a sequence");
181        return NULL;
182    }
183    npoints = PySequence_Length(py_points);
184    points = g_new(GdkPoint, npoints);
185    for (i = 0; i < npoints; i++) {
186        PyObject *item = PySequence_GetItem(py_points, i);
187        Py_DECREF(item);
188        if (!PyArg_ParseTuple(item, "ii", &points[i].x, &points[i].y)) {
189            PyErr_Clear();
190            PyErr_SetString(PyExc_TypeError,
191                            "sequence members must be 2-tuples");
192            g_free(points);
193            return NULL;
194        }
195    }
196    gdk_draw_lines(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), points, npoints);
197    g_free(points);
198    Py_INCREF(Py_None);
199    return Py_None;
200}
201%%
202override gdk_draw_rgb_image kwargs
203static PyObject *
204_wrap_gdk_draw_rgb_image(PyGObject *self, PyObject *args, PyObject *kwargs)
205{
206    static char *kwlist[] = { "gc", "x", "y", "width", "height", "dith",
207                              "rgb_buf", "rowstride", "xdith", "ydith", NULL };
208    PyGObject *gc;
209    PyObject *py_dith;
210    gint x, y, width, height, rowstride = -1, xdith = 0, ydith = 0;
211    Py_ssize_t len;
212    GdkRgbDither dith;
213    guchar *rgb_buf;
214
215    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
216                                     "O!iiiiOs#|iii:GdkDrawable.draw_rgb_image",
217                                     kwlist, &PyGdkGC_Type, &gc, &x, &y,
218                                     &width, &height, &py_dith,
219                                     &rgb_buf, &len, &rowstride,
220                                     &xdith, &ydith))
221        return NULL;
222
223    if (pyg_enum_get_value(GDK_TYPE_RGB_DITHER, py_dith, (gint *)&dith))
224        return NULL;
225    if (!(width > 0 && height > 0)) {
226        PyErr_SetString(PyExc_ValueError,
227                        "height and width must be greater than zero");
228        return NULL;
229    }
230    if (rowstride == -1) rowstride = width * 3;
231    if (len < rowstride * (height - 1) + width*3) {
232        PyErr_SetString(PyExc_IndexError, "rgb_buf is not large enough");
233        return NULL;
234    }
235      /* We always call gdk_draw_rgb_image_dithalign instead of
236       * gdk_draw_rgb_image, since gdk_draw_rgb_image is strictly
237       * equivalent to calling gdk_draw_rgb_image_dithalign with
238       * xdith=0 and ydith=0, which are their default values. */
239    gdk_draw_rgb_image_dithalign(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj),
240                                 x, y, width, height, dith, rgb_buf,
241                                 rowstride, xdith, ydith);
242    Py_INCREF(Py_None);
243    return Py_None;
244}
245%%
246ignore gdk_draw_rgb_image_dithalign
247%%
248override gdk_draw_rgb_32_image kwargs
249static PyObject *
250_wrap_gdk_draw_rgb_32_image(PyGObject *self, PyObject *args, PyObject *kwargs)
251{
252    static char *kwlist[] = { "gc", "x", "y", "width", "height", "dith",
253                              "rgb_buf", "rowstride", "xdith", "ydith", NULL };
254    PyGObject *gc;
255    PyObject *py_dith;
256    gint x, y, width, height, rowstride = -1, xdith = 0, ydith = 0;
257    Py_ssize_t len;
258    GdkRgbDither dith;
259    guchar *rgb_buf;
260
261    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
262                                "O!iiiiOs#|iii:GdkDrawable.draw_rgb_32_image",
263                                     kwlist, &PyGdkGC_Type, &gc, &x, &y,
264                                     &width, &height, &py_dith,
265                                     &rgb_buf, &len, &rowstride,
266                                     &xdith, &ydith))
267        return NULL;
268
269    if (pyg_enum_get_value(GDK_TYPE_RGB_DITHER, py_dith, (gint *)&dith))
270        return NULL;
271    if (!(width > 0 && height > 0)) {
272        PyErr_SetString(PyExc_ValueError,
273                        "height and width must be greater than zero");
274        return NULL;
275    }
276    if (rowstride == -1) rowstride = width * 4;
277    if (len < rowstride * (height - 1) + width*4) {
278        PyErr_SetString(PyExc_IndexError, "rgb_buf is not large enough");
279        return NULL;
280    }
281      /* We always call gdk_draw_rgb_32_image_dithalign instead of
282       * gdk_draw_rgb_32_image, since gdk_draw_rgb_32_image is strictly
283       * equivalent to calling gdk_draw_rgb_32_image_dithalign with
284       * xdith=0 and ydith=0, which are their default values. */
285    gdk_draw_rgb_32_image_dithalign(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj),
286                                    x, y, width, height, dith, rgb_buf,
287                                    rowstride, xdith, ydith);
288    Py_INCREF(Py_None);
289    return Py_None;
290}
291%%
292ignore gdk_draw_rgb_32_image_dithalign
293%%
294override gdk_draw_gray_image kwargs
295static PyObject *
296_wrap_gdk_draw_gray_image(PyGObject *self, PyObject *args, PyObject *kwargs)
297{
298    static char *kwlist[] = { "gc", "x", "y", "width", "height", "dith",
299                              "buf", "rowstride", NULL };
300    PyGObject *gc;
301    PyObject *py_dith;
302    gint x, y, width, height, rowstride = -1;
303    Py_ssize_t len;
304    GdkRgbDither dith;
305    guchar *buf;
306
307    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
308                                     "O!iiiiOs#|i:GdkDrawable.draw_gray_image",
309                                     kwlist, &PyGdkGC_Type, &gc, &x, &y,
310                                     &width, &height, &py_dith,
311                                     &buf, &len, &rowstride))
312        return NULL;
313
314    if (pyg_enum_get_value(GDK_TYPE_RGB_DITHER, py_dith, (gint *)&dith))
315        return NULL;
316    if (!(width > 0 && height > 0)) {
317        PyErr_SetString(PyExc_ValueError,
318                        "height and width must be greater than zero");
319        return NULL;
320    }
321    if (rowstride == -1) rowstride = width;
322    if (len < rowstride * (height - 1) + width) {
323        PyErr_SetString(PyExc_IndexError, "buf is not large enough");
324        return NULL;
325    }
326    gdk_draw_gray_image(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), x, y,
327                        width, height, dith, buf, rowstride);
328    Py_INCREF(Py_None);
329    return Py_None;
330}
331%%
332override gdk_draw_indexed_image kwargs
333static PyObject *
334_wrap_gdk_draw_indexed_image(PyGObject *self, PyObject *args, PyObject *kwargs)
335{
336    static char *kwlist[] = { "gc", "x", "y", "width", "height", "dith",
337                              "buf", "rowstride", "colors", NULL };
338    PyGObject *gc;
339    PyObject *py_dith;
340    gint x, y, width, height, rowstride = -1;
341    Py_ssize_t len;
342    GdkRgbDither dith;
343    guchar *buf;
344    PyObject *pycolors;
345    GdkRgbCmap *cmap;
346    guint32 *colors;
347    int i, n_colors;
348
349    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
350                                     "O!iiiiOs#iO:GdkDrawable.draw_indexed_image",
351                                     kwlist, &PyGdkGC_Type, &gc, &x, &y,
352                                     &width, &height, &py_dith,
353                                     &buf, &len, &rowstride,
354				     &pycolors))
355        return NULL;
356
357    if (pyg_enum_get_value(GDK_TYPE_RGB_DITHER, py_dith, (gint *)&dith))
358        return NULL;
359    if (!(width > 0 && height > 0)) {
360        PyErr_SetString(PyExc_ValueError,
361                        "height and width must be greater than zero");
362        return NULL;
363    }
364    if (rowstride == -1) rowstride = width;
365    if (len < rowstride * (height - 1) + width) {
366        PyErr_SetString(PyExc_IndexError, "buf is not large enough");
367        return NULL;
368    }
369    if (!PyList_Check(pycolors)) {
370        PyErr_SetString(PyExc_TypeError, "colors must be a list");
371        return NULL;
372    }
373    n_colors = PyList_Size(pycolors);
374    colors = g_new0(guint32, n_colors);
375    for (i = 0; i < n_colors; i++)
376	colors[i] = PyInt_AsLong(PyList_GetItem(pycolors, i));
377    cmap = gdk_rgb_cmap_new(colors, n_colors);
378    g_free(colors);
379    gdk_draw_indexed_image(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), x, y,
380			   width, height, dith, buf, rowstride,
381			   cmap);
382    gdk_rgb_cmap_free(cmap);
383    Py_INCREF(Py_None);
384    return Py_None;
385}
386%%
387override gdk_draw_layout kwargs
388static PyObject *
389_wrap_gdk_draw_layout(PyGObject *self, PyObject *args, PyObject *kwargs)
390{
391    static char *kwlist[] = { "gc", "x", "y", "layout", "foreground",
392			      "background", NULL };
393    PyGObject *gc, *layout;
394    int x, y;
395    GdkColor *foreground = NULL, *background = NULL;
396    PyObject *py_foreground = Py_None, *py_background = Py_None;
397
398    if (!PyArg_ParseTupleAndKeywords(
399	    args, kwargs, "O!iiO!|OO:GdkDrawable.draw_layout",
400	    kwlist, &PyGdkGC_Type, &gc, &x, &y, &PyPangoLayout_Type, &layout,
401	    &py_foreground, &py_background))
402        return NULL;
403    if (pyg_boxed_check(py_foreground, GDK_TYPE_COLOR))
404        foreground = pyg_boxed_get(py_foreground, GdkColor);
405    else if (py_foreground != Py_None) {
406        PyErr_SetString(PyExc_TypeError,
407			"foreground should be a GdkColor or None");
408        return NULL;
409    }
410    if (pyg_boxed_check(py_background, GDK_TYPE_COLOR))
411        background = pyg_boxed_get(py_background, GdkColor);
412    else if (py_background != Py_None) {
413        PyErr_SetString(PyExc_TypeError,
414			"background should be a GdkColor or None");
415        return NULL;
416    }
417    gdk_draw_layout_with_colors(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj), x, y,
418				PANGO_LAYOUT(layout->obj), foreground,
419				background);
420    Py_INCREF(Py_None);
421    return Py_None;
422}
423%%
424override gdk_draw_layout_line kwargs
425static PyObject *
426_wrap_gdk_draw_layout_line(PyGObject *self, PyObject *args, PyObject *kwargs)
427{
428    static char *kwlist[] = { "gc", "x", "y", "line", "foreground",
429			      "background", NULL };
430    PyGObject *gc, *py_line;
431    int x, y;
432    GdkColor *foreground = NULL, *background = NULL;
433    PyObject *py_foreground = Py_None, *py_background = Py_None;
434    PangoLayoutLine *line;
435
436    if (!PyArg_ParseTupleAndKeywords(
437	    args, kwargs, "O!iiO|OO:GdkDrawable.draw_layout_line",
438	    kwlist, &PyGdkGC_Type, &gc, &x, &y, &py_line,
439	    &py_foreground, &py_background))
440        return NULL;
441    if (pyg_boxed_check(py_line, PANGO_TYPE_LAYOUT_LINE))
442        line = pyg_boxed_get(py_line, PangoLayoutLine);
443    else {
444        PyErr_SetString(PyExc_TypeError, "line should be a PangoLayoutLine");
445        return NULL;
446    }
447    if (pyg_boxed_check(py_foreground, GDK_TYPE_COLOR))
448        foreground = pyg_boxed_get(py_foreground, GdkColor);
449    else if (py_foreground != Py_None) {
450        PyErr_SetString(PyExc_TypeError,
451			"foreground should be a GdkColor or None");
452        return NULL;
453    }
454    if (pyg_boxed_check(py_background, GDK_TYPE_COLOR))
455        background = pyg_boxed_get(py_background, GdkColor);
456    else if (py_background != Py_None) {
457        PyErr_SetString(PyExc_TypeError,
458			"background should be a GdkColor or None");
459        return NULL;
460    }
461    gdk_draw_layout_line_with_colors(GDK_DRAWABLE(self->obj), GDK_GC(gc->obj),
462                                     x, y, line, foreground, background);
463    Py_INCREF(Py_None);
464    return Py_None;
465}
466