1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * Gimp-Python - allows the writing of Gimp plugins in Python.
3 * Copyright (C) 1997-2002 James Henstridge <james@daa.com.au>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #define NO_IMPORT_PYGOBJECT
24 #include <pygobject.h>
25
26 #define GIMP_DISABLE_DEPRECATION_WARNINGS
27 #include "pygimp.h"
28
29 #define NO_IMPORT_PYGIMPCOLOR
30 #include "pygimpcolor-api.h"
31
32 #include <glib-object.h>
33
34 #include <gegl.h>
35
36 static void
ensure_drawable(PyGimpDrawable * self)37 ensure_drawable(PyGimpDrawable *self)
38 {
39 if (!self->drawable)
40 self->drawable = gimp_drawable_get(self->ID);
41 }
42
43 static PyObject *
drw_flush(PyGimpDrawable * self)44 drw_flush(PyGimpDrawable *self)
45 {
46 ensure_drawable(self);
47
48 gimp_drawable_flush(self->drawable);
49
50 Py_INCREF(Py_None);
51 return Py_None;
52 }
53
54
55 static PyObject *
drw_update(PyGimpDrawable * self,PyObject * args)56 drw_update(PyGimpDrawable *self, PyObject *args)
57 {
58 int x, y;
59 unsigned int w, h;
60
61 if (!PyArg_ParseTuple(args, "iiii:update", &x, &y, &w, &h))
62 return NULL;
63
64 if (!gimp_drawable_update(self->ID, x, y, w, h)) {
65 PyErr_Format(pygimp_error,
66 "could not update drawable (ID %d): "
67 "x=%d, y=%d, w=%d, h=%d",
68 self->ID, x, y, (int)w, (int)h);
69 return NULL;
70 }
71
72 Py_INCREF(Py_None);
73 return Py_None;
74 }
75
76
77 static PyObject *
drw_merge_shadow(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)78 drw_merge_shadow(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
79 {
80 gboolean undo = FALSE;
81
82 static char *kwlist[] = { "undo", NULL };
83
84 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:merge_shadow", kwlist,
85 &undo))
86 return NULL;
87
88 if (!gimp_drawable_merge_shadow(self->ID, undo)) {
89 PyErr_Format(pygimp_error,
90 "could not merge the shadow buffer on drawable (ID %d)",
91 self->ID);
92 return NULL;
93 }
94
95 Py_INCREF(Py_None);
96 return Py_None;
97 }
98
99 static PyObject *
drw_free_shadow(PyGimpDrawable * self)100 drw_free_shadow(PyGimpDrawable *self)
101 {
102 if (!gimp_drawable_free_shadow(self->ID)) {
103 PyErr_Format(pygimp_error, "could not free shadow tiles on drawable (ID %d)",
104 self->ID);
105 return NULL;
106 }
107
108 Py_INCREF(Py_None);
109 return Py_None;
110 }
111
112 static PyObject *
drw_fill(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)113 drw_fill(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
114 {
115 int fill = GIMP_FILL_FOREGROUND;
116
117 static char *kwlist[] = { "fill", NULL };
118
119 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fill", kwlist, &fill))
120 return NULL;
121
122 if (!gimp_drawable_fill(self->ID, fill)) {
123 PyErr_Format(pygimp_error,
124 "could not fill drawable (ID %d) with fill mode %d",
125 self->ID, fill);
126 return NULL;
127 }
128
129 Py_INCREF(Py_None);
130 return Py_None;
131 }
132
133
134 static PyObject *
drw_get_tile(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)135 drw_get_tile(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
136 {
137 GimpTile *t;
138 int shadow, row, col;
139
140 static char *kwlist[] = { "shadow", "row", "col", NULL };
141
142 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii:get_tile", kwlist,
143 &shadow, &row, &col))
144 return NULL;
145
146 ensure_drawable(self);
147
148 if(row < 0 || row >= self->drawable->ntile_rows ||
149 col < 0 || col >= self->drawable->ntile_cols) {
150 Py_INCREF(Py_None);
151 return Py_None;
152 }
153
154 t = gimp_drawable_get_tile(self->drawable, shadow, row, col);
155 return pygimp_tile_new(t, self);
156 }
157
158 static PyObject *
drw_get_tile2(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)159 drw_get_tile2(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
160 {
161 GimpTile *t;
162 int shadow, x, y, row, col;
163
164 static char *kwlist[] = { "shadow", "x", "y", NULL };
165
166 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii:get_tile2", kwlist,
167 &shadow, &x ,&y))
168 return NULL;
169
170 ensure_drawable(self);
171 if(x < 0 || x >= self->drawable->width ||
172 y < 0 || y >= self->drawable->height) {
173 Py_INCREF(Py_None);
174 return Py_None;
175 }
176
177 col = x / gimp_tile_width ();
178 row = y / gimp_tile_height ();
179
180 t = gimp_drawable_get_tile(self->drawable, shadow, col, row);
181 return pygimp_tile_new(t, self);
182 }
183
184 static PyObject *
drw_get_pixel_rgn(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)185 drw_get_pixel_rgn(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
186 {
187 int x, y, width, height, dirty = 1, shadow = 0;
188
189 static char *kwlist[] = { "x", "y", "width", "height", "dirty", "shadow",
190 NULL };
191
192 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
193 "iiii|ii:get_pixel_rgn", kwlist,
194 &x, &y, &width, &height, &dirty, &shadow))
195 return NULL;
196
197 ensure_drawable(self);
198
199 return pygimp_pixel_rgn_new(self, x, y, width, height, dirty, shadow);
200 }
201
202 static PyObject *
drw_offset(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)203 drw_offset(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
204 {
205 int wrap_around;
206 GimpOffsetType fill_type;
207 int offset_x, offset_y;
208
209 static char *kwlist[] = { "wrap_around", "fill_type",
210 "offset_x", "offset_y",
211 NULL };
212
213 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii:offset", kwlist,
214 &wrap_around, &fill_type,
215 &offset_x, &offset_y))
216 return NULL;
217
218 if (!gimp_drawable_offset(self->ID, wrap_around, fill_type,
219 offset_x, offset_y)) {
220 PyErr_Format(pygimp_error,
221 "could not offset drawable (ID %d) by x: %d, y: %d",
222 self->ID, offset_x, offset_y);
223 return NULL;
224 }
225
226 Py_INCREF(Py_None);
227 return Py_None;
228 }
229
230 static PyObject *
drw_parasite_find(PyGimpDrawable * self,PyObject * args)231 drw_parasite_find(PyGimpDrawable *self, PyObject *args)
232 {
233 char *name;
234
235 if (!PyArg_ParseTuple(args, "s:parasite_find", &name))
236 return NULL;
237
238 return pygimp_parasite_new(gimp_item_get_parasite(self->ID, name));
239 }
240
241 static PyObject *
drw_parasite_attach(PyGimpDrawable * self,PyObject * args)242 drw_parasite_attach(PyGimpDrawable *self, PyObject *args)
243 {
244 PyGimpParasite *parasite;
245
246 if (!PyArg_ParseTuple(args, "O!:parasite_attach", &PyGimpParasite_Type,
247 ¶site))
248 return NULL;
249
250 if (!gimp_item_attach_parasite(self->ID, parasite->para)) {
251 PyErr_Format(pygimp_error,
252 "could not attach parasite '%s' on drawable (ID %d)",
253 gimp_parasite_name(parasite->para), self->ID);
254 return NULL;
255 }
256
257 Py_INCREF(Py_None);
258 return Py_None;
259 }
260
261 static PyObject *
drw_attach_new_parasite(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)262 drw_attach_new_parasite(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
263 {
264 char *name;
265 int flags, size;
266 guint8 *data;
267 GimpParasite *parasite;
268 gboolean success;
269
270 static char *kwlist[] = { "name", "flags", "data", NULL };
271
272 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
273 "sis#:attach_new_parasite", kwlist,
274 &name, &flags, &data, &size))
275 return NULL;
276
277 parasite = gimp_parasite_new (name,
278 flags, size + 1, data);
279 success = gimp_item_attach_parasite (self->ID, parasite);
280 gimp_parasite_free (parasite);
281
282 if (!success) {
283 PyErr_Format(pygimp_error,
284 "could not attach new parasite '%s' to drawable (ID %d)",
285 name, self->ID);
286 return NULL;
287 }
288
289 Py_INCREF(Py_None);
290 return Py_None;
291 }
292
293 static PyObject *
drw_parasite_detach(PyGimpDrawable * self,PyObject * args)294 drw_parasite_detach(PyGimpDrawable *self, PyObject *args)
295 {
296 char *name;
297 if (!PyArg_ParseTuple(args, "s:detach_parasite", &name))
298 return NULL;
299
300 if (!gimp_item_detach_parasite(self->ID, name)) {
301 PyErr_Format(pygimp_error,
302 "could not detach parasite '%s' from drawable (ID %d)",
303 name, self->ID);
304 return NULL;
305 }
306
307 Py_INCREF(Py_None);
308 return Py_None;
309 }
310
311 static PyObject *
drw_parasite_list(PyGimpDrawable * self)312 drw_parasite_list(PyGimpDrawable *self)
313 {
314 gint num_parasites;
315 gchar **parasites;
316 PyObject *ret;
317 gint i;
318
319 parasites = gimp_item_get_parasite_list(self->ID, &num_parasites);
320
321 ret = PyTuple_New(num_parasites);
322
323 for (i = 0; i < num_parasites; i++)
324 PyTuple_SetItem(ret, i, PyString_FromString(parasites[i]));
325
326 g_strfreev(parasites);
327 return ret;
328 }
329
330 static PyObject *
drw_get_pixel(PyGimpDrawable * self,PyObject * args)331 drw_get_pixel(PyGimpDrawable *self, PyObject *args)
332 {
333 int x, y;
334 int num_channels, i;
335 guint8 *pixel;
336 PyObject *ret;
337
338 if (!PyArg_ParseTuple(args, "(ii):get_pixel", &x, &y)) {
339 PyErr_Clear();
340 if (!PyArg_ParseTuple(args, "ii:get_pixel", &x, &y))
341 return NULL;
342 }
343
344 pixel = gimp_drawable_get_pixel(self->ID, x, y, &num_channels);
345
346 if (!pixel) {
347 PyErr_Format(pygimp_error,
348 "could not get pixel (%d, %d) on drawable (ID %d)",
349 x, y, self->ID);
350 return NULL;
351 }
352
353 ret = PyTuple_New(num_channels);
354
355 for (i = 0; i < num_channels; i++)
356 PyTuple_SetItem(ret, i, PyInt_FromLong(pixel[i]));
357
358 g_free(pixel);
359
360 return ret;
361 }
362
363 static PyObject *
drw_set_pixel(PyGimpDrawable * self,PyObject * args)364 drw_set_pixel(PyGimpDrawable *self, PyObject *args)
365 {
366 int x, y;
367 int num_channels, i, val;
368 guint8 *pixel;
369 PyObject *seq, *item;
370 gboolean is_string, error = TRUE;
371
372 if (!PyArg_ParseTuple(args, "(ii)O:set_pixel", &x, &y, &seq)) {
373 PyErr_Clear();
374 if (!PyArg_ParseTuple(args, "iiO:set_pixel", &x, &y, &seq))
375 return NULL;
376 }
377
378 if (!PyString_Check(seq)) {
379 if (!PySequence_Check(seq)) {
380 PyErr_SetString(PyExc_TypeError,
381 "pixel values must be a sequence");
382 return NULL;
383 }
384
385 is_string = FALSE;
386
387 num_channels = PySequence_Length(seq);
388 pixel = g_new(guint8, num_channels);
389
390 for (i = 0; i < num_channels; i++) {
391 item = PySequence_GetItem(seq, i);
392
393 if (!PyInt_Check(item)) {
394 PyErr_SetString(PyExc_TypeError,
395 "pixel values must be a sequence of ints");
396 goto out;
397 }
398
399 val = PyInt_AsLong(item);
400
401 if (val < 0 || val > 255) {
402 PyErr_SetString(PyExc_TypeError,
403 "pixel values must be between 0 and 255");
404 goto out;
405 }
406
407 pixel[i] = val;
408 }
409 } else {
410 is_string = TRUE;
411
412 num_channels = PyString_Size(seq);
413 pixel = (guint8 *)PyString_AsString(seq);
414 }
415
416 error = !gimp_drawable_set_pixel(self->ID, x, y, num_channels, pixel);
417
418 if (error)
419 PyErr_Format(pygimp_error,
420 "could not set %d-element pixel (%d, %d) on "
421 "drawable (ID %d)",
422 num_channels, x, y, self->ID);
423
424 out:
425 if (!is_string)
426 g_free(pixel);
427
428 if (!error) {
429 Py_INCREF(Py_None);
430 return Py_None;
431 } else
432 return NULL;
433 }
434
435 static PyObject *
drw_mask_intersect(PyGimpDrawable * self)436 drw_mask_intersect(PyGimpDrawable *self)
437 {
438 int x, y, width, height;
439
440 if (!gimp_drawable_mask_intersect(self->ID, &x, &y, &width, &height)) {
441 PyErr_Format(pygimp_error,
442 "could not get selection bounds of drawable (ID %d)",
443 self->ID);
444 return NULL;
445 }
446
447 return Py_BuildValue("(iiii)", x, y, width, height);
448 }
449
450 static PyObject *
transform_result(PyGimpDrawable * self,gint32 id,const char * err_desc)451 transform_result(PyGimpDrawable *self, gint32 id, const char *err_desc)
452 {
453 if (id == self->ID) {
454 Py_INCREF(self);
455 return (PyObject *)self;
456 } else if (id != -1) {
457 return pygimp_drawable_new(NULL, id);
458 } else {
459 PyErr_Format(pygimp_error, "could not %s drawable (ID %d)",
460 err_desc, self->ID);
461 return NULL;
462 }
463 }
464
465 static PyObject *
drw_transform_flip(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)466 drw_transform_flip(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
467 {
468 double x0, y0, x1, y1;
469 int transform_direction, interpolation, recursion_level = 3;
470 gboolean supersample = FALSE, clip_result = FALSE;
471 gint32 id;
472
473 static char *kwlist[] = { "x0", "y0", "x1", "y1",
474 "transform_direction", "interpolation",
475 "supersample", "recursion_level",
476 "clip_result", NULL };
477
478 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
479 "ddddii|iii:transform_flip", kwlist,
480 &x0, &y0, &x1, &y1, &transform_direction,
481 &interpolation, &supersample,
482 &recursion_level, &clip_result))
483 return NULL;
484
485 gimp_context_push ();
486 gimp_context_set_transform_direction (transform_direction);
487 gimp_context_set_interpolation (interpolation);
488 gimp_context_set_transform_resize (clip_result);
489
490 id = gimp_item_transform_flip (self->ID, x0, y0, x1, y1);
491
492 gimp_context_pop ();
493
494 return transform_result(self, id, "flip");
495 }
496
497 static PyObject *
drw_transform_flip_simple(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)498 drw_transform_flip_simple(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
499 {
500 int flip_type;
501 gboolean auto_center, clip_result = FALSE;
502 double axis;
503 gint32 id;
504
505 static char *kwlist[] = { "flip_type", "auto_center", "axis",
506 "clip_result", NULL };
507
508 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
509 "iid|i:transform_flip_simple", kwlist,
510 &flip_type, &auto_center, &axis,
511 &clip_result))
512 return NULL;
513
514 gimp_context_push ();
515 gimp_context_set_transform_resize (clip_result);
516
517 id = gimp_item_transform_flip_simple (self->ID, flip_type,
518 auto_center, axis);
519
520 gimp_context_pop ();
521
522 return transform_result(self, id, "flip");
523 }
524
525 static PyObject *
drw_transform_flip_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)526 drw_transform_flip_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
527 {
528 double x0, y0, x1, y1;
529 gboolean interpolate = FALSE, clip_result = FALSE;
530 gint32 id;
531
532 static char *kwlist[] = { "x0", "y0", "x1", "y1", "interpolate",
533 "clip_result", NULL };
534
535 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
536 "dddd|ii:transform_flip_default", kwlist,
537 &x0, &y0, &x1, &y1, &interpolate,
538 &clip_result))
539 return NULL;
540
541 gimp_context_push ();
542 if (! interpolate)
543 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
544 gimp_context_set_transform_resize (clip_result);
545
546 id = gimp_item_transform_flip (self->ID, x0, y0, x1, y1);
547
548 gimp_context_pop ();
549
550 return transform_result(self, id, "flip");
551 }
552
553 static PyObject *
drw_transform_perspective(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)554 drw_transform_perspective(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
555 {
556 double x0, y0, x1, y1, x2, y2, x3, y3;
557 int transform_direction, interpolation, recursion_level = 3;
558 gboolean supersample = FALSE, clip_result = FALSE;
559 gint32 id;
560
561 static char *kwlist[] = { "x0", "y0", "x1", "y1", "x2", "y2", "x3", "y3",
562 "transform_direction", "interpolation",
563 "supersample", "recursion_level",
564 "clip_result", NULL };
565
566 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
567 "ddddddddii|iii:transform_perspective",
568 kwlist,
569 &x0, &y0, &x1, &y1, &x2, &y2, &x3, &y3,
570 &transform_direction, &interpolation,
571 &supersample, &recursion_level,
572 &clip_result))
573 return NULL;
574
575 gimp_context_push ();
576 gimp_context_set_transform_direction (transform_direction);
577 gimp_context_set_interpolation (interpolation);
578 gimp_context_set_transform_resize (clip_result);
579
580 id = gimp_item_transform_perspective (self->ID,
581 x0, y0, x1, y1, x2, y2, x3, y3);
582
583 gimp_context_pop ();
584
585 return transform_result(self, id, "apply perspective transform to");
586 }
587
588 static PyObject *
drw_transform_perspective_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)589 drw_transform_perspective_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
590 {
591 double x0, y0, x1, y1, x2, y2, x3, y3;
592 gboolean interpolate = FALSE, clip_result = FALSE;
593 gint32 id;
594
595 static char *kwlist[] = { "x0", "y0", "x1", "y1", "x2", "y2", "x3", "y3",
596 "interpolate", "clip_result", NULL };
597
598 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
599 "dddddddd|ii:transform_perspective_default",
600 kwlist,
601 &x0, &y0, &x1, &y1, &x2, &y2, &x3, &y3,
602 &interpolate, &clip_result))
603 return NULL;
604
605 gimp_context_push ();
606 if (! interpolate)
607 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
608 gimp_context_set_transform_resize (clip_result);
609
610 id = gimp_item_transform_perspective (self->ID,
611 x0, y0, x1, y1, x2, y2, x3, y3);
612
613 gimp_context_pop ();
614
615 return transform_result(self, id, "apply perspective transform to");
616 }
617
618 static PyObject *
drw_transform_rotate(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)619 drw_transform_rotate(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
620 {
621 double angle;
622 gboolean auto_center, supersample = FALSE, clip_result = FALSE;
623 int center_x, center_y, transform_direction, interpolation,
624 recursion_level = 3;
625 gint32 id;
626
627 static char *kwlist[] = { "angle", "auto_center", "center_x", "center_y",
628 "transform_direction", "interpolation",
629 "supersample", "recursion_level",
630 "clip_result", NULL };
631
632 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
633 "diiiii|iii:transform_rotate", kwlist,
634 &angle, &auto_center, ¢er_x, ¢er_y,
635 &transform_direction, &interpolation,
636 &supersample, &recursion_level,
637 &clip_result))
638 return NULL;
639
640 gimp_context_push ();
641 gimp_context_set_transform_direction (transform_direction);
642 gimp_context_set_interpolation (interpolation);
643 gimp_context_set_transform_resize (clip_result);
644
645 id = gimp_item_transform_rotate (self->ID, angle, auto_center,
646 center_x, center_y);
647
648 gimp_context_pop ();
649
650 return transform_result(self, id, "rotate");
651 }
652
653 static PyObject *
drw_transform_rotate_simple(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)654 drw_transform_rotate_simple(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
655 {
656 int rotate_type, center_x, center_y;
657 gboolean auto_center, clip_result = FALSE;
658 gint32 id;
659
660 static char *kwlist[] = { "rotate_type", "auto_center",
661 "center_x", "center_y",
662 "clip_result", NULL };
663
664 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
665 "iiii|i:transform_rotate_simple", kwlist,
666 &rotate_type, &auto_center,
667 ¢er_x, ¢er_y,
668 &clip_result))
669 return NULL;
670
671 gimp_context_push ();
672 gimp_context_set_transform_resize (clip_result);
673
674 id = gimp_item_transform_rotate_simple (self->ID, rotate_type,
675 auto_center,
676 center_x, center_y);
677
678 gimp_context_pop ();
679
680 return transform_result(self, id, "rotate");
681 }
682
683 static PyObject *
drw_transform_rotate_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)684 drw_transform_rotate_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
685 {
686 double angle;
687 gboolean auto_center, interpolate = FALSE, clip_result = FALSE;
688 int center_x, center_y;
689 gint32 id;
690
691 static char *kwlist[] = { "angle", "auto_center", "center_x", "center_y",
692 "interpolate", "clip_result", NULL };
693
694 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
695 "dddd|ii:transform_rotate_default", kwlist,
696 &angle, &auto_center, ¢er_x, ¢er_y,
697 &interpolate, &clip_result))
698 return NULL;
699
700 gimp_context_push ();
701 if (! interpolate)
702 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
703 gimp_context_set_transform_resize (clip_result);
704
705 id = gimp_item_transform_rotate (self->ID, angle, auto_center,
706 center_x, center_y);
707
708 gimp_context_pop ();
709
710 return transform_result(self, id, "rotate");
711 }
712
713 static PyObject *
drw_transform_scale(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)714 drw_transform_scale(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
715 {
716 double x0, y0, x1, y1;
717 int transform_direction, interpolation, recursion_level = 3;
718 gboolean supersample = FALSE, clip_result = FALSE;
719 gint32 id;
720
721 static char *kwlist[] = { "x0", "y0", "x1", "y1",
722 "transform_direction", "interpolation",
723 "supersample", "recursion_level",
724 "clip_result", NULL };
725
726 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
727 "ddddii|iii:transform_scale", kwlist,
728 &x0, &y0, &x1, &y1, &transform_direction,
729 &interpolation, &supersample,
730 &recursion_level, &clip_result))
731 return NULL;
732
733 gimp_context_push ();
734 gimp_context_set_transform_direction (transform_direction);
735 gimp_context_set_interpolation (interpolation);
736 gimp_context_set_transform_resize (clip_result);
737
738 id = gimp_item_transform_scale (self->ID, x0, y0, x1, y1);
739
740 gimp_context_pop ();
741
742 return transform_result(self, id, "scale");
743 }
744
745 static PyObject *
drw_transform_scale_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)746 drw_transform_scale_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
747 {
748 double x0, y0, x1, y1;
749 gboolean interpolate = FALSE, clip_result = FALSE;
750 gint32 id;
751
752 static char *kwlist[] = { "x0", "y0", "x1", "y1", "interpolate",
753 "clip_result", NULL };
754
755 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
756 "dddd|ii:transform_scale_default", kwlist,
757 &x0, &y0, &x1, &y1, &interpolate,
758 &clip_result))
759 return NULL;
760
761 gimp_context_push ();
762 if (! interpolate)
763 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
764 gimp_context_set_transform_resize (clip_result);
765
766 id = gimp_item_transform_scale (self->ID, x0, y0, x1, y1);
767
768 gimp_context_pop ();
769
770 return transform_result(self, id, "scale");
771 }
772
773 static PyObject *
drw_transform_shear(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)774 drw_transform_shear(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
775 {
776 int shear_type, transform_direction, interpolation, recursion_level = 3;
777 double magnitude;
778 gboolean supersample = FALSE, clip_result = FALSE;
779 gint32 id;
780
781 static char *kwlist[] = { "shear_type", "magnitude",
782 "transform_direction", "interpolation",
783 "supersample", "recursion_level",
784 "clip_result", NULL };
785
786 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
787 "idii|iii:transform_shear", kwlist,
788 &shear_type, &magnitude,
789 &transform_direction, &interpolation,
790 &supersample, &recursion_level,
791 &clip_result))
792 return NULL;
793
794 gimp_context_push ();
795 gimp_context_set_transform_direction (transform_direction);
796 gimp_context_set_interpolation (interpolation);
797 gimp_context_set_transform_resize (clip_result);
798
799 id = gimp_item_transform_shear (self->ID, shear_type, magnitude);
800
801 gimp_context_pop ();
802
803 return transform_result(self, id, "shear");
804 }
805
806 static PyObject *
drw_transform_shear_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)807 drw_transform_shear_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
808 {
809 int shear_type;
810 double magnitude;
811 gboolean interpolate = FALSE, clip_result = FALSE;
812 gint32 id;
813
814 static char *kwlist[] = { "shear_type", "magnitude", "interpolate",
815 "clip_result", NULL };
816
817 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
818 "id|ii:transform_shear_default", kwlist,
819 &shear_type, &magnitude, &interpolate,
820 &clip_result))
821 return NULL;
822
823 gimp_context_push ();
824 if (! interpolate)
825 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
826 gimp_context_set_transform_resize (clip_result);
827
828 id = gimp_item_transform_shear (self->ID, shear_type, magnitude);
829
830 gimp_context_pop ();
831
832 return transform_result(self, id, "shear");
833 }
834
835 static PyObject *
drw_transform_2d(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)836 drw_transform_2d(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
837 {
838 double source_x, source_y, scale_x, scale_y, angle, dest_x, dest_y;
839 int transform_direction, interpolation, recursion_level = 3;
840 gboolean supersample = FALSE, clip_result = FALSE;
841 gint32 id;
842
843 static char *kwlist[] = { "source_x", "source_y", "scale_x", "scale_y",
844 "angle", "dest_x", "dest_y",
845 "transform_direction", "interpolation",
846 "supersample", "recursion_level",
847 "clip_result", NULL };
848
849 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
850 "dddddddii|iii:transform_2d", kwlist,
851 &source_x, &source_y, &scale_x, &scale_y,
852 &angle, &dest_x, &dest_y,
853 &transform_direction, &interpolation,
854 &supersample, &recursion_level,
855 &clip_result))
856 return NULL;
857
858 gimp_context_push ();
859 gimp_context_set_transform_direction (transform_direction);
860 gimp_context_set_interpolation (interpolation);
861 gimp_context_set_transform_resize (clip_result);
862
863 id = gimp_item_transform_2d (self->ID, source_x, source_y,
864 scale_x, scale_y, angle, dest_x, dest_y);
865
866 gimp_context_pop ();
867
868 return transform_result(self, id, "apply 2d transform to");
869 }
870
871 static PyObject *
drw_transform_2d_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)872 drw_transform_2d_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
873 {
874 double source_x, source_y, scale_x, scale_y, angle, dest_x, dest_y;
875 gboolean interpolate = FALSE, clip_result = FALSE;
876 gint32 id;
877
878 static char *kwlist[] = { "source_x", "source_y", "scale_x", "scale_y",
879 "angle", "dest_x", "dest_y", "interpolate",
880 "clip_result", NULL };
881
882 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
883 "ddddddd|ii:transform_2d_default", kwlist,
884 &source_x, &source_y, &scale_x, &scale_y,
885 &angle, &dest_x, &dest_y, &interpolate,
886 &clip_result))
887 return NULL;
888
889 gimp_context_push ();
890 if (! interpolate)
891 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
892 gimp_context_set_transform_resize (clip_result);
893
894 id = gimp_item_transform_2d (self->ID, source_x, source_y,
895 scale_x, scale_y, angle, dest_x, dest_y);
896
897 gimp_context_pop ();
898
899 return transform_result(self, id, "apply 2d transform to");
900 }
901
902 static PyObject *
drw_transform_matrix(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)903 drw_transform_matrix(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
904 {
905 double coeff_0_0, coeff_0_1, coeff_0_2,
906 coeff_1_0, coeff_1_1, coeff_1_2,
907 coeff_2_0, coeff_2_1, coeff_2_2;
908 int transform_direction, interpolation, recursion_level = 3;
909 gboolean supersample = FALSE, clip_result = FALSE;
910 gint32 id;
911
912 static char *kwlist[] = { "coeff_0_0", "coeff_0_1", "coeff_0_2",
913 "coeff_1_0", "coeff_1_1", "coeff_1_2",
914 "coeff_2_0", "coeff_2_1", "coeff_2_2",
915 "transform_direction", "interpolation",
916 "supersample", "recursion_level",
917 "clip_result", NULL };
918
919 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
920 "dddddddddii|iii:transform_matrix", kwlist,
921 &coeff_0_0, &coeff_0_1, &coeff_0_2,
922 &coeff_1_0, &coeff_1_1, &coeff_1_2,
923 &coeff_2_0, &coeff_2_1, &coeff_2_2,
924 &transform_direction, &interpolation,
925 &supersample, &recursion_level,
926 &clip_result))
927 return NULL;
928
929 gimp_context_push ();
930 gimp_context_set_transform_direction (transform_direction);
931 gimp_context_set_interpolation (interpolation);
932 gimp_context_set_transform_resize (clip_result);
933
934 id = gimp_item_transform_matrix (self->ID,
935 coeff_0_0, coeff_0_1, coeff_0_2,
936 coeff_1_0, coeff_1_1, coeff_1_2,
937 coeff_2_0, coeff_2_1, coeff_2_2);
938
939 gimp_context_pop ();
940
941 return transform_result(self, id, "apply 2d matrix transform to");
942 }
943
944 static PyObject *
drw_transform_matrix_default(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)945 drw_transform_matrix_default(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
946 {
947 double coeff_0_0, coeff_0_1, coeff_0_2,
948 coeff_1_0, coeff_1_1, coeff_1_2,
949 coeff_2_0, coeff_2_1, coeff_2_2;
950 gboolean interpolate = FALSE, clip_result = FALSE;
951 gint32 id;
952
953 static char *kwlist[] = { "coeff_0_0", "coeff_0_1", "coeff_0_2",
954 "coeff_1_0", "coeff_1_1", "coeff_1_2",
955 "coeff_2_0", "coeff_2_1", "coeff_2_2",
956 "interpolate", "clip_result", NULL };
957
958 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
959 "ddddddddd|ii:transform_matrix_default",
960 kwlist,
961 &coeff_0_0, &coeff_0_1, &coeff_0_2,
962 &coeff_1_0, &coeff_1_1, &coeff_1_2,
963 &coeff_2_0, &coeff_2_1, &coeff_2_2,
964 &interpolate, &clip_result))
965 return NULL;
966
967 gimp_context_push ();
968 if (! interpolate)
969 gimp_context_set_interpolation (GIMP_INTERPOLATION_NONE);
970 gimp_context_set_transform_resize (clip_result);
971
972 id = gimp_item_transform_matrix (self->ID,
973 coeff_0_0, coeff_0_1, coeff_0_2,
974 coeff_1_0, coeff_1_1, coeff_1_2,
975 coeff_2_0, coeff_2_1, coeff_2_2);
976
977 gimp_context_pop ();
978
979 return transform_result(self, id, "apply 2d matrix transform to");
980 }
981
982 static PyObject *
drw_get_data(PyGimpDrawable * self,PyObject * args,PyObject * kwargs)983 drw_get_data(PyGimpDrawable *self, PyObject *args, PyObject *kwargs)
984 {
985 static char *kwlist[] = { "format", NULL };
986 gchar *format = "RGBA float";
987 const Babl *bbl_format;
988 void *output_buffer;
989 GeglBuffer *buffer;
990 int bpp;
991 Py_ssize_t size;
992 PyObject *buffer_data, *ret;
993 PyObject *array_module;
994 PyObject *array_type;
995 char array_data_type;
996
997 if (!PyArg_ParseTupleAndKeywords (args, kwargs,
998 "|s:get_data",
999 kwlist, &format
1000 ))
1001 return NULL;
1002
1003 if (g_str_has_suffix (format, "double")) {
1004 array_data_type = 'd';
1005 } else if (g_str_has_suffix (format, "float")) {
1006 array_data_type = 'f';
1007 }
1008 else if (g_str_has_suffix (format, "u16")) {
1009 array_data_type = 'H';
1010 } else if (g_str_has_suffix (format, "u8")) {
1011 array_data_type = 'B';
1012 } else {
1013 PyErr_Warn (PyExc_Warning,
1014 "Could not find appropriate data format - returning raw bytes");
1015 array_data_type = 'B';
1016 }
1017
1018 bbl_format = babl_format (format);
1019 bpp = babl_format_get_bytes_per_pixel (bbl_format);
1020 ensure_drawable(self);
1021 buffer = gimp_drawable_get_buffer (self->ID);
1022 size = bpp * self->drawable->width * self->drawable->height;
1023 output_buffer = g_malloc ((gsize) size);
1024 if (output_buffer == NULL) {
1025 return PyErr_NoMemory();
1026 }
1027 gegl_buffer_get (buffer,
1028 GEGL_RECTANGLE (0, 0, self->drawable->width, self->drawable->height),
1029 1.0,
1030 bbl_format,
1031 output_buffer,
1032 GEGL_AUTO_ROWSTRIDE,
1033 GEGL_ABYSS_NONE);
1034 buffer_data = PyString_FromStringAndSize (output_buffer, size);
1035
1036 array_module = PyImport_ImportModule ("array");
1037 if (!array_module) {
1038 PyErr_SetString (pygimp_error, "could not import array module");
1039 return NULL;
1040 }
1041
1042 array_type = PyObject_GetAttrString (array_module, "array");
1043 Py_DECREF(array_module);
1044 if (!array_type) {
1045 PyErr_SetString (pygimp_error, "could not get array.array type");
1046 return NULL;
1047 }
1048
1049 ret = PyObject_CallFunction (array_type, "cO", array_data_type, buffer_data);
1050 if (!ret) {
1051 PyErr_SetString (pygimp_error, "could not create array object");
1052 return NULL;
1053 }
1054
1055 Py_DECREF (buffer_data);
1056 g_free (output_buffer);
1057
1058 return ret;
1059 }
1060
1061
1062 /* for inclusion with the methods of layer and channel objects */
1063 static PyMethodDef drw_methods[] = {
1064 {"flush", (PyCFunction)drw_flush, METH_NOARGS},
1065 {"update", (PyCFunction)drw_update, METH_VARARGS},
1066 {"merge_shadow", (PyCFunction)drw_merge_shadow, METH_VARARGS | METH_KEYWORDS},
1067 {"free_shadow", (PyCFunction)drw_free_shadow, METH_NOARGS},
1068 {"fill", (PyCFunction)drw_fill, METH_VARARGS | METH_KEYWORDS},
1069 {"get_tile", (PyCFunction)drw_get_tile, METH_VARARGS | METH_KEYWORDS},
1070 {"get_tile2", (PyCFunction)drw_get_tile2, METH_VARARGS | METH_KEYWORDS},
1071 {"get_pixel_rgn", (PyCFunction)drw_get_pixel_rgn, METH_VARARGS | METH_KEYWORDS},
1072 {"get_data", (PyCFunction)drw_get_data, METH_VARARGS | METH_KEYWORDS,
1073 "Takes a BABL format string, returns a Python array.array object"},
1074 {"offset", (PyCFunction)drw_offset, METH_VARARGS | METH_KEYWORDS},
1075 {"parasite_find", (PyCFunction)drw_parasite_find, METH_VARARGS},
1076 {"parasite_attach", (PyCFunction)drw_parasite_attach, METH_VARARGS},
1077 {"attach_new_parasite",(PyCFunction)drw_attach_new_parasite,METH_VARARGS | METH_KEYWORDS},
1078 {"parasite_detach", (PyCFunction)drw_parasite_detach, METH_VARARGS},
1079 {"parasite_list", (PyCFunction)drw_parasite_list, METH_VARARGS},
1080 {"get_pixel", (PyCFunction)drw_get_pixel, METH_VARARGS},
1081 {"set_pixel", (PyCFunction)drw_set_pixel, METH_VARARGS},
1082 {"mask_intersect", (PyCFunction)drw_mask_intersect, METH_NOARGS},
1083 {"transform_flip", (PyCFunction)drw_transform_flip, METH_VARARGS | METH_KEYWORDS},
1084 {"transform_flip_simple", (PyCFunction)drw_transform_flip_simple, METH_VARARGS | METH_KEYWORDS},
1085 {"transform_flip_default", (PyCFunction)drw_transform_flip_default, METH_VARARGS | METH_KEYWORDS},
1086 {"transform_perspective", (PyCFunction)drw_transform_perspective, METH_VARARGS | METH_KEYWORDS},
1087 {"transform_perspective_default", (PyCFunction)drw_transform_perspective_default, METH_VARARGS | METH_KEYWORDS},
1088 {"transform_rotate", (PyCFunction)drw_transform_rotate, METH_VARARGS | METH_KEYWORDS},
1089 {"transform_rotate_simple", (PyCFunction)drw_transform_rotate_simple, METH_VARARGS | METH_KEYWORDS},
1090 {"transform_rotate_default", (PyCFunction)drw_transform_rotate_default, METH_VARARGS | METH_KEYWORDS},
1091 {"transform_scale", (PyCFunction)drw_transform_scale, METH_VARARGS | METH_KEYWORDS},
1092 {"transform_scale_default", (PyCFunction)drw_transform_scale_default, METH_VARARGS | METH_KEYWORDS},
1093 {"transform_shear", (PyCFunction)drw_transform_shear, METH_VARARGS | METH_KEYWORDS},
1094 {"transform_shear_default", (PyCFunction)drw_transform_shear_default, METH_VARARGS | METH_KEYWORDS},
1095 {"transform_2d", (PyCFunction)drw_transform_2d, METH_VARARGS | METH_KEYWORDS},
1096 {"transform_2d_default", (PyCFunction)drw_transform_2d_default, METH_VARARGS | METH_KEYWORDS},
1097 {"transform_matrix", (PyCFunction)drw_transform_matrix, METH_VARARGS | METH_KEYWORDS},
1098 {"transform_matrix_default", (PyCFunction)drw_transform_matrix_default, METH_VARARGS | METH_KEYWORDS},
1099 {NULL, NULL, 0}
1100 };
1101
1102 static PyObject *
drw_get_ID(PyGimpDrawable * self,void * closure)1103 drw_get_ID(PyGimpDrawable *self, void *closure)
1104 {
1105 return PyInt_FromLong(self->ID);
1106 }
1107
1108 static PyObject *
drw_get_name(PyGimpDrawable * self,void * closure)1109 drw_get_name(PyGimpDrawable *self, void *closure)
1110 {
1111 return PyString_FromString(gimp_item_get_name(self->ID));
1112 }
1113
1114 static int
drw_set_name(PyGimpDrawable * self,PyObject * value,void * closure)1115 drw_set_name(PyGimpDrawable *self, PyObject *value, void *closure)
1116 {
1117 if (value == NULL) {
1118 PyErr_SetString(PyExc_TypeError, "cannot delete name");
1119 return -1;
1120 }
1121
1122 if (!PyString_Check(value) && !PyUnicode_Check(value)) {
1123 PyErr_SetString(PyExc_TypeError, "type mismatch");
1124 return -1;
1125 }
1126
1127 gimp_item_set_name(self->ID, PyString_AsString(value));
1128
1129 return 0;
1130 }
1131
1132 static PyObject *
drw_get_bpp(PyGimpDrawable * self,void * closure)1133 drw_get_bpp(PyGimpDrawable *self, void *closure)
1134 {
1135 return PyInt_FromLong(gimp_drawable_bpp(self->ID));
1136 }
1137
1138 static PyObject *
drw_get_has_alpha(PyGimpDrawable * self,void * closure)1139 drw_get_has_alpha(PyGimpDrawable *self, void *closure)
1140 {
1141 return PyBool_FromLong(gimp_drawable_has_alpha(self->ID));
1142 }
1143
1144 static PyObject *
drw_get_height(PyGimpDrawable * self,void * closure)1145 drw_get_height(PyGimpDrawable *self, void *closure)
1146 {
1147 return PyInt_FromLong(gimp_drawable_height(self->ID));
1148 }
1149
1150 static PyObject *
drw_get_image(PyGimpDrawable * self,void * closure)1151 drw_get_image(PyGimpDrawable *self, void *closure)
1152 {
1153 return pygimp_image_new(gimp_item_get_image(self->ID));
1154 }
1155
1156 static PyObject *
drw_get_is_rgb(PyGimpDrawable * self,void * closure)1157 drw_get_is_rgb(PyGimpDrawable *self, void *closure)
1158 {
1159 return PyBool_FromLong(gimp_drawable_is_rgb(self->ID));
1160 }
1161
1162 static PyObject *
drw_get_is_gray(PyGimpDrawable * self,void * closure)1163 drw_get_is_gray(PyGimpDrawable *self, void *closure)
1164 {
1165 return PyBool_FromLong(gimp_drawable_is_gray(self->ID));
1166 }
1167
1168 static PyObject *
drw_get_is_indexed(PyGimpDrawable * self,void * closure)1169 drw_get_is_indexed(PyGimpDrawable *self, void *closure)
1170 {
1171 return PyBool_FromLong(gimp_drawable_is_indexed(self->ID));
1172 }
1173
1174 static PyObject *
drw_get_is_layer_mask(PyGimpDrawable * self,void * closure)1175 drw_get_is_layer_mask(PyGimpDrawable *self, void *closure)
1176 {
1177 return PyBool_FromLong(gimp_item_is_layer_mask(self->ID));
1178 }
1179
1180 static PyObject *
drw_get_mask_bounds(PyGimpDrawable * self,void * closure)1181 drw_get_mask_bounds(PyGimpDrawable *self, void *closure)
1182 {
1183 gint x1, y1, x2, y2;
1184
1185 gimp_drawable_mask_bounds(self->ID, &x1, &y1, &x2, &y2);
1186 return Py_BuildValue("(iiii)", x1, y1, x2, y2);
1187 }
1188
1189 static PyObject *
drw_get_mask_intersect(PyGimpDrawable * self,void * closure)1190 drw_get_mask_intersect(PyGimpDrawable *self, void *closure)
1191 {
1192 gint x, y, w, h;
1193
1194 if(!gimp_drawable_mask_intersect(self->ID, &x, &y, &w, &h))
1195 return Py_BuildValue("");
1196 return Py_BuildValue("(iiii)", x, y, w, h);
1197 }
1198
1199 static PyObject *
drw_get_offsets(PyGimpDrawable * self,void * closure)1200 drw_get_offsets(PyGimpDrawable *self, void *closure)
1201 {
1202 gint x, y;
1203
1204 gimp_drawable_offsets(self->ID, &x, &y);
1205
1206 return Py_BuildValue("(ii)", x, y);
1207 }
1208
1209 static PyObject *
drw_get_type(PyGimpDrawable * self,void * closure)1210 drw_get_type(PyGimpDrawable *self, void *closure)
1211 {
1212 return PyInt_FromLong(gimp_drawable_type(self->ID));
1213 }
1214
1215 static PyObject *
drw_get_type_with_alpha(PyGimpDrawable * self,void * closure)1216 drw_get_type_with_alpha(PyGimpDrawable *self, void *closure)
1217 {
1218 return PyInt_FromLong(gimp_drawable_type_with_alpha(self->ID));
1219 }
1220
1221 static PyObject *
drw_get_width(PyGimpDrawable * self,void * closure)1222 drw_get_width(PyGimpDrawable *self, void *closure)
1223 {
1224 return PyInt_FromLong(gimp_drawable_width(self->ID));
1225 }
1226
1227 static PyObject *
drw_get_linked(PyGimpDrawable * self,void * closure)1228 drw_get_linked(PyGimpDrawable *self, void *closure)
1229 {
1230 return PyBool_FromLong(gimp_item_get_linked(self->ID));
1231 }
1232
1233 static int
drw_set_linked(PyGimpDrawable * self,PyObject * value,void * closure)1234 drw_set_linked(PyGimpDrawable *self, PyObject *value, void *closure)
1235 {
1236 if (value == NULL) {
1237 PyErr_SetString(PyExc_TypeError, "cannot delete linked");
1238 return -1;
1239 }
1240
1241 if (!PyInt_Check(value)) {
1242 PyErr_SetString(PyExc_TypeError, "type mismatch");
1243 return -1;
1244 }
1245
1246 gimp_item_set_linked(self->ID, PyInt_AsLong(value));
1247
1248 return 0;
1249 }
1250
1251 static PyObject *
drw_get_tattoo(PyGimpDrawable * self,void * closure)1252 drw_get_tattoo(PyGimpDrawable *self, void *closure)
1253 {
1254 return PyInt_FromLong(gimp_item_get_tattoo(self->ID));
1255 }
1256
1257 static int
drw_set_tattoo(PyGimpDrawable * self,PyObject * value,void * closure)1258 drw_set_tattoo(PyGimpDrawable *self, PyObject *value, void *closure)
1259 {
1260 if (value == NULL) {
1261 PyErr_SetString(PyExc_TypeError, "cannot delete tattoo");
1262 return -1;
1263 }
1264
1265 if (!PyInt_Check(value)) {
1266 PyErr_SetString(PyExc_TypeError, "type mismatch");
1267 return -1;
1268 }
1269
1270 gimp_item_set_tattoo(self->ID, PyInt_AsLong(value));
1271
1272 return 0;
1273 }
1274
1275 static PyObject *
drw_get_visible(PyGimpDrawable * self,void * closure)1276 drw_get_visible(PyGimpDrawable *self, void *closure)
1277 {
1278 return PyBool_FromLong(gimp_item_get_visible(self->ID));
1279 }
1280
1281 static int
drw_set_visible(PyGimpDrawable * self,PyObject * value,void * closure)1282 drw_set_visible(PyGimpDrawable *self, PyObject *value, void *closure)
1283 {
1284 if (value == NULL) {
1285 PyErr_SetString(PyExc_TypeError, "cannot delete visible");
1286 return -1;
1287 }
1288
1289 if (!PyInt_Check(value)) {
1290 PyErr_SetString(PyExc_TypeError, "type mismatch");
1291 return -1;
1292 }
1293
1294 gimp_item_set_visible(self->ID, PyInt_AsLong(value));
1295
1296 return 0;
1297 }
1298
1299 static PyGetSetDef drw_getsets[] = {
1300 { "ID", (getter)drw_get_ID, (setter)0 },
1301 { "name", (getter)drw_get_name, (setter)drw_set_name },
1302 { "bpp", (getter)drw_get_bpp, (setter)0 },
1303 { "has_alpha", (getter)drw_get_has_alpha, (setter)0 },
1304 { "height", (getter)drw_get_height, (setter)0 },
1305 { "image", (getter)drw_get_image, (setter)0 },
1306 { "is_rgb", (getter)drw_get_is_rgb, (setter)0 },
1307 { "is_gray", (getter)drw_get_is_gray, (setter)0 },
1308 { "is_grey", (getter)drw_get_is_gray, (setter)0 },
1309 { "is_indexed", (getter)drw_get_is_indexed, (setter)0 },
1310 { "is_layer_mask", (getter)drw_get_is_layer_mask, (setter)0 },
1311 { "mask_bounds", (getter)drw_get_mask_bounds, (setter)0 },
1312 { "mask_intersect", (getter)drw_get_mask_intersect, (setter)0 },
1313 { "offsets", (getter)drw_get_offsets, (setter)0 },
1314 { "type", (getter)drw_get_type, (setter)0 },
1315 { "type_with_alpha", (getter)drw_get_type_with_alpha, (setter)0 },
1316 { "width", (getter)drw_get_width, (setter)0 },
1317 { "linked", (getter)drw_get_linked, (setter)drw_set_linked },
1318 { "tattoo", (getter)drw_get_tattoo, (setter)drw_set_tattoo },
1319 { "visible", (getter)drw_get_visible, (setter)drw_set_visible },
1320 { NULL, (getter)0, (setter)0 }
1321 };
1322
1323 static void
drw_dealloc(PyGimpDrawable * self)1324 drw_dealloc(PyGimpDrawable *self)
1325 {
1326 if (self->drawable)
1327 gimp_drawable_detach(self->drawable);
1328
1329 PyObject_DEL(self);
1330 }
1331
1332 static PyObject *
drw_repr(PyGimpDrawable * self)1333 drw_repr(PyGimpDrawable *self)
1334 {
1335 PyObject *s;
1336 gchar *name;
1337
1338 name = gimp_item_get_name(self->ID);
1339 s = PyString_FromFormat("<gimp.Drawable '%s'>", name ? name : "(null)");
1340 g_free(name);
1341
1342 return s;
1343 }
1344
1345 static int
drw_cmp(PyGimpDrawable * self,PyGimpDrawable * other)1346 drw_cmp(PyGimpDrawable *self, PyGimpDrawable *other)
1347 {
1348 if (self->ID == other->ID)
1349 return 0;
1350 if (self->ID > other->ID)
1351 return -1;
1352 return 1;
1353 }
1354
1355 PyTypeObject PyGimpDrawable_Type = {
1356 PyObject_HEAD_INIT(NULL)
1357 0, /* ob_size */
1358 "gimp.Drawable", /* tp_name */
1359 sizeof(PyGimpDrawable), /* tp_basicsize */
1360 0, /* tp_itemsize */
1361 /* methods */
1362 (destructor)drw_dealloc, /* tp_dealloc */
1363 (printfunc)0, /* tp_print */
1364 (getattrfunc)0, /* tp_getattr */
1365 (setattrfunc)0, /* tp_setattr */
1366 (cmpfunc)drw_cmp, /* tp_compare */
1367 (reprfunc)drw_repr, /* tp_repr */
1368 0, /* tp_as_number */
1369 0, /* tp_as_sequence */
1370 0, /* tp_as_mapping */
1371 (hashfunc)0, /* tp_hash */
1372 (ternaryfunc)0, /* tp_call */
1373 (reprfunc)0, /* tp_str */
1374 (getattrofunc)0, /* tp_getattro */
1375 (setattrofunc)0, /* tp_setattro */
1376 0, /* tp_as_buffer */
1377 Py_TPFLAGS_DEFAULT, /* tp_flags */
1378 NULL, /* Documentation string */
1379 (traverseproc)0, /* tp_traverse */
1380 (inquiry)0, /* tp_clear */
1381 (richcmpfunc)0, /* tp_richcompare */
1382 0, /* tp_weaklistoffset */
1383 (getiterfunc)0, /* tp_iter */
1384 (iternextfunc)0, /* tp_iternext */
1385 drw_methods, /* tp_methods */
1386 0, /* tp_members */
1387 drw_getsets, /* tp_getset */
1388 &PyGimpItem_Type, /* tp_base */
1389 (PyObject *)0, /* tp_dict */
1390 0, /* tp_descr_get */
1391 0, /* tp_descr_set */
1392 0, /* tp_dictoffset */
1393 (initproc)0, /* tp_init */
1394 (allocfunc)0, /* tp_alloc */
1395 (newfunc)0, /* tp_new */
1396 };
1397
1398
1399 PyObject *
pygimp_drawable_new(GimpDrawable * drawable,gint32 ID)1400 pygimp_drawable_new(GimpDrawable *drawable, gint32 ID)
1401 {
1402 PyObject *self;
1403
1404 if (drawable != NULL)
1405 ID = drawable->drawable_id;
1406
1407 if (!gimp_item_is_valid(ID)) {
1408 Py_INCREF(Py_None);
1409 return Py_None;
1410 }
1411
1412 /* create the appropriate object type */
1413 if (gimp_item_is_layer(ID))
1414 self = pygimp_layer_new(ID);
1415 else
1416 self = pygimp_channel_new(ID);
1417
1418 if (self == NULL)
1419 return NULL;
1420
1421 if (PyObject_TypeCheck(self, &PyGimpDrawable_Type))
1422 ((PyGimpDrawable *)self)->drawable = drawable;
1423
1424 return self;
1425 }
1426
1427 /* End of code for Drawable objects */
1428 /* -------------------------------------------------------- */
1429
1430
1431 static PyObject *
lay_copy(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1432 lay_copy(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1433 {
1434 int nreturn_vals;
1435 GimpParam *return_vals;
1436 gboolean add_alpha = FALSE;
1437 gint32 id = -1;
1438
1439 static char *kwlist[] = { "add_alpha", NULL };
1440
1441 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:copy", kwlist,
1442 &add_alpha))
1443 return NULL;
1444
1445 return_vals = gimp_run_procedure("gimp-layer-copy",
1446 &nreturn_vals,
1447 GIMP_PDB_LAYER, self->ID,
1448 GIMP_PDB_INT32, add_alpha,
1449 GIMP_PDB_END);
1450
1451 if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
1452 id = return_vals[1].data.d_layer;
1453 else
1454 PyErr_Format(pygimp_error,
1455 "could not create new layer copy from layer (ID %d)",
1456 self->ID);
1457
1458 gimp_destroy_params(return_vals, nreturn_vals);
1459
1460 return id != -1 ? pygimp_layer_new(id) : NULL;
1461 }
1462
1463
1464 static PyObject *
lay_add_alpha(PyGimpLayer * self)1465 lay_add_alpha(PyGimpLayer *self)
1466 {
1467 if (!gimp_layer_add_alpha(self->ID)) {
1468 PyErr_Format(pygimp_error, "could not add alpha to layer (ID %d)",
1469 self->ID);
1470 return NULL;
1471 }
1472
1473 Py_INCREF(Py_None);
1474 return Py_None;
1475 }
1476
1477
1478 static PyObject *
lay_add_mask(PyGimpLayer * self,PyObject * args)1479 lay_add_mask(PyGimpLayer *self, PyObject *args)
1480 {
1481 PyGimpChannel *mask;
1482
1483 if (!PyArg_ParseTuple(args, "O!:add_mask", &PyGimpChannel_Type, &mask))
1484 return NULL;
1485
1486 if (!gimp_layer_add_mask(self->ID, mask->ID)) {
1487 PyErr_Format(pygimp_error,
1488 "could not add mask (ID %d) to layer (ID %d)",
1489 mask->ID, self->ID);
1490 return NULL;
1491 }
1492
1493 Py_INCREF(Py_None);
1494 return Py_None;
1495 }
1496
1497 static PyObject *
lay_create_mask(PyGimpLayer * self,PyObject * args)1498 lay_create_mask(PyGimpLayer *self, PyObject *args)
1499 {
1500 int type;
1501 gint32 id;
1502
1503 if (!PyArg_ParseTuple(args, "i:create_mask", &type))
1504 return NULL;
1505
1506 id = gimp_layer_create_mask(self->ID, type);
1507
1508 if (id == -1) {
1509 PyErr_Format(pygimp_error,
1510 "could not create mask of type %d on layer (ID %d)",
1511 type, self->ID);
1512 return NULL;
1513 }
1514
1515 return pygimp_channel_new(id);
1516 }
1517
1518 static PyObject *
lay_remove_mask(PyGimpLayer * self,PyObject * args)1519 lay_remove_mask(PyGimpLayer *self, PyObject *args)
1520 {
1521 int mode;
1522
1523 if (!PyArg_ParseTuple(args, "i:remove_mask", &mode))
1524 return NULL;
1525
1526 if (!gimp_layer_remove_mask(self->ID, mode)) {
1527 PyErr_Format(pygimp_error,
1528 "could not remove mask from layer (ID %d) with mode %d",
1529 self->ID, mode);
1530 return NULL;
1531 }
1532
1533 Py_INCREF(Py_None);
1534 return Py_None;
1535 }
1536
1537
1538 static PyObject *
lay_resize(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1539 lay_resize(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1540 {
1541 unsigned int new_h, new_w;
1542 int offs_x = 0, offs_y = 0;
1543
1544 static char *kwlist[] = { "width", "height", "offset_x", "offset_y", NULL };
1545
1546 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii:resize", kwlist,
1547 &new_w, &new_h, &offs_x, &offs_y))
1548 return NULL;
1549
1550 if (!gimp_layer_resize(self->ID, new_w, new_h, offs_x, offs_y)) {
1551 PyErr_Format(pygimp_error,
1552 "could not resize layer (ID %d) to size %dx%d "
1553 "(offset %d, %d)",
1554 self->ID, new_w, new_h, offs_x, offs_y);
1555 return NULL;
1556 }
1557
1558 Py_INCREF(Py_None);
1559 return Py_None;
1560 }
1561
1562 static PyObject *
lay_resize_to_image_size(PyGimpLayer * self)1563 lay_resize_to_image_size(PyGimpLayer *self)
1564 {
1565 if (!gimp_layer_resize_to_image_size(self->ID)) {
1566 PyErr_Format(pygimp_error,
1567 "could not resize layer (ID %d) to image size",
1568 self->ID);
1569 return NULL;
1570 }
1571
1572 Py_INCREF(Py_None);
1573 return Py_None;
1574 }
1575
1576 static PyObject *
lay_scale(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1577 lay_scale(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1578 {
1579 int new_width, new_height;
1580 int interpolation = -1;
1581 gboolean local_origin = FALSE;
1582
1583 static char *kwlist[] = { "width", "height", "local_origin",
1584 "interpolation", NULL };
1585
1586 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii:scale", kwlist,
1587 &new_width, &new_height,
1588 &local_origin, &interpolation))
1589 return NULL;
1590
1591 if (interpolation != -1) {
1592 gimp_context_push();
1593 gimp_context_set_interpolation(interpolation);
1594 }
1595
1596 if (!gimp_layer_scale(self->ID, new_width, new_height, local_origin)) {
1597 PyErr_Format(pygimp_error,
1598 "could not scale layer (ID %d) to size %dx%d",
1599 self->ID, new_width, new_height);
1600 if (interpolation != -1) {
1601 gimp_context_pop();
1602 }
1603 return NULL;
1604 }
1605
1606 if (interpolation != -1) {
1607 gimp_context_pop();
1608 }
1609
1610 Py_INCREF(Py_None);
1611 return Py_None;
1612 }
1613
1614
1615 static PyObject *
lay_translate(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1616 lay_translate(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1617 {
1618 int offs_x, offs_y;
1619
1620 static char *kwlist[] = { "offset_x", "offset_y", NULL };
1621
1622 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:translate", kwlist,
1623 &offs_x, &offs_y))
1624 return NULL;
1625
1626 if (!gimp_item_transform_translate(self->ID, offs_x, offs_y)) {
1627 PyErr_Format(pygimp_error,
1628 "could not translate layer (ID %d) to offset %d, %d",
1629 self->ID, offs_x, offs_y);
1630 return NULL;
1631 }
1632
1633 Py_INCREF(Py_None);
1634 return Py_None;
1635 }
1636
1637
1638 static PyObject *
lay_set_offsets(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1639 lay_set_offsets(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1640 {
1641 int offs_x, offs_y;
1642
1643 static char *kwlist[] = { "offset_x", "offset_y", NULL };
1644
1645 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_offsets", kwlist,
1646 &offs_x, &offs_y))
1647 return NULL;
1648
1649 if (!gimp_layer_set_offsets(self->ID, offs_x, offs_y)) {
1650 PyErr_Format(pygimp_error,
1651 "could not set offset %d, %d on layer (ID %d)",
1652 offs_x, offs_y, self->ID);
1653 return NULL;
1654 }
1655
1656 Py_INCREF(Py_None);
1657 return Py_None;
1658 }
1659
1660 static PyMethodDef lay_methods[] = {
1661 {"copy", (PyCFunction)lay_copy, METH_VARARGS | METH_KEYWORDS},
1662 {"add_alpha", (PyCFunction)lay_add_alpha, METH_NOARGS},
1663 {"add_mask", (PyCFunction)lay_add_mask, METH_VARARGS},
1664 {"create_mask", (PyCFunction)lay_create_mask, METH_VARARGS},
1665 {"remove_mask", (PyCFunction)lay_remove_mask, METH_VARARGS},
1666 {"resize", (PyCFunction)lay_resize, METH_VARARGS | METH_KEYWORDS},
1667 {"resize_to_image_size", (PyCFunction)lay_resize_to_image_size, METH_NOARGS},
1668 {"scale", (PyCFunction)lay_scale, METH_VARARGS | METH_KEYWORDS},
1669 {"translate", (PyCFunction)lay_translate, METH_VARARGS | METH_KEYWORDS},
1670 {"set_offsets", (PyCFunction)lay_set_offsets, METH_VARARGS | METH_KEYWORDS},
1671 {NULL, NULL} /* sentinel */
1672 };
1673
1674 static PyObject *
lay_get_is_floating_sel(PyGimpLayer * self,void * closure)1675 lay_get_is_floating_sel(PyGimpLayer *self, void *closure)
1676 {
1677 return PyBool_FromLong(gimp_layer_is_floating_sel(self->ID));
1678 }
1679
1680 static PyObject *
lay_get_mask(PyGimpLayer * self,void * closure)1681 lay_get_mask(PyGimpLayer *self, void *closure)
1682 {
1683 gint32 id = gimp_layer_get_mask(self->ID);
1684
1685 if (id == -1) {
1686 Py_INCREF(Py_None);
1687 return Py_None;
1688 }
1689
1690 return pygimp_channel_new(id);
1691 }
1692
1693 static PyObject *
lay_get_apply_mask(PyGimpLayer * self,void * closure)1694 lay_get_apply_mask(PyGimpLayer *self, void *closure)
1695 {
1696 return PyBool_FromLong(gimp_layer_get_apply_mask(self->ID));
1697 }
1698
1699 static int
lay_set_apply_mask(PyGimpLayer * self,PyObject * value,void * closure)1700 lay_set_apply_mask(PyGimpLayer *self, PyObject *value, void *closure)
1701 {
1702 if (value == NULL) {
1703 PyErr_SetString(PyExc_TypeError, "cannot delete apply_mask");
1704 return -1;
1705 }
1706
1707 if (!PyInt_Check(value)) {
1708 PyErr_SetString(PyExc_TypeError, "type mismatch");
1709 return -1;
1710 }
1711
1712 if (!gimp_layer_set_apply_mask(self->ID, PyInt_AsLong(value))) {
1713 PyErr_Format(pygimp_error,
1714 "could not set layer mask on layer (ID %d)",
1715 self->ID);
1716 return -1;
1717 }
1718
1719 return 0;
1720 }
1721
1722 static PyObject *
lay_get_edit_mask(PyGimpLayer * self,void * closure)1723 lay_get_edit_mask(PyGimpLayer *self, void *closure)
1724 {
1725 return PyBool_FromLong(gimp_layer_get_edit_mask(self->ID));
1726 }
1727
1728 static int
lay_set_edit_mask(PyGimpLayer * self,PyObject * value,void * closure)1729 lay_set_edit_mask(PyGimpLayer *self, PyObject *value, void *closure)
1730 {
1731 if (value == NULL) {
1732 PyErr_SetString(PyExc_TypeError, "cannot delete edit_mask");
1733 return -1;
1734 }
1735
1736 if (!PyInt_Check(value)) {
1737 PyErr_SetString(PyExc_TypeError, "type mismatch");
1738 return -1;
1739 }
1740
1741 if (!gimp_layer_set_edit_mask(self->ID, PyInt_AsLong(value))) {
1742 PyErr_Format(pygimp_error,
1743 "could not set layer mask active on layer (ID %d)",
1744 self->ID);
1745 return -1;
1746 }
1747
1748 return 0;
1749 }
1750
1751 static PyObject *
lay_get_mode(PyGimpLayer * self,void * closure)1752 lay_get_mode(PyGimpLayer *self, void *closure)
1753 {
1754 return PyInt_FromLong(gimp_layer_get_mode(self->ID));
1755 }
1756
1757 static int
lay_set_mode(PyGimpLayer * self,PyObject * value,void * closure)1758 lay_set_mode(PyGimpLayer *self, PyObject *value, void *closure)
1759 {
1760 if (value == NULL) {
1761 PyErr_SetString(PyExc_TypeError, "cannot delete mode");
1762 return -1;
1763 }
1764
1765 if (!PyInt_Check(value)) {
1766 PyErr_SetString(PyExc_TypeError, "type mismatch");
1767 return -1;
1768 }
1769
1770 if (!gimp_layer_set_mode(self->ID, PyInt_AsLong(value))) {
1771 PyErr_Format(pygimp_error, "could not set mode on layer (ID %d)",
1772 self->ID);
1773 return -1;
1774 }
1775
1776 return 0;
1777 }
1778
1779 static PyObject *
lay_get_opacity(PyGimpLayer * self,void * closure)1780 lay_get_opacity(PyGimpLayer *self, void *closure)
1781 {
1782 return PyFloat_FromDouble(gimp_layer_get_opacity(self->ID));
1783 }
1784
1785 static int
lay_set_opacity(PyGimpLayer * self,PyObject * value,void * closure)1786 lay_set_opacity(PyGimpLayer *self, PyObject *value, void *closure)
1787 {
1788 if (value == NULL) {
1789 PyErr_SetString(PyExc_TypeError, "cannot delete opacity");
1790 return -1;
1791 }
1792
1793 if (!PyFloat_Check(value)) {
1794 PyErr_SetString(PyExc_TypeError, "type mismatch");
1795 return -1;
1796 }
1797
1798 if (!gimp_layer_set_opacity(self->ID, PyFloat_AsDouble(value))) {
1799 PyErr_Format(pygimp_error, "could not set opacity on layer (ID %d)",
1800 self->ID);
1801 return -1;
1802 }
1803
1804 return 0;
1805 }
1806
1807 static PyObject *
lay_get_lock_alpha(PyGimpLayer * self,void * closure)1808 lay_get_lock_alpha(PyGimpLayer *self, void *closure)
1809 {
1810 return PyBool_FromLong(gimp_layer_get_lock_alpha(self->ID));
1811 }
1812
1813 static int
lay_set_lock_alpha(PyGimpLayer * self,PyObject * value,void * closure)1814 lay_set_lock_alpha(PyGimpLayer *self, PyObject *value, void *closure)
1815 {
1816 if (value == NULL) {
1817 PyErr_SetString(PyExc_TypeError,
1818 "cannot delete lock_alpha");
1819 return -1;
1820 }
1821
1822 if (!PyInt_Check(value)) {
1823 PyErr_SetString(PyExc_TypeError, "type mismatch");
1824 return -1;
1825 }
1826
1827 if (!gimp_layer_set_lock_alpha(self->ID, PyInt_AsLong(value))) {
1828 PyErr_Format(pygimp_error,
1829 "could not set lock alpha setting on layer (ID %d)",
1830 self->ID);
1831 return -1;
1832 }
1833
1834 return 0;
1835 }
1836
1837 static PyObject *
lay_get_show_mask(PyGimpLayer * self,void * closure)1838 lay_get_show_mask(PyGimpLayer *self, void *closure)
1839 {
1840 return PyBool_FromLong(gimp_layer_get_show_mask(self->ID));
1841 }
1842
1843 static int
lay_set_show_mask(PyGimpLayer * self,PyObject * value,void * closure)1844 lay_set_show_mask(PyGimpLayer *self, PyObject *value, void *closure)
1845 {
1846 if (value == NULL) {
1847 PyErr_SetString(PyExc_TypeError, "cannot delete show_mask");
1848 return -1;
1849 }
1850
1851 if (!PyInt_Check(value)) {
1852 PyErr_SetString(PyExc_TypeError, "type mismatch");
1853 return -1;
1854 }
1855
1856 if (!gimp_layer_set_show_mask(self->ID, PyInt_AsLong(value))) {
1857 PyErr_Format(pygimp_error,
1858 "could not set mask visibility on layer (ID %d)",
1859 self->ID);
1860 return -1;
1861 }
1862
1863 return 0;
1864 }
1865
1866 static PyObject *
lay_get_preserve_trans(PyGimpLayer * self,void * closure)1867 lay_get_preserve_trans(PyGimpLayer *self, void *closure)
1868 {
1869 if (PyErr_Warn(PyExc_DeprecationWarning, "use lock_alpha attribute") < 0)
1870 return NULL;
1871
1872 return lay_get_lock_alpha(self, closure);
1873 }
1874
1875 static int
lay_set_preserve_trans(PyGimpLayer * self,PyObject * value,void * closure)1876 lay_set_preserve_trans(PyGimpLayer *self, PyObject *value, void *closure)
1877 {
1878 if (PyErr_Warn(PyExc_DeprecationWarning, "use lock_alpha attribute") < 0)
1879 return -1;
1880
1881 return lay_set_lock_alpha(self, value, closure);
1882 }
1883
1884 static PyGetSetDef lay_getsets[] = {
1885 { "is_floating_sel", (getter)lay_get_is_floating_sel, (setter)0 },
1886 { "mask", (getter)lay_get_mask, (setter)0 },
1887 { "apply_mask", (getter)lay_get_apply_mask, (setter)lay_set_apply_mask },
1888 { "edit_mask", (getter)lay_get_edit_mask, (setter)lay_set_edit_mask },
1889 { "mode", (getter)lay_get_mode, (setter)lay_set_mode },
1890 { "opacity", (getter)lay_get_opacity, (setter)lay_set_opacity },
1891 { "lock_alpha", (getter)lay_get_lock_alpha, (setter)lay_set_lock_alpha },
1892 { "show_mask", (getter)lay_get_show_mask, (setter)lay_set_show_mask },
1893 { "preserve_trans", (getter)lay_get_preserve_trans,
1894 (setter)lay_set_preserve_trans },
1895 { NULL, (getter)0, (setter)0 }
1896 };
1897
1898 static PyObject *
lay_repr(PyGimpLayer * self)1899 lay_repr(PyGimpLayer *self)
1900 {
1901 PyObject *s;
1902 gchar *name;
1903
1904 name = gimp_item_get_name(self->ID);
1905 s = PyString_FromFormat("<gimp.Layer '%s'>", name ? name : "(null)");
1906 g_free(name);
1907
1908 return s;
1909 }
1910
1911 static int
lay_init(PyGimpLayer * self,PyObject * args,PyObject * kwargs)1912 lay_init(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
1913 {
1914 PyGimpImage *img;
1915 char *name;
1916 unsigned int width, height;
1917 GimpImageType type = GIMP_RGB_IMAGE;
1918 double opacity = 100.0;
1919 GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL;
1920
1921
1922 if (!PyArg_ParseTuple(args, "O!sii|idi:gimp.Layer.__init__",
1923 &PyGimpImage_Type, &img, &name, &width, &height,
1924 &type, &opacity, &mode))
1925 return -1;
1926
1927 self->ID = gimp_layer_new(img->ID, name, width, height,
1928 type, opacity, mode);
1929
1930 self->drawable = NULL;
1931
1932 if (self->ID < 0) {
1933 PyErr_Format(pygimp_error,
1934 "could not create %dx%d layer '%s' of type %d on "
1935 "image (ID %d)",
1936 width, height, name, type, img->ID);
1937 return -1;
1938 }
1939
1940 return 0;
1941 }
1942
1943 PyTypeObject PyGimpLayer_Type = {
1944 PyObject_HEAD_INIT(NULL)
1945 0, /* ob_size */
1946 "gimp.Layer", /* tp_name */
1947 sizeof(PyGimpLayer), /* tp_basicsize */
1948 0, /* tp_itemsize */
1949 /* methods */
1950 (destructor)drw_dealloc, /* tp_dealloc */
1951 (printfunc)0, /* tp_print */
1952 (getattrfunc)0, /* tp_getattr */
1953 (setattrfunc)0, /* tp_setattr */
1954 (cmpfunc)drw_cmp, /* tp_compare */
1955 (reprfunc)lay_repr, /* tp_repr */
1956 0, /* tp_as_number */
1957 0, /* tp_as_sequence */
1958 0, /* tp_as_mapping */
1959 (hashfunc)0, /* tp_hash */
1960 (ternaryfunc)0, /* tp_call */
1961 (reprfunc)0, /* tp_str */
1962 (getattrofunc)0, /* tp_getattro */
1963 (setattrofunc)0, /* tp_setattro */
1964 0, /* tp_as_buffer */
1965 Py_TPFLAGS_DEFAULT, /* tp_flags */
1966 NULL, /* Documentation string */
1967 (traverseproc)0, /* tp_traverse */
1968 (inquiry)0, /* tp_clear */
1969 (richcmpfunc)0, /* tp_richcompare */
1970 0, /* tp_weaklistoffset */
1971 (getiterfunc)0, /* tp_iter */
1972 (iternextfunc)0, /* tp_iternext */
1973 lay_methods, /* tp_methods */
1974 0, /* tp_members */
1975 lay_getsets, /* tp_getset */
1976 &PyGimpDrawable_Type, /* tp_base */
1977 (PyObject *)0, /* tp_dict */
1978 0, /* tp_descr_get */
1979 0, /* tp_descr_set */
1980 0, /* tp_dictoffset */
1981 (initproc)lay_init, /* tp_init */
1982 (allocfunc)0, /* tp_alloc */
1983 (newfunc)0, /* tp_new */
1984 };
1985
1986 PyObject *
pygimp_layer_new(gint32 ID)1987 pygimp_layer_new(gint32 ID)
1988 {
1989 PyGimpLayer *self;
1990
1991 if (!gimp_item_is_valid(ID) || !gimp_item_is_layer(ID)) {
1992 Py_INCREF(Py_None);
1993 return Py_None;
1994 }
1995
1996
1997 if (gimp_item_is_group(ID)) {
1998 self = PyObject_NEW(PyGimpGroupLayer, &PyGimpGroupLayer_Type);
1999 }
2000 else {
2001 self = PyObject_NEW(PyGimpLayer, &PyGimpLayer_Type);
2002 }
2003
2004 if (self == NULL)
2005 return NULL;
2006
2007 self->ID = ID;
2008 self->drawable = NULL;
2009
2010 return (PyObject *)self;
2011 }
2012
2013 /* End of code for Layer objects */
2014 /* -------------------------------------------------------- */
2015
2016 /* Since this help will primarily be seen from within
2017 * GIMP's Python console, we should make it fit in that
2018 * window's default size.
2019 */
2020
2021 #define GROUPLAYER_DOC "" \
2022 "gimp.GroupLayer(img, name="", opacity=100.0, " \
2023 "mode=gimp.LAYER_MODE_NORMAL)\n" \
2024 "\n" \
2025 " Creates a new GroupLayer object that has to be \n" \
2026 "subsequently added to an image. Use Image.add_layer \n" \
2027 "or pdb.gimp_image_insert_layer calls to do that. \n" \
2028
2029 static PyMethodDef grouplay_methods[] = {
2030 {NULL, NULL} /* sentinel */
2031 };
2032
2033 static PyObject *
grouplay_get_layers(PyGimpGroupLayer * self,void * closure)2034 grouplay_get_layers(PyGimpGroupLayer *self, void *closure)
2035 {
2036 gint32 *layers;
2037 gint n_layers, i;
2038 PyObject *ret;
2039
2040 layers = gimp_item_get_children(self->ID, &n_layers);
2041
2042 ret = PyList_New(n_layers);
2043
2044 for (i = 0; i < n_layers; i++)
2045 PyList_SetItem(ret, i, pygimp_group_layer_new(layers[i]));
2046
2047 g_free(layers);
2048
2049 return ret;
2050 }
2051
2052 static PyGetSetDef grouplay_getsets[] = {
2053 { "layers", (getter)grouplay_get_layers, (setter)0 },
2054 { NULL, (getter)0, (setter)0 }
2055 };
2056
2057 static PyObject *
grouplay_repr(PyGimpLayer * self)2058 grouplay_repr(PyGimpLayer *self)
2059 {
2060 PyObject *s;
2061 gchar *name;
2062
2063 name = gimp_item_get_name(self->ID);
2064 s = PyString_FromFormat("<gimp.GroupLayer '%s'>", name ? name : "(null)");
2065 g_free(name);
2066
2067 return s;
2068 }
2069
2070 static int
grouplay_init(PyGimpLayer * self,PyObject * args,PyObject * kwargs)2071 grouplay_init(PyGimpLayer *self, PyObject *args, PyObject *kwargs)
2072 {
2073 PyGimpImage *img;
2074 char *name = "Layer Group";
2075 GimpImageType type = GIMP_RGB_IMAGE;
2076 double opacity = 100.0;
2077 GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL;
2078
2079
2080 if (!PyArg_ParseTuple(args, "O!|sdi:gimp.Layer.__init__",
2081 &PyGimpImage_Type, &img, &name,
2082 &opacity, &mode))
2083 return -1;
2084
2085 self->ID = gimp_layer_group_new(img->ID);
2086
2087 self->drawable = NULL;
2088
2089 if (self->ID < 0) {
2090 PyErr_Format(pygimp_error,
2091 "could not create layer group '%s' of type %d on "
2092 "image (ID %d)",
2093 name, type, img->ID);
2094 return -1;
2095 }
2096
2097 gimp_layer_set_opacity(self->ID, opacity);
2098 gimp_layer_set_mode(self->ID, mode);
2099
2100 gimp_item_set_name(self->ID, name);
2101
2102 return 0;
2103 }
2104
2105 PyTypeObject PyGimpGroupLayer_Type = {
2106 PyObject_HEAD_INIT(NULL)
2107 0, /* ob_size */
2108 "gimp.GroupLayer", /* tp_name */
2109 sizeof(PyGimpGroupLayer), /* tp_basicsize */
2110 0, /* tp_itemsize */
2111 /* methods */
2112 (destructor)drw_dealloc, /* tp_dealloc */
2113 (printfunc)0, /* tp_print */
2114 (getattrfunc)0, /* tp_getattr */
2115 (setattrfunc)0, /* tp_setattr */
2116 (cmpfunc)drw_cmp, /* tp_compare */
2117 (reprfunc)grouplay_repr, /* tp_repr */
2118 0, /* tp_as_number */
2119 0, /* tp_as_sequence */
2120 0, /* tp_as_mapping */
2121 (hashfunc)0, /* tp_hash */
2122 (ternaryfunc)0, /* tp_call */
2123 (reprfunc)0, /* tp_str */
2124 (getattrofunc)0, /* tp_getattro */
2125 (setattrofunc)0, /* tp_setattro */
2126 0, /* tp_as_buffer */
2127 Py_TPFLAGS_DEFAULT, /* tp_flags */
2128 GROUPLAYER_DOC, /* Documentation string */
2129 (traverseproc)0, /* tp_traverse */
2130 (inquiry)0, /* tp_clear */
2131 (richcmpfunc)0, /* tp_richcompare */
2132 0, /* tp_weaklistoffset */
2133 (getiterfunc)0, /* tp_iter */
2134 (iternextfunc)0, /* tp_iternext */
2135 grouplay_methods, /* tp_methods */
2136 0, /* tp_members */
2137 grouplay_getsets, /* tp_getset */
2138 &PyGimpLayer_Type, /* tp_base */
2139 (PyObject *)0, /* tp_dict */
2140 0, /* tp_descr_get */
2141 0, /* tp_descr_set */
2142 0, /* tp_dictoffset */
2143 (initproc)grouplay_init, /* tp_init */
2144 (allocfunc)0, /* tp_alloc */
2145 (newfunc)0, /* tp_new */
2146 };
2147
2148 PyObject *
pygimp_group_layer_new(gint32 ID)2149 pygimp_group_layer_new(gint32 ID)
2150 {
2151 PyGimpGroupLayer *self;
2152
2153 if (!gimp_item_is_valid(ID) || !gimp_item_is_layer(ID)) {
2154 Py_INCREF(Py_None);
2155 return Py_None;
2156 }
2157
2158 if (!gimp_item_is_group(ID)) {
2159 return pygimp_layer_new(ID);
2160 }
2161
2162 self = PyObject_NEW(PyGimpGroupLayer, &PyGimpGroupLayer_Type);
2163
2164 if (self == NULL)
2165 return NULL;
2166
2167 self->ID = ID;
2168 self->drawable = NULL;
2169
2170 return (PyObject *)self;
2171 }
2172
2173 /* End of code for GroupLayer objects */
2174 /* -------------------------------------------------------- */
2175
2176
2177 static PyObject *
chn_copy(PyGimpChannel * self)2178 chn_copy(PyGimpChannel *self)
2179 {
2180 gint32 id;
2181
2182 id = gimp_channel_copy(self->ID);
2183
2184 if (id == -1) {
2185 PyErr_Format(pygimp_error,
2186 "could not create new channel copy from channel (ID %d)",
2187 self->ID);
2188 return NULL;
2189 }
2190
2191 return pygimp_channel_new(id);
2192 }
2193
2194 static PyObject *
chn_combine_masks(PyGimpChannel * self,PyObject * args,PyObject * kwargs)2195 chn_combine_masks(PyGimpChannel *self, PyObject *args, PyObject *kwargs)
2196 {
2197 PyGimpChannel *channel2;
2198 GimpChannelOps operation;
2199 int offx = 0, offy = 0;
2200
2201 static char *kwlist[] = { "channel", "operation", "offset_x", "offset_y",
2202 NULL };
2203
2204 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!i|ii:combine_masks",
2205 kwlist,
2206 &PyGimpChannel_Type, &channel2,
2207 &operation, &offx, &offy))
2208 return NULL;
2209
2210 if (!gimp_channel_combine_masks(self->ID, channel2->ID, operation,
2211 offx, offy)) {
2212 PyErr_Format(pygimp_error,
2213 "could not combine masks with channels (ID %d and ID %d) "
2214 "with operation %d, offset %d, %d",
2215 self->ID, channel2->ID, operation, offx, offy);
2216 return NULL;
2217 }
2218
2219 Py_INCREF(Py_None);
2220 return Py_None;
2221 }
2222
2223 static PyMethodDef chn_methods[] = {
2224 {"copy", (PyCFunction)chn_copy, METH_NOARGS},
2225 {"combine_masks", (PyCFunction)chn_combine_masks, METH_VARARGS},
2226 {NULL, NULL} /* sentinel */
2227 };
2228
2229 static PyObject *
chn_get_color(PyGimpChannel * self,void * closure)2230 chn_get_color(PyGimpChannel *self, void *closure)
2231 {
2232 GimpRGB rgb;
2233
2234 if (!gimp_channel_get_color(self->ID, &rgb)) {
2235 PyErr_Format(pygimp_error,
2236 "could not get compositing color of channel (ID %d)",
2237 self->ID);
2238 return NULL;
2239 }
2240
2241 return pygimp_rgb_new(&rgb);
2242 }
2243
2244 static int
chn_set_color(PyGimpChannel * self,PyObject * value,void * closure)2245 chn_set_color(PyGimpChannel *self, PyObject *value, void *closure)
2246 {
2247 guchar r, g, b;
2248 GimpRGB tmprgb, *rgb;
2249
2250 if (value == NULL) {
2251 PyErr_SetString(PyExc_TypeError, "cannot delete color");
2252 return -1;
2253 }
2254
2255 if (pygimp_rgb_check(value)) {
2256 rgb = pyg_boxed_get(value, GimpRGB);
2257 } else if (PyTuple_Check(value) &&
2258 PyArg_ParseTuple(value, "(BBB)", &r, &g, &b)) {
2259 gimp_rgb_set_uchar(&tmprgb, r, g, b);
2260 rgb = &tmprgb;
2261 } else {
2262 PyErr_Clear();
2263 PyErr_SetString(PyExc_TypeError, "type mismatch");
2264 return -1;
2265 }
2266
2267 if (!gimp_channel_set_color(self->ID, rgb)) {
2268 PyErr_Format(pygimp_error,
2269 "could not set compositing color on channel (ID %d)",
2270 self->ID);
2271 return -1;
2272 }
2273
2274 return 0;
2275 }
2276
2277 static PyObject *
chn_get_opacity(PyGimpLayer * self,void * closure)2278 chn_get_opacity(PyGimpLayer *self, void *closure)
2279 {
2280 return PyFloat_FromDouble(gimp_channel_get_opacity(self->ID));
2281 }
2282
2283 static int
chn_set_opacity(PyGimpLayer * self,PyObject * value,void * closure)2284 chn_set_opacity(PyGimpLayer *self, PyObject *value, void *closure)
2285 {
2286 if (value == NULL) {
2287 PyErr_SetString(PyExc_TypeError, "cannot delete opacity");
2288 return -1;
2289 }
2290
2291 if (!PyFloat_Check(value)) {
2292 PyErr_SetString(PyExc_TypeError, "type mismatch");
2293 return -1;
2294 }
2295
2296 if (!gimp_channel_set_opacity(self->ID, PyFloat_AsDouble(value))) {
2297 PyErr_Format(pygimp_error,
2298 "could not set opacity on channel (ID %d)",
2299 self->ID);
2300 return -1;
2301 }
2302
2303 return 0;
2304 }
2305
2306 static PyObject *
chn_get_show_masked(PyGimpLayer * self,void * closure)2307 chn_get_show_masked(PyGimpLayer *self, void *closure)
2308 {
2309 return PyBool_FromLong(gimp_channel_get_show_masked(self->ID));
2310 }
2311
2312 static int
chn_set_show_masked(PyGimpLayer * self,PyObject * value,void * closure)2313 chn_set_show_masked(PyGimpLayer *self, PyObject *value, void *closure)
2314 {
2315 if (value == NULL) {
2316 PyErr_SetString(PyExc_TypeError, "cannot delete show_masked");
2317 return -1;
2318 }
2319
2320 if (!PyInt_Check(value)) {
2321 PyErr_SetString(PyExc_TypeError, "type mismatch");
2322 return -1;
2323 }
2324
2325 if (!gimp_channel_set_show_masked(self->ID, PyInt_AsLong(value))) {
2326 PyErr_Format(pygimp_error,
2327 "could not set composite method on channel (ID %d)",
2328 self->ID);
2329 return -1;
2330 }
2331
2332 return 0;
2333 }
2334
2335 static PyGetSetDef chn_getsets[] = {
2336 { "color", (getter)chn_get_color, (setter)chn_set_color },
2337 { "colour", (getter)chn_get_color, (setter)chn_set_color },
2338 { "opacity", (getter)chn_get_opacity, (setter)chn_set_opacity },
2339 { "show_masked", (getter)chn_get_show_masked, (setter)chn_set_show_masked},
2340 { NULL, (getter)0, (setter)0 }
2341 };
2342
2343 static PyObject *
chn_repr(PyGimpChannel * self)2344 chn_repr(PyGimpChannel *self)
2345 {
2346 PyObject *s;
2347 gchar *name;
2348
2349 name = gimp_item_get_name(self->ID);
2350 s = PyString_FromFormat("<gimp.Channel '%s'>", name ? name : "(null)");
2351 g_free(name);
2352
2353 return s;
2354 }
2355
2356 static int
chn_init(PyGimpChannel * self,PyObject * args,PyObject * kwargs)2357 chn_init(PyGimpChannel *self, PyObject *args, PyObject *kwargs)
2358 {
2359 PyGimpImage *img;
2360 PyObject *color;
2361 char *name;
2362 unsigned int width, height, r, g, b;
2363 double opacity;
2364 GimpRGB tmprgb, *rgb;
2365
2366 if (!PyArg_ParseTuple(args, "O!siidO:gimp.Channel.__init__",
2367 &PyGimpImage_Type, &img, &name, &width,
2368 &height, &opacity, &color))
2369 return -1;
2370
2371 if (pygimp_rgb_check(color)) {
2372 rgb = pyg_boxed_get(color, GimpRGB);
2373 } else if (PyTuple_Check(color) &&
2374 PyArg_ParseTuple(color, "(BBB)", &r, &g, &b)) {
2375 gimp_rgb_set_uchar(&tmprgb, r, g, b);
2376 rgb = &tmprgb;
2377 } else {
2378 PyErr_Clear();
2379 PyErr_SetString(PyExc_TypeError, "type mismatch");
2380 return -1;
2381 }
2382
2383 self->ID = gimp_channel_new(img->ID, name, width, height, opacity, rgb);
2384
2385 self->drawable = NULL;
2386
2387 if (self->ID < 0) {
2388 PyErr_Format(pygimp_error,
2389 "could not create %dx%d channel '%s' on image (ID %d)",
2390 width, height, name, img->ID);
2391 return -1;
2392 }
2393
2394 return 0;
2395 }
2396
2397 PyTypeObject PyGimpChannel_Type = {
2398 PyObject_HEAD_INIT(NULL)
2399 0, /* ob_size */
2400 "gimp.Channel", /* tp_name */
2401 sizeof(PyGimpChannel), /* tp_basicsize */
2402 0, /* tp_itemsize */
2403 /* methods */
2404 (destructor)drw_dealloc, /* tp_dealloc */
2405 (printfunc)0, /* tp_print */
2406 (getattrfunc)0, /* tp_getattr */
2407 (setattrfunc)0, /* tp_setattr */
2408 (cmpfunc)drw_cmp, /* tp_compare */
2409 (reprfunc)chn_repr, /* tp_repr */
2410 0, /* tp_as_number */
2411 0, /* tp_as_sequence */
2412 0, /* tp_as_mapping */
2413 (hashfunc)0, /* tp_hash */
2414 (ternaryfunc)0, /* tp_call */
2415 (reprfunc)0, /* tp_str */
2416 (getattrofunc)0, /* tp_getattro */
2417 (setattrofunc)0, /* tp_setattro */
2418 0, /* tp_as_buffer */
2419 Py_TPFLAGS_DEFAULT, /* tp_flags */
2420 NULL, /* Documentation string */
2421 (traverseproc)0, /* tp_traverse */
2422 (inquiry)0, /* tp_clear */
2423 (richcmpfunc)0, /* tp_richcompare */
2424 0, /* tp_weaklistoffset */
2425 (getiterfunc)0, /* tp_iter */
2426 (iternextfunc)0, /* tp_iternext */
2427 chn_methods, /* tp_methods */
2428 0, /* tp_members */
2429 chn_getsets, /* tp_getset */
2430 &PyGimpDrawable_Type, /* tp_base */
2431 (PyObject *)0, /* tp_dict */
2432 0, /* tp_descr_get */
2433 0, /* tp_descr_set */
2434 0, /* tp_dictoffset */
2435 (initproc)chn_init, /* tp_init */
2436 (allocfunc)0, /* tp_alloc */
2437 (newfunc)0, /* tp_new */
2438 };
2439
2440 PyObject *
pygimp_channel_new(gint32 ID)2441 pygimp_channel_new(gint32 ID)
2442 {
2443 PyGimpChannel *self;
2444
2445 if (!gimp_item_is_valid(ID) || !gimp_item_is_channel(ID)) {
2446 Py_INCREF(Py_None);
2447 return Py_None;
2448 }
2449
2450 self = PyObject_NEW(PyGimpChannel, &PyGimpChannel_Type);
2451
2452 if (self == NULL)
2453 return NULL;
2454
2455 self->ID = ID;
2456 self->drawable = NULL;
2457
2458 return (PyObject *)self;
2459 }
2460