1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-2003 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 /* NOTE: This file is auto-generated by pdbgen.pl. */
19 
20 #include "config.h"
21 
22 #include <gegl.h>
23 
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 
26 #include "libgimpmath/gimpmath.h"
27 
28 #include "libgimpbase/gimpbase.h"
29 
30 #include "pdb-types.h"
31 
32 #include "core/gimp-transform-utils.h"
33 #include "core/gimpchannel.h"
34 #include "core/gimpdrawable-transform.h"
35 #include "core/gimpdrawable.h"
36 #include "core/gimpimage.h"
37 #include "core/gimpitem-linked.h"
38 #include "core/gimpitem.h"
39 #include "core/gimpparamspecs.h"
40 #include "core/gimpprogress.h"
41 
42 #include "gimppdb.h"
43 #include "gimppdb-utils.h"
44 #include "gimppdbcontext.h"
45 #include "gimpprocedure.h"
46 #include "internal-procs.h"
47 
48 #include "gimp-intl.h"
49 
50 
51 static GimpValueArray *
item_transform_translate_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)52 item_transform_translate_invoker (GimpProcedure         *procedure,
53                                   Gimp                  *gimp,
54                                   GimpContext           *context,
55                                   GimpProgress          *progress,
56                                   const GimpValueArray  *args,
57                                   GError               **error)
58 {
59   gboolean success = TRUE;
60   GimpValueArray *return_vals;
61   GimpItem *item;
62   gdouble off_x;
63   gdouble off_y;
64 
65   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
66   off_x = g_value_get_double (gimp_value_array_index (args, 1));
67   off_y = g_value_get_double (gimp_value_array_index (args, 2));
68 
69   if (success)
70     {
71       if (gimp_pdb_item_is_modifiable (item,
72                                        GIMP_PDB_ITEM_POSITION, error))
73         {
74           if (gimp_item_get_linked (item) && gimp_item_is_attached (item))
75             {
76               gimp_item_linked_translate (item, off_x, off_y, TRUE);
77             }
78           else
79             {
80               gimp_item_translate (item, off_x, off_y, TRUE);
81             }
82         }
83       else
84         success = FALSE;
85     }
86 
87   return_vals = gimp_procedure_get_return_values (procedure, success,
88                                                   error ? *error : NULL);
89 
90   if (success)
91     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
92 
93   return return_vals;
94 }
95 
96 static GimpValueArray *
item_transform_flip_simple_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)97 item_transform_flip_simple_invoker (GimpProcedure         *procedure,
98                                     Gimp                  *gimp,
99                                     GimpContext           *context,
100                                     GimpProgress          *progress,
101                                     const GimpValueArray  *args,
102                                     GError               **error)
103 {
104   gboolean success = TRUE;
105   GimpValueArray *return_vals;
106   GimpItem *item;
107   gint32 flip_type;
108   gboolean auto_center;
109   gdouble axis;
110 
111   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
112   flip_type = g_value_get_enum (gimp_value_array_index (args, 1));
113   auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
114   axis = g_value_get_double (gimp_value_array_index (args, 3));
115 
116   if (success)
117     {
118       gint x, y, width, height;
119 
120       success = gimp_pdb_item_is_attached (item, NULL,
121                                            GIMP_PDB_ITEM_CONTENT |
122                                            GIMP_PDB_ITEM_POSITION, error);
123 
124       if (success &&
125           gimp_item_mask_intersect (item, &x, &y, &width, &height))
126         {
127           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
128           GimpImage      *image       = gimp_item_get_image (item);
129           GimpChannel    *mask        = gimp_image_get_mask (image);
130           gint            off_x, off_y;
131 
132           gimp_item_get_offset (item, &off_x, &off_y);
133           x += off_x;
134           y += off_y;
135 
136           gimp_transform_get_flip_axis (x, y, width, height,
137                                         flip_type, auto_center, &axis);
138 
139           if (GIMP_IS_DRAWABLE (item)                             &&
140               item != GIMP_ITEM (mask)                            &&
141               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
142               ! gimp_channel_is_empty (mask))
143             {
144               GimpDrawable *drawable;
145 
146               drawable = gimp_drawable_transform_flip (GIMP_DRAWABLE (item), context,
147                                                        flip_type, axis,
148                                                        pdb_context->transform_resize);
149 
150               if (drawable)
151                 item = GIMP_ITEM (drawable);
152               else
153                 success = FALSE;
154             }
155           else if (gimp_item_get_linked (item))
156             {
157               gimp_item_linked_flip (item, context,
158                                      flip_type, axis,
159                                      pdb_context->transform_resize);
160             }
161           else
162             {
163               gimp_item_flip (item, context,
164                               flip_type, axis,
165                               gimp_item_get_clip (
166                                 item, pdb_context->transform_resize));
167             }
168         }
169     }
170 
171   return_vals = gimp_procedure_get_return_values (procedure, success,
172                                                   error ? *error : NULL);
173 
174   if (success)
175     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
176 
177   return return_vals;
178 }
179 
180 static GimpValueArray *
item_transform_flip_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)181 item_transform_flip_invoker (GimpProcedure         *procedure,
182                              Gimp                  *gimp,
183                              GimpContext           *context,
184                              GimpProgress          *progress,
185                              const GimpValueArray  *args,
186                              GError               **error)
187 {
188   gboolean success = TRUE;
189   GimpValueArray *return_vals;
190   GimpItem *item;
191   gdouble x0;
192   gdouble y0;
193   gdouble x1;
194   gdouble y1;
195 
196   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
197   x0 = g_value_get_double (gimp_value_array_index (args, 1));
198   y0 = g_value_get_double (gimp_value_array_index (args, 2));
199   x1 = g_value_get_double (gimp_value_array_index (args, 3));
200   y1 = g_value_get_double (gimp_value_array_index (args, 4));
201 
202   if (success)
203     {
204       gint x, y, width, height;
205 
206       success = gimp_pdb_item_is_attached (item, NULL,
207                                            GIMP_PDB_ITEM_CONTENT |
208                                            GIMP_PDB_ITEM_POSITION, error);
209 
210       if (success &&
211           gimp_item_mask_intersect (item, &x, &y, &width, &height))
212         {
213           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
214           GimpImage      *image       = gimp_item_get_image (item);
215           GimpChannel    *mask        = gimp_image_get_mask (image);
216           GimpMatrix3     matrix;
217           gint            off_x, off_y;
218 
219           gimp_item_get_offset (item, &off_x, &off_y);
220           x += off_x;
221           y += off_y;
222 
223           /* Assemble the transformation matrix */
224           gimp_matrix3_identity (&matrix);
225           gimp_transform_matrix_flip_free (&matrix, x0, y0, x1, y1);
226 
227           if (progress)
228             gimp_progress_start (progress, FALSE, _("Flipping"));
229 
230           if (GIMP_IS_DRAWABLE (item)                             &&
231               item != GIMP_ITEM (mask)                            &&
232               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
233               ! gimp_channel_is_empty (mask))
234             {
235               GimpDrawable *drawable;
236 
237               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
238                                                          context, &matrix,
239                                                          pdb_context->transform_direction,
240                                                          pdb_context->interpolation,
241                                                          pdb_context->transform_resize,
242                                                          progress);
243 
244               if (drawable)
245                 item = GIMP_ITEM (drawable);
246               else
247                 success = FALSE;
248             }
249           else if (gimp_item_get_linked (item))
250             {
251               gimp_item_linked_transform (item, context, &matrix,
252                                           pdb_context->transform_direction,
253                                           pdb_context->interpolation,
254                                           pdb_context->transform_resize,
255                                           progress);
256             }
257           else
258             {
259               gimp_item_transform (item, context, &matrix,
260                                    pdb_context->transform_direction,
261                                    pdb_context->interpolation,
262                                    gimp_item_get_clip (
263                                      item, pdb_context->transform_resize),
264                                    progress);
265             }
266 
267           if (progress)
268             gimp_progress_end (progress);
269         }
270     }
271 
272   return_vals = gimp_procedure_get_return_values (procedure, success,
273                                                   error ? *error : NULL);
274 
275   if (success)
276     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
277 
278   return return_vals;
279 }
280 
281 static GimpValueArray *
item_transform_perspective_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)282 item_transform_perspective_invoker (GimpProcedure         *procedure,
283                                     Gimp                  *gimp,
284                                     GimpContext           *context,
285                                     GimpProgress          *progress,
286                                     const GimpValueArray  *args,
287                                     GError               **error)
288 {
289   gboolean success = TRUE;
290   GimpValueArray *return_vals;
291   GimpItem *item;
292   gdouble x0;
293   gdouble y0;
294   gdouble x1;
295   gdouble y1;
296   gdouble x2;
297   gdouble y2;
298   gdouble x3;
299   gdouble y3;
300 
301   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
302   x0 = g_value_get_double (gimp_value_array_index (args, 1));
303   y0 = g_value_get_double (gimp_value_array_index (args, 2));
304   x1 = g_value_get_double (gimp_value_array_index (args, 3));
305   y1 = g_value_get_double (gimp_value_array_index (args, 4));
306   x2 = g_value_get_double (gimp_value_array_index (args, 5));
307   y2 = g_value_get_double (gimp_value_array_index (args, 6));
308   x3 = g_value_get_double (gimp_value_array_index (args, 7));
309   y3 = g_value_get_double (gimp_value_array_index (args, 8));
310 
311   if (success)
312     {
313       gint x, y, width, height;
314 
315       success = gimp_pdb_item_is_attached (item, NULL,
316                                            GIMP_PDB_ITEM_CONTENT |
317                                            GIMP_PDB_ITEM_POSITION, error);
318 
319       if (success &&
320           gimp_item_mask_intersect (item, &x, &y, &width, &height))
321         {
322           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
323           GimpImage      *image       = gimp_item_get_image (item);
324           GimpChannel    *mask        = gimp_image_get_mask (image);
325           GimpMatrix3     matrix;
326           gint            off_x, off_y;
327 
328           gimp_item_get_offset (item, &off_x, &off_y);
329           x += off_x;
330           y += off_y;
331 
332           /* Assemble the transformation matrix */
333           gimp_matrix3_identity (&matrix);
334           gimp_transform_matrix_perspective (&matrix,
335                                              x, y, width, height,
336                                              x0, y0, x1, y1,
337                                              x2, y2, x3, y3);
338 
339           if (progress)
340             gimp_progress_start (progress, FALSE, _("Perspective"));
341 
342           if (GIMP_IS_DRAWABLE (item)                             &&
343               item != GIMP_ITEM (mask)                            &&
344               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
345               ! gimp_channel_is_empty (mask))
346             {
347               GimpDrawable *drawable;
348 
349               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
350                                                          context, &matrix,
351                                                          pdb_context->transform_direction,
352                                                          pdb_context->interpolation,
353                                                          pdb_context->transform_resize,
354                                                          progress);
355 
356               if (drawable)
357                 item = GIMP_ITEM (drawable);
358               else
359                 success = FALSE;
360             }
361           else if (gimp_item_get_linked (item))
362             {
363               gimp_item_linked_transform (item, context, &matrix,
364                                           pdb_context->transform_direction,
365                                           pdb_context->interpolation,
366                                           pdb_context->transform_resize,
367                                           progress);
368             }
369           else
370             {
371               gimp_item_transform (item, context, &matrix,
372                                    pdb_context->transform_direction,
373                                    pdb_context->interpolation,
374                                    gimp_item_get_clip (
375                                      item, pdb_context->transform_resize),
376                                    progress);
377             }
378 
379           if (progress)
380             gimp_progress_end (progress);
381         }
382     }
383 
384   return_vals = gimp_procedure_get_return_values (procedure, success,
385                                                   error ? *error : NULL);
386 
387   if (success)
388     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
389 
390   return return_vals;
391 }
392 
393 static GimpValueArray *
item_transform_rotate_simple_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)394 item_transform_rotate_simple_invoker (GimpProcedure         *procedure,
395                                       Gimp                  *gimp,
396                                       GimpContext           *context,
397                                       GimpProgress          *progress,
398                                       const GimpValueArray  *args,
399                                       GError               **error)
400 {
401   gboolean success = TRUE;
402   GimpValueArray *return_vals;
403   GimpItem *item;
404   gint32 rotate_type;
405   gboolean auto_center;
406   gdouble center_x;
407   gdouble center_y;
408 
409   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
410   rotate_type = g_value_get_enum (gimp_value_array_index (args, 1));
411   auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
412   center_x = g_value_get_double (gimp_value_array_index (args, 3));
413   center_y = g_value_get_double (gimp_value_array_index (args, 4));
414 
415   if (success)
416     {
417       gint x, y, width, height;
418 
419       success = gimp_pdb_item_is_attached (item, NULL,
420                                            GIMP_PDB_ITEM_CONTENT |
421                                            GIMP_PDB_ITEM_POSITION, error);
422 
423       if (success &&
424           gimp_item_mask_intersect (item, &x, &y, &width, &height))
425         {
426           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
427           GimpImage      *image       = gimp_item_get_image (item);
428           GimpChannel    *mask        = gimp_image_get_mask (image);
429           gint            off_x, off_y;
430 
431           gimp_item_get_offset (item, &off_x, &off_y);
432           x += off_x;
433           y += off_y;
434 
435           gimp_transform_get_rotate_center (x, y, width, height,
436                                             auto_center, &center_x, &center_y);
437 
438           if (GIMP_IS_DRAWABLE (item)                             &&
439               item != GIMP_ITEM (mask)                            &&
440               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
441               ! gimp_channel_is_empty (mask))
442             {
443               GimpDrawable *drawable;
444 
445               drawable = gimp_drawable_transform_rotate (GIMP_DRAWABLE (item),
446                                                          context,
447                                                          rotate_type,
448                                                          center_x, center_y,
449                                                          pdb_context->transform_resize);
450 
451               if (drawable)
452                 item = GIMP_ITEM (drawable);
453               else
454                 success = FALSE;
455             }
456           else if (gimp_item_get_linked (item))
457             {
458               gimp_item_linked_rotate (item, context,
459                                        rotate_type,
460                                        center_x, center_y,
461                                        pdb_context->transform_resize);
462             }
463           else
464             {
465               gimp_item_rotate (item, context,
466                                 rotate_type,
467                                 center_x, center_y,
468                                 gimp_item_get_clip (
469                                   item, pdb_context->transform_resize));
470             }
471         }
472     }
473 
474   return_vals = gimp_procedure_get_return_values (procedure, success,
475                                                   error ? *error : NULL);
476 
477   if (success)
478     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
479 
480   return return_vals;
481 }
482 
483 static GimpValueArray *
item_transform_rotate_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)484 item_transform_rotate_invoker (GimpProcedure         *procedure,
485                                Gimp                  *gimp,
486                                GimpContext           *context,
487                                GimpProgress          *progress,
488                                const GimpValueArray  *args,
489                                GError               **error)
490 {
491   gboolean success = TRUE;
492   GimpValueArray *return_vals;
493   GimpItem *item;
494   gdouble angle;
495   gboolean auto_center;
496   gdouble center_x;
497   gdouble center_y;
498 
499   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
500   angle = g_value_get_double (gimp_value_array_index (args, 1));
501   auto_center = g_value_get_boolean (gimp_value_array_index (args, 2));
502   center_x = g_value_get_double (gimp_value_array_index (args, 3));
503   center_y = g_value_get_double (gimp_value_array_index (args, 4));
504 
505   if (success)
506     {
507       gint x, y, width, height;
508 
509       success = gimp_pdb_item_is_attached (item, NULL,
510                                            GIMP_PDB_ITEM_CONTENT |
511                                            GIMP_PDB_ITEM_POSITION, error);
512 
513       if (success &&
514           gimp_item_mask_intersect (item, &x, &y, &width, &height))
515         {
516           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
517           GimpImage      *image       = gimp_item_get_image (item);
518           GimpChannel    *mask        = gimp_image_get_mask (image);
519           GimpMatrix3     matrix;
520           gint            off_x, off_y;
521 
522           gimp_item_get_offset (item, &off_x, &off_y);
523           x += off_x;
524           y += off_y;
525 
526           /* Assemble the transformation matrix */
527           gimp_matrix3_identity (&matrix);
528           if (auto_center)
529             gimp_transform_matrix_rotate_rect (&matrix,
530                                                x, y, width, height, angle);
531           else
532             gimp_transform_matrix_rotate_center (&matrix,
533                                                  center_x, center_y, angle);
534 
535           if (progress)
536             gimp_progress_start (progress, FALSE, _("Rotating"));
537 
538           if (GIMP_IS_DRAWABLE (item)                             &&
539               item != GIMP_ITEM (mask)                            &&
540               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
541               ! gimp_channel_is_empty (mask))
542             {
543               GimpDrawable *drawable;
544 
545               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
546                                                          context, &matrix,
547                                                          pdb_context->transform_direction,
548                                                          pdb_context->interpolation,
549                                                          pdb_context->transform_resize,
550                                                          progress);
551 
552               if (drawable)
553                 item = GIMP_ITEM (drawable);
554               else
555                 success = FALSE;
556             }
557           else if (gimp_item_get_linked (item))
558             {
559               gimp_item_linked_transform (item, context, &matrix,
560                                           pdb_context->transform_direction,
561                                           pdb_context->interpolation,
562                                           pdb_context->transform_resize,
563                                           progress);
564             }
565           else
566             {
567               gimp_item_transform (item, context, &matrix,
568                                    pdb_context->transform_direction,
569                                    pdb_context->interpolation,
570                                    gimp_item_get_clip (
571                                      item, pdb_context->transform_resize),
572                                    progress);
573             }
574 
575           if (progress)
576             gimp_progress_end (progress);
577         }
578     }
579 
580   return_vals = gimp_procedure_get_return_values (procedure, success,
581                                                   error ? *error : NULL);
582 
583   if (success)
584     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
585 
586   return return_vals;
587 }
588 
589 static GimpValueArray *
item_transform_scale_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)590 item_transform_scale_invoker (GimpProcedure         *procedure,
591                               Gimp                  *gimp,
592                               GimpContext           *context,
593                               GimpProgress          *progress,
594                               const GimpValueArray  *args,
595                               GError               **error)
596 {
597   gboolean success = TRUE;
598   GimpValueArray *return_vals;
599   GimpItem *item;
600   gdouble x0;
601   gdouble y0;
602   gdouble x1;
603   gdouble y1;
604 
605   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
606   x0 = g_value_get_double (gimp_value_array_index (args, 1));
607   y0 = g_value_get_double (gimp_value_array_index (args, 2));
608   x1 = g_value_get_double (gimp_value_array_index (args, 3));
609   y1 = g_value_get_double (gimp_value_array_index (args, 4));
610 
611   if (success)
612     {
613       gint x, y, width, height;
614 
615       success = (gimp_pdb_item_is_attached (item, NULL,
616                                             GIMP_PDB_ITEM_CONTENT |
617                                             GIMP_PDB_ITEM_POSITION, error) &&
618                  x0 < x1 && y0 < y1);
619 
620       if (success &&
621           gimp_item_mask_intersect (item, &x, &y, &width, &height))
622         {
623           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
624           GimpImage      *image       = gimp_item_get_image (item);
625           GimpChannel    *mask        = gimp_image_get_mask (image);
626           GimpMatrix3     matrix;
627           gint            off_x, off_y;
628 
629           gimp_item_get_offset (item, &off_x, &off_y);
630           x += off_x;
631           y += off_y;
632 
633           /* Assemble the transformation matrix */
634           gimp_matrix3_identity (&matrix);
635           gimp_transform_matrix_scale (&matrix,
636                                        x, y, width, height,
637                                        x0, y0, x1 - x0, y1 - y0);
638 
639           if (progress)
640             gimp_progress_start (progress, FALSE, _("Scaling"));
641 
642           if (GIMP_IS_DRAWABLE (item)                             &&
643               item != GIMP_ITEM (mask)                            &&
644               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
645               ! gimp_channel_is_empty (mask))
646             {
647               GimpDrawable *drawable;
648 
649               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
650                                                          context, &matrix,
651                                                          pdb_context->transform_direction,
652                                                          pdb_context->interpolation,
653                                                          pdb_context->transform_resize,
654                                                          progress);
655 
656               if (drawable)
657                 item = GIMP_ITEM (drawable);
658               else
659                 success = FALSE;
660             }
661           else if (gimp_item_get_linked (item))
662             {
663               gimp_item_linked_transform (item, context, &matrix,
664                                           pdb_context->transform_direction,
665                                           pdb_context->interpolation,
666                                           pdb_context->transform_resize,
667                                           progress);
668             }
669           else
670             {
671               gimp_item_transform (item, context, &matrix,
672                                    pdb_context->transform_direction,
673                                    pdb_context->interpolation,
674                                    gimp_item_get_clip (
675                                      item, pdb_context->transform_resize),
676                                    progress);
677             }
678 
679           if (progress)
680             gimp_progress_end (progress);
681         }
682     }
683 
684   return_vals = gimp_procedure_get_return_values (procedure, success,
685                                                   error ? *error : NULL);
686 
687   if (success)
688     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
689 
690   return return_vals;
691 }
692 
693 static GimpValueArray *
item_transform_shear_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)694 item_transform_shear_invoker (GimpProcedure         *procedure,
695                               Gimp                  *gimp,
696                               GimpContext           *context,
697                               GimpProgress          *progress,
698                               const GimpValueArray  *args,
699                               GError               **error)
700 {
701   gboolean success = TRUE;
702   GimpValueArray *return_vals;
703   GimpItem *item;
704   gint32 shear_type;
705   gdouble magnitude;
706 
707   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
708   shear_type = g_value_get_enum (gimp_value_array_index (args, 1));
709   magnitude = g_value_get_double (gimp_value_array_index (args, 2));
710 
711   if (success)
712     {
713       gint x, y, width, height;
714 
715       success = gimp_pdb_item_is_attached (item, NULL,
716                                            GIMP_PDB_ITEM_CONTENT |
717                                            GIMP_PDB_ITEM_POSITION, error);
718 
719       if (success &&
720           gimp_item_mask_intersect (item, &x, &y, &width, &height))
721         {
722           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
723           GimpImage      *image       = gimp_item_get_image (item);
724           GimpChannel    *mask        = gimp_image_get_mask (image);
725           GimpMatrix3     matrix;
726           gint            off_x, off_y;
727 
728           gimp_item_get_offset (item, &off_x, &off_y);
729           x += off_x;
730           y += off_y;
731 
732           /* Assemble the transformation matrix */
733           gimp_matrix3_identity (&matrix);
734           gimp_transform_matrix_shear (&matrix,
735                                        x, y, width, height,
736                                        shear_type, magnitude);
737 
738           if (progress)
739             gimp_progress_start (progress, FALSE, _("Shearing"));
740 
741           if (GIMP_IS_DRAWABLE (item)                             &&
742               item != GIMP_ITEM (mask)                            &&
743               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
744               ! gimp_channel_is_empty (mask))
745             {
746               GimpDrawable *drawable;
747 
748               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
749                                                          context, &matrix,
750                                                          pdb_context->transform_direction,
751                                                          pdb_context->interpolation,
752                                                          pdb_context->transform_resize,
753                                                          progress);
754 
755               if (drawable)
756                 item = GIMP_ITEM (drawable);
757               else
758                 success = FALSE;
759             }
760           else if (gimp_item_get_linked (item))
761             {
762               gimp_item_linked_transform (item, context, &matrix,
763                                           pdb_context->transform_direction,
764                                           pdb_context->interpolation,
765                                           pdb_context->transform_resize,
766                                           progress);
767             }
768           else
769             {
770               gimp_item_transform (item, context, &matrix,
771                                    pdb_context->transform_direction,
772                                    pdb_context->interpolation,
773                                    gimp_item_get_clip (
774                                      item, pdb_context->transform_resize),
775                                    progress);
776             }
777 
778           if (progress)
779             gimp_progress_end (progress);
780         }
781     }
782 
783   return_vals = gimp_procedure_get_return_values (procedure, success,
784                                                   error ? *error : NULL);
785 
786   if (success)
787     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
788 
789   return return_vals;
790 }
791 
792 static GimpValueArray *
item_transform_2d_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)793 item_transform_2d_invoker (GimpProcedure         *procedure,
794                            Gimp                  *gimp,
795                            GimpContext           *context,
796                            GimpProgress          *progress,
797                            const GimpValueArray  *args,
798                            GError               **error)
799 {
800   gboolean success = TRUE;
801   GimpValueArray *return_vals;
802   GimpItem *item;
803   gdouble source_x;
804   gdouble source_y;
805   gdouble scale_x;
806   gdouble scale_y;
807   gdouble angle;
808   gdouble dest_x;
809   gdouble dest_y;
810 
811   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
812   source_x = g_value_get_double (gimp_value_array_index (args, 1));
813   source_y = g_value_get_double (gimp_value_array_index (args, 2));
814   scale_x = g_value_get_double (gimp_value_array_index (args, 3));
815   scale_y = g_value_get_double (gimp_value_array_index (args, 4));
816   angle = g_value_get_double (gimp_value_array_index (args, 5));
817   dest_x = g_value_get_double (gimp_value_array_index (args, 6));
818   dest_y = g_value_get_double (gimp_value_array_index (args, 7));
819 
820   if (success)
821     {
822       gint x, y, width, height;
823 
824       success = gimp_pdb_item_is_attached (item, NULL,
825                                            GIMP_PDB_ITEM_CONTENT |
826                                            GIMP_PDB_ITEM_POSITION, error);
827 
828       if (success &&
829           gimp_item_mask_intersect (item, &x, &y, &width, &height))
830         {
831           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
832           GimpImage      *image       = gimp_item_get_image (item);
833           GimpChannel    *mask        = gimp_image_get_mask (image);
834           GimpMatrix3     matrix;
835           gint            off_x, off_y;
836 
837           gimp_item_get_offset (item, &off_x, &off_y);
838           x += off_x;
839           y += off_y;
840 
841           /* Assemble the transformation matrix */
842           gimp_matrix3_identity  (&matrix);
843           gimp_matrix3_translate (&matrix, -source_x, -source_y);
844           gimp_matrix3_scale     (&matrix, scale_x, scale_y);
845           gimp_matrix3_rotate    (&matrix, angle);
846           gimp_matrix3_translate (&matrix, dest_x, dest_y);
847 
848           if (progress)
849             gimp_progress_start (progress, FALSE, _("2D Transform"));
850 
851           if (GIMP_IS_DRAWABLE (item)                             &&
852               item != GIMP_ITEM (mask)                            &&
853               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
854               ! gimp_channel_is_empty (mask))
855             {
856               GimpDrawable *drawable;
857 
858               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
859                                                          context, &matrix,
860                                                          pdb_context->transform_direction,
861                                                          pdb_context->interpolation,
862                                                          pdb_context->transform_resize,
863                                                          progress);
864 
865               if (drawable)
866                 item = GIMP_ITEM (drawable);
867               else
868                 success = FALSE;
869             }
870           else if (gimp_item_get_linked (item))
871             {
872               gimp_item_linked_transform (item, context, &matrix,
873                                           pdb_context->transform_direction,
874                                           pdb_context->interpolation,
875                                           pdb_context->transform_resize,
876                                           progress);
877             }
878           else
879             {
880               gimp_item_transform (item, context, &matrix,
881                                    pdb_context->transform_direction,
882                                    pdb_context->interpolation,
883                                    gimp_item_get_clip (
884                                      item, pdb_context->transform_resize),
885                                    progress);
886             }
887 
888           if (progress)
889             gimp_progress_end (progress);
890         }
891     }
892 
893   return_vals = gimp_procedure_get_return_values (procedure, success,
894                                                   error ? *error : NULL);
895 
896   if (success)
897     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
898 
899   return return_vals;
900 }
901 
902 static GimpValueArray *
item_transform_matrix_invoker(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,const GimpValueArray * args,GError ** error)903 item_transform_matrix_invoker (GimpProcedure         *procedure,
904                                Gimp                  *gimp,
905                                GimpContext           *context,
906                                GimpProgress          *progress,
907                                const GimpValueArray  *args,
908                                GError               **error)
909 {
910   gboolean success = TRUE;
911   GimpValueArray *return_vals;
912   GimpItem *item;
913   gdouble coeff_0_0;
914   gdouble coeff_0_1;
915   gdouble coeff_0_2;
916   gdouble coeff_1_0;
917   gdouble coeff_1_1;
918   gdouble coeff_1_2;
919   gdouble coeff_2_0;
920   gdouble coeff_2_1;
921   gdouble coeff_2_2;
922 
923   item = gimp_value_get_item (gimp_value_array_index (args, 0), gimp);
924   coeff_0_0 = g_value_get_double (gimp_value_array_index (args, 1));
925   coeff_0_1 = g_value_get_double (gimp_value_array_index (args, 2));
926   coeff_0_2 = g_value_get_double (gimp_value_array_index (args, 3));
927   coeff_1_0 = g_value_get_double (gimp_value_array_index (args, 4));
928   coeff_1_1 = g_value_get_double (gimp_value_array_index (args, 5));
929   coeff_1_2 = g_value_get_double (gimp_value_array_index (args, 6));
930   coeff_2_0 = g_value_get_double (gimp_value_array_index (args, 7));
931   coeff_2_1 = g_value_get_double (gimp_value_array_index (args, 8));
932   coeff_2_2 = g_value_get_double (gimp_value_array_index (args, 9));
933 
934   if (success)
935     {
936       gint x, y, width, height;
937 
938       success = gimp_pdb_item_is_attached (item, NULL,
939                                            GIMP_PDB_ITEM_CONTENT |
940                                            GIMP_PDB_ITEM_POSITION, error);
941 
942       if (success &&
943           gimp_item_mask_intersect (item, &x, &y, &width, &height))
944         {
945           GimpPDBContext *pdb_context = GIMP_PDB_CONTEXT (context);
946           GimpImage      *image       = gimp_item_get_image (item);
947           GimpChannel    *mask        = gimp_image_get_mask (image);
948           GimpMatrix3     matrix;
949           gint            off_x, off_y;
950 
951           gimp_item_get_offset (item, &off_x, &off_y);
952           x += off_x;
953           y += off_y;
954 
955           /* Assemble the transformation matrix */
956           matrix.coeff[0][0] = coeff_0_0;
957           matrix.coeff[0][1] = coeff_0_1;
958           matrix.coeff[0][2] = coeff_0_2;
959           matrix.coeff[1][0] = coeff_1_0;
960           matrix.coeff[1][1] = coeff_1_1;
961           matrix.coeff[1][2] = coeff_1_2;
962           matrix.coeff[2][0] = coeff_2_0;
963           matrix.coeff[2][1] = coeff_2_1;
964           matrix.coeff[2][2] = coeff_2_2;
965 
966           if (progress)
967             gimp_progress_start (progress, FALSE, _("2D Transforming"));
968 
969           if (GIMP_IS_DRAWABLE (item)                             &&
970               item != GIMP_ITEM (mask)                            &&
971               ! gimp_viewable_get_children (GIMP_VIEWABLE (item)) &&
972               ! gimp_channel_is_empty (mask))
973             {
974               GimpDrawable *drawable;
975 
976               drawable = gimp_drawable_transform_affine (GIMP_DRAWABLE (item),
977                                                          context, &matrix,
978                                                          pdb_context->transform_direction,
979                                                          pdb_context->interpolation,
980                                                          pdb_context->transform_resize,
981                                                          progress);
982 
983               if (drawable)
984                 item = GIMP_ITEM (drawable);
985               else
986                 success = FALSE;
987             }
988           else if (gimp_item_get_linked (item))
989             {
990               gimp_item_linked_transform (item, context, &matrix,
991                                           pdb_context->transform_direction,
992                                           pdb_context->interpolation,
993                                           pdb_context->transform_resize,
994                                           progress);
995             }
996           else
997             {
998               gimp_item_transform (item, context, &matrix,
999                                    pdb_context->transform_direction,
1000                                    pdb_context->interpolation,
1001                                    gimp_item_get_clip (
1002                                      item, pdb_context->transform_resize),
1003                                    progress);
1004             }
1005 
1006           if (progress)
1007             gimp_progress_end (progress);
1008         }
1009     }
1010 
1011   return_vals = gimp_procedure_get_return_values (procedure, success,
1012                                                   error ? *error : NULL);
1013 
1014   if (success)
1015     gimp_value_set_item (gimp_value_array_index (return_vals, 1), item);
1016 
1017   return return_vals;
1018 }
1019 
1020 void
register_item_transform_procs(GimpPDB * pdb)1021 register_item_transform_procs (GimpPDB *pdb)
1022 {
1023   GimpProcedure *procedure;
1024 
1025   /*
1026    * gimp-item-transform-translate
1027    */
1028   procedure = gimp_procedure_new (item_transform_translate_invoker);
1029   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1030                                "gimp-item-transform-translate");
1031   gimp_procedure_set_static_strings (procedure,
1032                                      "gimp-item-transform-translate",
1033                                      "Translate the item by the specified offsets.",
1034                                      "This procedure translates the item by the amounts specified in the off_x and off_y arguments. These can be negative, and are considered offsets from the current position. The offsets will be rounded to the nearest pixel unless the item is a path.\n"
1035                                      "\n"
1036                                      "If the item is attached to an image and has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be translated by the specified offsets.",
1037                                      "Michael Natterer <mitch@gimp.org>",
1038                                      "Michael Natterer",
1039                                      "2018",
1040                                      NULL);
1041   gimp_procedure_add_argument (procedure,
1042                                gimp_param_spec_item_id ("item",
1043                                                         "item",
1044                                                         "The item",
1045                                                         pdb->gimp, FALSE,
1046                                                         GIMP_PARAM_READWRITE));
1047   gimp_procedure_add_argument (procedure,
1048                                g_param_spec_double ("off-x",
1049                                                     "off x",
1050                                                     "Offset in x direction",
1051                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1052                                                     GIMP_PARAM_READWRITE));
1053   gimp_procedure_add_argument (procedure,
1054                                g_param_spec_double ("off-y",
1055                                                     "off y",
1056                                                     "Offset in y direction",
1057                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1058                                                     GIMP_PARAM_READWRITE));
1059   gimp_procedure_add_return_value (procedure,
1060                                    gimp_param_spec_item_id ("item",
1061                                                             "item",
1062                                                             "The translated item",
1063                                                             pdb->gimp, FALSE,
1064                                                             GIMP_PARAM_READWRITE));
1065   gimp_pdb_register_procedure (pdb, procedure);
1066   g_object_unref (procedure);
1067 
1068   /*
1069    * gimp-item-transform-flip-simple
1070    */
1071   procedure = gimp_procedure_new (item_transform_flip_simple_invoker);
1072   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1073                                "gimp-item-transform-flip-simple");
1074   gimp_procedure_set_static_strings (procedure,
1075                                      "gimp-item-transform-flip-simple",
1076                                      "Flip the specified item either vertically or horizontally.",
1077                                      "This procedure flips the specified item.\n"
1078                                      "\n"
1079                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then flipped. If auto_center is set to TRUE, the flip is around the selection's center. Otherwise, the coordinate of the axis needs to be specified. The return value is the ID of the flipped floating selection.\n"
1080                                      "\n"
1081                                      "If there is no selection or the item is not a drawable, the entire item will be flipped around its center if auto_center is set to TRUE, otherwise the coordinate of the axis needs to be specified. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be flipped around the same axis. The return value will be equal to the item ID supplied as input.\n"
1082                                      "\n"
1083                                      "This procedure is affected by the following context setters: 'gimp-context-set-transform-resize'.",
1084                                      "Michael Natterer <mitch@gimp.org>",
1085                                      "Michael Natterer",
1086                                      "2004",
1087                                      NULL);
1088   gimp_procedure_add_argument (procedure,
1089                                gimp_param_spec_item_id ("item",
1090                                                         "item",
1091                                                         "The affected item",
1092                                                         pdb->gimp, FALSE,
1093                                                         GIMP_PARAM_READWRITE));
1094   gimp_procedure_add_argument (procedure,
1095                                gimp_param_spec_enum ("flip-type",
1096                                                      "flip type",
1097                                                      "Type of flip",
1098                                                      GIMP_TYPE_ORIENTATION_TYPE,
1099                                                      GIMP_ORIENTATION_HORIZONTAL,
1100                                                      GIMP_PARAM_READWRITE));
1101   gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[1]),
1102                                       GIMP_ORIENTATION_UNKNOWN);
1103   gimp_procedure_add_argument (procedure,
1104                                g_param_spec_boolean ("auto-center",
1105                                                      "auto center",
1106                                                      "Whether to automatically position the axis in the selection center",
1107                                                      FALSE,
1108                                                      GIMP_PARAM_READWRITE));
1109   gimp_procedure_add_argument (procedure,
1110                                g_param_spec_double ("axis",
1111                                                     "axis",
1112                                                     "coord. of flip axis",
1113                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1114                                                     GIMP_PARAM_READWRITE));
1115   gimp_procedure_add_return_value (procedure,
1116                                    gimp_param_spec_item_id ("item",
1117                                                             "item",
1118                                                             "The flipped item",
1119                                                             pdb->gimp, FALSE,
1120                                                             GIMP_PARAM_READWRITE));
1121   gimp_pdb_register_procedure (pdb, procedure);
1122   g_object_unref (procedure);
1123 
1124   /*
1125    * gimp-item-transform-flip
1126    */
1127   procedure = gimp_procedure_new (item_transform_flip_invoker);
1128   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1129                                "gimp-item-transform-flip");
1130   gimp_procedure_set_static_strings (procedure,
1131                                      "gimp-item-transform-flip",
1132                                      "Flip the specified item around a given line.",
1133                                      "This procedure flips the specified item.\n"
1134                                      "\n"
1135                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then flipped. The axis to flip around is specified by specifying two points from that line. The return value is the ID of the flipped floating selection.\n"
1136                                      "\n"
1137                                      "If there is no selection or the item is not a drawable, the entire item will be flipped around the specified axis. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be flipped around the same axis. The return value will be equal to the item ID supplied as input.\n"
1138                                      "\n"
1139                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1140                                      "Michael Natterer <mitch@gimp.org>",
1141                                      "Michael Natterer",
1142                                      "2010",
1143                                      NULL);
1144   gimp_procedure_add_argument (procedure,
1145                                gimp_param_spec_item_id ("item",
1146                                                         "item",
1147                                                         "The affected item",
1148                                                         pdb->gimp, FALSE,
1149                                                         GIMP_PARAM_READWRITE));
1150   gimp_procedure_add_argument (procedure,
1151                                g_param_spec_double ("x0",
1152                                                     "x0",
1153                                                     "horz. coord. of one end of axis",
1154                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1155                                                     GIMP_PARAM_READWRITE));
1156   gimp_procedure_add_argument (procedure,
1157                                g_param_spec_double ("y0",
1158                                                     "y0",
1159                                                     "vert. coord. of one end of axis",
1160                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1161                                                     GIMP_PARAM_READWRITE));
1162   gimp_procedure_add_argument (procedure,
1163                                g_param_spec_double ("x1",
1164                                                     "x1",
1165                                                     "horz. coord. of other end of axis",
1166                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1167                                                     GIMP_PARAM_READWRITE));
1168   gimp_procedure_add_argument (procedure,
1169                                g_param_spec_double ("y1",
1170                                                     "y1",
1171                                                     "vert. coord. of other end of axis",
1172                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1173                                                     GIMP_PARAM_READWRITE));
1174   gimp_procedure_add_return_value (procedure,
1175                                    gimp_param_spec_item_id ("item",
1176                                                             "item",
1177                                                             "The flipped item",
1178                                                             pdb->gimp, FALSE,
1179                                                             GIMP_PARAM_READWRITE));
1180   gimp_pdb_register_procedure (pdb, procedure);
1181   g_object_unref (procedure);
1182 
1183   /*
1184    * gimp-item-transform-perspective
1185    */
1186   procedure = gimp_procedure_new (item_transform_perspective_invoker);
1187   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1188                                "gimp-item-transform-perspective");
1189   gimp_procedure_set_static_strings (procedure,
1190                                      "gimp-item-transform-perspective",
1191                                      "Perform a possibly non-affine transformation on the specified item.",
1192                                      "This procedure performs a possibly non-affine transformation on the specified item by allowing the corners of the original bounding box to be arbitrarily remapped to any values.\n"
1193                                      "\n"
1194                                      "The 4 coordinates specify the new locations of each corner of the original bounding box. By specifying these values, any affine transformation (rotation, scaling, translation) can be affected. Additionally, these values can be specified such that the resulting transformed item will appear to have been projected via a perspective transform.\n"
1195                                      "\n"
1196                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then transformed as specified. The return value is the ID of the transformed floating selection.\n"
1197                                      "\n"
1198                                      "If there is no selection or the item is not a drawable, the entire item will be transformed according to the specified mapping. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be transformed the same way. The return value will be equal to the item ID supplied as input.\n"
1199                                      "\n"
1200                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1201                                      "Michael Natterer <mitch@gimp.org>",
1202                                      "Michael Natterer",
1203                                      "2010",
1204                                      NULL);
1205   gimp_procedure_add_argument (procedure,
1206                                gimp_param_spec_item_id ("item",
1207                                                         "item",
1208                                                         "The affected item",
1209                                                         pdb->gimp, FALSE,
1210                                                         GIMP_PARAM_READWRITE));
1211   gimp_procedure_add_argument (procedure,
1212                                g_param_spec_double ("x0",
1213                                                     "x0",
1214                                                     "The new x coordinate of upper-left corner of original bounding box",
1215                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1216                                                     GIMP_PARAM_READWRITE));
1217   gimp_procedure_add_argument (procedure,
1218                                g_param_spec_double ("y0",
1219                                                     "y0",
1220                                                     "The new y coordinate of upper-left corner of original bounding box",
1221                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1222                                                     GIMP_PARAM_READWRITE));
1223   gimp_procedure_add_argument (procedure,
1224                                g_param_spec_double ("x1",
1225                                                     "x1",
1226                                                     "The new x coordinate of upper-right corner of original bounding box",
1227                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1228                                                     GIMP_PARAM_READWRITE));
1229   gimp_procedure_add_argument (procedure,
1230                                g_param_spec_double ("y1",
1231                                                     "y1",
1232                                                     "The new y coordinate of upper-right corner of original bounding box",
1233                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1234                                                     GIMP_PARAM_READWRITE));
1235   gimp_procedure_add_argument (procedure,
1236                                g_param_spec_double ("x2",
1237                                                     "x2",
1238                                                     "The new x coordinate of lower-left corner of original bounding box",
1239                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1240                                                     GIMP_PARAM_READWRITE));
1241   gimp_procedure_add_argument (procedure,
1242                                g_param_spec_double ("y2",
1243                                                     "y2",
1244                                                     "The new y coordinate of lower-left corner of original bounding box",
1245                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1246                                                     GIMP_PARAM_READWRITE));
1247   gimp_procedure_add_argument (procedure,
1248                                g_param_spec_double ("x3",
1249                                                     "x3",
1250                                                     "The new x coordinate of lower-right corner of original bounding box",
1251                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1252                                                     GIMP_PARAM_READWRITE));
1253   gimp_procedure_add_argument (procedure,
1254                                g_param_spec_double ("y3",
1255                                                     "y3",
1256                                                     "The new y coordinate of lower-right corner of original bounding box",
1257                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1258                                                     GIMP_PARAM_READWRITE));
1259   gimp_procedure_add_return_value (procedure,
1260                                    gimp_param_spec_item_id ("item",
1261                                                             "item",
1262                                                             "The transformed item",
1263                                                             pdb->gimp, FALSE,
1264                                                             GIMP_PARAM_READWRITE));
1265   gimp_pdb_register_procedure (pdb, procedure);
1266   g_object_unref (procedure);
1267 
1268   /*
1269    * gimp-item-transform-rotate-simple
1270    */
1271   procedure = gimp_procedure_new (item_transform_rotate_simple_invoker);
1272   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1273                                "gimp-item-transform-rotate-simple");
1274   gimp_procedure_set_static_strings (procedure,
1275                                      "gimp-item-transform-rotate-simple",
1276                                      "Rotate the specified item about given coordinates through the specified angle.",
1277                                      "This function rotates the specified item.\n"
1278                                      "\n"
1279                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then rotated by the specified amount. If auto_center is set to TRUE, the rotation is around the selection's center. Otherwise, the coordinate of the center point needs to be specified. The return value is the ID of the rotated floating selection.\n"
1280                                      "\n"
1281                                      "If there is no selection or the item is not a drawable, the entire item will be rotated around its center if auto_center is set to TRUE, otherwise the coordinate of the center point needs to be specified. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be rotated around the same center point. The return value will be equal to the item ID supplied as input.\n"
1282                                      "\n"
1283                                      "This procedure is affected by the following context setters: 'gimp-context-set-transform-resize'.",
1284                                      "Michael Natterer <mitch@gimp.org>",
1285                                      "Michael Natterer",
1286                                      "2010",
1287                                      NULL);
1288   gimp_procedure_add_argument (procedure,
1289                                gimp_param_spec_item_id ("item",
1290                                                         "item",
1291                                                         "The affected item",
1292                                                         pdb->gimp, FALSE,
1293                                                         GIMP_PARAM_READWRITE));
1294   gimp_procedure_add_argument (procedure,
1295                                g_param_spec_enum ("rotate-type",
1296                                                   "rotate type",
1297                                                   "Type of rotation",
1298                                                   GIMP_TYPE_ROTATION_TYPE,
1299                                                   GIMP_ROTATE_90,
1300                                                   GIMP_PARAM_READWRITE));
1301   gimp_procedure_add_argument (procedure,
1302                                g_param_spec_boolean ("auto-center",
1303                                                      "auto center",
1304                                                      "Whether to automatically rotate around the selection center",
1305                                                      FALSE,
1306                                                      GIMP_PARAM_READWRITE));
1307   gimp_procedure_add_argument (procedure,
1308                                g_param_spec_double ("center-x",
1309                                                     "center x",
1310                                                     "The hor. coordinate of the center of rotation",
1311                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1312                                                     GIMP_PARAM_READWRITE));
1313   gimp_procedure_add_argument (procedure,
1314                                g_param_spec_double ("center-y",
1315                                                     "center y",
1316                                                     "The vert. coordinate of the center of rotation",
1317                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1318                                                     GIMP_PARAM_READWRITE));
1319   gimp_procedure_add_return_value (procedure,
1320                                    gimp_param_spec_item_id ("item",
1321                                                             "item",
1322                                                             "The rotated item",
1323                                                             pdb->gimp, FALSE,
1324                                                             GIMP_PARAM_READWRITE));
1325   gimp_pdb_register_procedure (pdb, procedure);
1326   g_object_unref (procedure);
1327 
1328   /*
1329    * gimp-item-transform-rotate
1330    */
1331   procedure = gimp_procedure_new (item_transform_rotate_invoker);
1332   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1333                                "gimp-item-transform-rotate");
1334   gimp_procedure_set_static_strings (procedure,
1335                                      "gimp-item-transform-rotate",
1336                                      "Rotate the specified item about given coordinates through the specified angle.",
1337                                      "This function rotates the specified item.\n"
1338                                      "\n"
1339                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then rotated by the specified amount. If auto_center is set to TRUE, the rotation is around the selection's center. Otherwise, the coordinate of the center point needs to be specified. The return value is the ID of the rotated floating selection.\n"
1340                                      "\n"
1341                                      "If there is no selection or the item is not a drawable, the entire item will be rotated around its center if auto_center is set to TRUE, otherwise the coordinate of the center point needs to be specified. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be rotated around the same center point. The return value will be equal to the item ID supplied as input.\n"
1342                                      "\n"
1343                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1344                                      "Michael Natterer <mitch@gimp.org>",
1345                                      "Michael Natterer",
1346                                      "2010",
1347                                      NULL);
1348   gimp_procedure_add_argument (procedure,
1349                                gimp_param_spec_item_id ("item",
1350                                                         "item",
1351                                                         "The affected item",
1352                                                         pdb->gimp, FALSE,
1353                                                         GIMP_PARAM_READWRITE));
1354   gimp_procedure_add_argument (procedure,
1355                                g_param_spec_double ("angle",
1356                                                     "angle",
1357                                                     "The angle of rotation (radians)",
1358                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1359                                                     GIMP_PARAM_READWRITE));
1360   gimp_procedure_add_argument (procedure,
1361                                g_param_spec_boolean ("auto-center",
1362                                                      "auto center",
1363                                                      "Whether to automatically rotate around the selection center",
1364                                                      FALSE,
1365                                                      GIMP_PARAM_READWRITE));
1366   gimp_procedure_add_argument (procedure,
1367                                g_param_spec_double ("center-x",
1368                                                     "center x",
1369                                                     "The hor. coordinate of the center of rotation",
1370                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1371                                                     GIMP_PARAM_READWRITE));
1372   gimp_procedure_add_argument (procedure,
1373                                g_param_spec_double ("center-y",
1374                                                     "center y",
1375                                                     "The vert. coordinate of the center of rotation",
1376                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1377                                                     GIMP_PARAM_READWRITE));
1378   gimp_procedure_add_return_value (procedure,
1379                                    gimp_param_spec_item_id ("item",
1380                                                             "item",
1381                                                             "The rotated item",
1382                                                             pdb->gimp, FALSE,
1383                                                             GIMP_PARAM_READWRITE));
1384   gimp_pdb_register_procedure (pdb, procedure);
1385   g_object_unref (procedure);
1386 
1387   /*
1388    * gimp-item-transform-scale
1389    */
1390   procedure = gimp_procedure_new (item_transform_scale_invoker);
1391   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1392                                "gimp-item-transform-scale");
1393   gimp_procedure_set_static_strings (procedure,
1394                                      "gimp-item-transform-scale",
1395                                      "Scale the specified item.",
1396                                      "This procedure scales the specified item.\n"
1397                                      "\n"
1398                                      "The 2 coordinates specify the new locations of the top-left and bottom-roght corners of the original bounding box.\n"
1399                                      "\n"
1400                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then scaled as specified. The return value is the ID of the scaled floating selection.\n"
1401                                      "\n"
1402                                      "If there is no selection or the item is not a drawable, the entire item will be scaled according to the specified coordinates. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be scaled the same way. The return value will be equal to the item ID supplied as input.\n"
1403                                      "\n"
1404                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1405                                      "Michael Natterer <mitch@gimp.org>",
1406                                      "Michael Natterer",
1407                                      "2010",
1408                                      NULL);
1409   gimp_procedure_add_argument (procedure,
1410                                gimp_param_spec_item_id ("item",
1411                                                         "item",
1412                                                         "The affected item",
1413                                                         pdb->gimp, FALSE,
1414                                                         GIMP_PARAM_READWRITE));
1415   gimp_procedure_add_argument (procedure,
1416                                g_param_spec_double ("x0",
1417                                                     "x0",
1418                                                     "The new x coordinate of the upper-left corner of the scaled region",
1419                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1420                                                     GIMP_PARAM_READWRITE));
1421   gimp_procedure_add_argument (procedure,
1422                                g_param_spec_double ("y0",
1423                                                     "y0",
1424                                                     "The new y coordinate of the upper-left corner of the scaled region",
1425                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1426                                                     GIMP_PARAM_READWRITE));
1427   gimp_procedure_add_argument (procedure,
1428                                g_param_spec_double ("x1",
1429                                                     "x1",
1430                                                     "The new x coordinate of the lower-right corner of the scaled region",
1431                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1432                                                     GIMP_PARAM_READWRITE));
1433   gimp_procedure_add_argument (procedure,
1434                                g_param_spec_double ("y1",
1435                                                     "y1",
1436                                                     "The new y coordinate of the lower-right corner of the scaled region",
1437                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1438                                                     GIMP_PARAM_READWRITE));
1439   gimp_procedure_add_return_value (procedure,
1440                                    gimp_param_spec_item_id ("item",
1441                                                             "item",
1442                                                             "The scaled item",
1443                                                             pdb->gimp, FALSE,
1444                                                             GIMP_PARAM_READWRITE));
1445   gimp_pdb_register_procedure (pdb, procedure);
1446   g_object_unref (procedure);
1447 
1448   /*
1449    * gimp-item-transform-shear
1450    */
1451   procedure = gimp_procedure_new (item_transform_shear_invoker);
1452   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1453                                "gimp-item-transform-shear");
1454   gimp_procedure_set_static_strings (procedure,
1455                                      "gimp-item-transform-shear",
1456                                      "Shear the specified item about its center by the specified magnitude.",
1457                                      "This procedure shears the specified item.\n"
1458                                      "\n"
1459                                      "The shear type parameter indicates whether the shear will be applied horizontally or vertically. The magnitude can be either positive or negative and indicates the extent (in pixels) to shear by.\n"
1460                                      "\n"
1461                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then sheared as specified. The return value is the ID of the sheared floating selection.\n"
1462                                      "\n"
1463                                      "If there is no selection or the item is not a drawable, the entire item will be sheared according to the specified parameters. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be sheared the same way. The return value will be equal to the item ID supplied as input.\n"
1464                                      "\n"
1465                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1466                                      "Michael Natterer <mitch@gimp.org>",
1467                                      "Michael Natterer",
1468                                      "2010",
1469                                      NULL);
1470   gimp_procedure_add_argument (procedure,
1471                                gimp_param_spec_item_id ("item",
1472                                                         "item",
1473                                                         "The affected item",
1474                                                         pdb->gimp, FALSE,
1475                                                         GIMP_PARAM_READWRITE));
1476   gimp_procedure_add_argument (procedure,
1477                                gimp_param_spec_enum ("shear-type",
1478                                                      "shear type",
1479                                                      "Type of shear",
1480                                                      GIMP_TYPE_ORIENTATION_TYPE,
1481                                                      GIMP_ORIENTATION_HORIZONTAL,
1482                                                      GIMP_PARAM_READWRITE));
1483   gimp_param_spec_enum_exclude_value (GIMP_PARAM_SPEC_ENUM (procedure->args[1]),
1484                                       GIMP_ORIENTATION_UNKNOWN);
1485   gimp_procedure_add_argument (procedure,
1486                                g_param_spec_double ("magnitude",
1487                                                     "magnitude",
1488                                                     "The magnitude of the shear",
1489                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1490                                                     GIMP_PARAM_READWRITE));
1491   gimp_procedure_add_return_value (procedure,
1492                                    gimp_param_spec_item_id ("item",
1493                                                             "item",
1494                                                             "The sheared item",
1495                                                             pdb->gimp, FALSE,
1496                                                             GIMP_PARAM_READWRITE));
1497   gimp_pdb_register_procedure (pdb, procedure);
1498   g_object_unref (procedure);
1499 
1500   /*
1501    * gimp-item-transform-2d
1502    */
1503   procedure = gimp_procedure_new (item_transform_2d_invoker);
1504   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1505                                "gimp-item-transform-2d");
1506   gimp_procedure_set_static_strings (procedure,
1507                                      "gimp-item-transform-2d",
1508                                      "Transform the specified item in 2d.",
1509                                      "This procedure transforms the specified item.\n"
1510                                      "\n"
1511                                      "The transformation is done by scaling by the x and y scale factors about the point (source_x, source_y), then rotating around the same point, then translating that point to the new position (dest_x, dest_y).\n"
1512                                      "\n"
1513                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then transformed as specified. The return value is the ID of the transformed floating selection.\n"
1514                                      "\n"
1515                                      "If there is no selection or the item is not a drawable, the entire item will be transformed according to the specified parameters. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be transformed the same way. The return value will be equal to the item ID supplied as input.\n"
1516                                      "\n"
1517                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1518                                      "Michael Natterer <mitch@gimp.org>",
1519                                      "Michael Natterer",
1520                                      "2010",
1521                                      NULL);
1522   gimp_procedure_add_argument (procedure,
1523                                gimp_param_spec_item_id ("item",
1524                                                         "item",
1525                                                         "The affected item",
1526                                                         pdb->gimp, FALSE,
1527                                                         GIMP_PARAM_READWRITE));
1528   gimp_procedure_add_argument (procedure,
1529                                g_param_spec_double ("source-x",
1530                                                     "source x",
1531                                                     "X coordinate of the transformation center",
1532                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1533                                                     GIMP_PARAM_READWRITE));
1534   gimp_procedure_add_argument (procedure,
1535                                g_param_spec_double ("source-y",
1536                                                     "source y",
1537                                                     "Y coordinate of the transformation center",
1538                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1539                                                     GIMP_PARAM_READWRITE));
1540   gimp_procedure_add_argument (procedure,
1541                                g_param_spec_double ("scale-x",
1542                                                     "scale x",
1543                                                     "Amount to scale in x direction",
1544                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1545                                                     GIMP_PARAM_READWRITE));
1546   gimp_procedure_add_argument (procedure,
1547                                g_param_spec_double ("scale-y",
1548                                                     "scale y",
1549                                                     "Amount to scale in y direction",
1550                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1551                                                     GIMP_PARAM_READWRITE));
1552   gimp_procedure_add_argument (procedure,
1553                                g_param_spec_double ("angle",
1554                                                     "angle",
1555                                                     "The angle of rotation (radians)",
1556                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1557                                                     GIMP_PARAM_READWRITE));
1558   gimp_procedure_add_argument (procedure,
1559                                g_param_spec_double ("dest-x",
1560                                                     "dest x",
1561                                                     "X coordinate of where the center goes",
1562                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1563                                                     GIMP_PARAM_READWRITE));
1564   gimp_procedure_add_argument (procedure,
1565                                g_param_spec_double ("dest-y",
1566                                                     "dest y",
1567                                                     "Y coordinate of where the center goes",
1568                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1569                                                     GIMP_PARAM_READWRITE));
1570   gimp_procedure_add_return_value (procedure,
1571                                    gimp_param_spec_item_id ("item",
1572                                                             "item",
1573                                                             "The transformed item",
1574                                                             pdb->gimp, FALSE,
1575                                                             GIMP_PARAM_READWRITE));
1576   gimp_pdb_register_procedure (pdb, procedure);
1577   g_object_unref (procedure);
1578 
1579   /*
1580    * gimp-item-transform-matrix
1581    */
1582   procedure = gimp_procedure_new (item_transform_matrix_invoker);
1583   gimp_object_set_static_name (GIMP_OBJECT (procedure),
1584                                "gimp-item-transform-matrix");
1585   gimp_procedure_set_static_strings (procedure,
1586                                      "gimp-item-transform-matrix",
1587                                      "Transform the specified item in 2d.",
1588                                      "This procedure transforms the specified item.\n"
1589                                      "\n"
1590                                      "The transformation is done by assembling a 3x3 matrix from the coefficients passed.\n"
1591                                      "\n"
1592                                      "If a selection exists and the item is a drawable, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then transformed as specified. The return value is the ID of the transformed floating selection.\n"
1593                                      "\n"
1594                                      "If there is no selection or the item is not a drawable, the entire item will be transformed according to the specified matrix. Additionally, if the item has its linked flag set to TRUE, all additional items contained in the image which have the linked flag set to TRUE will also be transformed the same way. The return value will be equal to the item ID supplied as input.\n"
1595                                      "\n"
1596                                      "This procedure is affected by the following context setters: 'gimp-context-set-interpolation', 'gimp-context-set-transform-direction', 'gimp-context-set-transform-resize'.",
1597                                      "Michael Natterer <mitch@gimp.org>",
1598                                      "Michael Natterer",
1599                                      "2010",
1600                                      NULL);
1601   gimp_procedure_add_argument (procedure,
1602                                gimp_param_spec_item_id ("item",
1603                                                         "item",
1604                                                         "The affected item",
1605                                                         pdb->gimp, FALSE,
1606                                                         GIMP_PARAM_READWRITE));
1607   gimp_procedure_add_argument (procedure,
1608                                g_param_spec_double ("coeff-0-0",
1609                                                     "coeff 0 0",
1610                                                     "coefficient (0,0) of the transformation matrix",
1611                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1612                                                     GIMP_PARAM_READWRITE));
1613   gimp_procedure_add_argument (procedure,
1614                                g_param_spec_double ("coeff-0-1",
1615                                                     "coeff 0 1",
1616                                                     "coefficient (0,1) of the transformation matrix",
1617                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1618                                                     GIMP_PARAM_READWRITE));
1619   gimp_procedure_add_argument (procedure,
1620                                g_param_spec_double ("coeff-0-2",
1621                                                     "coeff 0 2",
1622                                                     "coefficient (0,2) of the transformation matrix",
1623                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1624                                                     GIMP_PARAM_READWRITE));
1625   gimp_procedure_add_argument (procedure,
1626                                g_param_spec_double ("coeff-1-0",
1627                                                     "coeff 1 0",
1628                                                     "coefficient (1,0) of the transformation matrix",
1629                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1630                                                     GIMP_PARAM_READWRITE));
1631   gimp_procedure_add_argument (procedure,
1632                                g_param_spec_double ("coeff-1-1",
1633                                                     "coeff 1 1",
1634                                                     "coefficient (1,1) of the transformation matrix",
1635                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1636                                                     GIMP_PARAM_READWRITE));
1637   gimp_procedure_add_argument (procedure,
1638                                g_param_spec_double ("coeff-1-2",
1639                                                     "coeff 1 2",
1640                                                     "coefficient (1,2) of the transformation matrix",
1641                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1642                                                     GIMP_PARAM_READWRITE));
1643   gimp_procedure_add_argument (procedure,
1644                                g_param_spec_double ("coeff-2-0",
1645                                                     "coeff 2 0",
1646                                                     "coefficient (2,0) of the transformation matrix",
1647                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1648                                                     GIMP_PARAM_READWRITE));
1649   gimp_procedure_add_argument (procedure,
1650                                g_param_spec_double ("coeff-2-1",
1651                                                     "coeff 2 1",
1652                                                     "coefficient (2,1) of the transformation matrix",
1653                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1654                                                     GIMP_PARAM_READWRITE));
1655   gimp_procedure_add_argument (procedure,
1656                                g_param_spec_double ("coeff-2-2",
1657                                                     "coeff 2 2",
1658                                                     "coefficient (2,2) of the transformation matrix",
1659                                                     -G_MAXDOUBLE, G_MAXDOUBLE, 0,
1660                                                     GIMP_PARAM_READWRITE));
1661   gimp_procedure_add_return_value (procedure,
1662                                    gimp_param_spec_item_id ("item",
1663                                                             "item",
1664                                                             "The transformed item",
1665                                                             pdb->gimp, FALSE,
1666                                                             GIMP_PARAM_READWRITE));
1667   gimp_pdb_register_procedure (pdb, procedure);
1668   g_object_unref (procedure);
1669 }
1670