1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 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 #include "config.h"
19 
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpcolor/gimpcolor.h"
25 #include "libgimpwidgets/gimpwidgets.h"
26 
27 #include "actions-types.h"
28 
29 #include "config/gimpdialogconfig.h"
30 
31 #include "gegl/gimp-babl.h"
32 
33 #include "core/core-enums.h"
34 #include "core/gimp.h"
35 #include "core/gimpcontext.h"
36 #include "core/gimpimage.h"
37 #include "core/gimpimage-color-profile.h"
38 #include "core/gimpimage-convert-indexed.h"
39 #include "core/gimpimage-convert-precision.h"
40 #include "core/gimpimage-convert-type.h"
41 #include "core/gimpimage-crop.h"
42 #include "core/gimpimage-duplicate.h"
43 #include "core/gimpimage-flip.h"
44 #include "core/gimpimage-merge.h"
45 #include "core/gimpimage-resize.h"
46 #include "core/gimpimage-rotate.h"
47 #include "core/gimpimage-scale.h"
48 #include "core/gimpimage-undo.h"
49 #include "core/gimpitem.h"
50 #include "core/gimppickable.h"
51 #include "core/gimppickable-auto-shrink.h"
52 #include "core/gimpprogress.h"
53 
54 #include "widgets/gimpdialogfactory.h"
55 #include "widgets/gimpdock.h"
56 #include "widgets/gimphelp-ids.h"
57 #include "widgets/gimpwidgets-utils.h"
58 
59 #include "display/gimpdisplay.h"
60 #include "display/gimpdisplayshell.h"
61 
62 #include "dialogs/dialogs.h"
63 #include "dialogs/color-profile-dialog.h"
64 #include "dialogs/convert-indexed-dialog.h"
65 #include "dialogs/convert-precision-dialog.h"
66 #include "dialogs/grid-dialog.h"
67 #include "dialogs/image-merge-layers-dialog.h"
68 #include "dialogs/image-new-dialog.h"
69 #include "dialogs/image-properties-dialog.h"
70 #include "dialogs/image-scale-dialog.h"
71 #include "dialogs/print-size-dialog.h"
72 #include "dialogs/resize-dialog.h"
73 
74 #include "actions.h"
75 #include "image-commands.h"
76 
77 #include "gimp-intl.h"
78 
79 
80 /*  local function prototypes  */
81 
82 static void   image_convert_rgb_callback       (GtkWidget                *dialog,
83                                                 GimpImage                *image,
84                                                 GimpColorProfile         *new_profile,
85                                                 GFile                    *new_file,
86                                                 GimpColorRenderingIntent  intent,
87                                                 gboolean                  bpc,
88                                                 gpointer                  user_data);
89 
90 static void   image_convert_gray_callback      (GtkWidget                *dialog,
91                                                 GimpImage                *image,
92                                                 GimpColorProfile         *new_profile,
93                                                 GFile                    *new_file,
94                                                 GimpColorRenderingIntent  intent,
95                                                 gboolean                  bpc,
96                                                 gpointer                  user_data);
97 
98 static void   image_convert_indexed_callback   (GtkWidget              *dialog,
99                                                 GimpImage              *image,
100                                                 GimpConvertPaletteType  palette_type,
101                                                 gint                    max_colors,
102                                                 gboolean                remove_duplicates,
103                                                 GimpConvertDitherType   dither_type,
104                                                 gboolean                dither_alpha,
105                                                 gboolean                dither_text_layers,
106                                                 GimpPalette            *custom_palette,
107                                                 gpointer                user_data);
108 
109 static void   image_convert_precision_callback (GtkWidget              *dialog,
110                                                 GimpImage              *image,
111                                                 GimpPrecision           precision,
112                                                 GeglDitherMethod        layer_dither_method,
113                                                 GeglDitherMethod        text_layer_dither_method,
114                                                 GeglDitherMethod        mask_dither_method,
115                                                 gpointer                user_data);
116 
117 static void   image_profile_assign_callback    (GtkWidget                *dialog,
118                                                 GimpImage                *image,
119                                                 GimpColorProfile         *new_profile,
120                                                 GFile                    *new_file,
121                                                 GimpColorRenderingIntent  intent,
122                                                 gboolean                  bpc,
123                                                 gpointer                  user_data);
124 
125 static void   image_profile_convert_callback   (GtkWidget                *dialog,
126                                                 GimpImage                *image,
127                                                 GimpColorProfile         *new_profile,
128                                                 GFile                    *new_file,
129                                                 GimpColorRenderingIntent  intent,
130                                                 gboolean                  bpc,
131                                                 gpointer                  user_data);
132 
133 static void   image_resize_callback            (GtkWidget              *dialog,
134                                                 GimpViewable           *viewable,
135                                                 GimpContext            *context,
136                                                 gint                    width,
137                                                 gint                    height,
138                                                 GimpUnit                unit,
139                                                 gint                    offset_x,
140                                                 gint                    offset_y,
141                                                 GimpFillType            fill_type,
142                                                 GimpItemSet             layer_set,
143                                                 gboolean                resize_text_layers,
144                                                 gpointer                user_data);
145 
146 static void   image_print_size_callback        (GtkWidget              *dialog,
147                                                 GimpImage              *image,
148                                                 gdouble                 xresolution,
149                                                 gdouble                 yresolution,
150                                                 GimpUnit                resolution_unit,
151                                                 gpointer                user_data);
152 
153 static void   image_scale_callback             (GtkWidget              *dialog,
154                                                 GimpViewable           *viewable,
155                                                 gint                    width,
156                                                 gint                    height,
157                                                 GimpUnit                unit,
158                                                 GimpInterpolationType   interpolation,
159                                                 gdouble                 xresolution,
160                                                 gdouble                 yresolution,
161                                                 GimpUnit                resolution_unit,
162                                                 gpointer                user_data);
163 
164 static void   image_merge_layers_callback      (GtkWidget              *dialog,
165                                                 GimpImage              *image,
166                                                 GimpContext            *context,
167                                                 GimpMergeType           merge_type,
168                                                 gboolean                merge_active_group,
169                                                 gboolean                discard_invisible,
170                                                 gpointer                user_data);
171 
172 
173 /*  private variables  */
174 
175 static GimpUnit               image_resize_unit  = GIMP_UNIT_PIXEL;
176 static GimpUnit               image_scale_unit   = GIMP_UNIT_PIXEL;
177 static GimpInterpolationType  image_scale_interp = -1;
178 static GimpPalette           *image_convert_indexed_custom_palette = NULL;
179 
180 
181 /*  public functions  */
182 
183 void
image_new_cmd_callback(GimpAction * action,GVariant * value,gpointer data)184 image_new_cmd_callback (GimpAction *action,
185                         GVariant   *value,
186                         gpointer    data)
187 {
188   GtkWidget *widget;
189   GtkWidget *dialog;
190   return_if_no_widget (widget, data);
191 
192   dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
193                                            gtk_widget_get_screen (widget),
194                                            gimp_widget_get_monitor (widget),
195                                            NULL /*ui_manager*/,
196                                            "gimp-image-new-dialog", -1, FALSE);
197 
198   if (dialog)
199     {
200       GimpImage *image = action_data_get_image (data);
201 
202       image_new_dialog_set (dialog, image, NULL);
203 
204       gtk_window_present (GTK_WINDOW (dialog));
205     }
206 }
207 
208 void
image_duplicate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)209 image_duplicate_cmd_callback (GimpAction *action,
210                               GVariant   *value,
211                               gpointer    data)
212 {
213   GimpDisplay      *display;
214   GimpImage        *image;
215   GimpDisplayShell *shell;
216   GimpImage        *new_image;
217   return_if_no_display (display, data);
218 
219   image = gimp_display_get_image (display);
220   shell = gimp_display_get_shell (display);
221 
222   new_image = gimp_image_duplicate (image);
223 
224   gimp_create_display (new_image->gimp, new_image, shell->unit,
225                        gimp_zoom_model_get_factor (shell->zoom),
226                        G_OBJECT (gtk_widget_get_screen (GTK_WIDGET (shell))),
227                        gimp_widget_get_monitor (GTK_WIDGET (shell)));
228 
229   g_object_unref (new_image);
230 }
231 
232 void
image_convert_base_type_cmd_callback(GimpAction * action,GVariant * value,gpointer data)233 image_convert_base_type_cmd_callback (GimpAction *action,
234                                       GVariant   *value,
235                                       gpointer    data)
236 {
237   GimpImage         *image;
238   GimpDisplay       *display;
239   GtkWidget         *widget;
240   GimpDialogConfig  *config;
241   GtkWidget         *dialog;
242   GimpImageBaseType  base_type;
243   GError            *error = NULL;
244   return_if_no_image (image, data);
245   return_if_no_display (display, data);
246   return_if_no_widget (widget, data);
247 
248   base_type = (GimpImageBaseType) g_variant_get_int32 (value);
249 
250   if (base_type == gimp_image_get_base_type (image))
251     return;
252 
253 #define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog"
254 
255   dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_TYPE_DIALOG_KEY);
256 
257   if (dialog)
258     {
259       gtk_widget_destroy (dialog);
260       dialog = NULL;
261     }
262 
263   config = GIMP_DIALOG_CONFIG (image->gimp->config);
264 
265   switch (base_type)
266     {
267     case GIMP_RGB:
268     case GIMP_GRAY:
269       if (gimp_image_get_color_profile (image))
270         {
271           ColorProfileDialogType    dialog_type;
272           GimpColorProfileCallback  callback;
273           GimpColorProfile         *current_profile;
274           GimpColorProfile         *default_profile;
275           const Babl               *format;
276 
277           current_profile =
278             gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
279 
280           if (base_type == GIMP_RGB)
281             {
282               dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_RGB;
283               callback    = image_convert_rgb_callback;
284 
285               format = gimp_babl_format (GIMP_RGB,
286                                          gimp_image_get_precision (image),
287                                          TRUE);
288               default_profile = gimp_babl_format_get_color_profile (format);
289             }
290           else
291             {
292               dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_GRAY;
293               callback    = image_convert_gray_callback;
294 
295               format = gimp_babl_format (GIMP_GRAY,
296                                          gimp_image_get_precision (image),
297                                          TRUE);
298               default_profile = gimp_babl_format_get_color_profile (format);
299             }
300 
301           dialog = color_profile_dialog_new (dialog_type,
302                                              image,
303                                              action_data_get_context (data),
304                                              widget,
305                                              current_profile,
306                                              default_profile,
307                                              0, 0,
308                                              callback,
309                                              display);
310         }
311       else if (! gimp_image_convert_type (image, base_type, NULL, NULL, &error))
312         {
313           gimp_message_literal (image->gimp,
314                                 G_OBJECT (widget), GIMP_MESSAGE_WARNING,
315                                 error->message);
316           g_clear_error (&error);
317         }
318       break;
319 
320     case GIMP_INDEXED:
321       dialog = convert_indexed_dialog_new (image,
322                                            action_data_get_context (data),
323                                            widget,
324                                            config->image_convert_indexed_palette_type,
325                                            config->image_convert_indexed_max_colors,
326                                            config->image_convert_indexed_remove_duplicates,
327                                            config->image_convert_indexed_dither_type,
328                                            config->image_convert_indexed_dither_alpha,
329                                            config->image_convert_indexed_dither_text_layers,
330                                            image_convert_indexed_custom_palette,
331                                            image_convert_indexed_callback,
332                                            display);
333       break;
334     }
335 
336   if (dialog)
337     {
338       dialogs_attach_dialog (G_OBJECT (image),
339                              CONVERT_TYPE_DIALOG_KEY, dialog);
340       gtk_window_present (GTK_WINDOW (dialog));
341     }
342 
343   /*  always flush, also when only the indexed dialog was shown, so
344    *  the menu items get updated back to the current image type
345    */
346   gimp_image_flush (image);
347 }
348 
349 void
image_convert_precision_cmd_callback(GimpAction * action,GVariant * value,gpointer data)350 image_convert_precision_cmd_callback (GimpAction *action,
351                                       GVariant   *value,
352                                       gpointer    data)
353 {
354   GimpImage         *image;
355   GimpDisplay       *display;
356   GtkWidget         *widget;
357   GimpDialogConfig  *config;
358   GtkWidget         *dialog;
359   GimpComponentType  component_type;
360   return_if_no_image (image, data);
361   return_if_no_display (display, data);
362   return_if_no_widget (widget, data);
363 
364   component_type = (GimpComponentType) g_variant_get_int32 (value);
365 
366   if (component_type == gimp_image_get_component_type (image))
367     return;
368 
369 #define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog"
370 
371   dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_PRECISION_DIALOG_KEY);
372 
373   if (dialog)
374     {
375       gtk_widget_destroy (dialog);
376       dialog = NULL;
377     }
378 
379   config = GIMP_DIALOG_CONFIG (image->gimp->config);
380 
381   dialog = convert_precision_dialog_new (image,
382                                          action_data_get_context (data),
383                                          widget,
384                                          component_type,
385                                          config->image_convert_precision_layer_dither_method,
386                                          config->image_convert_precision_text_layer_dither_method,
387                                          config->image_convert_precision_channel_dither_method,
388                                          image_convert_precision_callback,
389                                          display);
390 
391   dialogs_attach_dialog (G_OBJECT (image),
392                          CONVERT_PRECISION_DIALOG_KEY, dialog);
393 
394   gtk_window_present (GTK_WINDOW (dialog));
395 
396   /*  see comment above  */
397   gimp_image_flush (image);
398 }
399 
400 void
image_convert_gamma_cmd_callback(GimpAction * action,GVariant * value,gpointer data)401 image_convert_gamma_cmd_callback (GimpAction *action,
402                                   GVariant   *value,
403                                   gpointer    data)
404 {
405   GimpImage     *image;
406   GimpDisplay   *display;
407   gboolean       linear;
408   GimpPrecision  precision;
409   return_if_no_image (image, data);
410   return_if_no_display (display, data);
411 
412   linear = (gboolean) g_variant_get_int32 (value);
413 
414   if (linear == gimp_babl_format_get_linear (gimp_image_get_layer_format (image,
415                                                                          FALSE)))
416     return;
417 
418   precision = gimp_babl_precision (gimp_image_get_component_type (image),
419                                    linear);
420 
421   gimp_image_convert_precision (image, precision,
422                                 GEGL_DITHER_NONE,
423                                 GEGL_DITHER_NONE,
424                                 GEGL_DITHER_NONE,
425                                 GIMP_PROGRESS (display));
426   gimp_image_flush (image);
427 }
428 
429 void
image_color_management_enabled_cmd_callback(GimpAction * action,GVariant * value,gpointer data)430 image_color_management_enabled_cmd_callback (GimpAction *action,
431                                              GVariant   *value,
432                                              gpointer    data)
433 {
434   GimpImage *image;
435   gboolean   enabled;
436   return_if_no_image (image, data);
437 
438   enabled = g_variant_get_boolean (value);
439 
440   if (enabled != gimp_image_get_is_color_managed (image))
441     {
442       gimp_image_set_is_color_managed (image, enabled, TRUE);
443       gimp_image_flush (image);
444     }
445 }
446 
447 void
image_color_profile_assign_cmd_callback(GimpAction * action,GVariant * value,gpointer data)448 image_color_profile_assign_cmd_callback (GimpAction *action,
449                                          GVariant   *value,
450                                          gpointer    data)
451 {
452   GimpImage   *image;
453   GimpDisplay *display;
454   GtkWidget   *widget;
455   GtkWidget   *dialog;
456   return_if_no_image (image, data);
457   return_if_no_display (display, data);
458   return_if_no_widget (widget, data);
459 
460 #define PROFILE_ASSIGN_DIALOG_KEY "gimp-profile-assign-dialog"
461 
462   dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_ASSIGN_DIALOG_KEY);
463 
464   if (! dialog)
465     {
466       GimpColorProfile *current_profile;
467       GimpColorProfile *default_profile;
468 
469       current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
470       default_profile = gimp_image_get_builtin_color_profile (image);
471 
472       dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_ASSIGN_PROFILE,
473                                          image,
474                                          action_data_get_context (data),
475                                          widget,
476                                          current_profile,
477                                          default_profile,
478                                          0, 0,
479                                          image_profile_assign_callback,
480                                          display);
481 
482       dialogs_attach_dialog (G_OBJECT (image),
483                              PROFILE_ASSIGN_DIALOG_KEY, dialog);
484     }
485 
486   gtk_window_present (GTK_WINDOW (dialog));
487 }
488 
489 void
image_color_profile_convert_cmd_callback(GimpAction * action,GVariant * value,gpointer data)490 image_color_profile_convert_cmd_callback (GimpAction *action,
491                                           GVariant   *value,
492                                           gpointer    data)
493 {
494   GimpImage   *image;
495   GimpDisplay *display;
496   GtkWidget   *widget;
497   GtkWidget   *dialog;
498   return_if_no_image (image, data);
499   return_if_no_display (display, data);
500   return_if_no_widget (widget, data);
501 
502 #define PROFILE_CONVERT_DIALOG_KEY "gimp-profile-convert-dialog"
503 
504   dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_CONVERT_DIALOG_KEY);
505 
506   if (! dialog)
507     {
508       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
509       GimpColorProfile *current_profile;
510       GimpColorProfile *default_profile;
511 
512       current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
513       default_profile = gimp_image_get_builtin_color_profile (image);
514 
515       dialog = color_profile_dialog_new (COLOR_PROFILE_DIALOG_CONVERT_TO_PROFILE,
516                                          image,
517                                          action_data_get_context (data),
518                                          widget,
519                                          current_profile,
520                                          default_profile,
521                                          config->image_convert_profile_intent,
522                                          config->image_convert_profile_bpc,
523                                          image_profile_convert_callback,
524                                          display);
525 
526       dialogs_attach_dialog (G_OBJECT (image),
527                              PROFILE_CONVERT_DIALOG_KEY, dialog);
528     }
529 
530   gtk_window_present (GTK_WINDOW (dialog));
531 }
532 
533 void
image_color_profile_discard_cmd_callback(GimpAction * action,GVariant * value,gpointer data)534 image_color_profile_discard_cmd_callback (GimpAction *action,
535                                           GVariant   *value,
536                                           gpointer    data)
537 {
538   GimpImage *image;
539   return_if_no_image (image, data);
540 
541   gimp_image_set_color_profile (image, NULL, NULL);
542   gimp_image_flush (image);
543 }
544 
545 static void
image_profile_save_dialog_response(GtkWidget * dialog,gint response_id,GimpImage * image)546 image_profile_save_dialog_response (GtkWidget *dialog,
547                                     gint       response_id,
548                                     GimpImage *image)
549 {
550   if (response_id == GTK_RESPONSE_ACCEPT)
551     {
552       GimpColorProfile *profile;
553       GFile            *file;
554       GError           *error = NULL;
555 
556       profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
557       file    = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
558 
559       if (! file)
560         return;
561 
562       if (! gimp_color_profile_save_to_file (profile, file, &error))
563         {
564           gimp_message (image->gimp, NULL,
565                         GIMP_MESSAGE_WARNING,
566                         _("Saving color profile failed: %s"),
567                         error->message);
568           g_clear_error (&error);
569           g_object_unref (file);
570           return;
571         }
572 
573       g_object_unref (file);
574     }
575 
576   gtk_widget_destroy (dialog);
577 }
578 
579 void
image_color_profile_save_cmd_callback(GimpAction * action,GVariant * value,gpointer data)580 image_color_profile_save_cmd_callback (GimpAction *action,
581                                        GVariant   *value,
582                                        gpointer    data)
583 {
584   GimpImage   *image;
585   GimpDisplay *display;
586   GtkWidget   *widget;
587   GtkWidget   *dialog;
588   return_if_no_image (image, data);
589   return_if_no_display (display, data);
590   return_if_no_widget (widget, data);
591 
592 #define PROFILE_SAVE_DIALOG_KEY "gimp-profile-save-dialog"
593 
594   dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY);
595 
596   if (! dialog)
597     {
598       GtkWindow        *toplevel;
599       GimpColorProfile *profile;
600       gchar            *basename;
601 
602       toplevel = GTK_WINDOW (gtk_widget_get_toplevel (widget));
603       profile  = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image));
604 
605       dialog =
606         gimp_color_profile_chooser_dialog_new (_("Save Color Profile"),
607                                                toplevel,
608                                                GTK_FILE_CHOOSER_ACTION_SAVE);
609 
610       gimp_color_profile_chooser_dialog_connect_path (dialog,
611                                                       G_OBJECT (image->gimp->config),
612                                                       "color-profile-path");
613 
614       basename = g_strconcat (gimp_color_profile_get_label (profile),
615                               ".icc", NULL);
616       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
617       g_free (basename);
618 
619       g_signal_connect (dialog, "response",
620                         G_CALLBACK (image_profile_save_dialog_response),
621                         image);
622 
623       dialogs_attach_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY, dialog);
624     }
625 
626   gtk_window_present (GTK_WINDOW (dialog));
627 }
628 
629 void
image_resize_cmd_callback(GimpAction * action,GVariant * value,gpointer data)630 image_resize_cmd_callback (GimpAction *action,
631                            GVariant   *value,
632                            gpointer    data)
633 {
634   GimpImage   *image;
635   GtkWidget   *widget;
636   GimpDisplay *display;
637   GtkWidget   *dialog;
638   return_if_no_image (image, data);
639   return_if_no_widget (widget, data);
640   return_if_no_display (display, data);
641 
642 #define RESIZE_DIALOG_KEY "gimp-resize-dialog"
643 
644   dialog = dialogs_get_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY);
645 
646   if (! dialog)
647     {
648       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
649 
650       if (image_resize_unit != GIMP_UNIT_PERCENT)
651         image_resize_unit = gimp_display_get_shell (display)->unit;
652 
653       dialog = resize_dialog_new (GIMP_VIEWABLE (image),
654                                   action_data_get_context (data),
655                                   _("Set Image Canvas Size"),
656                                   "gimp-image-resize",
657                                   widget,
658                                   gimp_standard_help_func,
659                                   GIMP_HELP_IMAGE_RESIZE,
660                                   image_resize_unit,
661                                   config->image_resize_fill_type,
662                                   config->image_resize_layer_set,
663                                   config->image_resize_resize_text_layers,
664                                   image_resize_callback,
665                                   display);
666 
667       dialogs_attach_dialog (G_OBJECT (image), RESIZE_DIALOG_KEY, dialog);
668     }
669 
670   gtk_window_present (GTK_WINDOW (dialog));
671 }
672 
673 void
image_resize_to_layers_cmd_callback(GimpAction * action,GVariant * value,gpointer data)674 image_resize_to_layers_cmd_callback (GimpAction *action,
675                                      GVariant   *value,
676                                      gpointer    data)
677 {
678   GimpDisplay  *display;
679   GimpImage    *image;
680   GimpProgress *progress;
681   return_if_no_display (display, data);
682 
683   image = gimp_display_get_image (display);
684 
685   progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
686                                   _("Resizing"));
687 
688   gimp_image_resize_to_layers (image,
689                                action_data_get_context (data),
690                                NULL, NULL, NULL, NULL, progress);
691 
692   if (progress)
693     gimp_progress_end (progress);
694 
695   gimp_image_flush (image);
696 }
697 
698 void
image_resize_to_selection_cmd_callback(GimpAction * action,GVariant * value,gpointer data)699 image_resize_to_selection_cmd_callback (GimpAction *action,
700                                         GVariant   *value,
701                                         gpointer    data)
702 {
703   GimpDisplay  *display;
704   GimpImage    *image;
705   GimpProgress *progress;
706   return_if_no_display (display, data);
707 
708   image = gimp_display_get_image (display);
709 
710   progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
711                                   _("Resizing"));
712 
713   gimp_image_resize_to_selection (image,
714                                   action_data_get_context (data),
715                                   progress);
716 
717   if (progress)
718     gimp_progress_end (progress);
719 
720   gimp_image_flush (image);
721 }
722 
723 void
image_print_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)724 image_print_size_cmd_callback (GimpAction *action,
725                                GVariant   *value,
726                                gpointer    data)
727 {
728   GimpDisplay *display;
729   GimpImage   *image;
730   GtkWidget   *widget;
731   GtkWidget   *dialog;
732   return_if_no_display (display, data);
733   return_if_no_widget (widget, data);
734 
735   image = gimp_display_get_image (display);
736 
737 #define PRINT_SIZE_DIALOG_KEY "gimp-print-size-dialog"
738 
739   dialog = dialogs_get_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY);
740 
741   if (! dialog)
742     {
743       dialog = print_size_dialog_new (image,
744                                       action_data_get_context (data),
745                                       _("Set Image Print Resolution"),
746                                       "gimp-image-print-size",
747                                       widget,
748                                       gimp_standard_help_func,
749                                       GIMP_HELP_IMAGE_PRINT_SIZE,
750                                       image_print_size_callback,
751                                       NULL);
752 
753       dialogs_attach_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY, dialog);
754     }
755 
756   gtk_window_present (GTK_WINDOW (dialog));
757 }
758 
759 void
image_scale_cmd_callback(GimpAction * action,GVariant * value,gpointer data)760 image_scale_cmd_callback (GimpAction *action,
761                           GVariant   *value,
762                           gpointer    data)
763 {
764   GimpDisplay *display;
765   GimpImage   *image;
766   GtkWidget   *widget;
767   GtkWidget   *dialog;
768   return_if_no_display (display, data);
769   return_if_no_widget (widget, data);
770 
771   image = gimp_display_get_image (display);
772 
773 #define SCALE_DIALOG_KEY "gimp-scale-dialog"
774 
775   dialog = dialogs_get_dialog (G_OBJECT (image), SCALE_DIALOG_KEY);
776 
777   if (! dialog)
778     {
779       if (image_scale_unit != GIMP_UNIT_PERCENT)
780         image_scale_unit = gimp_display_get_shell (display)->unit;
781 
782       if (image_scale_interp == -1)
783         image_scale_interp = display->gimp->config->interpolation_type;
784 
785       dialog = image_scale_dialog_new (image,
786                                        action_data_get_context (data),
787                                        widget,
788                                        image_scale_unit,
789                                        image_scale_interp,
790                                        image_scale_callback,
791                                        display);
792 
793       dialogs_attach_dialog (G_OBJECT (image), SCALE_DIALOG_KEY, dialog);
794     }
795 
796   gtk_window_present (GTK_WINDOW (dialog));
797 }
798 
799 void
image_flip_cmd_callback(GimpAction * action,GVariant * value,gpointer data)800 image_flip_cmd_callback (GimpAction *action,
801                          GVariant   *value,
802                          gpointer    data)
803 {
804   GimpDisplay         *display;
805   GimpImage           *image;
806   GimpProgress        *progress;
807   GimpOrientationType  orientation;
808   return_if_no_display (display, data);
809 
810   orientation = (GimpOrientationType) g_variant_get_int32 (value);
811 
812   image = gimp_display_get_image (display);
813 
814   progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
815                                   _("Flipping"));
816 
817   gimp_image_flip (image, action_data_get_context (data),
818                    orientation, progress);
819 
820   if (progress)
821     gimp_progress_end (progress);
822 
823   gimp_image_flush (image);
824 }
825 
826 void
image_rotate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)827 image_rotate_cmd_callback (GimpAction *action,
828                            GVariant   *value,
829                            gpointer    data)
830 {
831   GimpDisplay      *display;
832   GimpImage        *image;
833   GimpProgress     *progress;
834   GimpRotationType  rotation;
835   return_if_no_display (display, data);
836 
837   rotation = (GimpRotationType) g_variant_get_int32 (value);
838 
839   image = gimp_display_get_image (display);
840 
841   progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
842                                   _("Rotating"));
843 
844   gimp_image_rotate (image, action_data_get_context (data),
845                      rotation, progress);
846 
847   if (progress)
848     gimp_progress_end (progress);
849 
850   gimp_image_flush (image);
851 }
852 
853 void
image_crop_to_selection_cmd_callback(GimpAction * action,GVariant * value,gpointer data)854 image_crop_to_selection_cmd_callback (GimpAction *action,
855                                       GVariant   *value,
856                                       gpointer    data)
857 {
858   GimpImage *image;
859   GtkWidget *widget;
860   gint       x, y;
861   gint       width, height;
862   return_if_no_image (image, data);
863   return_if_no_widget (widget, data);
864 
865   if (! gimp_item_bounds (GIMP_ITEM (gimp_image_get_mask (image)),
866                           &x, &y, &width, &height))
867     {
868       gimp_message_literal (image->gimp,
869                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
870                             _("Cannot crop because the current selection "
871                               "is empty."));
872       return;
873     }
874 
875   gimp_image_crop (image,
876                    action_data_get_context (data), GIMP_FILL_TRANSPARENT,
877                    x, y, width, height, TRUE);
878   gimp_image_flush (image);
879 }
880 
881 void
image_crop_to_content_cmd_callback(GimpAction * action,GVariant * value,gpointer data)882 image_crop_to_content_cmd_callback (GimpAction *action,
883                                     GVariant   *value,
884                                     gpointer    data)
885 {
886   GimpImage *image;
887   GtkWidget *widget;
888   gint       x, y;
889   gint       width, height;
890   return_if_no_image (image, data);
891   return_if_no_widget (widget, data);
892 
893   switch (gimp_pickable_auto_shrink (GIMP_PICKABLE (image),
894                                      0, 0,
895                                      gimp_image_get_width  (image),
896                                      gimp_image_get_height (image),
897                                      &x, &y, &width, &height))
898     {
899     case GIMP_AUTO_SHRINK_SHRINK:
900       gimp_image_crop (image,
901                        action_data_get_context (data), GIMP_FILL_TRANSPARENT,
902                        x, y, width, height, TRUE);
903       gimp_image_flush (image);
904       break;
905 
906     case GIMP_AUTO_SHRINK_EMPTY:
907       gimp_message_literal (image->gimp,
908                             G_OBJECT (widget), GIMP_MESSAGE_INFO,
909                             _("Cannot crop because the image has no content."));
910       break;
911 
912     case GIMP_AUTO_SHRINK_UNSHRINKABLE:
913       gimp_message_literal (image->gimp,
914                             G_OBJECT (widget), GIMP_MESSAGE_INFO,
915                             _("Cannot crop because the image is already "
916                               "cropped to its content."));
917       break;
918     }
919 }
920 
921 void
image_merge_layers_cmd_callback(GimpAction * action,GVariant * value,gpointer data)922 image_merge_layers_cmd_callback (GimpAction *action,
923                                  GVariant   *value,
924                                  gpointer    data)
925 {
926   GtkWidget   *dialog;
927   GimpImage   *image;
928   GimpDisplay *display;
929   GtkWidget   *widget;
930   return_if_no_image (image, data);
931   return_if_no_display (display, data);
932   return_if_no_widget (widget, data);
933 
934 #define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog"
935 
936   dialog = dialogs_get_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY);
937 
938   if (! dialog)
939     {
940       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
941 
942       dialog = image_merge_layers_dialog_new (image,
943                                               action_data_get_context (data),
944                                               widget,
945                                               config->layer_merge_type,
946                                               config->layer_merge_active_group_only,
947                                               config->layer_merge_discard_invisible,
948                                               image_merge_layers_callback,
949                                               display);
950 
951       dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog);
952     }
953 
954   gtk_window_present (GTK_WINDOW (dialog));
955 }
956 
957 void
image_merge_layers_last_vals_cmd_callback(GimpAction * action,GVariant * value,gpointer data)958 image_merge_layers_last_vals_cmd_callback (GimpAction *action,
959                                            GVariant   *value,
960                                            gpointer    data)
961 {
962   GimpImage        *image;
963   GimpDisplay      *display;
964   GimpDialogConfig *config;
965   return_if_no_image (image, data);
966   return_if_no_display (display, data);
967 
968   config = GIMP_DIALOG_CONFIG (image->gimp->config);
969 
970   image_merge_layers_callback (NULL,
971                                image,
972                                action_data_get_context (data),
973                                config->layer_merge_type,
974                                config->layer_merge_active_group_only,
975                                config->layer_merge_discard_invisible,
976                                display);
977 }
978 
979 void
image_flatten_image_cmd_callback(GimpAction * action,GVariant * value,gpointer data)980 image_flatten_image_cmd_callback (GimpAction *action,
981                                   GVariant   *value,
982                                   gpointer    data)
983 {
984   GimpImage   *image;
985   GimpDisplay *display;
986   GtkWidget   *widget;
987   GError      *error = NULL;
988   return_if_no_image (image, data);
989   return_if_no_display (display, data);
990   return_if_no_widget (widget, data);
991 
992   if (! gimp_image_flatten (image, action_data_get_context (data),
993                             GIMP_PROGRESS (display), &error))
994     {
995       gimp_message_literal (image->gimp,
996                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
997                             error->message);
998       g_clear_error (&error);
999       return;
1000     }
1001 
1002   gimp_image_flush (image);
1003 }
1004 
1005 void
image_configure_grid_cmd_callback(GimpAction * action,GVariant * value,gpointer data)1006 image_configure_grid_cmd_callback (GimpAction *action,
1007                                    GVariant   *value,
1008                                    gpointer    data)
1009 {
1010   GimpDisplay *display;
1011   GimpImage   *image;
1012   GtkWidget   *dialog;
1013   return_if_no_display (display, data);
1014 
1015   image = gimp_display_get_image (display);
1016 
1017 #define GRID_DIALOG_KEY "gimp-grid-dialog"
1018 
1019   dialog = dialogs_get_dialog (G_OBJECT (image), GRID_DIALOG_KEY);
1020 
1021   if (! dialog)
1022     {
1023       GimpDisplayShell *shell = gimp_display_get_shell (display);
1024 
1025       dialog = grid_dialog_new (image,
1026                                 action_data_get_context (data),
1027                                 gtk_widget_get_toplevel (GTK_WIDGET (shell)));
1028 
1029       dialogs_attach_dialog (G_OBJECT (image), GRID_DIALOG_KEY, dialog);
1030     }
1031 
1032   gtk_window_present (GTK_WINDOW (dialog));
1033 }
1034 
1035 void
image_properties_cmd_callback(GimpAction * action,GVariant * value,gpointer data)1036 image_properties_cmd_callback (GimpAction *action,
1037                                GVariant   *value,
1038                                gpointer    data)
1039 {
1040   GimpDisplay *display;
1041   GimpImage   *image;
1042   GtkWidget   *dialog;
1043   return_if_no_display (display, data);
1044 
1045   image = gimp_display_get_image (display);
1046 
1047 #define PROPERTIES_DIALOG_KEY "gimp-image-properties-dialog"
1048 
1049   dialog = dialogs_get_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY);
1050 
1051   if (! dialog)
1052     {
1053       GimpDisplayShell *shell = gimp_display_get_shell (display);
1054 
1055       dialog = image_properties_dialog_new (image,
1056                                             action_data_get_context (data),
1057                                             gtk_widget_get_toplevel (GTK_WIDGET (shell)));
1058 
1059       dialogs_attach_dialog (G_OBJECT (image), PROPERTIES_DIALOG_KEY, dialog);
1060     }
1061 
1062   gtk_window_present (GTK_WINDOW (dialog));
1063 }
1064 
1065 
1066 /*  private functions  */
1067 
1068 static void
image_convert_rgb_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1069 image_convert_rgb_callback (GtkWidget                *dialog,
1070                             GimpImage                *image,
1071                             GimpColorProfile         *new_profile,
1072                             GFile                    *new_file,
1073                             GimpColorRenderingIntent  intent,
1074                             gboolean                  bpc,
1075                             gpointer                  user_data)
1076 {
1077   GimpProgress *progress = user_data;
1078   GError       *error    = NULL;
1079 
1080   progress = gimp_progress_start (progress, FALSE,
1081                                   _("Converting to RGB (%s)"),
1082                                   gimp_color_profile_get_label (new_profile));
1083 
1084   if (! gimp_image_convert_type (image, GIMP_RGB, new_profile,
1085                                  progress, &error))
1086     {
1087       gimp_message (image->gimp, G_OBJECT (dialog),
1088                     GIMP_MESSAGE_ERROR,
1089                     "%s", error->message);
1090       g_clear_error (&error);
1091 
1092       if (progress)
1093         gimp_progress_end (progress);
1094 
1095       return;
1096     }
1097 
1098   if (progress)
1099     gimp_progress_end (progress);
1100 
1101   gimp_image_flush (image);
1102 
1103  gtk_widget_destroy (dialog);
1104 }
1105 
1106 static void
image_convert_gray_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1107 image_convert_gray_callback (GtkWidget                *dialog,
1108                              GimpImage                *image,
1109                              GimpColorProfile         *new_profile,
1110                              GFile                    *new_file,
1111                              GimpColorRenderingIntent  intent,
1112                              gboolean                  bpc,
1113                              gpointer                  user_data)
1114 {
1115   GimpProgress *progress = user_data;
1116   GError       *error    = NULL;
1117 
1118   progress = gimp_progress_start (progress, FALSE,
1119                                   _("Converting to grayscale (%s)"),
1120                                   gimp_color_profile_get_label (new_profile));
1121 
1122   if (! gimp_image_convert_type (image, GIMP_GRAY, new_profile,
1123                                  progress, &error))
1124     {
1125       gimp_message (image->gimp, G_OBJECT (dialog),
1126                     GIMP_MESSAGE_ERROR,
1127                     "%s", error->message);
1128       g_clear_error (&error);
1129 
1130       if (progress)
1131         gimp_progress_end (progress);
1132 
1133       return;
1134     }
1135 
1136   if (progress)
1137     gimp_progress_end (progress);
1138 
1139   gimp_image_flush (image);
1140 
1141   gtk_widget_destroy (dialog);
1142 }
1143 
1144 static void
image_convert_indexed_callback(GtkWidget * dialog,GimpImage * image,GimpConvertPaletteType palette_type,gint max_colors,gboolean remove_duplicates,GimpConvertDitherType dither_type,gboolean dither_alpha,gboolean dither_text_layers,GimpPalette * custom_palette,gpointer user_data)1145 image_convert_indexed_callback (GtkWidget              *dialog,
1146                                 GimpImage              *image,
1147                                 GimpConvertPaletteType  palette_type,
1148                                 gint                    max_colors,
1149                                 gboolean                remove_duplicates,
1150                                 GimpConvertDitherType   dither_type,
1151                                 gboolean                dither_alpha,
1152                                 gboolean                dither_text_layers,
1153                                 GimpPalette            *custom_palette,
1154                                 gpointer                user_data)
1155 {
1156   GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
1157   GimpDisplay      *display = user_data;
1158   GimpProgress     *progress;
1159   GError           *error   = NULL;
1160 
1161   g_object_set (config,
1162                 "image-convert-indexed-palette-type",       palette_type,
1163                 "image-convert-indexed-max-colors",         max_colors,
1164                 "image-convert-indexed-remove-duplicates",  remove_duplicates,
1165                 "image-convert-indexed-dither-type",        dither_type,
1166                 "image-convert-indexed-dither-alpha",       dither_alpha,
1167                 "image-convert-indexed-dither-text-layers", dither_text_layers,
1168                 NULL);
1169 
1170   if (image_convert_indexed_custom_palette)
1171     g_object_remove_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
1172                                   (gpointer) &image_convert_indexed_custom_palette);
1173 
1174   image_convert_indexed_custom_palette = custom_palette;
1175 
1176   if (image_convert_indexed_custom_palette)
1177     g_object_add_weak_pointer (G_OBJECT (image_convert_indexed_custom_palette),
1178                                (gpointer) &image_convert_indexed_custom_palette);
1179 
1180   progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
1181                                   _("Converting to indexed colors"));
1182 
1183   if (! gimp_image_convert_indexed (image,
1184                                     config->image_convert_indexed_palette_type,
1185                                     config->image_convert_indexed_max_colors,
1186                                     config->image_convert_indexed_remove_duplicates,
1187                                     config->image_convert_indexed_dither_type,
1188                                     config->image_convert_indexed_dither_alpha,
1189                                     config->image_convert_indexed_dither_text_layers,
1190                                     image_convert_indexed_custom_palette,
1191                                     progress,
1192                                     &error))
1193     {
1194       gimp_message_literal (image->gimp, G_OBJECT (display),
1195                             GIMP_MESSAGE_WARNING, error->message);
1196       g_clear_error (&error);
1197 
1198       if (progress)
1199         gimp_progress_end (progress);
1200 
1201       return;
1202     }
1203 
1204   if (progress)
1205     gimp_progress_end (progress);
1206 
1207   gimp_image_flush (image);
1208 
1209   gtk_widget_destroy (dialog);
1210 }
1211 
1212 static void
image_convert_precision_callback(GtkWidget * dialog,GimpImage * image,GimpPrecision precision,GeglDitherMethod layer_dither_method,GeglDitherMethod text_layer_dither_method,GeglDitherMethod channel_dither_method,gpointer user_data)1213 image_convert_precision_callback (GtkWidget        *dialog,
1214                                   GimpImage        *image,
1215                                   GimpPrecision     precision,
1216                                   GeglDitherMethod  layer_dither_method,
1217                                   GeglDitherMethod  text_layer_dither_method,
1218                                   GeglDitherMethod  channel_dither_method,
1219                                   gpointer          user_data)
1220 {
1221   GimpDialogConfig *config   = GIMP_DIALOG_CONFIG (image->gimp->config);
1222   GimpProgress     *progress = user_data;
1223   const gchar      *enum_desc;
1224   const Babl       *old_format;
1225   const Babl       *new_format;
1226   gint              old_bits;
1227   gint              new_bits;
1228 
1229   g_object_set (config,
1230                 "image-convert-precision-layer-dither-method",
1231                 layer_dither_method,
1232                 "image-convert-precision-text-layer-dither-method",
1233                 text_layer_dither_method,
1234                 "image-convert-precision-channel-dither-method",
1235                 channel_dither_method,
1236                 NULL);
1237 
1238   /*  we do the same dither method checks here *and* in the dialog,
1239    *  because the dialog leaves the passed dither methods untouched if
1240    *  dithering is disabled and passes the original values to the
1241    *  callback, in order not to change the values saved in
1242    *  GimpDialogConfig.
1243    */
1244 
1245   /* random formats with the right precision */
1246   old_format = gimp_image_get_layer_format (image, FALSE);
1247   new_format = gimp_babl_format (GIMP_RGB, precision, FALSE);
1248 
1249   old_bits = (babl_format_get_bytes_per_pixel (old_format) * 8 /
1250               babl_format_get_n_components (old_format));
1251   new_bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
1252               babl_format_get_n_components (new_format));
1253 
1254   if (new_bits >= old_bits ||
1255       new_bits >  CONVERT_PRECISION_DIALOG_MAX_DITHER_BITS)
1256     {
1257       /*  don't dither if we are converting to a higher bit depth,
1258        *  or to more than MAX_DITHER_BITS.
1259        */
1260       layer_dither_method      = GEGL_DITHER_NONE;
1261       text_layer_dither_method = GEGL_DITHER_NONE;
1262       channel_dither_method    = GEGL_DITHER_NONE;
1263     }
1264 
1265   gimp_enum_get_value (GIMP_TYPE_PRECISION, precision,
1266                        NULL, NULL, &enum_desc, NULL);
1267 
1268   progress = gimp_progress_start (progress, FALSE,
1269                                   _("Converting image to %s"),
1270                                   enum_desc);
1271 
1272   gimp_image_convert_precision (image,
1273                                 precision,
1274                                 layer_dither_method,
1275                                 text_layer_dither_method,
1276                                 channel_dither_method,
1277                                 progress);
1278 
1279   if (progress)
1280     gimp_progress_end (progress);
1281 
1282   gimp_image_flush (image);
1283 
1284   gtk_widget_destroy (dialog);
1285 }
1286 
1287 static void
image_profile_assign_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1288 image_profile_assign_callback (GtkWidget                *dialog,
1289                                GimpImage                *image,
1290                                GimpColorProfile         *new_profile,
1291                                GFile                    *new_file,
1292                                GimpColorRenderingIntent  intent,
1293                                gboolean                  bpc,
1294                                gpointer                  user_data)
1295 {
1296   GError *error = NULL;
1297 
1298   gimp_image_undo_group_start (image,
1299                                GIMP_UNDO_GROUP_PARASITE_ATTACH,
1300                                _("Assign color profile"));
1301 
1302   if (! gimp_image_set_color_profile (image, new_profile, &error))
1303     {
1304       gimp_message (image->gimp, G_OBJECT (dialog),
1305                     GIMP_MESSAGE_ERROR,
1306                     "%s", error->message);
1307       g_clear_error (&error);
1308 
1309       gimp_image_undo_group_end (image);
1310       gimp_image_undo (image);
1311 
1312       return;
1313     }
1314 
1315   gimp_image_set_is_color_managed (image, TRUE, TRUE);
1316 
1317   /*  omg...  */
1318   gimp_image_parasite_detach (image, "icc-profile-name", TRUE);
1319 
1320   gimp_image_undo_group_end (image);
1321 
1322   gimp_image_flush (image);
1323 
1324   gtk_widget_destroy (dialog);
1325 }
1326 
1327 static void
image_profile_convert_callback(GtkWidget * dialog,GimpImage * image,GimpColorProfile * new_profile,GFile * new_file,GimpColorRenderingIntent intent,gboolean bpc,gpointer user_data)1328 image_profile_convert_callback (GtkWidget                *dialog,
1329                                 GimpImage                *image,
1330                                 GimpColorProfile         *new_profile,
1331                                 GFile                    *new_file,
1332                                 GimpColorRenderingIntent  intent,
1333                                 gboolean                  bpc,
1334                                 gpointer                  user_data)
1335 {
1336   GimpDialogConfig *config   = GIMP_DIALOG_CONFIG (image->gimp->config);
1337   GimpProgress     *progress = user_data;
1338   GError           *error    = NULL;
1339 
1340   g_object_set (config,
1341                 "image-convert-profile-intent",                   intent,
1342                 "image-convert-profile-black-point-compensation", bpc,
1343                 NULL);
1344 
1345   progress = gimp_progress_start (progress, FALSE,
1346                                   _("Converting to '%s'"),
1347                                   gimp_color_profile_get_label (new_profile));
1348 
1349   if (! gimp_image_convert_color_profile (image, new_profile,
1350                                           config->image_convert_profile_intent,
1351                                           config->image_convert_profile_bpc,
1352                                           progress, &error))
1353     {
1354       gimp_message (image->gimp, G_OBJECT (dialog),
1355                     GIMP_MESSAGE_ERROR,
1356                     "%s", error->message);
1357       g_clear_error (&error);
1358 
1359       if (progress)
1360         gimp_progress_end (progress);
1361 
1362       return;
1363     }
1364 
1365   if (progress)
1366     gimp_progress_end (progress);
1367 
1368   gimp_image_flush (image);
1369 
1370   gtk_widget_destroy (dialog);
1371 }
1372 
1373 static void
image_resize_callback(GtkWidget * dialog,GimpViewable * viewable,GimpContext * context,gint width,gint height,GimpUnit unit,gint offset_x,gint offset_y,GimpFillType fill_type,GimpItemSet layer_set,gboolean resize_text_layers,gpointer user_data)1374 image_resize_callback (GtkWidget    *dialog,
1375                        GimpViewable *viewable,
1376                        GimpContext  *context,
1377                        gint          width,
1378                        gint          height,
1379                        GimpUnit      unit,
1380                        gint          offset_x,
1381                        gint          offset_y,
1382                        GimpFillType  fill_type,
1383                        GimpItemSet   layer_set,
1384                        gboolean      resize_text_layers,
1385                        gpointer      user_data)
1386 {
1387   GimpDisplay *display = user_data;
1388 
1389   image_resize_unit = unit;
1390 
1391   if (width > 0 && height > 0)
1392     {
1393       GimpImage        *image  = GIMP_IMAGE (viewable);
1394       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
1395       GimpProgress     *progress;
1396 
1397       g_object_set (config,
1398                     "image-resize-fill-type",          fill_type,
1399                     "image-resize-layer-set",          layer_set,
1400                     "image-resize-resize-text-layers", resize_text_layers,
1401                     NULL);
1402 
1403       gtk_widget_destroy (dialog);
1404 
1405       if (width  == gimp_image_get_width  (image) &&
1406           height == gimp_image_get_height (image))
1407         return;
1408 
1409       progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE,
1410                                       _("Resizing"));
1411 
1412       gimp_image_resize_with_layers (image,
1413                                      context, fill_type,
1414                                      width, height, offset_x, offset_y,
1415                                      layer_set,
1416                                      resize_text_layers,
1417                                      progress);
1418 
1419       if (progress)
1420         gimp_progress_end (progress);
1421 
1422       gimp_image_flush (image);
1423     }
1424   else
1425     {
1426       g_warning ("Resize Error: "
1427                  "Both width and height must be greater than zero.");
1428     }
1429 }
1430 
1431 static void
image_print_size_callback(GtkWidget * dialog,GimpImage * image,gdouble xresolution,gdouble yresolution,GimpUnit resolution_unit,gpointer data)1432 image_print_size_callback (GtkWidget *dialog,
1433                            GimpImage *image,
1434                            gdouble    xresolution,
1435                            gdouble    yresolution,
1436                            GimpUnit   resolution_unit,
1437                            gpointer   data)
1438 {
1439   gdouble xres;
1440   gdouble yres;
1441 
1442   gtk_widget_destroy (dialog);
1443 
1444   gimp_image_get_resolution (image, &xres, &yres);
1445 
1446   if (xresolution     == xres &&
1447       yresolution     == yres &&
1448       resolution_unit == gimp_image_get_unit (image))
1449     return;
1450 
1451   gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
1452                                _("Change Print Size"));
1453 
1454   gimp_image_set_resolution (image, xresolution, yresolution);
1455   gimp_image_set_unit (image, resolution_unit);
1456 
1457   gimp_image_undo_group_end (image);
1458 
1459   gimp_image_flush (image);
1460 }
1461 
1462 static void
image_scale_callback(GtkWidget * dialog,GimpViewable * viewable,gint width,gint height,GimpUnit unit,GimpInterpolationType interpolation,gdouble xresolution,gdouble yresolution,GimpUnit resolution_unit,gpointer user_data)1463 image_scale_callback (GtkWidget              *dialog,
1464                       GimpViewable           *viewable,
1465                       gint                    width,
1466                       gint                    height,
1467                       GimpUnit                unit,
1468                       GimpInterpolationType   interpolation,
1469                       gdouble                 xresolution,
1470                       gdouble                 yresolution,
1471                       GimpUnit                resolution_unit,
1472                       gpointer                user_data)
1473 {
1474   GimpProgress *progress = user_data;
1475   GimpImage    *image    = GIMP_IMAGE (viewable);
1476   gdouble       xres;
1477   gdouble       yres;
1478 
1479   image_scale_unit   = unit;
1480   image_scale_interp = interpolation;
1481 
1482   gimp_image_get_resolution (image, &xres, &yres);
1483 
1484   if (width > 0 && height > 0)
1485     {
1486       gtk_widget_destroy (dialog);
1487 
1488       if (width           == gimp_image_get_width  (image) &&
1489           height          == gimp_image_get_height (image) &&
1490           xresolution     == xres                          &&
1491           yresolution     == yres                          &&
1492           resolution_unit == gimp_image_get_unit (image))
1493         return;
1494 
1495       gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_SCALE,
1496                                    _("Scale Image"));
1497 
1498       gimp_image_set_resolution (image, xresolution, yresolution);
1499       gimp_image_set_unit (image, resolution_unit);
1500 
1501       if (width  != gimp_image_get_width  (image) ||
1502           height != gimp_image_get_height (image))
1503         {
1504           progress = gimp_progress_start (progress, FALSE,
1505                                           _("Scaling"));
1506 
1507           gimp_image_scale (image, width, height, interpolation, progress);
1508 
1509           if (progress)
1510             gimp_progress_end (progress);
1511         }
1512 
1513       gimp_image_undo_group_end (image);
1514 
1515       gimp_image_flush (image);
1516     }
1517   else
1518     {
1519       g_warning ("Scale Error: "
1520                  "Both width and height must be greater than zero.");
1521     }
1522 }
1523 
1524 static void
image_merge_layers_callback(GtkWidget * dialog,GimpImage * image,GimpContext * context,GimpMergeType merge_type,gboolean merge_active_group,gboolean discard_invisible,gpointer user_data)1525 image_merge_layers_callback (GtkWidget     *dialog,
1526                              GimpImage     *image,
1527                              GimpContext   *context,
1528                              GimpMergeType  merge_type,
1529                              gboolean       merge_active_group,
1530                              gboolean       discard_invisible,
1531                              gpointer       user_data)
1532 {
1533   GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
1534   GimpDisplay      *display = user_data;
1535 
1536   g_object_set (config,
1537                 "layer-merge-type",              merge_type,
1538                 "layer-merge-active-group-only", merge_active_group,
1539                 "layer-merge-discard-invisible", discard_invisible,
1540                 NULL);
1541 
1542   gimp_image_merge_visible_layers (image,
1543                                    context,
1544                                    config->layer_merge_type,
1545                                    config->layer_merge_active_group_only,
1546                                    config->layer_merge_discard_invisible,
1547                                    GIMP_PROGRESS (display));
1548 
1549   gimp_image_flush (image);
1550 
1551   gtk_widget_destroy (dialog);
1552 }
1553