diff -Nru gimp-2.10.8+zorin2/acinclude.m4 gimp-2.10.14+om/acinclude.m4 --- gimp-2.10.8+zorin2/acinclude.m4 2018-04-17 09:24:32.000000000 +0000 +++ gimp-2.10.14+om/acinclude.m4 2019-04-07 11:38:14.000000000 +0000 @@ -4,6 +4,5 @@ m4_include([m4macros/ax_gcc_func_attribute.m4]) m4_include([m4macros/ax_prog_cc_for_build.m4]) m4_include([m4macros/ax_prog_perl_version.m4]) -m4_include([m4macros/binreloc.m4]) m4_include([m4macros/detectcflags.m4]) m4_include([m4macros/pythondev.m4]) diff -Nru gimp-2.10.8+zorin2/aclocal.m4 gimp-2.10.14+om/aclocal.m4 --- gimp-2.10.8+zorin2/aclocal.m4 2018-11-08 16:06:21.000000000 +0000 +++ gimp-2.10.14+om/aclocal.m4 2019-10-27 17:12:52.000000000 +0000 @@ -1498,18 +1498,11 @@ AC_SUBST([am__untar]) ]) # _AM_PROG_TAR -m4_include([m4macros/gtk-doc.m4]) -m4_include([m4macros/intltool.m4]) -m4_include([m4macros/libtool.m4]) -m4_include([m4macros/ltoptions.m4]) -m4_include([m4macros/ltsugar.m4]) -m4_include([m4macros/ltversion.m4]) -m4_include([m4macros/lt~obsolete.m4]) # Configure paths for GLIB # Owen Taylor 1997-2001 # Increment this whenever this file is changed. -#serial 1 +#serial 3 dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject, @@ -1519,10 +1512,16 @@ [dnl dnl Get the cflags and libraries from pkg-config dnl + +dnl We can't use PKG_PREREQ because that needs 0.29. +m4_ifndef([PKG_PROG_PKG_CONFIG], + [pkg.m4 version 0.28 or later is required]) + AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], , enable_glibtest=yes) - pkg_config_args=glib-2.0 + min_glib_version=ifelse([$1], [], [2.0.0], [$1]) + pkg_config_args="glib-2.0 >= $min_glib_version" for module in . $4 do case "$module" in @@ -1553,7 +1552,15 @@ PKG_CONFIG=no fi - min_glib_version=ifelse([$1], ,2.0.0,$1) + dnl For GLIB_CFLAGS and GLIB_LIBS + PKG_CHECK_MODULES([GLIB], [$pkg_config_args], [:], [:]) + + dnl For the tools + PKG_CHECK_VAR([GLIB_GENMARSHAL], [glib-2.0], [glib_genmarshal]) + PKG_CHECK_VAR([GOBJECT_QUERY], [glib-2.0], [gobject_query]) + PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums]) + PKG_CHECK_VAR([GLIB_COMPILE_RESOURCES], [gio-2.0], [glib_compile_resources]) + AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) if test x$PKG_CONFIG != xno ; then @@ -1571,13 +1578,6 @@ fi if test x"$no_glib" = x ; then - GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` - GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` - GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` - GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0` - - GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` - GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ @@ -1711,12 +1711,6 @@ GLIB_COMPILE_RESOURCES="" ifelse([$3], , :, [$3]) fi - AC_SUBST(GLIB_CFLAGS) - AC_SUBST(GLIB_LIBS) - AC_SUBST(GLIB_GENMARSHAL) - AC_SUBST(GOBJECT_QUERY) - AC_SUBST(GLIB_MKENUMS) - AC_SUBST(GLIB_COMPILE_RESOURCES) rm -f conf.glibtest ]) @@ -2210,6 +2204,10 @@ # Configure paths for GTK+ # Owen Taylor 1997-2001 +# Version number used by aclocal, see `info automake Serials`. +# Increment on every change. +#serial 1 + dnl AM_PATH_GTK_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) dnl Test for GTK+, and define GTK_CFLAGS and GTK_LIBS, if gthread is specified in MODULES, dnl pass to pkg-config @@ -2393,4 +2391,11 @@ rm -f conf.gtktest ]) +m4_include([m4macros/gtk-doc.m4]) +m4_include([m4macros/intltool.m4]) +m4_include([m4macros/libtool.m4]) +m4_include([m4macros/ltoptions.m4]) +m4_include([m4macros/ltsugar.m4]) +m4_include([m4macros/ltversion.m4]) +m4_include([m4macros/lt~obsolete.m4]) m4_include([acinclude.m4]) diff -Nru gimp-2.10.8+zorin2/app/actions/actions.c gimp-2.10.14+om/app/actions/actions.c --- gimp-2.10.8+zorin2/app/actions/actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/actions.c 2019-04-07 11:38:14.000000000 +0000 @@ -280,172 +280,196 @@ Gimp * action_data_get_gimp (gpointer data) { - GimpContext *context = NULL; + Gimp *result = NULL; + static gboolean recursion = FALSE; - if (! data) + if (! data || recursion) return NULL; - if (GIMP_IS_DISPLAY (data)) - return ((GimpDisplay *) data)->gimp; - else if (GIMP_IS_IMAGE_WINDOW (data)) + recursion = TRUE; + + if (GIMP_IS_GIMP (data)) + result = data; + + if (! result) { - GimpDisplayShell *shell = gimp_image_window_get_active_shell (data); - return shell ? shell->display->gimp : NULL; + GimpDisplay *display = action_data_get_display (data); + + if (display) + result = display->gimp; + } + + if (! result) + { + GimpContext *context = action_data_get_context (data); + + if (context) + result = context->gimp; } - else if (GIMP_IS_GIMP (data)) - return data; - else if (GIMP_IS_DOCK (data)) - context = gimp_dock_get_context (((GimpDock *) data)); - else if (GIMP_IS_DOCK_WINDOW (data)) - context = gimp_dock_window_get_context (((GimpDockWindow *) data)); - else if (GIMP_IS_CONTAINER_VIEW (data)) - context = gimp_container_view_get_context ((GimpContainerView *) data); - else if (GIMP_IS_CONTAINER_EDITOR (data)) - context = gimp_container_view_get_context (((GimpContainerEditor *) data)->view); - else if (GIMP_IS_IMAGE_EDITOR (data)) - context = ((GimpImageEditor *) data)->context; - else if (GIMP_IS_NAVIGATION_EDITOR (data)) - context = ((GimpNavigationEditor *) data)->context; - if (context) - return context->gimp; + recursion = FALSE; - return NULL; + return result; } GimpContext * action_data_get_context (gpointer data) { - if (! data) + GimpContext *result = NULL; + static gboolean recursion = FALSE; + + if (! data || recursion) return NULL; - if (GIMP_IS_DISPLAY (data)) - return gimp_get_user_context (((GimpDisplay *) data)->gimp); - else if (GIMP_IS_IMAGE_WINDOW (data)) - { - GimpDisplayShell *shell = gimp_image_window_get_active_shell (data); - return shell ? gimp_get_user_context (shell->display->gimp) : NULL; - } - else if (GIMP_IS_GIMP (data)) - return gimp_get_user_context (data); - else if (GIMP_IS_DOCK (data)) - return gimp_dock_get_context ((GimpDock *) data); + recursion = TRUE; + + if (GIMP_IS_DOCK (data)) + result = gimp_dock_get_context ((GimpDock *) data); else if (GIMP_IS_DOCK_WINDOW (data)) - return gimp_dock_window_get_context (((GimpDockWindow *) data)); + result = gimp_dock_window_get_context (((GimpDockWindow *) data)); else if (GIMP_IS_CONTAINER_VIEW (data)) - return gimp_container_view_get_context ((GimpContainerView *) data); + result = gimp_container_view_get_context ((GimpContainerView *) data); else if (GIMP_IS_CONTAINER_EDITOR (data)) - return gimp_container_view_get_context (((GimpContainerEditor *) data)->view); + result = gimp_container_view_get_context (((GimpContainerEditor *) data)->view); else if (GIMP_IS_IMAGE_EDITOR (data)) - return ((GimpImageEditor *) data)->context; + result = ((GimpImageEditor *) data)->context; else if (GIMP_IS_NAVIGATION_EDITOR (data)) - return ((GimpNavigationEditor *) data)->context; + result = ((GimpNavigationEditor *) data)->context; + + if (! result) + { + Gimp *gimp = action_data_get_gimp (data); - return NULL; + if (gimp) + result = gimp_get_user_context (gimp); + } + + recursion = FALSE; + + return result; } GimpImage * action_data_get_image (gpointer data) { - GimpContext *context = NULL; - GimpDisplay *display = NULL; + GimpImage *result = NULL; + static gboolean recursion = FALSE; - if (! data) + if (! data || recursion) return NULL; - if (GIMP_IS_DISPLAY (data)) - display = (GimpDisplay *) data; - else if (GIMP_IS_IMAGE_WINDOW (data)) + recursion = TRUE; + + if (GIMP_IS_ITEM_TREE_VIEW (data)) + result = gimp_item_tree_view_get_image ((GimpItemTreeView *) data); + else if (GIMP_IS_IMAGE_EDITOR (data)) + result = ((GimpImageEditor *) data)->image; + + if (! result) { - GimpDisplayShell *shell = gimp_image_window_get_active_shell (data); - display = shell ? shell->display : NULL; + GimpDisplay *display = action_data_get_display (data); + + if (display) + result = gimp_display_get_image (display); } - else if (GIMP_IS_GIMP (data)) - context = gimp_get_user_context (data); - else if (GIMP_IS_DOCK (data)) - context = gimp_dock_get_context ((GimpDock *) data); - else if (GIMP_IS_DOCK_WINDOW (data)) - context = gimp_dock_window_get_context (((GimpDockWindow *) data)); - else if (GIMP_IS_ITEM_TREE_VIEW (data)) - return gimp_item_tree_view_get_image ((GimpItemTreeView *) data); - else if (GIMP_IS_IMAGE_EDITOR (data)) - return ((GimpImageEditor *) data)->image; - else if (GIMP_IS_NAVIGATION_EDITOR (data)) - context = ((GimpNavigationEditor *) data)->context; - if (context) - return gimp_context_get_image (context); - else if (display) - return gimp_display_get_image (display); + if (! result) + { + GimpContext *context = action_data_get_context (data); + + if (context) + result = gimp_context_get_image (context); + } + + recursion = FALSE; - return NULL; + return result; } GimpDisplay * action_data_get_display (gpointer data) { - GimpContext *context = NULL; + GimpDisplay *result = NULL; + static gboolean recursion = FALSE; - if (! data) + if (! data || recursion) return NULL; + recursion = TRUE; + if (GIMP_IS_DISPLAY (data)) - return data; + result = data; else if (GIMP_IS_IMAGE_WINDOW (data)) { GimpDisplayShell *shell = gimp_image_window_get_active_shell (data); - return shell ? shell->display : NULL; + result = shell ? shell->display : NULL; } - else if (GIMP_IS_GIMP (data)) - context = gimp_get_user_context (data); - else if (GIMP_IS_DOCK (data)) - context = gimp_dock_get_context ((GimpDock *) data); - else if (GIMP_IS_DOCK_WINDOW (data)) - context = gimp_dock_window_get_context (((GimpDockWindow *) data)); - else if (GIMP_IS_IMAGE_EDITOR (data)) - context = ((GimpImageEditor *) data)->context; - else if (GIMP_IS_NAVIGATION_EDITOR (data)) - context = ((GimpNavigationEditor *) data)->context; - if (context) - return gimp_context_get_display (context); + if (! result) + { + GimpContext *context = action_data_get_context (data); - return NULL; + if (context) + result = gimp_context_get_display (context); + } + + recursion = FALSE; + + return result; } GimpDisplayShell * action_data_get_shell (gpointer data) { - GimpDisplay *display = NULL; - GimpDisplayShell *shell = NULL; + GimpDisplayShell *result = NULL; + static gboolean recursion = FALSE; + + if (! data || recursion) + return NULL; - display = action_data_get_display (data); + recursion = TRUE; + + if (! result) + { + GimpDisplay *display = action_data_get_display (data); + + if (display) + result = gimp_display_get_shell (display); + } - if (display) - shell = gimp_display_get_shell (display); + recursion = FALSE; - return shell; + return result; } GtkWidget * action_data_get_widget (gpointer data) { - GimpDisplay *display = NULL; + GtkWidget *result = NULL; + static gboolean recursion = FALSE; - if (! data) + if (! data || recursion) return NULL; - if (GIMP_IS_DISPLAY (data)) - display = data; - else if (GIMP_IS_GIMP (data)) - display = gimp_context_get_display (gimp_get_user_context (data)); - else if (GTK_IS_WIDGET (data)) - return data; + recursion = TRUE; + + if (GTK_IS_WIDGET (data)) + result = data; + + if (! result) + { + GimpDisplay *display = action_data_get_display (data); + + if (display) + result = GTK_WIDGET (gimp_display_get_shell (display)); + } + + if (! result) + result = dialogs_get_toolbox (); - if (display) - return GTK_WIDGET (gimp_display_get_shell (display)); + recursion = FALSE; - return dialogs_get_toolbox (); + return result; } gint diff -Nru gimp-2.10.8+zorin2/app/actions/brush-editor-actions.c gimp-2.10.14+om/app/actions/brush-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/brush-editor-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/brush-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -48,7 +48,7 @@ { { "brush-editor-edit-active", GIMP_ICON_LINKED, NC_("brush-editor-action", "Edit Active Brush"), NULL, NULL, - G_CALLBACK (data_editor_edit_active_cmd_callback), + data_editor_edit_active_cmd_callback, FALSE, GIMP_HELP_BRUSH_EDITOR_EDIT_ACTIVE } }; diff -Nru gimp-2.10.8+zorin2/app/actions/brushes-actions.c gimp-2.10.14+om/app/actions/brushes-actions.c --- gimp-2.10.8+zorin2/app/actions/brushes-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/brushes-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,43 +46,43 @@ { "brushes-open-as-image", GIMP_ICON_DOCUMENT_OPEN, NC_("brushes-action", "_Open Brush as Image"), NULL, NC_("brushes-action", "Open brush as image"), - G_CALLBACK (data_open_as_image_cmd_callback), + data_open_as_image_cmd_callback, GIMP_HELP_BRUSH_OPEN_AS_IMAGE }, { "brushes-new", GIMP_ICON_DOCUMENT_NEW, NC_("brushes-action", "_New Brush"), NULL, NC_("brushes-action", "Create a new brush"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_BRUSH_NEW }, { "brushes-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("brushes-action", "D_uplicate Brush"), NULL, NC_("brushes-action", "Duplicate this brush"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_BRUSH_DUPLICATE }, { "brushes-copy-location", GIMP_ICON_EDIT_COPY, NC_("brushes-action", "Copy Brush _Location"), NULL, NC_("brushes-action", "Copy brush file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_BRUSH_COPY_LOCATION }, { "brushes-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("brushes-action", "Show in _File Manager"), NULL, NC_("brushes-action", "Show brush file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_BRUSH_SHOW_IN_FILE_MANAGER }, { "brushes-delete", GIMP_ICON_EDIT_DELETE, NC_("brushes-action", "_Delete Brush"), NULL, NC_("brushes-action", "Delete this brush"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_BRUSH_DELETE }, { "brushes-refresh", GIMP_ICON_VIEW_REFRESH, NC_("brushes-action", "_Refresh Brushes"), NULL, NC_("brushes-action", "Refresh brushes"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_BRUSH_REFRESH } }; @@ -106,7 +106,7 @@ gimp_action_group_add_string_actions (group, "brushes-action", brushes_edit_actions, G_N_ELEMENTS (brushes_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/buffers-actions.c gimp-2.10.14+om/app/actions/buffers-actions.c --- gimp-2.10.8+zorin2/app/actions/buffers-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/buffers-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -45,13 +45,13 @@ { "buffers-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW, NC_("buffers-action", "Paste Buffer as _New Image"), NULL, NC_("buffers-action", "Paste the selected buffer as a new image"), - G_CALLBACK (buffers_paste_as_new_image_cmd_callback), + buffers_paste_as_new_image_cmd_callback, GIMP_HELP_BUFFER_PASTE_AS_NEW_IMAGE }, { "buffers-delete", GIMP_ICON_EDIT_DELETE, NC_("buffers-action", "_Delete Buffer"), NULL, NC_("buffers-action", "Delete the selected buffer"), - G_CALLBACK (buffers_delete_cmd_callback), + buffers_delete_cmd_callback, GIMP_HELP_BUFFER_DELETE } }; @@ -107,7 +107,7 @@ gimp_action_group_add_enum_actions (group, "buffers-action", buffers_paste_actions, G_N_ELEMENTS (buffers_paste_actions), - G_CALLBACK (buffers_paste_cmd_callback)); + buffers_paste_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/buffers-commands.c gimp-2.10.14+om/app/actions/buffers-commands.c --- gimp-2.10.8+zorin2/app/actions/buffers-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/buffers-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,15 +46,15 @@ /* public functions */ void -buffers_paste_cmd_callback (GtkAction *action, - gint value, - gpointer data) +buffers_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; GimpContext *context; GimpBuffer *buffer; - GimpPasteType paste_type = (GimpPasteType) value; + GimpPasteType paste_type = (GimpPasteType) g_variant_get_int32 (value); container = gimp_container_view_get_container (editor->view); context = gimp_container_view_get_context (editor->view); @@ -74,8 +74,10 @@ { GimpDisplayShell *shell = gimp_display_get_shell (display); - gimp_display_shell_untransform_viewport (shell, - &x, &y, &width, &height); + gimp_display_shell_untransform_viewport ( + shell, + ! gimp_display_shell_get_infinite_canvas (shell), + &x, &y, &width, &height); image = gimp_display_get_image (display); } @@ -96,8 +98,9 @@ } void -buffers_paste_as_new_image_cmd_callback (GtkAction *action, - gpointer data) +buffers_paste_as_new_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -125,8 +128,9 @@ } void -buffers_delete_cmd_callback (GtkAction *action, - gpointer data) +buffers_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); diff -Nru gimp-2.10.8+zorin2/app/actions/buffers-commands.h gimp-2.10.14+om/app/actions/buffers-commands.h --- gimp-2.10.8+zorin2/app/actions/buffers-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/buffers-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,13 +19,15 @@ #define __BUFFERS_COMMANDS_H__ -void buffers_paste_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void buffers_paste_as_new_image_cmd_callback (GtkAction *action, - gpointer data); -void buffers_delete_cmd_callback (GtkAction *action, - gpointer data); +void buffers_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void buffers_paste_as_new_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void buffers_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __BUFFERS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/channels-actions.c gimp-2.10.14+om/app/actions/channels-actions.c --- gimp-2.10.8+zorin2/app/actions/channels-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/channels-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -52,58 +52,58 @@ { "channels-edit-attributes", GIMP_ICON_EDIT, NC_("channels-action", "_Edit Channel Attributes..."), NULL, NC_("channels-action", "Edit the channel's name, color and opacity"), - G_CALLBACK (channels_edit_attributes_cmd_callback), + channels_edit_attributes_cmd_callback, GIMP_HELP_CHANNEL_EDIT }, { "channels-new", GIMP_ICON_DOCUMENT_NEW, NC_("channels-action", "_New Channel..."), NULL, NC_("channels-action", "Create a new channel"), - G_CALLBACK (channels_new_cmd_callback), + channels_new_cmd_callback, GIMP_HELP_CHANNEL_NEW }, { "channels-new-last-values", GIMP_ICON_DOCUMENT_NEW, NC_("channels-action", "_New Channel"), NULL, NC_("channels-action", "Create a new channel with last used values"), - G_CALLBACK (channels_new_last_vals_cmd_callback), + channels_new_last_vals_cmd_callback, GIMP_HELP_CHANNEL_NEW }, { "channels-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("channels-action", "D_uplicate Channel"), NULL, NC_("channels-action", "Create a duplicate of this channel and add it to the image"), - G_CALLBACK (channels_duplicate_cmd_callback), + channels_duplicate_cmd_callback, GIMP_HELP_CHANNEL_DUPLICATE }, { "channels-delete", GIMP_ICON_EDIT_DELETE, NC_("channels-action", "_Delete Channel"), NULL, NC_("channels-action", "Delete this channel"), - G_CALLBACK (channels_delete_cmd_callback), + channels_delete_cmd_callback, GIMP_HELP_CHANNEL_DELETE }, { "channels-raise", GIMP_ICON_GO_UP, NC_("channels-action", "_Raise Channel"), NULL, NC_("channels-action", "Raise this channel one step in the channel stack"), - G_CALLBACK (channels_raise_cmd_callback), + channels_raise_cmd_callback, GIMP_HELP_CHANNEL_RAISE }, { "channels-raise-to-top", GIMP_ICON_GO_TOP, NC_("channels-action", "Raise Channel to _Top"), NULL, NC_("channels-action", "Raise this channel to the top of the channel stack"), - G_CALLBACK (channels_raise_to_top_cmd_callback), + channels_raise_to_top_cmd_callback, GIMP_HELP_CHANNEL_RAISE_TO_TOP }, { "channels-lower", GIMP_ICON_GO_DOWN, NC_("channels-action", "_Lower Channel"), NULL, NC_("channels-action", "Lower this channel one step in the channel stack"), - G_CALLBACK (channels_lower_cmd_callback), + channels_lower_cmd_callback, GIMP_HELP_CHANNEL_LOWER }, { "channels-lower-to-bottom", GIMP_ICON_GO_BOTTOM, NC_("channels-action", "Lower Channel to _Bottom"), NULL, NC_("channels-action", "Lower this channel to the bottom of the channel stack"), - G_CALLBACK (channels_lower_to_bottom_cmd_callback), + channels_lower_to_bottom_cmd_callback, GIMP_HELP_CHANNEL_LOWER_TO_BOTTOM } }; @@ -111,25 +111,25 @@ { { "channels-visible", GIMP_ICON_VISIBLE, NC_("channels-action", "Toggle Channel _Visibility"), NULL, NULL, - G_CALLBACK (channels_visible_cmd_callback), + channels_visible_cmd_callback, FALSE, GIMP_HELP_CHANNEL_VISIBLE }, { "channels-linked", GIMP_ICON_LINKED, NC_("channels-action", "Toggle Channel _Linked State"), NULL, NULL, - G_CALLBACK (channels_linked_cmd_callback), + channels_linked_cmd_callback, FALSE, GIMP_HELP_CHANNEL_LINKED }, { "channels-lock-content", NULL /* GIMP_ICON_LOCK */, NC_("channels-action", "L_ock Pixels of Channel"), NULL, NULL, - G_CALLBACK (channels_lock_content_cmd_callback), + channels_lock_content_cmd_callback, FALSE, GIMP_HELP_CHANNEL_LOCK_PIXELS }, { "channels-lock-position", GIMP_ICON_TOOL_MOVE, NC_("channels-action", "L_ock Position of Channel"), NULL, NULL, - G_CALLBACK (channels_lock_position_cmd_callback), + channels_lock_position_cmd_callback, FALSE, GIMP_HELP_CHANNEL_LOCK_POSITION } }; @@ -260,17 +260,17 @@ gimp_action_group_add_enum_actions (group, "channels-action", channels_color_tag_actions, G_N_ELEMENTS (channels_color_tag_actions), - G_CALLBACK (channels_color_tag_cmd_callback)); + channels_color_tag_cmd_callback); gimp_action_group_add_enum_actions (group, "channels-action", channels_to_selection_actions, G_N_ELEMENTS (channels_to_selection_actions), - G_CALLBACK (channels_to_selection_cmd_callback)); + channels_to_selection_cmd_callback); gimp_action_group_add_enum_actions (group, "channels-action", channels_select_actions, G_N_ELEMENTS (channels_select_actions), - G_CALLBACK (channels_select_cmd_callback)); + channels_select_cmd_callback); items_actions_setup (group, "channels"); } diff -Nru gimp-2.10.8+zorin2/app/actions/channels-commands.c gimp-2.10.14+om/app/actions/channels-commands.c --- gimp-2.10.8+zorin2/app/actions/channels-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/channels-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -54,6 +54,9 @@ #include "gimp-intl.h" +#define RGBA_EPSILON 1e-6 + + /* local function prototypes */ static void channels_new_callback (GtkWidget *dialog, @@ -87,8 +90,9 @@ /* public functions */ void -channels_edit_attributes_cmd_callback (GtkAction *action, - gpointer data) +channels_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -133,8 +137,9 @@ } void -channels_new_cmd_callback (GtkAction *action, - gpointer data) +channels_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -178,8 +183,9 @@ } void -channels_new_last_vals_cmd_callback (GtkAction *action, - gpointer data) +channels_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -204,8 +210,9 @@ } void -channels_raise_cmd_callback (GtkAction *action, - gpointer data) +channels_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -216,8 +223,9 @@ } void -channels_raise_to_top_cmd_callback (GtkAction *action, - gpointer data) +channels_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -228,8 +236,9 @@ } void -channels_lower_cmd_callback (GtkAction *action, - gpointer data) +channels_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -240,8 +249,9 @@ } void -channels_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data) +channels_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -252,8 +262,9 @@ } void -channels_duplicate_cmd_callback (GtkAction *action, - gpointer data) +channels_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *new_channel; @@ -304,8 +315,9 @@ } void -channels_delete_cmd_callback (GtkAction *action, - gpointer data) +channels_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -316,14 +328,14 @@ } void -channels_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data) +channels_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpChannelOps op; GimpImage *image; - op = (GimpChannelOps) value; + op = (GimpChannelOps) g_variant_get_int32 (value); if (GIMP_IS_COMPONENT_EDITOR (data)) { @@ -348,76 +360,85 @@ } void -channels_visible_cmd_callback (GtkAction *action, - gpointer data) +channels_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; return_if_no_channel (image, channel, data); - items_visible_cmd_callback (action, image, GIMP_ITEM (channel)); + items_visible_cmd_callback (action, value, image, GIMP_ITEM (channel)); } void -channels_linked_cmd_callback (GtkAction *action, - gpointer data) +channels_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; return_if_no_channel (image, channel, data); - items_linked_cmd_callback (action, image, GIMP_ITEM (channel)); + items_linked_cmd_callback (action, value, image, GIMP_ITEM (channel)); } void -channels_lock_content_cmd_callback (GtkAction *action, - gpointer data) +channels_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; return_if_no_channel (image, channel, data); - items_lock_content_cmd_callback (action, image, GIMP_ITEM (channel)); + items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (channel)); } void -channels_lock_position_cmd_callback (GtkAction *action, - gpointer data) +channels_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; return_if_no_channel (image, channel, data); - items_lock_position_cmd_callback (action, image, GIMP_ITEM (channel)); + items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (channel)); } void -channels_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data) +channels_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpChannel *channel; + GimpImage *image; + GimpChannel *channel; + GimpColorTag color_tag; return_if_no_channel (image, channel, data); + color_tag = (GimpColorTag) g_variant_get_int32 (value); + items_color_tag_cmd_callback (action, image, GIMP_ITEM (channel), - (GimpColorTag) value); + color_tag); } void -channels_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +channels_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpChannel *channel; - GimpChannel *channel2; - GimpContainer *container; + GimpImage *image; + GimpChannel *channel; + GimpChannel *channel2; + GimpContainer *container; + GimpActionSelectType type; return_if_no_channel (image, channel, data); + type = (GimpActionSelectType) g_variant_get_int32 (value); + container = gimp_image_get_channels (image); - channel2 = (GimpChannel *) action_select_object ((GimpActionSelectType) value, - container, + channel2 = (GimpChannel *) action_select_object (type, container, (GimpObject *) channel); if (channel2 && channel2 != channel) @@ -504,12 +525,12 @@ { GimpItem *item = GIMP_ITEM (channel); - if (strcmp (channel_name, gimp_object_get_name (channel)) || - gimp_rgba_distance (channel_color, &channel->color) > 0.0001 || - channel_visible != gimp_item_get_visible (item) || - channel_linked != gimp_item_get_linked (item) || - channel_color_tag != gimp_item_get_color_tag (item) || - channel_lock_content != gimp_item_get_lock_content (item) || + if (strcmp (channel_name, gimp_object_get_name (channel)) || + gimp_rgba_distance (channel_color, &channel->color) > RGBA_EPSILON || + channel_visible != gimp_item_get_visible (item) || + channel_linked != gimp_item_get_linked (item) || + channel_color_tag != gimp_item_get_color_tag (item) || + channel_lock_content != gimp_item_get_lock_content (item) || channel_lock_position != gimp_item_get_lock_position (item)) { gimp_image_undo_group_start (image, @@ -519,7 +540,7 @@ if (strcmp (channel_name, gimp_object_get_name (channel))) gimp_item_rename (GIMP_ITEM (channel), channel_name, NULL); - if (gimp_rgba_distance (channel_color, &channel->color) > 0.0001) + if (gimp_rgba_distance (channel_color, &channel->color) > RGBA_EPSILON) gimp_channel_set_color (channel, channel_color, TRUE); if (channel_visible != gimp_item_get_visible (item)) diff -Nru gimp-2.10.8+zorin2/app/actions/channels-commands.h gimp-2.10.14+om/app/actions/channels-commands.h --- gimp-2.10.8+zorin2/app/actions/channels-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/channels-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,46 +19,59 @@ #define __CHANNELS_COMMANDS_H__ -void channels_edit_attributes_cmd_callback (GtkAction *action, - gpointer data); -void channels_new_cmd_callback (GtkAction *action, - gpointer data); -void channels_new_last_vals_cmd_callback (GtkAction *action, - gpointer data); - -void channels_raise_cmd_callback (GtkAction *action, - gpointer data); -void channels_raise_to_top_cmd_callback (GtkAction *action, - gpointer data); -void channels_lower_cmd_callback (GtkAction *action, - gpointer data); -void channels_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data); - -void channels_duplicate_cmd_callback (GtkAction *action, - gpointer data); -void channels_delete_cmd_callback (GtkAction *action, - gpointer data); -void channels_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void channels_visible_cmd_callback (GtkAction *action, - gpointer data); -void channels_linked_cmd_callback (GtkAction *action, - gpointer data); -void channels_lock_content_cmd_callback (GtkAction *action, - gpointer data); -void channels_lock_position_cmd_callback (GtkAction *action, - gpointer data); - -void channels_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void channels_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void channels_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void channels_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void channels_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void channels_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void channels_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void channels_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void channels_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __CHANNELS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/colormap-actions.c gimp-2.10.14+om/app/actions/colormap-actions.c --- gimp-2.10.8+zorin2/app/actions/colormap-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/colormap-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -48,7 +48,7 @@ { "colormap-edit-color", GIMP_ICON_EDIT, NC_("colormap-action", "_Edit Color..."), NULL, NC_("colormap-action", "Edit this color"), - G_CALLBACK (colormap_edit_color_cmd_callback), + colormap_edit_color_cmd_callback, GIMP_HELP_INDEXED_PALETTE_EDIT } }; @@ -104,12 +104,12 @@ gimp_action_group_add_enum_actions (group, "colormap-action", colormap_add_color_actions, G_N_ELEMENTS (colormap_add_color_actions), - G_CALLBACK (colormap_add_color_cmd_callback)); + colormap_add_color_cmd_callback); gimp_action_group_add_enum_actions (group, "colormap-action", colormap_to_selection_actions, G_N_ELEMENTS (colormap_to_selection_actions), - G_CALLBACK (colormap_to_selection_cmd_callback)); + colormap_to_selection_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/colormap-commands.c gimp-2.10.14+om/app/actions/colormap-commands.c --- gimp-2.10.8+zorin2/app/actions/colormap-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/colormap-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,8 +36,9 @@ /* public functions */ void -colormap_edit_color_cmd_callback (GtkAction *action, - gpointer data) +colormap_edit_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpColormapEditor *editor = GIMP_COLORMAP_EDITOR (data); @@ -45,20 +46,23 @@ } void -colormap_add_color_cmd_callback (GtkAction *action, - gint value, - gpointer data) +colormap_add_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpImage *image; + gboolean background; return_if_no_context (context, data); return_if_no_image (image, data); + background = (gboolean) g_variant_get_int32 (value); + if (gimp_image_get_colormap_size (image) < 256) { GimpRGB color; - if (value) + if (background) gimp_context_get_background (context, &color); else gimp_context_get_foreground (context, &color); @@ -69,9 +73,9 @@ } void -colormap_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data) +colormap_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpColormapEditor *editor; GimpImage *image; @@ -80,7 +84,7 @@ editor = GIMP_COLORMAP_EDITOR (data); - op = (GimpChannelOps) value; + op = (GimpChannelOps) g_variant_get_int32 (value); gimp_channel_select_by_index (gimp_image_get_mask (image), gimp_image_get_active_drawable (image), diff -Nru gimp-2.10.8+zorin2/app/actions/colormap-commands.h gimp-2.10.14+om/app/actions/colormap-commands.h --- gimp-2.10.8+zorin2/app/actions/colormap-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/colormap-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,14 +19,15 @@ #define __COLORMAP_COMMANDS_H__ -void colormap_edit_color_cmd_callback (GtkAction *action, - gpointer data); -void colormap_add_color_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void colormap_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void colormap_edit_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void colormap_add_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void colormap_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __COLORMAP_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/context-actions.c gimp-2.10.14+om/app/actions/context-actions.c --- gimp-2.10.8+zorin2/app/actions/context-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/context-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -81,13 +81,13 @@ NC_("context-action", "_Default Colors"), "D", NC_("context-action", "Set foreground color to black, background color to white"), - G_CALLBACK (context_colors_default_cmd_callback), + context_colors_default_cmd_callback, GIMP_HELP_TOOLBOX_DEFAULT_COLORS }, { "context-colors-swap", GIMP_ICON_COLORS_SWAP, NC_("context-action", "S_wap Colors"), "X", NC_("context-action", "Exchange foreground and background colors"), - G_CALLBACK (context_colors_swap_cmd_callback), + context_colors_swap_cmd_callback, GIMP_HELP_TOOLBOX_SWAP_COLORS } }; @@ -1095,148 +1095,148 @@ context_actions, G_N_ELEMENTS (context_actions)); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_palette_foreground_actions, G_N_ELEMENTS (context_palette_foreground_actions), - G_CALLBACK (context_palette_foreground_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_palette_foreground_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_palette_background_actions, G_N_ELEMENTS (context_palette_background_actions), - G_CALLBACK (context_palette_background_cmd_callback)); + context_palette_background_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_colormap_foreground_actions, G_N_ELEMENTS (context_colormap_foreground_actions), - G_CALLBACK (context_colormap_foreground_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_colormap_foreground_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_colormap_background_actions, G_N_ELEMENTS (context_colormap_background_actions), - G_CALLBACK (context_colormap_background_cmd_callback)); + context_colormap_background_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_swatch_foreground_actions, G_N_ELEMENTS (context_swatch_foreground_actions), - G_CALLBACK (context_swatch_foreground_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_swatch_foreground_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_swatch_background_actions, G_N_ELEMENTS (context_swatch_background_actions), - G_CALLBACK (context_swatch_background_cmd_callback)); + context_swatch_background_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_red_actions, G_N_ELEMENTS (context_foreground_red_actions), - G_CALLBACK (context_foreground_red_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_foreground_red_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_green_actions, G_N_ELEMENTS (context_foreground_green_actions), - G_CALLBACK (context_foreground_green_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_foreground_green_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_blue_actions, G_N_ELEMENTS (context_foreground_blue_actions), - G_CALLBACK (context_foreground_blue_cmd_callback)); + context_foreground_blue_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_hue_actions, G_N_ELEMENTS (context_foreground_hue_actions), - G_CALLBACK (context_foreground_hue_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_foreground_hue_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_saturation_actions, G_N_ELEMENTS (context_foreground_saturation_actions), - G_CALLBACK (context_foreground_saturation_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_foreground_saturation_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_foreground_value_actions, G_N_ELEMENTS (context_foreground_value_actions), - G_CALLBACK (context_foreground_value_cmd_callback)); + context_foreground_value_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_background_red_actions, G_N_ELEMENTS (context_background_red_actions), - G_CALLBACK (context_background_red_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_background_red_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_background_green_actions, G_N_ELEMENTS (context_background_green_actions), - G_CALLBACK (context_background_green_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_background_green_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_background_blue_actions, G_N_ELEMENTS (context_background_blue_actions), - G_CALLBACK (context_background_blue_cmd_callback)); + context_background_blue_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_background_hue_actions, G_N_ELEMENTS (context_background_hue_actions), - G_CALLBACK (context_background_hue_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_background_hue_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_background_saturation_actions, G_N_ELEMENTS (context_background_saturation_actions), - G_CALLBACK (context_background_saturation_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_background_saturation_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_background_value_actions, G_N_ELEMENTS (context_background_value_actions), - G_CALLBACK (context_background_value_cmd_callback)); + context_background_value_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_opacity_actions, G_N_ELEMENTS (context_opacity_actions), - G_CALLBACK (context_opacity_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_opacity_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_paint_mode_actions, G_N_ELEMENTS (context_paint_mode_actions), - G_CALLBACK (context_paint_mode_cmd_callback)); + context_paint_mode_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_tool_select_actions, G_N_ELEMENTS (context_tool_select_actions), - G_CALLBACK (context_tool_select_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_tool_select_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_select_actions, G_N_ELEMENTS (context_brush_select_actions), - G_CALLBACK (context_brush_select_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_select_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_pattern_select_actions, G_N_ELEMENTS (context_pattern_select_actions), - G_CALLBACK (context_pattern_select_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_pattern_select_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_palette_select_actions, G_N_ELEMENTS (context_palette_select_actions), - G_CALLBACK (context_palette_select_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_palette_select_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_gradient_select_actions, G_N_ELEMENTS (context_gradient_select_actions), - G_CALLBACK (context_gradient_select_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_gradient_select_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_font_select_actions, G_N_ELEMENTS (context_font_select_actions), - G_CALLBACK (context_font_select_cmd_callback)); + context_font_select_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "context-action", context_brush_spacing_actions, G_N_ELEMENTS (context_brush_spacing_actions), - G_CALLBACK (context_brush_spacing_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_spacing_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_shape_actions, G_N_ELEMENTS (context_brush_shape_actions), - G_CALLBACK (context_brush_shape_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_shape_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_radius_actions, G_N_ELEMENTS (context_brush_radius_actions), - G_CALLBACK (context_brush_radius_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_radius_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_spikes_actions, G_N_ELEMENTS (context_brush_spikes_actions), - G_CALLBACK (context_brush_spikes_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_spikes_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_hardness_actions, G_N_ELEMENTS (context_brush_hardness_actions), - G_CALLBACK (context_brush_hardness_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_hardness_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_aspect_actions, G_N_ELEMENTS (context_brush_aspect_actions), - G_CALLBACK (context_brush_aspect_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + context_brush_aspect_cmd_callback); + gimp_action_group_add_enum_actions (group, "context-action", context_brush_angle_actions, G_N_ELEMENTS (context_brush_angle_actions), - G_CALLBACK (context_brush_angle_cmd_callback)); + context_brush_angle_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/context-commands.c gimp-2.10.14+om/app/actions/context-commands.c --- gimp-2.10.8+zorin2/app/actions/context-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/context-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -81,8 +81,9 @@ /* public functions */ void -context_colors_default_cmd_callback (GtkAction *action, - gpointer data) +context_colors_default_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; return_if_no_context (context, data); @@ -91,8 +92,9 @@ } void -context_colors_swap_cmd_callback (GtkAction *action, - gpointer data) +context_colors_swap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; return_if_no_context (context, data); @@ -102,16 +104,19 @@ #define SELECT_COLOR_CMD_CALLBACK(name, fgbg, use_colormap, use_palette) \ void \ -context_##name##_##fgbg##ground_cmd_callback (GtkAction *action, \ - gint value, \ - gpointer data) \ +context_##name##_##fgbg##ground_cmd_callback (GimpAction *action, \ + GVariant *value, \ + gpointer data) \ { \ - GimpContext *context; \ - GimpRGB color; \ + GimpContext *context; \ + GimpRGB color; \ + GimpActionSelectType select_type; \ return_if_no_context (context, data); \ -\ + \ + select_type = (GimpActionSelectType) g_variant_get_int32 (value); \ + \ gimp_context_get_##fgbg##ground (context, &color); \ - context_select_color ((GimpActionSelectType) value, &color, \ + context_select_color (select_type, &color, \ use_colormap, use_palette); \ gimp_context_set_##fgbg##ground (context, &color); \ } @@ -124,16 +129,19 @@ SELECT_COLOR_CMD_CALLBACK (swatch, back, TRUE, TRUE) void -context_foreground_red_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_red_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); - color.r = action_select_value ((GimpActionSelectType) value, + color.r = action_select_value (select_type, color.r, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -141,16 +149,19 @@ } void -context_foreground_green_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_green_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); - color.g = action_select_value ((GimpActionSelectType) value, + color.g = action_select_value (select_type, color.g, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -158,16 +169,19 @@ } void -context_foreground_blue_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_blue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); - color.b = action_select_value ((GimpActionSelectType) value, + color.b = action_select_value (select_type, color.b, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -175,16 +189,19 @@ } void -context_background_red_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_red_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); - color.r = action_select_value ((GimpActionSelectType) value, + color.r = action_select_value (select_type, color.r, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -192,16 +209,19 @@ } void -context_background_green_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_green_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); - color.g = action_select_value ((GimpActionSelectType) value, + color.g = action_select_value (select_type, color.g, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -209,16 +229,19 @@ } void -context_background_blue_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_blue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; + GimpContext *context; + GimpRGB color; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); - color.b = action_select_value ((GimpActionSelectType) value, + color.b = action_select_value (select_type, color.b, 0.0, 1.0, 1.0, 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE); @@ -226,18 +249,21 @@ } void -context_foreground_hue_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_hue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.h = action_select_value ((GimpActionSelectType) value, + hsv.h = action_select_value (select_type, hsv.h, 0.0, 1.0, 1.0, 1.0 / 360.0, 0.01, 0.1, 0.0, FALSE); @@ -246,18 +272,21 @@ } void -context_foreground_saturation_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_saturation_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.s = action_select_value ((GimpActionSelectType) value, + hsv.s = action_select_value (select_type, hsv.s, 0.0, 1.0, 1.0, 0.01, 0.01, 0.1, 0.0, FALSE); @@ -266,18 +295,21 @@ } void -context_foreground_value_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_foreground_value_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_foreground (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.v = action_select_value ((GimpActionSelectType) value, + hsv.v = action_select_value (select_type, hsv.v, 0.0, 1.0, 1.0, 0.01, 0.01, 0.1, 0.0, FALSE); @@ -286,18 +318,21 @@ } void -context_background_hue_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_hue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.h = action_select_value ((GimpActionSelectType) value, + hsv.h = action_select_value (select_type, hsv.h, 0.0, 1.0, 1.0, 1.0 / 360.0, 0.01, 0.1, 0.0, FALSE); @@ -306,18 +341,21 @@ } void -context_background_saturation_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_saturation_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.s = action_select_value ((GimpActionSelectType) value, + hsv.s = action_select_value (select_type, hsv.s, 0.0, 1.0, 1.0, 0.01, 0.01, 0.1, 0.0, FALSE); @@ -326,18 +364,21 @@ } void -context_background_value_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_background_value_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpRGB color; - GimpHSV hsv; + GimpContext *context; + GimpRGB color; + GimpHSV hsv; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + gimp_context_get_background (context, &color); gimp_rgb_to_hsv (&color, &hsv); - hsv.v = action_select_value ((GimpActionSelectType) value, + hsv.v = action_select_value (select_type, hsv.v, 0.0, 1.0, 1.0, 0.01, 0.01, 0.1, 0.0, FALSE); @@ -346,19 +387,22 @@ } void -context_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_TOOL_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "opacity", @@ -367,25 +411,28 @@ } void -context_paint_mode_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpContext *context; - GimpToolInfo *tool_info; - GimpLayerMode *modes; - gint n_modes; - GimpLayerMode paint_mode; - gint index; +context_paint_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpContext *context; + GimpToolInfo *tool_info; + GimpLayerMode *modes; + gint n_modes; + GimpLayerMode paint_mode; + gint index; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + paint_mode = gimp_context_get_paint_mode (context); modes = gimp_layer_mode_get_context_array (paint_mode, GIMP_LAYER_MODE_CONTEXT_PAINT, &n_modes); index = context_paint_mode_index (paint_mode, modes, n_modes); - index = action_select_value ((GimpActionSelectType) value, + index = action_select_value (select_type, index, 0, n_modes - 1, 0, 0.0, 1.0, 1.0, 0.0, FALSE); paint_mode = modes[index]; @@ -414,91 +461,117 @@ } void -context_tool_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_tool_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, context, context->gimp->tool_info_list); } void -context_brush_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, - context, gimp_data_factory_get_container (context->gimp->brush_factory)); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, + context, + gimp_data_factory_get_container (context->gimp->brush_factory)); } void -context_pattern_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_pattern_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, - context, gimp_data_factory_get_container (context->gimp->pattern_factory)); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, + context, + gimp_data_factory_get_container (context->gimp->pattern_factory)); } void -context_palette_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_palette_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, - context, gimp_data_factory_get_container (context->gimp->palette_factory)); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, + context, + gimp_data_factory_get_container (context->gimp->palette_factory)); } void -context_gradient_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_gradient_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, - context, gimp_data_factory_get_container (context->gimp->gradient_factory)); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, + context, + gimp_data_factory_get_container (context->gimp->gradient_factory)); } void -context_font_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_font_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; + GimpContext *context; + GimpActionSelectType select_type; return_if_no_context (context, data); - context_select_object ((GimpActionSelectType) value, - context, gimp_data_factory_get_container (context->gimp->font_factory)); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + context_select_object (select_type, + context, + gimp_data_factory_get_container (context->gimp->font_factory)); } void -context_brush_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH (brush) && gimp_data_is_writable (GIMP_DATA (brush))) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (brush), "spacing", @@ -507,14 +580,17 @@ } void -context_brush_shape_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_shape_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpBrushGeneratedShape shape; return_if_no_context (context, data); + shape = (GimpBrushGeneratedShape) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && @@ -524,10 +600,9 @@ GimpDisplay *display; const char *value_desc; - gimp_brush_generated_set_shape (generated, - (GimpBrushGeneratedShape) value); + gimp_brush_generated_set_shape (generated, shape); - gimp_enum_get_value (GIMP_TYPE_BRUSH_GENERATED_SHAPE, value, + gimp_enum_get_value (GIMP_TYPE_BRUSH_GENERATED_SHAPE, shape, NULL, NULL, &value_desc, NULL); display = action_data_get_display (data); @@ -540,14 +615,17 @@ } void -context_brush_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && @@ -566,7 +644,7 @@ * is less than 1.0 px. This prevents irritating 0.1, 1.1, 2.1 etc * radius sequences when 1.0 px steps are used. */ - switch ((GimpActionSelectType) value) + switch (select_type) { case GIMP_ACTION_SELECT_SMALL_PREVIOUS: case GIMP_ACTION_SELECT_SMALL_NEXT: @@ -583,7 +661,7 @@ break; } - radius = action_select_value ((GimpActionSelectType) value, + radius = action_select_value (select_type, radius, min_radius, 4000.0, min_radius, 0.1, 1.0, 10.0, 0.05, FALSE); @@ -600,20 +678,23 @@ } void -context_brush_spikes_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_spikes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && gimp_data_is_writable (GIMP_DATA (brush))) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (brush), "spikes", @@ -622,20 +703,23 @@ } void -context_brush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && gimp_data_is_writable (GIMP_DATA (brush))) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (brush), "hardness", @@ -644,20 +728,23 @@ } void -context_brush_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && gimp_data_is_writable (GIMP_DATA (brush))) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (brush), "aspect-ratio", @@ -666,14 +753,17 @@ } void -context_brush_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data) +context_brush_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpBrush *brush; + GimpContext *context; + GimpBrush *brush; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + brush = gimp_context_get_brush (context); if (GIMP_IS_BRUSH_GENERATED (brush) && @@ -685,12 +775,12 @@ angle = gimp_brush_generated_get_angle (generated); - if (value == GIMP_ACTION_SELECT_FIRST) + if (select_type == GIMP_ACTION_SELECT_FIRST) angle = 0.0; - else if (value == GIMP_ACTION_SELECT_LAST) + else if (select_type == GIMP_ACTION_SELECT_LAST) angle = 90.0; else - angle = action_select_value ((GimpActionSelectType) value, + angle = action_select_value (select_type, angle, 0.0, 180.0, 0.0, 0.1, 1.0, 15.0, 0.1, TRUE); @@ -717,14 +807,16 @@ { GimpObject *current; - current = gimp_context_get_by_type (context, - gimp_container_get_children_type (container)); + current = + gimp_context_get_by_type (context, + gimp_container_get_children_type (container)); current = action_select_object (select_type, container, current); if (current) gimp_context_set_by_type (context, - gimp_container_get_children_type (container), current); + gimp_container_get_children_type (container), + current); } static gint diff -Nru gimp-2.10.8+zorin2/app/actions/context-commands.h gimp-2.10.14+om/app/actions/context-commands.h --- gimp-2.10.8+zorin2/app/actions/context-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/context-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -20,119 +20,121 @@ -void context_colors_default_cmd_callback (GtkAction *action, - gpointer data); -void context_colors_swap_cmd_callback (GtkAction *action, - gpointer data); - -void context_palette_foreground_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_palette_background_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_colormap_foreground_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_colormap_background_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_swatch_foreground_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_swatch_background_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_foreground_red_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_foreground_green_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_foreground_blue_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_background_red_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_background_green_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_background_blue_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_foreground_hue_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_foreground_saturation_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_foreground_value_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_background_hue_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_background_saturation_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_background_value_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_paint_mode_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_tool_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_pattern_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_palette_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_gradient_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_font_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void context_brush_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_shape_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_spikes_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void context_brush_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void context_colors_default_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_colors_swap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_palette_foreground_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_palette_background_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_colormap_foreground_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_colormap_background_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_swatch_foreground_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_swatch_background_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_foreground_red_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_foreground_green_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_foreground_blue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_background_red_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_background_green_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_background_blue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_foreground_hue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_foreground_saturation_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_foreground_value_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_background_hue_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_background_saturation_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_background_value_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_paint_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_tool_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_pattern_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_palette_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_gradient_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_font_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void context_brush_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_shape_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_spikes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void context_brush_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __CONTEXT_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/cursor-info-actions.c gimp-2.10.14+om/app/actions/cursor-info-actions.c --- gimp-2.10.8+zorin2/app/actions/cursor-info-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/cursor-info-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,7 +47,7 @@ { "cursor-info-sample-merged", NULL, NC_("cursor-info-action", "_Sample Merged"), "", NC_("cursor-info-action", "Use the composite color of all visible layers"), - G_CALLBACK (cursor_info_sample_merged_cmd_callback), + cursor_info_sample_merged_cmd_callback, TRUE, GIMP_HELP_POINTER_INFO_SAMPLE_MERGED } }; diff -Nru gimp-2.10.8+zorin2/app/actions/cursor-info-commands.c gimp-2.10.14+om/app/actions/cursor-info-commands.c --- gimp-2.10.8+zorin2/app/actions/cursor-info-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/cursor-info-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,13 +30,12 @@ /* public functions */ void -cursor_info_sample_merged_cmd_callback (GtkAction *action, - gpointer data) +cursor_info_sample_merged_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpCursorView *view = GIMP_CURSOR_VIEW (data); - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + GimpCursorView *view = GIMP_CURSOR_VIEW (data); + gboolean active = g_variant_get_boolean (value); gimp_cursor_view_set_sample_merged (view, active); } diff -Nru gimp-2.10.8+zorin2/app/actions/cursor-info-commands.h gimp-2.10.14+om/app/actions/cursor-info-commands.h --- gimp-2.10.8+zorin2/app/actions/cursor-info-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/cursor-info-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,8 +19,9 @@ #define __CURSOR_INFO_COMMANDS_H__ -void cursor_info_sample_merged_cmd_callback (GtkAction *action, - gpointer data); +void cursor_info_sample_merged_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __CURSOR_INFO_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/dashboard-actions.c gimp-2.10.14+om/app/actions/dashboard-actions.c --- gimp-2.10.8+zorin2/app/actions/dashboard-actions.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dashboard-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -50,25 +50,25 @@ { "dashboard-log-record", GIMP_ICON_RECORD, NC_("dashboard-action", "_Start/Stop Recording..."), NULL, NC_("dashboard-action", "Start/stop recording performance log"), - G_CALLBACK (dashboard_log_record_cmd_callback), + dashboard_log_record_cmd_callback, GIMP_HELP_DASHBOARD_LOG_RECORD }, { "dashboard-log-add-marker", GIMP_ICON_MARKER, NC_("dashboard-action", "_Add Marker..."), NULL, NC_("dashboard-action", "Add an event marker " "to the performance log"), - G_CALLBACK (dashboard_log_add_marker_cmd_callback), + dashboard_log_add_marker_cmd_callback, GIMP_HELP_DASHBOARD_LOG_ADD_MARKER }, { "dashboard-log-add-empty-marker", GIMP_ICON_MARKER, NC_("dashboard-action", "Add _Empty Marker"), NULL, NC_("dashboard-action", "Add an empty event marker " "to the performance log"), - G_CALLBACK (dashboard_log_add_empty_marker_cmd_callback), + dashboard_log_add_empty_marker_cmd_callback, GIMP_HELP_DASHBOARD_LOG_ADD_EMPTY_MARKER }, { "dashboard-reset", GIMP_ICON_RESET, NC_("dashboard-action", "_Reset"), NULL, NC_("dashboard-action", "Reset cumulative data"), - G_CALLBACK (dashboard_reset_cmd_callback), + dashboard_reset_cmd_callback, GIMP_HELP_DASHBOARD_RESET }, }; @@ -78,7 +78,7 @@ NC_("dashboard-action", "_Low Swap Space Warning"), NULL, NC_("dashboard-action", "Raise the dashboard when " "the swap size approaches its limit"), - G_CALLBACK (dashboard_low_swap_space_warning_cmd_callback), + dashboard_low_swap_space_warning_cmd_callback, FALSE, GIMP_HELP_DASHBOARD_LOW_SWAP_SPACE_WARNING } }; @@ -156,14 +156,14 @@ G_N_ELEMENTS (dashboard_update_interval_actions), NULL, 0, - G_CALLBACK (dashboard_update_interval_cmd_callback)); + dashboard_update_interval_cmd_callback); gimp_action_group_add_radio_actions (group, "dashboard-history-duration", dashboard_history_duration_actions, G_N_ELEMENTS (dashboard_history_duration_actions), NULL, 0, - G_CALLBACK (dashboard_history_duration_cmd_callback)); + dashboard_history_duration_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/dashboard-commands.c gimp-2.10.14+om/app/actions/dashboard-commands.c --- gimp-2.10.8+zorin2/app/actions/dashboard-commands.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dashboard-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -52,34 +52,35 @@ void -dashboard_update_interval_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +dashboard_update_interval_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); GimpDashboardUpdateInteval update_interval; - update_interval = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + update_interval = g_variant_get_int32 (value); gimp_dashboard_set_update_interval (dashboard, update_interval); } void -dashboard_history_duration_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +dashboard_history_duration_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); GimpDashboardHistoryDuration history_duration; - history_duration = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + history_duration = g_variant_get_int32 (value); gimp_dashboard_set_history_duration (dashboard, history_duration); } void -dashboard_log_record_cmd_callback (GtkAction *action, - gpointer data) +dashboard_log_record_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); @@ -181,8 +182,9 @@ } void -dashboard_log_add_marker_cmd_callback (GtkAction *action, - gpointer data) +dashboard_log_add_marker_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); GtkWidget *dialog; @@ -211,8 +213,9 @@ } void -dashboard_log_add_empty_marker_cmd_callback (GtkAction *action, - gpointer data) +dashboard_log_add_empty_marker_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); @@ -220,8 +223,9 @@ } void -dashboard_reset_cmd_callback (GtkAction *action, - gpointer data) +dashboard_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDashboard *dashboard = GIMP_DASHBOARD (data); @@ -229,13 +233,12 @@ } void -dashboard_low_swap_space_warning_cmd_callback (GtkAction *action, - gpointer data) +dashboard_low_swap_space_warning_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpDashboard *dashboard = GIMP_DASHBOARD (data); - gboolean low_swap_space_warning; - - low_swap_space_warning = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + GimpDashboard *dashboard = GIMP_DASHBOARD (data); + gboolean low_swap_space_warning = g_variant_get_boolean (value); gimp_dashboard_set_low_swap_space_warning (dashboard, low_swap_space_warning); } @@ -243,7 +246,6 @@ /* private functions */ - static void dashboard_log_record_response (GtkWidget *dialog, int response_id, diff -Nru gimp-2.10.8+zorin2/app/actions/dashboard-commands.h gimp-2.10.14+om/app/actions/dashboard-commands.h --- gimp-2.10.8+zorin2/app/actions/dashboard-commands.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dashboard-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,25 +19,30 @@ #define __DASHBOARD_COMMANDS_H__ -void dashboard_update_interval_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void dashboard_history_duration_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); - -void dashboard_log_record_cmd_callback (GtkAction *action, - gpointer data); -void dashboard_log_add_marker_cmd_callback (GtkAction *action, - gpointer data); -void dashboard_log_add_empty_marker_cmd_callback (GtkAction *action, - gpointer data); - -void dashboard_reset_cmd_callback (GtkAction *action, - gpointer data); - -void dashboard_low_swap_space_warning_cmd_callback (GtkAction *action, - gpointer data); +void dashboard_update_interval_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dashboard_history_duration_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void dashboard_log_record_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dashboard_log_add_marker_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dashboard_log_add_empty_marker_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void dashboard_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void dashboard_low_swap_space_warning_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DASHBOARD_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/data-commands.c gimp-2.10.14+om/app/actions/data-commands.c --- gimp-2.10.8+zorin2/app/actions/data-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/data-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -55,8 +55,9 @@ /* public functions */ void -data_open_as_image_cmd_callback (GtkAction *action, - gpointer user_data) +data_open_as_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -95,8 +96,9 @@ } void -data_new_cmd_callback (GtkAction *action, - gpointer user_data) +data_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); @@ -125,8 +127,9 @@ } void -data_duplicate_cmd_callback (GtkAction *action, - gpointer user_data) +data_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -156,8 +159,9 @@ } void -data_copy_location_cmd_callback (GtkAction *action, - gpointer user_data) +data_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -184,8 +188,9 @@ } void -data_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer user_data) +data_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -218,8 +223,9 @@ } void -data_delete_cmd_callback (GtkAction *action, - gpointer user_data) +data_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -248,8 +254,9 @@ } void -data_refresh_cmd_callback (GtkAction *action, - gpointer user_data) +data_refresh_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); Gimp *gimp; @@ -262,9 +269,9 @@ } void -data_edit_cmd_callback (GtkAction *action, - const gchar *value, - gpointer user_data) +data_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpDataFactoryView *view = GIMP_DATA_FACTORY_VIEW (user_data); GimpContext *context; @@ -288,7 +295,8 @@ gimp_dialog_factory_get_singleton (), screen, monitor, - value); + g_variant_get_string (value, + NULL)); gimp_data_editor_set_data (GIMP_DATA_EDITOR (gtk_bin_get_child (GTK_BIN (dockable))), data); diff -Nru gimp-2.10.8+zorin2/app/actions/data-commands.h gimp-2.10.14+om/app/actions/data-commands.h --- gimp-2.10.8+zorin2/app/actions/data-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/data-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,23 +19,30 @@ #define __DATA_COMMANDS_H__ -void data_open_as_image_cmd_callback (GtkAction *action, - gpointer data); -void data_new_cmd_callback (GtkAction *action, - gpointer data); -void data_duplicate_cmd_callback (GtkAction *action, - gpointer data); -void data_copy_location_cmd_callback (GtkAction *action, - gpointer user_data); -void data_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer user_data); -void data_delete_cmd_callback (GtkAction *action, - gpointer data); -void data_refresh_cmd_callback (GtkAction *action, - gpointer data); -void data_edit_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data); +void data_open_as_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_refresh_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void data_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DATA_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/data-editor-commands.c gimp-2.10.14+om/app/actions/data-editor-commands.c --- gimp-2.10.8+zorin2/app/actions/data-editor-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/data-editor-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,13 +30,14 @@ /* public functions */ void -data_editor_edit_active_cmd_callback (GtkAction *action, - gpointer data) +data_editor_edit_active_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDataEditor *editor = GIMP_DATA_EDITOR (data); gboolean edit_active; - edit_active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + edit_active = g_variant_get_boolean (value); gimp_data_editor_set_edit_active (editor, edit_active); } diff -Nru gimp-2.10.8+zorin2/app/actions/data-editor-commands.h gimp-2.10.14+om/app/actions/data-editor-commands.h --- gimp-2.10.8+zorin2/app/actions/data-editor-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/data-editor-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,8 +19,9 @@ #define __DATA_EDITOR_COMMANDS_H__ -void data_editor_edit_active_cmd_callback (GtkAction *action, - gpointer data); +void data_editor_edit_active_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DATA_EDITOR_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/debug-actions.c gimp-2.10.14+om/app/actions/debug-actions.c --- gimp-2.10.8+zorin2/app/actions/debug-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/debug-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -38,7 +38,7 @@ { "debug-mem-profile", NULL, "_Memory Profile", NULL, NULL, - G_CALLBACK (debug_mem_profile_cmd_callback), + debug_mem_profile_cmd_callback, NULL }, { "debug-benchmark-projection", NULL, @@ -46,33 +46,33 @@ "Invalidates the entire projection, measures the time it takes to " "validate (render) the part that is visible in the active display, " "and print the result to stdout.", - G_CALLBACK (debug_benchmark_projection_cmd_callback), + debug_benchmark_projection_cmd_callback, NULL }, { "debug-show-image-graph", NULL, "Show Image _Graph", NULL, "Creates a new image showing the GEGL graph of this image", - G_CALLBACK (debug_show_image_graph_cmd_callback), + debug_show_image_graph_cmd_callback, NULL }, { "debug-dump-items", NULL, "_Dump Items", NULL, NULL, - G_CALLBACK (debug_dump_menus_cmd_callback), + debug_dump_menus_cmd_callback, NULL }, { "debug-dump-managers", NULL, "Dump _UI Managers", NULL, NULL, - G_CALLBACK (debug_dump_managers_cmd_callback), + debug_dump_managers_cmd_callback, NULL }, { "debug-dump-keyboard-shortcuts", NULL, "Dump _Keyboard Shortcuts", NULL, NULL, - G_CALLBACK (debug_dump_keyboard_shortcuts_cmd_callback), + debug_dump_keyboard_shortcuts_cmd_callback, NULL }, { "debug-dump-attached-data", NULL, "Dump Attached Data", NULL, NULL, - G_CALLBACK (debug_dump_attached_data_cmd_callback), + debug_dump_attached_data_cmd_callback, NULL } }; diff -Nru gimp-2.10.8+zorin2/app/actions/debug-commands.c gimp-2.10.14+om/app/actions/debug-commands.c --- gimp-2.10.8+zorin2/app/actions/debug-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/debug-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,6 +36,7 @@ #include "gegl/gimp-gegl-utils.h" #include "widgets/gimpaction.h" +#include "widgets/gimpactiongroup.h" #include "widgets/gimpmenufactory.h" #include "widgets/gimpuimanager.h" @@ -71,8 +72,9 @@ /* public functions */ void -debug_mem_profile_cmd_callback (GtkAction *action, - gpointer data) +debug_mem_profile_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { extern gboolean gimp_debug_memsize; Gimp *gimp; @@ -86,8 +88,9 @@ } void -debug_benchmark_projection_cmd_callback (GtkAction *action, - gpointer data) +debug_benchmark_projection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; return_if_no_display (display, data); @@ -96,8 +99,9 @@ } void -debug_show_image_graph_cmd_callback (GtkAction *action, - gpointer data) +debug_show_image_graph_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *source_image = NULL; return_if_no_image (source_image, data); @@ -106,8 +110,9 @@ } void -debug_dump_menus_cmd_callback (GtkAction *action, - gpointer data) +debug_dump_menus_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GList *list; @@ -147,8 +152,9 @@ } void -debug_dump_managers_cmd_callback (GtkAction *action, - gpointer data) +debug_dump_managers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GList *list; @@ -169,30 +175,31 @@ "========================================\n\n", entry->identifier); - g_print ("%s\n", gtk_ui_manager_get_ui (managers->data)); + g_print ("%s\n", gimp_ui_manager_get_ui (managers->data)); } } } void -debug_dump_keyboard_shortcuts_cmd_callback (GtkAction *action, - gpointer data) +debug_dump_keyboard_shortcuts_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImageWindow *window; - GtkUIManager *manager; + GimpUIManager *manager; GtkAccelGroup *accel_group; GList *group_it; GList *strings = NULL; return_if_no_display (display, data); window = gimp_display_shell_get_window (gimp_display_get_shell (display)); - manager = GTK_UI_MANAGER (gimp_image_window_get_ui_manager (window)); + manager = gimp_image_window_get_ui_manager (window); - accel_group = gtk_ui_manager_get_accel_group (manager); + accel_group = gimp_ui_manager_get_accel_group (manager); /* Gather formatted strings of keyboard shortcuts */ - for (group_it = gtk_ui_manager_get_action_groups (manager); + for (group_it = gimp_ui_manager_get_action_groups (manager); group_it; group_it = g_list_next (group_it)) { @@ -200,13 +207,13 @@ GList *actions = NULL; GList *action_it = NULL; - actions = gtk_action_group_list_actions (GTK_ACTION_GROUP (group)); + actions = gimp_action_group_list_actions (group); actions = g_list_sort (actions, (GCompareFunc) gimp_action_name_compare); for (action_it = actions; action_it; action_it = g_list_next (action_it)) { - GtkAction *action = action_it->data; - const gchar *name = gtk_action_get_name (action); + GimpAction *action = action_it->data; + const gchar *name = gimp_action_get_name (action); GClosure *accel_closure = NULL; if (strstr (name, "-menu") || @@ -214,7 +221,7 @@ name[0] == '<') continue; - accel_closure = gtk_action_get_accel_closure (action); + accel_closure = gimp_action_get_accel_closure (action); if (accel_closure) { @@ -229,7 +236,7 @@ gchar *label; gchar *key_string; - label_tmp = gtk_action_get_label (action); + label_tmp = gimp_action_get_label (action); label = gimp_strip_uline (label_tmp); key_string = gtk_accelerator_get_label (key->accel_key, key->accel_mods); @@ -264,8 +271,9 @@ } void -debug_dump_attached_data_cmd_callback (GtkAction *action, - gpointer data) +debug_dump_attached_data_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp = action_data_get_gimp (data); GimpContext *user_context = gimp_get_user_context (gimp); @@ -286,15 +294,12 @@ { GimpProjection *projection = gimp_image_get_projection (image); - GIMP_TIMER_START (); + gimp_projection_stop_rendering (projection); - gimp_image_invalidate (image, - 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image)); - gimp_projection_flush_now (projection); + GIMP_TIMER_START (); - gimp_display_flush_now (display); + gimp_image_invalidate_all (image); + gimp_projection_flush_now (projection, TRUE); GIMP_TIMER_END ("Validation of the entire projection"); diff -Nru gimp-2.10.8+zorin2/app/actions/debug-commands.h gimp-2.10.14+om/app/actions/debug-commands.h --- gimp-2.10.8+zorin2/app/actions/debug-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/debug-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,21 +19,28 @@ #define __DEBUG_COMMANDS_H__ -void debug_mem_profile_cmd_callback (GtkAction *action, - gpointer data); -void debug_benchmark_projection_cmd_callback (GtkAction *action, - gpointer data); -void debug_show_image_graph_cmd_callback (GtkAction *action, - gpointer data); -void debug_dump_menus_cmd_callback (GtkAction *action, - gpointer data); -void debug_dump_managers_cmd_callback (GtkAction *action, - gpointer data); -void debug_dump_keyboard_shortcuts_cmd_callback (GtkAction *action, - gpointer data); -void debug_dump_attached_data_cmd_callback (GtkAction *action, - gpointer data); -void debug_benchmark_projection_cmd_callback (GtkAction *action, - gpointer data); +void debug_mem_profile_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_benchmark_projection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_show_image_graph_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_dump_menus_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_dump_managers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_dump_keyboard_shortcuts_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void debug_dump_attached_data_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + + #endif /* __DEBUG_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/dialogs-actions.c gimp-2.10.14+om/app/actions/dialogs-actions.c --- gimp-2.10.8+zorin2/app/actions/dialogs-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dialogs-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -116,7 +116,7 @@ GIMP_HELP_UNDO_DIALOG }, { "dialogs-cursor", GIMP_ICON_CURSOR, - NC_("dialogs-action", "Pointer"), NULL, + NC_("dialogs-action", "_Pointer"), NULL, NC_("dialogs-action", "Open the pointer information dialog"), "gimp-cursor-view", GIMP_HELP_POINTER_INFO_DIALOG }, @@ -146,7 +146,7 @@ GIMP_HELP_BRUSH_EDIT }, { "dialogs-dynamics", GIMP_ICON_DYNAMICS, - NC_("dialogs-action", "Paint Dynamics"), NULL, + NC_("dialogs-action", "Paint D_ynamics"), NULL, NC_("dialogs-action", "Open paint dynamics dialog"), "gimp-dynamics-list|gimp-dynamics-grid", GIMP_HELP_DYNAMICS_DIALOG }, @@ -188,13 +188,13 @@ GIMP_HELP_PALETTE_DIALOG }, { "dialogs-palette-editor", GIMP_ICON_PALETTE, - NC_("dialogs-action", "Palette Editor"), NULL, + NC_("dialogs-action", "Palette _Editor"), NULL, NC_("dialogs-action", "Open the palette editor"), "gimp-palette-editor", GIMP_HELP_PALETTE_EDIT }, { "dialogs-tool-presets", GIMP_ICON_TOOL_PRESET, - NC_("dialogs-action", "Tool presets"), NULL, + NC_("dialogs-action", "Tool Pre_sets"), NULL, NC_("dialogs-action", "Open tool presets dialog"), "gimp-tool-preset-list|gimp-tool-preset-grid", GIMP_HELP_TOOL_PRESET_DIALOG }, @@ -336,12 +336,12 @@ gimp_action_group_add_string_actions (group, "dialogs-action", dialogs_dockable_actions, G_N_ELEMENTS (dialogs_dockable_actions), - G_CALLBACK (dialogs_create_dockable_cmd_callback)); + dialogs_create_dockable_cmd_callback); gimp_action_group_add_string_actions (group, "dialogs-action", dialogs_toplevel_actions, G_N_ELEMENTS (dialogs_toplevel_actions), - G_CALLBACK (dialogs_create_toplevel_cmd_callback)); + dialogs_create_toplevel_cmd_callback); } void @@ -354,12 +354,12 @@ if (dialogs_actions_toolbox_exists (gimp)) { - toolbox_label = _("Toolbox"); + toolbox_label = _("Tool_box"); toolbox_tooltip = _("Raise the toolbox"); } else { - toolbox_label = _("New Toolbox"); + toolbox_label = _("New Tool_box"); toolbox_tooltip = _("Create a new toolbox"); } diff -Nru gimp-2.10.8+zorin2/app/actions/dialogs-commands.c gimp-2.10.14+om/app/actions/dialogs-commands.c --- gimp-2.10.8+zorin2/app/actions/dialogs-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dialogs-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -37,36 +37,42 @@ /* public functions */ void -dialogs_create_toplevel_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data) +dialogs_create_toplevel_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GtkWidget *widget; + GtkWidget *widget; + const gchar *identifier; return_if_no_widget (widget, data); - if (value) + identifier = g_variant_get_string (value, NULL); + + if (identifier) gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (), gtk_widget_get_screen (widget), gimp_widget_get_monitor (widget), NULL /*ui_manager*/, - value, -1, TRUE); + identifier, -1, TRUE); } void -dialogs_create_dockable_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data) +dialogs_create_dockable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - Gimp *gimp; - GtkWidget *widget; + Gimp *gimp; + GtkWidget *widget; + const gchar *identifier; return_if_no_gimp (gimp, data); return_if_no_widget (widget, data); - if (value) + identifier = g_variant_get_string (value, NULL); + + if (identifier) gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (gimp)), gimp, gimp_dialog_factory_get_singleton (), gtk_widget_get_screen (widget), gimp_widget_get_monitor (widget), - value); + identifier); } diff -Nru gimp-2.10.8+zorin2/app/actions/dialogs-commands.h gimp-2.10.14+om/app/actions/dialogs-commands.h --- gimp-2.10.8+zorin2/app/actions/dialogs-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dialogs-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,12 +19,12 @@ #define __DIALOGS_COMMANDS_H__ -void dialogs_create_toplevel_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data); -void dialogs_create_dockable_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data); +void dialogs_create_toplevel_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dialogs_create_dockable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DIALOGS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/dockable-actions.c gimp-2.10.14+om/app/actions/dockable-actions.c --- gimp-2.10.8+zorin2/app/actions/dockable-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dockable-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -59,12 +59,12 @@ { "dockable-close-tab", "window-close", NC_("dockable-action", "_Close Tab"), "", NULL, - G_CALLBACK (dockable_close_tab_cmd_callback), + dockable_close_tab_cmd_callback, GIMP_HELP_DOCK_TAB_CLOSE }, { "dockable-detach-tab", GIMP_ICON_DETACH, NC_("dockable-action", "_Detach Tab"), "", NULL, - G_CALLBACK (dockable_detach_tab_cmd_callback), + dockable_detach_tab_cmd_callback, GIMP_HELP_DOCK_TAB_DETACH } }; @@ -127,13 +127,13 @@ NC_("dockable-action", "Loc_k Tab to Dock"), NULL, NC_("dockable-action", "Protect this tab from being dragged with the mouse pointer"), - G_CALLBACK (dockable_lock_tab_cmd_callback), + dockable_lock_tab_cmd_callback, FALSE, GIMP_HELP_DOCK_TAB_LOCK }, { "dockable-show-button-bar", NULL, NC_("dockable-action", "Show _Button Bar"), NULL, NULL, - G_CALLBACK (dockable_show_button_bar_cmd_callback), + dockable_show_button_bar_cmd_callback, TRUE, GIMP_HELP_DOCK_SHOW_BUTTON_BAR } }; @@ -166,28 +166,28 @@ gimp_action_group_add_string_actions (group, "dialogs-action", dialogs_dockable_actions, n_dialogs_dockable_actions, - G_CALLBACK (dockable_add_tab_cmd_callback)); + dockable_add_tab_cmd_callback); gimp_action_group_add_radio_actions (group, "preview-size", dockable_view_size_actions, G_N_ELEMENTS (dockable_view_size_actions), NULL, GIMP_VIEW_SIZE_MEDIUM, - G_CALLBACK (dockable_view_size_cmd_callback)); + dockable_view_size_cmd_callback); gimp_action_group_add_radio_actions (group, "tab-style", dockable_tab_style_actions, G_N_ELEMENTS (dockable_tab_style_actions), NULL, GIMP_TAB_STYLE_AUTOMATIC, - G_CALLBACK (dockable_tab_style_cmd_callback)); + dockable_tab_style_cmd_callback); gimp_action_group_add_radio_actions (group, "dockable-action", dockable_view_type_actions, G_N_ELEMENTS (dockable_view_type_actions), NULL, GIMP_VIEW_TYPE_LIST, - G_CALLBACK (dockable_toggle_view_cmd_callback)); + dockable_toggle_view_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/dockable-commands.c gimp-2.10.14+om/app/actions/dockable-commands.c --- gimp-2.10.8+zorin2/app/actions/dockable-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dockable-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -44,20 +44,21 @@ /* public functions */ void -dockable_add_tab_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data) +dockable_add_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); gimp_dockbook_add_from_dialog_factory (dockbook, - value /*identifiers*/, + g_variant_get_string (value, NULL), -1); } void -dockable_close_tab_cmd_callback (GtkAction *action, - gpointer data) +dockable_close_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); @@ -72,8 +73,9 @@ } void -dockable_detach_tab_cmd_callback (GtkAction *action, - gpointer data) +dockable_detach_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); @@ -83,32 +85,32 @@ } void -dockable_lock_tab_cmd_callback (GtkAction *action, - gpointer data) +dockable_lock_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); if (dockable) { - gboolean lock = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean lock = g_variant_get_boolean (value); gimp_dockable_set_locked (dockable, lock); } } void -dockable_toggle_view_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +dockable_toggle_view_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable; GimpViewType view_type; gint page_num; - view_type = (GimpViewType) - gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + view_type = (GimpViewType) g_variant_get_int32 (value); page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook)); @@ -211,15 +213,15 @@ } void -dockable_view_size_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +dockable_view_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); gint view_size; - view_size = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + view_size = g_variant_get_int32 (value); if (dockable) { @@ -239,16 +241,15 @@ } void -dockable_tab_style_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +dockable_tab_style_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); GimpTabStyle tab_style; - tab_style = (GimpTabStyle) - gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + tab_style = (GimpTabStyle) g_variant_get_int32 (value); if (dockable && gimp_dockable_get_tab_style (dockable) != tab_style) { @@ -265,8 +266,9 @@ } void -dockable_show_button_bar_cmd_callback (GtkAction *action, - gpointer data) +dockable_show_button_bar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDockbook *dockbook = GIMP_DOCKBOOK (data); GimpDockable *dockable = dockable_get_current (dockbook); @@ -277,7 +279,7 @@ gboolean show; docked = GIMP_DOCKED (gtk_bin_get_child (GTK_BIN (dockable))); - show = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + show = g_variant_get_boolean (value); gimp_docked_set_show_button_bar (docked, show); } diff -Nru gimp-2.10.8+zorin2/app/actions/dockable-commands.h gimp-2.10.14+om/app/actions/dockable-commands.h --- gimp-2.10.8+zorin2/app/actions/dockable-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dockable-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,27 +19,31 @@ #define __DOCKABLE_COMMANDS_H__ -void dockable_add_tab_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data); -void dockable_close_tab_cmd_callback (GtkAction *action, - gpointer data); -void dockable_detach_tab_cmd_callback (GtkAction *action, - gpointer data); -void dockable_lock_tab_cmd_callback (GtkAction *action, - gpointer data); +void dockable_add_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_close_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_detach_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_lock_tab_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void dockable_toggle_view_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void dockable_view_size_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void dockable_tab_style_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void dockable_show_button_bar_cmd_callback (GtkAction *action, - gpointer data); +void dockable_toggle_view_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_view_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_tab_style_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dockable_show_button_bar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DOCKABLE_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/dock-actions.c gimp-2.10.14+om/app/actions/dock-actions.c --- gimp-2.10.8+zorin2/app/actions/dock-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dock-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -48,13 +48,13 @@ { "dock-close", GIMP_ICON_WINDOW_CLOSE, NC_("dock-action", "Close Dock"), "", NULL, - G_CALLBACK (window_close_cmd_callback), + window_close_cmd_callback, GIMP_HELP_DOCK_CLOSE }, { "dock-open-display", NULL, NC_("dock-action", "_Open Display..."), NULL, NC_("dock-action", "Connect to another display"), - G_CALLBACK (window_open_display_cmd_callback), + window_open_display_cmd_callback, NULL } }; @@ -62,13 +62,13 @@ { { "dock-show-image-menu", NULL, NC_("dock-action", "_Show Image Selection"), NULL, NULL, - G_CALLBACK (dock_toggle_image_menu_cmd_callback), + dock_toggle_image_menu_cmd_callback, TRUE, GIMP_HELP_DOCK_IMAGE_MENU }, { "dock-auto-follow-active", NULL, NC_("dock-action", "Auto _Follow Active Image"), NULL, NULL, - G_CALLBACK (dock_toggle_auto_cmd_callback), + dock_toggle_auto_cmd_callback, TRUE, GIMP_HELP_DOCK_AUTO_BUTTON } }; diff -Nru gimp-2.10.8+zorin2/app/actions/dock-commands.c gimp-2.10.14+om/app/actions/dock-commands.c --- gimp-2.10.8+zorin2/app/actions/dock-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dock-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,8 +47,9 @@ /* public functions */ void -dock_toggle_image_menu_cmd_callback (GtkAction *action, - gpointer data) +dock_toggle_image_menu_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget = NULL; GimpDockWindow *dock_window = NULL; @@ -58,15 +59,16 @@ if (dock_window) { - gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_dock_window_set_show_image_menu (dock_window, active); } } void -dock_toggle_auto_cmd_callback (GtkAction *action, - gpointer data) +dock_toggle_auto_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget = NULL; GimpDockWindow *dock_window = NULL; @@ -76,7 +78,7 @@ if (dock_window) { - gboolean active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_dock_window_set_auto_follow_active (dock_window, active); } diff -Nru gimp-2.10.8+zorin2/app/actions/dock-commands.h gimp-2.10.14+om/app/actions/dock-commands.h --- gimp-2.10.8+zorin2/app/actions/dock-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dock-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,12 @@ #define __DOCK_COMMANDS_H__ -void dock_toggle_image_menu_cmd_callback (GtkAction *action, - gpointer data); -void dock_toggle_auto_cmd_callback (GtkAction *action, - gpointer data); +void dock_toggle_image_menu_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void dock_toggle_auto_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DOCK_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/documents-actions.c gimp-2.10.14+om/app/actions/documents-actions.c --- gimp-2.10.8+zorin2/app/actions/documents-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/documents-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -45,62 +45,62 @@ { "documents-open", GIMP_ICON_DOCUMENT_OPEN, NC_("documents-action", "_Open Image"), NULL, NC_("documents-action", "Open the selected entry"), - G_CALLBACK (documents_open_cmd_callback), + documents_open_cmd_callback, GIMP_HELP_DOCUMENT_OPEN }, { "documents-raise-or-open", NULL, NC_("documents-action", "_Raise or Open Image"), NULL, NC_("documents-action", "Raise window if already open"), - G_CALLBACK (documents_raise_or_open_cmd_callback), + documents_raise_or_open_cmd_callback, GIMP_HELP_DOCUMENT_OPEN }, { "documents-file-open-dialog", NULL, NC_("documents-action", "File Open _Dialog"), NULL, NC_("documents-action", "Open image dialog"), - G_CALLBACK (documents_file_open_dialog_cmd_callback), + documents_file_open_dialog_cmd_callback, GIMP_HELP_DOCUMENT_OPEN }, { "documents-copy-location", GIMP_ICON_EDIT_COPY, NC_("documents-action", "Copy Image _Location"), NULL, NC_("documents-action", "Copy image location to clipboard"), - G_CALLBACK (documents_copy_location_cmd_callback), + documents_copy_location_cmd_callback, GIMP_HELP_DOCUMENT_COPY_LOCATION }, { "documents-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("documents-action", "Show in _File Manager"), NULL, NC_("documents-action", "Show image location in the file manager"), - G_CALLBACK (documents_show_in_file_manager_cmd_callback), + documents_show_in_file_manager_cmd_callback, GIMP_HELP_DOCUMENT_SHOW_IN_FILE_MANAGER }, { "documents-remove", GIMP_ICON_LIST_REMOVE, NC_("documents-action", "Remove _Entry"), NULL, NC_("documents-action", "Remove the selected entry"), - G_CALLBACK (documents_remove_cmd_callback), + documents_remove_cmd_callback, GIMP_HELP_DOCUMENT_REMOVE }, { "documents-clear", GIMP_ICON_SHRED, NC_("documents-action", "_Clear History"), NULL, NC_("documents-action", "Clear the entire document history"), - G_CALLBACK (documents_clear_cmd_callback), + documents_clear_cmd_callback, GIMP_HELP_DOCUMENT_CLEAR }, { "documents-recreate-preview", GIMP_ICON_VIEW_REFRESH, NC_("documents-action", "Recreate _Preview"), NULL, NC_("documents-action", "Recreate preview"), - G_CALLBACK (documents_recreate_preview_cmd_callback), + documents_recreate_preview_cmd_callback, GIMP_HELP_DOCUMENT_REFRESH }, { "documents-reload-previews", NULL, NC_("documents-action", "Reload _all Previews"), NULL, NC_("documents-action", "Reload all previews"), - G_CALLBACK (documents_reload_previews_cmd_callback), + documents_reload_previews_cmd_callback, GIMP_HELP_DOCUMENT_REFRESH }, { "documents-remove-dangling", NULL, NC_("documents-action", "Remove Dangling E_ntries"), NULL, NC_("documents-action", "Remove entries for which the corresponding file is not available"), - G_CALLBACK (documents_remove_dangling_cmd_callback), + documents_remove_dangling_cmd_callback, GIMP_HELP_DOCUMENT_REFRESH } }; diff -Nru gimp-2.10.8+zorin2/app/actions/documents-commands.c gimp-2.10.14+om/app/actions/documents-commands.c --- gimp-2.10.8+zorin2/app/actions/documents-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/documents-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -75,8 +75,9 @@ /* public functions */ void -documents_open_cmd_callback (GtkAction *action, - gpointer data) +documents_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -99,8 +100,9 @@ } void -documents_raise_or_open_cmd_callback (GtkAction *action, - gpointer data) +documents_raise_or_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -129,8 +131,9 @@ } void -documents_file_open_dialog_cmd_callback (GtkAction *action, - gpointer data) +documents_file_open_dialog_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -151,8 +154,9 @@ } void -documents_copy_location_cmd_callback (GtkAction *action, - gpointer data) +documents_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -167,8 +171,9 @@ } void -documents_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer data) +documents_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -196,8 +201,9 @@ } void -documents_remove_cmd_callback (GtkAction *action, - gpointer data) +documents_remove_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context = gimp_container_view_get_context (editor->view); @@ -212,8 +218,9 @@ } void -documents_clear_cmd_callback (GtkAction *action, - gpointer data) +documents_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context = gimp_container_view_get_context (editor->view); @@ -282,8 +289,9 @@ } void -documents_recreate_preview_cmd_callback (GtkAction *action, - gpointer data) +documents_recreate_preview_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -313,8 +321,9 @@ } void -documents_reload_previews_cmd_callback (GtkAction *action, - gpointer data) +documents_reload_previews_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -344,8 +353,9 @@ } void -documents_remove_dangling_cmd_callback (GtkAction *action, - gpointer data) +documents_remove_dangling_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; diff -Nru gimp-2.10.8+zorin2/app/actions/documents-commands.h gimp-2.10.14+om/app/actions/documents-commands.h --- gimp-2.10.8+zorin2/app/actions/documents-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/documents-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,26 +19,36 @@ #define __DOCUMENTS_COMMANDS_H__ -void documents_open_cmd_callback (GtkAction *action, - gpointer data); -void documents_raise_or_open_cmd_callback (GtkAction *action, - gpointer data); -void documents_file_open_dialog_cmd_callback (GtkAction *action, - gpointer data); -void documents_copy_location_cmd_callback (GtkAction *action, - gpointer data); -void documents_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer data); -void documents_remove_cmd_callback (GtkAction *action, - gpointer data); -void documents_clear_cmd_callback (GtkAction *action, - gpointer data); -void documents_recreate_preview_cmd_callback (GtkAction *action, - gpointer data); -void documents_reload_previews_cmd_callback (GtkAction *action, - gpointer data); -void documents_remove_dangling_cmd_callback (GtkAction *action, - gpointer data); +void documents_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_raise_or_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_file_open_dialog_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_remove_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_recreate_preview_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_reload_previews_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void documents_remove_dangling_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DOCUMENTS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/drawable-actions.c gimp-2.10.14+om/app/actions/drawable-actions.c --- gimp-2.10.8+zorin2/app/actions/drawable-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/drawable-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -44,34 +44,27 @@ { "drawable-equalize", NULL, NC_("drawable-action", "_Equalize"), NULL, NC_("drawable-action", "Automatic contrast enhancement"), - G_CALLBACK (drawable_equalize_cmd_callback), + drawable_equalize_cmd_callback, GIMP_HELP_LAYER_EQUALIZE }, { "drawable-levels-stretch", NULL, NC_("drawable-action", "_White Balance"), NULL, NC_("drawable-action", "Automatic white balance correction"), - G_CALLBACK (drawable_levels_stretch_cmd_callback), - GIMP_HELP_LAYER_WHITE_BALANCE }, - - { "drawable-offset", NULL, - NC_("drawable-action", "_Offset..."), "O", - NC_("drawable-action", - "Shift the pixels, optionally wrapping them at the borders"), - G_CALLBACK (drawable_offset_cmd_callback), - GIMP_HELP_LAYER_OFFSET } + drawable_levels_stretch_cmd_callback, + GIMP_HELP_LAYER_WHITE_BALANCE } }; static const GimpToggleActionEntry drawable_toggle_actions[] = { { "drawable-visible", GIMP_ICON_VISIBLE, NC_("drawable-action", "Toggle Drawable _Visibility"), NULL, NULL, - G_CALLBACK (drawable_visible_cmd_callback), + drawable_visible_cmd_callback, FALSE, GIMP_HELP_LAYER_VISIBLE }, { "drawable-linked", GIMP_ICON_LINKED, NC_("drawable-action", "Toggle Drawable _Linked State"), NULL, NULL, - G_CALLBACK (drawable_linked_cmd_callback), + drawable_linked_cmd_callback, FALSE, GIMP_HELP_LAYER_LINKED }, @@ -79,7 +72,7 @@ NC_("drawable-action", "L_ock Pixels of Drawable"), NULL, NC_("drawable-action", "Keep the pixels on this drawable from being modified"), - G_CALLBACK (drawable_lock_content_cmd_callback), + drawable_lock_content_cmd_callback, FALSE, GIMP_HELP_LAYER_LOCK_PIXELS }, @@ -87,7 +80,7 @@ NC_("drawable-action", "L_ock Position of Drawable"), NULL, NC_("drawable-action", "Keep the position on this drawable from being modified"), - G_CALLBACK (drawable_lock_position_cmd_callback), + drawable_lock_position_cmd_callback, FALSE, GIMP_HELP_LAYER_LOCK_POSITION }, }; @@ -143,12 +136,12 @@ gimp_action_group_add_enum_actions (group, "drawable-action", drawable_flip_actions, G_N_ELEMENTS (drawable_flip_actions), - G_CALLBACK (drawable_flip_cmd_callback)); + drawable_flip_cmd_callback); gimp_action_group_add_enum_actions (group, "drawable-action", drawable_rotate_actions, G_N_ELEMENTS (drawable_rotate_actions), - G_CALLBACK (drawable_rotate_cmd_callback)); + drawable_rotate_cmd_callback); #define SET_ALWAYS_SHOW_IMAGE(action,show) \ gimp_action_group_set_action_always_show_image (group, action, show) @@ -215,7 +208,6 @@ SET_SENSITIVE ("drawable-equalize", writable && !children); SET_SENSITIVE ("drawable-levels-stretch", writable && !children && is_rgb); - SET_SENSITIVE ("drawable-offset", writable && !children); SET_SENSITIVE ("drawable-visible", drawable); SET_SENSITIVE ("drawable-linked", drawable); diff -Nru gimp-2.10.8+zorin2/app/actions/drawable-commands.c gimp-2.10.14+om/app/actions/drawable-commands.c --- gimp-2.10.8+zorin2/app/actions/drawable-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/drawable-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -27,7 +27,6 @@ #include "core/gimp.h" #include "core/gimpdrawable-equalize.h" #include "core/gimpdrawable-levels.h" -#include "core/gimpdrawable-offset.h" #include "core/gimpdrawable-operation.h" #include "core/gimpimage.h" #include "core/gimpimage-undo.h" @@ -37,7 +36,6 @@ #include "core/gimpprogress.h" #include "dialogs/dialogs.h" -#include "dialogs/offset-dialog.h" #include "actions.h" #include "drawable-commands.h" @@ -45,22 +43,12 @@ #include "gimp-intl.h" -/* local function prototypes */ - -static void drawable_offset_callback (GtkWidget *dialog, - GimpDrawable *drawable, - GimpContext *context, - gboolean wrap_around, - GimpOffsetType fill_type, - gint offset_x, - gint offset_y); - - /* public functions */ void -drawable_equalize_cmd_callback (GtkAction *action, - gpointer data) +drawable_equalize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -71,8 +59,9 @@ } void -drawable_levels_stretch_cmd_callback (GtkAction *action, - gpointer data) +drawable_levels_stretch_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -96,44 +85,16 @@ } void -drawable_offset_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpImage *image; - GimpDrawable *drawable; - GtkWidget *widget; - GtkWidget *dialog; - return_if_no_drawable (image, drawable, data); - return_if_no_widget (widget, data); - -#define OFFSET_DIALOG_KEY "gimp-offset-dialog" - - dialog = dialogs_get_dialog (G_OBJECT (drawable), OFFSET_DIALOG_KEY); - - if (! dialog) - { - dialog = offset_dialog_new (drawable, action_data_get_context (data), - widget, - drawable_offset_callback, - NULL); - - dialogs_attach_dialog (G_OBJECT (drawable), - OFFSET_DIALOG_KEY, dialog); - } - - gtk_window_present (GTK_WINDOW (dialog)); -} - -void -drawable_linked_cmd_callback (GtkAction *action, - gpointer data) +drawable_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; gboolean linked; return_if_no_drawable (image, drawable, data); - linked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + linked = g_variant_get_boolean (value); if (GIMP_IS_LAYER_MASK (drawable)) drawable = @@ -156,15 +117,16 @@ } void -drawable_visible_cmd_callback (GtkAction *action, - gpointer data) +drawable_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; gboolean visible; return_if_no_drawable (image, drawable, data); - visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + visible = g_variant_get_boolean (value); if (GIMP_IS_LAYER_MASK (drawable)) drawable = @@ -187,15 +149,16 @@ } void -drawable_lock_content_cmd_callback (GtkAction *action, - gpointer data) +drawable_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; gboolean locked; return_if_no_drawable (image, drawable, data); - locked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + locked = g_variant_get_boolean (value); if (GIMP_IS_LAYER_MASK (drawable)) drawable = @@ -222,15 +185,16 @@ } void -drawable_lock_position_cmd_callback (GtkAction *action, - gpointer data) +drawable_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; gboolean locked; return_if_no_drawable (image, drawable, data); - locked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + locked = g_variant_get_boolean (value); if (GIMP_IS_LAYER_MASK (drawable)) drawable = @@ -253,24 +217,27 @@ } void -drawable_flip_cmd_callback (GtkAction *action, - gint value, - gpointer data) +drawable_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpDrawable *drawable; - GimpItem *item; - GimpContext *context; - gint off_x, off_y; - gdouble axis = 0.0; + GimpImage *image; + GimpDrawable *drawable; + GimpItem *item; + GimpContext *context; + gint off_x, off_y; + gdouble axis = 0.0; + GimpOrientationType orientation; return_if_no_drawable (image, drawable, data); return_if_no_context (context, data); + orientation = (GimpOrientationType) g_variant_get_int32 (value); + item = GIMP_ITEM (drawable); gimp_item_get_offset (item, &off_x, &off_y); - switch ((GimpOrientationType) value) + switch (orientation) { case GIMP_ORIENTATION_HORIZONTAL: axis = ((gdouble) off_x + (gdouble) gimp_item_get_width (item) / 2.0); @@ -286,33 +253,34 @@ if (gimp_item_get_linked (item)) { - gimp_item_linked_flip (item, context, - (GimpOrientationType) value, axis, FALSE); + gimp_item_linked_flip (item, context, orientation, axis, FALSE); } else { - gimp_item_flip (item, context, - (GimpOrientationType) value, axis, FALSE); + gimp_item_flip (item, context, orientation, axis, + gimp_item_get_clip (item, FALSE)); } gimp_image_flush (image); } void -drawable_rotate_cmd_callback (GtkAction *action, - gint value, - gpointer data) +drawable_rotate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpDrawable *drawable; - GimpContext *context; - GimpItem *item; - gint off_x, off_y; - gdouble center_x, center_y; - gboolean clip_result = FALSE; + GimpImage *image; + GimpDrawable *drawable; + GimpContext *context; + GimpItem *item; + gint off_x, off_y; + gdouble center_x, center_y; + GimpRotationType rotation_type; return_if_no_drawable (image, drawable, data); return_if_no_context (context, data); + rotation_type = (GimpRotationType) g_variant_get_int32 (value); + item = GIMP_ITEM (drawable); gimp_item_get_offset (item, &off_x, &off_y); @@ -320,41 +288,17 @@ center_x = ((gdouble) off_x + (gdouble) gimp_item_get_width (item) / 2.0); center_y = ((gdouble) off_y + (gdouble) gimp_item_get_height (item) / 2.0); - if (GIMP_IS_CHANNEL (item)) - clip_result = TRUE; - if (gimp_item_get_linked (item)) { - gimp_item_linked_rotate (item, context, (GimpRotationType) value, + gimp_item_linked_rotate (item, context, rotation_type, center_x, center_y, FALSE); } else { - gimp_item_rotate (item, context, (GimpRotationType) value, - center_x, center_y, clip_result); + gimp_item_rotate (item, context, + rotation_type, center_x, center_y, + gimp_item_get_clip (item, FALSE)); } gimp_image_flush (image); } - - -/* private functions */ - -static void -drawable_offset_callback (GtkWidget *dialog, - GimpDrawable *drawable, - GimpContext *context, - gboolean wrap_around, - GimpOffsetType fill_type, - gint offset_x, - gint offset_y) -{ - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); - - gimp_drawable_offset (drawable, context, - wrap_around, fill_type, - offset_x, offset_y); - gimp_image_flush (image); - - gtk_widget_destroy (dialog); -} diff -Nru gimp-2.10.8+zorin2/app/actions/drawable-commands.h gimp-2.10.14+om/app/actions/drawable-commands.h --- gimp-2.10.8+zorin2/app/actions/drawable-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/drawable-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,28 +19,32 @@ #define __DRAWABLE_COMMANDS_H__ -void drawable_equalize_cmd_callback (GtkAction *action, - gpointer data); -void drawable_levels_stretch_cmd_callback (GtkAction *action, - gpointer data); -void drawable_offset_cmd_callback (GtkAction *action, - gpointer data); - -void drawable_linked_cmd_callback (GtkAction *action, - gpointer data); -void drawable_visible_cmd_callback (GtkAction *action, - gpointer data); -void drawable_lock_content_cmd_callback (GtkAction *action, - gpointer data); -void drawable_lock_position_cmd_callback (GtkAction *action, - gpointer data); - -void drawable_flip_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void drawable_rotate_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void drawable_equalize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void drawable_levels_stretch_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void drawable_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void drawable_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void drawable_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void drawable_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void drawable_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void drawable_rotate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __DRAWABLE_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/dynamics-actions.c gimp-2.10.14+om/app/actions/dynamics-actions.c --- gimp-2.10.8+zorin2/app/actions/dynamics-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dynamics-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,37 +46,37 @@ { "dynamics-new", GIMP_ICON_DOCUMENT_NEW, NC_("dynamics-action", "_New Dynamics"), NULL, NC_("dynamics-action", "Create a new dynamics"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_DYNAMICS_NEW }, { "dynamics-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("dynamics-action", "D_uplicate Dynamics"), NULL, NC_("dynamics-action", "Duplicate this dynamics"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_DYNAMICS_DUPLICATE }, { "dynamics-copy-location", GIMP_ICON_EDIT_COPY, NC_("dynamics-action", "Copy Dynamics _Location"), NULL, NC_("dynamics-action", "Copy dynamics file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_DYNAMICS_COPY_LOCATION }, { "dynamics-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("dynamics-action", "Show in _File Manager"), NULL, NC_("dynamics-action", "Show dynamics file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_DYNAMICS_SHOW_IN_FILE_MANAGER }, { "dynamics-delete", GIMP_ICON_EDIT_DELETE, NC_("dynamics-action", "_Delete Dynamics"), NULL, NC_("dynamics-action", "Delete this dynamics"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_DYNAMICS_DELETE }, { "dynamics-refresh", GIMP_ICON_VIEW_REFRESH, NC_("dynamics-action", "_Refresh Dynamics"), NULL, NC_("dynamics-action", "Refresh dynamics"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_DYNAMICS_REFRESH } }; @@ -100,7 +100,7 @@ gimp_action_group_add_string_actions (group, "dynamics-action", dynamics_edit_actions, G_N_ELEMENTS (dynamics_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/dynamics-editor-actions.c gimp-2.10.14+om/app/actions/dynamics-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/dynamics-editor-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/dynamics-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -49,7 +49,7 @@ { { "dynamics-editor-edit-active", GIMP_ICON_LINKED, NC_("dynamics-editor-action", "Edit Active Dynamics"), NULL, NULL, - G_CALLBACK (data_editor_edit_active_cmd_callback), + data_editor_edit_active_cmd_callback, FALSE, GIMP_HELP_BRUSH_EDITOR_EDIT_ACTIVE } }; diff -Nru gimp-2.10.8+zorin2/app/actions/edit-actions.c gimp-2.10.14+om/app/actions/edit-actions.c --- gimp-2.10.8+zorin2/app/actions/edit-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/edit-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -27,7 +27,6 @@ #include "core/gimp.h" #include "core/gimpchannel.h" #include "core/gimpcontext.h" -#include "core/gimpdrawableundo.h" #include "core/gimpimage.h" #include "core/gimpimage-undo.h" #include "core/gimplayer.h" @@ -35,6 +34,7 @@ #include "core/gimptoolinfo.h" #include "core/gimpundostack.h" +#include "widgets/gimpaction.h" #include "widgets/gimpactiongroup.h" #include "widgets/gimphelp-ids.h" @@ -73,100 +73,93 @@ { "edit-undo", GIMP_ICON_EDIT_UNDO, NC_("edit-action", "_Undo"), "Z", NC_("edit-action", "Undo the last operation"), - G_CALLBACK (edit_undo_cmd_callback), + edit_undo_cmd_callback, GIMP_HELP_EDIT_UNDO }, { "edit-redo", GIMP_ICON_EDIT_REDO, NC_("edit-action", "_Redo"), "Y", NC_("edit-action", "Redo the last operation that was undone"), - G_CALLBACK (edit_redo_cmd_callback), + edit_redo_cmd_callback, GIMP_HELP_EDIT_REDO }, { "edit-strong-undo", GIMP_ICON_EDIT_UNDO, NC_("edit-action", "Strong Undo"), "Z", NC_("edit-action", "Undo the last operation, skipping visibility changes"), - G_CALLBACK (edit_strong_undo_cmd_callback), + edit_strong_undo_cmd_callback, GIMP_HELP_EDIT_STRONG_UNDO }, { "edit-strong-redo", GIMP_ICON_EDIT_REDO, NC_("edit-action", "Strong Redo"), "Y", NC_("edit-action", "Redo the last operation that was undone, skipping visibility changes"), - G_CALLBACK (edit_strong_redo_cmd_callback), + edit_strong_redo_cmd_callback, GIMP_HELP_EDIT_STRONG_REDO }, { "edit-undo-clear", GIMP_ICON_SHRED, NC_("edit-action", "_Clear Undo History"), NULL, NC_("edit-action", "Remove all operations from the undo history"), - G_CALLBACK (edit_undo_clear_cmd_callback), + edit_undo_clear_cmd_callback, GIMP_HELP_EDIT_UNDO_CLEAR }, - { "edit-fade", GIMP_ICON_EDIT_UNDO, - NC_("edit-action", "_Fade..."), NULL, - NC_("edit-action", - "Modify paint mode and opacity of the last pixel manipulation"), - G_CALLBACK (edit_fade_cmd_callback), - GIMP_HELP_EDIT_FADE }, - { "edit-cut", GIMP_ICON_EDIT_CUT, NC_("edit-action", "Cu_t"), "X", NC_("edit-action", "Move the selected pixels to the clipboard"), - G_CALLBACK (edit_cut_cmd_callback), + edit_cut_cmd_callback, GIMP_HELP_EDIT_CUT }, { "edit-copy", GIMP_ICON_EDIT_COPY, NC_("edit-action", "_Copy"), "C", NC_("edit-action", "Copy the selected pixels to the clipboard"), - G_CALLBACK (edit_copy_cmd_callback), + edit_copy_cmd_callback, GIMP_HELP_EDIT_COPY }, { "edit-copy-visible", NULL, /* GIMP_ICON_COPY_VISIBLE, */ NC_("edit-action", "Copy _Visible"), "C", NC_("edit-action", "Copy what is visible in the selected region"), - G_CALLBACK (edit_copy_visible_cmd_callback), + edit_copy_visible_cmd_callback, GIMP_HELP_EDIT_COPY_VISIBLE }, { "edit-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW, NC_("edit-action", "From _Clipboard"), "V", NC_("edit-action", "Create a new image from the content of the clipboard"), - G_CALLBACK (edit_paste_as_new_image_cmd_callback), + edit_paste_as_new_image_cmd_callback, GIMP_HELP_EDIT_PASTE_AS_NEW_IMAGE }, { "edit-paste-as-new-image-short", GIMP_ICON_EDIT_PASTE_AS_NEW, NC_("edit-action", "_New Image"), NULL, NC_("edit-action", "Create a new image from the content of the clipboard"), - G_CALLBACK (edit_paste_as_new_image_cmd_callback), + edit_paste_as_new_image_cmd_callback, GIMP_HELP_EDIT_PASTE_AS_NEW_IMAGE }, { "edit-named-cut", GIMP_ICON_EDIT_CUT, NC_("edit-action", "Cu_t Named..."), NULL, NC_("edit-action", "Move the selected pixels to a named buffer"), - G_CALLBACK (edit_named_cut_cmd_callback), + edit_named_cut_cmd_callback, GIMP_HELP_BUFFER_CUT }, { "edit-named-copy", GIMP_ICON_EDIT_COPY, NC_("edit-action", "_Copy Named..."), NULL, NC_("edit-action", "Copy the selected pixels to a named buffer"), - G_CALLBACK (edit_named_copy_cmd_callback), + edit_named_copy_cmd_callback, GIMP_HELP_BUFFER_COPY }, { "edit-named-copy-visible", NULL, /* GIMP_ICON_COPY_VISIBLE, */ NC_("edit-action", "Copy _Visible Named..."), "", NC_("edit-action", "Copy what is visible in the selected region to a named buffer"), - G_CALLBACK (edit_named_copy_visible_cmd_callback), + edit_named_copy_visible_cmd_callback, GIMP_HELP_BUFFER_COPY }, { "edit-named-paste", GIMP_ICON_EDIT_PASTE, NC_("edit-action", "_Paste Named..."), NULL, NC_("edit-action", "Paste the content of a named buffer"), - G_CALLBACK (edit_named_paste_cmd_callback), + edit_named_paste_cmd_callback, GIMP_HELP_BUFFER_PASTE }, { "edit-clear", GIMP_ICON_EDIT_CLEAR, NC_("edit-action", "Cl_ear"), "Delete", NC_("edit-action", "Clear the selected pixels"), - G_CALLBACK (edit_clear_cmd_callback), + edit_clear_cmd_callback, GIMP_HELP_EDIT_CLEAR } }; @@ -179,7 +172,7 @@ GIMP_HELP_EDIT_PASTE }, { "edit-paste-in-place", GIMP_ICON_EDIT_PASTE, - NC_("edit-action", "Paste In Place"), "V", + NC_("edit-action", "Paste In P_lace"), "V", NC_("edit-action", "Paste the content of the clipboard at its original position"), GIMP_PASTE_TYPE_FLOATING_IN_PLACE, FALSE, @@ -193,7 +186,7 @@ GIMP_HELP_EDIT_PASTE_INTO }, { "edit-paste-into-in-place", GIMP_ICON_EDIT_PASTE_INTO, - NC_("edit-action", "Paste Into Selection In Place"), NULL, + NC_("edit-action", "Paste Int_o Selection In Place"), NULL, NC_("edit-action", "Paste the content of the clipboard into the current selection " "at its original position"), @@ -243,7 +236,7 @@ GimpContext *context = gimp_get_user_context (group->gimp); GimpRGB color; GimpPattern *pattern; - GtkAction *action; + GimpAction *action; gimp_action_group_add_actions (group, "edit-action", edit_actions, @@ -252,16 +245,17 @@ gimp_action_group_add_enum_actions (group, "edit-action", edit_paste_actions, G_N_ELEMENTS (edit_paste_actions), - G_CALLBACK (edit_paste_cmd_callback)); + edit_paste_cmd_callback); gimp_action_group_add_enum_actions (group, "edit-action", edit_fill_actions, G_N_ELEMENTS (edit_fill_actions), - G_CALLBACK (edit_fill_cmd_callback)); + edit_fill_cmd_callback); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - "edit-paste-as-new-image-short"); - gtk_action_set_accel_path (action, "/edit/edit-paste-as-new-image"); + action = gimp_action_group_get_action (group, + "edit-paste-as-new-image-short"); + gimp_action_set_accel_path (action, + "/edit/edit-paste-as-new-image"); gimp_action_group_set_action_context (group, "edit-fill-fg", context); gimp_action_group_set_action_context (group, "edit-fill-bg", context); @@ -305,11 +299,9 @@ GimpDrawable *drawable = NULL; gchar *undo_name = NULL; gchar *redo_name = NULL; - gchar *fade_name = NULL; gboolean writable = FALSE; gboolean children = FALSE; gboolean undo_enabled = FALSE; - gboolean fade_enabled = FALSE; if (image) { @@ -351,21 +343,6 @@ else if (redo) redo_name = g_strdup_printf (_("_Redo %s"), gimp_object_get_name (redo)); - - undo = gimp_image_undo_get_fadeable (image); - - if (GIMP_IS_DRAWABLE_UNDO (undo) && - GIMP_DRAWABLE_UNDO (undo)->applied_buffer) - { - fade_enabled = TRUE; - } - - if (fade_enabled) - { - fade_name = - g_strdup_printf (_("_Fade %s..."), - gimp_object_get_name (undo)); - } } } @@ -377,18 +354,15 @@ SET_LABEL ("edit-undo", undo_name ? undo_name : _("_Undo")); SET_LABEL ("edit-redo", redo_name ? redo_name : _("_Redo")); - SET_LABEL ("edit-fade", fade_name ? fade_name : _("_Fade...")); SET_SENSITIVE ("edit-undo", undo_enabled && undo_name); SET_SENSITIVE ("edit-redo", undo_enabled && redo_name); SET_SENSITIVE ("edit-strong-undo", undo_enabled && undo_name); SET_SENSITIVE ("edit-strong-redo", undo_enabled && redo_name); SET_SENSITIVE ("edit-undo-clear", undo_enabled && (undo_name || redo_name)); - SET_SENSITIVE ("edit-fade", fade_enabled && fade_name); g_free (undo_name); g_free (redo_name); - g_free (fade_name); SET_SENSITIVE ("edit-cut", writable && !children); SET_SENSITIVE ("edit-copy", drawable); diff -Nru gimp-2.10.8+zorin2/app/actions/edit-commands.c gimp-2.10.14+om/app/actions/edit-commands.c --- gimp-2.10.8+zorin2/app/actions/edit-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/edit-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -53,10 +53,9 @@ #include "display/gimpdisplayshell.h" #include "display/gimpdisplayshell-transform.h" +#include "tools/gimptools-utils.h" #include "tools/tool_manager.h" -#include "dialogs/fade-dialog.h" - #include "actions.h" #include "edit-commands.h" @@ -65,25 +64,28 @@ /* local function prototypes */ -static void edit_paste (GimpDisplay *display, - GimpPasteType paste_type, - gboolean try_svg); -static void cut_named_buffer_callback (GtkWidget *widget, - const gchar *name, - gpointer data); -static void copy_named_buffer_callback (GtkWidget *widget, - const gchar *name, - gpointer data); -static void copy_named_visible_buffer_callback (GtkWidget *widget, - const gchar *name, - gpointer data); +static gboolean check_drawable_alpha (GimpDrawable *drawable, + gpointer data); +static void edit_paste (GimpDisplay *display, + GimpPasteType paste_type, + gboolean try_svg); +static void cut_named_buffer_callback (GtkWidget *widget, + const gchar *name, + gpointer data); +static void copy_named_buffer_callback (GtkWidget *widget, + const gchar *name, + gpointer data); +static void copy_named_visible_buffer_callback (GtkWidget *widget, + const gchar *name, + gpointer data); /* public functions */ void -edit_undo_cmd_callback (GtkAction *action, - gpointer data) +edit_undo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; @@ -98,8 +100,9 @@ } void -edit_redo_cmd_callback (GtkAction *action, - gpointer data) +edit_redo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; @@ -114,8 +117,9 @@ } void -edit_strong_undo_cmd_callback (GtkAction *action, - gpointer data) +edit_strong_undo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -125,8 +129,9 @@ } void -edit_strong_redo_cmd_callback (GtkAction *action, - gpointer data) +edit_strong_redo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -136,8 +141,9 @@ } void -edit_undo_clear_cmd_callback (GtkAction *action, - gpointer data) +edit_undo_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpUndoStack *undo_stack; @@ -205,29 +211,9 @@ } void -edit_fade_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpImage *image; - GtkWidget *widget; - GtkWidget *dialog; - return_if_no_image (image, data); - return_if_no_widget (widget, data); - - dialog = fade_dialog_new (image, widget); - - if (dialog) - { - g_signal_connect_object (image, "disconnect", - G_CALLBACK (gtk_widget_destroy), - dialog, G_CONNECT_SWAPPED); - gtk_widget_show (dialog); - } -} - -void -edit_cut_cmd_callback (GtkAction *action, - gpointer data) +edit_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -235,6 +221,9 @@ GError *error = NULL; return_if_no_drawable (image, drawable, data); + if (! check_drawable_alpha (drawable, data)) + return; + cut = gimp_edit_cut (image, drawable, action_data_get_context (data), &error); @@ -262,8 +251,9 @@ } void -edit_copy_cmd_callback (GtkAction *action, - gpointer data) +edit_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -298,8 +288,9 @@ } void -edit_copy_visible_cmd_callback (GtkAction *action, - gpointer data) +edit_copy_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GError *error = NULL; @@ -327,18 +318,18 @@ } void -edit_paste_cmd_callback (GtkAction *action, - gint value, - gpointer data) +edit_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display = action_data_get_display (data); - GimpPasteType paste_type = (GimpPasteType) value; + GimpPasteType paste_type = (GimpPasteType) g_variant_get_int32 (value); if (paste_type == GIMP_PASTE_TYPE_FLOATING) { if (! display || ! gimp_display_get_image (display)) { - edit_paste_as_new_image_cmd_callback (action, data); + edit_paste_as_new_image_cmd_callback (action, value, data); return; } } @@ -363,8 +354,9 @@ } void -edit_paste_as_new_image_cmd_callback (GtkAction *action, - gpointer data) +edit_paste_as_new_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GtkWidget *widget; @@ -397,8 +389,9 @@ } void -edit_named_cut_cmd_callback (GtkAction *action, - gpointer data) +edit_named_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -417,8 +410,9 @@ } void -edit_named_copy_cmd_callback (GtkAction *action, - gpointer data) +edit_named_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -437,8 +431,9 @@ } void -edit_named_copy_visible_cmd_callback (GtkAction *action, - gpointer data) +edit_named_copy_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -457,8 +452,9 @@ } void -edit_named_paste_cmd_callback (GtkAction *action, - gpointer data) +edit_named_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GtkWidget *widget; @@ -474,21 +470,25 @@ } void -edit_clear_cmd_callback (GtkAction *action, - gpointer data) +edit_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; return_if_no_drawable (image, drawable, data); + if (! check_drawable_alpha (drawable, data)) + return; + gimp_drawable_edit_clear (drawable, action_data_get_context (data)); gimp_image_flush (image); } void -edit_fill_cmd_callback (GtkAction *action, - gint value, - gpointer data) +edit_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -497,7 +497,7 @@ GError *error = NULL; return_if_no_drawable (image, drawable, data); - fill_type = (GimpFillType) value; + fill_type = (GimpFillType) g_variant_get_int32 (value); options = gimp_fill_options_new (action_data_get_gimp (data), NULL, FALSE); @@ -521,6 +521,32 @@ /* private functions */ +static gboolean +check_drawable_alpha (GimpDrawable *drawable, + gpointer data) +{ + if (gimp_drawable_has_alpha (drawable) && + GIMP_IS_LAYER (drawable) && + gimp_layer_get_lock_alpha (GIMP_LAYER (drawable))) + { + Gimp *gimp = action_data_get_gimp (data); + GimpDisplay *display = action_data_get_display (data); + + if (gimp && display) + { + gimp_message_literal ( + gimp, G_OBJECT (display), GIMP_MESSAGE_WARNING, + _("The active layer's alpha channel is locked.")); + + gimp_tools_blink_lock_box (gimp, GIMP_ITEM (drawable)); + } + + return FALSE; + } + + return TRUE; +} + static void edit_paste (GimpDisplay *display, GimpPasteType paste_type, @@ -583,7 +609,10 @@ /* the actual paste-type conversion happens in gimp_edit_paste() */ } - gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); + gimp_display_shell_untransform_viewport ( + shell, + ! gimp_display_shell_get_infinite_canvas (shell), + &x, &y, &width, &height); if (gimp_edit_paste (image, drawable, paste, paste_type, x, y, width, height)) diff -Nru gimp-2.10.8+zorin2/app/actions/edit-commands.h gimp-2.10.14+om/app/actions/edit-commands.h --- gimp-2.10.8+zorin2/app/actions/edit-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/edit-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,47 +19,58 @@ #define __EDIT_COMMANDS_H__ -void edit_undo_cmd_callback (GtkAction *action, - gpointer data); -void edit_redo_cmd_callback (GtkAction *action, - gpointer data); -void edit_strong_undo_cmd_callback (GtkAction *action, - gpointer data); -void edit_strong_redo_cmd_callback (GtkAction *action, - gpointer data); -void edit_undo_clear_cmd_callback (GtkAction *action, - gpointer data); - -void edit_fade_cmd_callback (GtkAction *action, - gpointer data); - -void edit_cut_cmd_callback (GtkAction *action, - gpointer data); -void edit_copy_cmd_callback (GtkAction *action, - gpointer data); -void edit_copy_visible_cmd_callback (GtkAction *action, - gpointer data); - -void edit_paste_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void edit_paste_as_new_image_cmd_callback (GtkAction *action, - gpointer data); - -void edit_named_cut_cmd_callback (GtkAction *action, - gpointer data); -void edit_named_copy_cmd_callback (GtkAction *action, - gpointer data); -void edit_named_copy_visible_cmd_callback (GtkAction *action, - gpointer data); -void edit_named_paste_cmd_callback (GtkAction *action, - gpointer data); - -void edit_clear_cmd_callback (GtkAction *action, - gpointer data); -void edit_fill_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void edit_undo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_redo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_strong_undo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_strong_redo_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_undo_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void edit_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_copy_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void edit_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_paste_as_new_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void edit_named_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_named_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_named_copy_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_named_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void edit_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void edit_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __EDIT_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/error-console-actions.c gimp-2.10.14+om/app/actions/error-console-actions.c --- gimp-2.10.8+zorin2/app/actions/error-console-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/error-console-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -43,13 +43,13 @@ { "error-console-clear", GIMP_ICON_EDIT_CLEAR, NC_("error-console-action", "_Clear"), NULL, NC_("error-console-action", "Clear error console"), - G_CALLBACK (error_console_clear_cmd_callback), + error_console_clear_cmd_callback, GIMP_HELP_ERRORS_CLEAR }, { "error-console-select-all", NULL, NC_("error-console-action", "Select _All"), "", NC_("error-console-action", "Select all error messages"), - G_CALLBACK (error_console_select_all_cmd_callback), + error_console_select_all_cmd_callback, GIMP_HELP_ERRORS_SELECT_ALL }, { "error-console-highlight", NULL, @@ -77,21 +77,21 @@ { "error-console-highlight-error", NULL, NC_("error-console-action", "_Errors"), NULL, NC_("error-console-action", "Highlight error console on errors"), - G_CALLBACK (error_console_highlight_error_cmd_callback), + error_console_highlight_error_cmd_callback, FALSE, GIMP_HELP_ERRORS_HIGHLIGHT }, { "error-console-highlight-warning", NULL, NC_("error-console-action", "_Warnings"), NULL, NC_("error-console-action", "Highlight error console on warnings"), - G_CALLBACK (error_console_highlight_warning_cmd_callback), + error_console_highlight_warning_cmd_callback, FALSE, GIMP_HELP_ERRORS_HIGHLIGHT }, { "error-console-highlight-info", NULL, NC_("error-console-action", "_Messages"), NULL, NC_("error-console-action", "Highlight error console on messages"), - G_CALLBACK (error_console_highlight_info_cmd_callback), + error_console_highlight_info_cmd_callback, FALSE, GIMP_HELP_ERRORS_HIGHLIGHT } }; @@ -107,7 +107,7 @@ gimp_action_group_add_enum_actions (group, "error-console-action", error_console_save_actions, G_N_ELEMENTS (error_console_save_actions), - G_CALLBACK (error_console_save_cmd_callback)); + error_console_save_cmd_callback); gimp_action_group_add_toggle_actions (group, "error-console-action", error_console_highlight_actions, diff -Nru gimp-2.10.8+zorin2/app/actions/error-console-commands.c gimp-2.10.14+om/app/actions/error-console-commands.c --- gimp-2.10.8+zorin2/app/actions/error-console-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/error-console-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,8 +46,9 @@ /* public functions */ void -error_console_clear_cmd_callback (GtkAction *action, - gpointer data) +error_console_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); GtkTextIter start_iter; @@ -58,8 +59,9 @@ } void -error_console_select_all_cmd_callback (GtkAction *action, - gpointer data) +error_console_select_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); GtkTextIter start_iter; @@ -70,14 +72,16 @@ } void -error_console_save_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); - - if (value && ! gtk_text_buffer_get_selection_bounds (console->text_buffer, - NULL, NULL)) +error_console_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); + gboolean selection = (gboolean) g_variant_get_int32 (value); + + if (selection && + ! gtk_text_buffer_get_selection_bounds (console->text_buffer, + NULL, NULL)) { gimp_message_literal (console->gimp, G_OBJECT (console), GIMP_MESSAGE_WARNING, @@ -104,7 +108,7 @@ GTK_RESPONSE_CANCEL, -1); - console->save_selection = value; + console->save_selection = selection; g_object_add_weak_pointer (G_OBJECT (dialog), (gpointer) &console->file_dialog); @@ -132,37 +136,34 @@ } void -error_console_highlight_error_cmd_callback (GtkAction *action, - gpointer data) +error_console_highlight_error_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); console->highlight[GIMP_MESSAGE_ERROR] = active; } void -error_console_highlight_warning_cmd_callback (GtkAction *action, - gpointer data) +error_console_highlight_warning_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); console->highlight[GIMP_MESSAGE_WARNING] = active; } void -error_console_highlight_info_cmd_callback (GtkAction *action, - gpointer data) +error_console_highlight_info_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpErrorConsole *console = GIMP_ERROR_CONSOLE (data); - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); console->highlight[GIMP_MESSAGE_INFO] = active; } diff -Nru gimp-2.10.8+zorin2/app/actions/error-console-commands.h gimp-2.10.14+om/app/actions/error-console-commands.h --- gimp-2.10.8+zorin2/app/actions/error-console-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/error-console-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,20 +19,25 @@ #define __ERROR_CONSOLE_COMMANDS_H__ -void error_console_clear_cmd_callback (GtkAction *action, - gpointer data); -void error_console_select_all_cmd_callback (GtkAction *action, - gpointer data); -void error_console_save_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void error_console_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void error_console_select_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void error_console_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void error_console_highlight_error_cmd_callback (GtkAction *action, - gpointer data); -void error_console_highlight_warning_cmd_callback (GtkAction *action, - gpointer data); -void error_console_highlight_info_cmd_callback (GtkAction *action, - gpointer data); +void error_console_highlight_error_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void error_console_highlight_warning_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void error_console_highlight_info_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __ERROR_CONSOLE_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/file-actions.c gimp-2.10.14+om/app/actions/file-actions.c --- gimp-2.10.8+zorin2/app/actions/file-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/file-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -39,6 +39,7 @@ #include "widgets/gimpaction.h" #include "widgets/gimpactiongroup.h" +#include "widgets/gimpactionimpl.h" #include "widgets/gimphelp-ids.h" #include "display/gimpdisplay.h" @@ -75,55 +76,55 @@ { "file-open", GIMP_ICON_IMAGE_OPEN, NC_("file-action", "_Open..."), "O", NC_("file-action", "Open an image file"), - G_CALLBACK (file_open_cmd_callback), + file_open_cmd_callback, GIMP_HELP_FILE_OPEN }, { "file-open-as-layers", GIMP_ICON_LAYER, NC_("file-action", "Op_en as Layers..."), "O", NC_("file-action", "Open an image file as layers"), - G_CALLBACK (file_open_as_layers_cmd_callback), + file_open_as_layers_cmd_callback, GIMP_HELP_FILE_OPEN_AS_LAYER }, { "file-open-location", GIMP_ICON_WEB, NC_("file-action", "Open _Location..."), NULL, NC_("file-action", "Open an image file from a specified location"), - G_CALLBACK (file_open_location_cmd_callback), + file_open_location_cmd_callback, GIMP_HELP_FILE_OPEN_LOCATION }, { "file-create-template", NULL, - NC_("file-action", "Create Template..."), NULL, + NC_("file-action", "Create _Template..."), NULL, NC_("file-action", "Create a new template from this image"), - G_CALLBACK (file_create_template_cmd_callback), + file_create_template_cmd_callback, GIMP_HELP_FILE_CREATE_TEMPLATE }, { "file-revert", GIMP_ICON_IMAGE_RELOAD, NC_("file-action", "Re_vert"), NULL, NC_("file-action", "Reload the image file from disk"), - G_CALLBACK (file_revert_cmd_callback), + file_revert_cmd_callback, GIMP_HELP_FILE_REVERT }, { "file-close-all", GIMP_ICON_CLOSE_ALL, - NC_("file-action", "Close all"), "W", + NC_("file-action", "C_lose All"), "W", NC_("file-action", "Close all opened images"), - G_CALLBACK (file_close_all_cmd_callback), + file_close_all_cmd_callback, GIMP_HELP_FILE_CLOSE_ALL }, { "file-copy-location", GIMP_ICON_EDIT_COPY, NC_("file-action", "Copy _Image Location"), NULL, NC_("file-action", "Copy image file location to clipboard"), - G_CALLBACK (file_copy_location_cmd_callback), + file_copy_location_cmd_callback, GIMP_HELP_FILE_COPY_LOCATION }, { "file-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("file-action", "Show in _File Manager"), "F", NC_("file-action", "Show image file location in the file manager"), - G_CALLBACK (file_show_in_file_manager_cmd_callback), + file_show_in_file_manager_cmd_callback, GIMP_HELP_FILE_SHOW_IN_FILE_MANAGER }, { "file-quit", GIMP_ICON_APPLICATION_EXIT, NC_("file-action", "_Quit"), "Q", NC_("file-action", "Quit the GNU Image Manipulation Program"), - G_CALLBACK (file_quit_cmd_callback), + file_quit_cmd_callback, GIMP_HELP_FILE_QUIT } }; @@ -156,7 +157,7 @@ GIMP_HELP_FILE_SAVE }, { "file-export", NULL, - NC_("file-action", "Export..."), "E", + NC_("file-action", "E_xport..."), "E", NC_("file-action", "Export the image"), GIMP_SAVE_MODE_EXPORT, FALSE, GIMP_HELP_FILE_EXPORT }, @@ -168,7 +169,7 @@ GIMP_HELP_FILE_OVERWRITE }, { "file-export-as", NULL, - NC_("file-action", "Export As..."), "E", + NC_("file-action", "E_xport As..."), "E", NC_("file-action", "Export the image to various file formats such as PNG or JPEG"), GIMP_SAVE_MODE_EXPORT_AS, FALSE, GIMP_HELP_FILE_EXPORT_AS } @@ -188,7 +189,7 @@ gimp_action_group_add_enum_actions (group, "file-action", file_save_actions, G_N_ELEMENTS (file_save_actions), - G_CALLBACK (file_save_cmd_callback)); + file_save_cmd_callback); n_entries = GIMP_GUI_CONFIG (group->gimp->config)->last_opened_size; @@ -213,7 +214,7 @@ } gimp_action_group_add_enum_actions (group, NULL, entries, n_entries, - G_CALLBACK (file_open_recent_cmd_callback)); + file_open_recent_cmd_callback); for (i = 0; i < n_entries; i++) { @@ -330,7 +331,7 @@ { gimp_action_group_set_action_label (group, "file-export", - C_("file-action", "Export...")); + C_("file-action", "E_xport...")); } /* needed for the empty display */ @@ -355,17 +356,17 @@ for (i = 0; i < n; i++) { - GtkAction *action; - gchar *name = g_strdup_printf ("file-open-recent-%02d", i + 1); + GimpAction *action; + gchar *name = g_strdup_printf ("file-open-recent-%02d", i + 1); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), name); + action = gimp_action_group_get_action (group, name); if (i < num_documents) { GimpImagefile *imagefile = (GimpImagefile *) gimp_container_get_child_by_index (container, i); - if (GIMP_ACTION (action)->viewable != (GimpViewable *) imagefile) + if (GIMP_ACTION_IMPL (action)->viewable != (GimpViewable *) imagefile) { GFile *file; const gchar *name; diff -Nru gimp-2.10.8+zorin2/app/actions/file-commands.c gimp-2.10.14+om/app/actions/file-commands.c --- gimp-2.10.8+zorin2/app/actions/file-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/file-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -103,8 +103,9 @@ void -file_open_cmd_callback (GtkAction *action, - gpointer data) +file_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GtkWidget *widget; @@ -120,8 +121,9 @@ } void -file_open_as_layers_cmd_callback (GtkAction *action, - gpointer data) +file_open_as_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GtkWidget *widget; @@ -141,8 +143,9 @@ } void -file_open_location_cmd_callback (GtkAction *action, - gpointer data) +file_open_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; return_if_no_widget (widget, data); @@ -155,22 +158,25 @@ } void -file_open_recent_cmd_callback (GtkAction *action, - gint value, - gpointer data) +file_open_recent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpImagefile *imagefile; + gint index; gint num_entries; return_if_no_gimp (gimp, data); + index = g_variant_get_int32 (value); + num_entries = gimp_container_get_n_children (gimp->documents); - if (value >= num_entries) + if (index >= num_entries) return; imagefile = (GimpImagefile *) - gimp_container_get_child_by_index (gimp->documents, value); + gimp_container_get_child_by_index (gimp->documents, index); if (imagefile) { @@ -213,9 +219,9 @@ } void -file_save_cmd_callback (GtkAction *action, - gint value, - gpointer data) +file_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpDisplay *display; @@ -230,7 +236,7 @@ image = gimp_display_get_image (display); - save_mode = (GimpSaveMode) value; + save_mode = (GimpSaveMode) g_variant_get_int32 (value); if (! gimp_image_get_active_drawable (image)) return; @@ -354,8 +360,9 @@ } void -file_create_template_cmd_callback (GtkAction *action, - gpointer data) +file_create_template_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -376,8 +383,9 @@ } void -file_revert_cmd_callback (GtkAction *action, - gpointer data) +file_revert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -448,8 +456,9 @@ } void -file_close_all_cmd_callback (GtkAction *action, - gpointer data) +file_close_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; return_if_no_gimp (gimp, data); @@ -471,8 +480,9 @@ } void -file_copy_location_cmd_callback (GtkAction *action, - gpointer data) +file_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpDisplay *display; @@ -495,8 +505,9 @@ } void -file_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer data) +file_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpDisplay *display; @@ -524,8 +535,9 @@ } void -file_quit_cmd_callback (GtkAction *action, - gpointer data) +file_quit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; return_if_no_gimp (gimp, data); diff -Nru gimp-2.10.8+zorin2/app/actions/file-commands.h gimp-2.10.14+om/app/actions/file-commands.h --- gimp-2.10.8+zorin2/app/actions/file-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/file-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,36 +19,45 @@ #define __FILE_COMMANDS_H__ -void file_open_cmd_callback (GtkAction *action, - gpointer data); -void file_open_as_layers_cmd_callback (GtkAction *action, - gpointer data); -void file_open_location_cmd_callback (GtkAction *action, - gpointer data); -void file_open_recent_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void file_save_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void file_create_template_cmd_callback (GtkAction *action, - gpointer data); - -void file_revert_cmd_callback (GtkAction *action, - gpointer data); -void file_close_all_cmd_callback (GtkAction *action, - gpointer data); -void file_copy_location_cmd_callback (GtkAction *action, - gpointer data); -void file_show_in_file_manager_cmd_callback (GtkAction *action, - gpointer data); -void file_quit_cmd_callback (GtkAction *action, - gpointer data); - -void file_file_open_dialog (Gimp *gimp, - GFile *file, - GtkWidget *parent); +void file_open_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_open_as_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_open_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_open_recent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void file_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_create_template_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void file_revert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_close_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_copy_location_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_show_in_file_manager_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void file_quit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void file_file_open_dialog (Gimp *gimp, + GFile *file, + GtkWidget *parent); #endif /* __FILE_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/filters-actions.c gimp-2.10.14+om/app/actions/filters-actions.c --- gimp-2.10.8+zorin2/app/actions/filters-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/filters-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,6 +30,7 @@ #include "pdb/gimpprocedure.h" +#include "widgets/gimpaction.h" #include "widgets/gimpactiongroup.h" #include "widgets/gimphelp-ids.h" #include "widgets/gimpuimanager.h" @@ -57,7 +58,7 @@ { "filters-menu", NULL, NC_("filters-action", "Filte_rs") }, { "filters-recent-menu", NULL, NC_("filters-action", - "Recently Used") }, + "Recently _Used") }, { "filters-blur-menu", NULL, NC_("filters-action", "_Blur") }, { "filters-noise-menu", NULL, NC_("filters-action", @@ -111,7 +112,7 @@ GIMP_HELP_FILTER_COLOR_ENHANCE }, { "filters-invert-linear", GIMP_ICON_INVERT, - NC_("filters-action", "_Linear Invert"), NULL, NULL, + NC_("filters-action", "L_inear Invert"), NULL, NULL, "gegl:invert-linear", GIMP_HELP_FILTER_INVERT_LINEAR }, @@ -135,7 +136,7 @@ { { "filters-dilate", GIMP_ICON_GEGL, NC_("filters-action", "_Dilate"), NULL, - NC_("drawable-action", "Grow lighter areas of the image"), + NC_("filters-action", "Grow lighter areas of the image"), "gegl:value-propagate\n" "(mode white)" "(lower-threshold 0.000000)" @@ -151,7 +152,7 @@ { "filters-erode", GIMP_ICON_GEGL, NC_("filters-action", "_Erode"), NULL, - NC_("drawable-action", "Grow darker areas of the image"), + NC_("filters-action", "Grow darker areas of the image"), "gegl:value-propagate\n" "(mode black)" "(lower-threshold 0.000000)" @@ -183,6 +184,11 @@ "gegl:apply-lens", GIMP_HELP_FILTER_APPLY_LENS }, + { "filters-bayer-matrix", GIMP_ICON_GEGL, + NC_("filters-action", "_Bayer Matrix..."), NULL, NULL, + "gegl:bayer-matrix", + GIMP_HELP_FILTER_BAYER_MATRIX }, + { "filters-brightness-contrast", GIMP_ICON_TOOL_BRIGHTNESS_CONTRAST, NC_("filters-action", "B_rightness-Contrast..."), NULL, NULL, "gimp:brightness-contrast", @@ -279,22 +285,22 @@ GIMP_HELP_FILTER_DESATURATE }, { "filters-difference-of-gaussians", GIMP_ICON_GEGL, - NC_("filters-action", "Difference of Gaussians..."), NULL, NULL, + NC_("filters-action", "Difference of _Gaussians..."), NULL, NULL, "gegl:difference-of-gaussians", GIMP_HELP_FILTER_DIFFERENCE_OF_GAUSSIANS }, { "filters-diffraction-patterns", GIMP_ICON_GEGL, - NC_("filters-action", "Diffraction Patterns..."), NULL, NULL, + NC_("filters-action", "D_iffraction Patterns..."), NULL, NULL, "gegl:diffraction-patterns", GIMP_HELP_FILTER_DIFFRACTION_PATTERNS }, { "filters-displace", GIMP_ICON_GEGL, - NC_("filters-action", "Displace..."), NULL, NULL, + NC_("filters-action", "_Displace..."), NULL, NULL, "gegl:displace", GIMP_HELP_FILTER_DISPLACE }, { "filters-distance-map", GIMP_ICON_GEGL, - NC_("filters-action", "Distance Map..."), NULL, NULL, + NC_("filters-action", "Distance _Map..."), NULL, NULL, "gegl:distance-transform", GIMP_HELP_FILTER_DISTANCE_MAP }, @@ -399,12 +405,12 @@ GIMP_HELP_FILTER_KALEIDOSCOPE }, { "filters-lens-distortion", GIMP_ICON_GEGL, - NC_("filters-action", "Lens Distortion..."), NULL, NULL, + NC_("filters-action", "Le_ns Distortion..."), NULL, NULL, "gegl:lens-distortion", GIMP_HELP_FILTER_LENS_DISTORTION }, { "filters-lens-flare", GIMP_ICON_GEGL, - NC_("filters-action", "Lens Flare..."), NULL, NULL, + NC_("filters-action", "Lens _Flare..."), NULL, NULL, "gegl:lens-flare", GIMP_HELP_FILTER_LENS_FLARE }, @@ -413,6 +419,11 @@ "gimp:levels", GIMP_HELP_TOOL_LEVELS }, + { "filters-linear-sinusoid", GIMP_ICON_TOOL_LEVELS, + NC_("filters-action", "_Linear Sinusoid..."), NULL, NULL, + "gegl:linear-sinusoid", + GIMP_HELP_FILTER_LINEAR_SINUSOID }, + { "filters-little-planet", GIMP_ICON_GEGL, NC_("filters-action", "_Little Planet..."), NULL, NULL, "gegl:stereographic-projection", @@ -433,6 +444,11 @@ "gegl:maze", GIMP_HELP_FILTER_MAZE }, + { "filters-mean-curvature-blur", GIMP_ICON_GEGL, + NC_("filters-action", "Mean C_urvature Blur..."), NULL, NULL, + "gegl:mean-curvature-blur", + GIMP_HELP_FILTER_MEAN_CURVATURE_BLUR }, + { "filters-median-blur", GIMP_ICON_GEGL, NC_("filters-action", "_Median Blur..."), NULL, NULL, "gegl:median-blur", @@ -468,13 +484,18 @@ "gegl:cell-noise", GIMP_HELP_FILTER_NOISE_CELL }, + { "filters-newsprint", GIMP_ICON_GEGL, + NC_("filters-action", "_Newsprint..."), NULL, NULL, + "gegl:newsprint", + GIMP_HELP_FILTER_NEWSPRINT }, + { "filters-noise-cie-lch", GIMP_ICON_GEGL, - NC_("filters-action", "CIE lch Noise..."), NULL, NULL, + NC_("filters-action", "_CIE lch Noise..."), NULL, NULL, "gegl:noise-cie-lch", GIMP_HELP_FILTER_NOISE_CIE_LCH }, { "filters-noise-hsv", GIMP_ICON_GEGL, - NC_("filters-action", "HSV Noise..."), NULL, NULL, + NC_("filters-action", "HS_V Noise..."), NULL, NULL, "gegl:noise-hsv", GIMP_HELP_FILTER_NOISE_HSV }, @@ -484,7 +505,7 @@ GIMP_HELP_FILTER_NOISE_HURL }, { "filters-noise-perlin", GIMP_ICON_GEGL, - NC_("filters-action", "_Perlin Noise..."), NULL, NULL, + NC_("filters-action", "Perlin _Noise..."), NULL, NULL, "gegl:perlin-noise", GIMP_HELP_FILTER_NOISE_PERLIN }, @@ -523,6 +544,16 @@ "gegl:noise-spread", GIMP_HELP_FILTER_NOISE_SPREAD }, + { "filters-normal-map", GIMP_ICON_GEGL, + NC_("filters-action", "_Normal Map..."), NULL, NULL, + "gegl:normal-map", + GIMP_HELP_FILTER_NORMAL_MAP }, + + { "filters-offset", GIMP_ICON_TOOL_OFFSET, + NC_("filters-action", "_Offset..."), "O", NULL, + "gimp:offset", + GIMP_HELP_TOOL_OFFSET }, + { "filters-oilify", GIMP_ICON_GEGL, NC_("filters-action", "Oili_fy..."), NULL, NULL, "gegl:oilify", @@ -750,28 +781,28 @@ gimp_action_group_add_string_actions (group, "filters-action", filters_actions, G_N_ELEMENTS (filters_actions), - G_CALLBACK (filters_apply_cmd_callback)); + filters_apply_cmd_callback); filters_actions_set_tooltips (group, filters_actions, G_N_ELEMENTS (filters_actions)); gimp_action_group_add_string_actions (group, "filters-action", filters_settings_actions, G_N_ELEMENTS (filters_settings_actions), - G_CALLBACK (filters_apply_cmd_callback)); + filters_apply_cmd_callback); filters_actions_set_tooltips (group, filters_settings_actions, G_N_ELEMENTS (filters_settings_actions)); gimp_action_group_add_string_actions (group, "filters-action", filters_interactive_actions, G_N_ELEMENTS (filters_interactive_actions), - G_CALLBACK (filters_apply_interactive_cmd_callback)); + filters_apply_interactive_cmd_callback); filters_actions_set_tooltips (group, filters_interactive_actions, G_N_ELEMENTS (filters_interactive_actions)); gimp_action_group_add_enum_actions (group, "filters-action", filters_repeat_actions, G_N_ELEMENTS (filters_repeat_actions), - G_CALLBACK (filters_repeat_cmd_callback)); + filters_repeat_cmd_callback); n_entries = gimp_filter_history_size (group->gimp); @@ -789,7 +820,7 @@ } gimp_action_group_add_procedure_actions (group, entries, n_entries, - G_CALLBACK (filters_history_cmd_callback)); + filters_history_cmd_callback); for (i = 0; i < n_entries; i++) { @@ -848,6 +879,7 @@ SET_SENSITIVE ("filters-antialias", writable); SET_SENSITIVE ("filters-apply-canvas", writable); SET_SENSITIVE ("filters-apply-lens", writable); + SET_SENSITIVE ("filters-bayer-matrix", writable); SET_SENSITIVE ("filters-brightness-contrast", writable); SET_SENSITIVE ("filters-bump-map", writable); SET_SENSITIVE ("filters-c2g", writable && !gray); @@ -900,16 +932,19 @@ SET_SENSITIVE ("filters-lens-distortion", writable); SET_SENSITIVE ("filters-lens-flare", writable); SET_SENSITIVE ("filters-levels", writable); + SET_SENSITIVE ("filters-linear-sinusoid", writable); SET_SENSITIVE ("filters-little-planet", writable); SET_SENSITIVE ("filters-long-shadow", writable && alpha); SET_SENSITIVE ("filters-mantiuk-2006", writable); SET_SENSITIVE ("filters-maze", writable); + SET_SENSITIVE ("filters-mean-curvature-blur", writable); SET_SENSITIVE ("filters-median-blur", writable); SET_SENSITIVE ("filters-mono-mixer", writable && !gray); SET_SENSITIVE ("filters-mosaic", writable); SET_SENSITIVE ("filters-motion-blur-circular", writable); SET_SENSITIVE ("filters-motion-blur-linear", writable); SET_SENSITIVE ("filters-motion-blur-zoom", writable); + SET_SENSITIVE ("filters-newsprint", writable); SET_SENSITIVE ("filters-noise-cell", writable); SET_SENSITIVE ("filters-noise-cie-lch", writable); SET_SENSITIVE ("filters-noise-hsv", writable && !gray); @@ -922,6 +957,8 @@ SET_SENSITIVE ("filters-noise-slur", writable); SET_SENSITIVE ("filters-noise-solid", writable); SET_SENSITIVE ("filters-noise-spread", writable); + SET_SENSITIVE ("filters-normal-map", writable); + SET_SENSITIVE ("filters-offset", writable); SET_SENSITIVE ("filters-oilify", writable); SET_SENSITIVE ("filters-panorama-projection", writable); SET_SENSITIVE ("filters-photocopy", writable); @@ -1052,7 +1089,7 @@ if (proc) { - GtkAction *actual_action = NULL; + GimpAction *actual_action = NULL; const gchar *label; gchar *repeat; gchar *reshow; @@ -1072,8 +1109,8 @@ if (g_str_has_prefix (gimp_object_get_name (proc), "filters-")) { actual_action = - gtk_action_group_get_action (GTK_ACTION_GROUP (group), - gimp_object_get_name (proc)); + gimp_action_group_get_action (group, + gimp_object_get_name (proc)); } else if (plug_in_group) { @@ -1084,12 +1121,12 @@ * #517683. */ actual_action = - gtk_action_group_get_action (GTK_ACTION_GROUP (plug_in_group), - gimp_object_get_name (proc)); + gimp_action_group_get_action (plug_in_group, + gimp_object_get_name (proc)); } if (actual_action) - sensitive = gtk_action_get_sensitive (actual_action); + sensitive = gimp_action_get_sensitive (actual_action); gimp_action_group_set_action_sensitive (group, "filters-repeat", sensitive); @@ -1109,14 +1146,14 @@ for (i = 0; i < gimp_filter_history_length (gimp); i++) { - GtkAction *action; - GtkAction *actual_action = NULL; + GimpAction *action; + GimpAction *actual_action = NULL; const gchar *label; gchar *name; gboolean sensitive = FALSE; name = g_strdup_printf ("filters-recent-%02d", i + 1); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), name); + action = gimp_action_group_get_action (group, name); g_free (name); proc = gimp_filter_history_nth (gimp, i); @@ -1126,19 +1163,19 @@ if (g_str_has_prefix (gimp_object_get_name (proc), "filters-")) { actual_action = - gtk_action_group_get_action (GTK_ACTION_GROUP (group), - gimp_object_get_name (proc)); + gimp_action_group_get_action (group, + gimp_object_get_name (proc)); } else if (plug_in_group) { /* see comment above */ actual_action = - gtk_action_group_get_action (GTK_ACTION_GROUP (plug_in_group), - gimp_object_get_name (proc)); + gimp_action_group_get_action (plug_in_group, + gimp_object_get_name (proc)); } if (actual_action) - sensitive = gtk_action_get_sensitive (actual_action); + sensitive = gimp_action_get_sensitive (actual_action); g_object_set (action, "visible", TRUE, @@ -1152,10 +1189,10 @@ for (; i < gimp_filter_history_size (gimp); i++) { - GtkAction *action; - gchar *name = g_strdup_printf ("filters-recent-%02d", i + 1); + GimpAction *action; + gchar *name = g_strdup_printf ("filters-recent-%02d", i + 1); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), name); + action = gimp_action_group_get_action (group, name); g_free (name); g_object_set (action, diff -Nru gimp-2.10.8+zorin2/app/actions/filters-commands.c gimp-2.10.14+om/app/actions/filters-commands.c --- gimp-2.10.8+zorin2/app/actions/filters-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/filters-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,6 +36,8 @@ #include "core/gimpprogress.h" #include "core/gimpsettings.h" +#include "widgets/gimpaction.h" + #include "actions.h" #include "filters-commands.h" #include "gimpgeglprocedure.h" @@ -58,9 +60,9 @@ /* public functions */ void -filters_apply_cmd_callback (GtkAction *action, - const gchar *operation_str, - gpointer data) +filters_apply_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -70,19 +72,18 @@ return_if_no_drawable (image, drawable, data); operation = filters_parse_operation (image->gimp, - operation_str, - gtk_action_get_icon_name (action), + g_variant_get_string (value, NULL), + gimp_action_get_icon_name (action), &settings); procedure = gimp_gegl_procedure_new (image->gimp, GIMP_RUN_NONINTERACTIVE, settings, operation, - gtk_action_get_name (action), - gtk_action_get_label (action), - gtk_action_get_tooltip (action), - gtk_action_get_icon_name (action), - g_object_get_qdata (G_OBJECT (action), - GIMP_HELP_ID)); + gimp_action_get_name (action), + gimp_action_get_label (action), + gimp_action_get_tooltip (action), + gimp_action_get_icon_name (action), + gimp_action_get_help_id (action)); g_free (operation); @@ -90,15 +91,17 @@ g_object_unref (settings); gimp_filter_history_add (image->gimp, procedure); - filters_history_cmd_callback (NULL, procedure, data); + filters_history_cmd_callback (NULL, + g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)), + data); g_object_unref (procedure); } void -filters_apply_interactive_cmd_callback (GtkAction *action, - const gchar *operation, - gpointer data) +filters_apply_interactive_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; @@ -107,49 +110,58 @@ procedure = gimp_gegl_procedure_new (image->gimp, GIMP_RUN_INTERACTIVE, NULL, - operation, - gtk_action_get_name (action), - gtk_action_get_label (action), - gtk_action_get_tooltip (action), - gtk_action_get_icon_name (action), - g_object_get_qdata (G_OBJECT (action), - GIMP_HELP_ID)); + g_variant_get_string (value, NULL), + gimp_action_get_name (action), + gimp_action_get_label (action), + gimp_action_get_tooltip (action), + gimp_action_get_icon_name (action), + gimp_action_get_help_id (action)); gimp_filter_history_add (image->gimp, procedure); - filters_history_cmd_callback (NULL, procedure, data); + filters_history_cmd_callback (NULL, + g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)), + data); g_object_unref (procedure); } void -filters_repeat_cmd_callback (GtkAction *action, - gint value, - gpointer data) +filters_repeat_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDrawable *drawable; GimpDisplay *display; GimpProcedure *procedure; + GimpRunMode run_mode; return_if_no_drawable (image, drawable, data); return_if_no_display (display, data); + run_mode = (GimpRunMode) g_variant_get_int32 (value); + procedure = gimp_filter_history_nth (image->gimp, 0); if (procedure) - filters_run_procedure (image->gimp, display, procedure, - (GimpRunMode) value); + filters_run_procedure (image->gimp, display, procedure, run_mode); } void -filters_history_cmd_callback (GtkAction *action, - GimpProcedure *procedure, - gpointer data) +filters_history_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - Gimp *gimp; - GimpDisplay *display; + Gimp *gimp; + GimpDisplay *display; + GimpProcedure *procedure; + gsize hack; return_if_no_gimp (gimp, data); return_if_no_display (display, data); + hack = g_variant_get_uint64 (value); + + procedure = GSIZE_TO_POINTER (hack); + filters_run_procedure (gimp, display, procedure, GIMP_RUN_INTERACTIVE); } diff -Nru gimp-2.10.8+zorin2/app/actions/filters-commands.h gimp-2.10.14+om/app/actions/filters-commands.h --- gimp-2.10.8+zorin2/app/actions/filters-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/filters-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,19 +19,19 @@ #define __FILTERS_COMMANDS_H__ -void filters_apply_cmd_callback (GtkAction *action, - const gchar *operation, - gpointer data); -void filters_apply_interactive_cmd_callback (GtkAction *action, - const gchar *operation, - gpointer data); +void filters_apply_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void filters_apply_interactive_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void filters_repeat_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void filters_history_cmd_callback (GtkAction *action, - GimpProcedure *procedure, - gpointer data); +void filters_repeat_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void filters_history_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __FILTERS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/fonts-actions.c gimp-2.10.14+om/app/actions/fonts-actions.c --- gimp-2.10.8+zorin2/app/actions/fonts-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/fonts-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,7 +47,7 @@ { "fonts-refresh", GIMP_ICON_VIEW_REFRESH, NC_("fonts-action", "_Rescan Font List"), NULL, NC_("fonts-action", "Rescan the installed fonts"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_FONT_REFRESH } }; diff -Nru gimp-2.10.8+zorin2/app/actions/gimpgeglprocedure.c gimp-2.10.14+om/app/actions/gimpgeglprocedure.c --- gimp-2.10.8+zorin2/app/actions/gimpgeglprocedure.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gimpgeglprocedure.c 2019-06-12 16:43:38.000000000 +0000 @@ -339,6 +339,10 @@ { tool_name = "gimp-threshold-tool"; } + else if (! strcmp (procedure->original_name, "gimp:offset")) + { + tool_name = "gimp-offset-tool"; + } else { tool_name = "gimp-operation-tool"; diff -Nru gimp-2.10.8+zorin2/app/actions/gradient-editor-actions.c gimp-2.10.14+om/app/actions/gradient-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/gradient-editor-actions.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradient-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -65,57 +65,57 @@ { "gradient-editor-left-color", NULL, NC_("gradient-editor-action", "L_eft Endpoint's Color..."), NULL, NULL, - G_CALLBACK (gradient_editor_left_color_cmd_callback), + gradient_editor_left_color_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_LEFT_COLOR }, { "gradient-editor-right-color", NULL, NC_("gradient-editor-action", "R_ight Endpoint's Color..."), NULL, NULL, - G_CALLBACK (gradient_editor_right_color_cmd_callback), + gradient_editor_right_color_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_RIGHT_COLOR }, { "gradient-editor-flip", GIMP_ICON_OBJECT_FLIP_HORIZONTAL, "flip", NULL, NULL, - G_CALLBACK (gradient_editor_flip_cmd_callback), + gradient_editor_flip_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_FLIP }, { "gradient-editor-replicate", GIMP_ICON_OBJECT_DUPLICATE, "replicate", NULL, NULL, - G_CALLBACK (gradient_editor_replicate_cmd_callback), + gradient_editor_replicate_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_FLIP }, { "gradient-editor-split-midpoint", NULL, "splitmidpoint", NULL, NULL, - G_CALLBACK (gradient_editor_split_midpoint_cmd_callback), + gradient_editor_split_midpoint_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_SPLIT_MIDPOINT }, { "gradient-editor-split-uniform", NULL, "splituniform", NULL, NULL, - G_CALLBACK (gradient_editor_split_uniformly_cmd_callback), + gradient_editor_split_uniformly_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_SPLIT_UNIFORM }, { "gradient-editor-delete", GIMP_ICON_EDIT_DELETE, "delete", "", NULL, - G_CALLBACK (gradient_editor_delete_cmd_callback), + gradient_editor_delete_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_DELETE }, { "gradient-editor-recenter", NULL, "recenter", NULL, NULL, - G_CALLBACK (gradient_editor_recenter_cmd_callback), + gradient_editor_recenter_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_RECENTER }, { "gradient-editor-redistribute", NULL, "redistribute", NULL, NULL, - G_CALLBACK (gradient_editor_redistribute_cmd_callback), + gradient_editor_redistribute_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_REDISTRIBUTE }, { "gradient-editor-blend-color", NULL, NC_("gradient-editor-action", "Ble_nd Endpoints' Colors"), NULL, NULL, - G_CALLBACK (gradient_editor_blend_color_cmd_callback), + gradient_editor_blend_color_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_BLEND_COLOR }, { "gradient-editor-blend-opacity", NULL, NC_("gradient-editor-action", "Blend Endpoints' Opacit_y"), NULL, NULL, - G_CALLBACK (gradient_editor_blend_opacity_cmd_callback), + gradient_editor_blend_opacity_cmd_callback, GIMP_HELP_GRADIENT_EDITOR_BLEND_OPACITY } }; @@ -123,7 +123,7 @@ { { "gradient-editor-edit-active", GIMP_ICON_LINKED, NC_("gradient-editor-action", "Edit Active Gradient"), NULL, NULL, - G_CALLBACK (data_editor_edit_active_cmd_callback), + data_editor_edit_active_cmd_callback, FALSE, GIMP_HELP_GRADIENT_EDITOR_EDIT_ACTIVE } }; @@ -409,56 +409,56 @@ gimp_action_group_add_enum_actions (group, "gradient-editor-action", gradient_editor_load_left_actions, G_N_ELEMENTS (gradient_editor_load_left_actions), - G_CALLBACK (gradient_editor_load_left_cmd_callback)); + gradient_editor_load_left_cmd_callback); gimp_action_group_add_enum_actions (group, "gradient-editor-action", gradient_editor_save_left_actions, G_N_ELEMENTS (gradient_editor_save_left_actions), - G_CALLBACK (gradient_editor_save_left_cmd_callback)); + gradient_editor_save_left_cmd_callback); gimp_action_group_add_enum_actions (group, "gradient-editor-action", gradient_editor_load_right_actions, G_N_ELEMENTS (gradient_editor_load_right_actions), - G_CALLBACK (gradient_editor_load_right_cmd_callback)); + gradient_editor_load_right_cmd_callback); gimp_action_group_add_enum_actions (group, "gradient-editor-action", gradient_editor_save_right_actions, G_N_ELEMENTS (gradient_editor_save_right_actions), - G_CALLBACK (gradient_editor_save_right_cmd_callback)); + gradient_editor_save_right_cmd_callback); gimp_action_group_add_radio_actions (group, "gradient-editor-color-type", gradient_editor_left_color_type_actions, G_N_ELEMENTS (gradient_editor_left_color_type_actions), NULL, 0, - G_CALLBACK (gradient_editor_left_color_type_cmd_callback)); + gradient_editor_left_color_type_cmd_callback); gimp_action_group_add_radio_actions (group, "gradient-editor-color-type", gradient_editor_right_color_type_actions, G_N_ELEMENTS (gradient_editor_right_color_type_actions), NULL, 0, - G_CALLBACK (gradient_editor_right_color_type_cmd_callback)); + gradient_editor_right_color_type_cmd_callback); gimp_action_group_add_radio_actions (group, "gradient-editor-blending", gradient_editor_blending_actions, G_N_ELEMENTS (gradient_editor_blending_actions), NULL, 0, - G_CALLBACK (gradient_editor_blending_func_cmd_callback)); + gradient_editor_blending_func_cmd_callback); gimp_action_group_add_radio_actions (group, "gradient-editor-coloring", gradient_editor_coloring_actions, G_N_ELEMENTS (gradient_editor_coloring_actions), NULL, 0, - G_CALLBACK (gradient_editor_coloring_type_cmd_callback)); + gradient_editor_coloring_type_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, gradient_editor_zoom_actions, G_N_ELEMENTS (gradient_editor_zoom_actions), - G_CALLBACK (gradient_editor_zoom_cmd_callback)); + gradient_editor_zoom_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/gradient-editor-commands.c gimp-2.10.14+om/app/actions/gradient-editor-commands.c --- gimp-2.10.8+zorin2/app/actions/gradient-editor-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradient-editor-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -52,8 +52,9 @@ /* public functions */ void -gradient_editor_left_color_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_left_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); @@ -61,18 +62,18 @@ } void -gradient_editor_left_color_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +gradient_editor_left_color_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; GimpGradientSegment *left; GimpGradientColor color_type; - gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL); + color_type = (GimpGradientColor) g_variant_get_int32 (value); - color_type = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL); if (gradient && color_type >= 0 && @@ -97,9 +98,9 @@ } void -gradient_editor_load_left_cmd_callback (GtkAction *action, - gint value, - gpointer data) +gradient_editor_load_left_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -109,10 +110,11 @@ GimpGradientSegment *seg; GimpRGB color; GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED; + gint index = g_variant_get_int32 (value); gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); - switch (value) + switch (index) { case GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT: if (left->prev != NULL) @@ -138,7 +140,7 @@ break; default: /* Load a color */ - color = editor->saved_colors[value - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM]; + color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM]; break; } @@ -154,23 +156,25 @@ } void -gradient_editor_save_left_cmd_callback (GtkAction *action, - gint value, - gpointer data) +gradient_editor_save_left_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; GimpGradientSegment *left; + gint index = g_variant_get_int32 (value); gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL); gimp_gradient_segment_get_left_color (gradient, left, - &editor->saved_colors[value]); + &editor->saved_colors[index]); } void -gradient_editor_right_color_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_right_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); @@ -178,18 +182,18 @@ } void -gradient_editor_right_color_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +gradient_editor_right_color_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; GimpGradientSegment *right; GimpGradientColor color_type; - gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right); + color_type = (GimpGradientColor) g_variant_get_int32 (value); - color_type = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right); if (gradient && color_type >= 0 && @@ -214,9 +218,9 @@ } void -gradient_editor_load_right_cmd_callback (GtkAction *action, - gint value, - gpointer data) +gradient_editor_load_right_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -226,10 +230,11 @@ GimpGradientSegment *seg; GimpRGB color; GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED; + gint index = g_variant_get_int32 (value); gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); - switch (value) + switch (index) { case GRADIENT_EDITOR_COLOR_NEIGHBOR_ENDPOINT: if (right->next != NULL) @@ -255,7 +260,7 @@ break; default: /* Load a color */ - color = editor->saved_colors[value - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM]; + color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM]; break; } @@ -271,24 +276,25 @@ } void -gradient_editor_save_right_cmd_callback (GtkAction *action, - gint value, - gpointer data) +gradient_editor_save_right_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; GimpGradientSegment *right; + gint index = g_variant_get_int32 (value); gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right); gimp_gradient_segment_get_right_color (gradient, right, - &editor->saved_colors[value]); + &editor->saved_colors[index]); } void -gradient_editor_blending_func_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +gradient_editor_blending_func_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -297,9 +303,9 @@ GEnumClass *enum_class = NULL; GimpGradientSegmentType type; - gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); + type = (GimpGradientSegmentType) g_variant_get_int32 (value); - type = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); enum_class = g_type_class_ref (GIMP_TYPE_GRADIENT_SEGMENT_TYPE); @@ -314,9 +320,9 @@ } void -gradient_editor_coloring_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +gradient_editor_coloring_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -325,9 +331,9 @@ GEnumClass *enum_class = NULL; GimpGradientSegmentColor color; - gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); + color = (GimpGradientSegmentColor) g_variant_get_int32 (value); - color = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + gimp_gradient_editor_get_selection (editor, &gradient, &left, &right); enum_class = g_type_class_ref (GIMP_TYPE_GRADIENT_SEGMENT_COLOR); @@ -342,8 +348,9 @@ } void -gradient_editor_flip_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -360,8 +367,9 @@ } void -gradient_editor_replicate_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_replicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -448,8 +456,9 @@ } void -gradient_editor_split_midpoint_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_split_midpoint_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -469,8 +478,9 @@ } void -gradient_editor_split_uniformly_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_split_uniformly_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -558,8 +568,9 @@ } void -gradient_editor_delete_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -576,8 +587,9 @@ } void -gradient_editor_recenter_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_recenter_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -590,8 +602,9 @@ } void -gradient_editor_redistribute_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_redistribute_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -604,8 +617,9 @@ } void -gradient_editor_blend_color_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_blend_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -621,8 +635,9 @@ } void -gradient_editor_blend_opacity_cmd_callback (GtkAction *action, - gpointer data) +gradient_editor_blend_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); GimpGradient *gradient; @@ -638,13 +653,14 @@ } void -gradient_editor_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data) +gradient_editor_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); + GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data); + GimpZoomType zoom_type = (GimpZoomType) g_variant_get_int32 (value); - gimp_gradient_editor_zoom (editor, (GimpZoomType) value); + gimp_gradient_editor_zoom (editor, zoom_type); } diff -Nru gimp-2.10.8+zorin2/app/actions/gradient-editor-commands.h gimp-2.10.14+om/app/actions/gradient-editor-commands.h --- gimp-2.10.8+zorin2/app/actions/gradient-editor-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradient-editor-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -29,60 +29,71 @@ }; -void gradient_editor_left_color_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_left_color_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void gradient_editor_load_left_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void gradient_editor_save_left_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void gradient_editor_right_color_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_right_color_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void gradient_editor_load_right_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void gradient_editor_save_right_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void gradient_editor_blending_func_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void gradient_editor_coloring_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); - -void gradient_editor_flip_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_replicate_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_split_midpoint_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_split_uniformly_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_delete_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_recenter_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_redistribute_cmd_callback (GtkAction *action, - gpointer data); - -void gradient_editor_blend_color_cmd_callback (GtkAction *action, - gpointer data); -void gradient_editor_blend_opacity_cmd_callback (GtkAction *action, - gpointer data); - -void gradient_editor_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void gradient_editor_left_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_left_color_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_load_left_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_save_left_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void gradient_editor_right_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_right_color_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_load_right_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_save_right_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void gradient_editor_blending_func_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_coloring_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void gradient_editor_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_replicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_split_midpoint_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_split_uniformly_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_recenter_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_redistribute_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void gradient_editor_blend_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void gradient_editor_blend_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void gradient_editor_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __GRADIENT_EDITOR_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/gradients-actions.c gimp-2.10.14+om/app/actions/gradients-actions.c --- gimp-2.10.8+zorin2/app/actions/gradients-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradients-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,43 +47,43 @@ { "gradients-new", GIMP_ICON_DOCUMENT_NEW, NC_("gradients-action", "_New Gradient"), NULL, NC_("gradients-action", "Create a new gradient"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_GRADIENT_NEW }, { "gradients-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("gradients-action", "D_uplicate Gradient"), NULL, NC_("gradients-action", "Duplicate this gradient"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_GRADIENT_DUPLICATE }, { "gradients-copy-location", GIMP_ICON_EDIT_COPY, NC_("gradients-action", "Copy Gradient _Location"), NULL, NC_("gradients-action", "Copy gradient file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_GRADIENT_COPY_LOCATION }, { "gradients-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("gradients-action", "Show in _File Manager"), NULL, NC_("gradients-action", "Show gradient file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_GRADIENT_SHOW_IN_FILE_MANAGER }, { "gradients-save-as-pov", GIMP_ICON_DOCUMENT_SAVE_AS, NC_("gradients-action", "Save as _POV-Ray..."), NULL, NC_("gradients-action", "Save gradient as POV-Ray"), - G_CALLBACK (gradients_save_as_pov_ray_cmd_callback), + gradients_save_as_pov_ray_cmd_callback, GIMP_HELP_GRADIENT_SAVE_AS_POV }, { "gradients-delete", GIMP_ICON_EDIT_DELETE, NC_("gradients-action", "_Delete Gradient"), NULL, NC_("gradients-action", "Delete this gradient"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_GRADIENT_DELETE }, { "gradients-refresh", GIMP_ICON_VIEW_REFRESH, NC_("gradients-action", "_Refresh Gradients"), NULL, NC_("gradients-action", "Refresh gradients"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_GRADIENT_REFRESH } }; @@ -107,7 +107,7 @@ gimp_action_group_add_string_actions (group, "gradients-action", gradients_edit_actions, G_N_ELEMENTS (gradients_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/gradients-commands.c gimp-2.10.14+om/app/actions/gradients-commands.c --- gimp-2.10.8+zorin2/app/actions/gradients-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradients-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -49,8 +49,9 @@ /* public functions */ void -gradients_save_as_pov_ray_cmd_callback (GtkAction *action, - gpointer data) +gradients_save_as_pov_ray_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; diff -Nru gimp-2.10.8+zorin2/app/actions/gradients-commands.h gimp-2.10.14+om/app/actions/gradients-commands.h --- gimp-2.10.8+zorin2/app/actions/gradients-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/gradients-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,8 +19,9 @@ #define __GRADIENTS_COMMANDS_H__ -void gradients_save_as_pov_ray_cmd_callback (GtkAction *action, - gpointer data); +void gradients_save_as_pov_ray_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __GRADIENTS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/help-actions.c gimp-2.10.14+om/app/actions/help-actions.c --- gimp-2.10.8+zorin2/app/actions/help-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/help-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -40,13 +40,13 @@ { "help-help", "gimp-prefs-help-system", NC_("help-action", "_Help"), "F1", NC_("help-action", "Open the GIMP user manual"), - G_CALLBACK (help_help_cmd_callback), + help_help_cmd_callback, GIMP_HELP_HELP }, { "help-context-help", "gimp-prefs-help-system", NC_("help-action", "_Context Help"), "F1", NC_("help-action", "Show the help for a specific user interface item"), - G_CALLBACK (help_context_help_cmd_callback), + help_context_help_cmd_callback, GIMP_HELP_HELP_CONTEXT } }; diff -Nru gimp-2.10.8+zorin2/app/actions/help-commands.c gimp-2.10.14+om/app/actions/help-commands.c --- gimp-2.10.8+zorin2/app/actions/help-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/help-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -33,8 +33,9 @@ void -help_help_cmd_callback (GtkAction *action, - gpointer data) +help_help_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpDisplay *display; @@ -45,8 +46,9 @@ } void -help_context_help_cmd_callback (GtkAction *action, - gpointer data) +help_context_help_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; return_if_no_widget (widget, data); diff -Nru gimp-2.10.8+zorin2/app/actions/help-commands.h gimp-2.10.14+om/app/actions/help-commands.h --- gimp-2.10.8+zorin2/app/actions/help-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/help-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,12 @@ #define __HELP_COMMANDS_H__ -void help_help_cmd_callback (GtkAction *action, - gpointer data); -void help_context_help_cmd_callback (GtkAction *action, - gpointer data); +void help_help_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void help_context_help_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __HELP_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/image-actions.c gimp-2.10.14+om/app/actions/image-actions.c --- gimp-2.10.8+zorin2/app/actions/image-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/image-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -75,103 +75,103 @@ { "image-new", GIMP_ICON_DOCUMENT_NEW, NC_("image-action", "_New..."), "N", NC_("image-action", "Create a new image"), - G_CALLBACK (image_new_cmd_callback), + image_new_cmd_callback, GIMP_HELP_FILE_NEW }, { "image-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("image-action", "_Duplicate"), "D", NC_("image-action", "Create a duplicate of this image"), - G_CALLBACK (image_duplicate_cmd_callback), + image_duplicate_cmd_callback, GIMP_HELP_IMAGE_DUPLICATE }, { "image-color-profile-assign", NULL, NC_("image-action", "_Assign Color Profile..."), NULL, NC_("image-action", "Set a color profile on the image"), - G_CALLBACK (image_color_profile_assign_cmd_callback), + image_color_profile_assign_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_ASSIGN }, { "image-color-profile-convert", NULL, NC_("image-action", "_Convert to Color Profile..."), NULL, NC_("image-action", "Apply a color profile to the image"), - G_CALLBACK (image_color_profile_convert_cmd_callback), + image_color_profile_convert_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_CONVERT }, { "image-color-profile-discard", NULL, NC_("image-action", "_Discard Color Profile"), NULL, NC_("image-action", "Remove the image's color profile"), - G_CALLBACK (image_color_profile_discard_cmd_callback), + image_color_profile_discard_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_DISCARD }, { "image-color-profile-save", NULL, NC_("image-action", "_Save Color Profile to File..."), NULL, NC_("image-action", "Save the image's color profile to an ICC file"), - G_CALLBACK (image_color_profile_save_cmd_callback), + image_color_profile_save_cmd_callback, GIMP_HELP_IMAGE_COLOR_PROFILE_SAVE }, { "image-resize", GIMP_ICON_OBJECT_RESIZE, NC_("image-action", "Can_vas Size..."), NULL, NC_("image-action", "Adjust the image dimensions"), - G_CALLBACK (image_resize_cmd_callback), + image_resize_cmd_callback, GIMP_HELP_IMAGE_RESIZE }, { "image-resize-to-layers", NULL, NC_("image-action", "Fit Canvas to L_ayers"), NULL, NC_("image-action", "Resize the image to enclose all layers"), - G_CALLBACK (image_resize_to_layers_cmd_callback), + image_resize_to_layers_cmd_callback, GIMP_HELP_IMAGE_RESIZE_TO_LAYERS }, { "image-resize-to-selection", NULL, NC_("image-action", "F_it Canvas to Selection"), NULL, NC_("image-action", "Resize the image to the extents of the selection"), - G_CALLBACK (image_resize_to_selection_cmd_callback), + image_resize_to_selection_cmd_callback, GIMP_HELP_IMAGE_RESIZE_TO_SELECTION }, { "image-print-size", GIMP_ICON_DOCUMENT_PRINT_RESOLUTION, NC_("image-action", "_Print Size..."), NULL, NC_("image-action", "Adjust the print resolution"), - G_CALLBACK (image_print_size_cmd_callback), + image_print_size_cmd_callback, GIMP_HELP_IMAGE_PRINT_SIZE }, { "image-scale", GIMP_ICON_OBJECT_SCALE, NC_("image-action", "_Scale Image..."), NULL, NC_("image-action", "Change the size of the image content"), - G_CALLBACK (image_scale_cmd_callback), + image_scale_cmd_callback, GIMP_HELP_IMAGE_SCALE }, { "image-crop-to-selection", GIMP_ICON_TOOL_CROP, NC_("image-action", "_Crop to Selection"), NULL, NC_("image-action", "Crop the image to the extents of the selection"), - G_CALLBACK (image_crop_to_selection_cmd_callback), + image_crop_to_selection_cmd_callback, GIMP_HELP_IMAGE_CROP }, { "image-crop-to-content", GIMP_ICON_TOOL_CROP, NC_("image-action", "Crop to C_ontent"), NULL, NC_("image-action", "Crop the image to the extents of its content (remove empty borders from the image)"), - G_CALLBACK (image_crop_to_content_cmd_callback), + image_crop_to_content_cmd_callback, GIMP_HELP_IMAGE_CROP }, { "image-merge-layers", NULL, NC_("image-action", "Merge Visible _Layers..."), "M", NC_("image-action", "Merge all visible layers into one layer"), - G_CALLBACK (image_merge_layers_cmd_callback), + image_merge_layers_cmd_callback, GIMP_HELP_IMAGE_MERGE_LAYERS }, { "image-flatten", NULL, NC_("image-action", "_Flatten Image"), NULL, NC_("image-action", "Merge all layers into one and remove transparency"), - G_CALLBACK (image_flatten_image_cmd_callback), + image_flatten_image_cmd_callback, GIMP_HELP_IMAGE_FLATTEN }, { "image-configure-grid", GIMP_ICON_GRID, NC_("image-action", "Configure G_rid..."), NULL, NC_("image-action", "Configure the grid for this image"), - G_CALLBACK (image_configure_grid_cmd_callback), + image_configure_grid_cmd_callback, GIMP_HELP_IMAGE_GRID }, { "image-properties", "dialog-information", NC_("image-action", "Image Pr_operties"), "Return", NC_("image-action", "Display information about this image"), - G_CALLBACK (image_properties_cmd_callback), + image_properties_cmd_callback, GIMP_HELP_IMAGE_PROPERTIES } }; @@ -182,7 +182,7 @@ NC_("image-action", "Whether the image is color managed. Disabling " "color management is equivalent to assigning a built-in sRGB " "color profile. Better leave color management enabled."), - G_CALLBACK (image_color_management_enabled_cmd_callback), + image_color_management_enabled_cmd_callback, TRUE, GIMP_HELP_IMAGE_COLOR_MANAGEMENT_ENABLED } }; @@ -311,29 +311,29 @@ image_convert_base_type_actions, G_N_ELEMENTS (image_convert_base_type_actions), NULL, 0, - G_CALLBACK (image_convert_base_type_cmd_callback)); + image_convert_base_type_cmd_callback); gimp_action_group_add_radio_actions (group, "image-convert-action", image_convert_precision_actions, G_N_ELEMENTS (image_convert_precision_actions), NULL, 0, - G_CALLBACK (image_convert_precision_cmd_callback)); + image_convert_precision_cmd_callback); gimp_action_group_add_radio_actions (group, "image-convert-action", image_convert_gamma_actions, G_N_ELEMENTS (image_convert_gamma_actions), NULL, 0, - G_CALLBACK (image_convert_gamma_cmd_callback)); + image_convert_gamma_cmd_callback); gimp_action_group_add_enum_actions (group, "image-action", image_flip_actions, G_N_ELEMENTS (image_flip_actions), - G_CALLBACK (image_flip_cmd_callback)); + image_flip_cmd_callback); gimp_action_group_add_enum_actions (group, "image-action", image_rotate_actions, G_N_ELEMENTS (image_rotate_actions), - G_CALLBACK (image_rotate_cmd_callback)); + image_rotate_cmd_callback); #define SET_ALWAYS_SHOW_IMAGE(action,show) \ gimp_action_group_set_action_always_show_image (group, action, show) diff -Nru gimp-2.10.8+zorin2/app/actions/image-commands.c gimp-2.10.14+om/app/actions/image-commands.c --- gimp-2.10.8+zorin2/app/actions/image-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/image-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -166,7 +166,8 @@ GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, - gboolean discard_invisible); + gboolean discard_invisible, + gpointer user_data); /* private variables */ @@ -180,8 +181,9 @@ /* public functions */ void -image_new_cmd_callback (GtkAction *action, - gpointer data) +image_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; GtkWidget *dialog; @@ -204,8 +206,9 @@ } void -image_duplicate_cmd_callback (GtkAction *action, - gpointer data) +image_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -227,24 +230,24 @@ } void -image_convert_base_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +image_convert_base_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; GtkWidget *widget; GimpDialogConfig *config; GtkWidget *dialog; - GimpImageBaseType value; + GimpImageBaseType base_type; GError *error = NULL; return_if_no_image (image, data); return_if_no_display (display, data); return_if_no_widget (widget, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + base_type = (GimpImageBaseType) g_variant_get_int32 (value); - if (value == gimp_image_get_base_type (image)) + if (base_type == gimp_image_get_base_type (image)) return; #define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog" @@ -259,7 +262,7 @@ config = GIMP_DIALOG_CONFIG (image->gimp->config); - switch (value) + switch (base_type) { case GIMP_RGB: case GIMP_GRAY: @@ -274,7 +277,7 @@ current_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (image)); - if (value == GIMP_RGB) + if (base_type == GIMP_RGB) { dialog_type = COLOR_PROFILE_DIALOG_CONVERT_TO_RGB; callback = image_convert_rgb_callback; @@ -305,7 +308,7 @@ callback, display); } - else if (! gimp_image_convert_type (image, value, NULL, NULL, &error)) + else if (! gimp_image_convert_type (image, base_type, NULL, NULL, &error)) { gimp_message_literal (image->gimp, G_OBJECT (widget), GIMP_MESSAGE_WARNING, @@ -344,23 +347,23 @@ } void -image_convert_precision_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +image_convert_precision_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; GtkWidget *widget; GimpDialogConfig *config; GtkWidget *dialog; - GimpComponentType value; + GimpComponentType component_type; return_if_no_image (image, data); return_if_no_display (display, data); return_if_no_widget (widget, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + component_type = (GimpComponentType) g_variant_get_int32 (value); - if (value == gimp_image_get_component_type (image)) + if (component_type == gimp_image_get_component_type (image)) return; #define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog" @@ -378,7 +381,7 @@ dialog = convert_precision_dialog_new (image, action_data_get_context (data), widget, - value, + component_type, config->image_convert_precision_layer_dither_method, config->image_convert_precision_text_layer_dither_method, config->image_convert_precision_channel_dither_method, @@ -395,25 +398,25 @@ } void -image_convert_gamma_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +image_convert_gamma_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; - gboolean value; + gboolean linear; GimpPrecision precision; return_if_no_image (image, data); return_if_no_display (display, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + linear = (gboolean) g_variant_get_int32 (value); - if (value == gimp_babl_format_get_linear (gimp_image_get_layer_format (image, + if (linear == gimp_babl_format_get_linear (gimp_image_get_layer_format (image, FALSE))) return; precision = gimp_babl_precision (gimp_image_get_component_type (image), - value); + linear); gimp_image_convert_precision (image, precision, GEGL_DITHER_NONE, @@ -424,14 +427,15 @@ } void -image_color_management_enabled_cmd_callback (GtkAction *action, - gpointer data) +image_color_management_enabled_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; gboolean enabled; return_if_no_image (image, data); - enabled = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + enabled = g_variant_get_boolean (value); if (enabled != gimp_image_get_is_color_managed (image)) { @@ -441,8 +445,9 @@ } void -image_color_profile_assign_cmd_callback (GtkAction *action, - gpointer data) +image_color_profile_assign_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; @@ -482,8 +487,9 @@ } void -image_color_profile_convert_cmd_callback (GtkAction *action, - gpointer data) +image_color_profile_convert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; @@ -525,8 +531,9 @@ } void -image_color_profile_discard_cmd_callback (GtkAction *action, - gpointer data) +image_color_profile_discard_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -570,8 +577,9 @@ } void -image_color_profile_save_cmd_callback (GtkAction *action, - gpointer data) +image_color_profile_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplay *display; @@ -619,8 +627,9 @@ } void -image_resize_cmd_callback (GtkAction *action, - gpointer data) +image_resize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -662,8 +671,9 @@ } void -image_resize_to_layers_cmd_callback (GtkAction *action, - gpointer data) +image_resize_to_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -686,8 +696,9 @@ } void -image_resize_to_selection_cmd_callback (GtkAction *action, - gpointer data) +image_resize_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -710,8 +721,9 @@ } void -image_print_size_cmd_callback (GtkAction *action, - gpointer data) +image_print_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -745,8 +757,9 @@ } void -image_scale_cmd_callback (GtkAction *action, - gpointer data) +image_scale_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -784,22 +797,25 @@ } void -image_flip_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplay *display; - GimpImage *image; - GimpProgress *progress; +image_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplay *display; + GimpImage *image; + GimpProgress *progress; + GimpOrientationType orientation; return_if_no_display (display, data); + orientation = (GimpOrientationType) g_variant_get_int32 (value); + image = gimp_display_get_image (display); progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE, _("Flipping")); gimp_image_flip (image, action_data_get_context (data), - (GimpOrientationType) value, progress); + orientation, progress); if (progress) gimp_progress_end (progress); @@ -808,22 +824,25 @@ } void -image_rotate_cmd_callback (GtkAction *action, - gint value, - gpointer data) +image_rotate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpDisplay *display; - GimpImage *image; - GimpProgress *progress; + GimpDisplay *display; + GimpImage *image; + GimpProgress *progress; + GimpRotationType rotation; return_if_no_display (display, data); + rotation = (GimpRotationType) g_variant_get_int32 (value); + image = gimp_display_get_image (display); progress = gimp_progress_start (GIMP_PROGRESS (display), FALSE, _("Rotating")); gimp_image_rotate (image, action_data_get_context (data), - (GimpRotationType) value, progress); + rotation, progress); if (progress) gimp_progress_end (progress); @@ -832,8 +851,9 @@ } void -image_crop_to_selection_cmd_callback (GtkAction *action, - gpointer data) +image_crop_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -859,8 +879,9 @@ } void -image_crop_to_content_cmd_callback (GtkAction *action, - gpointer data) +image_crop_to_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -898,13 +919,16 @@ } void -image_merge_layers_cmd_callback (GtkAction *action, - gpointer data) +image_merge_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GtkWidget *dialog; - GimpImage *image; - GtkWidget *widget; + GtkWidget *dialog; + GimpImage *image; + GimpDisplay *display; + GtkWidget *widget; return_if_no_image (image, data); + return_if_no_display (display, data); return_if_no_widget (widget, data); #define MERGE_LAYERS_DIALOG_KEY "gimp-merge-layers-dialog" @@ -922,7 +946,7 @@ config->layer_merge_active_group_only, config->layer_merge_discard_invisible, image_merge_layers_callback, - NULL); + display); dialogs_attach_dialog (G_OBJECT (image), MERGE_LAYERS_DIALOG_KEY, dialog); } @@ -931,16 +955,20 @@ } void -image_flatten_image_cmd_callback (GtkAction *action, - gpointer data) +image_flatten_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GtkWidget *widget; - GError *error = NULL; + GimpImage *image; + GimpDisplay *display; + GtkWidget *widget; + GError *error = NULL; return_if_no_image (image, data); + return_if_no_display (display, data); return_if_no_widget (widget, data); - if (! gimp_image_flatten (image, action_data_get_context (data), &error)) + if (! gimp_image_flatten (image, action_data_get_context (data), + GIMP_PROGRESS (display), &error)) { gimp_message_literal (image->gimp, G_OBJECT (widget), GIMP_MESSAGE_WARNING, @@ -953,8 +981,9 @@ } void -image_configure_grid_cmd_callback (GtkAction *action, - gpointer data) +image_configure_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -982,8 +1011,9 @@ } void -image_properties_cmd_callback (GtkAction *action, - gpointer data) +image_properties_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -1263,7 +1293,7 @@ gimp_image_set_is_color_managed (image, TRUE, TRUE); /* omg... */ - gimp_image_parasite_detach (image, "icc-profile-name"); + gimp_image_parasite_detach (image, "icc-profile-name", TRUE); gimp_image_undo_group_end (image); @@ -1475,9 +1505,11 @@ GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, - gboolean discard_invisible) + gboolean discard_invisible, + gpointer user_data) { - GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config); + GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config); + GimpDisplay *display = user_data; g_object_set (config, "layer-merge-type", merge_type, @@ -1489,7 +1521,8 @@ context, config->layer_merge_type, config->layer_merge_active_group_only, - config->layer_merge_discard_invisible); + config->layer_merge_discard_invisible, + GIMP_PROGRESS (display)); gimp_image_flush (image); diff -Nru gimp-2.10.8+zorin2/app/actions/image-commands.h gimp-2.10.14+om/app/actions/image-commands.h --- gimp-2.10.8+zorin2/app/actions/image-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/image-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,62 +19,80 @@ #define __IMAGE_COMMANDS_H__ -void image_new_cmd_callback (GtkAction *action, - gpointer data); -void image_duplicate_cmd_callback (GtkAction *action, - gpointer data); - -void image_convert_base_type_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void image_convert_precision_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void image_convert_gamma_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); - -void image_color_management_enabled_cmd_callback (GtkAction *action, - gpointer data); -void image_color_profile_assign_cmd_callback (GtkAction *action, - gpointer data); -void image_color_profile_convert_cmd_callback (GtkAction *action, - gpointer data); -void image_color_profile_discard_cmd_callback (GtkAction *action, - gpointer data); -void image_color_profile_save_cmd_callback (GtkAction *action, - gpointer data); - -void image_resize_cmd_callback (GtkAction *action, - gpointer data); -void image_resize_to_layers_cmd_callback (GtkAction *action, - gpointer data); -void image_resize_to_selection_cmd_callback (GtkAction *action, - gpointer data); -void image_print_size_cmd_callback (GtkAction *action, - gpointer data); -void image_scale_cmd_callback (GtkAction *action, - gpointer data); -void image_flip_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void image_rotate_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void image_crop_to_selection_cmd_callback (GtkAction *action, - gpointer data); -void image_crop_to_content_cmd_callback (GtkAction *action, - gpointer data); - -void image_merge_layers_cmd_callback (GtkAction *action, - gpointer data); -void image_flatten_image_cmd_callback (GtkAction *action, - gpointer data); - -void image_configure_grid_cmd_callback (GtkAction *action, - gpointer data); -void image_properties_cmd_callback (GtkAction *action, - gpointer data); +void image_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void image_convert_base_type_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_convert_precision_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_convert_gamma_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void image_color_management_enabled_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_color_profile_assign_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_color_profile_convert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_color_profile_discard_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_color_profile_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void image_resize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_resize_to_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_resize_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_print_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_scale_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_flip_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_rotate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_crop_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_crop_to_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void image_merge_layers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_flatten_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void image_configure_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void image_properties_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __IMAGE_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/images-actions.c gimp-2.10.14+om/app/actions/images-actions.c --- gimp-2.10.8+zorin2/app/actions/images-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/images-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,19 +46,19 @@ { "images-raise-views", GIMP_ICON_GO_TOP, NC_("images-action", "_Raise Views"), NULL, NC_("images-action", "Raise this image's displays"), - G_CALLBACK (images_raise_views_cmd_callback), + images_raise_views_cmd_callback, NULL }, { "images-new-view", GIMP_ICON_DOCUMENT_NEW, NC_("images-action", "_New View"), NULL, NC_("images-action", "Create a new display for this image"), - G_CALLBACK (images_new_view_cmd_callback), + images_new_view_cmd_callback, NULL }, { "images-delete", GIMP_ICON_EDIT_DELETE, NC_("images-action", "_Delete Image"), NULL, NC_("images-action", "Delete this image"), - G_CALLBACK (images_delete_image_cmd_callback), + images_delete_image_cmd_callback, NULL } }; diff -Nru gimp-2.10.8+zorin2/app/actions/images-commands.c gimp-2.10.14+om/app/actions/images-commands.c --- gimp-2.10.8+zorin2/app/actions/images-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/images-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -41,8 +41,9 @@ /* public functions */ void -images_raise_views_cmd_callback (GtkAction *action, - gpointer data) +images_raise_views_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -71,8 +72,9 @@ } void -images_new_view_cmd_callback (GtkAction *action, - gpointer data) +images_new_view_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -93,8 +95,9 @@ } void -images_delete_image_cmd_callback (GtkAction *action, - gpointer data) +images_delete_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; diff -Nru gimp-2.10.8+zorin2/app/actions/images-commands.h gimp-2.10.14+om/app/actions/images-commands.h --- gimp-2.10.8+zorin2/app/actions/images-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/images-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,12 +19,15 @@ #define __IMAGES_COMMANDS_H__ -void images_raise_views_cmd_callback (GtkAction *action, - gpointer data); -void images_new_view_cmd_callback (GtkAction *action, - gpointer data); -void images_delete_image_cmd_callback (GtkAction *action, - gpointer data); +void images_raise_views_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void images_new_view_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void images_delete_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __IMAGES_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/items-commands.c gimp-2.10.14+om/app/actions/items-commands.c --- gimp-2.10.8+zorin2/app/actions/items-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/items-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -62,13 +62,12 @@ /* public functions */ void -items_visible_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item) +items_visible_cmd_callback (GimpAction *action, + GVariant *value, + GimpImage *image, + GimpItem *item) { - gboolean visible; - - visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean visible = g_variant_get_boolean (value); if (visible != gimp_item_get_visible (item)) { @@ -87,13 +86,12 @@ } void -items_linked_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item) +items_linked_cmd_callback (GimpAction *action, + GVariant *value, + GimpImage *image, + GimpItem *item) { - gboolean linked; - - linked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean linked = g_variant_get_boolean (value); if (linked != gimp_item_get_linked (item)) { @@ -112,13 +110,12 @@ } void -items_lock_content_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item) +items_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + GimpImage *image, + GimpItem *item) { - gboolean locked; - - locked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean locked = g_variant_get_boolean (value); if (locked != gimp_item_get_lock_content (item)) { @@ -137,13 +134,12 @@ } void -items_lock_position_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item) +items_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + GimpImage *image, + GimpItem *item) { - gboolean locked; - - locked = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean locked = g_variant_get_boolean (value); if (locked != gimp_item_get_lock_position (item)) { @@ -163,7 +159,7 @@ } void -items_color_tag_cmd_callback (GtkAction *action, +items_color_tag_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, GimpColorTag color_tag) @@ -185,7 +181,7 @@ } void -items_fill_cmd_callback (GtkAction *action, +items_fill_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, const gchar *dialog_key, @@ -233,10 +229,10 @@ } void -items_fill_last_vals_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item, - gpointer data) +items_fill_last_vals_cmd_callback (GimpAction *action, + GimpImage *image, + GimpItem *item, + gpointer data) { GimpDrawable *drawable; GimpDialogConfig *config; @@ -270,7 +266,7 @@ } void -items_stroke_cmd_callback (GtkAction *action, +items_stroke_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, const gchar *dialog_key, @@ -318,10 +314,10 @@ } void -items_stroke_last_vals_cmd_callback (GtkAction *action, - GimpImage *image, - GimpItem *item, - gpointer data) +items_stroke_last_vals_cmd_callback (GimpAction *action, + GimpImage *image, + GimpItem *item, + gpointer data) { GimpDrawable *drawable; GimpDialogConfig *config; diff -Nru gimp-2.10.8+zorin2/app/actions/items-commands.h gimp-2.10.14+om/app/actions/items-commands.h --- gimp-2.10.8+zorin2/app/actions/items-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/items-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,25 +19,29 @@ #define __ITEMS_COMMANDS_H__ -void items_visible_cmd_callback (GtkAction *action, +void items_visible_cmd_callback (GimpAction *action, + GVariant *value, GimpImage *image, GimpItem *item); -void items_linked_cmd_callback (GtkAction *action, +void items_linked_cmd_callback (GimpAction *action, + GVariant *value, GimpImage *image, GimpItem *item); -void items_lock_content_cmd_callback (GtkAction *action, +void items_lock_content_cmd_callback (GimpAction *action, + GVariant *value, GimpImage *image, GimpItem *item); -void items_lock_position_cmd_callback (GtkAction *action, +void items_lock_position_cmd_callback (GimpAction *action, + GVariant *value, GimpImage *image, GimpItem *item); -void items_color_tag_cmd_callback (GtkAction *action, +void items_color_tag_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, GimpColorTag color_tag); -void items_fill_cmd_callback (GtkAction *action, +void items_fill_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, const gchar *dialog_key, @@ -45,12 +49,12 @@ const gchar *dialog_icon_name, const gchar *dialog_help_id, gpointer data); -void items_fill_last_vals_cmd_callback (GtkAction *action, +void items_fill_last_vals_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, gpointer data); -void items_stroke_cmd_callback (GtkAction *action, +void items_stroke_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, const gchar *dialog_key, @@ -58,7 +62,7 @@ const gchar *dialog_icon_name, const gchar *dialog_help_id, gpointer data); -void items_stroke_last_vals_cmd_callback (GtkAction *action, +void items_stroke_last_vals_cmd_callback (GimpAction *action, GimpImage *image, GimpItem *item, gpointer data); diff -Nru gimp-2.10.8+zorin2/app/actions/layers-actions.c gimp-2.10.14+om/app/actions/layers-actions.c --- gimp-2.10.8+zorin2/app/actions/layers-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/layers-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -88,166 +88,166 @@ { "layers-edit", GIMP_ICON_EDIT, NC_("layers-action", "Default Edit Action"), NULL, NC_("layers-action", "Activate the default edit action for this type of layer"), - G_CALLBACK (layers_edit_cmd_callback), + layers_edit_cmd_callback, GIMP_HELP_LAYER_EDIT }, { "layers-edit-text", GIMP_ICON_EDIT, NC_("layers-action", "Edit Te_xt on canvas"), NULL, NC_("layers-action", "Edit this text layer content on canvas"), - G_CALLBACK (layers_edit_text_cmd_callback), + layers_edit_text_cmd_callback, GIMP_HELP_LAYER_EDIT }, { "layers-edit-attributes", GIMP_ICON_EDIT, NC_("layers-action", "_Edit Layer Attributes..."), NULL, NC_("layers-action", "Edit the layer's name"), - G_CALLBACK (layers_edit_attributes_cmd_callback), + layers_edit_attributes_cmd_callback, GIMP_HELP_LAYER_EDIT }, { "layers-new", GIMP_ICON_DOCUMENT_NEW, NC_("layers-action", "_New Layer..."), "N", NC_("layers-action", "Create a new layer and add it to the image"), - G_CALLBACK (layers_new_cmd_callback), + layers_new_cmd_callback, GIMP_HELP_LAYER_NEW }, { "layers-new-last-values", GIMP_ICON_DOCUMENT_NEW, NC_("layers-action", "_New Layer"), NULL, NC_("layers-action", "Create a new layer with last used values"), - G_CALLBACK (layers_new_last_vals_cmd_callback), + layers_new_last_vals_cmd_callback, GIMP_HELP_LAYER_NEW }, { "layers-new-from-visible", NULL, NC_("layers-action", "New from _Visible"), NULL, NC_("layers-action", "Create a new layer from what is visible in this image"), - G_CALLBACK (layers_new_from_visible_cmd_callback), + layers_new_from_visible_cmd_callback, GIMP_HELP_LAYER_NEW_FROM_VISIBLE }, { "layers-new-group", GIMP_ICON_FOLDER_NEW, NC_("layers-action", "New Layer _Group"), NULL, NC_("layers-action", "Create a new layer group and add it to the image"), - G_CALLBACK (layers_new_group_cmd_callback), + layers_new_group_cmd_callback, GIMP_HELP_LAYER_NEW }, { "layers-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("layers-action", "D_uplicate Layer"), "D", NC_("layers-action", "Create a duplicate of the layer and add it to the image"), - G_CALLBACK (layers_duplicate_cmd_callback), + layers_duplicate_cmd_callback, GIMP_HELP_LAYER_DUPLICATE }, { "layers-delete", GIMP_ICON_EDIT_DELETE, NC_("layers-action", "_Delete Layer"), NULL, NC_("layers-action", "Delete this layer"), - G_CALLBACK (layers_delete_cmd_callback), + layers_delete_cmd_callback, GIMP_HELP_LAYER_DELETE }, { "layers-raise", GIMP_ICON_GO_UP, NC_("layers-action", "_Raise Layer"), NULL, NC_("layers-action", "Raise this layer one step in the layer stack"), - G_CALLBACK (layers_raise_cmd_callback), + layers_raise_cmd_callback, GIMP_HELP_LAYER_RAISE }, { "layers-raise-to-top", GIMP_ICON_GO_TOP, NC_("layers-action", "Layer to _Top"), NULL, NC_("layers-action", "Move this layer to the top of the layer stack"), - G_CALLBACK (layers_raise_to_top_cmd_callback), + layers_raise_to_top_cmd_callback, GIMP_HELP_LAYER_RAISE_TO_TOP }, { "layers-lower", GIMP_ICON_GO_DOWN, NC_("layers-action", "_Lower Layer"), NULL, NC_("layers-action", "Lower this layer one step in the layer stack"), - G_CALLBACK (layers_lower_cmd_callback), + layers_lower_cmd_callback, GIMP_HELP_LAYER_LOWER }, { "layers-lower-to-bottom", GIMP_ICON_GO_BOTTOM, NC_("layers-action", "Layer to _Bottom"), NULL, NC_("layers-action", "Move this layer to the bottom of the layer stack"), - G_CALLBACK (layers_lower_to_bottom_cmd_callback), + layers_lower_to_bottom_cmd_callback, GIMP_HELP_LAYER_LOWER_TO_BOTTOM }, { "layers-anchor", GIMP_ICON_LAYER_ANCHOR, NC_("layers-action", "_Anchor Layer"), "H", NC_("layers-action", "Anchor the floating layer"), - G_CALLBACK (layers_anchor_cmd_callback), + layers_anchor_cmd_callback, GIMP_HELP_LAYER_ANCHOR }, { "layers-merge-down", GIMP_ICON_LAYER_MERGE_DOWN, NC_("layers-action", "Merge Do_wn"), NULL, NC_("layers-action", "Merge this layer with the first visible layer below it"), - G_CALLBACK (layers_merge_down_cmd_callback), + layers_merge_down_cmd_callback, GIMP_HELP_LAYER_MERGE_DOWN }, { "layers-merge-group", NULL, NC_("layers-action", "Merge Layer Group"), NULL, NC_("layers-action", "Merge the layer group's layers into one normal layer"), - G_CALLBACK (layers_merge_group_cmd_callback), + layers_merge_group_cmd_callback, GIMP_HELP_LAYER_MERGE_GROUP }, { "layers-merge-layers", NULL, NC_("layers-action", "Merge _Visible Layers..."), NULL, NC_("layers-action", "Merge all visible layers into one layer"), - G_CALLBACK (image_merge_layers_cmd_callback), + image_merge_layers_cmd_callback, GIMP_HELP_IMAGE_MERGE_LAYERS }, { "layers-flatten-image", NULL, NC_("layers-action", "_Flatten Image"), NULL, NC_("layers-action", "Merge all layers into one and remove transparency"), - G_CALLBACK (image_flatten_image_cmd_callback), + image_flatten_image_cmd_callback, GIMP_HELP_IMAGE_FLATTEN }, { "layers-text-discard", GIMP_ICON_TOOL_TEXT, NC_("layers-action", "_Discard Text Information"), NULL, NC_("layers-action", "Turn this text layer into a normal layer"), - G_CALLBACK (layers_text_discard_cmd_callback), + layers_text_discard_cmd_callback, GIMP_HELP_LAYER_TEXT_DISCARD }, { "layers-text-to-vectors", GIMP_ICON_TOOL_TEXT, NC_("layers-action", "Text to _Path"), NULL, NC_("layers-action", "Create a path from this text layer"), - G_CALLBACK (layers_text_to_vectors_cmd_callback), + layers_text_to_vectors_cmd_callback, GIMP_HELP_LAYER_TEXT_TO_PATH }, { "layers-text-along-vectors", GIMP_ICON_TOOL_TEXT, NC_("layers-action", "Text alon_g Path"), NULL, NC_("layers-action", "Warp this layer's text along the current path"), - G_CALLBACK (layers_text_along_vectors_cmd_callback), + layers_text_along_vectors_cmd_callback, GIMP_HELP_LAYER_TEXT_ALONG_PATH }, { "layers-resize", GIMP_ICON_OBJECT_RESIZE, NC_("layers-action", "Layer B_oundary Size..."), NULL, NC_("layers-action", "Adjust the layer dimensions"), - G_CALLBACK (layers_resize_cmd_callback), + layers_resize_cmd_callback, GIMP_HELP_LAYER_RESIZE }, { "layers-resize-to-image", GIMP_ICON_LAYER_TO_IMAGESIZE, NC_("layers-action", "Layer to _Image Size"), NULL, NC_("layers-action", "Resize the layer to the size of the image"), - G_CALLBACK (layers_resize_to_image_cmd_callback), + layers_resize_to_image_cmd_callback, GIMP_HELP_LAYER_RESIZE_TO_IMAGE }, { "layers-scale", GIMP_ICON_OBJECT_SCALE, NC_("layers-action", "_Scale Layer..."), NULL, NC_("layers-action", "Change the size of the layer content"), - G_CALLBACK (layers_scale_cmd_callback), + layers_scale_cmd_callback, GIMP_HELP_LAYER_SCALE }, { "layers-crop-to-selection", GIMP_ICON_TOOL_CROP, NC_("layers-action", "_Crop to Selection"), NULL, NC_("layers-action", "Crop the layer to the extents of the selection"), - G_CALLBACK (layers_crop_to_selection_cmd_callback), + layers_crop_to_selection_cmd_callback, GIMP_HELP_LAYER_CROP }, { "layers-crop-to-content", GIMP_ICON_TOOL_CROP, NC_("layers-action", "Crop to C_ontent"), NULL, NC_("layers-action", "Crop the layer to the extents of its content (remove empty borders from the layer)"), - G_CALLBACK (layers_crop_to_content_cmd_callback), + layers_crop_to_content_cmd_callback, GIMP_HELP_LAYER_CROP }, { "layers-mask-add", GIMP_ICON_LAYER_MASK, NC_("layers-action", "Add La_yer Mask..."), NULL, NC_("layers-action", "Add a mask that allows non-destructive editing of transparency"), - G_CALLBACK (layers_mask_add_cmd_callback), + layers_mask_add_cmd_callback, GIMP_HELP_LAYER_MASK_ADD }, /* this is the same as layers-mask-add, except it's sensitive even if @@ -257,26 +257,26 @@ NC_("layers-action", "Add La_yer Mask..."), NULL, NC_("layers-action", "Add a mask that allows non-destructive editing of transparency"), - G_CALLBACK (layers_mask_add_cmd_callback), + layers_mask_add_cmd_callback, GIMP_HELP_LAYER_MASK_ADD }, { "layers-mask-add-last-values", GIMP_ICON_LAYER_MASK, NC_("layers-action", "Add La_yer Mask"), NULL, NC_("layers-action", "Add a mask with last used values"), - G_CALLBACK (layers_mask_add_last_vals_cmd_callback), + layers_mask_add_last_vals_cmd_callback, GIMP_HELP_LAYER_MASK_ADD }, { "layers-alpha-add", GIMP_ICON_TRANSPARENCY, NC_("layers-action", "Add Alpha C_hannel"), NULL, NC_("layers-action", "Add transparency information to the layer"), - G_CALLBACK (layers_alpha_add_cmd_callback), + layers_alpha_add_cmd_callback, GIMP_HELP_LAYER_ALPHA_ADD }, { "layers-alpha-remove", NULL, NC_("layers-action", "_Remove Alpha Channel"), NULL, NC_("layers-action", "Remove transparency information from the layer"), - G_CALLBACK (layers_alpha_remove_cmd_callback), + layers_alpha_remove_cmd_callback, GIMP_HELP_LAYER_ALPHA_REMOVE } }; @@ -285,44 +285,44 @@ { "layers-mask-edit", GIMP_ICON_EDIT, NC_("layers-action", "_Edit Layer Mask"), NULL, NC_("layers-action", "Work on the layer mask"), - G_CALLBACK (layers_mask_edit_cmd_callback), + layers_mask_edit_cmd_callback, FALSE, GIMP_HELP_LAYER_MASK_EDIT }, { "layers-mask-show", GIMP_ICON_VISIBLE, NC_("layers-action", "S_how Layer Mask"), NULL, NULL, - G_CALLBACK (layers_mask_show_cmd_callback), + layers_mask_show_cmd_callback, FALSE, GIMP_HELP_LAYER_MASK_SHOW }, { "layers-mask-disable", NULL, NC_("layers-action", "_Disable Layer Mask"), NULL, NC_("layers-action", "Dismiss the effect of the layer mask"), - G_CALLBACK (layers_mask_disable_cmd_callback), + layers_mask_disable_cmd_callback, FALSE, GIMP_HELP_LAYER_MASK_DISABLE }, { "layers-visible", GIMP_ICON_VISIBLE, NC_("layers-action", "Toggle Layer _Visibility"), NULL, NULL, - G_CALLBACK (layers_visible_cmd_callback), + layers_visible_cmd_callback, FALSE, GIMP_HELP_LAYER_VISIBLE }, { "layers-linked", GIMP_ICON_LINKED, NC_("layers-action", "Toggle Layer _Linked State"), NULL, NULL, - G_CALLBACK (layers_linked_cmd_callback), + layers_linked_cmd_callback, FALSE, GIMP_HELP_LAYER_LINKED }, { "layers-lock-content", NULL /* GIMP_ICON_LOCK */, NC_("layers-action", "L_ock Pixels of Layer"), NULL, NULL, - G_CALLBACK (layers_lock_content_cmd_callback), + layers_lock_content_cmd_callback, FALSE, GIMP_HELP_LAYER_LOCK_PIXELS }, { "layers-lock-position", GIMP_ICON_TOOL_MOVE, NC_("layers-action", "L_ock Position of Layer"), NULL, NULL, - G_CALLBACK (layers_lock_position_cmd_callback), + layers_lock_position_cmd_callback, FALSE, GIMP_HELP_LAYER_LOCK_POSITION }, @@ -330,7 +330,7 @@ NC_("layers-action", "Lock Alph_a Channel"), NULL, NC_("layers-action", "Keep transparency information on this layer from being modified"), - G_CALLBACK (layers_lock_alpha_cmd_callback), + layers_lock_alpha_cmd_callback, FALSE, GIMP_HELP_LAYER_LOCK_ALPHA }, }; @@ -681,39 +681,39 @@ layers_blend_space_actions, G_N_ELEMENTS (layers_blend_space_actions), NULL, 0, - G_CALLBACK (layers_blend_space_cmd_callback)); + layers_blend_space_cmd_callback); gimp_action_group_add_radio_actions (group, "layers-action", layers_composite_space_actions, G_N_ELEMENTS (layers_composite_space_actions), NULL, 0, - G_CALLBACK (layers_composite_space_cmd_callback)); + layers_composite_space_cmd_callback); gimp_action_group_add_radio_actions (group, "layers-action", layers_composite_mode_actions, G_N_ELEMENTS (layers_composite_mode_actions), NULL, 0, - G_CALLBACK (layers_composite_mode_cmd_callback)); + layers_composite_mode_cmd_callback); gimp_action_group_add_enum_actions (group, "layers-action", layers_color_tag_actions, G_N_ELEMENTS (layers_color_tag_actions), - G_CALLBACK (layers_color_tag_cmd_callback)); + layers_color_tag_cmd_callback); gimp_action_group_add_enum_actions (group, "layers-action", layers_mask_apply_actions, G_N_ELEMENTS (layers_mask_apply_actions), - G_CALLBACK (layers_mask_apply_cmd_callback)); + layers_mask_apply_cmd_callback); gimp_action_group_add_enum_actions (group, "layers-action", layers_mask_to_selection_actions, G_N_ELEMENTS (layers_mask_to_selection_actions), - G_CALLBACK (layers_mask_to_selection_cmd_callback)); + layers_mask_to_selection_cmd_callback); gimp_action_group_add_enum_actions (group, "layers-action", layers_alpha_to_selection_actions, G_N_ELEMENTS (layers_alpha_to_selection_actions), - G_CALLBACK (layers_alpha_to_selection_cmd_callback)); + layers_alpha_to_selection_cmd_callback); layers_actions_fix_tooltip (group, "layers-alpha-selection-replace", GDK_MOD1_MASK); @@ -727,17 +727,17 @@ gimp_action_group_add_enum_actions (group, "layers-action", layers_select_actions, G_N_ELEMENTS (layers_select_actions), - G_CALLBACK (layers_select_cmd_callback)); + layers_select_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "layers-action", layers_opacity_actions, G_N_ELEMENTS (layers_opacity_actions), - G_CALLBACK (layers_opacity_cmd_callback)); + layers_opacity_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "layers-action", layers_mode_actions, G_N_ELEMENTS (layers_mode_actions), - G_CALLBACK (layers_mode_cmd_callback)); + layers_mode_cmd_callback); items_actions_setup (group, "layers"); } diff -Nru gimp-2.10.8+zorin2/app/actions/layers-commands.c gimp-2.10.14+om/app/actions/layers-commands.c --- gimp-2.10.8+zorin2/app/actions/layers-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/layers-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -57,6 +57,8 @@ #include "text/gimptext-vectors.h" #include "text/gimptextlayer.h" +#include "vectors/gimpstroke.h" +#include "vectors/gimpvectors.h" #include "vectors/gimpvectors-warp.h" #include "widgets/gimpaction.h" @@ -176,8 +178,9 @@ /* public functions */ void -layers_edit_cmd_callback (GtkAction *action, - gpointer data) +layers_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -187,17 +190,18 @@ if (gimp_item_is_text_layer (GIMP_ITEM (layer))) { - layers_edit_text_cmd_callback (action, data); + layers_edit_text_cmd_callback (action, value, data); } else { - layers_edit_attributes_cmd_callback (action, data); + layers_edit_attributes_cmd_callback (action, value, data); } } void -layers_edit_text_cmd_callback (GtkAction *action, - gpointer data) +layers_edit_text_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -235,8 +239,9 @@ } void -layers_edit_attributes_cmd_callback (GtkAction *action, - gpointer data) +layers_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -285,8 +290,9 @@ } void -layers_new_cmd_callback (GtkAction *action, - gpointer data) +layers_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -361,8 +367,9 @@ } void -layers_new_last_vals_cmd_callback (GtkAction *action, - gpointer data) +layers_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -380,7 +387,7 @@ */ if (gimp_image_get_floating_selection (image)) { - layers_new_cmd_callback (action, data); + layers_new_cmd_callback (action, value, data); return; } @@ -415,16 +422,19 @@ } void -layers_new_from_visible_cmd_callback (GtkAction *action, - gpointer data) +layers_new_from_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; + GimpDisplayShell *shell; GimpLayer *layer; GimpPickable *pickable; GimpColorProfile *profile; return_if_no_image (image, data); + return_if_no_shell (shell, data); - pickable = GIMP_PICKABLE (image); + pickable = gimp_display_shell_get_canvas_pickable (shell); gimp_pickable_flush (pickable); @@ -444,8 +454,9 @@ } void -layers_new_group_cmd_callback (GtkAction *action, - gpointer data) +layers_new_group_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -458,16 +469,19 @@ } void -layers_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpImage *image; - GimpLayer *layer; - GimpContainer *container; - GimpLayer *new_layer; +layers_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpImage *image; + GimpLayer *layer; + GimpContainer *container; + GimpLayer *new_layer; + GimpActionSelectType select_type; return_if_no_image (image, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + layer = gimp_image_get_active_layer (image); if (layer) @@ -475,7 +489,7 @@ else container = gimp_image_get_layers (image); - new_layer = (GimpLayer *) action_select_object ((GimpActionSelectType) value, + new_layer = (GimpLayer *) action_select_object (select_type, container, (GimpObject *) layer); @@ -487,8 +501,9 @@ } void -layers_raise_cmd_callback (GtkAction *action, - gpointer data) +layers_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -499,8 +514,9 @@ } void -layers_raise_to_top_cmd_callback (GtkAction *action, - gpointer data) +layers_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -511,8 +527,9 @@ } void -layers_lower_cmd_callback (GtkAction *action, - gpointer data) +layers_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -523,8 +540,9 @@ } void -layers_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data) +layers_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -535,8 +553,9 @@ } void -layers_duplicate_cmd_callback (GtkAction *action, - gpointer data) +layers_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -557,8 +576,9 @@ } void -layers_anchor_cmd_callback (GtkAction *action, - gpointer data) +layers_anchor_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -572,21 +592,26 @@ } void -layers_merge_down_cmd_callback (GtkAction *action, - gpointer data) +layers_merge_down_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpLayer *layer; + GimpImage *image; + GimpLayer *layer; + GimpDisplay *display; return_if_no_layer (image, layer, data); + return_if_no_display (display, data); gimp_image_merge_down (image, layer, action_data_get_context (data), - GIMP_EXPAND_AS_NECESSARY, NULL); + GIMP_EXPAND_AS_NECESSARY, + GIMP_PROGRESS (display), NULL); gimp_image_flush (image); } void -layers_merge_group_cmd_callback (GtkAction *action, - gpointer data) +layers_merge_group_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -597,8 +622,9 @@ } void -layers_delete_cmd_callback (GtkAction *action, - gpointer data) +layers_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -609,8 +635,9 @@ } void -layers_text_discard_cmd_callback (GtkAction *action, - gpointer data) +layers_text_discard_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -621,8 +648,9 @@ } void -layers_text_to_vectors_cmd_callback (GtkAction *action, - gpointer data) +layers_text_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -645,8 +673,9 @@ } void -layers_text_along_vectors_cmd_callback (GtkAction *action, - gpointer data) +layers_text_along_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -656,12 +685,42 @@ if (GIMP_IS_TEXT_LAYER (layer)) { + gdouble box_width; + gdouble box_height; GimpVectors *new_vectors; + gdouble offset; + + box_width = gimp_item_get_width (GIMP_ITEM (layer)); + box_height = gimp_item_get_height (GIMP_ITEM (layer)); new_vectors = gimp_text_vectors_new (image, GIMP_TEXT_LAYER (layer)->text); - gimp_vectors_warp_vectors (vectors, new_vectors, - 0.5 * gimp_item_get_height (GIMP_ITEM (layer))); + offset = 0; + switch (GIMP_TEXT_LAYER (layer)->text->base_dir) + { + case GIMP_TEXT_DIRECTION_LTR: + case GIMP_TEXT_DIRECTION_RTL: + offset = 0.5 * box_height; + break; + case GIMP_TEXT_DIRECTION_TTB_RTL: + case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT: + case GIMP_TEXT_DIRECTION_TTB_LTR: + case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT: + { + GimpStroke *stroke = NULL; + + while ((stroke = gimp_vectors_stroke_get_next (new_vectors, stroke))) + { + gimp_stroke_rotate (stroke, 0, 0, 270); + gimp_stroke_translate (stroke, 0, box_width); + } + } + offset = 0.5 * box_width; + break; + } + + + gimp_vectors_warp_vectors (vectors, new_vectors, offset); gimp_item_set_visible (GIMP_ITEM (new_vectors), TRUE, FALSE); @@ -672,8 +731,9 @@ } void -layers_resize_cmd_callback (GtkAction *action, - gpointer data) +layers_resize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -718,8 +778,9 @@ } void -layers_resize_to_image_cmd_callback (GtkAction *action, - gpointer data) +layers_resize_to_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -732,8 +793,9 @@ } void -layers_scale_cmd_callback (GtkAction *action, - gpointer data) +layers_scale_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -776,8 +838,9 @@ } void -layers_crop_to_selection_cmd_callback (GtkAction *action, - gpointer data) +layers_crop_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -814,8 +877,9 @@ } void -layers_crop_to_content_cmd_callback (GtkAction *action, - gpointer data) +layers_crop_to_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -860,8 +924,9 @@ } void -layers_mask_add_cmd_callback (GtkAction *action, - gpointer data) +layers_mask_add_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -895,8 +960,9 @@ } void -layers_mask_add_last_vals_cmd_callback (GtkAction *action, - gpointer data) +layers_mask_add_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -925,7 +991,7 @@ if (! channel) { - layers_mask_add_cmd_callback (action, data); + layers_mask_add_cmd_callback (action, value, data); return; } } @@ -942,9 +1008,9 @@ } void -layers_mask_apply_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_mask_apply_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -952,7 +1018,7 @@ if (gimp_layer_get_mask (layer)) { - GimpMaskApplyMode mode = (GimpMaskApplyMode) value; + GimpMaskApplyMode mode = (GimpMaskApplyMode) g_variant_get_int32 (value); gimp_layer_apply_mask (layer, mode, TRUE); gimp_image_flush (image); @@ -960,8 +1026,9 @@ } void -layers_mask_edit_cmd_callback (GtkAction *action, - gpointer data) +layers_mask_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -969,9 +1036,7 @@ if (gimp_layer_get_mask (layer)) { - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_layer_set_edit_mask (layer, active); gimp_image_flush (image); @@ -979,8 +1044,9 @@ } void -layers_mask_show_cmd_callback (GtkAction *action, - gpointer data) +layers_mask_show_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -988,9 +1054,7 @@ if (gimp_layer_get_mask (layer)) { - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_layer_set_show_mask (layer, active, TRUE); gimp_image_flush (image); @@ -998,8 +1062,9 @@ } void -layers_mask_disable_cmd_callback (GtkAction *action, - gpointer data) +layers_mask_disable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1007,9 +1072,7 @@ if (gimp_layer_get_mask (layer)) { - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_layer_set_apply_mask (layer, ! active, TRUE); gimp_image_flush (image); @@ -1017,9 +1080,9 @@ } void -layers_mask_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_mask_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1030,16 +1093,18 @@ if (mask) { - gimp_item_to_selection (GIMP_ITEM (mask), - (GimpChannelOps) value, + GimpChannelOps operation = (GimpChannelOps) g_variant_get_int32 (value); + + gimp_item_to_selection (GIMP_ITEM (mask), operation, TRUE, FALSE, 0.0, 0.0); gimp_image_flush (image); } } void -layers_alpha_add_cmd_callback (GtkAction *action, - gpointer data) +layers_alpha_add_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1053,8 +1118,9 @@ } void -layers_alpha_remove_cmd_callback (GtkAction *action, - gpointer data) +layers_alpha_remove_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1068,24 +1134,26 @@ } void -layers_alpha_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_alpha_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpLayer *layer; + GimpImage *image; + GimpLayer *layer; + GimpChannelOps operation; return_if_no_layer (image, layer, data); - gimp_item_to_selection (GIMP_ITEM (layer), - (GimpChannelOps) value, + operation = (GimpChannelOps) g_variant_get_int32 (value); + + gimp_item_to_selection (GIMP_ITEM (layer), operation, TRUE, FALSE, 0.0, 0.0); gimp_image_flush (image); } void -layers_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1109,9 +1177,9 @@ } void -layers_mode_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; @@ -1146,16 +1214,16 @@ } void -layers_blend_space_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +layers_blend_space_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; GimpLayerColorSpace blend_space; return_if_no_layer (image, layer, data); - blend_space = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + blend_space = (GimpLayerColorSpace) g_variant_get_int32 (value); if (blend_space != gimp_layer_get_blend_space (layer)) { @@ -1174,16 +1242,16 @@ } void -layers_composite_space_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +layers_composite_space_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; GimpLayerColorSpace composite_space; return_if_no_layer (image, layer, data); - composite_space = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + composite_space = (GimpLayerColorSpace) g_variant_get_int32 (value); if (composite_space != gimp_layer_get_composite_space (layer)) { @@ -1202,16 +1270,16 @@ } void -layers_composite_mode_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +layers_composite_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; GimpLayerCompositeMode composite_mode; return_if_no_layer (image, layer, data); - composite_mode = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + composite_mode = (GimpLayerCompositeMode) g_variant_get_int32 (value); if (composite_mode != gimp_layer_get_composite_mode (layer)) { @@ -1230,59 +1298,64 @@ } void -layers_visible_cmd_callback (GtkAction *action, +layers_visible_cmd_callback (GimpAction *action, + GVariant *value, gpointer data) { GimpImage *image; GimpLayer *layer; return_if_no_layer (image, layer, data); - items_visible_cmd_callback (action, image, GIMP_ITEM (layer)); + items_visible_cmd_callback (action, value, image, GIMP_ITEM (layer)); } void -layers_linked_cmd_callback (GtkAction *action, - gpointer data) +layers_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; return_if_no_layer (image, layer, data); - items_linked_cmd_callback (action, image, GIMP_ITEM (layer)); + items_linked_cmd_callback (action, value, image, GIMP_ITEM (layer)); } void -layers_lock_content_cmd_callback (GtkAction *action, - gpointer data) +layers_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; return_if_no_layer (image, layer, data); - items_lock_content_cmd_callback (action, image, GIMP_ITEM (layer)); + items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (layer)); } void -layers_lock_position_cmd_callback (GtkAction *action, - gpointer data) +layers_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; return_if_no_layer (image, layer, data); - items_lock_position_cmd_callback (action, image, GIMP_ITEM (layer)); + items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (layer)); } void -layers_lock_alpha_cmd_callback (GtkAction *action, - gpointer data) +layers_lock_alpha_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpLayer *layer; gboolean lock_alpha; return_if_no_layer (image, layer, data); - lock_alpha = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + lock_alpha = g_variant_get_boolean (value); if (lock_alpha != gimp_layer_get_lock_alpha (layer)) { @@ -1301,16 +1374,19 @@ } void -layers_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data) +layers_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpLayer *layer; + GimpImage *image; + GimpLayer *layer; + GimpColorTag color_tag; return_if_no_layer (image, layer, data); + color_tag = (GimpColorTag) g_variant_get_int32 (value); + items_color_tag_cmd_callback (action, image, GIMP_ITEM (layer), - (GimpColorTag) value); + color_tag); } diff -Nru gimp-2.10.8+zorin2/app/actions/layers-commands.h gimp-2.10.14+om/app/actions/layers-commands.h --- gimp-2.10.8+zorin2/app/actions/layers-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/layers-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,119 +19,155 @@ #define __LAYERS_COMMANDS_H__ -void layers_edit_cmd_callback (GtkAction *action, - gpointer data); -void layers_edit_text_cmd_callback (GtkAction *action, - gpointer data); -void layers_edit_attributes_cmd_callback (GtkAction *action, - gpointer data); - -void layers_new_cmd_callback (GtkAction *action, - gpointer data); -void layers_new_last_vals_cmd_callback (GtkAction *action, - gpointer data); -void layers_new_from_visible_cmd_callback (GtkAction *action, - gpointer data); - -void layers_new_group_cmd_callback (GtkAction *action, - gpointer data); - -void layers_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void layers_raise_cmd_callback (GtkAction *action, - gpointer data); -void layers_raise_to_top_cmd_callback (GtkAction *action, - gpointer data); -void layers_lower_cmd_callback (GtkAction *action, - gpointer data); -void layers_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data); - -void layers_duplicate_cmd_callback (GtkAction *action, - gpointer data); -void layers_anchor_cmd_callback (GtkAction *action, - gpointer data); -void layers_merge_down_cmd_callback (GtkAction *action, - gpointer data); -void layers_merge_group_cmd_callback (GtkAction *action, - gpointer data); -void layers_delete_cmd_callback (GtkAction *action, - gpointer data); -void layers_text_discard_cmd_callback (GtkAction *action, - gpointer data); -void layers_text_to_vectors_cmd_callback (GtkAction *action, - gpointer data); -void layers_text_along_vectors_cmd_callback (GtkAction *action, - gpointer data); - -void layers_resize_cmd_callback (GtkAction *action, - gpointer data); -void layers_resize_to_image_cmd_callback (GtkAction *action, - gpointer data); -void layers_scale_cmd_callback (GtkAction *action, - gpointer data); -void layers_crop_to_selection_cmd_callback (GtkAction *action, - gpointer data); -void layers_crop_to_content_cmd_callback (GtkAction *action, - gpointer data); - -void layers_mask_add_cmd_callback (GtkAction *action, - gpointer data); -void layers_mask_add_last_vals_cmd_callback (GtkAction *action, - gpointer data); -void layers_mask_apply_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void layers_mask_edit_cmd_callback (GtkAction *action, - gpointer data); -void layers_mask_show_cmd_callback (GtkAction *action, - gpointer data); -void layers_mask_disable_cmd_callback (GtkAction *action, - gpointer data); -void layers_mask_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void layers_alpha_add_cmd_callback (GtkAction *action, - gpointer data); -void layers_alpha_remove_cmd_callback (GtkAction *action, - gpointer data); -void layers_alpha_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void layers_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void layers_mode_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void layers_blend_space_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void layers_composite_space_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void layers_composite_mode_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); - -void layers_visible_cmd_callback (GtkAction *action, - gpointer data); -void layers_linked_cmd_callback (GtkAction *action, - gpointer data); -void layers_lock_content_cmd_callback (GtkAction *action, - gpointer data); -void layers_lock_position_cmd_callback (GtkAction *action, - gpointer data); -void layers_lock_alpha_cmd_callback (GtkAction *action, - gpointer data); - -void layers_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void layers_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_edit_text_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_new_from_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_new_group_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_anchor_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_merge_down_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_merge_group_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_text_discard_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_text_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_text_along_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_resize_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_resize_to_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_scale_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_crop_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_crop_to_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_mask_add_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_add_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_apply_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_show_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_disable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mask_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_alpha_add_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_alpha_remove_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_alpha_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_blend_space_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_composite_space_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_composite_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void layers_lock_alpha_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void layers_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __LAYERS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/Makefile.in gimp-2.10.14+om/app/actions/Makefile.in --- gimp-2.10.8+zorin2/app/actions/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/actions/Makefile.in 2019-10-27 17:12:52.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -329,8 +328,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -460,7 +457,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -599,8 +595,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/actions/mypaint-brushes-actions.c gimp-2.10.14+om/app/actions/mypaint-brushes-actions.c --- gimp-2.10.8+zorin2/app/actions/mypaint-brushes-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/mypaint-brushes-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,37 +46,37 @@ { "mypaint-brushes-new", GIMP_ICON_DOCUMENT_NEW, NC_("mypaint-brushes-action", "_New MyPaint Brush"), NULL, NC_("mypaint-brushes-action", "Create a new MyPaint brush"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_NEW }, { "mypaint-brushes-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("mypaint-brushes-action", "D_uplicate MyPaint Brush"), NULL, NC_("mypaint-brushes-action", "Duplicate this MyPaint brush"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_DUPLICATE }, { "mypaint-brushes-copy-location", GIMP_ICON_EDIT_COPY, NC_("mypaint-brushes-action", "Copy MyPaint Brush _Location"), NULL, NC_("mypaint-brushes-action", "Copy MyPaint brush file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_COPY_LOCATION }, { "mypaint-brushes-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("mypaint-brushes-action", "Show in _File Manager"), NULL, NC_("mypaint-brushes-action", "Show MyPaint brush file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_SHOW_IN_FILE_MANAGER }, { "mypaint-brushes-delete", GIMP_ICON_EDIT_DELETE, NC_("mypaint-brushes-action", "_Delete MyPaint Brush"), NULL, NC_("mypaint-brushes-action", "Delete this MyPaint brush"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_DELETE }, { "mypaint-brushes-refresh", GIMP_ICON_VIEW_REFRESH, NC_("mypaint-brushes-action", "_Refresh MyPaint Brushes"), NULL, NC_("mypaint-brushes-action", "Refresh MyPaint brushes"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_MYPAINT_BRUSH_REFRESH } }; @@ -100,7 +100,7 @@ gimp_action_group_add_string_actions (group, "mypaint-brushes-action", mypaint_brushes_edit_actions, G_N_ELEMENTS (mypaint_brushes_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/palette-editor-actions.c gimp-2.10.14+om/app/actions/palette-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/palette-editor-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palette-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,13 +47,13 @@ { "palette-editor-edit-color", GIMP_ICON_EDIT, NC_("palette-editor-action", "_Edit Color..."), NULL, NC_("palette-editor-action", "Edit this entry"), - G_CALLBACK (palette_editor_edit_color_cmd_callback), + palette_editor_edit_color_cmd_callback, GIMP_HELP_PALETTE_EDITOR_EDIT }, { "palette-editor-delete-color", GIMP_ICON_EDIT_DELETE, NC_("palette-editor-action", "_Delete Color"), NULL, NC_("palette-editor-action", "Delete this entry"), - G_CALLBACK (palette_editor_delete_color_cmd_callback), + palette_editor_delete_color_cmd_callback, GIMP_HELP_PALETTE_EDITOR_DELETE } }; @@ -61,7 +61,7 @@ { { "palette-editor-edit-active", GIMP_ICON_LINKED, NC_("palette-editor-action", "Edit Active Palette"), NULL, NULL, - G_CALLBACK (data_editor_edit_active_cmd_callback), + data_editor_edit_active_cmd_callback, FALSE, GIMP_HELP_PALETTE_EDITOR_EDIT_ACTIVE } }; @@ -119,12 +119,12 @@ gimp_action_group_add_enum_actions (group, "palette-editor-action", palette_editor_new_actions, G_N_ELEMENTS (palette_editor_new_actions), - G_CALLBACK (palette_editor_new_color_cmd_callback)); + palette_editor_new_color_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, palette_editor_zoom_actions, G_N_ELEMENTS (palette_editor_zoom_actions), - G_CALLBACK (palette_editor_zoom_cmd_callback)); + palette_editor_zoom_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/palette-editor-commands.c gimp-2.10.14+om/app/actions/palette-editor-commands.c --- gimp-2.10.8+zorin2/app/actions/palette-editor-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palette-editor-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -34,8 +34,9 @@ /* public functions */ void -palette_editor_edit_color_cmd_callback (GtkAction *action, - gpointer data) +palette_editor_edit_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data); @@ -43,12 +44,13 @@ } void -palette_editor_new_color_cmd_callback (GtkAction *action, - gint value, - gpointer data) +palette_editor_new_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); + gboolean background = (gboolean) g_variant_get_int32 (value); if (data_editor->data_editable) { @@ -56,7 +58,7 @@ GimpPaletteEntry *entry; GimpRGB color; - if (value) + if (background) gimp_context_get_background (data_editor->context, &color); else gimp_context_get_foreground (data_editor->context, &color); @@ -67,8 +69,9 @@ } void -palette_editor_delete_color_cmd_callback (GtkAction *action, - gpointer data) +palette_editor_delete_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data); GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data); @@ -82,11 +85,12 @@ } void -palette_editor_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data) +palette_editor_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data); + GimpPaletteEditor *editor = GIMP_PALETTE_EDITOR (data); + GimpZoomType zoom_type = (GimpZoomType) g_variant_get_int32 (value); - gimp_palette_editor_zoom (editor, (GimpZoomType) value); + gimp_palette_editor_zoom (editor, zoom_type); } diff -Nru gimp-2.10.8+zorin2/app/actions/palette-editor-commands.h gimp-2.10.14+om/app/actions/palette-editor-commands.h --- gimp-2.10.8+zorin2/app/actions/palette-editor-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palette-editor-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,17 +19,19 @@ #define __PALETTE_EDITOR_COMMANDS_H__ -void palette_editor_edit_color_cmd_callback (GtkAction *action, - gpointer data); -void palette_editor_new_color_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void palette_editor_delete_color_cmd_callback (GtkAction *action, - gpointer data); +void palette_editor_edit_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void palette_editor_new_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void palette_editor_delete_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void palette_editor_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void palette_editor_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __PALETTE_EDITOR_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/palettes-actions.c gimp-2.10.14+om/app/actions/palettes-actions.c --- gimp-2.10.8+zorin2/app/actions/palettes-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palettes-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,49 +47,49 @@ { "palettes-new", GIMP_ICON_DOCUMENT_NEW, NC_("palettes-action", "_New Palette"), NULL, NC_("palettes-action", "Create a new palette"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_PALETTE_NEW }, { "palettes-import", "gtk-convert", NC_("palettes-action", "_Import Palette..."), NULL, NC_("palettes-action", "Import palette"), - G_CALLBACK (palettes_import_cmd_callback), + palettes_import_cmd_callback, GIMP_HELP_PALETTE_IMPORT }, { "palettes-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("palettes-action", "D_uplicate Palette"), NULL, NC_("palettes-action", "Duplicate this palette"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_PALETTE_DUPLICATE }, { "palettes-merge", NULL, NC_("palettes-action", "_Merge Palettes..."), NULL, NC_("palettes-action", "Merge palettes"), - G_CALLBACK (palettes_merge_cmd_callback), + palettes_merge_cmd_callback, GIMP_HELP_PALETTE_MERGE }, { "palettes-copy-location", GIMP_ICON_EDIT_COPY, NC_("palettes-action", "Copy Palette _Location"), NULL, NC_("palettes-action", "Copy palette file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_PALETTE_COPY_LOCATION }, { "palettes-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("palettes-action", "Show in _File Manager"), NULL, NC_("palettes-action", "Show palette file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_PALETTE_SHOW_IN_FILE_MANAGER }, { "palettes-delete", GIMP_ICON_EDIT_DELETE, NC_("palettes-action", "_Delete Palette"), NULL, NC_("palettes-action", "Delete this palette"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_PALETTE_DELETE }, { "palettes-refresh", GIMP_ICON_VIEW_REFRESH, NC_("palettes-action", "_Refresh Palettes"), NULL, NC_("palettes-action", "Refresh palettes"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_PALETTE_REFRESH } }; @@ -113,7 +113,7 @@ gimp_action_group_add_string_actions (group, "palettes-action", palettes_edit_actions, G_N_ELEMENTS (palettes_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/palettes-commands.c gimp-2.10.14+om/app/actions/palettes-commands.c --- gimp-2.10.8+zorin2/app/actions/palettes-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palettes-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -54,8 +54,9 @@ /* public functions */ void -palettes_import_cmd_callback (GtkAction *action, - gpointer data) +palettes_import_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; return_if_no_widget (widget, data); @@ -68,8 +69,9 @@ } void -palettes_merge_cmd_callback (GtkAction *action, - gpointer data) +palettes_merge_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GtkWidget *dialog; diff -Nru gimp-2.10.8+zorin2/app/actions/palettes-commands.h gimp-2.10.14+om/app/actions/palettes-commands.h --- gimp-2.10.8+zorin2/app/actions/palettes-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/palettes-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,12 @@ #define __PALETTES_COMMANDS_H__ -void palettes_import_cmd_callback (GtkAction *action, - gpointer data); -void palettes_merge_cmd_callback (GtkAction *action, - gpointer data); +void palettes_import_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void palettes_merge_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __PALETTES_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/patterns-actions.c gimp-2.10.14+om/app/actions/patterns-actions.c --- gimp-2.10.8+zorin2/app/actions/patterns-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/patterns-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,43 +46,43 @@ { "patterns-open-as-image", GIMP_ICON_DOCUMENT_OPEN, NC_("patterns-action", "_Open Pattern as Image"), NULL, NC_("patterns-action", "Open this pattern as an image"), - G_CALLBACK (data_open_as_image_cmd_callback), + data_open_as_image_cmd_callback, GIMP_HELP_PATTERN_OPEN_AS_IMAGE }, { "patterns-new", GIMP_ICON_DOCUMENT_NEW, NC_("patterns-action", "_New Pattern"), NULL, NC_("patterns-action", "Create a new pattern"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_PATTERN_NEW }, { "patterns-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("patterns-action", "D_uplicate Pattern"), NULL, NC_("patterns-action", "Duplicate this pattern"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_PATTERN_DUPLICATE }, { "patterns-copy-location", GIMP_ICON_EDIT_COPY, NC_("patterns-action", "Copy Pattern _Location"), NULL, NC_("patterns-action", "Copy pattern file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_PATTERN_COPY_LOCATION }, { "patterns-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("patterns-action", "Show in _File Manager"), NULL, NC_("patterns-action", "Show pattern file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_PATTERN_SHOW_IN_FILE_MANAGER }, { "patterns-delete", GIMP_ICON_EDIT_DELETE, NC_("patterns-action", "_Delete Pattern"), NULL, NC_("patterns-action", "Delete this pattern"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_PATTERN_DELETE }, { "patterns-refresh", GIMP_ICON_VIEW_REFRESH, NC_("patterns-action", "_Refresh Patterns"), NULL, NC_("patterns-action", "Refresh patterns"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_PATTERN_REFRESH } }; @@ -106,7 +106,7 @@ gimp_action_group_add_string_actions (group, "patterns-action", patterns_edit_actions, G_N_ELEMENTS (patterns_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/plug-in-actions.c gimp-2.10.14+om/app/actions/plug-in-actions.c --- gimp-2.10.8+zorin2/app/actions/plug-in-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/plug-in-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -38,7 +38,9 @@ #include "plug-in/gimppluginmanager-menu-branch.h" #include "plug-in/gimppluginprocedure.h" +#include "widgets/gimpaction.h" #include "widgets/gimpactiongroup.h" +#include "widgets/gimpactionimpl.h" #include "widgets/gimphelp-ids.h" #include "actions.h" @@ -81,7 +83,7 @@ { "plug-in-reset-all", GIMP_ICON_RESET, NC_("plug-in-action", "Reset all _Filters"), NULL, NC_("plug-in-action", "Reset all plug-ins to their default settings"), - G_CALLBACK (plug_in_reset_all_cmd_callback), + plug_in_reset_all_cmd_callback, GIMP_HELP_FILTER_RESET_ALL } }; @@ -253,18 +255,18 @@ if ((plug_in_proc->menu_label || plug_in_proc->menu_paths) && ! plug_in_proc->file_proc) { - GtkAction *action; + GimpAction *action; #if 0 g_print ("%s: %s\n", G_STRFUNC, gimp_object_get_name (procedure)); #endif - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - gimp_object_get_name (procedure)); + action = gimp_action_group_get_action (group, + gimp_object_get_name (procedure)); if (action) - gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action); + gimp_action_group_remove_action (group, action); } } } @@ -346,7 +348,7 @@ entry.help_id = gimp_procedure_get_help_id (GIMP_PROCEDURE (proc)); gimp_action_group_add_procedure_actions (group, &entry, 1, - G_CALLBACK (plug_in_run_cmd_callback)); + plug_in_run_cmd_callback); if (proc->menu_label) { @@ -487,8 +489,8 @@ if (p1 && p2 && ! g_hash_table_lookup (path_table, copy_original)) { - GtkAction *action; - gchar *label; + GimpAction *action; + gchar *label; label = p2 + 1; @@ -497,8 +499,8 @@ copy_original, label); #endif - action = gtk_action_new (copy_original, label, NULL, NULL); - gtk_action_group_add_action (GTK_ACTION_GROUP (group), action); + action = gimp_action_impl_new (copy_original, label, NULL, NULL, NULL); + gimp_action_group_add_action (group, action); g_object_unref (action); g_hash_table_insert (path_table, g_strdup (copy_original), action); diff -Nru gimp-2.10.8+zorin2/app/actions/plug-in-commands.c gimp-2.10.14+om/app/actions/plug-in-commands.c --- gimp-2.10.8+zorin2/app/actions/plug-in-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/plug-in-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -67,15 +67,21 @@ /* public functions */ void -plug_in_run_cmd_callback (GtkAction *action, - GimpProcedure *procedure, - gpointer data) +plug_in_run_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpValueArray *args = NULL; GimpDisplay *display = NULL; + GimpProcedure *procedure; + gsize hack; return_if_no_gimp (gimp, data); + hack = g_variant_get_uint64 (value); + + procedure = GSIZE_TO_POINTER (hack); + switch (procedure->proc_type) { case GIMP_EXTENSION: @@ -157,8 +163,9 @@ } void -plug_in_reset_all_cmd_callback (GtkAction *action, - gpointer data) +plug_in_reset_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GtkWidget *dialog; diff -Nru gimp-2.10.8+zorin2/app/actions/plug-in-commands.h gimp-2.10.14+om/app/actions/plug-in-commands.h --- gimp-2.10.8+zorin2/app/actions/plug-in-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/plug-in-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,12 +19,13 @@ #define __PLUG_IN_COMMANDS_H__ -void plug_in_run_cmd_callback (GtkAction *action, - GimpProcedure *proc, - gpointer data); +void plug_in_run_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void plug_in_reset_all_cmd_callback (GtkAction *action, - gpointer data); +void plug_in_reset_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __PLUG_IN_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/quick-mask-actions.c gimp-2.10.14+om/app/actions/quick-mask-actions.c --- gimp-2.10.8+zorin2/app/actions/quick-mask-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/quick-mask-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -45,7 +45,7 @@ { "quick-mask-configure", NULL, NC_("quick-mask-action", "_Configure Color and Opacity..."), NULL, NULL, - G_CALLBACK (quick_mask_configure_cmd_callback), + quick_mask_configure_cmd_callback, GIMP_HELP_QUICK_MASK_EDIT } }; @@ -54,7 +54,7 @@ { "quick-mask-toggle", GIMP_ICON_QUICK_MASK_ON, NC_("quick-mask-action", "Toggle _Quick Mask"), "Q", NC_("quick-mask-action", "Toggle Quick Mask on/off"), - G_CALLBACK (quick_mask_toggle_cmd_callback), + quick_mask_toggle_cmd_callback, FALSE, GIMP_HELP_QUICK_MASK_TOGGLE } }; @@ -89,7 +89,7 @@ G_N_ELEMENTS (quick_mask_invert_actions), NULL, FALSE, - G_CALLBACK (quick_mask_invert_cmd_callback)); + quick_mask_invert_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/quick-mask-commands.c gimp-2.10.14+om/app/actions/quick-mask-commands.c --- gimp-2.10.8+zorin2/app/actions/quick-mask-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/quick-mask-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -42,6 +42,9 @@ #include "gimp-intl.h" +#define RGBA_EPSILON 1e-6 + + /* local function prototypes */ static void quick_mask_configure_callback (GtkWidget *dialog, @@ -62,14 +65,15 @@ /* public functions */ void -quick_mask_toggle_cmd_callback (GtkAction *action, - gpointer data) +quick_mask_toggle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; gboolean active; return_if_no_image (image, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_image_get_quick_mask_state (image)) { @@ -79,17 +83,17 @@ } void -quick_mask_invert_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +quick_mask_invert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; - gint value; + gboolean inverted; return_if_no_image (image, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + inverted = (gboolean) g_variant_get_int32 (value); - if (value != gimp_image_get_quick_mask_inverted (image)) + if (inverted != gimp_image_get_quick_mask_inverted (image)) { gimp_image_quick_mask_invert (image); gimp_image_flush (image); @@ -97,8 +101,9 @@ } void -quick_mask_configure_cmd_callback (GtkAction *action, - gpointer data) +quick_mask_configure_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -167,7 +172,7 @@ gimp_image_get_quick_mask_color (image, &old_color); - if (gimp_rgba_distance (&old_color, channel_color) > 0.0001) + if (gimp_rgba_distance (&old_color, channel_color) > RGBA_EPSILON) { gimp_image_set_quick_mask_color (image, channel_color); gimp_image_flush (image); diff -Nru gimp-2.10.8+zorin2/app/actions/quick-mask-commands.h gimp-2.10.14+om/app/actions/quick-mask-commands.h --- gimp-2.10.8+zorin2/app/actions/quick-mask-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/quick-mask-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,13 +19,15 @@ #define __QUICK_MASK_COMMANDS_H__ -void quick_mask_toggle_cmd_callback (GtkAction *action, - gpointer data); -void quick_mask_invert_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void quick_mask_configure_cmd_callback (GtkAction *action, - gpointer data); +void quick_mask_toggle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void quick_mask_invert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void quick_mask_configure_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __QUICK_MASK_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/sample-points-actions.c gimp-2.10.14+om/app/actions/sample-points-actions.c --- gimp-2.10.8+zorin2/app/actions/sample-points-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/sample-points-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,7 +47,7 @@ NC_("sample-points-action", "_Sample Merged"), "", NC_("sample-points-action", "Use the composite color of all visible layers"), - G_CALLBACK (sample_points_sample_merged_cmd_callback), + sample_points_sample_merged_cmd_callback, TRUE, GIMP_HELP_SAMPLE_POINT_SAMPLE_MERGED } }; diff -Nru gimp-2.10.8+zorin2/app/actions/sample-points-commands.c gimp-2.10.14+om/app/actions/sample-points-commands.c --- gimp-2.10.8+zorin2/app/actions/sample-points-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/sample-points-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,13 +30,12 @@ /* public functions */ void -sample_points_sample_merged_cmd_callback (GtkAction *action, - gpointer data) +sample_points_sample_merged_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpSamplePointEditor *editor = GIMP_SAMPLE_POINT_EDITOR (data); - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_sample_point_editor_set_sample_merged (editor, active); } diff -Nru gimp-2.10.8+zorin2/app/actions/sample-points-commands.h gimp-2.10.14+om/app/actions/sample-points-commands.h --- gimp-2.10.8+zorin2/app/actions/sample-points-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/sample-points-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,8 +19,9 @@ #define __SAMPLE_POINTS_COMMANDS_H__ -void sample_points_sample_merged_cmd_callback (GtkAction *action, - gpointer data); +void sample_points_sample_merged_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __SAMPLE_POINTS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/select-actions.c gimp-2.10.14+om/app/actions/select-actions.c --- gimp-2.10.8+zorin2/app/actions/select-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/select-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -49,92 +49,92 @@ { "select-all", GIMP_ICON_SELECTION_ALL, NC_("select-action", "_All"), "A", NC_("select-action", "Select everything"), - G_CALLBACK (select_all_cmd_callback), + select_all_cmd_callback, GIMP_HELP_SELECTION_ALL }, { "select-none", GIMP_ICON_SELECTION_NONE, NC_("select-action", "_None"), "A", NC_("select-action", "Dismiss the selection"), - G_CALLBACK (select_none_cmd_callback), + select_none_cmd_callback, GIMP_HELP_SELECTION_NONE }, { "select-invert", GIMP_ICON_INVERT, NC_("select-action", "_Invert"), "I", NC_("select-action", "Invert the selection"), - G_CALLBACK (select_invert_cmd_callback), + select_invert_cmd_callback, GIMP_HELP_SELECTION_INVERT }, { "select-float", GIMP_ICON_LAYER_FLOATING_SELECTION, NC_("select-action", "_Float"), "L", NC_("select-action", "Create a floating selection"), - G_CALLBACK (select_float_cmd_callback), + select_float_cmd_callback, GIMP_HELP_SELECTION_FLOAT }, { "select-feather", NULL, NC_("select-action", "Fea_ther..."), NULL, NC_("select-action", "Blur the selection border so that it fades out smoothly"), - G_CALLBACK (select_feather_cmd_callback), + select_feather_cmd_callback, GIMP_HELP_SELECTION_FEATHER }, { "select-sharpen", NULL, NC_("select-action", "_Sharpen"), NULL, NC_("select-action", "Remove fuzziness from the selection"), - G_CALLBACK (select_sharpen_cmd_callback), + select_sharpen_cmd_callback, GIMP_HELP_SELECTION_SHARPEN }, { "select-shrink", GIMP_ICON_SELECTION_SHRINK, NC_("select-action", "S_hrink..."), NULL, NC_("select-action", "Contract the selection"), - G_CALLBACK (select_shrink_cmd_callback), + select_shrink_cmd_callback, GIMP_HELP_SELECTION_SHRINK }, { "select-grow", GIMP_ICON_SELECTION_GROW, NC_("select-action", "_Grow..."), NULL, NC_("select-action", "Enlarge the selection"), - G_CALLBACK (select_grow_cmd_callback), + select_grow_cmd_callback, GIMP_HELP_SELECTION_GROW }, { "select-border", GIMP_ICON_SELECTION_BORDER, NC_("select-action", "Bo_rder..."), NULL, NC_("select-action", "Replace the selection by its border"), - G_CALLBACK (select_border_cmd_callback), + select_border_cmd_callback, GIMP_HELP_SELECTION_BORDER }, { "select-flood", NULL, NC_("select-action", "Re_move Holes"), NULL, NC_("select-action", "Remove holes from the selection"), - G_CALLBACK (select_flood_cmd_callback), + select_flood_cmd_callback, GIMP_HELP_SELECTION_FLOOD }, { "select-save", GIMP_ICON_SELECTION_TO_CHANNEL, NC_("select-action", "Save to _Channel"), NULL, NC_("select-action", "Save the selection to a channel"), - G_CALLBACK (select_save_cmd_callback), + select_save_cmd_callback, GIMP_HELP_SELECTION_TO_CHANNEL }, { "select-fill", GIMP_ICON_TOOL_BUCKET_FILL, NC_("select-action", "_Fill Selection Outline..."), NULL, NC_("select-action", "Fill the selection outline"), - G_CALLBACK (select_fill_cmd_callback), + select_fill_cmd_callback, GIMP_HELP_SELECTION_FILL }, { "select-fill-last-values", GIMP_ICON_TOOL_BUCKET_FILL, NC_("select-action", "_Fill Selection Outline"), NULL, NC_("select-action", "Fill the selection outline with last used values"), - G_CALLBACK (select_fill_last_vals_cmd_callback), + select_fill_last_vals_cmd_callback, GIMP_HELP_SELECTION_FILL }, { "select-stroke", GIMP_ICON_SELECTION_STROKE, NC_("select-action", "_Stroke Selection..."), NULL, NC_("select-action", "Paint along the selection outline"), - G_CALLBACK (select_stroke_cmd_callback), + select_stroke_cmd_callback, GIMP_HELP_SELECTION_STROKE }, { "select-stroke-last-values", GIMP_ICON_SELECTION_STROKE, NC_("select-action", "_Stroke Selection"), NULL, NC_("select-action", "Stroke the selection with last used values"), - G_CALLBACK (select_stroke_last_vals_cmd_callback), + select_stroke_last_vals_cmd_callback, GIMP_HELP_SELECTION_STROKE } }; diff -Nru gimp-2.10.8+zorin2/app/actions/select-commands.c gimp-2.10.14+om/app/actions/select-commands.c --- gimp-2.10.8+zorin2/app/actions/select-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/select-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -72,8 +72,9 @@ /* public functions */ void -select_all_cmd_callback (GtkAction *action, - gpointer data) +select_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -83,8 +84,9 @@ } void -select_none_cmd_callback (GtkAction *action, - gpointer data) +select_none_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -94,8 +96,9 @@ } void -select_invert_cmd_callback (GtkAction *action, - gpointer data) +select_invert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -105,8 +108,9 @@ } void -select_float_cmd_callback (GtkAction *action, - gpointer data) +select_float_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -131,8 +135,9 @@ } void -select_feather_cmd_callback (GtkAction *action, - gpointer data) +select_feather_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -148,6 +153,7 @@ if (! dialog) { GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config); + GtkWidget *button; gdouble xres; gdouble yres; @@ -165,6 +171,19 @@ G_OBJECT (image), "disconnect", select_feather_callback, image); + /* Edge lock button */ + button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image")); + g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button); + gimp_help_set_help_data (button, + _("When feathering, act as if selected areas " + "continued outside the image."), + NULL); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), + config->selection_feather_edge_lock); + gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button, + FALSE, FALSE, 0); + gtk_widget_show (button); + dialogs_attach_dialog (G_OBJECT (image), FEATHER_DIALOG_KEY, dialog); } @@ -172,8 +191,9 @@ } void -select_sharpen_cmd_callback (GtkAction *action, - gpointer data) +select_sharpen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -183,8 +203,9 @@ } void -select_shrink_cmd_callback (GtkAction *action, - gpointer data) +select_shrink_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -246,8 +267,9 @@ } void -select_grow_cmd_callback (GtkAction *action, - gpointer data) +select_grow_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -295,8 +317,9 @@ } void -select_border_cmd_callback (GtkAction *action, - gpointer data) +select_border_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -372,8 +395,9 @@ } void -select_flood_cmd_callback (GtkAction *action, - gpointer data) +select_flood_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -383,8 +407,9 @@ } void -select_save_cmd_callback (GtkAction *action, - gpointer data) +select_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpChannel *channel; @@ -411,8 +436,9 @@ } void -select_fill_cmd_callback (GtkAction *action, - gpointer data) +select_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -427,8 +453,9 @@ } void -select_fill_last_vals_cmd_callback (GtkAction *action, - gpointer data) +select_fill_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -440,8 +467,9 @@ } void -select_stroke_cmd_callback (GtkAction *action, - gpointer data) +select_stroke_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -456,8 +484,9 @@ } void -select_stroke_last_vals_cmd_callback (GtkAction *action, - gpointer data) +select_stroke_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; return_if_no_image (image, data); @@ -479,11 +508,16 @@ { GimpImage *image = GIMP_IMAGE (data); GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config); + GtkWidget *button; gdouble radius_x; gdouble radius_y; + button = g_object_get_data (G_OBJECT (widget), "edge-lock-toggle"); + g_object_set (config, "selection-feather-radius", size, + "selection-feather-edge-lock", + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)), NULL); radius_x = config->selection_feather_radius; @@ -506,7 +540,9 @@ radius_x *= factor; } - gimp_channel_feather (gimp_image_get_mask (image), radius_x, radius_y, TRUE); + gimp_channel_feather (gimp_image_get_mask (image), radius_x, radius_y, + config->selection_feather_edge_lock, + TRUE); gimp_image_flush (image); } @@ -617,7 +653,7 @@ button = g_object_get_data (G_OBJECT (widget), "edge-lock-toggle"); g_object_set (config, - "selection-shrink-radius", size, + "selection-shrink-radius", size, "selection-shrink-edge-lock", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)), NULL); diff -Nru gimp-2.10.8+zorin2/app/actions/select-commands.h gimp-2.10.14+om/app/actions/select-commands.h --- gimp-2.10.8+zorin2/app/actions/select-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/select-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,37 +19,52 @@ #define __SELECT_COMMANDS_H__ -void select_all_cmd_callback (GtkAction *action, - gpointer data); -void select_none_cmd_callback (GtkAction *action, - gpointer data); -void select_invert_cmd_callback (GtkAction *action, - gpointer data); -void select_float_cmd_callback (GtkAction *action, - gpointer data); -void select_feather_cmd_callback (GtkAction *action, - gpointer data); -void select_sharpen_cmd_callback (GtkAction *action, - gpointer data); -void select_shrink_cmd_callback (GtkAction *action, - gpointer data); -void select_grow_cmd_callback (GtkAction *action, - gpointer data); -void select_border_cmd_callback (GtkAction *action, - gpointer data); -void select_flood_cmd_callback (GtkAction *action, - gpointer data); -void select_save_cmd_callback (GtkAction *action, - gpointer data); +void select_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_none_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_invert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_float_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_feather_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_sharpen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_shrink_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_grow_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_border_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_flood_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); -void select_fill_cmd_callback (GtkAction *action, - gpointer data); -void select_fill_last_vals_cmd_callback (GtkAction *action, - gpointer data); -void select_stroke_cmd_callback (GtkAction *action, - gpointer data); -void select_stroke_last_vals_cmd_callback (GtkAction *action, - gpointer data); +void select_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_fill_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_stroke_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void select_stroke_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __SELECT_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/templates-actions.c gimp-2.10.14+om/app/actions/templates-actions.c --- gimp-2.10.8+zorin2/app/actions/templates-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/templates-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -45,31 +45,31 @@ { "templates-create-image", GIMP_ICON_IMAGE, NC_("templates-action", "_Create Image from Template"), "", NC_("templates-action", "Create a new image from the selected template"), - G_CALLBACK (templates_create_image_cmd_callback), + templates_create_image_cmd_callback, GIMP_HELP_TEMPLATE_IMAGE_NEW }, { "templates-new", GIMP_ICON_DOCUMENT_NEW, NC_("templates-action", "_New Template..."), NULL, NC_("templates-action", "Create a new template"), - G_CALLBACK (templates_new_cmd_callback), + templates_new_cmd_callback, GIMP_HELP_TEMPLATE_NEW }, { "templates-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("templates-action", "D_uplicate Template..."), "", NC_("templates-action", "Duplicate this template"), - G_CALLBACK (templates_duplicate_cmd_callback), + templates_duplicate_cmd_callback, GIMP_HELP_TEMPLATE_DUPLICATE }, { "templates-edit", GIMP_ICON_EDIT, NC_("templates-action", "_Edit Template..."), NULL, NC_("templates-action", "Edit this template"), - G_CALLBACK (templates_edit_cmd_callback), + templates_edit_cmd_callback, GIMP_HELP_TEMPLATE_EDIT }, { "templates-delete", GIMP_ICON_EDIT_DELETE, NC_("templates-action", "_Delete Template"), NULL, NC_("templates-action", "Delete this template"), - G_CALLBACK (templates_delete_cmd_callback), + templates_delete_cmd_callback, GIMP_HELP_TEMPLATE_DELETE } }; diff -Nru gimp-2.10.8+zorin2/app/actions/templates-commands.c gimp-2.10.14+om/app/actions/templates-commands.c --- gimp-2.10.8+zorin2/app/actions/templates-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/templates-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -80,8 +80,9 @@ /* public functions */ void -templates_create_image_cmd_callback (GtkAction *action, - gpointer data) +templates_create_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); @@ -111,8 +112,9 @@ } void -templates_new_cmd_callback (GtkAction *action, - gpointer data) +templates_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -143,8 +145,9 @@ } void -templates_duplicate_cmd_callback (GtkAction *action, - gpointer data) +templates_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -168,13 +171,14 @@ GIMP_OBJECT (new_template)); g_object_unref (new_template); - templates_edit_cmd_callback (action, data); + templates_edit_cmd_callback (action, value, data); } } void -templates_edit_cmd_callback (GtkAction *action, - gpointer data) +templates_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; @@ -214,8 +218,9 @@ } void -templates_delete_cmd_callback (GtkAction *action, - gpointer data) +templates_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; diff -Nru gimp-2.10.8+zorin2/app/actions/templates-commands.h gimp-2.10.14+om/app/actions/templates-commands.h --- gimp-2.10.8+zorin2/app/actions/templates-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/templates-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,16 +19,21 @@ #define __TEMPLATES_COMMANDS_H__ -void templates_create_image_cmd_callback (GtkAction *action, - gpointer data); -void templates_new_cmd_callback (GtkAction *action, - gpointer data); -void templates_duplicate_cmd_callback (GtkAction *action, - gpointer data); -void templates_edit_cmd_callback (GtkAction *action, - gpointer data); -void templates_delete_cmd_callback (GtkAction *action, - gpointer data); +void templates_create_image_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void templates_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void templates_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void templates_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void templates_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TEMPLATES_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/text-editor-actions.c gimp-2.10.14+om/app/actions/text-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/text-editor-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -43,13 +43,13 @@ { "text-editor-load", GIMP_ICON_DOCUMENT_OPEN, NC_("text-editor-action", "Open"), NULL, NC_("text-editor-action", "Load text from file"), - G_CALLBACK (text_editor_load_cmd_callback), + text_editor_load_cmd_callback, NULL }, { "text-editor-clear", GIMP_ICON_EDIT_CLEAR, NC_("text-editor-action", "Clear"), NULL, NC_("text-editor-action", "Clear all text"), - G_CALLBACK (text_editor_clear_cmd_callback), + text_editor_clear_cmd_callback, NULL } }; @@ -105,7 +105,7 @@ G_N_ELEMENTS (text_editor_direction_actions), NULL, GIMP_TEXT_DIRECTION_LTR, - G_CALLBACK (text_editor_direction_cmd_callback)); + text_editor_direction_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/text-editor-commands.c gimp-2.10.14+om/app/actions/text-editor-commands.c --- gimp-2.10.8+zorin2/app/actions/text-editor-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-editor-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,8 +47,9 @@ /* public functions */ void -text_editor_load_cmd_callback (GtkAction *action, - gpointer data) +text_editor_load_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextEditor *editor = GIMP_TEXT_EDITOR (data); @@ -91,8 +92,9 @@ } void -text_editor_clear_cmd_callback (GtkAction *action, - gpointer data) +text_editor_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextEditor *editor = GIMP_TEXT_EDITOR (data); GtkTextBuffer *buffer; @@ -103,16 +105,16 @@ } void -text_editor_direction_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +text_editor_direction_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpTextEditor *editor = GIMP_TEXT_EDITOR (data); - gint value; + GimpTextEditor *editor = GIMP_TEXT_EDITOR (data); + GimpTextDirection direction; - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + direction = (GimpTextDirection) g_variant_get_int32 (value); - gimp_text_editor_set_direction (editor, (GimpTextDirection) value); + gimp_text_editor_set_direction (editor, direction); } diff -Nru gimp-2.10.8+zorin2/app/actions/text-editor-commands.h gimp-2.10.14+om/app/actions/text-editor-commands.h --- gimp-2.10.8+zorin2/app/actions/text-editor-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-editor-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,13 +19,15 @@ #define __TEXT_EDITOR_COMMANDS_H__ -void text_editor_load_cmd_callback (GtkAction *action, - gpointer data); -void text_editor_clear_cmd_callback (GtkAction *action, - gpointer data); -void text_editor_direction_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); +void text_editor_load_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_editor_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_editor_direction_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TEXT_EDITOR_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/text-tool-actions.c gimp-2.10.14+om/app/actions/text-tool-actions.c --- gimp-2.10.8+zorin2/app/actions/text-tool-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-tool-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -56,47 +56,47 @@ { "text-tool-cut", GIMP_ICON_EDIT_CUT, NC_("text-tool-action", "Cu_t"), NULL, "X", - G_CALLBACK (text_tool_cut_cmd_callback), + text_tool_cut_cmd_callback, NULL }, { "text-tool-copy", GIMP_ICON_EDIT_COPY, NC_("text-tool-action", "_Copy"), NULL, "C", - G_CALLBACK (text_tool_copy_cmd_callback), + text_tool_copy_cmd_callback, NULL }, { "text-tool-paste", GIMP_ICON_EDIT_PASTE, NC_("text-tool-action", "_Paste"), NULL, "V", - G_CALLBACK (text_tool_paste_cmd_callback), + text_tool_paste_cmd_callback, NULL }, { "text-tool-delete", GIMP_ICON_EDIT_DELETE, NC_("text-tool-action", "_Delete"), NULL, NULL, - G_CALLBACK (text_tool_delete_cmd_callback), + text_tool_delete_cmd_callback, NULL }, { "text-tool-load", GIMP_ICON_DOCUMENT_OPEN, NC_("text-tool-action", "_Open text file..."), NULL, NULL, - G_CALLBACK (text_tool_load_cmd_callback), + text_tool_load_cmd_callback, NULL }, { "text-tool-clear", GIMP_ICON_EDIT_CLEAR, NC_("text-tool-action", "Cl_ear"), NULL, NC_("text-tool-action", "Clear all text"), - G_CALLBACK (text_tool_clear_cmd_callback), + text_tool_clear_cmd_callback, NULL }, { "text-tool-text-to-path", GIMP_ICON_PATH, NC_("text-tool-action", "_Path from Text"), "", NC_("text-tool-action", "Create a path from the outlines of the current text"), - G_CALLBACK (text_tool_text_to_path_cmd_callback), + text_tool_text_to_path_cmd_callback, NULL }, { "text-tool-text-along-path", GIMP_ICON_PATH, NC_("text-tool-action", "Text _along Path"), "", NC_("text-tool-action", "Bend the text along the currently active path"), - G_CALLBACK (text_tool_text_along_path_cmd_callback), + text_tool_text_along_path_cmd_callback, NULL } }; @@ -149,7 +149,7 @@ G_N_ELEMENTS (text_tool_direction_actions), NULL, GIMP_TEXT_DIRECTION_LTR, - G_CALLBACK (text_tool_direction_cmd_callback)); + text_tool_direction_cmd_callback); SET_HIDE_EMPTY ("text-tool-input-methods-menu", FALSE); } diff -Nru gimp-2.10.8+zorin2/app/actions/text-tool-commands.c gimp-2.10.14+om/app/actions/text-tool-commands.c --- gimp-2.10.8+zorin2/app/actions/text-tool-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-tool-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -54,8 +54,9 @@ /* public functions */ void -text_tool_cut_cmd_callback (GtkAction *action, - gpointer data) +text_tool_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -63,8 +64,9 @@ } void -text_tool_copy_cmd_callback (GtkAction *action, - gpointer data) +text_tool_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -72,8 +74,9 @@ } void -text_tool_paste_cmd_callback (GtkAction *action, - gpointer data) +text_tool_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -81,8 +84,9 @@ } void -text_tool_delete_cmd_callback (GtkAction *action, - gpointer data) +text_tool_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -90,8 +94,9 @@ } void -text_tool_load_cmd_callback (GtkAction *action, - gpointer data) +text_tool_load_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); GtkWidget *dialog; @@ -144,8 +149,9 @@ } void -text_tool_clear_cmd_callback (GtkAction *action, - gpointer data) +text_tool_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); @@ -157,8 +163,9 @@ } void -text_tool_text_to_path_cmd_callback (GtkAction *action, - gpointer data) +text_tool_text_to_path_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -166,8 +173,9 @@ } void -text_tool_text_along_path_cmd_callback (GtkAction *action, - gpointer data) +text_tool_text_along_path_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); @@ -175,17 +183,17 @@ } void -text_tool_direction_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +text_tool_direction_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); - gint value; + GimpTextTool *text_tool = GIMP_TEXT_TOOL (data); + GimpTextDirection direction; - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + direction = (GimpTextDirection) g_variant_get_int32 (value); g_object_set (text_tool->proxy, - "base-direction", (GimpTextDirection) value, + "base-direction", direction, NULL); } diff -Nru gimp-2.10.8+zorin2/app/actions/text-tool-commands.h gimp-2.10.14+om/app/actions/text-tool-commands.h --- gimp-2.10.8+zorin2/app/actions/text-tool-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/text-tool-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,25 +19,33 @@ #define __TEXT_TOOL_COMMANDS_H__ -void text_tool_cut_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_copy_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_paste_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_delete_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_load_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_clear_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_text_to_path_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_text_along_path_cmd_callback (GtkAction *action, - gpointer data); -void text_tool_direction_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); +void text_tool_cut_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_load_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_clear_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_text_to_path_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_text_along_path_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void text_tool_direction_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TEXT_TOOL_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/tool-options-actions.c gimp-2.10.14+om/app/actions/tool-options-actions.c --- gimp-2.10.8+zorin2/app/actions/tool-options-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-options-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -40,13 +40,13 @@ /* local function prototypes */ -static void tool_options_actions_update_presets (GimpActionGroup *group, - const gchar *action_prefix, - GCallback callback, - const gchar *help_id, - GimpContainer *presets, - gboolean need_writable, - gboolean need_deletable); +static void tool_options_actions_update_presets (GimpActionGroup *group, + const gchar *action_prefix, + GimpActionCallback callback, + const gchar *help_id, + GimpContainer *presets, + gboolean need_writable, + gboolean need_deletable); /* global variables */ @@ -75,19 +75,19 @@ { "tool-options-save-new-preset", GIMP_ICON_DOCUMENT_NEW, NC_("tool-options-action", "_New Tool Preset..."), "", NULL, - G_CALLBACK (tool_options_save_new_preset_cmd_callback), + tool_options_save_new_preset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_SAVE }, { "tool-options-reset", GIMP_ICON_RESET, NC_("tool-options-action", "R_eset Tool Options"), NULL, NC_("tool-options-action", "Reset to default values"), - G_CALLBACK (tool_options_reset_cmd_callback), + tool_options_reset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_RESET }, { "tool-options-reset-all", GIMP_ICON_RESET, NC_("tool-options-action", "Reset _all Tool Options"), NULL, NC_("tool-options-action", "Reset all tool options"), - G_CALLBACK (tool_options_reset_all_cmd_callback), + tool_options_reset_all_cmd_callback, GIMP_HELP_TOOL_OPTIONS_RESET } }; @@ -126,28 +126,28 @@ SET_VISIBLE ("tool-options-delete-preset-menu", tool_info->presets); tool_options_actions_update_presets (group, "tool-options-save-preset", - G_CALLBACK (tool_options_save_preset_cmd_callback), + tool_options_save_preset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_SAVE, tool_info->presets, TRUE /* writable */, FALSE /* deletable */); tool_options_actions_update_presets (group, "tool-options-restore-preset", - G_CALLBACK (tool_options_restore_preset_cmd_callback), + tool_options_restore_preset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_RESTORE, tool_info->presets, FALSE /* writable */, FALSE /* deletable */); tool_options_actions_update_presets (group, "tool-options-edit-preset", - G_CALLBACK (tool_options_edit_preset_cmd_callback), + tool_options_edit_preset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_EDIT, tool_info->presets, FALSE /* writable */, FALSE /* deletable */); tool_options_actions_update_presets (group, "tool-options-delete-preset", - G_CALLBACK (tool_options_delete_preset_cmd_callback), + tool_options_delete_preset_cmd_callback, GIMP_HELP_TOOL_OPTIONS_DELETE, tool_info->presets, FALSE /* writable */, @@ -158,13 +158,13 @@ /* private function */ static void -tool_options_actions_update_presets (GimpActionGroup *group, - const gchar *action_prefix, - GCallback callback, - const gchar *help_id, - GimpContainer *presets, - gboolean need_writable, - gboolean need_deletable) +tool_options_actions_update_presets (GimpActionGroup *group, + const gchar *action_prefix, + GimpActionCallback callback, + const gchar *help_id, + GimpContainer *presets, + gboolean need_writable, + gboolean need_deletable) { GList *list; gint n_children = 0; @@ -172,18 +172,17 @@ for (i = 0; ; i++) { - gchar *action_name; - GtkAction *action; + gchar *action_name; + GimpAction *action; action_name = g_strdup_printf ("%s-%03d", action_prefix, i); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); g_free (action_name); if (! action) break; - gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action); + gimp_action_group_remove_action (group, action); } if (presets) diff -Nru gimp-2.10.8+zorin2/app/actions/tool-options-commands.c gimp-2.10.14+om/app/actions/tool-options-commands.c --- gimp-2.10.8+zorin2/app/actions/tool-options-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-options-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -62,8 +62,9 @@ /* public functions */ void -tool_options_save_new_preset_cmd_callback (GtkAction *action, - gpointer user_data) +tool_options_save_new_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer user_data) { GimpEditor *editor = GIMP_EDITOR (user_data); Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp; @@ -77,18 +78,21 @@ } void -tool_options_save_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tool_options_save_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp; GimpContext *context = gimp_get_user_context (gimp); GimpToolInfo *tool_info = gimp_context_get_tool (context); GimpToolPreset *preset; + gint index; + + index = g_variant_get_int32 (value); preset = (GimpToolPreset *) - gimp_container_get_child_by_index (tool_info->presets, value); + gimp_container_get_child_by_index (tool_info->presets, index); if (preset) { @@ -100,18 +104,21 @@ } void -tool_options_restore_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tool_options_restore_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp; GimpContext *context = gimp_get_user_context (gimp); GimpToolInfo *tool_info = gimp_context_get_tool (context); GimpToolPreset *preset; + gint index; + + index = g_variant_get_int32 (value); preset = (GimpToolPreset *) - gimp_container_get_child_by_index (tool_info->presets, value); + gimp_container_get_child_by_index (tool_info->presets, index); if (preset) { @@ -123,18 +130,21 @@ } void -tool_options_edit_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tool_options_edit_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); Gimp *gimp = gimp_editor_get_ui_manager (editor)->gimp; GimpContext *context = gimp_get_user_context (gimp); GimpToolInfo *tool_info = gimp_context_get_tool (context); GimpToolPreset *preset; + gint index; + + index = g_variant_get_int32 (value); preset = (GimpToolPreset *) - gimp_container_get_child_by_index (tool_info->presets, value); + gimp_container_get_child_by_index (tool_info->presets, index); if (preset) { @@ -143,17 +153,20 @@ } void -tool_options_delete_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tool_options_delete_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); GimpContext *context = gimp_get_user_context (gimp_editor_get_ui_manager (editor)->gimp); GimpToolInfo *tool_info = gimp_context_get_tool (context); GimpToolPreset *preset; + gint index; + + index = g_variant_get_int32 (value); preset = (GimpToolPreset *) - gimp_container_get_child_by_index (tool_info->presets, value); + gimp_container_get_child_by_index (tool_info->presets, index); if (preset && gimp_data_is_deletable (GIMP_DATA (preset))) @@ -168,8 +181,9 @@ } void -tool_options_reset_cmd_callback (GtkAction *action, - gpointer data) +tool_options_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); GimpContext *context = gimp_get_user_context (gimp_editor_get_ui_manager (editor)->gimp); @@ -179,8 +193,9 @@ } void -tool_options_reset_all_cmd_callback (GtkAction *action, - gpointer data) +tool_options_reset_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpEditor *editor = GIMP_EDITOR (data); GtkWidget *dialog; diff -Nru gimp-2.10.8+zorin2/app/actions/tool-options-commands.h gimp-2.10.14+om/app/actions/tool-options-commands.h --- gimp-2.10.8+zorin2/app/actions/tool-options-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-options-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,26 +19,29 @@ #define __TOOL_OPTIONS_COMMANDS_H__ -void tool_options_save_new_preset_cmd_callback (GtkAction *action, - gpointer data); - -void tool_options_save_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tool_options_restore_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tool_options_edit_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tool_options_delete_preset_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tool_options_reset_cmd_callback (GtkAction *action, - gpointer data); -void tool_options_reset_all_cmd_callback (GtkAction *action, - gpointer data); +void tool_options_save_new_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tool_options_save_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_options_restore_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_options_edit_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_options_delete_preset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tool_options_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_options_reset_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TOOL_OPTIONS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/tool-preset-editor-actions.c gimp-2.10.14+om/app/actions/tool-preset-editor-actions.c --- gimp-2.10.8+zorin2/app/actions/tool-preset-editor-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-preset-editor-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -48,13 +48,13 @@ NC_("tool-preset-editor-action", "_Save Tool Options to Preset"), NULL, NC_("tool-preset-editor-action", "Save the active tool options to this " "tool preset"), - G_CALLBACK (tool_preset_editor_save_cmd_callback), + tool_preset_editor_save_cmd_callback, GIMP_HELP_TOOL_PRESET_SAVE }, { "tool-preset-editor-restore", GIMP_ICON_DOCUMENT_REVERT, NC_("tool-preset-editor-action", "_Restore Tool Preset"), NULL, NC_("tool-preset-editor-action", "Restore this tool preset"), - G_CALLBACK (tool_preset_editor_restore_cmd_callback), + tool_preset_editor_restore_cmd_callback, GIMP_HELP_TOOL_PRESET_RESTORE } }; @@ -63,7 +63,7 @@ { { "tool-preset-editor-edit-active", GIMP_ICON_LINKED, NC_("tool-preset-editor-action", "Edit Active Tool Preset"), NULL, NULL, - G_CALLBACK (data_editor_edit_active_cmd_callback), + data_editor_edit_active_cmd_callback, FALSE, GIMP_HELP_TOOL_PRESET_EDITOR_EDIT_ACTIVE } }; diff -Nru gimp-2.10.8+zorin2/app/actions/tool-preset-editor-commands.c gimp-2.10.14+om/app/actions/tool-preset-editor-commands.c --- gimp-2.10.8+zorin2/app/actions/tool-preset-editor-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-preset-editor-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -40,8 +40,9 @@ /* public functions */ void -tool_preset_editor_save_cmd_callback (GtkAction *action, - gpointer data) +tool_preset_editor_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDataEditor *editor = GIMP_DATA_EDITOR (data); GimpContext *context = editor->context; @@ -74,8 +75,9 @@ } void -tool_preset_editor_restore_cmd_callback (GtkAction *action, - gpointer data) +tool_preset_editor_restore_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDataEditor *editor = GIMP_DATA_EDITOR (data); GimpContext *context = editor->context; diff -Nru gimp-2.10.8+zorin2/app/actions/tool-preset-editor-commands.h gimp-2.10.14+om/app/actions/tool-preset-editor-commands.h --- gimp-2.10.8+zorin2/app/actions/tool-preset-editor-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-preset-editor-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,12 @@ #define __TOOL_PRESET_EDITOR_COMMANDS_H__ -void tool_preset_editor_save_cmd_callback (GtkAction *action, - gpointer data); -void tool_preset_editor_restore_cmd_callback (GtkAction *action, - gpointer data); +void tool_preset_editor_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_preset_editor_restore_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TOOL_PRESET_EDITOR_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/tool-presets-actions.c gimp-2.10.14+om/app/actions/tool-presets-actions.c --- gimp-2.10.8+zorin2/app/actions/tool-presets-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-presets-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -49,50 +49,50 @@ { "tool-presets-new", GIMP_ICON_DOCUMENT_NEW, NC_("tool-presets-action", "_New Tool Preset"), NULL, NC_("tool-presets-action", "Create a new tool preset"), - G_CALLBACK (data_new_cmd_callback), + data_new_cmd_callback, GIMP_HELP_TOOL_PRESET_NEW }, { "tool-presets-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("tool-presets-action", "D_uplicate Tool Preset"), NULL, NC_("tool-presets-action", "Duplicate this tool preset"), - G_CALLBACK (data_duplicate_cmd_callback), + data_duplicate_cmd_callback, GIMP_HELP_TOOL_PRESET_DUPLICATE }, { "tool-presets-copy-location", GIMP_ICON_EDIT_COPY, NC_("tool-presets-action", "Copy Tool Preset _Location"), NULL, NC_("tool-presets-action", "Copy tool preset file location to clipboard"), - G_CALLBACK (data_copy_location_cmd_callback), + data_copy_location_cmd_callback, GIMP_HELP_TOOL_PRESET_COPY_LOCATION }, { "tool-presets-show-in-file-manager", GIMP_ICON_FILE_MANAGER, NC_("tool-presets-action", "Show in _File Manager"), NULL, NC_("tool-presets-action", "Show tool preset file location in the file manager"), - G_CALLBACK (data_show_in_file_manager_cmd_callback), + data_show_in_file_manager_cmd_callback, GIMP_HELP_TOOL_PRESET_SHOW_IN_FILE_MANAGER }, { "tool-presets-save", GIMP_ICON_DOCUMENT_SAVE, NC_("tool-presets-action", "_Save Tool Options to Preset"), NULL, NC_("tool-presets-action", "Save the active tool options to this " "tool preset"), - G_CALLBACK (tool_presets_save_cmd_callback), + tool_presets_save_cmd_callback, GIMP_HELP_TOOL_PRESET_SAVE }, { "tool-presets-restore", GIMP_ICON_DOCUMENT_REVERT, NC_("tool-presets-action", "_Restore Tool Preset"), NULL, NC_("tool-presets-action", "Restore this tool preset"), - G_CALLBACK (tool_presets_restore_cmd_callback), + tool_presets_restore_cmd_callback, GIMP_HELP_TOOL_PRESET_RESTORE }, { "tool-presets-delete", GIMP_ICON_EDIT_DELETE, NC_("tool-presets-action", "_Delete Tool Preset"), NULL, NC_("tool-presets-action", "Delete this tool preset"), - G_CALLBACK (data_delete_cmd_callback), + data_delete_cmd_callback, GIMP_HELP_TOOL_PRESET_DELETE }, { "tool-presets-refresh", GIMP_ICON_VIEW_REFRESH, NC_("tool-presets-action", "_Refresh Tool Presets"), NULL, NC_("tool-presets-action", "Refresh tool presets"), - G_CALLBACK (data_refresh_cmd_callback), + data_refresh_cmd_callback, GIMP_HELP_TOOL_PRESET_REFRESH } }; @@ -116,7 +116,7 @@ gimp_action_group_add_string_actions (group, "tool-presets-action", tool_presets_edit_actions, G_N_ELEMENTS (tool_presets_edit_actions), - G_CALLBACK (data_edit_cmd_callback)); + data_edit_cmd_callback); } void diff -Nru gimp-2.10.8+zorin2/app/actions/tool-presets-commands.c gimp-2.10.14+om/app/actions/tool-presets-commands.c --- gimp-2.10.8+zorin2/app/actions/tool-presets-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-presets-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -41,8 +41,9 @@ /* public functions */ void -tool_presets_save_cmd_callback (GtkAction *action, - gpointer data) +tool_presets_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; @@ -77,8 +78,9 @@ } void -tool_presets_restore_cmd_callback (GtkAction *action, - gpointer data) +tool_presets_restore_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContext *context; diff -Nru gimp-2.10.8+zorin2/app/actions/tool-presets-commands.h gimp-2.10.14+om/app/actions/tool-presets-commands.h --- gimp-2.10.8+zorin2/app/actions/tool-presets-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tool-presets-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,12 @@ #define __TOOL_PRESETS_COMMANDS_H__ -void tool_presets_save_cmd_callback (GtkAction *action, - gpointer data); -void tool_presets_restore_cmd_callback (GtkAction *action, - gpointer data); +void tool_presets_save_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tool_presets_restore_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TOOL_PRESETS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/tools-actions.c gimp-2.10.14+om/app/actions/tools-actions.c --- gimp-2.10.8+zorin2/app/actions/tools-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tools-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -31,6 +31,7 @@ #include "core/gimpcontext.h" #include "core/gimptoolinfo.h" +#include "widgets/gimpaction.h" #include "widgets/gimpactiongroup.h" #include "widgets/gimphelp-ids.h" @@ -60,8 +61,14 @@ { "tools-rotate-arbitrary", GIMP_ICON_TOOL_ROTATE, NC_("tools-action", "_Arbitrary Rotation..."), "", - NC_("tools-action", "Rotate by an arbitrary angle"), + NC_("tools-action", "Rotate drawable by an arbitrary angle"), "gimp-rotate-layer", + GIMP_HELP_TOOL_ROTATE }, + + { "tools-rotate-image-arbitrary", GIMP_ICON_TOOL_ROTATE, + NC_("tools-action", "_Arbitrary Rotation..."), "", + NC_("tools-action", "Rotate image by an arbitrary angle"), + "gimp-rotate-image", GIMP_HELP_TOOL_ROTATE } }; @@ -618,8 +625,8 @@ void tools_actions_setup (GimpActionGroup *group) { - GtkAction *action; - GList *list; + GimpAction *action; + GList *list; gimp_action_group_add_actions (group, "tools-action", tools_actions, @@ -628,129 +635,129 @@ gimp_action_group_add_string_actions (group, "tools-action", tools_alternative_actions, G_N_ELEMENTS (tools_alternative_actions), - G_CALLBACK (tools_select_cmd_callback)); + tools_select_cmd_callback); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - "tools-by-color-select-short"); - gtk_action_set_accel_path (action, "/tools/tools-by-color-select"); + action = gimp_action_group_get_action (group, + "tools-by-color-select-short"); + gimp_action_set_accel_path (action, "/tools/tools-by-color-select"); gimp_action_group_add_enum_actions (group, NULL, tools_color_average_radius_actions, G_N_ELEMENTS (tools_color_average_radius_actions), - G_CALLBACK (tools_color_average_radius_cmd_callback)); + tools_color_average_radius_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_size_actions, G_N_ELEMENTS (tools_paintbrush_size_actions), - G_CALLBACK (tools_paintbrush_size_cmd_callback)); + tools_paintbrush_size_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_aspect_ratio_actions, G_N_ELEMENTS (tools_paintbrush_aspect_ratio_actions), - G_CALLBACK (tools_paintbrush_aspect_ratio_cmd_callback)); + tools_paintbrush_aspect_ratio_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_angle_actions, G_N_ELEMENTS (tools_paintbrush_angle_actions), - G_CALLBACK (tools_paintbrush_angle_cmd_callback)); + tools_paintbrush_angle_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_spacing_actions, G_N_ELEMENTS (tools_paintbrush_spacing_actions), - G_CALLBACK (tools_paintbrush_spacing_cmd_callback)); + tools_paintbrush_spacing_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_hardness_actions, G_N_ELEMENTS (tools_paintbrush_hardness_actions), - G_CALLBACK (tools_paintbrush_hardness_cmd_callback)); + tools_paintbrush_hardness_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_paintbrush_force_actions, G_N_ELEMENTS (tools_paintbrush_force_actions), - G_CALLBACK (tools_paintbrush_force_cmd_callback)); + tools_paintbrush_force_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_ink_blob_size_actions, G_N_ELEMENTS (tools_ink_blob_size_actions), - G_CALLBACK (tools_ink_blob_size_cmd_callback)); + tools_ink_blob_size_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_ink_blob_aspect_actions, G_N_ELEMENTS (tools_ink_blob_aspect_actions), - G_CALLBACK (tools_ink_blob_aspect_cmd_callback)); + tools_ink_blob_aspect_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_ink_blob_angle_actions, G_N_ELEMENTS (tools_ink_blob_angle_actions), - G_CALLBACK (tools_ink_blob_angle_cmd_callback)); + tools_ink_blob_angle_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "tools-action", tools_airbrush_rate_actions, G_N_ELEMENTS (tools_airbrush_rate_actions), - G_CALLBACK (tools_airbrush_rate_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_airbrush_rate_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_airbrush_flow_actions, G_N_ELEMENTS (tools_airbrush_flow_actions), - G_CALLBACK (tools_airbrush_flow_cmd_callback)); + tools_airbrush_flow_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_mybrush_radius_actions, G_N_ELEMENTS (tools_mybrush_radius_actions), - G_CALLBACK (tools_mybrush_radius_cmd_callback)); + tools_mybrush_radius_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_mybrush_hardness_actions, G_N_ELEMENTS (tools_mybrush_hardness_actions), - G_CALLBACK (tools_mybrush_hardness_cmd_callback)); + tools_mybrush_hardness_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_foreground_select_brush_size_actions, G_N_ELEMENTS (tools_foreground_select_brush_size_actions), - G_CALLBACK (tools_fg_select_brush_size_cmd_callback)); + tools_fg_select_brush_size_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_transform_preview_opacity_actions, G_N_ELEMENTS (tools_transform_preview_opacity_actions), - G_CALLBACK (tools_transform_preview_opacity_cmd_callback)); + tools_transform_preview_opacity_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_warp_effect_size_actions, G_N_ELEMENTS (tools_warp_effect_size_actions), - G_CALLBACK (tools_warp_effect_size_cmd_callback)); + tools_warp_effect_size_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_warp_effect_hardness_actions, G_N_ELEMENTS (tools_warp_effect_hardness_actions), - G_CALLBACK (tools_warp_effect_hardness_cmd_callback)); + tools_warp_effect_hardness_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "tools-action", tools_opacity_actions, G_N_ELEMENTS (tools_opacity_actions), - G_CALLBACK (tools_opacity_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_opacity_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_size_actions, G_N_ELEMENTS (tools_size_actions), - G_CALLBACK (tools_size_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_size_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_aspect_actions, G_N_ELEMENTS (tools_aspect_actions), - G_CALLBACK (tools_aspect_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_aspect_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_angle_actions, G_N_ELEMENTS (tools_angle_actions), - G_CALLBACK (tools_angle_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_angle_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_spacing_actions, G_N_ELEMENTS (tools_spacing_actions), - G_CALLBACK (tools_spacing_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_spacing_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_hardness_actions, G_N_ELEMENTS (tools_hardness_actions), - G_CALLBACK (tools_hardness_cmd_callback)); - gimp_action_group_add_enum_actions (group, NULL, + tools_hardness_cmd_callback); + gimp_action_group_add_enum_actions (group, "tools-action", tools_force_actions, G_N_ELEMENTS (tools_force_actions), - G_CALLBACK (tools_force_cmd_callback)); + tools_force_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_object_1_actions, G_N_ELEMENTS (tools_object_1_actions), - G_CALLBACK (tools_object_1_cmd_callback)); + tools_object_1_cmd_callback); gimp_action_group_add_enum_actions (group, NULL, tools_object_2_actions, G_N_ELEMENTS (tools_object_2_actions), - G_CALLBACK (tools_object_2_cmd_callback)); + tools_object_2_cmd_callback); for (list = gimp_get_tool_info_iter (group->gimp); list; @@ -784,7 +791,7 @@ gimp_action_group_add_string_actions (group, NULL, &entry, 1, - G_CALLBACK (tools_select_cmd_callback)); + tools_select_cmd_callback); g_free (name); } diff -Nru gimp-2.10.8+zorin2/app/actions/tools-commands.c gimp-2.10.14+om/app/actions/tools-commands.c --- gimp-2.10.8+zorin2/app/actions/tools-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tools-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -35,6 +35,7 @@ #include "paint/gimpairbrushoptions.h" #include "paint/gimpmybrushoptions.h" +#include "widgets/gimpaction.h" #include "widgets/gimpenumaction.h" #include "widgets/gimpuimanager.h" @@ -47,6 +48,7 @@ #include "tools/gimptool.h" #include "tools/gimptoolcontrol.h" #include "tools/gimptransformoptions.h" +#include "tools/gimptransformtool.h" #include "tools/gimpwarpoptions.h" #include "tools/tool_manager.h" @@ -57,48 +59,60 @@ /* local function prototypes */ static void tools_activate_enum_action (const gchar *action_desc, - gint value); + GVariant *value); /* public functions */ void -tools_select_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data) -{ - Gimp *gimp; - GimpToolInfo *tool_info; - GimpContext *context; - GimpDisplay *display; - gboolean rotate_layer = FALSE; +tools_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + Gimp *gimp; + GimpToolInfo *tool_info; + GimpContext *context; + GimpDisplay *display; + const gchar *tool_name; + gboolean set_transform_type = FALSE; + GimpTransformType transform_type; return_if_no_gimp (gimp, data); - /* special case gimp-rotate-tool being called from the Layer menu */ - if (strcmp (value, "gimp-rotate-layer") == 0) + tool_name = g_variant_get_string (value, NULL); + + /* special case gimp-rotate-tool being called from the Image or Layer + * menus + */ + if (strcmp (tool_name, "gimp-rotate-layer") == 0) + { + tool_name = "gimp-rotate-tool"; + set_transform_type = TRUE; + transform_type = GIMP_TRANSFORM_TYPE_LAYER; + } + else if (strcmp (tool_name, "gimp-rotate-image") == 0) { - rotate_layer = TRUE; - value = "gimp-rotate-tool"; + tool_name = "gimp-rotate-tool"; + set_transform_type = TRUE; + transform_type = GIMP_TRANSFORM_TYPE_IMAGE; } - tool_info = gimp_get_tool_info (gimp, value); + tool_info = gimp_get_tool_info (gimp, tool_name); context = gimp_get_user_context (gimp); /* always allocate a new tool when selected from the image menu */ if (gimp_context_get_tool (context) != tool_info) - { - gimp_context_set_tool (context, tool_info); - - if (rotate_layer) - g_object_set (tool_info->tool_options, - "type", GIMP_TRANSFORM_TYPE_LAYER, - NULL); - } + gimp_context_set_tool (context, tool_info); else + gimp_context_tool_changed (context); + + if (set_transform_type) { - gimp_context_tool_changed (context); + GimpTool *tool = tool_manager_get_active (gimp); + + gimp_transform_tool_set_type (GIMP_TRANSFORM_TOOL (tool), + transform_type); } display = gimp_context_get_display (context); @@ -108,19 +122,22 @@ } void -tools_color_average_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_color_average_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_COLOR_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "average-radius", @@ -129,19 +146,22 @@ } void -tools_paintbrush_size_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-size", @@ -150,19 +170,22 @@ } void -tools_paintbrush_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-angle", @@ -171,19 +194,22 @@ } void -tools_paintbrush_aspect_ratio_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-aspect-ratio", @@ -192,19 +218,22 @@ } void -tools_paintbrush_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-spacing", @@ -213,19 +242,22 @@ } void -tools_paintbrush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-hardness", @@ -234,19 +266,22 @@ } void -tools_paintbrush_force_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_paintbrush_force_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "brush-force", @@ -255,19 +290,22 @@ } void -tools_ink_blob_size_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_ink_blob_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "size", @@ -276,19 +314,22 @@ } void -tools_ink_blob_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_ink_blob_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "blob-aspect", @@ -297,19 +338,22 @@ } void -tools_ink_blob_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_ink_blob_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "blob-angle", @@ -321,19 +365,22 @@ } void -tools_airbrush_rate_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_airbrush_rate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "rate", @@ -342,19 +389,22 @@ } void -tools_airbrush_flow_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_airbrush_flow_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "flow", @@ -363,19 +413,22 @@ } void -tools_mybrush_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_mybrush_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "radius", @@ -384,19 +437,22 @@ } void -tools_mybrush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_mybrush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "hardness", @@ -405,19 +461,22 @@ } void -tools_fg_select_brush_size_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_fg_select_brush_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_FOREGROUND_SELECT_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "stroke-width", @@ -426,19 +485,22 @@ } void -tools_transform_preview_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_transform_preview_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_TRANSFORM_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "preview-opacity", @@ -447,19 +509,22 @@ } void -tools_warp_effect_size_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_warp_effect_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "effect-size", @@ -468,19 +533,22 @@ } void -tools_warp_effect_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_warp_effect_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpContext *context; - GimpToolInfo *tool_info; + GimpContext *context; + GimpToolInfo *tool_info; + GimpActionSelectType select_type; return_if_no_context (context, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + tool_info = gimp_context_get_tool (context); if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options)) { - action_select_property ((GimpActionSelectType) value, + action_select_property (select_type, action_data_get_display (data), G_OBJECT (tool_info->tool_options), "effect-hardness", @@ -489,9 +557,9 @@ } void -tools_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -511,9 +579,9 @@ } void -tools_size_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -533,9 +601,9 @@ } void -tools_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -555,9 +623,9 @@ } void -tools_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -577,9 +645,9 @@ } void -tools_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -599,9 +667,9 @@ } void -tools_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -621,9 +689,9 @@ } void -tools_force_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_force_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -643,9 +711,9 @@ } void -tools_object_1_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_object_1_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -665,9 +733,9 @@ } void -tools_object_2_cmd_callback (GtkAction *action, - gint value, - gpointer data) +tools_object_2_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpContext *context; GimpTool *tool; @@ -691,7 +759,7 @@ static void tools_activate_enum_action (const gchar *action_desc, - gint value) + GVariant *value) { gchar *group_name; gchar *action_name; @@ -701,8 +769,8 @@ if (action_name) { - GList *managers; - GtkAction *action; + GList *managers; + GimpAction *action; *action_name++ = '\0'; @@ -714,7 +782,7 @@ if (GIMP_IS_ENUM_ACTION (action) && GIMP_ENUM_ACTION (action)->value_variable) { - gimp_enum_action_selected (GIMP_ENUM_ACTION (action), value); + gimp_action_emit_activate (GIMP_ACTION (action), value); } } diff -Nru gimp-2.10.8+zorin2/app/actions/tools-commands.h gimp-2.10.14+om/app/actions/tools-commands.h --- gimp-2.10.8+zorin2/app/actions/tools-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/tools-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,100 +19,100 @@ #define __TOOLS_COMMANDS_H__ -void tools_select_cmd_callback (GtkAction *action, - const gchar *value, - gpointer data); - -void tools_color_average_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_paintbrush_size_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_paintbrush_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_paintbrush_aspect_ratio_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_paintbrush_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_paintbrush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_paintbrush_force_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_ink_blob_size_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_ink_blob_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_ink_blob_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_airbrush_rate_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_airbrush_flow_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_mybrush_radius_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_mybrush_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_fg_select_brush_size_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_transform_preview_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_warp_effect_size_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_warp_effect_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_opacity_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_size_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_aspect_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_angle_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_spacing_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_hardness_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_force_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void tools_object_1_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void tools_object_2_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void tools_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_color_average_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_paintbrush_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_paintbrush_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_paintbrush_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_paintbrush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_paintbrush_force_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_ink_blob_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_ink_blob_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_ink_blob_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_airbrush_rate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_airbrush_flow_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_mybrush_radius_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_mybrush_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_fg_select_brush_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_transform_preview_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_warp_effect_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_warp_effect_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_opacity_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_size_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_aspect_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_angle_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_spacing_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_hardness_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_force_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void tools_object_1_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void tools_object_2_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __TOOLS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/vectors-actions.c gimp-2.10.14+om/app/actions/vectors-actions.c --- gimp-2.10.8+zorin2/app/actions/vectors-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/vectors-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -53,110 +53,110 @@ { "vectors-edit", GIMP_ICON_TOOL_PATH, NC_("vectors-action", "Edit Pa_th"), NULL, NC_("vectors-action", "Edit the active path"), - G_CALLBACK (vectors_edit_cmd_callback), + vectors_edit_cmd_callback, GIMP_HELP_TOOL_VECTORS }, { "vectors-edit-attributes", GIMP_ICON_EDIT, NC_("vectors-action", "_Edit Path Attributes..."), NULL, NC_("vectors-action", "Edit path attributes"), - G_CALLBACK (vectors_edit_attributes_cmd_callback), + vectors_edit_attributes_cmd_callback, GIMP_HELP_PATH_EDIT }, { "vectors-new", GIMP_ICON_DOCUMENT_NEW, NC_("vectors-action", "_New Path..."), NULL, NC_("vectors-action", "Create a new path..."), - G_CALLBACK (vectors_new_cmd_callback), + vectors_new_cmd_callback, GIMP_HELP_PATH_NEW }, { "vectors-new-last-values", GIMP_ICON_DOCUMENT_NEW, NC_("vectors-action", "_New Path with last values"), NULL, NC_("vectors-action", "Create a new path with last used values"), - G_CALLBACK (vectors_new_last_vals_cmd_callback), + vectors_new_last_vals_cmd_callback, GIMP_HELP_PATH_NEW }, { "vectors-duplicate", GIMP_ICON_OBJECT_DUPLICATE, NC_("vectors-action", "D_uplicate Path"), NULL, NC_("vectors-action", "Duplicate this path"), - G_CALLBACK (vectors_duplicate_cmd_callback), + vectors_duplicate_cmd_callback, GIMP_HELP_PATH_DUPLICATE }, { "vectors-delete", GIMP_ICON_EDIT_DELETE, NC_("vectors-action", "_Delete Path"), NULL, NC_("vectors-action", "Delete this path"), - G_CALLBACK (vectors_delete_cmd_callback), + vectors_delete_cmd_callback, GIMP_HELP_PATH_DELETE }, { "vectors-merge-visible", NULL, NC_("vectors-action", "Merge _Visible Paths"), NULL, NULL, - G_CALLBACK (vectors_merge_visible_cmd_callback), + vectors_merge_visible_cmd_callback, GIMP_HELP_PATH_MERGE_VISIBLE }, { "vectors-raise", GIMP_ICON_GO_UP, NC_("vectors-action", "_Raise Path"), NULL, NC_("vectors-action", "Raise this path"), - G_CALLBACK (vectors_raise_cmd_callback), + vectors_raise_cmd_callback, GIMP_HELP_PATH_RAISE }, { "vectors-raise-to-top", GIMP_ICON_GO_TOP, NC_("vectors-action", "Raise Path to _Top"), NULL, NC_("vectors-action", "Raise this path to the top"), - G_CALLBACK (vectors_raise_to_top_cmd_callback), + vectors_raise_to_top_cmd_callback, GIMP_HELP_PATH_RAISE_TO_TOP }, { "vectors-lower", GIMP_ICON_GO_DOWN, NC_("vectors-action", "_Lower Path"), NULL, NC_("vectors-action", "Lower this path"), - G_CALLBACK (vectors_lower_cmd_callback), + vectors_lower_cmd_callback, GIMP_HELP_PATH_LOWER }, { "vectors-lower-to-bottom", GIMP_ICON_GO_BOTTOM, NC_("vectors-action", "Lower Path to _Bottom"), NULL, NC_("vectors-action", "Lower this path to the bottom"), - G_CALLBACK (vectors_lower_to_bottom_cmd_callback), + vectors_lower_to_bottom_cmd_callback, GIMP_HELP_PATH_LOWER_TO_BOTTOM }, { "vectors-fill", GIMP_ICON_TOOL_BUCKET_FILL, - NC_("vectors-action", "Fill Path..."), NULL, + NC_("vectors-action", "Fill Pat_h..."), NULL, NC_("vectors-action", "Fill the path"), - G_CALLBACK (vectors_fill_cmd_callback), + vectors_fill_cmd_callback, GIMP_HELP_PATH_FILL }, { "vectors-fill-last-values", GIMP_ICON_TOOL_BUCKET_FILL, NC_("vectors-action", "Fill Path"), NULL, NC_("vectors-action", "Fill the path with last values"), - G_CALLBACK (vectors_fill_last_vals_cmd_callback), + vectors_fill_last_vals_cmd_callback, GIMP_HELP_PATH_FILL }, { "vectors-stroke", GIMP_ICON_PATH_STROKE, NC_("vectors-action", "Stro_ke Path..."), NULL, NC_("vectors-action", "Paint along the path"), - G_CALLBACK (vectors_stroke_cmd_callback), + vectors_stroke_cmd_callback, GIMP_HELP_PATH_STROKE }, { "vectors-stroke-last-values", GIMP_ICON_PATH_STROKE, NC_("vectors-action", "Stro_ke Path"), NULL, NC_("vectors-action", "Paint along the path with last values"), - G_CALLBACK (vectors_stroke_last_vals_cmd_callback), + vectors_stroke_last_vals_cmd_callback, GIMP_HELP_PATH_STROKE }, { "vectors-copy", GIMP_ICON_EDIT_COPY, NC_("vectors-action", "Co_py Path"), "", NULL, - G_CALLBACK (vectors_copy_cmd_callback), + vectors_copy_cmd_callback, GIMP_HELP_PATH_COPY }, { "vectors-paste", GIMP_ICON_EDIT_PASTE, NC_("vectors-action", "Paste Pat_h"), "", NULL, - G_CALLBACK (vectors_paste_cmd_callback), + vectors_paste_cmd_callback, GIMP_HELP_PATH_PASTE }, { "vectors-export", GIMP_ICON_DOCUMENT_SAVE, NC_("vectors-action", "E_xport Path..."), "", NULL, - G_CALLBACK (vectors_export_cmd_callback), + vectors_export_cmd_callback, GIMP_HELP_PATH_EXPORT }, { "vectors-import", GIMP_ICON_DOCUMENT_OPEN, NC_("vectors-action", "I_mport Path..."), "", NULL, - G_CALLBACK (vectors_import_cmd_callback), + vectors_import_cmd_callback, GIMP_HELP_PATH_IMPORT } }; @@ -164,25 +164,25 @@ { { "vectors-visible", GIMP_ICON_VISIBLE, NC_("vectors-action", "Toggle Path _Visibility"), NULL, NULL, - G_CALLBACK (vectors_visible_cmd_callback), + vectors_visible_cmd_callback, FALSE, GIMP_HELP_PATH_VISIBLE }, { "vectors-linked", GIMP_ICON_LINKED, NC_("vectors-action", "Toggle Path _Linked State"), NULL, NULL, - G_CALLBACK (vectors_linked_cmd_callback), + vectors_linked_cmd_callback, FALSE, GIMP_HELP_PATH_LINKED }, { "vectors-lock-content", NULL /* GIMP_ICON_LOCK */, NC_("vectors-action", "L_ock Strokes of Path"), NULL, NULL, - G_CALLBACK (vectors_lock_content_cmd_callback), + vectors_lock_content_cmd_callback, FALSE, GIMP_HELP_PATH_LOCK_STROKES }, { "vectors-lock-position", GIMP_ICON_TOOL_MOVE, NC_("vectors-action", "L_ock Position of Path"), NULL, NULL, - G_CALLBACK (vectors_lock_position_cmd_callback), + vectors_lock_position_cmd_callback, FALSE, GIMP_HELP_PATH_LOCK_POSITION } }; @@ -339,22 +339,22 @@ gimp_action_group_add_enum_actions (group, "vectors-action", vectors_color_tag_actions, G_N_ELEMENTS (vectors_color_tag_actions), - G_CALLBACK (vectors_color_tag_cmd_callback)); + vectors_color_tag_cmd_callback); gimp_action_group_add_enum_actions (group, "vectors-action", vectors_to_selection_actions, G_N_ELEMENTS (vectors_to_selection_actions), - G_CALLBACK (vectors_to_selection_cmd_callback)); + vectors_to_selection_cmd_callback); gimp_action_group_add_enum_actions (group, "vectors-action", vectors_selection_to_vectors_actions, G_N_ELEMENTS (vectors_selection_to_vectors_actions), - G_CALLBACK (vectors_selection_to_vectors_cmd_callback)); + vectors_selection_to_vectors_cmd_callback); gimp_action_group_add_enum_actions (group, "vectors-action", vectors_select_actions, G_N_ELEMENTS (vectors_select_actions), - G_CALLBACK (vectors_select_cmd_callback)); + vectors_select_cmd_callback); items_actions_setup (group, "vectors"); } diff -Nru gimp-2.10.8+zorin2/app/actions/vectors-commands.c gimp-2.10.14+om/app/actions/vectors-commands.c --- gimp-2.10.8+zorin2/app/actions/vectors-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/vectors-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -111,8 +111,9 @@ /* public functions */ void -vectors_edit_cmd_callback (GtkAction *action, - gpointer data) +vectors_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -138,8 +139,9 @@ } void -vectors_edit_attributes_cmd_callback (GtkAction *action, - gpointer data) +vectors_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -180,8 +182,9 @@ } void -vectors_new_cmd_callback (GtkAction *action, - gpointer data) +vectors_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -221,8 +224,9 @@ } void -vectors_new_last_vals_cmd_callback (GtkAction *action, - gpointer data) +vectors_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -238,8 +242,9 @@ } void -vectors_raise_cmd_callback (GtkAction *action, - gpointer data) +vectors_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -250,8 +255,9 @@ } void -vectors_raise_to_top_cmd_callback (GtkAction *action, - gpointer data) +vectors_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -262,8 +268,9 @@ } void -vectors_lower_cmd_callback (GtkAction *action, - gpointer data) +vectors_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -274,8 +281,9 @@ } void -vectors_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data) +vectors_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -286,8 +294,9 @@ } void -vectors_duplicate_cmd_callback (GtkAction *action, - gpointer data) +vectors_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -307,8 +316,9 @@ } void -vectors_delete_cmd_callback (GtkAction *action, - gpointer data) +vectors_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -319,8 +329,9 @@ } void -vectors_merge_visible_cmd_callback (GtkAction *action, - gpointer data) +vectors_merge_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -342,35 +353,40 @@ } void -vectors_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data) +vectors_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpVectors *vectors; + GimpImage *image; + GimpVectors *vectors; + GimpChannelOps operation; return_if_no_vectors (image, vectors, data); - gimp_item_to_selection (GIMP_ITEM (vectors), - (GimpChannelOps) value, + operation = (GimpChannelOps) g_variant_get_int32 (value); + + gimp_item_to_selection (GIMP_ITEM (vectors), operation, TRUE, FALSE, 0, 0); gimp_image_flush (image); } void -vectors_selection_to_vectors_cmd_callback (GtkAction *action, - gint value, - gpointer data) +vectors_selection_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; GimpProcedure *procedure; GimpValueArray *args; GimpDisplay *display; + gboolean advanced; GError *error = NULL; return_if_no_image (image, data); return_if_no_widget (widget, data); - if (value) + advanced = (gboolean) g_variant_get_int32 (value); + + if (advanced) procedure = gimp_pdb_lookup_procedure (image->gimp->pdb, "plug-in-sel2path-advanced"); else @@ -412,8 +428,9 @@ } void -vectors_fill_cmd_callback (GtkAction *action, - gpointer data) +vectors_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -429,8 +446,9 @@ } void -vectors_fill_last_vals_cmd_callback (GtkAction *action, - gpointer data) +vectors_fill_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -442,8 +460,9 @@ } void -vectors_stroke_cmd_callback (GtkAction *action, - gpointer data) +vectors_stroke_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -459,8 +478,9 @@ } void -vectors_stroke_last_vals_cmd_callback (GtkAction *action, - gpointer data) +vectors_stroke_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -472,8 +492,9 @@ } void -vectors_copy_cmd_callback (GtkAction *action, - gpointer data) +vectors_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -490,8 +511,9 @@ } void -vectors_paste_cmd_callback (GtkAction *action, - gpointer data) +vectors_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -525,8 +547,9 @@ } void -vectors_export_cmd_callback (GtkAction *action, - gpointer data) +vectors_export_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; @@ -564,8 +587,9 @@ } void -vectors_import_cmd_callback (GtkAction *action, - gpointer data) +vectors_import_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GtkWidget *widget; @@ -600,60 +624,67 @@ } void -vectors_visible_cmd_callback (GtkAction *action, - gpointer data) +vectors_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; return_if_no_vectors (image, vectors, data); - items_visible_cmd_callback (action, image, GIMP_ITEM (vectors)); + items_visible_cmd_callback (action, value, image, GIMP_ITEM (vectors)); } void -vectors_linked_cmd_callback (GtkAction *action, - gpointer data) +vectors_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; return_if_no_vectors (image, vectors, data); - items_linked_cmd_callback (action, image, GIMP_ITEM (vectors)); + items_linked_cmd_callback (action, value, image, GIMP_ITEM (vectors)); } void -vectors_lock_content_cmd_callback (GtkAction *action, - gpointer data) +vectors_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; return_if_no_vectors (image, vectors, data); - items_lock_content_cmd_callback (action, image, GIMP_ITEM (vectors)); + items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (vectors)); } void -vectors_lock_position_cmd_callback (GtkAction *action, - gpointer data) +vectors_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; return_if_no_vectors (image, vectors, data); - items_lock_position_cmd_callback (action, image, GIMP_ITEM (vectors)); + items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (vectors)); } void -vectors_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data) +vectors_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpImage *image; - GimpVectors *vectors; + GimpImage *image; + GimpVectors *vectors; + GimpColorTag color_tag; return_if_no_vectors (image, vectors, data); + color_tag = (GimpColorTag) g_variant_get_int32 (value); + items_color_tag_cmd_callback (action, image, GIMP_ITEM (vectors), - (GimpColorTag) value); + color_tag); } @@ -829,9 +860,9 @@ } void -vectors_select_cmd_callback (GtkAction *action, - gint value, - gpointer data) +vectors_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpVectors *vectors; diff -Nru gimp-2.10.8+zorin2/app/actions/vectors-commands.h gimp-2.10.14+om/app/actions/vectors-commands.h --- gimp-2.10.8+zorin2/app/actions/vectors-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/vectors-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,70 +19,94 @@ #define __VECTORS_COMMANDS_H__ -void vectors_edit_cmd_callback (GtkAction *action, - gpointer data); -void vectors_edit_attributes_cmd_callback (GtkAction *action, - gpointer data); -void vectors_new_cmd_callback (GtkAction *action, - gpointer data); -void vectors_new_last_vals_cmd_callback (GtkAction *action, - gpointer data); - -void vectors_raise_cmd_callback (GtkAction *action, - gpointer data); -void vectors_raise_to_top_cmd_callback (GtkAction *action, - gpointer data); -void vectors_lower_cmd_callback (GtkAction *action, - gpointer data); -void vectors_lower_to_bottom_cmd_callback (GtkAction *action, - gpointer data); - -void vectors_duplicate_cmd_callback (GtkAction *action, - gpointer data); -void vectors_delete_cmd_callback (GtkAction *action, - gpointer data); -void vectors_merge_visible_cmd_callback (GtkAction *action, - gpointer data); -void vectors_to_selection_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void vectors_selection_to_vectors_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void vectors_fill_cmd_callback (GtkAction *action, - gpointer data); -void vectors_fill_last_vals_cmd_callback (GtkAction *action, - gpointer data); -void vectors_stroke_cmd_callback (GtkAction *action, - gpointer data); -void vectors_stroke_last_vals_cmd_callback (GtkAction *action, - gpointer data); - -void vectors_copy_cmd_callback (GtkAction *action, - gpointer data); -void vectors_paste_cmd_callback (GtkAction *action, - gpointer data); -void vectors_export_cmd_callback (GtkAction *action, - gpointer data); -void vectors_import_cmd_callback (GtkAction *action, - gpointer data); - -void vectors_visible_cmd_callback (GtkAction *action, - gpointer data); -void vectors_linked_cmd_callback (GtkAction *action, - gpointer data); -void vectors_lock_content_cmd_callback (GtkAction *action, - gpointer data); -void vectors_lock_position_cmd_callback (GtkAction *action, - gpointer data); - -void vectors_color_tag_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void vectors_select_cmd_callback (GtkAction *action, - gint value, - gpointer data); +void vectors_edit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_edit_attributes_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_new_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_raise_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_raise_to_top_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_lower_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_lower_to_bottom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_duplicate_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_delete_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_merge_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_to_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_selection_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_fill_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_stroke_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_stroke_last_vals_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_copy_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_paste_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_export_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_import_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_visible_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_linked_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_lock_content_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void vectors_lock_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_color_tag_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void vectors_select_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + #endif /* __VECTORS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/view-actions.c gimp-2.10.14+om/app/actions/view-actions.c --- gimp-2.10.8+zorin2/app/actions/view-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/view-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -88,123 +88,131 @@ { "view-new", GIMP_ICON_WINDOW_NEW, NC_("view-action", "_New View"), NULL, NC_("view-action", "Create another view on this image"), - G_CALLBACK (view_new_cmd_callback), + view_new_cmd_callback, GIMP_HELP_VIEW_NEW }, { "view-close", GIMP_ICON_WINDOW_CLOSE, NC_("view-action", "_Close View"), "W", NC_("view-action", "Close the active image view"), - G_CALLBACK (view_close_cmd_callback), + view_close_cmd_callback, GIMP_HELP_FILE_CLOSE }, { "view-scroll-center", GIMP_ICON_CENTER, - NC_("view-action", "Center Image in Window"), "J", + NC_("view-action", "C_enter Image in Window"), "J", NC_("view-action", "Scroll the image so that it is centered in the window"), - G_CALLBACK (view_scroll_center_cmd_callback), + view_scroll_center_cmd_callback, GIMP_HELP_VIEW_SCROLL_CENTER }, { "view-zoom-fit-in", GIMP_ICON_ZOOM_FIT_BEST, NC_("view-action", "_Fit Image in Window"), "J", NC_("view-action", "Adjust the zoom ratio so that the image becomes fully visible"), - G_CALLBACK (view_zoom_fit_in_cmd_callback), + view_zoom_fit_in_cmd_callback, GIMP_HELP_VIEW_ZOOM_FIT_IN }, { "view-zoom-fill", GIMP_ICON_ZOOM_FIT_BEST, NC_("view-action", "Fi_ll Window"), NULL, NC_("view-action", "Adjust the zoom ratio so that the entire window is used"), - G_CALLBACK (view_zoom_fill_cmd_callback), + view_zoom_fill_cmd_callback, GIMP_HELP_VIEW_ZOOM_FILL }, { "view-zoom-selection", GIMP_ICON_SELECTION, NC_("view-action", "Zoom to _Selection"), NULL, NC_("view-action", "Adjust the zoom ratio so that the selection fills the window"), - G_CALLBACK (view_zoom_selection_cmd_callback), + view_zoom_selection_cmd_callback, GIMP_HELP_VIEW_ZOOM_SELECTION }, { "view-zoom-revert", NULL, NC_("view-action", "Re_vert Zoom"), "grave", NC_("view-action", "Restore the previous zoom level"), - G_CALLBACK (view_zoom_revert_cmd_callback), + view_zoom_revert_cmd_callback, GIMP_HELP_VIEW_ZOOM_REVERT }, { "view-rotate-other", NULL, NC_("view-action", "Othe_r rotation angle..."), NULL, NC_("view-action", "Set a custom rotation angle"), - G_CALLBACK (view_rotate_other_cmd_callback), + view_rotate_other_cmd_callback, GIMP_HELP_VIEW_ROTATE_OTHER }, { "view-navigation-window", GIMP_ICON_DIALOG_NAVIGATION, NC_("view-action", "Na_vigation Window"), NULL, NC_("view-action", "Show an overview window for this image"), - G_CALLBACK (view_navigation_window_cmd_callback), + view_navigation_window_cmd_callback, GIMP_HELP_NAVIGATION_DIALOG }, { "view-display-filters", GIMP_ICON_DISPLAY_FILTER, NC_("view-action", "Display _Filters..."), NULL, NC_("view-action", "Configure filters applied to this view"), - G_CALLBACK (view_display_filters_cmd_callback), + view_display_filters_cmd_callback, GIMP_HELP_DISPLAY_FILTER_DIALOG }, { "view-color-management-reset", GIMP_ICON_RESET, NC_("view-action", "As in _Preferences"), NULL, NC_("view-action", "Reset color management to what's configured in preferences"), - G_CALLBACK (view_color_management_reset_cmd_callback), + view_color_management_reset_cmd_callback, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-softproof-profile", NULL, NC_("view-action", "Soft-_Proofing Profile..."), NULL, NC_("view-action", "Set the soft-proofing profile"), - G_CALLBACK (view_softproof_profile_cmd_callback), + view_softproof_profile_cmd_callback, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-shrink-wrap", GIMP_ICON_ZOOM_FIT_BEST, NC_("view-action", "Shrink _Wrap"), "J", NC_("view-action", "Reduce the image window to the size of the image display"), - G_CALLBACK (view_shrink_wrap_cmd_callback), + view_shrink_wrap_cmd_callback, GIMP_HELP_VIEW_SHRINK_WRAP }, { "view-open-display", NULL, NC_("view-action", "_Open Display..."), NULL, NC_("view-action", "Connect to another display"), - G_CALLBACK (window_open_display_cmd_callback), + window_open_display_cmd_callback, NULL } }; static const GimpToggleActionEntry view_toggle_actions[] = { + + { "view-show-all", NULL, + NC_("view-action", "Show _All"), NULL, + NC_("view-action", "Show full image content"), + view_show_all_cmd_callback, + FALSE, + GIMP_HELP_VIEW_SHOW_ALL }, + { "view-dot-for-dot", NULL, NC_("view-action", "_Dot for Dot"), NULL, NC_("view-action", "A pixel on the screen represents an image pixel"), - G_CALLBACK (view_dot_for_dot_cmd_callback), + view_dot_for_dot_cmd_callback, TRUE, GIMP_HELP_VIEW_DOT_FOR_DOT }, { "view-color-management-enable", NULL, NC_("view-action", "_Color-Manage this View"), NULL, NC_("view-action", "Use color management for this view"), - G_CALLBACK (view_color_management_enable_cmd_callback), + view_color_management_enable_cmd_callback, TRUE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-color-management-softproof", NULL, NC_("view-action", "_Proof Colors"), NULL, NC_("view-action", "Use this view for soft-proofing"), - G_CALLBACK (view_color_management_softproof_cmd_callback), + view_color_management_softproof_cmd_callback, FALSE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-display-black-point-compensation", NULL, NC_("view-action", "_Black Point Compensation"), NULL, NC_("view-action", "Use black point compensation for image display"), - G_CALLBACK (view_display_bpc_cmd_callback), + view_display_bpc_cmd_callback, TRUE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-softproof-black-point-compensation", NULL, NC_("view-action", "_Black Point Compensation"), NULL, NC_("view-action", "Use black point compensation for soft-proofing"), - G_CALLBACK (view_softproof_bpc_cmd_callback), + view_softproof_bpc_cmd_callback, TRUE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, @@ -212,105 +220,112 @@ NC_("view-action", "_Mark Out Of Gamut Colors"), NULL, NC_("view-action", "When soft-proofing, mark colors which cannot " "be represented in the target color space"), - G_CALLBACK (view_softproof_gamut_check_cmd_callback), + view_softproof_gamut_check_cmd_callback, FALSE, GIMP_HELP_VIEW_COLOR_MANAGEMENT }, { "view-show-selection", NULL, NC_("view-action", "Show _Selection"), "T", NC_("view-action", "Display the selection outline"), - G_CALLBACK (view_toggle_selection_cmd_callback), + view_toggle_selection_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_SELECTION }, { "view-show-layer-boundary", NULL, NC_("view-action", "Show _Layer Boundary"), NULL, NC_("view-action", "Draw a border around the active layer"), - G_CALLBACK (view_toggle_layer_boundary_cmd_callback), + view_toggle_layer_boundary_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_LAYER_BOUNDARY }, + { "view-show-canvas-boundary", NULL, + NC_("view-action", "Show Canvas Bounda_ry"), NULL, + NC_("view-action", "Draw a border around the canvas"), + view_toggle_canvas_boundary_cmd_callback, + TRUE, + GIMP_HELP_VIEW_SHOW_CANVAS_BOUNDARY }, + { "view-show-guides", NULL, NC_("view-action", "Show _Guides"), "T", NC_("view-action", "Display the image's guides"), - G_CALLBACK (view_toggle_guides_cmd_callback), + view_toggle_guides_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_GUIDES }, { "view-show-grid", NULL, NC_("view-action", "S_how Grid"), NULL, NC_("view-action", "Display the image's grid"), - G_CALLBACK (view_toggle_grid_cmd_callback), + view_toggle_grid_cmd_callback, FALSE, GIMP_HELP_VIEW_SHOW_GRID }, { "view-show-sample-points", NULL, - NC_("view-action", "Show Sample Points"), NULL, + NC_("view-action", "Sh_ow Sample Points"), NULL, NC_("view-action", "Display the image's color sample points"), - G_CALLBACK (view_toggle_sample_points_cmd_callback), + view_toggle_sample_points_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_SAMPLE_POINTS }, { "view-snap-to-guides", NULL, - NC_("view-action", "Sn_ap to Guides"), NULL, + NC_("view-action", "Snap to Gu_ides"), NULL, NC_("view-action", "Tool operations snap to guides"), - G_CALLBACK (view_snap_to_guides_cmd_callback), + view_snap_to_guides_cmd_callback, TRUE, GIMP_HELP_VIEW_SNAP_TO_GUIDES }, { "view-snap-to-grid", NULL, NC_("view-action", "Sna_p to Grid"), NULL, NC_("view-action", "Tool operations snap to the grid"), - G_CALLBACK (view_snap_to_grid_cmd_callback), + view_snap_to_grid_cmd_callback, FALSE, GIMP_HELP_VIEW_SNAP_TO_GRID }, { "view-snap-to-canvas", NULL, NC_("view-action", "Snap to _Canvas Edges"), NULL, NC_("view-action", "Tool operations snap to the canvas edges"), - G_CALLBACK (view_snap_to_canvas_cmd_callback), + view_snap_to_canvas_cmd_callback, FALSE, GIMP_HELP_VIEW_SNAP_TO_CANVAS }, { "view-snap-to-vectors", NULL, NC_("view-action", "Snap t_o Active Path"), NULL, NC_("view-action", "Tool operations snap to the active path"), - G_CALLBACK (view_snap_to_vectors_cmd_callback), + view_snap_to_vectors_cmd_callback, FALSE, GIMP_HELP_VIEW_SNAP_TO_VECTORS }, { "view-show-menubar", NULL, NC_("view-action", "Show _Menubar"), NULL, NC_("view-action", "Show this window's menubar"), - G_CALLBACK (view_toggle_menubar_cmd_callback), + view_toggle_menubar_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_MENUBAR }, { "view-show-rulers", NULL, NC_("view-action", "Show R_ulers"), "R", NC_("view-action", "Show this window's rulers"), - G_CALLBACK (view_toggle_rulers_cmd_callback), + view_toggle_rulers_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_RULERS }, { "view-show-scrollbars", NULL, NC_("view-action", "Show Scroll_bars"), NULL, NC_("view-action", "Show this window's scrollbars"), - G_CALLBACK (view_toggle_scrollbars_cmd_callback), + view_toggle_scrollbars_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_SCROLLBARS }, { "view-show-statusbar", NULL, NC_("view-action", "Show S_tatusbar"), NULL, NC_("view-action", "Show this window's statusbar"), - G_CALLBACK (view_toggle_statusbar_cmd_callback), + view_toggle_statusbar_cmd_callback, TRUE, GIMP_HELP_VIEW_SHOW_STATUSBAR }, { "view-fullscreen", GIMP_ICON_VIEW_FULLSCREEN, NC_("view-action", "Fullscr_een"), "F11", NC_("view-action", "Toggle fullscreen view"), - G_CALLBACK (view_fullscreen_cmd_callback), + view_fullscreen_cmd_callback, FALSE, GIMP_HELP_VIEW_FULLSCREEN } }; @@ -318,17 +333,17 @@ static const GimpEnumActionEntry view_zoom_actions[] = { { "view-zoom", NULL, - NC_("view-action", "Set zoom factor"), NULL, NULL, + NC_("view-zoom-action", "Set zoom factor"), NULL, NULL, GIMP_ACTION_SELECT_SET, TRUE, NULL }, { "view-zoom-minimum", GIMP_ICON_ZOOM_OUT, - NC_("view-action", "Zoom out as far as possible"), NULL, NULL, + NC_("view-zoom-action", "Zoom out as far as possible"), NULL, NULL, GIMP_ACTION_SELECT_FIRST, FALSE, GIMP_HELP_VIEW_ZOOM_OUT }, { "view-zoom-maximum", GIMP_ICON_ZOOM_IN, - NC_("view-action", "Zoom in as far as possible"), NULL, NULL, + NC_("view-zoom-action", "Zoom in as far as possible"), NULL, NULL, GIMP_ACTION_SELECT_LAST, FALSE, GIMP_HELP_VIEW_ZOOM_IN }, @@ -357,12 +372,12 @@ GIMP_HELP_VIEW_ZOOM_IN }, { "view-zoom-out-skip", GIMP_ICON_ZOOM_OUT, - NC_("view-action", "Zoom out a lot"), NULL, NULL, + NC_("view-zoom-action", "Zoom out a lot"), NULL, NULL, GIMP_ACTION_SELECT_SKIP_PREVIOUS, FALSE, GIMP_HELP_VIEW_ZOOM_OUT }, { "view-zoom-in-skip", GIMP_ICON_ZOOM_IN, - NC_("view-action", "Zoom in a lot"), NULL, NULL, + NC_("view-zoom-action", "Zoom in a lot"), NULL, NULL, GIMP_ACTION_SELECT_SKIP_NEXT, FALSE, GIMP_HELP_VIEW_ZOOM_IN } }; @@ -463,16 +478,16 @@ static const GimpToggleActionEntry view_flip_actions[] = { { "view-flip-horizontally", GIMP_ICON_OBJECT_FLIP_HORIZONTAL, - NC_("view-action", "Flip Horizontally"), NULL, + NC_("view-action", "Flip _Horizontally"), NULL, NC_("view-action", "Flip the view horizontally"), - G_CALLBACK (view_flip_horizontally_cmd_callback), + view_flip_horizontally_cmd_callback, FALSE, GIMP_HELP_VIEW_FLIP }, { "view-flip-vertically", GIMP_ICON_OBJECT_FLIP_VERTICAL, - NC_("view-action", "Flip Vertically"), NULL, + NC_("view-action", "Flip _Vertically"), NULL, NC_("view-action", "Flip the view vertically"), - G_CALLBACK (view_flip_vertically_cmd_callback), + view_flip_vertically_cmd_callback, FALSE, GIMP_HELP_VIEW_FLIP } }; @@ -613,6 +628,17 @@ GIMP_HELP_VIEW_PADDING_COLOR } }; +static const GimpToggleActionEntry view_padding_color_toggle_actions[] = +{ + { "view-padding-color-in-show-all", NULL, + NC_("view-padding-color", "Keep Padding in \"Show _All\" Mode"), NULL, + NC_("view-padding-color", + "Keep canvas padding when \"View -> Show All\" is enabled"), + view_padding_color_in_show_all_cmd_callback, + FALSE, + GIMP_HELP_VIEW_PADDING_COLOR } +}; + static const GimpEnumActionEntry view_scroll_horizontal_actions[] = { { "view-scroll-horizontal", NULL, @@ -693,7 +719,7 @@ void view_actions_setup (GimpActionGroup *group) { - GtkAction *action; + GimpAction *action; gimp_action_group_add_actions (group, "view-action", view_actions, @@ -706,14 +732,14 @@ gimp_action_group_add_enum_actions (group, "view-zoom-action", view_zoom_actions, G_N_ELEMENTS (view_zoom_actions), - G_CALLBACK (view_zoom_cmd_callback)); + view_zoom_cmd_callback); gimp_action_group_add_radio_actions (group, "view-zoom-action", view_zoom_explicit_actions, G_N_ELEMENTS (view_zoom_explicit_actions), NULL, 10000, - G_CALLBACK (view_zoom_explicit_cmd_callback)); + view_zoom_explicit_cmd_callback); gimp_action_group_add_toggle_actions (group, "view-action", view_flip_actions, @@ -722,47 +748,51 @@ gimp_action_group_add_enum_actions (group, "view-action", view_rotate_absolute_actions, G_N_ELEMENTS (view_rotate_absolute_actions), - G_CALLBACK (view_rotate_absolute_cmd_callback)); + view_rotate_absolute_cmd_callback); gimp_action_group_add_enum_actions (group, "view-action", view_rotate_relative_actions, G_N_ELEMENTS (view_rotate_relative_actions), - G_CALLBACK (view_rotate_relative_cmd_callback)); + view_rotate_relative_cmd_callback); gimp_action_group_add_radio_actions (group, "view-action", view_display_intent_actions, G_N_ELEMENTS (view_display_intent_actions), NULL, GIMP_COLOR_MANAGEMENT_DISPLAY, - G_CALLBACK (view_display_intent_cmd_callback)); + view_display_intent_cmd_callback); gimp_action_group_add_radio_actions (group, "view-action", view_softproof_intent_actions, G_N_ELEMENTS (view_softproof_intent_actions), NULL, GIMP_COLOR_MANAGEMENT_DISPLAY, - G_CALLBACK (view_softproof_intent_cmd_callback)); + view_softproof_intent_cmd_callback); gimp_action_group_add_enum_actions (group, "view-padding-color", view_padding_color_actions, G_N_ELEMENTS (view_padding_color_actions), - G_CALLBACK (view_padding_color_cmd_callback)); + view_padding_color_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_toggle_actions (group, "view-padding-color", + view_padding_color_toggle_actions, + G_N_ELEMENTS (view_padding_color_toggle_actions)); + + gimp_action_group_add_enum_actions (group, "view-action", view_scroll_horizontal_actions, G_N_ELEMENTS (view_scroll_horizontal_actions), - G_CALLBACK (view_scroll_horizontal_cmd_callback)); + view_scroll_horizontal_cmd_callback); - gimp_action_group_add_enum_actions (group, NULL, + gimp_action_group_add_enum_actions (group, "view-action", view_scroll_vertical_actions, G_N_ELEMENTS (view_scroll_vertical_actions), - G_CALLBACK (view_scroll_vertical_cmd_callback)); + view_scroll_vertical_cmd_callback); /* connect "activate" of view-zoom-other manually so it can be * selected even if it's the active item of the radio group */ - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - "view-zoom-other"); + action = gimp_action_group_get_action (group, "view-zoom-other"); + g_signal_connect (action, "activate", G_CALLBACK (view_zoom_other_cmd_callback), group->user_data); @@ -900,6 +930,9 @@ SET_SENSITIVE ("view-new", image); SET_SENSITIVE ("view-close", image); + SET_SENSITIVE ("view-show-all", image); + SET_ACTIVE ("view-show-all", display && shell->show_all); + SET_SENSITIVE ("view-dot-for-dot", image); SET_ACTIVE ("view-dot-for-dot", display && shell->dot_for_dot); @@ -994,25 +1027,27 @@ SET_ACTIVE ("view-softproof-gamut-check", gammut); SET_SENSITIVE ("view-color-management-reset", image); - SET_SENSITIVE ("view-show-selection", image); - SET_ACTIVE ("view-show-selection", display && options->show_selection); - SET_SENSITIVE ("view-show-layer-boundary", image); - SET_ACTIVE ("view-show-layer-boundary", display && options->show_layer_boundary); - SET_SENSITIVE ("view-show-guides", image); - SET_ACTIVE ("view-show-guides", display && options->show_guides); - SET_SENSITIVE ("view-show-grid", image); - SET_ACTIVE ("view-show-grid", display && options->show_grid); - SET_SENSITIVE ("view-show-sample-points", image); - SET_ACTIVE ("view-show-sample-points", display && options->show_sample_points); - - SET_SENSITIVE ("view-snap-to-guides", image); - SET_ACTIVE ("view-snap-to-guides", display && options->snap_to_guides); - SET_SENSITIVE ("view-snap-to-grid", image); - SET_ACTIVE ("view-snap-to-grid", display && options->snap_to_grid); - SET_SENSITIVE ("view-snap-to-canvas", image); - SET_ACTIVE ("view-snap-to-canvas", display && options->snap_to_canvas); - SET_SENSITIVE ("view-snap-to-vectors", image); - SET_ACTIVE ("view-snap-to-vectors", display && options->snap_to_path); + SET_SENSITIVE ("view-show-selection", image); + SET_ACTIVE ("view-show-selection", display && options->show_selection); + SET_SENSITIVE ("view-show-layer-boundary", image); + SET_ACTIVE ("view-show-layer-boundary", display && options->show_layer_boundary); + SET_SENSITIVE ("view-show-canvas-boundary", image && shell->show_all); + SET_ACTIVE ("view-show-canvas-boundary", display && options->show_canvas_boundary); + SET_SENSITIVE ("view-show-guides", image); + SET_ACTIVE ("view-show-guides", display && options->show_guides); + SET_SENSITIVE ("view-show-grid", image); + SET_ACTIVE ("view-show-grid", display && options->show_grid); + SET_SENSITIVE ("view-show-sample-points", image); + SET_ACTIVE ("view-show-sample-points", display && options->show_sample_points); + + SET_SENSITIVE ("view-snap-to-guides", image); + SET_ACTIVE ("view-snap-to-guides", display && options->snap_to_guides); + SET_SENSITIVE ("view-snap-to-grid", image); + SET_ACTIVE ("view-snap-to-grid", display && options->snap_to_grid); + SET_SENSITIVE ("view-snap-to-canvas", image); + SET_ACTIVE ("view-snap-to-canvas", display && options->snap_to_canvas); + SET_SENSITIVE ("view-snap-to-vectors", image); + SET_ACTIVE ("view-snap-to-vectors", display && options->snap_to_path); SET_SENSITIVE ("view-padding-color-theme", image); SET_SENSITIVE ("view-padding-color-light-check", image); @@ -1037,6 +1072,9 @@ } } + SET_SENSITIVE ("view-padding-color-in-show-all", image); + SET_ACTIVE ("view-padding-color-in-show-all", display && options->padding_in_show_all); + SET_SENSITIVE ("view-show-menubar", image); SET_ACTIVE ("view-show-menubar", display && options->show_menubar); SET_SENSITIVE ("view-show-rulers", image); @@ -1133,16 +1171,19 @@ shell->flip_vertically) { /* please preserve the trailing space */ + /* H: Horizontal, V: Vertical */ flip = _("(H+V) "); } else if (shell->flip_horizontally) { /* please preserve the trailing space */ + /* H: Horizontal */ flip = _("(H) "); } else if (shell->flip_vertically) { /* please preserve the trailing space */ + /* V: Vertical */ flip = _("(V) "); } else diff -Nru gimp-2.10.8+zorin2/app/actions/view-commands.c gimp-2.10.14+om/app/actions/view-commands.c --- gimp-2.10.8+zorin2/app/actions/view-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/view-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -92,8 +92,9 @@ /* public functions */ void -view_new_cmd_callback (GtkAction *action, - gpointer data) +view_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -109,8 +110,9 @@ } void -view_close_cmd_callback (GtkAction *action, - gpointer data) +view_close_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -126,8 +128,9 @@ } void -view_scroll_center_cmd_callback (GtkAction *action, - gpointer data) +view_scroll_center_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; return_if_no_display (display, data); @@ -137,8 +140,9 @@ } void -view_zoom_fit_in_cmd_callback (GtkAction *action, - gpointer data) +view_zoom_fit_in_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; return_if_no_display (display, data); @@ -147,8 +151,9 @@ } void -view_zoom_fill_cmd_callback (GtkAction *action, - gpointer data) +view_zoom_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; return_if_no_display (display, data); @@ -157,8 +162,9 @@ } void -view_zoom_selection_cmd_callback (GtkAction *action, - gpointer data) +view_zoom_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpImage *image; @@ -176,8 +182,9 @@ } void -view_zoom_revert_cmd_callback (GtkAction *action, - gpointer data) +view_zoom_revert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; return_if_no_display (display, data); @@ -186,14 +193,17 @@ } void -view_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data) +view_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - GimpDisplayShell *shell; + GimpDisplayShell *shell; + GimpActionSelectType select_type; return_if_no_shell (shell, data); - switch ((GimpActionSelectType) value) + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + switch (select_type) { case GIMP_ACTION_SELECT_FIRST: gimp_display_shell_scale (shell, @@ -241,7 +251,7 @@ { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); - scale = action_select_value ((GimpActionSelectType) value, + scale = action_select_value (select_type, scale, 0.0, 512.0, 1.0, 1.0 / 8.0, 1.0, 16.0, 0.0, @@ -261,37 +271,39 @@ } void -view_zoom_explicit_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +view_zoom_explicit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; - gint value; + gint factor; return_if_no_shell (shell, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + factor = g_variant_get_int32 (value); - if (value != 0 /* not Other... */) + if (factor != 0 /* not Other... */) { - if (fabs (value - gimp_zoom_model_get_factor (shell->zoom)) > 0.0001) + if (fabs (factor - gimp_zoom_model_get_factor (shell->zoom)) > 0.0001) gimp_display_shell_scale (shell, GIMP_ZOOM_TO, - (gdouble) value / 10000, + (gdouble) factor / 10000, GIMP_ZOOM_FOCUS_RETAIN_CENTERING_ELSE_BEST_GUESS); } } +/* not a GimpActionCallback */ void -view_zoom_other_cmd_callback (GtkAction *action, - gpointer data) +view_zoom_other_cmd_callback (GimpAction *action, + gpointer data) { GimpDisplayShell *shell; return_if_no_shell (shell, data); /* check if we are activated by the user or from - * view_actions_set_zoom() + * view_actions_set_zoom(), also this is really a GtkToggleAction + * NOT a GimpToggleAction */ - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) && + if (gtk_toggle_action_get_active ((GtkToggleAction *) action) && shell->other_scale != gimp_zoom_model_get_factor (shell->zoom)) { gimp_display_shell_scale_dialog (shell); @@ -299,8 +311,39 @@ } void -view_dot_for_dot_cmd_callback (GtkAction *action, - gpointer data) +view_show_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplay *display; + GimpDisplayShell *shell; + gboolean active; + return_if_no_display (display, data); + + shell = gimp_display_get_shell (display); + + active = g_variant_get_boolean (value); + + if (active != shell->show_all) + { + GimpImageWindow *window = gimp_display_shell_get_window (shell); + + gimp_display_shell_set_show_all (shell, active); + + if (window) + SET_ACTIVE (gimp_image_window_get_ui_manager (window), + "view-show-all", shell->show_all); + + if (IS_ACTIVE_DISPLAY (display)) + SET_ACTIVE (shell->popup_manager, "view-show-all", + shell->show_all); + } +} + +void +view_dot_for_dot_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -309,7 +352,7 @@ shell = gimp_display_get_shell (display); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != shell->dot_for_dot) { @@ -328,8 +371,9 @@ } void -view_flip_horizontally_cmd_callback (GtkAction *action, - gpointer data) +view_flip_horizontally_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -338,7 +382,7 @@ shell = gimp_display_get_shell (display); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != shell->flip_horizontally) { @@ -347,8 +391,9 @@ } void -view_flip_vertically_cmd_callback (GtkAction *action, - gpointer data) +view_flip_vertically_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -357,7 +402,7 @@ shell = gimp_display_get_shell (display); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != shell->flip_vertically) { @@ -366,18 +411,21 @@ } void -view_rotate_absolute_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplay *display; - GimpDisplayShell *shell; - gdouble angle = 0.0; +view_rotate_absolute_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplay *display; + GimpDisplayShell *shell; + GimpActionSelectType select_type; + gdouble angle = 0.0; return_if_no_display (display, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + shell = gimp_display_get_shell (display); - angle = action_select_value ((GimpActionSelectType) value, + angle = action_select_value (select_type, 0.0, -180.0, 180.0, 0.0, 1.0, 15.0, 90.0, 0.0, @@ -385,23 +433,26 @@ gimp_display_shell_rotate_to (shell, angle); - if (value == GIMP_ACTION_SELECT_SET_TO_DEFAULT) + if (select_type == GIMP_ACTION_SELECT_SET_TO_DEFAULT) gimp_display_shell_flip (shell, FALSE, FALSE); } void -view_rotate_relative_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplay *display; - GimpDisplayShell *shell; - gdouble delta = 0.0; +view_rotate_relative_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplay *display; + GimpDisplayShell *shell; + GimpActionSelectType select_type; + gdouble delta = 0.0; return_if_no_display (display, data); + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + shell = gimp_display_get_shell (display); - delta = action_select_value ((GimpActionSelectType) value, + delta = action_select_value (select_type, 0.0, -180.0, 180.0, 0.0, 1.0, 15.0, 90.0, 0.0, @@ -411,8 +462,9 @@ } void -view_rotate_other_cmd_callback (GtkAction *action, - gpointer data) +view_rotate_other_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -424,23 +476,29 @@ } void -view_scroll_horizontal_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplayShell *shell; - gdouble offset; - return_if_no_shell (shell, data); - - offset = action_select_value ((GimpActionSelectType) value, - gtk_adjustment_get_value (shell->hsbdata), - gtk_adjustment_get_lower (shell->hsbdata), - gtk_adjustment_get_upper (shell->hsbdata) - - gtk_adjustment_get_page_size (shell->hsbdata), - gtk_adjustment_get_lower (shell->hsbdata), +view_scroll_horizontal_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplayShell *shell; + GtkAdjustment *adj; + GimpActionSelectType select_type; + gdouble offset; + return_if_no_shell (shell, data); + + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + adj = shell->hsbdata; + + offset = action_select_value (select_type, + gtk_adjustment_get_value (adj), + gtk_adjustment_get_lower (adj), + gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj), + gtk_adjustment_get_lower (adj), 1, - gtk_adjustment_get_step_increment (shell->hsbdata), - gtk_adjustment_get_page_increment (shell->hsbdata), + gtk_adjustment_get_step_increment (adj), + gtk_adjustment_get_page_increment (adj), 0, FALSE); @@ -448,23 +506,29 @@ } void -view_scroll_vertical_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplayShell *shell; - gdouble offset; - return_if_no_shell (shell, data); - - offset = action_select_value ((GimpActionSelectType) value, - gtk_adjustment_get_value (shell->vsbdata), - gtk_adjustment_get_lower (shell->vsbdata), - gtk_adjustment_get_upper (shell->vsbdata) - - gtk_adjustment_get_page_size (shell->vsbdata), - gtk_adjustment_get_lower (shell->vsbdata), +view_scroll_vertical_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplayShell *shell; + GtkAdjustment *adj; + GimpActionSelectType select_type; + gdouble offset; + return_if_no_shell (shell, data); + + select_type = (GimpActionSelectType) g_variant_get_int32 (value); + + adj = shell->vsbdata; + + offset = action_select_value (select_type, + gtk_adjustment_get_value (adj), + gtk_adjustment_get_lower (adj), + gtk_adjustment_get_upper (adj) - + gtk_adjustment_get_page_size (adj), + gtk_adjustment_get_lower (adj), 1, - gtk_adjustment_get_step_increment (shell->vsbdata), - gtk_adjustment_get_page_increment (shell->vsbdata), + gtk_adjustment_get_step_increment (adj), + gtk_adjustment_get_page_increment (adj), 0, FALSE); @@ -472,8 +536,9 @@ } void -view_navigation_window_cmd_callback (GtkAction *action, - gpointer data) +view_navigation_window_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; GimpDisplayShell *shell; @@ -489,8 +554,9 @@ } void -view_display_filters_cmd_callback (GtkAction *action, - gpointer data) +view_display_filters_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GtkWidget *dialog; @@ -511,8 +577,9 @@ } void -view_color_management_reset_cmd_callback (GtkAction *action, - gpointer data) +view_color_management_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *global_config; @@ -529,8 +596,9 @@ } void -view_color_management_enable_cmd_callback (GtkAction *action, - gpointer data) +view_color_management_enable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; @@ -540,7 +608,7 @@ color_config = gimp_display_shell_get_color_config (shell); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); mode = gimp_color_config_get_mode (color_config); @@ -564,8 +632,9 @@ } void -view_color_management_softproof_cmd_callback (GtkAction *action, - gpointer data) +view_color_management_softproof_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; @@ -575,7 +644,7 @@ color_config = gimp_display_shell_get_color_config (shell); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); mode = gimp_color_config_get_mode (color_config); @@ -599,31 +668,32 @@ } void -view_display_intent_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +view_display_intent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; - GimpColorRenderingIntent value; + GimpColorRenderingIntent intent; return_if_no_shell (shell, data); - color_config = gimp_display_shell_get_color_config (shell); + intent = (GimpColorRenderingIntent) g_variant_get_int32 (value); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + color_config = gimp_display_shell_get_color_config (shell); - if (value != gimp_color_config_get_display_intent (color_config)) + if (intent != gimp_color_config_get_display_intent (color_config)) { g_object_set (color_config, - "display-rendering-intent", value, + "display-rendering-intent", intent, NULL); shell->color_config_set = TRUE; } } void -view_display_bpc_cmd_callback (GtkAction *action, - gpointer data) +view_display_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; @@ -632,7 +702,7 @@ color_config = gimp_display_shell_get_color_config (shell); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_color_config_get_display_bpc (color_config)) { @@ -644,8 +714,9 @@ } void -view_softproof_profile_cmd_callback (GtkAction *action, - gpointer data) +view_softproof_profile_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpImage *image; GimpDisplayShell *shell; @@ -685,31 +756,32 @@ } void -view_softproof_intent_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +view_softproof_intent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; - GimpColorRenderingIntent value; + GimpColorRenderingIntent intent; return_if_no_shell (shell, data); - color_config = gimp_display_shell_get_color_config (shell); + intent = (GimpColorRenderingIntent) g_variant_get_int32 (value); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + color_config = gimp_display_shell_get_color_config (shell); - if (value != gimp_color_config_get_simulation_intent (color_config)) + if (intent != gimp_color_config_get_simulation_intent (color_config)) { g_object_set (color_config, - "simulation-rendering-intent", value, + "simulation-rendering-intent", intent, NULL); shell->color_config_set = TRUE; } } void -view_softproof_bpc_cmd_callback (GtkAction *action, - gpointer data) +view_softproof_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; @@ -718,7 +790,7 @@ color_config = gimp_display_shell_get_color_config (shell); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_color_config_get_simulation_bpc (color_config)) { @@ -730,8 +802,9 @@ } void -view_softproof_gamut_check_cmd_callback (GtkAction *action, - gpointer data) +view_softproof_gamut_check_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; GimpColorConfig *color_config; @@ -740,7 +813,7 @@ color_config = gimp_display_shell_get_color_config (shell); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_color_config_get_simulation_gamut_check (color_config)) { @@ -752,14 +825,15 @@ } void -view_toggle_selection_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_selection (shell)) { @@ -768,14 +842,15 @@ } void -view_toggle_layer_boundary_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_layer_boundary_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_layer (shell)) { @@ -784,14 +859,32 @@ } void -view_toggle_menubar_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_canvas_boundary_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); + + if (active != gimp_display_shell_get_show_canvas (shell)) + { + gimp_display_shell_set_show_canvas (shell, active); + } +} + +void +view_toggle_menubar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplayShell *shell; + gboolean active; + return_if_no_shell (shell, data); + + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_menubar (shell)) { @@ -800,14 +893,15 @@ } void -view_toggle_rulers_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_rulers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_rulers (shell)) { @@ -816,14 +910,15 @@ } void -view_toggle_scrollbars_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_scrollbars_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_scrollbars (shell)) { @@ -832,14 +927,15 @@ } void -view_toggle_statusbar_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_statusbar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_statusbar (shell)) { @@ -848,14 +944,15 @@ } void -view_toggle_guides_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_guides_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_guides (shell)) { @@ -864,14 +961,15 @@ } void -view_toggle_grid_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_grid (shell)) { @@ -880,14 +978,15 @@ } void -view_toggle_sample_points_cmd_callback (GtkAction *action, - gpointer data) +view_toggle_sample_points_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_show_sample_points (shell)) { @@ -896,14 +995,15 @@ } void -view_snap_to_guides_cmd_callback (GtkAction *action, - gpointer data) +view_snap_to_guides_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_snap_to_guides (shell)) { @@ -912,14 +1012,15 @@ } void -view_snap_to_grid_cmd_callback (GtkAction *action, - gpointer data) +view_snap_to_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_snap_to_grid (shell)) { @@ -928,14 +1029,15 @@ } void -view_snap_to_canvas_cmd_callback (GtkAction *action, - gpointer data) +view_snap_to_canvas_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_snap_to_canvas (shell)) { @@ -944,14 +1046,15 @@ } void -view_snap_to_vectors_cmd_callback (GtkAction *action, - gpointer data) +view_snap_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; gboolean active; return_if_no_shell (shell, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != gimp_display_shell_get_snap_to_vectors (shell)) { @@ -960,17 +1063,20 @@ } void -view_padding_color_cmd_callback (GtkAction *action, - gint value, - gpointer data) -{ - GimpDisplay *display; - GimpImageWindow *window; - GimpDisplayShell *shell; - GimpDisplayOptions *options; - gboolean fullscreen; +view_padding_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplay *display; + GimpImageWindow *window; + GimpDisplayShell *shell; + GimpDisplayOptions *options; + GimpCanvasPaddingMode padding_mode; + gboolean fullscreen; return_if_no_display (display, data); + padding_mode = (GimpCanvasPaddingMode) g_variant_get_int32 (value); + shell = gimp_display_get_shell (display); window = gimp_display_shell_get_window (shell); @@ -986,7 +1092,7 @@ #define PADDING_COLOR_DIALOG_KEY "gimp-padding-color-dialog" - switch ((GimpCanvasPaddingMode) value) + switch (padding_mode) { case GIMP_CANVAS_PADDING_MODE_DEFAULT: case GIMP_CANVAS_PADDING_MODE_LIGHT_CHECK: @@ -995,7 +1101,7 @@ options->padding_mode_set = TRUE; - gimp_display_shell_set_padding (shell, (GimpCanvasPaddingMode) value, + gimp_display_shell_set_padding (shell, padding_mode, &options->padding_color); break; @@ -1049,14 +1155,34 @@ gimp_display_shell_set_padding (shell, default_options->padding_mode, &default_options->padding_color); + gimp_display_shell_set_padding_in_show_all (shell, + default_options->padding_in_show_all); } break; } } void -view_shrink_wrap_cmd_callback (GtkAction *action, - gpointer data) +view_padding_color_in_show_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) +{ + GimpDisplayShell *shell; + gboolean active; + return_if_no_shell (shell, data); + + active = g_variant_get_boolean (value); + + if (active != gimp_display_shell_get_padding_in_show_all (shell)) + { + gimp_display_shell_set_padding_in_show_all (shell, active); + } +} + +void +view_shrink_wrap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplayShell *shell; return_if_no_shell (shell, data); @@ -1065,8 +1191,9 @@ } void -view_fullscreen_cmd_callback (GtkAction *action, - gpointer data) +view_fullscreen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; GimpDisplayShell *shell; @@ -1078,9 +1205,7 @@ if (window) { - gboolean active; - - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + gboolean active = g_variant_get_boolean (value); gimp_image_window_set_fullscreen (window, active); } diff -Nru gimp-2.10.8+zorin2/app/actions/view-commands.h gimp-2.10.14+om/app/actions/view-commands.h --- gimp-2.10.8+zorin2/app/actions/view-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/view-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,116 +19,163 @@ #define __VIEW_COMMANDS_H__ -void view_new_cmd_callback (GtkAction *action, - gpointer data); -void view_close_cmd_callback (GtkAction *action, - gpointer data); - -void view_scroll_center_cmd_callback (GtkAction *action, - gpointer data); - -void view_zoom_fit_in_cmd_callback (GtkAction *action, - gpointer data); -void view_zoom_fill_cmd_callback (GtkAction *action, - gpointer data); -void view_zoom_selection_cmd_callback (GtkAction *action, - gpointer data); -void view_zoom_revert_cmd_callback (GtkAction *action, - gpointer data); -void view_zoom_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void view_zoom_explicit_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void view_zoom_other_cmd_callback (GtkAction *action, - gpointer data); -void view_dot_for_dot_cmd_callback (GtkAction *action, - gpointer data); - -void view_scroll_horizontal_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void view_scroll_vertical_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void view_flip_horizontally_cmd_callback (GtkAction *action, - gpointer data); -void view_flip_vertically_cmd_callback (GtkAction *action, - gpointer data); - -void view_rotate_absolute_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void view_rotate_relative_cmd_callback (GtkAction *action, - gint value, - gpointer data); -void view_rotate_other_cmd_callback (GtkAction *action, - gpointer data); - -void view_navigation_window_cmd_callback (GtkAction *action, - gpointer data); -void view_display_filters_cmd_callback (GtkAction *action, - gpointer data); - -void view_color_management_reset_cmd_callback (GtkAction *action, - gpointer data); -void view_color_management_enable_cmd_callback(GtkAction *action, - gpointer data); -void view_color_management_softproof_cmd_callback - (GtkAction *action, - gpointer data); -void view_display_intent_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void view_display_bpc_cmd_callback (GtkAction *action, - gpointer data); -void view_softproof_profile_cmd_callback (GtkAction *action, - gpointer data); -void view_softproof_intent_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void view_softproof_bpc_cmd_callback (GtkAction *action, - gpointer data); -void view_softproof_gamut_check_cmd_callback (GtkAction *action, - gpointer data); - -void view_toggle_selection_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_layer_boundary_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_menubar_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_rulers_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_scrollbars_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_statusbar_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_guides_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_grid_cmd_callback (GtkAction *action, - gpointer data); -void view_toggle_sample_points_cmd_callback (GtkAction *action, - gpointer data); - -void view_snap_to_guides_cmd_callback (GtkAction *action, - gpointer data); -void view_snap_to_grid_cmd_callback (GtkAction *action, - gpointer data); -void view_snap_to_canvas_cmd_callback (GtkAction *action, - gpointer data); -void view_snap_to_vectors_cmd_callback (GtkAction *action, - gpointer data); -void view_padding_color_cmd_callback (GtkAction *action, - gint value, - gpointer data); - -void view_shrink_wrap_cmd_callback (GtkAction *action, - gpointer data); -void view_fullscreen_cmd_callback (GtkAction *action, - gpointer data); +void view_new_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_close_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_scroll_center_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_zoom_fit_in_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_zoom_fill_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_zoom_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_zoom_revert_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_zoom_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_zoom_explicit_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +/* not a GimpActionCallback */ +void view_zoom_other_cmd_callback (GimpAction *action, + gpointer data); + +void view_show_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_dot_for_dot_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_scroll_horizontal_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_scroll_vertical_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_flip_horizontally_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_flip_vertically_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_rotate_absolute_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_rotate_relative_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_rotate_other_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_navigation_window_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_display_filters_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_color_management_reset_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_color_management_enable_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_color_management_softproof_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_display_intent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_display_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_softproof_profile_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_softproof_intent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_softproof_bpc_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_softproof_gamut_check_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_toggle_selection_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_layer_boundary_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_canvas_boundary_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_menubar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_rulers_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_scrollbars_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_statusbar_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_guides_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_toggle_sample_points_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_snap_to_guides_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_snap_to_grid_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_snap_to_canvas_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_snap_to_vectors_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_padding_color_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_padding_color_in_show_all_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void view_shrink_wrap_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void view_fullscreen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __VIEW_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/window-actions.c gimp-2.10.14+om/app/actions/window-actions.c --- gimp-2.10.8+zorin2/app/actions/window-actions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/window-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -89,7 +89,7 @@ gint show_menu = FALSE; gchar *name; - group_name = gtk_action_group_get_name (GTK_ACTION_GROUP (group)); + group_name = gimp_action_group_get_name (group); #define SET_ACTIVE(action,active) \ gimp_action_group_set_action_active (group, action, (active) != 0) @@ -174,7 +174,7 @@ help_id = g_object_get_data (G_OBJECT (group), "change-to-screen-help-id"); - group_name = gtk_action_group_get_name (GTK_ACTION_GROUP (group)); + group_name = gimp_action_group_get_name (group); n_screens = gdk_display_get_n_screens (display); @@ -205,17 +205,17 @@ radio_group = gimp_action_group_add_radio_actions (group, NULL, entries, n_screens, radio_group, 0, - G_CALLBACK (window_move_to_screen_cmd_callback)); + window_move_to_screen_cmd_callback); g_object_set_data (G_OBJECT (group), "change-to-screen-radio-group", radio_group); for (i = 0; i < n_screens; i++) { - GdkScreen *screen = gdk_display_get_screen (display, i); - GtkAction *action; + GdkScreen *screen = gdk_display_get_screen (display, i); + GimpAction *action; + + action = gimp_action_group_get_action (group, entries[i].name); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - entries[i].name); if (action) g_object_set_data (G_OBJECT (action), "screen", screen); @@ -260,24 +260,23 @@ g_hash_table_remove (displays, display_name); - group_name = gtk_action_group_get_name (GTK_ACTION_GROUP (group)); + group_name = gimp_action_group_get_name (group); n_screens = gdk_display_get_n_screens (display); for (i = 0; i < n_screens; i++) { - GdkScreen *screen = gdk_display_get_screen (display, i); - GtkAction *action; - gchar *screen_name; - gchar *action_name; + GdkScreen *screen = gdk_display_get_screen (display, i); + GimpAction *action; + gchar *screen_name; + gchar *action_name; screen_name = gdk_screen_make_display_name (screen); action_name = g_strdup_printf ("%s-move-to-screen-%s", group_name, screen_name); g_free (screen_name); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); if (action) { @@ -287,7 +286,7 @@ if (radio_group->data == (gpointer) action) radio_group = radio_group->next; - gtk_action_group_remove_action (GTK_ACTION_GROUP (group), action); + gimp_action_group_remove_action (group, action); g_object_set_data (G_OBJECT (group), "change-to-screen-radio-group", radio_group); diff -Nru gimp-2.10.8+zorin2/app/actions/window-commands.c gimp-2.10.14+om/app/actions/window-commands.c --- gimp-2.10.8+zorin2/app/actions/window-commands.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/window-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -38,8 +38,9 @@ /* public functions */ void -window_close_cmd_callback (GtkAction *action, - gpointer data) +window_close_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; return_if_no_widget (widget, data); @@ -60,8 +61,9 @@ } void -window_open_display_cmd_callback (GtkAction *action, - gpointer data) +window_open_display_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; GtkWidget *dialog; @@ -132,14 +134,17 @@ } void -window_move_to_screen_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +window_move_to_screen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWidget *widget; +#if 0 GdkScreen *screen; +#endif return_if_no_widget (widget, data); +#if 0 if (! gtk_widget_is_toplevel (widget)) widget = gtk_widget_get_toplevel (widget); @@ -149,4 +154,5 @@ { gtk_window_set_screen (GTK_WINDOW (widget), screen); } +#endif } diff -Nru gimp-2.10.8+zorin2/app/actions/window-commands.h gimp-2.10.14+om/app/actions/window-commands.h --- gimp-2.10.8+zorin2/app/actions/window-commands.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/actions/window-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,13 +19,15 @@ #define __WINDOW_COMMANDS_H__ -void window_close_cmd_callback (GtkAction *action, - gpointer data); -void window_open_display_cmd_callback (GtkAction *action, - gpointer data); -void window_move_to_screen_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); +void window_close_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void window_open_display_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void window_move_to_screen_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __WINDOW_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/actions/windows-actions.c gimp-2.10.14+om/app/actions/windows-actions.c --- gimp-2.10.8+zorin2/app/actions/windows-actions.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/windows-actions.c 2019-10-26 18:49:18.000000000 +0000 @@ -41,6 +41,7 @@ #include "widgets/gimphelp-ids.h" #include "display/gimpdisplay.h" +#include "display/gimpdisplayshell.h" #include "dialogs/dialogs.h" @@ -63,6 +64,9 @@ static void windows_actions_image_notify (GimpDisplay *display, const GParamSpec *unused, GimpActionGroup *group); +static void windows_actions_title_notify (GimpDisplayShell *shell, + const GParamSpec *unused, + GimpActionGroup *group); static void windows_actions_update_display_accels (GimpActionGroup *group); static void windows_actions_dock_window_added (GimpDialogFactory *factory, @@ -104,13 +108,13 @@ { "windows-show-display-next", NULL, NC_("windows-action", "Next Image"), "Tab", NC_("windows-action", "Switch to the next image"), - G_CALLBACK (windows_show_display_next_cmd_callback), + windows_show_display_next_cmd_callback, NULL }, { "windows-show-display-previous", NULL, NC_("windows-action", "Previous Image"), "Tab", NC_("windows-action", "Switch to the previous image"), - G_CALLBACK (windows_show_display_previous_cmd_callback), + windows_show_display_previous_cmd_callback, NULL }, { "windows-tab-position", NULL, NC_("windows-action", @@ -120,23 +124,23 @@ static const GimpToggleActionEntry windows_toggle_actions[] = { { "windows-hide-docks", NULL, - NC_("windows-action", "Hide Docks"), "Tab", + NC_("windows-action", "_Hide Docks"), "Tab", NC_("windows-action", "When enabled, docks and other dialogs are hidden, leaving only image windows."), - G_CALLBACK (windows_hide_docks_cmd_callback), + windows_hide_docks_cmd_callback, FALSE, GIMP_HELP_WINDOWS_HIDE_DOCKS }, { "windows-show-tabs", NULL, - NC_("windows-action", "Show Tabs"), NULL, + NC_("windows-action", "_Show Tabs"), NULL, NC_("windows-action", "When enabled, the image tabs bar is shown."), - G_CALLBACK (windows_show_tabs_cmd_callback), + windows_show_tabs_cmd_callback, FALSE, GIMP_HELP_WINDOWS_SHOW_TABS }, { "windows-use-single-window-mode", NULL, - NC_("windows-action", "Single-Window Mode"), NULL, + NC_("windows-action", "Single-Window _Mode"), NULL, NC_("windows-action", "When enabled, GIMP is in a single-window mode."), - G_CALLBACK (windows_use_single_window_mode_cmd_callback), + windows_use_single_window_mode_cmd_callback, FALSE, GIMP_HELP_WINDOWS_USE_SINGLE_WINDOW_MODE } }; @@ -181,7 +185,7 @@ windows_tabs_position_actions, G_N_ELEMENTS (windows_tabs_position_actions), NULL, 0, - G_CALLBACK (windows_set_tabs_position_cmd_callback)); + windows_set_tabs_position_cmd_callback); gimp_action_group_set_action_hide_empty (group, "windows-docks-menu", FALSE); @@ -299,12 +303,17 @@ GimpDisplay *display, GimpActionGroup *group) { + GimpDisplayShell *shell = gimp_display_get_shell (display); + g_signal_connect_object (display, "notify::image", G_CALLBACK (windows_actions_image_notify), group, 0); - if (gimp_display_get_image (display)) - windows_actions_image_notify (display, NULL, group); + g_signal_connect_object (shell, "notify::title", + G_CALLBACK (windows_actions_title_notify), + group, 0); + + windows_actions_image_notify (display, NULL, group); } static void @@ -312,15 +321,21 @@ GimpDisplay *display, GimpActionGroup *group) { - GtkAction *action; - gchar *action_name = gimp_display_get_action_name (display); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpAction *action; + gchar *action_name; + + if (shell) + g_signal_handlers_disconnect_by_func (shell, + windows_actions_title_notify, + group); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); + action_name = gimp_display_get_action_name (display); + action = gimp_action_group_get_action (group, action_name); + g_free (action_name); if (action) - gimp_action_group_remove_action (group, - GIMP_ACTION (action)); - g_free (action_name); + gimp_action_group_remove_action_and_accel (group, action); windows_actions_update_display_accels (group); } @@ -339,73 +354,81 @@ const GParamSpec *unused, GimpActionGroup *group) { - GimpImage *image = gimp_display_get_image (display); + GimpImage *image = gimp_display_get_image (display); + GimpAction *action; + gchar *action_name; - if (image) - { - GtkAction *action; - gchar *action_name = gimp_display_get_action_name (display); + action_name = gimp_display_get_action_name (display); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); - if (! action) - { - GimpActionEntry entry; - - entry.name = action_name; - entry.icon_name = GIMP_ICON_IMAGE; - entry.label = ""; - entry.accelerator = NULL; - entry.tooltip = NULL; - entry.callback = G_CALLBACK (windows_show_display_cmd_callback); - entry.help_id = NULL; - - gimp_action_group_add_actions (group, NULL, &entry, 1); - - gimp_action_group_set_action_always_show_image (group, action_name, - TRUE); + if (! action) + { + GimpActionEntry entry; - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + entry.name = action_name; + entry.icon_name = GIMP_ICON_IMAGE; + entry.label = ""; + entry.accelerator = NULL; + entry.tooltip = NULL; + entry.callback = windows_show_display_cmd_callback; + entry.help_id = NULL; + + gimp_action_group_add_actions (group, NULL, &entry, 1); + + gimp_action_group_set_action_always_show_image (group, action_name, + TRUE); + action = gimp_action_group_get_action (group, action_name); - g_object_set_data (G_OBJECT (action), "display", display); - } + g_object_set_data (G_OBJECT (action), "display", display); + } - { - const gchar *display_name; - gchar *escaped; - gchar *title; - - display_name = gimp_image_get_display_name (image); - escaped = gimp_escape_uline (display_name); - - title = g_strdup_printf ("%s-%d.%d", escaped, - gimp_image_get_ID (image), - gimp_display_get_instance (display)); - g_free (escaped); - - g_object_set (action, - "label", title, - "tooltip", gimp_image_get_display_path (image), - "viewable", image, - "context", gimp_get_user_context (group->gimp), - NULL); + g_free (action_name); - g_free (title); - } + if (image) + { + const gchar *display_name; + gchar *escaped; + gchar *title; + + display_name = gimp_image_get_display_name (image); + escaped = gimp_escape_uline (display_name); + + title = g_strdup_printf ("%s-%d.%d", escaped, + gimp_image_get_ID (image), + gimp_display_get_instance (display)); + g_free (escaped); + + g_object_set (action, + "visible", TRUE, + "label", title, + "tooltip", gimp_image_get_display_path (image), + "viewable", image, + "context", gimp_get_user_context (group->gimp), + NULL); - g_free (action_name); + g_free (title); windows_actions_update_display_accels (group); } else { - windows_actions_display_remove (group->gimp->displays, display, group); + g_object_set (action, + "visible", FALSE, + "viewable", NULL, + NULL); } } static void +windows_actions_title_notify (GimpDisplayShell *shell, + const GParamSpec *unused, + GimpActionGroup *group) +{ + windows_actions_image_notify (shell->display, NULL, group); +} + +static void windows_actions_update_display_accels (GimpActionGroup *group) { GList *list; @@ -416,7 +439,7 @@ list = g_list_next (list), i++) { GimpDisplay *display = list->data; - GtkAction *action; + GimpAction *action; gchar *action_name; if (! gimp_display_get_image (display)) @@ -424,8 +447,7 @@ action_name = gimp_display_get_action_name (display); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); g_free (action_name); if (action) @@ -433,7 +455,7 @@ const gchar *accel_path; guint accel_key; - accel_path = gtk_action_get_accel_path (action); + accel_path = gimp_action_get_accel_path (action); if (i < 9) accel_key = GDK_KEY_1 + i; @@ -452,7 +474,7 @@ GimpDockWindow *dock_window, GimpActionGroup *group) { - GtkAction *action; + GimpAction *action; GimpActionEntry entry; gchar *action_name = windows_actions_dock_window_to_action_name (dock_window); @@ -461,13 +483,12 @@ entry.label = ""; entry.accelerator = NULL; entry.tooltip = NULL; - entry.callback = G_CALLBACK (windows_show_dock_cmd_callback); + entry.callback = windows_show_dock_cmd_callback; entry.help_id = GIMP_HELP_WINDOWS_SHOW_DOCK; gimp_action_group_add_actions (group, NULL, &entry, 1); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); g_object_set (action, "ellipsize", PANGO_ELLIPSIZE_END, @@ -490,15 +511,15 @@ GimpDockWindow *dock_window, GimpActionGroup *group) { - GtkAction *action; - gchar *action_name = windows_actions_dock_window_to_action_name (dock_window); + GimpAction *action; + gchar *action_name; - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); + action_name = windows_actions_dock_window_to_action_name (dock_window); + action = gimp_action_group_get_action (group, action_name); + g_free (action_name); if (action) - gimp_action_group_remove_action (group, GIMP_ACTION (action)); - - g_free (action_name); + gimp_action_group_remove_action_and_accel (group, action); } static void @@ -506,11 +527,11 @@ const GParamSpec *pspec, GimpActionGroup *group) { - GtkAction *action; - gchar *action_name; + GimpAction *action; + gchar *action_name; action_name = windows_actions_dock_window_to_action_name (dock_window); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); + action = gimp_action_group_get_action (group, action_name); g_free (action_name); if (action) @@ -525,7 +546,7 @@ GimpSessionInfo *info, GimpActionGroup *group) { - GtkAction *action; + GimpAction *action; GimpActionEntry entry; gint info_id; static gint info_id_counter = 1; @@ -549,13 +570,12 @@ entry.label = gimp_object_get_name (info); entry.accelerator = NULL; entry.tooltip = gimp_object_get_name (info); - entry.callback = G_CALLBACK (windows_open_recent_cmd_callback); + entry.callback = windows_open_recent_cmd_callback; entry.help_id = GIMP_HELP_WINDOWS_OPEN_RECENT_DOCK; gimp_action_group_add_actions (group, NULL, &entry, 1); - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), - action_name); + action = gimp_action_group_get_action (group, action_name); g_object_set (action, "ellipsize", PANGO_ELLIPSIZE_END, @@ -572,21 +592,19 @@ GimpSessionInfo *info, GimpActionGroup *group) { - GtkAction *action; - gint info_id; - gchar *action_name; + GimpAction *action; + gint info_id; + gchar *action_name; info_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), "recent-action-id")); action_name = g_strdup_printf ("windows-recent-%04d", info_id); - - action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); + action = gimp_action_group_get_action (group, action_name); + g_free (action_name); if (action) - gimp_action_group_remove_action (group, GIMP_ACTION (action)); - - g_free (action_name); + gimp_action_group_remove_action_and_accel (group, action); } static void diff -Nru gimp-2.10.8+zorin2/app/actions/windows-commands.c gimp-2.10.14+om/app/actions/windows-commands.c --- gimp-2.10.8+zorin2/app/actions/windows-commands.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/windows-commands.c 2019-10-26 18:49:18.000000000 +0000 @@ -50,14 +50,15 @@ void -windows_hide_docks_cmd_callback (GtkAction *action, - gpointer data) +windows_hide_docks_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; gboolean active; return_if_no_gimp (gimp, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); if (active != GIMP_GUI_CONFIG (gimp->config)->hide_docks) g_object_set (gimp->config, @@ -66,58 +67,61 @@ } void -windows_show_tabs_cmd_callback (GtkAction *action, - gpointer data) +windows_use_single_window_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { Gimp *gimp; gboolean active; return_if_no_gimp (gimp, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + active = g_variant_get_boolean (value); - if (active != GIMP_GUI_CONFIG (gimp->config)->show_tabs) + if (active != GIMP_GUI_CONFIG (gimp->config)->single_window_mode) g_object_set (gimp->config, - "show-tabs", active, + "single-window-mode", active, NULL); } - void -windows_set_tabs_position_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data) +windows_show_tabs_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - Gimp *gimp; - GimpPosition value; + Gimp *gimp; + gboolean active; return_if_no_gimp (gimp, data); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + active = g_variant_get_boolean (value); - if (value != GIMP_GUI_CONFIG (gimp->config)->tabs_position) + if (active != GIMP_GUI_CONFIG (gimp->config)->show_tabs) g_object_set (gimp->config, - "tabs-position", value, + "show-tabs", active, NULL); } + void -windows_use_single_window_mode_cmd_callback (GtkAction *action, - gpointer data) +windows_set_tabs_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { - Gimp *gimp; - gboolean active; + Gimp *gimp; + GimpPosition position; return_if_no_gimp (gimp, data); - active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + position = (GimpPosition) g_variant_get_int32 (value); - if (active != GIMP_GUI_CONFIG (gimp->config)->single_window_mode) + if (position != GIMP_GUI_CONFIG (gimp->config)->tabs_position) g_object_set (gimp->config, - "single-window-mode", active, + "tabs-position", position, NULL); } void -windows_show_display_next_cmd_callback (GtkAction *action, - gpointer data) +windows_show_display_next_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; Gimp *gimp; @@ -138,8 +142,9 @@ } void -windows_show_display_previous_cmd_callback (GtkAction *action, - gpointer data) +windows_show_display_previous_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display; Gimp *gimp; @@ -160,8 +165,9 @@ } void -windows_show_display_cmd_callback (GtkAction *action, - gpointer data) +windows_show_display_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpDisplay *display = g_object_get_data (G_OBJECT (action), "display"); @@ -169,8 +175,9 @@ } void -windows_show_dock_cmd_callback (GtkAction *action, - gpointer data) +windows_show_dock_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GtkWindow *dock_window = g_object_get_data (G_OBJECT (action), "dock-window"); @@ -178,8 +185,9 @@ } void -windows_open_recent_cmd_callback (GtkAction *action, - gpointer data) +windows_open_recent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data) { GimpSessionInfo *info; GimpDialogFactoryEntry *entry; diff -Nru gimp-2.10.8+zorin2/app/actions/windows-commands.h gimp-2.10.14+om/app/actions/windows-commands.h --- gimp-2.10.8+zorin2/app/actions/windows-commands.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/actions/windows-commands.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,28 +19,35 @@ #define __WINDOWS_COMMANDS_H__ -void windows_hide_docks_cmd_callback (GtkAction *action, - gpointer data); - -void windows_show_tabs_cmd_callback (GtkAction *action, - gpointer data); - -void windows_set_tabs_position_cmd_callback (GtkAction *action, - GtkAction *current, - gpointer data); -void windows_use_single_window_mode_cmd_callback (GtkAction *action, - gpointer data); - -void windows_show_display_next_cmd_callback (GtkAction *action, - gpointer data); -void windows_show_display_previous_cmd_callback (GtkAction *action, - gpointer data); -void windows_show_display_cmd_callback (GtkAction *action, - gpointer data); -void windows_show_dock_cmd_callback (GtkAction *action, - gpointer data); -void windows_open_recent_cmd_callback (GtkAction *action, - gpointer data); +void windows_hide_docks_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_use_single_window_mode_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void windows_show_tabs_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_set_tabs_position_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); + +void windows_show_display_next_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_show_display_previous_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_show_display_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_show_dock_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); +void windows_open_recent_cmd_callback (GimpAction *action, + GVariant *value, + gpointer data); #endif /* __WINDOWS_COMMANDS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/app.c gimp-2.10.14+om/app/app.c --- gimp-2.10.8+zorin2/app/app.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/app.c 2019-06-12 16:43:38.000000000 +0000 @@ -56,7 +56,6 @@ #include "core/gimp.h" #include "core/gimp-batch.h" #include "core/gimp-user-install.h" -#include "core/gimpbacktrace.h" #include "core/gimpimage.h" #include "file/file-open.h" @@ -213,12 +212,6 @@ filenames = NULL; } - /* Initialize GimpBacktrace early on. In particular, we want the - * Windows backend to catch the SET_THREAD_NAME exceptions of newly - * created threads. - */ - gimp_backtrace_init (); - /* Language needs to be determined first, before any GimpContext is * instantiated (which happens when the Gimp object is created) * because its properties need to be properly localized in the diff -Nru gimp-2.10.8+zorin2/app/config/config-enums.c gimp-2.10.14+om/app/config/config-enums.c --- gimp-2.10.8+zorin2/app/config/config-enums.c 2018-11-08 14:45:44.000000000 +0000 +++ gimp-2.10.14+om/app/config/config-enums.c 2019-10-26 19:20:33.000000000 +0000 @@ -102,6 +102,47 @@ } GType +gimp_export_file_type_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_EXPORT_FILE_PNG, "GIMP_EXPORT_FILE_PNG", "png" }, + { GIMP_EXPORT_FILE_JPG, "GIMP_EXPORT_FILE_JPG", "jpg" }, + { GIMP_EXPORT_FILE_ORA, "GIMP_EXPORT_FILE_ORA", "ora" }, + { GIMP_EXPORT_FILE_PSD, "GIMP_EXPORT_FILE_PSD", "psd" }, + { GIMP_EXPORT_FILE_PDF, "GIMP_EXPORT_FILE_PDF", "pdf" }, + { GIMP_EXPORT_FILE_TIF, "GIMP_EXPORT_FILE_TIF", "tif" }, + { GIMP_EXPORT_FILE_BMP, "GIMP_EXPORT_FILE_BMP", "bmp" }, + { GIMP_EXPORT_FILE_WEBP, "GIMP_EXPORT_FILE_WEBP", "webp" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_EXPORT_FILE_PNG, NC_("export-file-type", "PNG Image"), NULL }, + { GIMP_EXPORT_FILE_JPG, NC_("export-file-type", "JPEG Image"), NULL }, + { GIMP_EXPORT_FILE_ORA, NC_("export-file-type", "OpenRaster Image"), NULL }, + { GIMP_EXPORT_FILE_PSD, NC_("export-file-type", "Photoshop Image"), NULL }, + { GIMP_EXPORT_FILE_PDF, NC_("export-file-type", "Portable Document Format"), NULL }, + { GIMP_EXPORT_FILE_TIF, NC_("export-file-type", "TIFF Image"), NULL }, + { GIMP_EXPORT_FILE_BMP, NC_("export-file-type", "Windows BMP Image"), NULL }, + { GIMP_EXPORT_FILE_WEBP, NC_("export-file-type", "WebP Image"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpExportFileType", values); + gimp_type_set_translation_context (type, "export-file-type"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + +GType gimp_handedness_get_type (void) { static const GEnumValue values[] = diff -Nru gimp-2.10.8+zorin2/app/config/config-enums.h gimp-2.10.14+om/app/config/config-enums.h --- gimp-2.10.8+zorin2/app/config/config-enums.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/config-enums.h 2019-01-03 14:13:22.000000000 +0000 @@ -56,6 +56,23 @@ } GimpCursorMode; +#define GIMP_TYPE_EXPORT_FILE_TYPE (gimp_export_file_type_get_type ()) + +GType gimp_export_file_type_get_type (void) G_GNUC_CONST; + +typedef enum +{ + GIMP_EXPORT_FILE_PNG, /*< desc="PNG Image" >*/ + GIMP_EXPORT_FILE_JPG, /*< desc="JPEG Image" >*/ + GIMP_EXPORT_FILE_ORA, /*< desc="OpenRaster Image" >*/ + GIMP_EXPORT_FILE_PSD, /*< desc="Photoshop Image" >*/ + GIMP_EXPORT_FILE_PDF, /*< desc="Portable Document Format" >*/ + GIMP_EXPORT_FILE_TIF, /*< desc="TIFF Image" >*/ + GIMP_EXPORT_FILE_BMP, /*< desc="Windows BMP Image" >*/ + GIMP_EXPORT_FILE_WEBP, /*< desc="WebP Image" >*/ +} GimpExportFileType; + + #define GIMP_TYPE_HANDEDNESS (gimp_handedness_get_type ()) GType gimp_handedness_get_type (void) G_GNUC_CONST; diff -Nru gimp-2.10.8+zorin2/app/config/gimpconfig-dump.c gimp-2.10.14+om/app/config/gimpconfig-dump.c --- gimp-2.10.8+zorin2/app/config/gimpconfig-dump.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpconfig-dump.c 2019-01-03 14:13:22.000000000 +0000 @@ -271,6 +271,14 @@ "Path to configuration files, which is set to the value of the environment\n" "variable GIMP2_SYSCONFDIR or to the compiled-in default value \n" "@gimpsysconfdir@.\n" +".TP\n" +".I gimp_cache_dir\n" +"Path to cached files, which is set to the value of the environment\n" +"variable GIMP2_CACHEDIR or to the system default for per-user cached files.\n" +".TP\n" +".I gimp_temp_dir\n" +"Path to temporary files, which is set to the value of the environment\n" +"variable GIMP2_TEMPDIR or to the system default for temporary files.\n" "\n"; static const gchar man_page_footer[] = diff -Nru gimp-2.10.8+zorin2/app/config/gimpcoreconfig.c gimp-2.10.14+om/app/config/gimpcoreconfig.c --- gimp-2.10.8+zorin2/app/config/gimpcoreconfig.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpcoreconfig.c 2019-06-12 16:43:38.000000000 +0000 @@ -24,6 +24,16 @@ #include #include +#ifdef G_OS_WIN32 +#include + +/* Constant available since Shell32.dll 5.0 */ +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif + +#endif + #include "libgimpbase/gimpbase.h" #include "libgimpcolor/gimpcolor.h" #include "libgimpconfig/gimpconfig.h" @@ -41,15 +51,15 @@ #include "gimp-intl.h" -#define DEFAULT_BRUSH "2. Hardness 050" -#define DEFAULT_DYNAMICS "Dynamics Off" -#define DEFAULT_PATTERN "Pine" -#define DEFAULT_PALETTE "Default" -#define DEFAULT_GRADIENT "FG to BG (RGB)" -#define DEFAULT_TOOL_PRESET "Current Options" -#define DEFAULT_FONT "Sans-serif" -#define DEFAULT_MYPAINT_BRUSH "Fixme" -#define DEFAULT_COMMENT "Created with GIMP" +#define GIMP_DEFAULT_BRUSH "2. Hardness 050" +#define GIMP_DEFAULT_DYNAMICS "Dynamics Off" +#define GIMP_DEFAULT_PATTERN "Pine" +#define GIMP_DEFAULT_PALETTE "Default" +#define GIMP_DEFAULT_GRADIENT "FG to BG (RGB)" +#define GIMP_DEFAULT_TOOL_PRESET "Current Options" +#define GIMP_DEFAULT_FONT "Sans-serif" +#define GIMP_DEFAULT_MYPAINT_BRUSH "Fixme" +#define GIMP_DEFAULT_COMMENT "Created with GIMP" enum @@ -111,6 +121,7 @@ PROP_IMPORT_PROMOTE_DITHER, PROP_IMPORT_ADD_ALPHA, PROP_IMPORT_RAW_PLUG_IN, + PROP_EXPORT_FILE_TYPE, PROP_EXPORT_COLOR_PROFILE, PROP_EXPORT_METADATA_EXIF, PROP_EXPORT_METADATA_XMP, @@ -147,6 +158,34 @@ #define parent_class gimp_core_config_parent_class +#ifdef G_OS_WIN32 +/* + * Taken from glib 2.35 code / gimpenv.c. + * Only temporary until the user-font folder detection can go upstream + * in fontconfig! + * XXX + */ +static gchar * +get_special_folder (int csidl) +{ + wchar_t path[MAX_PATH+1]; + HRESULT hr; + LPITEMIDLIST pidl = NULL; + BOOL b; + gchar *retval = NULL; + + hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl); + if (hr == S_OK) + { + b = SHGetPathFromIDListW (pidl, path); + if (b) + retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL); + CoTaskMemFree (pidl); + } + + return retval; +} +#endif static void gimp_core_config_class_init (GimpCoreConfigClass *klass) @@ -380,6 +419,36 @@ g_free (path); path = gimp_config_build_data_path ("fonts"); +#if defined G_OS_WIN32 + /* XXX: since a Windows 10 update, build 17704, Microsoft added the + * concept of user-installed fonts (until now it was only possible to + * have system-wide fonts! How weird is that?). + * A feature request at fontconfig is also done, but until this gets + * implemented upstream, let's add the folder ourselves in GIMP's + * default list of folders. + * See: https://gitlab.gnome.org/GNOME/gimp/issues/2949 + * Also: https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/144 + */ + { + gchar *user_fonts_dir = get_special_folder (CSIDL_LOCAL_APPDATA); + + if (user_fonts_dir) + { + gchar *path2; + gchar *tmp; + + path2 = g_build_filename (user_fonts_dir, + "Microsoft", "Windows", "Fonts", NULL); + g_free (user_fonts_dir); + + /* G_SEARCHPATH_SEPARATOR-separated list of folders. */ + tmp = g_strconcat (path2, G_SEARCHPATH_SEPARATOR_S, path, NULL); + g_free (path2); + g_free (path); + path = tmp; + } + } +#endif GIMP_CONFIG_PROP_PATH (object_class, PROP_FONT_PATH, "font-path", "Font path", @@ -401,56 +470,56 @@ "default-brush", "Default brush", DEFAULT_BRUSH_BLURB, - DEFAULT_BRUSH, + GIMP_DEFAULT_BRUSH, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_DYNAMICS, "default-dynamics", "Default dynamics", DEFAULT_DYNAMICS_BLURB, - DEFAULT_DYNAMICS, + GIMP_DEFAULT_DYNAMICS, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_MYPAINT_BRUSH, "default-mypaint-brush", "Default MyPaint brush", DEFAULT_MYPAINT_BRUSH_BLURB, - DEFAULT_MYPAINT_BRUSH, + GIMP_DEFAULT_MYPAINT_BRUSH, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_PATTERN, "default-pattern", "Default pattern", DEFAULT_PATTERN_BLURB, - DEFAULT_PATTERN, + GIMP_DEFAULT_PATTERN, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_PALETTE, "default-palette", "Default palette", DEFAULT_PALETTE_BLURB, - DEFAULT_PALETTE, + GIMP_DEFAULT_PALETTE, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_GRADIENT, "default-gradient", "Default gradient", DEFAULT_GRADIENT_BLURB, - DEFAULT_GRADIENT, + GIMP_DEFAULT_GRADIENT, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_TOOL_PRESET, "default-tool-preset", "Default tool preset", DEFAULT_TOOL_PRESET_BLURB, - DEFAULT_TOOL_PRESET, + GIMP_DEFAULT_TOOL_PRESET, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_STRING (object_class, PROP_DEFAULT_FONT, "default-font", "Default font", DEFAULT_FONT_BLURB, - DEFAULT_FONT, + GIMP_DEFAULT_FONT, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_GLOBAL_BRUSH, @@ -650,6 +719,14 @@ GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_RESTART); + GIMP_CONFIG_PROP_ENUM (object_class, PROP_EXPORT_FILE_TYPE, + "export-file-type", + "Default export file type", + EXPORT_FILE_TYPE_BLURB, + GIMP_TYPE_EXPORT_FILE_TYPE, + GIMP_EXPORT_FILE_PNG, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_EXPORT_COLOR_PROFILE, "export-color-profile", "Export Color Profile", @@ -711,7 +788,7 @@ { config->default_image = g_object_new (GIMP_TYPE_TEMPLATE, "name", "Default Image", - "comment", DEFAULT_COMMENT, + "comment", GIMP_DEFAULT_COMMENT, NULL); g_signal_connect (config->default_image, "notify", G_CALLBACK (gimp_core_config_default_image_notify), @@ -986,6 +1063,9 @@ g_free (core_config->import_raw_plug_in); core_config->import_raw_plug_in = g_value_dup_string (value); break; + case PROP_EXPORT_FILE_TYPE: + core_config->export_file_type = g_value_get_enum (value); + break; case PROP_EXPORT_COLOR_PROFILE: core_config->export_color_profile = g_value_get_boolean (value); break; @@ -1191,6 +1271,9 @@ case PROP_IMPORT_RAW_PLUG_IN: g_value_set_string (value, core_config->import_raw_plug_in); break; + case PROP_EXPORT_FILE_TYPE: + g_value_set_enum (value, core_config->export_file_type); + break; case PROP_EXPORT_COLOR_PROFILE: g_value_set_boolean (value, core_config->export_color_profile); break; diff -Nru gimp-2.10.8+zorin2/app/config/gimpcoreconfig.h gimp-2.10.14+om/app/config/gimpcoreconfig.h --- gimp-2.10.8+zorin2/app/config/gimpcoreconfig.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpcoreconfig.h 2019-01-03 14:13:22.000000000 +0000 @@ -96,6 +96,7 @@ gboolean import_promote_dither; gboolean import_add_alpha; gchar *import_raw_plug_in; + GimpExportFileType export_file_type; gboolean export_color_profile; gboolean export_metadata_exif; gboolean export_metadata_xmp; diff -Nru gimp-2.10.8+zorin2/app/config/gimpdialogconfig.c gimp-2.10.14+om/app/config/gimpdialogconfig.c --- gimp-2.10.8+zorin2/app/config/gimpdialogconfig.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdialogconfig.c 2019-10-26 18:49:18.000000000 +0000 @@ -98,6 +98,7 @@ PROP_VECTORS_IMPORT_SCALE, PROP_SELECTION_FEATHER_RADIUS, + PROP_SELECTION_FEATHER_EDGE_LOCK, PROP_SELECTION_GROW_RADIUS, @@ -185,7 +186,7 @@ GIMP_CONFIG_PROP_ENUM (object_class, PROP_IMAGE_CONVERT_PROFILE_INTENT, "image-convert-profile-intent", - "Default rendering intent fo color profile conversion", + "Default rendering intent for color profile conversion", IMAGE_CONVERT_PROFILE_INTENT_BLURB, GIMP_TYPE_COLOR_RENDERING_INTENT, GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, @@ -465,6 +466,13 @@ 0.0, 32767.0, 5.0, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SELECTION_FEATHER_EDGE_LOCK, + "selection-feather-edge-lock", + "Selection feather edge lock", + SELECTION_FEATHER_EDGE_LOCK_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_SELECTION_GROW_RADIUS, "selection-grow-radius", "Selection grow radius", @@ -736,6 +744,9 @@ case PROP_SELECTION_FEATHER_RADIUS: config->selection_feather_radius = g_value_get_double (value); break; + case PROP_SELECTION_FEATHER_EDGE_LOCK: + config->selection_feather_edge_lock = g_value_get_boolean (value); + break; case PROP_SELECTION_GROW_RADIUS: config->selection_grow_radius = g_value_get_double (value); @@ -921,6 +932,9 @@ case PROP_SELECTION_FEATHER_RADIUS: g_value_set_double (value, config->selection_feather_radius); break; + case PROP_SELECTION_FEATHER_EDGE_LOCK: + g_value_set_boolean (value, config->selection_feather_edge_lock); + break; case PROP_SELECTION_GROW_RADIUS: g_value_set_double (value, config->selection_grow_radius); diff -Nru gimp-2.10.8+zorin2/app/config/gimpdialogconfig.h gimp-2.10.14+om/app/config/gimpdialogconfig.h --- gimp-2.10.8+zorin2/app/config/gimpdialogconfig.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdialogconfig.h 2019-10-26 18:49:18.000000000 +0000 @@ -96,6 +96,7 @@ gboolean vectors_import_scale; gdouble selection_feather_radius; + gboolean selection_feather_edge_lock; gdouble selection_grow_radius; diff -Nru gimp-2.10.8+zorin2/app/config/gimpdisplayconfig.c gimp-2.10.14+om/app/config/gimpdisplayconfig.c --- gimp-2.10.8+zorin2/app/config/gimpdisplayconfig.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdisplayconfig.c 2019-10-26 18:49:18.000000000 +0000 @@ -51,6 +51,7 @@ PROP_MARCHING_ANTS_SPEED, PROP_RESIZE_WINDOWS_ON_ZOOM, PROP_RESIZE_WINDOWS_ON_RESIZE, + PROP_DEFAULT_SHOW_ALL, PROP_DEFAULT_DOT_FOR_DOT, PROP_INITIAL_ZOOM_TO_FIT, PROP_CURSOR_MODE, @@ -158,6 +159,13 @@ FALSE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DEFAULT_SHOW_ALL, + "default-show-all", + "Default show-all", + DEFAULT_SHOW_ALL_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DEFAULT_DOT_FOR_DOT, "default-dot-for-dot", "Default dot-for-dot", @@ -401,6 +409,9 @@ case PROP_RESIZE_WINDOWS_ON_RESIZE: display_config->resize_windows_on_resize = g_value_get_boolean (value); break; + case PROP_DEFAULT_SHOW_ALL: + display_config->default_show_all = g_value_get_boolean (value); + break; case PROP_DEFAULT_DOT_FOR_DOT: display_config->default_dot_for_dot = g_value_get_boolean (value); break; @@ -507,6 +518,9 @@ case PROP_RESIZE_WINDOWS_ON_RESIZE: g_value_set_boolean (value, display_config->resize_windows_on_resize); break; + case PROP_DEFAULT_SHOW_ALL: + g_value_set_boolean (value, display_config->default_show_all); + break; case PROP_DEFAULT_DOT_FOR_DOT: g_value_set_boolean (value, display_config->default_dot_for_dot); break; diff -Nru gimp-2.10.8+zorin2/app/config/gimpdisplayconfig.h gimp-2.10.14+om/app/config/gimpdisplayconfig.h --- gimp-2.10.8+zorin2/app/config/gimpdisplayconfig.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdisplayconfig.h 2019-10-26 18:49:18.000000000 +0000 @@ -47,6 +47,7 @@ gint marching_ants_speed; gboolean resize_windows_on_zoom; gboolean resize_windows_on_resize; + gboolean default_show_all; gboolean default_dot_for_dot; gboolean initial_zoom_to_fit; GimpCursorMode cursor_mode; diff -Nru gimp-2.10.8+zorin2/app/config/gimpdisplayoptions.c gimp-2.10.14+om/app/config/gimpdisplayoptions.c --- gimp-2.10.8+zorin2/app/config/gimpdisplayoptions.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdisplayoptions.c 2019-10-26 18:49:18.000000000 +0000 @@ -47,6 +47,7 @@ PROP_SHOW_SCROLLBARS, PROP_SHOW_SELECTION, PROP_SHOW_LAYER_BOUNDARY, + PROP_SHOW_CANVAS_BOUNDARY, PROP_SHOW_GUIDES, PROP_SHOW_GRID, PROP_SHOW_SAMPLE_POINTS, @@ -55,7 +56,8 @@ PROP_SNAP_TO_CANVAS, PROP_SNAP_TO_PATH, PROP_PADDING_MODE, - PROP_PADDING_COLOR + PROP_PADDING_COLOR, + PROP_PADDING_IN_SHOW_ALL }; @@ -148,6 +150,13 @@ TRUE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_CANVAS_BOUNDARY, + "show-canvas-boundary", + "Show canvas boundary", + SHOW_CANVAS_BOUNDARY_BLURB, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_GUIDES, "show-guides", "Show guides", @@ -211,6 +220,13 @@ CANVAS_PADDING_COLOR_BLURB, FALSE, &white, GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_PADDING_IN_SHOW_ALL, + "padding-in-show-all", + "Keep padding in \"Show All\" mode", + CANVAS_PADDING_IN_SHOW_ALL_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); } static void @@ -266,6 +282,13 @@ FALSE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_CANVAS_BOUNDARY, + "show-canvas-boundary", + "Show canvas boundary", + SHOW_CANVAS_BOUNDARY_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_GUIDES, "show-guides", "Show guides", @@ -329,6 +352,13 @@ CANVAS_PADDING_COLOR_BLURB, FALSE, &black, GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_PADDING_IN_SHOW_ALL, + "padding-in-show-all", + "Keep padding in \"Show All\" mode", + CANVAS_PADDING_IN_SHOW_ALL_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); } static void @@ -367,6 +397,13 @@ FALSE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_CANVAS_BOUNDARY, + "show-canvas-boundary", + "Show canvas boundary", + SHOW_CANVAS_BOUNDARY_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_GUIDES, "show-guides", "Show guides", @@ -451,6 +488,9 @@ case PROP_SHOW_LAYER_BOUNDARY: options->show_layer_boundary = g_value_get_boolean (value); break; + case PROP_SHOW_CANVAS_BOUNDARY: + options->show_canvas_boundary = g_value_get_boolean (value); + break; case PROP_SHOW_GUIDES: options->show_guides = g_value_get_boolean (value); break; @@ -478,6 +518,9 @@ case PROP_PADDING_COLOR: options->padding_color = *(GimpRGB *) g_value_get_boxed (value); break; + case PROP_PADDING_IN_SHOW_ALL: + options->padding_in_show_all = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -513,6 +556,9 @@ case PROP_SHOW_LAYER_BOUNDARY: g_value_set_boolean (value, options->show_layer_boundary); break; + case PROP_SHOW_CANVAS_BOUNDARY: + g_value_set_boolean (value, options->show_canvas_boundary); + break; case PROP_SHOW_GUIDES: g_value_set_boolean (value, options->show_guides); break; @@ -540,6 +586,9 @@ case PROP_PADDING_COLOR: g_value_set_boxed (value, &options->padding_color); break; + case PROP_PADDING_IN_SHOW_ALL: + g_value_set_boolean (value, options->padding_in_show_all); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); diff -Nru gimp-2.10.8+zorin2/app/config/gimpdisplayoptions.h gimp-2.10.14+om/app/config/gimpdisplayoptions.h --- gimp-2.10.8+zorin2/app/config/gimpdisplayoptions.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpdisplayoptions.h 2019-10-26 18:49:18.000000000 +0000 @@ -48,6 +48,7 @@ gboolean show_scrollbars; gboolean show_selection; gboolean show_layer_boundary; + gboolean show_canvas_boundary; gboolean show_guides; gboolean show_grid; gboolean show_sample_points; @@ -60,6 +61,7 @@ GimpCanvasPaddingMode padding_mode; GimpRGB padding_color; gboolean padding_mode_set; + gboolean padding_in_show_all; }; struct _GimpDisplayOptionsClass diff -Nru gimp-2.10.8+zorin2/app/config/gimpgeglconfig.c gimp-2.10.14+om/app/config/gimpgeglconfig.c --- gimp-2.10.8+zorin2/app/config/gimpgeglconfig.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpgeglconfig.c 2019-10-26 18:49:18.000000000 +0000 @@ -38,7 +38,9 @@ #include "gimp-intl.h" -#define GIMP_MAX_MEM_PROCESS (MIN (G_MAXSIZE, GIMP_MAX_MEMSIZE)) +#define GIMP_DEFAULT_SWAP_COMPRESSION "fast" + +#define GIMP_MAX_MEM_PROCESS (MIN (G_MAXSIZE, GIMP_MAX_MEMSIZE)) enum @@ -46,6 +48,7 @@ PROP_0, PROP_TEMP_PATH, PROP_SWAP_PATH, + PROP_SWAP_COMPRESSION, PROP_NUM_PROCESSORS, PROP_TILE_CACHE_SIZE, PROP_USE_OPENCL, @@ -55,9 +58,7 @@ }; -static void gimp_gegl_config_class_init (GimpGeglConfigClass *klass); -static void gimp_gegl_config_init (GimpGeglConfig *config, - GimpGeglConfigClass *klass); +static void gimp_gegl_config_constructed (GObject *object); static void gimp_gegl_config_finalize (GObject *object); static void gimp_gegl_config_set_property (GObject *object, guint property_id, @@ -69,36 +70,10 @@ GParamSpec *pspec); -static GObjectClass *parent_class = NULL; - - -GType -gimp_gegl_config_get_type (void) -{ - static GType config_type = 0; +G_DEFINE_TYPE (GimpGeglConfig, gimp_gegl_config, G_TYPE_OBJECT) - if (! config_type) - { - const GTypeInfo config_info = - { - sizeof (GimpGeglConfigClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_gegl_config_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpGeglConfig), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_gegl_config_init, - }; - - config_type = g_type_register_static (G_TYPE_OBJECT, - "GimpGeglConfig", - &config_info, 0); - } +#define parent_class gimp_gegl_config_parent_class - return config_type; -} static void gimp_gegl_config_class_init (GimpGeglConfigClass *klass) @@ -110,6 +85,7 @@ parent_class = g_type_class_peek_parent (klass); + object_class->constructed = gimp_gegl_config_constructed; object_class->finalize = gimp_gegl_config_finalize; object_class->set_property = gimp_gegl_config_set_property; object_class->get_property = gimp_gegl_config_get_property; @@ -119,7 +95,7 @@ "Temp path", TEMP_PATH_BLURB, GIMP_CONFIG_PATH_DIR, - "${gimp_dir}" G_DIR_SEPARATOR_S "tmp", + "${gimp_temp_dir}", GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_RESTART); @@ -128,10 +104,17 @@ "Swap path", SWAP_PATH_BLURB, GIMP_CONFIG_PATH_DIR, - "${gimp_dir}", + "${gimp_cache_dir}", GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_RESTART); + GIMP_CONFIG_PROP_STRING (object_class, PROP_SWAP_COMPRESSION, + "swap-compression", + "Swap compression", + SWAP_COMPRESSION_BLURB, + GIMP_DEFAULT_SWAP_COMPRESSION, + GIMP_PARAM_STATIC_STRINGS); + n_threads = g_get_num_processors (); max_n_threads = @@ -182,10 +165,16 @@ } static void -gimp_gegl_config_init (GimpGeglConfig *config, - GimpGeglConfigClass *klass) +gimp_gegl_config_init (GimpGeglConfig *config) { - gimp_debug_add_instance (G_OBJECT (config), G_OBJECT_CLASS (klass)); +} + +static void +gimp_gegl_config_constructed (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->constructed (object); + + gimp_debug_add_instance (object, G_OBJECT_GET_CLASS (object)); } static void @@ -195,6 +184,7 @@ g_free (gegl_config->temp_path); g_free (gegl_config->swap_path); + g_free (gegl_config->swap_compression); gimp_debug_remove_instance (object); @@ -219,6 +209,10 @@ g_free (gegl_config->swap_path); gegl_config->swap_path = g_value_dup_string (value); break; + case PROP_SWAP_COMPRESSION: + g_free (gegl_config->swap_compression); + gegl_config->swap_compression = g_value_dup_string (value); + break; case PROP_NUM_PROCESSORS: gegl_config->num_processors = g_value_get_int (value); break; @@ -255,6 +249,9 @@ case PROP_SWAP_PATH: g_value_set_string (value, gegl_config->swap_path); break; + case PROP_SWAP_COMPRESSION: + g_value_set_string (value, gegl_config->swap_compression); + break; case PROP_NUM_PROCESSORS: g_value_set_int (value, gegl_config->num_processors); break; diff -Nru gimp-2.10.8+zorin2/app/config/gimpgeglconfig.h gimp-2.10.14+om/app/config/gimpgeglconfig.h --- gimp-2.10.8+zorin2/app/config/gimpgeglconfig.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpgeglconfig.h 2019-10-26 18:49:18.000000000 +0000 @@ -37,6 +37,7 @@ gchar *temp_path; gchar *swap_path; + gchar *swap_compression; gint num_processors; guint64 tile_cache_size; gboolean use_opencl; diff -Nru gimp-2.10.8+zorin2/app/config/gimpguiconfig.c gimp-2.10.14+om/app/config/gimpguiconfig.c --- gimp-2.10.8+zorin2/app/config/gimpguiconfig.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpguiconfig.c 2019-10-26 18:49:18.000000000 +0000 @@ -52,6 +52,7 @@ enum { PROP_0, + PROP_EDIT_NON_VISIBLE, PROP_MOVE_TOOL_CHANGES_ACTIVE, PROP_FILTER_TOOL_MAX_RECENT, PROP_FILTER_TOOL_USE_LAST_SETTINGS, @@ -151,6 +152,13 @@ object_class->set_property = gimp_gui_config_set_property; object_class->get_property = gimp_gui_config_get_property; + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_EDIT_NON_VISIBLE, + "edit-non-visible", + "Non-visible layers can be edited", + EDIT_NON_VISIBLE_BLURB, + FALSE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_MOVE_TOOL_CHANGES_ACTIVE, "move-tool-changes-active", "Move tool changes active layer", @@ -580,6 +588,9 @@ switch (property_id) { + case PROP_EDIT_NON_VISIBLE: + gui_config->edit_non_visible = g_value_get_boolean (value); + break; case PROP_MOVE_TOOL_CHANGES_ACTIVE: gui_config->move_tool_changes_active = g_value_get_boolean (value); break; @@ -768,6 +779,9 @@ switch (property_id) { + case PROP_EDIT_NON_VISIBLE: + g_value_set_boolean (value, gui_config->edit_non_visible); + break; case PROP_MOVE_TOOL_CHANGES_ACTIVE: g_value_set_boolean (value, gui_config->move_tool_changes_active); break; diff -Nru gimp-2.10.8+zorin2/app/config/gimpguiconfig.h gimp-2.10.14+om/app/config/gimpguiconfig.h --- gimp-2.10.8+zorin2/app/config/gimpguiconfig.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimpguiconfig.h 2019-10-26 18:49:18.000000000 +0000 @@ -41,6 +41,7 @@ { GimpDisplayConfig parent_instance; + gboolean edit_non_visible; gboolean move_tool_changes_active; gint filter_tool_max_recent; gboolean filter_tool_use_last_settings; diff -Nru gimp-2.10.8+zorin2/app/config/gimplangrc.c gimp-2.10.14+om/app/config/gimplangrc.c --- gimp-2.10.8+zorin2/app/config/gimplangrc.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimplangrc.c 2019-06-12 16:43:38.000000000 +0000 @@ -149,11 +149,8 @@ g_clear_object (&rc->system_gimprc); g_clear_object (&rc->user_gimprc); - if (rc->language) - { - g_free (rc->language); - rc->language = NULL; - } + + g_clear_pointer (&rc->language, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } diff -Nru gimp-2.10.8+zorin2/app/config/gimprc-blurbs.h gimp-2.10.14+om/app/config/gimprc-blurbs.h --- gimp-2.10.8+zorin2/app/config/gimprc-blurbs.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/config/gimprc-blurbs.h 2019-10-26 18:49:18.000000000 +0000 @@ -33,6 +33,10 @@ _("Sets the canvas padding color used if the padding mode is set to " \ "custom color.") +#define CANVAS_PADDING_IN_SHOW_ALL_BLURB \ +_("Specifies whether to keep the canvas padding when \"View -> Show All\" " \ + "is enabled.") + #define CANVAS_PADDING_MODE_BLURB \ _("Specifies how the area around the image should be drawn.") @@ -67,6 +71,9 @@ "Specify a default tool preset. The tool preset is searched for in the " \ "specified tool prests path." +#define DEFAULT_SHOW_ALL_BLURB \ +_("Show full image content by default.") + #define DEFAULT_DOT_FOR_DOT_BLURB \ _("When enabled, this will ensure that each pixel of an image gets " \ "mapped to a pixel on the screen.") @@ -97,16 +104,16 @@ "activates.") #define SNAP_TO_GUIDES_BLURB \ -"Snap to guides by default in new image windows." +_("Snap to guides by default in new image windows.") #define SNAP_TO_GRID_BLURB \ -"Snap to the grid by default in new image windows." +_("Snap to the grid by default in new image windows.") #define SNAP_TO_CANVAS_BLURB \ -"Snap to the canvas edges by default in new image windows." +_("Snap to the canvas edges by default in new image windows.") #define SNAP_TO_PATH_BLURB \ -"Snap to the active path by default in new image windows." +_("Snap to the active path by default in new image windows.") #define DEFAULT_THRESHOLD_BLURB \ _("Tools such as fuzzy-select and bucket fill find regions based on a " \ @@ -204,6 +211,9 @@ #define IMPORT_RAW_PLUG_IN_BLURB \ _("Which plug-in to use for importing raw digital camera files.") +#define EXPORT_FILE_TYPE_BLURB \ +_("Export file type used by default.") + #define EXPORT_COLOR_PROFILE_BLURB \ _("Export the image's color profile by default.") @@ -269,6 +279,9 @@ "0, forces the X server to be queried for both horizontal and vertical " \ "resolution information.") +#define EDIT_NON_VISIBLE_BLURB \ +_("When enabled, non-visible layers can be edited as normal.") + #define MOVE_TOOL_CHANGES_ACTIVE_BLURB \ _("If enabled, the move tool sets the edited layer or path as active. " \ "This used to be the default behaviour in older versions.") @@ -397,6 +410,10 @@ _("When enabled, the layer boundary is visible by default. This can also " \ "be toggled with the \"View->Show Layer Boundary\" command.") +#define SHOW_CANVAS_BOUNDARY_BLURB \ +_("When enabled, the canvas boundary is visible by default. This can also " \ + "be toggled with the \"View->Show Canvas Boundary\" command.") + #define SHOW_GUIDES_BLURB \ _("When enabled, the guides are visible by default. This can also be " \ "toggled with the \"View->Show Guides\" command.") @@ -439,6 +456,9 @@ #define SPACE_BAR_ACTION_BLURB \ _("What to do when the space bar is pressed in the image window.") +#define SWAP_COMPRESSION_BLURB \ +_("The compression method used for tile data stored in the swap file.") + #define SWAP_PATH_BLURB \ _("Sets the swap file location. GIMP uses a tile based memory allocation " \ "scheme. The swap file is used to quickly and easily swap tiles out to " \ @@ -468,7 +488,7 @@ "is best if this folder not be one that is shared by other users.") #define THEME_BLURB \ -"The name of the theme to use." +_("The name of the theme to use.") #define THEME_PATH_BLURB \ "Sets the theme search path." @@ -591,6 +611,10 @@ #define SELECTION_FEATHER_RADIUS_BLURB \ _("Sets the default feather radius for the 'Feather Selection' dialog.") +#define SELECTION_FEATHER_EDGE_LOCK_BLURB \ +_("Sets the default 'Selected areas continue outside the image' setting " \ + "for the 'Feather Selection' dialog.") + #define SELECTION_GROW_RADIUS_BLURB \ _("Sets the default grow radius for the 'Grow Selection' dialog.") @@ -686,10 +710,10 @@ "offset problems turning it off helps." #define SEARCH_SHOW_UNAVAILABLE_BLURB \ -"When enabled, a search of actions will also return inactive actions." +_("When enabled, a search of actions will also return inactive actions.") #define ACTION_HISTORY_SIZE_BLURB \ -"The maximum number of actions saved in history." +_("The maximum number of actions saved in history.") #endif /* __GIMP_RC_BLURBS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/config/Makefile.am gimp-2.10.14+om/app/config/Makefile.am --- gimp-2.10.8+zorin2/app/config/Makefile.am 2018-07-04 11:00:26.000000000 +0000 +++ gimp-2.10.14+om/app/config/Makefile.am 2019-06-12 16:43:38.000000000 +0000 @@ -15,7 +15,6 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Gimp-Config\" \ -DGIMP_APP_VERSION_STRING=\"$(GIMP_APP_VERSION)\" \ - -DDATADIR=\""$(datadir)"\" \ -I$(top_builddir) \ -I$(top_srcdir) \ -I$(top_builddir)/app \ @@ -105,6 +104,7 @@ ../vectors/libappvectors.a \ ../core/libappcore.a \ ../file/libappfile.a \ + ../file-data/libappfile-data.a \ ../text/libapptext.a \ ../paint/libapppaint.a \ ../gegl/libappgegl.a \ diff -Nru gimp-2.10.8+zorin2/app/config/Makefile.in gimp-2.10.14+om/app/config/Makefile.in --- gimp-2.10.8+zorin2/app/config/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/config/Makefile.in 2019-10-27 17:12:52.000000000 +0000 @@ -105,7 +105,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -445,8 +444,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -576,7 +573,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -715,8 +711,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -849,7 +843,6 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Gimp-Config\" \ -DGIMP_APP_VERSION_STRING=\"$(GIMP_APP_VERSION)\" \ - -DDATADIR=\""$(datadir)"\" \ -I$(top_builddir) \ -I$(top_srcdir) \ -I$(top_builddir)/app \ @@ -930,6 +923,7 @@ ../vectors/libappvectors.a \ ../core/libappcore.a \ ../file/libappfile.a \ + ../file-data/libappfile-data.a \ ../text/libapptext.a \ ../paint/libapppaint.a \ ../gegl/libappgegl.a \ diff -Nru gimp-2.10.8+zorin2/app/core/core-enums.c gimp-2.10.14+om/app/core/core-enums.c --- gimp-2.10.8+zorin2/app/core/core-enums.c 2018-11-08 14:45:53.000000000 +0000 +++ gimp-2.10.14+om/app/core/core-enums.c 2019-10-26 19:20:35.000000000 +0000 @@ -185,7 +185,7 @@ { { GIMP_COLOR_PROFILE_POLICY_ASK, NC_("color-profile-policy", "Ask what to do"), NULL }, { GIMP_COLOR_PROFILE_POLICY_KEEP, NC_("color-profile-policy", "Keep embedded profile"), NULL }, - { GIMP_COLOR_PROFILE_POLICY_CONVERT, NC_("color-profile-policy", "Convert to preferred RGB color profile"), NULL }, + { GIMP_COLOR_PROFILE_POLICY_CONVERT, NC_("color-profile-policy", "Convert to built-in sRGB or grayscale profile"), NULL }, { 0, NULL, NULL } }; @@ -330,6 +330,35 @@ } GType +gimp_curve_point_type_get_type (void) +{ + static const GEnumValue values[] = + { + { GIMP_CURVE_POINT_SMOOTH, "GIMP_CURVE_POINT_SMOOTH", "smooth" }, + { GIMP_CURVE_POINT_CORNER, "GIMP_CURVE_POINT_CORNER", "corner" }, + { 0, NULL, NULL } + }; + + static const GimpEnumDesc descs[] = + { + { GIMP_CURVE_POINT_SMOOTH, NC_("curve-point-type", "Smooth"), NULL }, + { GIMP_CURVE_POINT_CORNER, NC_("curve-point-type", "Corner"), NULL }, + { 0, NULL, NULL } + }; + + static GType type = 0; + + if (G_UNLIKELY (! type)) + { + type = g_enum_register_static ("GimpCurvePointType", values); + gimp_type_set_translation_context (type, "curve-point-type"); + gimp_enum_set_value_descriptions (type, descs); + } + + return type; +} + +GType gimp_curve_type_get_type (void) { static const GEnumValue values[] = @@ -1005,6 +1034,7 @@ { GIMP_UNDO_GROUP_IMAGE_RESIZE, "GIMP_UNDO_GROUP_IMAGE_RESIZE", "group-image-resize" }, { GIMP_UNDO_GROUP_IMAGE_FLIP, "GIMP_UNDO_GROUP_IMAGE_FLIP", "group-image-flip" }, { GIMP_UNDO_GROUP_IMAGE_ROTATE, "GIMP_UNDO_GROUP_IMAGE_ROTATE", "group-image-rotate" }, + { GIMP_UNDO_GROUP_IMAGE_TRANSFORM, "GIMP_UNDO_GROUP_IMAGE_TRANSFORM", "group-image-transform" }, { GIMP_UNDO_GROUP_IMAGE_CROP, "GIMP_UNDO_GROUP_IMAGE_CROP", "group-image-crop" }, { GIMP_UNDO_GROUP_IMAGE_CONVERT, "GIMP_UNDO_GROUP_IMAGE_CONVERT", "group-image-convert" }, { GIMP_UNDO_GROUP_IMAGE_ITEM_REMOVE, "GIMP_UNDO_GROUP_IMAGE_ITEM_REMOVE", "group-image-item-remove" }, @@ -1103,6 +1133,7 @@ { GIMP_UNDO_GROUP_IMAGE_RESIZE, NC_("undo-type", "Resize image"), NULL }, { GIMP_UNDO_GROUP_IMAGE_FLIP, NC_("undo-type", "Flip image"), NULL }, { GIMP_UNDO_GROUP_IMAGE_ROTATE, NC_("undo-type", "Rotate image"), NULL }, + { GIMP_UNDO_GROUP_IMAGE_TRANSFORM, NC_("undo-type", "Transform image"), NULL }, { GIMP_UNDO_GROUP_IMAGE_CROP, NC_("undo-type", "Crop image"), NULL }, { GIMP_UNDO_GROUP_IMAGE_CONVERT, NC_("undo-type", "Convert image"), NULL }, { GIMP_UNDO_GROUP_IMAGE_ITEM_REMOVE, NC_("undo-type", "Remove item"), NULL }, diff -Nru gimp-2.10.8+zorin2/app/core/core-enums.h gimp-2.10.14+om/app/core/core-enums.h --- gimp-2.10.8+zorin2/app/core/core-enums.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/core-enums.h 2019-10-26 18:49:18.000000000 +0000 @@ -117,7 +117,7 @@ { GIMP_COLOR_PROFILE_POLICY_ASK, /*< desc="Ask what to do" >*/ GIMP_COLOR_PROFILE_POLICY_KEEP, /*< desc="Keep embedded profile" >*/ - GIMP_COLOR_PROFILE_POLICY_CONVERT /*< desc="Convert to preferred RGB color profile" >*/ + GIMP_COLOR_PROFILE_POLICY_CONVERT /*< desc="Convert to built-in sRGB or grayscale profile" >*/ } GimpColorProfilePolicy; @@ -176,6 +176,17 @@ } GimpConvolutionType; +#define GIMP_TYPE_CURVE_POINT_TYPE (gimp_curve_point_type_get_type ()) + +GType gimp_curve_point_type_get_type (void) G_GNUC_CONST; + +typedef enum /*< pdb-skip >*/ +{ + GIMP_CURVE_POINT_SMOOTH, /*< desc="Smooth" >*/ + GIMP_CURVE_POINT_CORNER /*< desc="Corner" >*/ +} GimpCurvePointType; + + #define GIMP_TYPE_CURVE_TYPE (gimp_curve_type_get_type ()) GType gimp_curve_type_get_type (void) G_GNUC_CONST; @@ -459,6 +470,7 @@ GIMP_UNDO_GROUP_IMAGE_RESIZE, /*< desc="Resize image" >*/ GIMP_UNDO_GROUP_IMAGE_FLIP, /*< desc="Flip image" >*/ GIMP_UNDO_GROUP_IMAGE_ROTATE, /*< desc="Rotate image" >*/ + GIMP_UNDO_GROUP_IMAGE_TRANSFORM, /*< desc="Transform image" >*/ GIMP_UNDO_GROUP_IMAGE_CROP, /*< desc="Crop image" >*/ GIMP_UNDO_GROUP_IMAGE_CONVERT, /*< desc="Convert image" >*/ GIMP_UNDO_GROUP_IMAGE_ITEM_REMOVE, /*< desc="Remove item" >*/ diff -Nru gimp-2.10.8+zorin2/app/core/core-types.h gimp-2.10.14+om/app/core/core-types.h --- gimp-2.10.8+zorin2/app/core/core-types.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/core-types.h 2019-10-26 18:49:18.000000000 +0000 @@ -186,7 +186,9 @@ typedef struct _GimpHistogram GimpHistogram; typedef struct _GimpIdTable GimpIdTable; typedef struct _GimpImagefile GimpImagefile; +typedef struct _GimpImageViewable GimpImageViewable; typedef struct _GimpInterpreterDB GimpInterpreterDB; +typedef struct _GimpLineArt GimpLineArt; typedef struct _GimpObjectQueue GimpObjectQueue; typedef struct _GimpParasiteList GimpParasiteList; typedef struct _GimpPdbProgress GimpPdbProgress; @@ -213,6 +215,7 @@ typedef struct _GimpBacktrace GimpBacktrace; typedef struct _GimpBoundSeg GimpBoundSeg; +typedef struct _GimpChunkIterator GimpChunkIterator; typedef struct _GimpCoords GimpCoords; typedef struct _GimpGradientSegment GimpGradientSegment; typedef struct _GimpPaletteEntry GimpPaletteEntry; diff -Nru gimp-2.10.8+zorin2/app/core/gimpasync.c gimp-2.10.14+om/app/core/gimpasync.c --- gimp-2.10.8+zorin2/app/core/gimpasync.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpasync.c 2019-01-03 14:13:22.000000000 +0000 @@ -27,6 +27,7 @@ #include "gimpasync.h" #include "gimpcancelable.h" +#include "gimpmarshal.h" #include "gimpwaitable.h" @@ -60,13 +61,22 @@ /* #define TIME_ASYNC_OPS */ +enum +{ + WAITING, + LAST_SIGNAL +}; + + typedef struct _GimpAsyncCallbackInfo GimpAsyncCallbackInfo; struct _GimpAsyncCallbackInfo { - GimpAsyncCallback callback; - gpointer data; + GimpAsync *async; + GimpAsyncCallback callback; + gpointer data; + gpointer gobject; }; struct _GimpAsyncPrivate @@ -94,23 +104,26 @@ /* local function prototypes */ -static void gimp_async_waitable_iface_init (GimpWaitableInterface *iface); +static void gimp_async_waitable_iface_init (GimpWaitableInterface *iface); static void gimp_async_cancelable_iface_init (GimpCancelableInterface *iface); -static void gimp_async_finalize (GObject *object); +static void gimp_async_finalize (GObject *object); + +static void gimp_async_wait (GimpWaitable *waitable); +static gboolean gimp_async_try_wait (GimpWaitable *waitable); +static gboolean gimp_async_wait_until (GimpWaitable *waitable, + gint64 end_time); -static void gimp_async_wait (GimpWaitable *waitable); -static gboolean gimp_async_try_wait (GimpWaitable *waitable); -static gboolean gimp_async_wait_until (GimpWaitable *waitable, - gint64 end_time); +static void gimp_async_cancel (GimpCancelable *cancelable); -static void gimp_async_cancel (GimpCancelable *cancelable); +static gboolean gimp_async_idle (GimpAsync *async); -static gboolean gimp_async_idle (GimpAsync *async); +static void gimp_async_callback_weak_notify (GimpAsyncCallbackInfo *callback_info, + GObject *gobject); -static void gimp_async_stop (GimpAsync *async); -static void gimp_async_run_callbacks (GimpAsync *async); +static void gimp_async_stop (GimpAsync *async); +static void gimp_async_run_callbacks (GimpAsync *async); G_DEFINE_TYPE_WITH_CODE (GimpAsync, gimp_async, G_TYPE_OBJECT, @@ -122,6 +135,8 @@ #define parent_class gimp_async_parent_class +static guint async_signals[LAST_SIGNAL] = { 0 }; + /* local variables */ @@ -136,6 +151,15 @@ { GObjectClass *object_class = G_OBJECT_CLASS (klass); + async_signals[WAITING] = + g_signal_new ("waiting", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpAsyncClass, waiting), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + object_class->finalize = gimp_async_finalize; } @@ -209,8 +233,13 @@ g_mutex_lock (&async->priv->mutex); - while (! async->priv->stopped) - g_cond_wait (&async->priv->cond, &async->priv->mutex); + if (! async->priv->stopped) + { + g_signal_emit (async, async_signals[WAITING], 0); + + while (! async->priv->stopped) + g_cond_wait (&async->priv->cond, &async->priv->mutex); + } g_mutex_unlock (&async->priv->mutex); @@ -259,14 +288,19 @@ g_mutex_lock (&async->priv->mutex); - while (! async->priv->stopped) + if (! async->priv->stopped) { - if (! g_cond_wait_until (&async->priv->cond, &async->priv->mutex, - end_time)) + g_signal_emit (async, async_signals[WAITING], 0); + + while (! async->priv->stopped) { - g_mutex_unlock (&async->priv->mutex); + if (! g_cond_wait_until (&async->priv->cond, &async->priv->mutex, + end_time)) + { + g_mutex_unlock (&async->priv->mutex); - return FALSE; + return FALSE; + } } } @@ -302,6 +336,33 @@ } static void +gimp_async_callback_weak_notify (GimpAsyncCallbackInfo *callback_info, + GObject *gobject) +{ + GimpAsync *async = callback_info->async; + gboolean unref_async = FALSE; + + g_mutex_lock (&async->priv->mutex); + + g_queue_remove (&async->priv->callbacks, callback_info); + + g_slice_free (GimpAsyncCallbackInfo, callback_info); + + if (g_queue_is_empty (&async->priv->callbacks) && async->priv->idle_id) + { + g_source_remove (async->priv->idle_id); + async->priv->idle_id = 0; + + unref_async = TRUE; + } + + g_mutex_unlock (&async->priv->mutex); + + if (unref_async) + g_object_unref (async); +} + +static void gimp_async_stop (GimpAsync *async) { #ifdef TIME_ASYNC_OPS @@ -348,8 +409,20 @@ while ((callback_info = g_queue_pop_head (&async->priv->callbacks))) { + if (callback_info->gobject) + { + g_object_ref (callback_info->gobject); + + g_object_weak_unref (callback_info->gobject, + (GWeakNotify) gimp_async_callback_weak_notify, + callback_info); + } + callback_info->callback (async, callback_info->data); + if (callback_info->gobject) + g_object_unref (callback_info->gobject); + g_slice_free (GimpAsyncCallbackInfo, callback_info); } @@ -418,7 +491,8 @@ return; } - callback_info = g_slice_new (GimpAsyncCallbackInfo); + callback_info = g_slice_new0 (GimpAsyncCallbackInfo); + callback_info->async = async; callback_info->callback = callback; callback_info->data = data; @@ -427,6 +501,57 @@ g_mutex_unlock (&async->priv->mutex); } +/* same as 'gimp_async_add_callback()', however, takes an additional 'gobject' + * argument, which should be a GObject. + * + * 'gobject' is guaranteed to remain alive for the duration of the callback. + * + * When 'gobject' is destroyed, the callback is automatically removed. + */ +void +gimp_async_add_callback_for_object (GimpAsync *async, + GimpAsyncCallback callback, + gpointer data, + gpointer gobject) +{ + GimpAsyncCallbackInfo *callback_info; + + g_return_if_fail (GIMP_IS_ASYNC (async)); + g_return_if_fail (callback != NULL); + g_return_if_fail (G_IS_OBJECT (gobject)); + + g_mutex_lock (&async->priv->mutex); + + if (async->priv->stopped && g_queue_is_empty (&async->priv->callbacks)) + { + async->priv->synced = TRUE; + + g_mutex_unlock (&async->priv->mutex); + + g_object_ref (gobject); + + callback (async, data); + + g_object_unref (gobject); + + return; + } + + callback_info = g_slice_new0 (GimpAsyncCallbackInfo); + callback_info->async = async; + callback_info->callback = callback; + callback_info->data = data; + callback_info->gobject = gobject; + + g_queue_push_tail (&async->priv->callbacks, callback_info); + + g_object_weak_ref (gobject, + (GWeakNotify) gimp_async_callback_weak_notify, + callback_info); + + g_mutex_unlock (&async->priv->mutex); +} + /* removes all callbacks previously registered through * 'gimp_async_add_callback()', matching 'callback' and 'data', which hasn't * been called yet. @@ -438,7 +563,8 @@ GimpAsyncCallback callback, gpointer data) { - GList *iter; + GList *iter; + gboolean unref_async = FALSE; g_return_if_fail (GIMP_IS_ASYNC (async)); g_return_if_fail (callback != NULL); @@ -455,6 +581,14 @@ if (callback_info->callback == callback && callback_info->data == data) { + if (callback_info->gobject) + { + g_object_weak_unref ( + callback_info->gobject, + (GWeakNotify) gimp_async_callback_weak_notify, + callback_info); + } + g_queue_delete_link (&async->priv->callbacks, iter); g_slice_free (GimpAsyncCallbackInfo, callback_info); @@ -463,7 +597,18 @@ iter = next; } + if (g_queue_is_empty (&async->priv->callbacks) && async->priv->idle_id) + { + g_source_remove (async->priv->idle_id); + async->priv->idle_id = 0; + + unref_async = TRUE; + } + g_mutex_unlock (&async->priv->mutex); + + if (unref_async) + g_object_unref (async); } /* checks if 'async' is in the "stopped" state. diff -Nru gimp-2.10.8+zorin2/app/core/gimpasync.h gimp-2.10.14+om/app/core/gimpasync.h --- gimp-2.10.8+zorin2/app/core/gimpasync.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpasync.h 2019-01-03 14:13:22.000000000 +0000 @@ -47,42 +47,49 @@ struct _GimpAsyncClass { GObjectClass parent_class; -}; - -GType gimp_async_get_type (void) G_GNUC_CONST; + /* signals */ + void (* waiting) (GimpAsync *async); +}; -GimpAsync * gimp_async_new (void); -gboolean gimp_async_is_synced (GimpAsync *async); +GType gimp_async_get_type (void) G_GNUC_CONST; -void gimp_async_add_callback (GimpAsync *async, - GimpAsyncCallback callback, - gpointer data); -void gimp_async_remove_callback (GimpAsync *async, - GimpAsyncCallback callback, - gpointer data); +GimpAsync * gimp_async_new (void); -gboolean gimp_async_is_stopped (GimpAsync *async); +gboolean gimp_async_is_synced (GimpAsync *async); -void gimp_async_finish (GimpAsync *async, - gpointer result); -void gimp_async_finish_full (GimpAsync *async, - gpointer result, - GDestroyNotify result_destroy_func); -gboolean gimp_async_is_finished (GimpAsync *async); -gpointer gimp_async_get_result (GimpAsync *async); +void gimp_async_add_callback (GimpAsync *async, + GimpAsyncCallback callback, + gpointer data); +void gimp_async_add_callback_for_object (GimpAsync *async, + GimpAsyncCallback callback, + gpointer data, + gpointer gobject); +void gimp_async_remove_callback (GimpAsync *async, + GimpAsyncCallback callback, + gpointer data); + +gboolean gimp_async_is_stopped (GimpAsync *async); + +void gimp_async_finish (GimpAsync *async, + gpointer result); +void gimp_async_finish_full (GimpAsync *async, + gpointer result, + GDestroyNotify result_destroy_func); +gboolean gimp_async_is_finished (GimpAsync *async); +gpointer gimp_async_get_result (GimpAsync *async); -void gimp_async_abort (GimpAsync *async); +void gimp_async_abort (GimpAsync *async); -gboolean gimp_async_is_canceled (GimpAsync *async); +gboolean gimp_async_is_canceled (GimpAsync *async); -void gimp_async_cancel_and_wait (GimpAsync *async); +void gimp_async_cancel_and_wait (GimpAsync *async); /* stats */ -gint gimp_async_get_n_running (void); +gint gimp_async_get_n_running (void); #endif /* __GIMP_ASYNC_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpbacktrace-linux.c gimp-2.10.14+om/app/core/gimpbacktrace-linux.c --- gimp-2.10.8+zorin2/app/core/gimpbacktrace-linux.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbacktrace-linux.c 2019-01-03 14:13:22.000000000 +0000 @@ -83,7 +83,6 @@ { GimpBacktraceThread *threads; gint n_threads; - gint n_remaining_threads; }; @@ -113,13 +112,14 @@ static pid_t blacklisted_threads[MAX_N_THREADS]; static gint n_blacklisted_threads; static GimpBacktrace *handler_backtrace; +static gint handler_n_remaining_threads; static gint handler_lock; #ifdef HAVE_LIBBACKTRACE static struct backtrace_state *backtrace_state; #endif -static const gchar *blacklisted_thread_names[] = +static const gchar * const blacklisted_thread_names[] = { "gmain", "threaded-ml" @@ -282,7 +282,7 @@ thread->n_frames = backtrace ((gpointer *) thread->frames, MAX_N_FRAMES); - g_atomic_int_dec_and_test (&curr_backtrace->n_remaining_threads); + g_atomic_int_dec_and_test (&handler_n_remaining_threads); break; } @@ -412,13 +412,13 @@ backtrace = g_slice_new (GimpBacktrace); - backtrace->threads = g_new (GimpBacktraceThread, n_threads); - backtrace->n_threads = n_threads; - backtrace->n_remaining_threads = n_threads; + backtrace->threads = g_new (GimpBacktraceThread, n_threads); + backtrace->n_threads = n_threads; while (! g_atomic_int_compare_and_exchange (&handler_lock, 0, -1)); - g_atomic_pointer_set (&handler_backtrace, backtrace); + g_atomic_pointer_set (&handler_backtrace, backtrace); + g_atomic_int_set (&handler_n_remaining_threads, n_threads); g_atomic_int_set (&handler_lock, 0); @@ -441,7 +441,7 @@ start_time = g_get_monotonic_time (); - while (g_atomic_int_get (&backtrace->n_remaining_threads) > 0) + while (g_atomic_int_get (&handler_n_remaining_threads) > 0) { gint64 time = g_get_monotonic_time (); @@ -458,7 +458,7 @@ g_atomic_int_set (&handler_lock, 0); #if 0 - if (backtrace->n_remaining_threads > 0) + if (handler_n_remaining_threads > 0) { gint j = 0; @@ -500,7 +500,7 @@ void gimp_backtrace_free (GimpBacktrace *backtrace) { - if (! backtrace || backtrace->n_remaining_threads > 0) + if (! backtrace) return; g_free (backtrace->threads); diff -Nru gimp-2.10.8+zorin2/app/core/gimp-batch.c gimp-2.10.14+om/app/core/gimp-batch.c --- gimp-2.10.8+zorin2/app/core/gimp-batch.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-batch.c 2019-10-26 18:49:18.000000000 +0000 @@ -72,8 +72,8 @@ batch_interpreter = BATCH_DEFAULT_EVAL_PROC; if (gimp->be_verbose) - g_printerr (_("No batch interpreter specified, using the default " - "'%s'.\n"), batch_interpreter); + g_printerr ("No batch interpreter specified, using the default " + "'%s'.\n", batch_interpreter); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-boundary.c gimp-2.10.14+om/app/core/gimpbrush-boundary.c --- gimp-2.10.8+zorin2/app/core/gimpbrush-boundary.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-boundary.c 2019-06-12 16:43:38.000000000 +0000 @@ -40,7 +40,7 @@ { const GimpTempBuf *mask; - mask = gimp_brush_transform_mask (brush, NULL, + mask = gimp_brush_transform_mask (brush, scale, aspect_ratio, angle, reflect, hardness); diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush.c gimp-2.10.14+om/app/core/gimpbrush.c --- gimp-2.10.8+zorin2/app/core/gimpbrush.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush.c 2019-06-12 16:43:38.000000000 +0000 @@ -31,6 +31,7 @@ #include "gimpbrush-boundary.h" #include "gimpbrush-load.h" #include "gimpbrush-private.h" +#include "gimpbrush-save.h" #include "gimpbrush-transform.h" #include "gimpbrushcache.h" #include "gimpbrushgenerated.h" @@ -82,6 +83,8 @@ static void gimp_brush_dirty (GimpData *data); static const gchar * gimp_brush_get_extension (GimpData *data); +static void gimp_brush_copy (GimpData *data, + GimpData *src_data); static void gimp_brush_real_begin_use (GimpBrush *brush); static void gimp_brush_real_end_use (GimpBrush *brush); @@ -134,7 +137,9 @@ viewable_class->get_description = gimp_brush_get_description; data_class->dirty = gimp_brush_dirty; + data_class->save = gimp_brush_save; data_class->get_extension = gimp_brush_get_extension; + data_class->copy = gimp_brush_copy; klass->begin_use = gimp_brush_real_begin_use; klass->end_use = gimp_brush_real_end_use; @@ -270,6 +275,7 @@ GimpTempBuf *return_buf = NULL; gint mask_width; gint mask_height; + guchar *mask_data; guchar *mask; guchar *buf; gint x, y; @@ -292,14 +298,14 @@ { GimpBrushGenerated *gen_brush = GIMP_BRUSH_GENERATED (brush); - mask_buf = gimp_brush_transform_mask (brush, NULL, scale, + mask_buf = gimp_brush_transform_mask (brush, scale, (gimp_brush_generated_get_aspect_ratio (gen_brush) - 1.0) * 20.0 / 19.0, gimp_brush_generated_get_angle (gen_brush) / 360.0, FALSE, gimp_brush_generated_get_hardness (gen_brush)); } else - mask_buf = gimp_brush_transform_mask (brush, NULL, scale, + mask_buf = gimp_brush_transform_mask (brush, scale, 0.0, 0.0, FALSE, 1.0); if (! mask_buf) @@ -313,7 +319,7 @@ } if (pixmap_buf) - pixmap_buf = gimp_brush_transform_pixmap (brush, NULL, scale, + pixmap_buf = gimp_brush_transform_pixmap (brush, scale, 0.0, 0.0, FALSE, 1.0); mask_width = gimp_temp_buf_get_width (mask_buf); @@ -325,14 +331,19 @@ return_buf = gimp_temp_buf_new (mask_width, mask_height, babl_format ("R'G'B'A u8")); - gimp_temp_buf_data_clear (return_buf); - mask = gimp_temp_buf_get_data (mask_buf); + mask = mask_data = gimp_temp_buf_lock (mask_buf, babl_format ("Y u8"), + GEGL_ACCESS_READ); buf = gimp_temp_buf_get_data (return_buf); if (pixmap_buf) { - guchar *pixmap = gimp_temp_buf_get_data (pixmap_buf); + guchar *pixmap_data; + guchar *pixmap; + + pixmap = pixmap_data = gimp_temp_buf_lock (pixmap_buf, + babl_format ("R'G'B' u8"), + GEGL_ACCESS_READ); for (y = 0; y < mask_height; y++) { @@ -344,6 +355,8 @@ *buf++ = *mask++; } } + + gimp_temp_buf_unlock (pixmap_buf, pixmap_data); } else { @@ -359,6 +372,8 @@ } } + gimp_temp_buf_unlock (mask_buf, mask_data); + if (scaled) { gimp_temp_buf_unref ((GimpTempBuf *) mask_buf); @@ -408,6 +423,28 @@ } static void +gimp_brush_copy (GimpData *data, + GimpData *src_data) +{ + GimpBrush *brush = GIMP_BRUSH (data); + GimpBrush *src_brush = GIMP_BRUSH (src_data); + + g_clear_pointer (&brush->priv->mask, gimp_temp_buf_unref); + if (src_brush->priv->mask) + brush->priv->mask = gimp_temp_buf_copy (src_brush->priv->mask); + + g_clear_pointer (&brush->priv->pixmap, gimp_temp_buf_unref); + if (src_brush->priv->pixmap) + brush->priv->pixmap = gimp_temp_buf_copy (src_brush->priv->pixmap); + + brush->priv->spacing = src_brush->priv->spacing; + brush->priv->x_axis = src_brush->priv->x_axis; + brush->priv->y_axis = src_brush->priv->y_axis; + + gimp_data_dirty (data); +} + +static void gimp_brush_real_begin_use (GimpBrush *brush) { brush->priv->mask_cache = @@ -596,7 +633,6 @@ const GimpTempBuf * gimp_brush_transform_mask (GimpBrush *brush, - GeglNode *op, gdouble scale, gdouble aspect_ratio, gdouble angle, @@ -616,7 +652,7 @@ &width, &height); mask = gimp_brush_cache_get (brush->priv->mask_cache, - op, width, height, + width, height, scale, aspect_ratio, angle, reflect, hardness); if (! mask) @@ -653,37 +689,9 @@ reflect, effective_hardness); - if (op) - { - GeglNode *graph, *source, *target; - GeglBuffer *buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) mask); - - graph = gegl_node_new (); - source = gegl_node_new_child (graph, - "operation", "gegl:buffer-source", - "buffer", buffer, - NULL); - gegl_node_add_child (graph, op); - target = gegl_node_new_child (graph, - "operation", "gegl:write-buffer", - "buffer", buffer, - NULL); - - gegl_node_link_many (source, op, target, NULL); - gegl_node_blit (target, 1.0, - GEGL_RECTANGLE (0, 0, - gegl_buffer_get_width (buffer), - gegl_buffer_get_height (buffer)), - NULL, NULL, 0, GEGL_BLIT_DEFAULT); - - - g_object_unref (graph); - g_object_unref (buffer); - } - gimp_brush_cache_add (brush->priv->mask_cache, (gpointer) mask, - op, width, height, + width, height, scale, aspect_ratio, angle, reflect, effective_hardness); } @@ -692,7 +700,6 @@ const GimpTempBuf * gimp_brush_transform_pixmap (GimpBrush *brush, - GeglNode *op, gdouble scale, gdouble aspect_ratio, gdouble angle, @@ -713,7 +720,7 @@ &width, &height); pixmap = gimp_brush_cache_get (brush->priv->pixmap_cache, - op, width, height, + width, height, scale, aspect_ratio, angle, reflect, hardness); if (! pixmap) @@ -745,36 +752,9 @@ reflect, effective_hardness); - if (op) - { - GeglNode *graph, *source, *target; - GeglBuffer *buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) pixmap); - - graph = gegl_node_new (); - source = gegl_node_new_child (graph, - "operation", "gegl:buffer-source", - "buffer", buffer, - NULL); - gegl_node_add_child (graph, op); - target = gegl_node_new_child (graph, - "operation", "gegl:write-buffer", - "buffer", buffer, - NULL); - - gegl_node_link_many (source, op, target, NULL); - gegl_node_blit (target, 1.0, - GEGL_RECTANGLE (0, 0, - gegl_buffer_get_width (buffer), - gegl_buffer_get_height (buffer)), - NULL, NULL, 0, GEGL_BLIT_DEFAULT); - - g_object_unref (graph); - g_object_unref (buffer); - } - gimp_brush_cache_add (brush->priv->pixmap_cache, (gpointer) pixmap, - op, width, height, + width, height, scale, aspect_ratio, angle, reflect, effective_hardness); } @@ -803,7 +783,7 @@ width, height); boundary = gimp_brush_cache_get (brush->priv->boundary_cache, - NULL, *width, *height, + *width, *height, scale, aspect_ratio, angle, reflect, hardness); if (! boundary) @@ -826,7 +806,7 @@ if (boundary) gimp_brush_cache_add (brush->priv->boundary_cache, (gpointer) boundary, - NULL, *width, *height, + *width, *height, scale, aspect_ratio, angle, reflect, hardness); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushcache.c gimp-2.10.14+om/app/core/gimpbrushcache.c --- gimp-2.10.8+zorin2/app/core/gimpbrushcache.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushcache.c 2019-06-12 16:43:38.000000000 +0000 @@ -44,16 +44,15 @@ struct _GimpBrushCacheUnit { - gpointer data; + gpointer data; - gint width; - gint height; - gdouble scale; - gdouble aspect_ratio; - gdouble angle; - gboolean reflect; - gdouble hardness; - GeglNode *op; + gint width; + gint height; + gdouble scale; + gdouble aspect_ratio; + gdouble angle; + gboolean reflect; + gdouble hardness; }; @@ -201,7 +200,6 @@ gconstpointer gimp_brush_cache_get (GimpBrushCache *cache, - GeglNode *op, gint width, gint height, gdouble scale, @@ -225,8 +223,7 @@ unit->aspect_ratio == aspect_ratio && unit->angle == angle && unit->reflect == reflect && - unit->hardness == hardness && - unit->op == op) + unit->hardness == hardness) { if (gimp_log_flags & GIMP_LOG_BRUSH_CACHE) g_printerr ("%c", cache->debug_hit); @@ -251,7 +248,6 @@ void gimp_brush_cache_add (GimpBrushCache *cache, gpointer data, - GeglNode *op, gint width, gint height, gdouble scale, @@ -298,7 +294,6 @@ unit->angle = angle; unit->reflect = reflect; unit->hardness = hardness; - unit->op = op; cache->cached_units = g_list_prepend (cache->cached_units, unit); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushcache.h gimp-2.10.14+om/app/core/gimpbrushcache.h --- gimp-2.10.8+zorin2/app/core/gimpbrushcache.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushcache.h 2019-06-12 16:43:38.000000000 +0000 @@ -62,7 +62,6 @@ void gimp_brush_cache_clear (GimpBrushCache *cache); gconstpointer gimp_brush_cache_get (GimpBrushCache *cache, - GeglNode *op, gint width, gint height, gdouble scale, @@ -72,7 +71,6 @@ gdouble hardness); void gimp_brush_cache_add (GimpBrushCache *cache, gpointer data, - GeglNode *op, gint width, gint height, gdouble scale, diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushclipboard.c gimp-2.10.14+om/app/core/gimpbrushclipboard.c --- gimp-2.10.8+zorin2/app/core/gimpbrushclipboard.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushclipboard.c 2019-04-07 11:38:14.000000000 +0000 @@ -57,9 +57,8 @@ guint property_id, GValue *value, GParamSpec *pspec); -#if 0 + static GimpData * gimp_brush_clipboard_duplicate (GimpData *data); -#endif static void gimp_brush_clipboard_changed (Gimp *gimp, GimpBrush *brush); @@ -74,17 +73,13 @@ gimp_brush_clipboard_class_init (GimpBrushClipboardClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); -#if 0 GimpDataClass *data_class = GIMP_DATA_CLASS (klass); -#endif object_class->constructed = gimp_brush_clipboard_constructed; object_class->set_property = gimp_brush_clipboard_set_property; object_class->get_property = gimp_brush_clipboard_get_property; -#if 0 data_class->duplicate = gimp_brush_clipboard_duplicate; -#endif g_object_class_install_property (object_class, PROP_GIMP, g_param_spec_object ("gimp", NULL, NULL, @@ -168,15 +163,15 @@ } } -#if 0 static GimpData * gimp_brush_clipboard_duplicate (GimpData *data) { - GimpBrushClipboard *brush = GIMP_BRUSH_CLIPBOARD (data); + GimpData *new = g_object_new (GIMP_TYPE_BRUSH, NULL); + + gimp_data_copy (new, data); - return gimp_brush_clipboard_new (brush->gimp); + return new; } -#endif GimpData * gimp_brush_clipboard_new (Gimp *gimp, diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushgenerated.c gimp-2.10.14+om/app/core/gimpbrushgenerated.c --- gimp-2.10.8+zorin2/app/core/gimpbrushgenerated.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushgenerated.c 2019-04-07 11:38:14.000000000 +0000 @@ -405,11 +405,11 @@ } /* set up lookup table */ -static guchar * +static gfloat * gimp_brush_generated_calc_lut (gdouble radius, gdouble hardness) { - guchar *lookup; + gfloat *lookup; gint length; gint x; gdouble d; @@ -419,7 +419,7 @@ length = OVERSAMPLING * ceil (1 + sqrt (2 * SQR (ceil (radius + 1.0)))); - lookup = g_malloc (length); + lookup = gegl_scratch_new (gfloat, length); sum = 0.0; if ((1.0 - hardness) < 0.0000004) @@ -449,12 +449,12 @@ buffer[x % OVERSAMPLING] = gauss (pow (d / radius, exponent)); sum += buffer[x % OVERSAMPLING]; - lookup[x++] = RINT (sum * (255.0 / OVERSAMPLING)); + lookup[x++] = sum / OVERSAMPLING; } while (x < length) { - lookup[x++] = 0; + lookup[x++] = 0.0f; } return lookup; @@ -472,9 +472,9 @@ GimpVector2 *xaxis, GimpVector2 *yaxis) { - guchar *centerp; - guchar *lookup; - guchar a; + gfloat *centerp; + gfloat *lookup; + gfloat a; gint x, y; gdouble c, s, cs, ss; GimpVector2 x_axis; @@ -497,12 +497,12 @@ &s, &c, &x_axis, &y_axis); mask = gimp_temp_buf_new (width, height, - babl_format ("Y u8")); + babl_format ("Y float")); half_width = width / 2; half_height = height / 2; - centerp = gimp_temp_buf_get_data (mask) + + centerp = (gfloat *) gimp_temp_buf_get_data (mask) + half_height * width + half_width; lookup = gimp_brush_generated_calc_lut (radius, hardness); @@ -553,7 +553,7 @@ if (d < radius + 1) a = lookup[(gint) RINT (d * OVERSAMPLING)]; else - a = 0; + a = 0.0f; centerp[y * width + x] = a; @@ -562,7 +562,7 @@ } } - g_free (lookup); + gegl_scratch_free (lookup); if (xaxis) *xaxis = x_axis; diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushgenerated-save.c gimp-2.10.14+om/app/core/gimpbrushgenerated-save.c --- gimp-2.10.8+zorin2/app/core/gimpbrushgenerated-save.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushgenerated-save.c 2019-10-26 18:49:18.000000000 +0000 @@ -76,13 +76,13 @@ /* write brush spacing */ g_string_append_printf (string, "%s\n", - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - gimp_brush_get_spacing (GIMP_BRUSH (brush)))); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + gimp_brush_get_spacing (GIMP_BRUSH (brush)))); /* write brush radius */ g_string_append_printf (string, "%s\n", - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - brush->radius)); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + brush->radius)); if (have_shape) { @@ -92,18 +92,18 @@ /* write brush hardness */ g_string_append_printf (string, "%s\n", - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - brush->hardness)); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + brush->hardness)); /* write brush aspect_ratio */ g_string_append_printf (string, "%s\n", - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - brush->aspect_ratio)); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + brush->aspect_ratio)); /* write brush angle */ g_string_append_printf (string, "%s\n", - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - brush->angle)); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + brush->angle)); if (! g_output_stream_write_all (output, string->str, string->len, NULL, NULL, error)) diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush.h gimp-2.10.14+om/app/core/gimpbrush.h --- gimp-2.10.8+zorin2/app/core/gimpbrush.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush.h 2019-06-12 16:43:38.000000000 +0000 @@ -113,14 +113,12 @@ gint *width, gint *height); const GimpTempBuf * gimp_brush_transform_mask (GimpBrush *brush, - GeglNode *op, gdouble scale, gdouble aspect_ratio, gdouble angle, gboolean reflect, gdouble hardness); const GimpTempBuf * gimp_brush_transform_pixmap (GimpBrush *brush, - GeglNode *op, gdouble scale, gdouble aspect_ratio, gdouble angle, diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-header.h gimp-2.10.14+om/app/core/gimpbrush-header.h --- gimp-2.10.8+zorin2/app/core/gimpbrush-header.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-header.h 2019-06-12 16:43:38.000000000 +0000 @@ -19,11 +19,10 @@ #define __GIMP_BRUSH_HEADER_H__ -#define GIMP_BRUSH_FILE_VERSION 2 -#define GIMP_BRUSH_MAGIC (('G' << 24) + ('I' << 16) + \ - ('M' << 8) + ('P' << 0)) -#define GIMP_BRUSH_MAX_SIZE 10000 /* Max size in either dimension in px */ -#define GIMP_BRUSH_MAX_NAME 256 /* Max length of the brush's name */ +#define GIMP_BRUSH_MAGIC (('G' << 24) + ('I' << 16) + \ + ('M' << 8) + ('P' << 0)) +#define GIMP_BRUSH_MAX_SIZE 10000 /* Max size in either dimension in px */ +#define GIMP_BRUSH_MAX_NAME 256 /* Max length of the brush's name */ /* All field entries are MSB */ @@ -36,14 +35,15 @@ guint32 version; /* brush file version # */ guint32 width; /* width of brush */ guint32 height; /* height of brush */ - guint32 bytes; /* depth of brush in bytes--always 1 */ + guint32 bytes; /* depth of brush in bytes */ guint32 magic_number; /* GIMP brush magic number */ guint32 spacing; /* brush spacing */ }; -/* In a brush file, next comes the brush name, null-terminated. After that - * comes the brush data--width * height * bytes bytes of it... +/* In a brush file, next comes the brush name, null-terminated. + * After that comes the brush data -- width * height * bytes bytes of + * it... */ -#endif /* __GIMP_BRUSH_HEADER_H__ */ +#endif /* __GIMP_BRUSH_HEADER_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-load.c gimp-2.10.14+om/app/core/gimpbrush-load.c --- gimp-2.10.8+zorin2/app/core/gimpbrush-load.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-load.c 2019-06-12 16:43:38.000000000 +0000 @@ -30,6 +30,7 @@ #include "gimpbrush-header.h" #include "gimpbrush-load.h" #include "gimpbrush-private.h" +#include "gimppattern-header.h" #include "gimptempbuf.h" #include "gimp-intl.h" @@ -138,7 +139,6 @@ gsize bn_size; GimpBrushHeader header; gchar *name = NULL; - guchar *pixmap; guchar *mask; gsize bytes_read; gssize i, size; @@ -189,7 +189,8 @@ } if (header.width > GIMP_BRUSH_MAX_SIZE || - header.height > GIMP_BRUSH_MAX_SIZE) + header.height > GIMP_BRUSH_MAX_SIZE || + G_MAXSIZE / header.width / header.height / MAX (4, header.bytes) < 1) { g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ, _("Fatal parse error in brush file: %dx%d over max size."), @@ -293,8 +294,69 @@ { case 1: success = (g_input_stream_read_all (input, mask, size, - &bytes_read, NULL, error) && + &bytes_read, NULL, error) && bytes_read == size); + + /* For backwards-compatibility, check if a pattern follows. + * The obsolete .gpb format did it this way. + */ + if (success) + { + GimpPatternHeader ph; + goffset rewind; + + rewind = g_seekable_tell (G_SEEKABLE (input)); + + if (g_input_stream_read_all (input, &ph, sizeof (GimpPatternHeader), + &bytes_read, NULL, NULL) && + bytes_read == sizeof (GimpPatternHeader)) + { + /* rearrange the bytes in each unsigned int */ + ph.header_size = g_ntohl (ph.header_size); + ph.version = g_ntohl (ph.version); + ph.width = g_ntohl (ph.width); + ph.height = g_ntohl (ph.height); + ph.bytes = g_ntohl (ph.bytes); + ph.magic_number = g_ntohl (ph.magic_number); + + if (ph.magic_number == GIMP_PATTERN_MAGIC && + ph.version == 1 && + ph.header_size > sizeof (GimpPatternHeader) && + ph.bytes == 3 && + ph.width == header.width && + ph.height == header.height && + g_input_stream_skip (input, + ph.header_size - + sizeof (GimpPatternHeader), + NULL, NULL) == + ph.header_size - sizeof (GimpPatternHeader)) + { + guchar *pixmap; + gssize pixmap_size; + + brush->priv->pixmap = + gimp_temp_buf_new (header.width, header.height, + babl_format ("R'G'B' u8")); + + pixmap = gimp_temp_buf_get_data (brush->priv->pixmap); + + pixmap_size = gimp_temp_buf_get_data_size (brush->priv->pixmap); + + success = (g_input_stream_read_all (input, pixmap, + pixmap_size, + &bytes_read, NULL, + error) && + bytes_read == pixmap_size); + } + else + { + /* seek back if pattern wasn't found */ + success = g_seekable_seek (G_SEEKABLE (input), + rewind, G_SEEK_SET, + NULL, error); + } + } + } break; case 2: /* cinepaint brush, 16 bit floats */ @@ -338,26 +400,10 @@ } break; - case 3: - /* The obsolete .gbp format had a 3-byte pattern following a - * 1-byte brush, when embedded in a brush pipe, the current code - * tries to load that pattern as a brush, and encounters the '3' - * in the header. - */ - g_object_unref (brush); - g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ, - _("Fatal parse error in brush file:\n" - "Unsupported brush depth %d\n" - "GIMP brushes must be GRAY or RGBA.\n" - "This might be an obsolete GIMP brush file, try " - "loading it as image and save it again."), - header.bytes); - return NULL; - break; - case 4: { - guchar buf[8 * 1024]; + guchar *pixmap; + guchar buf[8 * 1024]; brush->priv->pixmap = gimp_temp_buf_new (header.width, header.height, babl_format ("R'G'B' u8")); diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushpipe.c gimp-2.10.14+om/app/core/gimpbrushpipe.c --- gimp-2.10.8+zorin2/app/core/gimpbrushpipe.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushpipe.c 2019-06-12 16:43:38.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include "libgimpbase/gimpparasiteio.h" #include "libgimpmath/gimpmath.h" #include "core-types.h" @@ -28,28 +29,34 @@ #include "gimpbrush-private.h" #include "gimpbrushpipe.h" #include "gimpbrushpipe-load.h" +#include "gimpbrushpipe-save.h" +#include "gimptempbuf.h" -static void gimp_brush_pipe_finalize (GObject *object); +static void gimp_brush_pipe_finalize (GObject *object); -static gint64 gimp_brush_pipe_get_memsize (GimpObject *object, - gint64 *gui_size); +static gint64 gimp_brush_pipe_get_memsize (GimpObject *object, + gint64 *gui_size); -static gboolean gimp_brush_pipe_get_popup_size (GimpViewable *viewable, - gint width, - gint height, - gboolean dot_for_dot, - gint *popup_width, - gint *popup_height); - -static void gimp_brush_pipe_begin_use (GimpBrush *brush); -static void gimp_brush_pipe_end_use (GimpBrush *brush); -static GimpBrush * gimp_brush_pipe_select_brush (GimpBrush *brush, - const GimpCoords *last_coords, - const GimpCoords *current_coords); -static gboolean gimp_brush_pipe_want_null_motion (GimpBrush *brush, - const GimpCoords *last_coords, - const GimpCoords *current_coords); +static gboolean gimp_brush_pipe_get_popup_size (GimpViewable *viewable, + gint width, + gint height, + gboolean dot_for_dot, + gint *popup_width, + gint *popup_height); + +static const gchar * gimp_brush_pipe_get_extension (GimpData *data); +static void gimp_brush_pipe_copy (GimpData *data, + GimpData *src_data); + +static void gimp_brush_pipe_begin_use (GimpBrush *brush); +static void gimp_brush_pipe_end_use (GimpBrush *brush); +static GimpBrush * gimp_brush_pipe_select_brush (GimpBrush *brush, + const GimpCoords *last_coords, + const GimpCoords *current_coords); +static gboolean gimp_brush_pipe_want_null_motion (GimpBrush *brush, + const GimpCoords *last_coords, + const GimpCoords *current_coords); G_DEFINE_TYPE (GimpBrushPipe, gimp_brush_pipe, GIMP_TYPE_BRUSH); @@ -63,6 +70,7 @@ GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); + GimpDataClass *data_class = GIMP_DATA_CLASS (klass); GimpBrushClass *brush_class = GIMP_BRUSH_CLASS (klass); object_class->finalize = gimp_brush_pipe_finalize; @@ -71,6 +79,10 @@ viewable_class->get_popup_size = gimp_brush_pipe_get_popup_size; + data_class->save = gimp_brush_pipe_save; + data_class->get_extension = gimp_brush_pipe_get_extension; + data_class->copy = gimp_brush_pipe_copy; + brush_class->begin_use = gimp_brush_pipe_begin_use; brush_class->end_use = gimp_brush_pipe_end_use; brush_class->select_brush = gimp_brush_pipe_select_brush; @@ -95,16 +107,11 @@ { GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (object); - if (pipe->rank) - { - g_free (pipe->rank); - pipe->rank = NULL; - } - if (pipe->stride) - { - g_free (pipe->stride); - pipe->stride = NULL; - } + g_clear_pointer (&pipe->rank, g_free); + g_clear_pointer (&pipe->stride, g_free); + g_clear_pointer (&pipe->select, g_free); + g_clear_pointer (&pipe->index, g_free); + g_clear_pointer (&pipe->params, g_free); if (pipe->brushes) { @@ -114,19 +121,7 @@ if (pipe->brushes[i]) g_object_unref (pipe->brushes[i]); - g_free (pipe->brushes); - pipe->brushes = NULL; - } - - if (pipe->select) - { - g_free (pipe->select); - pipe->select = NULL; - } - if (pipe->index) - { - g_free (pipe->index); - pipe->index = NULL; + g_clear_pointer (&pipe->brushes, g_free); } GIMP_BRUSH (pipe)->priv->mask = NULL; @@ -166,6 +161,69 @@ return gimp_viewable_get_size (viewable, popup_width, popup_height); } +static const gchar * +gimp_brush_pipe_get_extension (GimpData *data) +{ + return GIMP_BRUSH_PIPE_FILE_EXTENSION; +} + +static void +gimp_brush_pipe_copy (GimpData *data, + GimpData *src_data) +{ + GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (data); + GimpBrushPipe *src_pipe = GIMP_BRUSH_PIPE (src_data); + gint i; + + pipe->dimension = src_pipe->dimension; + + g_clear_pointer (&pipe->rank, g_free); + pipe->rank = g_memdup (src_pipe->rank, + pipe->dimension * sizeof (gint)); + + g_clear_pointer (&pipe->stride, g_free); + pipe->stride = g_memdup (src_pipe->stride, + pipe->dimension * sizeof (gint)); + + g_clear_pointer (&pipe->select, g_free); + pipe->select = g_memdup (src_pipe->select, + pipe->dimension * sizeof (PipeSelectModes)); + + g_clear_pointer (&pipe->index, g_free); + pipe->index = g_memdup (src_pipe->index, + pipe->dimension * sizeof (gint)); + + for (i = 0; i < pipe->n_brushes; i++) + if (pipe->brushes[i]) + g_object_unref (pipe->brushes[i]); + g_clear_pointer (&pipe->brushes, g_free); + + pipe->n_brushes = src_pipe->n_brushes; + + pipe->brushes = g_new0 (GimpBrush *, pipe->n_brushes); + for (i = 0; i < pipe->n_brushes; i++) + if (src_pipe->brushes[i]) + { + pipe->brushes[i] = + GIMP_BRUSH (gimp_data_duplicate (GIMP_DATA (src_pipe->brushes[i]))); + gimp_object_set_name (GIMP_OBJECT (pipe->brushes[i]), + gimp_object_get_name (src_pipe->brushes[i])); + } + + g_clear_pointer (&pipe->params, g_free); + pipe->params = g_strdup (src_pipe->params); + + pipe->current = pipe->brushes[0]; + + GIMP_BRUSH (pipe)->priv->spacing = pipe->current->priv->spacing; + GIMP_BRUSH (pipe)->priv->x_axis = pipe->current->priv->x_axis; + GIMP_BRUSH (pipe)->priv->y_axis = pipe->current->priv->y_axis; + GIMP_BRUSH (pipe)->priv->mask = pipe->current->priv->mask; + GIMP_BRUSH (pipe)->priv->pixmap = pipe->current->priv->pixmap; + + gimp_data_dirty (data); +} + static void gimp_brush_pipe_begin_use (GimpBrush *brush) { @@ -275,3 +333,88 @@ return TRUE; } + + +/* public functions */ + +gboolean +gimp_brush_pipe_set_params (GimpBrushPipe *pipe, + const gchar *paramstring) +{ + gint totalcells; + gint i; + + g_return_val_if_fail (GIMP_IS_BRUSH_PIPE (pipe), FALSE); + g_return_val_if_fail (pipe->dimension == 0, FALSE); /* only on a new pipe! */ + + if (paramstring && *paramstring) + { + GimpPixPipeParams params; + + gimp_pixpipe_params_init (¶ms); + gimp_pixpipe_params_parse (paramstring, ¶ms); + + pipe->dimension = params.dim; + pipe->rank = g_new0 (gint, pipe->dimension); + pipe->select = g_new0 (PipeSelectModes, pipe->dimension); + pipe->index = g_new0 (gint, pipe->dimension); + /* placement is not used at all ?? */ + + for (i = 0; i < pipe->dimension; i++) + { + pipe->rank[i] = MAX (1, params.rank[i]); + + if (strcmp (params.selection[i], "incremental") == 0) + pipe->select[i] = PIPE_SELECT_INCREMENTAL; + else if (strcmp (params.selection[i], "angular") == 0) + pipe->select[i] = PIPE_SELECT_ANGULAR; + else if (strcmp (params.selection[i], "velocity") == 0) + pipe->select[i] = PIPE_SELECT_VELOCITY; + else if (strcmp (params.selection[i], "random") == 0) + pipe->select[i] = PIPE_SELECT_RANDOM; + else if (strcmp (params.selection[i], "pressure") == 0) + pipe->select[i] = PIPE_SELECT_PRESSURE; + else if (strcmp (params.selection[i], "xtilt") == 0) + pipe->select[i] = PIPE_SELECT_TILT_X; + else if (strcmp (params.selection[i], "ytilt") == 0) + pipe->select[i] = PIPE_SELECT_TILT_Y; + else + pipe->select[i] = PIPE_SELECT_CONSTANT; + + pipe->index[i] = 0; + } + + gimp_pixpipe_params_free (¶ms); + + pipe->params = g_strdup (paramstring); + } + else + { + pipe->dimension = 1; + pipe->rank = g_new (gint, 1); + pipe->rank[0] = pipe->n_brushes; + pipe->select = g_new (PipeSelectModes, 1); + pipe->select[0] = PIPE_SELECT_INCREMENTAL; + pipe->index = g_new (gint, 1); + pipe->index[0] = 0; + } + + totalcells = 1; /* Not all necessarily present, maybe */ + for (i = 0; i < pipe->dimension; i++) + totalcells *= pipe->rank[i]; + + pipe->stride = g_new0 (gint, pipe->dimension); + + for (i = 0; i < pipe->dimension; i++) + { + if (i == 0) + pipe->stride[i] = totalcells / pipe->rank[i]; + else + pipe->stride[i] = pipe->stride[i-1] / pipe->rank[i]; + } + + if (pipe->stride[pipe->dimension - 1] != 1) + return FALSE; + + return TRUE; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushpipe.h gimp-2.10.14+om/app/core/gimpbrushpipe.h --- gimp-2.10.8+zorin2/app/core/gimpbrushpipe.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushpipe.h 2019-04-07 11:38:14.000000000 +0000 @@ -61,6 +61,8 @@ * ranks in some odd special case */ GimpBrush **brushes; GimpBrush *current; /* Currently selected brush */ + + gchar *params; /* For pipe <-> image conversion */ }; struct _GimpBrushPipeClass @@ -69,7 +71,10 @@ }; -GType gimp_brush_pipe_get_type (void) G_GNUC_CONST; +GType gimp_brush_pipe_get_type (void) G_GNUC_CONST; + +gboolean gimp_brush_pipe_set_params (GimpBrushPipe *pipe, + const gchar *paramstring); #endif /* __GIMP_BRUSH_PIPE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushpipe-load.c gimp-2.10.14+om/app/core/gimpbrushpipe-load.c --- gimp-2.10.8+zorin2/app/core/gimpbrushpipe-load.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushpipe-load.c 2019-04-07 11:38:14.000000000 +0000 @@ -21,10 +21,8 @@ #include #include -#include #include "libgimpbase/gimpbase.h" -#include "libgimpbase/gimpparasiteio.h" #include "core-types.h" @@ -42,14 +40,12 @@ GInputStream *input, GError **error) { - GimpBrushPipe *pipe = NULL; - gint i; - gint num_of_brushes = 0; - gint totalcells; - gchar *paramstring; - GString *buffer; - gchar c; - gsize bytes_read; + GimpBrushPipe *pipe = NULL; + gint n_brushes = 0; + GString *buffer; + gchar *paramstring; + gchar c; + gsize bytes_read; g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL); @@ -105,10 +101,10 @@ if (buffer->len > 0 && buffer->len < 1024) { - num_of_brushes = strtol (buffer->str, ¶mstring, 10); + n_brushes = strtol (buffer->str, ¶mstring, 10); } - if (num_of_brushes < 1) + if (n_brushes < 1) { g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ, _("Fatal parse error in brush file '%s': " @@ -122,91 +118,37 @@ while (*paramstring && g_ascii_isspace (*paramstring)) paramstring++; - if (*paramstring) - { - GimpPixPipeParams params; - - gimp_pixpipe_params_init (¶ms); - gimp_pixpipe_params_parse (paramstring, ¶ms); - - pipe->dimension = params.dim; - pipe->rank = g_new0 (gint, pipe->dimension); - pipe->select = g_new0 (PipeSelectModes, pipe->dimension); - pipe->index = g_new0 (gint, pipe->dimension); - /* placement is not used at all ?? */ - - for (i = 0; i < pipe->dimension; i++) - { - pipe->rank[i] = MAX (1, params.rank[i]); - if (strcmp (params.selection[i], "incremental") == 0) - pipe->select[i] = PIPE_SELECT_INCREMENTAL; - else if (strcmp (params.selection[i], "angular") == 0) - pipe->select[i] = PIPE_SELECT_ANGULAR; - else if (strcmp (params.selection[i], "velocity") == 0) - pipe->select[i] = PIPE_SELECT_VELOCITY; - else if (strcmp (params.selection[i], "random") == 0) - pipe->select[i] = PIPE_SELECT_RANDOM; - else if (strcmp (params.selection[i], "pressure") == 0) - pipe->select[i] = PIPE_SELECT_PRESSURE; - else if (strcmp (params.selection[i], "xtilt") == 0) - pipe->select[i] = PIPE_SELECT_TILT_X; - else if (strcmp (params.selection[i], "ytilt") == 0) - pipe->select[i] = PIPE_SELECT_TILT_Y; - else - pipe->select[i] = PIPE_SELECT_CONSTANT; - pipe->index[i] = 0; - } - - gimp_pixpipe_params_free (¶ms); - } - else - { - pipe->dimension = 1; - pipe->rank = g_new (gint, 1); - pipe->rank[0] = num_of_brushes; - pipe->select = g_new (PipeSelectModes, 1); - pipe->select[0] = PIPE_SELECT_INCREMENTAL; - pipe->index = g_new (gint, 1); - pipe->index[0] = 0; - } - - g_string_free (buffer, TRUE); - - totalcells = 1; /* Not all necessarily present, maybe */ - for (i = 0; i < pipe->dimension; i++) - totalcells *= pipe->rank[i]; - pipe->stride = g_new0 (gint, pipe->dimension); - for (i = 0; i < pipe->dimension; i++) - { - if (i == 0) - pipe->stride[i] = totalcells / pipe->rank[i]; - else - pipe->stride[i] = pipe->stride[i-1] / pipe->rank[i]; - } - g_return_val_if_fail (pipe->stride[pipe->dimension-1] == 1, NULL); + pipe->brushes = g_new0 (GimpBrush *, n_brushes); - pipe->brushes = g_new0 (GimpBrush *, num_of_brushes); - - while (pipe->n_brushes < num_of_brushes) + while (pipe->n_brushes < n_brushes) { pipe->brushes[pipe->n_brushes] = gimp_brush_load_brush (context, file, input, error); - if (pipe->brushes[pipe->n_brushes]) - { - gimp_object_set_name (GIMP_OBJECT (pipe->brushes[pipe->n_brushes]), - NULL); - } - else + if (! pipe->brushes[pipe->n_brushes]) { g_object_unref (pipe); + g_string_free (buffer, TRUE); return NULL; } pipe->n_brushes++; } + if (! gimp_brush_pipe_set_params (pipe, paramstring)) + { + g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ, + _("Fatal parse error in brush file '%s': " + "Inconsistent parameters."), + gimp_file_get_utf8_name (file)); + g_object_unref (pipe); + g_string_free (buffer, TRUE); + return NULL; + } + + g_string_free (buffer, TRUE); + /* Current brush is the first one. */ pipe->current = pipe->brushes[0]; diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushpipe-save.c gimp-2.10.14+om/app/core/gimpbrushpipe-save.c --- gimp-2.10.8+zorin2/app/core/gimpbrushpipe-save.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushpipe-save.c 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,59 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "gimpbrushpipe.h" +#include "gimpbrushpipe-save.h" + + +gboolean +gimp_brush_pipe_save (GimpData *data, + GOutputStream *output, + GError **error) +{ + GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (data); + const gchar *name; + gint i; + + name = gimp_object_get_name (pipe); + + if (! g_output_stream_printf (output, NULL, NULL, error, + "%s\n%d %s\n", + name, pipe->n_brushes, pipe->params)) + { + return FALSE; + } + + for (i = 0; i < pipe->n_brushes; i++) + { + GimpBrush *brush = pipe->brushes[i]; + + if (brush && + ! GIMP_DATA_GET_CLASS (brush)->save (GIMP_DATA (brush), + output, error)) + { + return FALSE; + } + } + + return TRUE; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrushpipe-save.h gimp-2.10.14+om/app/core/gimpbrushpipe-save.h --- gimp-2.10.8+zorin2/app/core/gimpbrushpipe-save.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrushpipe-save.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,28 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_BRUSH_PIPE_SAVE_H__ +#define __GIMP_BRUSH_PIPE_SAVE_H__ + + +/* don't call this function directly, use gimp_data_save() instead */ +gboolean gimp_brush_pipe_save (GimpData *data, + GOutputStream *output, + GError **error); + + +#endif /* __GIMP_BRUSH_PIPE_SAVE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-save.c gimp-2.10.14+om/app/core/gimpbrush-save.c --- gimp-2.10.8+zorin2/app/core/gimpbrush-save.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-save.c 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,107 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "gimpbrush.h" +#include "gimpbrush-header.h" +#include "gimpbrush-save.h" +#include "gimptempbuf.h" + + +gboolean +gimp_brush_save (GimpData *data, + GOutputStream *output, + GError **error) +{ + GimpBrush *brush = GIMP_BRUSH (data); + GimpTempBuf *mask = gimp_brush_get_mask (brush); + GimpTempBuf *pixmap = gimp_brush_get_pixmap (brush); + GimpBrushHeader header; + const gchar *name; + gint width; + gint height; + + name = gimp_object_get_name (brush); + width = gimp_temp_buf_get_width (mask); + height = gimp_temp_buf_get_height (mask); + + header.header_size = g_htonl (sizeof (GimpBrushHeader) + + strlen (name) + 1); + header.version = g_htonl (2); + header.width = g_htonl (width); + header.height = g_htonl (height); + header.bytes = g_htonl (pixmap ? 4 : 1); + header.magic_number = g_htonl (GIMP_BRUSH_MAGIC); + header.spacing = g_htonl (gimp_brush_get_spacing (brush)); + + if (! g_output_stream_write_all (output, &header, sizeof (header), + NULL, NULL, error)) + { + return FALSE; + } + + if (! g_output_stream_write_all (output, name, strlen (name) + 1, + NULL, NULL, error)) + { + return FALSE; + } + + if (pixmap) + { + gsize size = width * height * 4; + guchar *data = g_malloc (size); + guchar *p = gimp_temp_buf_get_data (pixmap); + guchar *m = gimp_temp_buf_get_data (mask); + guchar *d = data; + gint i; + + for (i = 0; i < width * height; i++) + { + *d++ = *p++; + *d++ = *p++; + *d++ = *p++; + *d++ = *m++; + } + + if (! g_output_stream_write_all (output, data, size, + NULL, NULL, error)) + { + g_free (data); + + return FALSE; + } + + g_free (data); + } + else + { + if (! g_output_stream_write_all (output, + gimp_temp_buf_get_data (mask), + gimp_temp_buf_get_data_size (mask), + NULL, NULL, error)) + { + return FALSE; + } + } + + return TRUE; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-save.h gimp-2.10.14+om/app/core/gimpbrush-save.h --- gimp-2.10.8+zorin2/app/core/gimpbrush-save.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-save.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,28 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_BRUSH_SAVE_H__ +#define __GIMP_BRUSH_SAVE_H__ + + +/* don't call this function directly, use gimp_data_save() instead */ +gboolean gimp_brush_save (GimpData *data, + GOutputStream *output, + GError **error); + + +#endif /* __GIMP_BRUSH_SAVE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpbrush-transform.cc gimp-2.10.14+om/app/core/gimpbrush-transform.cc --- gimp-2.10.8+zorin2/app/core/gimpbrush-transform.cc 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbrush-transform.cc 2019-01-03 14:13:22.000000000 +0000 @@ -33,14 +33,13 @@ #include "gegl/gimp-gegl-loops.h" -#include "gimp-parallel.h" #include "gimpbrush.h" #include "gimpbrush-transform.h" #include "gimptempbuf.h" -#define MIN_PARALLEL_SUB_SIZE 64 -#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE) +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) /* local function prototypes */ @@ -256,9 +255,9 @@ src_walk_vx_i = (gint) ((src_tl_to_bl_delta_x / dest_height) * int_multiple); src_walk_vy_i = (gint) ((src_tl_to_bl_delta_y / dest_height) * int_multiple); - gimp_parallel_distribute_area (GEGL_RECTANGLE (0, 0, dest_width, dest_height), - MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *area) + gegl_parallel_distribute_area ( + GEGL_RECTANGLE (0, 0, dest_width, dest_height), PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) { guchar *dest; gint src_space_cur_pos_x; @@ -556,9 +555,9 @@ src_walk_vx_i = (gint) ((src_tl_to_bl_delta_x / dest_height) * int_multiple); src_walk_vy_i = (gint) ((src_tl_to_bl_delta_y / dest_height) * int_multiple); - gimp_parallel_distribute_area (GEGL_RECTANGLE (0, 0, dest_width, dest_height), - MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *area) + gegl_parallel_distribute_area ( + GEGL_RECTANGLE (0, 0, dest_width, dest_height), PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) { guchar *dest; gint src_space_cur_pos_x; @@ -808,8 +807,9 @@ sums = g_new (Sums, width * height * components); - gimp_parallel_distribute_range (height, MIN_PARALLEL_SUB_SIZE, - [=] (gint y0, gint height) + gegl_parallel_distribute_range ( + height, PIXELS_PER_THREAD / width, + [=] (gint y0, gint height) { gint x; gint y; @@ -885,8 +885,9 @@ } }); - gimp_parallel_distribute_range (width, MIN_PARALLEL_SUB_SIZE, - [=] (gint x0, gint width) + gegl_parallel_distribute_range ( + width, PIXELS_PER_THREAD / height, + [=] (gint x0, gint width) { gint x; gint y; diff -Nru gimp-2.10.8+zorin2/app/core/gimpbuffer.c gimp-2.10.14+om/app/core/gimpbuffer.c --- gimp-2.10.8+zorin2/app/core/gimpbuffer.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpbuffer.c 2019-10-26 18:49:18.000000000 +0000 @@ -28,6 +28,7 @@ #include "gegl/gimp-babl.h" #include "gegl/gimp-gegl-loops.h" +#include "gegl/gimp-gegl-utils.h" #include "gimp-memsize.h" #include "gimpbuffer.h" @@ -379,7 +380,7 @@ NULL); if (copy_pixels) - gimp_buffer->buffer = gegl_buffer_dup (buffer); + gimp_buffer->buffer = gimp_gegl_buffer_dup (buffer); else gimp_buffer->buffer = g_object_ref (buffer); diff -Nru gimp-2.10.8+zorin2/app/core/gimp.c gimp-2.10.14+om/app/core/gimp.c --- gimp-2.10.8+zorin2/app/core/gimp.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp.c 2019-06-12 16:43:38.000000000 +0000 @@ -41,6 +41,7 @@ #include "paint/gimp-paint.h" #include "xcf/xcf.h" +#include "file-data/file-data.h" #include "gimp.h" #include "gimp-contexts.h" @@ -282,6 +283,7 @@ gimp->pdb = gimp_pdb_new (gimp); xcf_init (gimp); + file_data_init (gimp); /* create user and default context */ gimp_contexts_init (gimp); @@ -383,6 +385,7 @@ g_clear_object (&gimp->tool_info_list); } + file_data_exit (gimp); xcf_exit (gimp); g_clear_object (&gimp->pdb); @@ -978,7 +981,7 @@ GIMP_PARASITE_PERSISTENT, strlen (comment) + 1, comment); - gimp_image_parasite_attach (image, parasite); + gimp_image_parasite_attach (image, parasite, FALSE); gimp_parasite_free (parasite); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimpchannel.c gimp-2.10.14+om/app/core/gimpchannel.c --- gimp-2.10.8+zorin2/app/core/gimpchannel.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchannel.c 2019-10-26 18:49:18.000000000 +0000 @@ -59,6 +59,8 @@ #include "gimp-intl.h" +#define RGBA_EPSILON 1e-6 + enum { COLOR_CHANGED, @@ -108,24 +110,9 @@ gint new_height, gint offset_x, gint offset_y); -static void gimp_channel_flip (GimpItem *item, - GimpContext *context, - GimpOrientationType flip_type, - gdouble axis, - gboolean flip_result); -static void gimp_channel_rotate (GimpItem *item, - GimpContext *context, - GimpRotationType flip_type, - gdouble center_x, - gdouble center_y, - gboolean flip_result); -static void gimp_channel_transform (GimpItem *item, - GimpContext *context, - const GimpMatrix3 *matrix, - GimpTransformDirection direction, - GimpInterpolationType interpolation_type, - GimpTransformResize clip_result, - GimpProgress *progress); +static GimpTransformResize + gimp_channel_get_clip (GimpItem *item, + GimpTransformResize clip_result); static gboolean gimp_channel_fill (GimpItem *item, GimpDrawable *drawable, GimpFillOptions *fill_options, @@ -156,15 +143,12 @@ static void gimp_channel_invalidate_boundary (GimpDrawable *drawable); static void gimp_channel_get_active_components (GimpDrawable *drawable, gboolean *active); -static GimpComponentMask - gimp_channel_get_active_mask (GimpDrawable *drawable); static void gimp_channel_set_buffer (GimpDrawable *drawable, gboolean push_undo, const gchar *undo_desc, GeglBuffer *buffer, - gint offset_x, - gint offset_y); + const GeglRectangle *bounds); static gdouble gimp_channel_get_opacity_at (GimpPickable *pickable, gint x, @@ -183,6 +167,7 @@ static void gimp_channel_real_feather (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo); static void gimp_channel_real_sharpen (GimpChannel *channel, gboolean push_undo); @@ -262,9 +247,7 @@ item_class->translate = gimp_channel_translate; item_class->scale = gimp_channel_scale; item_class->resize = gimp_channel_resize; - item_class->flip = gimp_channel_flip; - item_class->rotate = gimp_channel_rotate; - item_class->transform = gimp_channel_transform; + item_class->get_clip = gimp_channel_get_clip; item_class->fill = gimp_channel_fill; item_class->stroke = gimp_channel_stroke; item_class->to_selection = gimp_channel_to_selection; @@ -290,7 +273,6 @@ drawable_class->convert_type = gimp_channel_convert_type; drawable_class->invalidate_boundary = gimp_channel_invalidate_boundary; drawable_class->get_active_components = gimp_channel_get_active_components; - drawable_class->get_active_mask = gimp_channel_get_active_mask; drawable_class->set_buffer = gimp_channel_set_buffer; klass->boundary = gimp_channel_real_boundary; @@ -348,17 +330,8 @@ { GimpChannel *channel = GIMP_CHANNEL (object); - if (channel->segs_in) - { - g_free (channel->segs_in); - channel->segs_in = NULL; - } - - if (channel->segs_out) - { - g_free (channel->segs_out); - channel->segs_out = NULL; - } + g_clear_pointer (&channel->segs_in, g_free); + g_clear_pointer (&channel->segs_out, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -610,8 +583,10 @@ gimp_drawable_set_buffer_full (drawable, FALSE, NULL, new_buffer, - gimp_item_get_offset_x (item), - gimp_item_get_offset_y (item), + GEGL_RECTANGLE ( + gimp_item_get_offset_x (item), + gimp_item_get_offset_y (item), + 0, 0), TRUE); g_object_unref (new_buffer); } @@ -742,7 +717,8 @@ gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL, new_buffer, - new_offset_x, new_offset_y, + GEGL_RECTANGLE (new_offset_x, new_offset_y, + 0, 0), TRUE); g_object_unref (new_buffer); @@ -775,51 +751,11 @@ } } -static void -gimp_channel_flip (GimpItem *item, - GimpContext *context, - GimpOrientationType flip_type, - gdouble axis, - gboolean clip_result) +static GimpTransformResize +gimp_channel_get_clip (GimpItem *item, + GimpTransformResize clip_result) { - if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL) - clip_result = TRUE; - - GIMP_ITEM_CLASS (parent_class)->flip (item, context, flip_type, axis, - clip_result); -} - -static void -gimp_channel_rotate (GimpItem *item, - GimpContext *context, - GimpRotationType rotate_type, - gdouble center_x, - gdouble center_y, - gboolean clip_result) -{ - /* don't default to clip_result == TRUE here */ - - GIMP_ITEM_CLASS (parent_class)->rotate (item, context, - rotate_type, center_x, center_y, - clip_result); -} - -static void -gimp_channel_transform (GimpItem *item, - GimpContext *context, - const GimpMatrix3 *matrix, - GimpTransformDirection direction, - GimpInterpolationType interpolation_type, - GimpTransformResize clip_result, - GimpProgress *progress) -{ - if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL) - clip_result = TRUE; - - GIMP_ITEM_CLASS (parent_class)->transform (item, context, matrix, direction, - interpolation_type, - clip_result, - progress); + return GIMP_TRANSFORM_RESIZE_CLIP; } static gboolean @@ -1006,20 +942,12 @@ active[ALPHA_G] = FALSE; } -static GimpComponentMask -gimp_channel_get_active_mask (GimpDrawable *drawable) -{ - /* Return all, because that skips the component mask op when painting */ - return GIMP_COMPONENT_MASK_ALL; -} - static void -gimp_channel_set_buffer (GimpDrawable *drawable, - gboolean push_undo, - const gchar *undo_desc, - GeglBuffer *buffer, - gint offset_x, - gint offset_y) +gimp_channel_set_buffer (GimpDrawable *drawable, + gboolean push_undo, + const gchar *undo_desc, + GeglBuffer *buffer, + const GeglRectangle *bounds) { GimpChannel *channel = GIMP_CHANNEL (drawable); GeglBuffer *old_buffer = gimp_drawable_get_buffer (drawable); @@ -1033,8 +961,7 @@ GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable, push_undo, undo_desc, - buffer, - offset_x, offset_y); + buffer, bounds); gegl_buffer_signal_connect (buffer, "changed", G_CALLBACK (gimp_channel_buffer_changed), @@ -1170,14 +1097,10 @@ return FALSE; /* The mask is empty, meaning we can set the bounds as known */ - if (channel->segs_in) - g_free (channel->segs_in); - if (channel->segs_out) - g_free (channel->segs_out); + g_clear_pointer (&channel->segs_in, g_free); + g_clear_pointer (&channel->segs_out, g_free); channel->empty = TRUE; - channel->segs_in = NULL; - channel->segs_out = NULL; channel->num_segs_in = 0; channel->num_segs_out = 0; channel->bounds_known = TRUE; @@ -1194,6 +1117,7 @@ gimp_channel_real_feather (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo) { gint x1, y1, x2, y2; @@ -1225,7 +1149,8 @@ gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)), GEGL_RECTANGLE (x1, y1, x2 - x1, y2 - y1), radius_x, - radius_y); + radius_y, + edge_lock); gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1); } @@ -1253,6 +1178,13 @@ const gchar *undo_desc, gboolean push_undo) { + GeglBuffer *buffer; + GeglRectangle rect; + GeglRectangle aligned_rect; + + if (channel->bounds_known && channel->empty) + return; + if (push_undo) { if (! undo_desc) @@ -1261,19 +1193,28 @@ gimp_channel_push_undo (channel, undo_desc); } - if (channel->bounds_known && ! channel->empty) + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)); + + if (channel->bounds_known) { - gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)), - GEGL_RECTANGLE (channel->x1, channel->y1, - channel->x2 - channel->x1, - channel->y2 - channel->y1)); + rect.x = channel->x1; + rect.y = channel->y1; + rect.width = channel->x2 - channel->x1; + rect.height = channel->y2 - channel->y1; } else { - gegl_buffer_clear (gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)), - NULL); + rect.x = 0; + rect.y = 0; + rect.width = gimp_item_get_width (GIMP_ITEM (channel)); + rect.height = gimp_item_get_height (GIMP_ITEM (channel)); } + gegl_rectangle_align_to_buffer (&aligned_rect, &rect, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + gegl_buffer_clear (buffer, &aligned_rect); + /* we know the bounds */ channel->bounds_known = TRUE; channel->empty = TRUE; @@ -1282,7 +1223,8 @@ channel->x2 = gimp_item_get_width (GIMP_ITEM (channel)); channel->y2 = gimp_item_get_height (GIMP_ITEM (channel)); - gimp_drawable_update (GIMP_DRAWABLE (channel), 0, 0, -1, -1); + gimp_drawable_update (GIMP_DRAWABLE (channel), + rect.x, rect.y, rect.width, rect.height); } static void @@ -1695,7 +1637,7 @@ g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (color != NULL); - if (gimp_rgba_distance (&channel->color, color) > 0.0001) + if (gimp_rgba_distance (&channel->color, color) > RGBA_EPSILON) { if (push_undo && gimp_item_is_attached (GIMP_ITEM (channel))) { @@ -1891,6 +1833,7 @@ gimp_channel_feather (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); @@ -1899,7 +1842,7 @@ push_undo = FALSE; GIMP_CHANNEL_GET_CLASS (channel)->feather (channel, radius_x, radius_y, - push_undo); + edge_lock, push_undo); } void diff -Nru gimp-2.10.8+zorin2/app/core/gimpchannel-combine.c gimp-2.10.14+om/app/core/gimpchannel-combine.c --- gimp-2.10.8+zorin2/app/core/gimpchannel-combine.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchannel-combine.c 2019-10-26 18:49:18.000000000 +0000 @@ -33,6 +33,333 @@ #include "gimpchannel-combine.h" +typedef struct +{ + GeglRectangle rect; + + gboolean bounds_known; + gboolean empty; + GeglRectangle bounds; +} GimpChannelCombineData; + + +/* local function prototypes */ + +static void gimp_channel_combine_clear (GimpChannel *mask, + const GeglRectangle *rect); +static void gimp_channel_combine_clear_complement (GimpChannel *mask, + const GeglRectangle *rect); + +static gboolean gimp_channel_combine_start (GimpChannel *mask, + GimpChannelOps op, + const GeglRectangle *rect, + gboolean full_extent, + gboolean full_value, + GimpChannelCombineData *data); +static void gimp_channel_combine_end (GimpChannel *mask, + GimpChannelCombineData *data); + + +/* private functions */ + +static void +gimp_channel_combine_clear (GimpChannel *mask, + const GeglRectangle *rect) +{ + GeglBuffer *buffer; + GeglRectangle area; + GeglRectangle update_area; + + if (mask->bounds_known && mask->empty) + return; + + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + + if (rect) + { + if (rect->width <= 0 || rect->height <= 0) + return; + + if (mask->bounds_known) + { + if (! gegl_rectangle_intersect (&area, + GEGL_RECTANGLE (mask->x1, + mask->y1, + mask->x2 - mask->x1, + mask->y2 - mask->y1), + rect)) + { + return; + } + } + else + { + area = *rect; + } + + update_area = area; + } + else + { + if (mask->bounds_known) + { + area.x = mask->x1; + area.y = mask->y1; + area.width = mask->x2 - mask->x1; + area.height = mask->y2 - mask->y1; + } + else + { + area.x = 0; + area.y = 0; + area.width = gimp_item_get_width (GIMP_ITEM (mask)); + area.height = gimp_item_get_height (GIMP_ITEM (mask)); + } + + update_area = area; + + gegl_rectangle_align_to_buffer (&area, &area, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + } + + gegl_buffer_clear (buffer, &area); + + gimp_drawable_update (GIMP_DRAWABLE (mask), + update_area.x, update_area.y, + update_area.width, update_area.height); +} + +static void +gimp_channel_combine_clear_complement (GimpChannel *mask, + const GeglRectangle *rect) +{ + gint width = gimp_item_get_width (GIMP_ITEM (mask)); + gint height = gimp_item_get_height (GIMP_ITEM (mask)); + + gimp_channel_combine_clear ( + mask, + GEGL_RECTANGLE (0, + 0, + width, + rect->y)); + + gimp_channel_combine_clear ( + mask, + GEGL_RECTANGLE (0, + rect->y + rect->height, + width, + height - (rect->y + rect->height))); + + gimp_channel_combine_clear ( + mask, + GEGL_RECTANGLE (0, + rect->y, + rect->x, + rect->height)); + + gimp_channel_combine_clear ( + mask, + GEGL_RECTANGLE (rect->x + rect->width, + rect->y, + width - (rect->x + rect->width), + rect->height)); +} + +static gboolean +gimp_channel_combine_start (GimpChannel *mask, + GimpChannelOps op, + const GeglRectangle *rect, + gboolean full_extent, + gboolean full_value, + GimpChannelCombineData *data) +{ + GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + GeglRectangle extent; + gboolean intersects; + + extent.x = 0; + extent.y = 0; + extent.width = gimp_item_get_width (GIMP_ITEM (mask)); + extent.height = gimp_item_get_height (GIMP_ITEM (mask)); + + intersects = gegl_rectangle_intersect (&data->rect, rect, &extent); + + data->bounds_known = mask->bounds_known; + data->empty = mask->empty; + + data->bounds.x = mask->x1; + data->bounds.y = mask->y1; + data->bounds.width = mask->x2 - mask->x1; + data->bounds.height = mask->y2 - mask->y1; + + gegl_buffer_freeze_changed (buffer); + + /* Determine new boundary */ + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + gimp_channel_combine_clear (mask, NULL); + + if (! intersects) + { + data->bounds_known = TRUE; + data->empty = TRUE; + + return FALSE; + } + + data->bounds_known = FALSE; + + if (full_extent) + { + data->bounds_known = TRUE; + data->empty = FALSE; + data->bounds = data->rect; + } + break; + + case GIMP_CHANNEL_OP_ADD: + if (! intersects) + return FALSE; + + data->bounds_known = FALSE; + + if (full_extent && (mask->bounds_known || + gegl_rectangle_equal (&data->rect, &extent))) + { + data->bounds_known = TRUE; + data->empty = FALSE; + + if (mask->bounds_known && ! mask->empty) + { + gegl_rectangle_bounding_box (&data->bounds, + &data->bounds, &data->rect); + } + else + { + data->bounds = data->rect; + } + } + break; + + case GIMP_CHANNEL_OP_SUBTRACT: + if (intersects && mask->bounds_known) + { + if (mask->empty) + { + intersects = FALSE; + } + else + { + intersects = gegl_rectangle_intersect (&data->rect, + &data->rect, + &data->bounds); + } + } + + if (! intersects) + return FALSE; + + if (full_value && + gegl_rectangle_contains (&data->rect, + mask->bounds_known ? &data->bounds : + &extent)) + { + gimp_channel_combine_clear (mask, NULL); + + data->bounds_known = TRUE; + data->empty = TRUE; + + return FALSE; + } + + data->bounds_known = FALSE; + + gegl_buffer_set_abyss (buffer, &data->rect); + break; + + case GIMP_CHANNEL_OP_INTERSECT: + if (intersects && mask->bounds_known) + { + if (mask->empty) + { + intersects = FALSE; + } + else + { + intersects = gegl_rectangle_intersect (&data->rect, + &data->rect, + &data->bounds); + } + } + + if (! intersects) + { + gimp_channel_combine_clear (mask, NULL); + + data->bounds_known = TRUE; + data->empty = TRUE; + + return FALSE; + } + + if (full_value && mask->bounds_known && + gegl_rectangle_contains (&data->rect, &data->bounds)) + { + return FALSE; + } + + data->bounds_known = FALSE; + + gimp_channel_combine_clear_complement (mask, &data->rect); + + gegl_buffer_set_abyss (buffer, &data->rect); + break; + } + + return TRUE; +} + +static void +gimp_channel_combine_end (GimpChannel *mask, + GimpChannelCombineData *data) +{ + GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + + gegl_buffer_set_abyss (buffer, gegl_buffer_get_extent (buffer)); + + gegl_buffer_thaw_changed (buffer); + + mask->bounds_known = data->bounds_known; + + if (data->bounds_known) + { + mask->empty = data->empty; + + if (data->empty) + { + mask->x1 = 0; + mask->y1 = 0; + mask->x2 = gimp_item_get_width (GIMP_ITEM (mask)); + mask->y2 = gimp_item_get_height (GIMP_ITEM (mask)); + } + else + { + mask->x1 = data->bounds.x; + mask->y1 = data->bounds.y; + mask->x2 = data->bounds.x + data->bounds.width; + mask->y2 = data->bounds.y + data->bounds.height; + } + } + + gimp_drawable_update (GIMP_DRAWABLE (mask), + data->rect.x, data->rect.y, + data->rect.width, data->rect.height); +} + + +/* public functions */ + void gimp_channel_combine_rect (GimpChannel *mask, GimpChannelOps op, @@ -41,72 +368,21 @@ gint w, gint h) { - GeglBuffer *buffer; + GimpChannelCombineData data; g_return_if_fail (GIMP_IS_CHANNEL (mask)); - buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - - if (! gimp_gegl_mask_combine_rect (buffer, op, x, y, w, h)) - return; - - gimp_rectangle_intersect (x, y, w, h, - 0, 0, - gimp_item_get_width (GIMP_ITEM (mask)), - gimp_item_get_height (GIMP_ITEM (mask)), - &x, &y, &w, &h); - - /* Determine new boundary */ - if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && ! mask->empty) + if (gimp_channel_combine_start (mask, op, GEGL_RECTANGLE (x, y, w, h), + TRUE, TRUE, &data)) { - if (x < mask->x1) - mask->x1 = x; - if (y < mask->y1) - mask->y1 = y; - if ((x + w) > mask->x2) - mask->x2 = (x + w); - if ((y + h) > mask->y2) - mask->y2 = (y + h); - } - else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty) - { - mask->empty = FALSE; - mask->x1 = x; - mask->y1 = y; - mask->x2 = x + w; - mask->y2 = y + h; - } - else - { - mask->bounds_known = FALSE; + GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + + gimp_gegl_mask_combine_rect (buffer, op, x, y, w, h); } - mask->x1 = CLAMP (mask->x1, 0, gimp_item_get_width (GIMP_ITEM (mask))); - mask->y1 = CLAMP (mask->y1, 0, gimp_item_get_height (GIMP_ITEM (mask))); - mask->x2 = CLAMP (mask->x2, 0, gimp_item_get_width (GIMP_ITEM (mask))); - mask->y2 = CLAMP (mask->y2, 0, gimp_item_get_height (GIMP_ITEM (mask))); - - gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h); -} - -/** - * gimp_channel_combine_ellipse: - * @mask: the channel with which to combine the ellipse - * @op: whether to replace, add to, or subtract from the current - * contents - * @x: x coordinate of upper left corner of ellipse - * @y: y coordinate of upper left corner of ellipse - * @w: width of ellipse bounding box - * @h: height of ellipse bounding box - * @antialias: if %TRUE, antialias the ellipse - * - * Mainly used for elliptical selections. If @op is - * %GIMP_CHANNEL_OP_REPLACE or %GIMP_CHANNEL_OP_ADD, sets pixels - * within the ellipse to 255. If @op is %GIMP_CHANNEL_OP_SUBTRACT, - * sets pixels within to zero. If @antialias is %TRUE, pixels that - * impinge on the edge of the ellipse are set to intermediate values, - * depending on how much they overlap. - **/ + gimp_channel_combine_end (mask, &data); +} + void gimp_channel_combine_ellipse (GimpChannel *mask, GimpChannelOps op, @@ -120,26 +396,6 @@ w / 2.0, h / 2.0, antialias); } -/** - * gimp_channel_combine_ellipse_rect: - * @mask: the channel with which to combine the elliptic rect - * @op: whether to replace, add to, or subtract from the current - * contents - * @x: x coordinate of upper left corner of bounding rect - * @y: y coordinate of upper left corner of bounding rect - * @w: width of bounding rect - * @h: height of bounding rect - * @a: elliptic a-constant applied to corners - * @b: elliptic b-constant applied to corners - * @antialias: if %TRUE, antialias the elliptic corners - * - * Used for rounded cornered rectangles and ellipses. If @op is - * %GIMP_CHANNEL_OP_REPLACE or %GIMP_CHANNEL_OP_ADD, sets pixels - * within the ellipse to 255. If @op is %GIMP_CHANNEL_OP_SUBTRACT, - * sets pixels within to zero. If @antialias is %TRUE, pixels that - * impinge on the edge of the ellipse are set to intermediate values, - * depending on how much they overlap. - **/ void gimp_channel_combine_ellipse_rect (GimpChannel *mask, GimpChannelOps op, @@ -147,51 +403,24 @@ gint y, gint w, gint h, - gdouble a, - gdouble b, + gdouble rx, + gdouble ry, gboolean antialias) { - GeglBuffer *buffer; + GimpChannelCombineData data; g_return_if_fail (GIMP_IS_CHANNEL (mask)); - g_return_if_fail (a >= 0.0 && b >= 0.0); - g_return_if_fail (op != GIMP_CHANNEL_OP_INTERSECT); - - buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - - if (! gimp_gegl_mask_combine_ellipse_rect (buffer, op, x, y, w, h, - a, b, antialias)) - return; - gimp_rectangle_intersect (x, y, w, h, - 0, 0, - gimp_item_get_width (GIMP_ITEM (mask)), - gimp_item_get_height (GIMP_ITEM (mask)), - &x, &y, &w, &h); - - /* determine new boundary */ - if (mask->bounds_known && (op == GIMP_CHANNEL_OP_ADD) && ! mask->empty) - { - if (x < mask->x1) mask->x1 = x; - if (y < mask->y1) mask->y1 = y; - - if ((x + w) > mask->x2) mask->x2 = (x + w); - if ((y + h) > mask->y2) mask->y2 = (y + h); - } - else if (op == GIMP_CHANNEL_OP_REPLACE || mask->empty) - { - mask->empty = FALSE; - mask->x1 = x; - mask->y1 = y; - mask->x2 = x + w; - mask->y2 = y + h; - } - else + if (gimp_channel_combine_start (mask, op, GEGL_RECTANGLE (x, y, w, h), + TRUE, FALSE, &data)) { - mask->bounds_known = FALSE; + GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); + + gimp_gegl_mask_combine_ellipse_rect (buffer, op, x, y, w, h, + rx, ry, antialias); } - gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h); + gimp_channel_combine_end (mask, &data); } void @@ -219,27 +448,24 @@ gint off_x, gint off_y) { - GeglBuffer *buffer; - gint x, y, w, h; + GimpChannelCombineData data; g_return_if_fail (GIMP_IS_CHANNEL (mask)); g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer)); - buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - - if (! gimp_gegl_mask_combine_buffer (buffer, add_on_buffer, - op, off_x, off_y)) - return; - - gimp_rectangle_intersect (off_x, off_y, - gegl_buffer_get_width (add_on_buffer), - gegl_buffer_get_height (add_on_buffer), - 0, 0, - gimp_item_get_width (GIMP_ITEM (mask)), - gimp_item_get_height (GIMP_ITEM (mask)), - &x, &y, &w, &h); + if (gimp_channel_combine_start (mask, op, + GEGL_RECTANGLE ( + off_x, + off_y, + gegl_buffer_get_width (add_on_buffer), + gegl_buffer_get_height (add_on_buffer)), + FALSE, FALSE, &data)) + { + GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - mask->bounds_known = FALSE; + gimp_gegl_mask_combine_buffer (buffer, add_on_buffer, op, + off_x, off_y); + } - gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h); + gimp_channel_combine_end (mask, &data); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpchannel-combine.h gimp-2.10.14+om/app/core/gimpchannel-combine.h --- gimp-2.10.8+zorin2/app/core/gimpchannel-combine.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchannel-combine.h 2019-04-07 11:38:14.000000000 +0000 @@ -38,8 +38,8 @@ gint y, gint w, gint h, - gdouble a, - gdouble b, + gdouble rx, + gdouble ry, gboolean antialias); void gimp_channel_combine_mask (GimpChannel *mask, GimpChannel *add_on, diff -Nru gimp-2.10.8+zorin2/app/core/gimpchannel.h gimp-2.10.14+om/app/core/gimpchannel.h --- gimp-2.10.8+zorin2/app/core/gimpchannel.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchannel.h 2019-10-26 18:49:18.000000000 +0000 @@ -77,6 +77,7 @@ void (* feather) (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo); void (* sharpen) (GimpChannel *channel, gboolean push_undo); @@ -180,6 +181,7 @@ void gimp_channel_feather (GimpChannel *mask, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo); void gimp_channel_sharpen (GimpChannel *mask, gboolean push_undo); diff -Nru gimp-2.10.8+zorin2/app/core/gimpchannel-select.c gimp-2.10.14+om/app/core/gimpchannel-select.c --- gimp-2.10.8+zorin2/app/core/gimpchannel-select.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchannel-select.c 2019-10-26 18:49:18.000000000 +0000 @@ -65,14 +65,10 @@ if (push_undo) gimp_channel_push_undo (channel, C_("undo-type", "Rectangle Select")); - /* if applicable, replace the current selection */ - if (op == GIMP_CHANNEL_OP_REPLACE) - gimp_channel_clear (channel, NULL, FALSE); - /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ - if (feather || op == GIMP_CHANNEL_OP_INTERSECT) + if (feather) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on; @@ -82,12 +78,12 @@ gimp_item_get_height (item)), babl_format ("Y float")); - gimp_gegl_mask_combine_rect (add_on, GIMP_CHANNEL_OP_ADD, x, y, w, h); + gimp_gegl_mask_combine_rect (add_on, GIMP_CHANNEL_OP_REPLACE, x, y, w, h); - if (feather) - gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, - feather_radius_x, - feather_radius_y); + gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, + feather_radius_x, + feather_radius_y, + TRUE); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); @@ -117,14 +113,10 @@ if (push_undo) gimp_channel_push_undo (channel, C_("undo-type", "Ellipse Select")); - /* if applicable, replace the current selection */ - if (op == GIMP_CHANNEL_OP_REPLACE) - gimp_channel_clear (channel, NULL, FALSE); - /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ - if (feather || op == GIMP_CHANNEL_OP_INTERSECT) + if (feather) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on; @@ -134,13 +126,13 @@ gimp_item_get_height (item)), babl_format ("Y float")); - gimp_gegl_mask_combine_ellipse (add_on, GIMP_CHANNEL_OP_ADD, + gimp_gegl_mask_combine_ellipse (add_on, GIMP_CHANNEL_OP_REPLACE, x, y, w, h, antialias); - if (feather) - gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, - feather_radius_x, - feather_radius_y); + gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, + feather_radius_x, + feather_radius_y, + TRUE); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); @@ -172,14 +164,10 @@ if (push_undo) gimp_channel_push_undo (channel, C_("undo-type", "Rounded Rectangle Select")); - /* if applicable, replace the current selection */ - if (op == GIMP_CHANNEL_OP_REPLACE) - gimp_channel_clear (channel, NULL, FALSE); - /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ - if (feather || op == GIMP_CHANNEL_OP_INTERSECT) + if (feather) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on; @@ -189,15 +177,15 @@ gimp_item_get_height (item)), babl_format ("Y float")); - gimp_gegl_mask_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_ADD, + gimp_gegl_mask_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_REPLACE, x, y, w, h, corner_radius_x, corner_radius_y, antialias); - if (feather) - gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, - feather_radius_x, - feather_radius_y); + gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, + feather_radius_x, + feather_radius_y, + TRUE); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); @@ -236,10 +224,6 @@ if (push_undo) gimp_channel_push_undo (channel, undo_desc); - /* if applicable, replace the current selection */ - if (op == GIMP_CHANNEL_OP_REPLACE) - gimp_channel_clear (channel, NULL, FALSE); - item = GIMP_ITEM (channel); add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0, @@ -253,7 +237,8 @@ if (feather) gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL, feather_radius_x, - feather_radius_y); + feather_radius_y, + TRUE); gimp_channel_combine_buffer (channel, add_on, op, 0, 0); g_object_unref (add_on); @@ -346,11 +331,7 @@ gimp_channel_push_undo (channel, undo_desc); - /* if applicable, replace the current selection */ - if (op == GIMP_CHANNEL_OP_REPLACE) - gimp_channel_clear (channel, NULL, FALSE); - - if (feather || op == GIMP_CHANNEL_OP_INTERSECT) + if (feather) { GimpItem *item = GIMP_ITEM (channel); GeglBuffer *add_on2; @@ -361,13 +342,13 @@ babl_format ("Y float")); gimp_gegl_mask_combine_buffer (add_on2, add_on, - GIMP_CHANNEL_OP_ADD, + GIMP_CHANNEL_OP_REPLACE, offset_x, offset_y); - if (feather) - gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL, - feather_radius_x, - feather_radius_y); + gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL, + feather_radius_x, + feather_radius_y, + TRUE); gimp_channel_combine_buffer (channel, add_on2, op, 0, 0); g_object_unref (add_on2); @@ -470,6 +451,7 @@ gimp_channel_feather (add_on, feather_radius_x, feather_radius_y, + TRUE, FALSE /* no undo */); gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component, diff -Nru gimp-2.10.8+zorin2/app/core/gimpchunkiterator.c gimp-2.10.14+om/app/core/gimpchunkiterator.c --- gimp-2.10.8+zorin2/app/core/gimpchunkiterator.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchunkiterator.c 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,555 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis + * + * gimpchunkiterator.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "config.h" + +#include + +#include +#include +#include + +#include "libgimpmath/gimpmath.h" + +#include "core-types.h" + +#include "gimpchunkiterator.h" + + +/* the maximal chunk size */ +#define MAX_CHUNK_WIDTH 4096 +#define MAX_CHUNK_HEIGHT 4096 + +/* the default iteration interval */ +#define DEFAULT_INTERVAL (1.0 / 15.0) /* seconds */ + +/* the minimal area to process per iteration */ +#define MIN_AREA_PER_ITERATION 4096 + +/* the maximal ratio between the actual processed area and the target area, + * above which the current chunk height is readjusted, even in the middle of a + * row, to better match the target area + */ +#define MAX_AREA_RATIO 2.0 + +/* the width of the target-area sliding window */ +#define TARGET_AREA_HISTORY_SIZE 3 + + +struct _GimpChunkIterator +{ + cairo_region_t *region; + cairo_region_t *priority_region; + + GeglRectangle tile_rect; + GeglRectangle priority_rect; + + gdouble interval; + + cairo_region_t *current_region; + GeglRectangle current_rect; + + gint current_x; + gint current_y; + gint current_height; + + gint64 iteration_time; + + gint64 last_time; + gint last_area; + + gdouble target_area; + gdouble target_area_min; + gdouble target_area_history[TARGET_AREA_HISTORY_SIZE]; + gint target_area_history_i; + gint target_area_history_n; +}; + + +/* local function prototypes */ + +static void gimp_chunk_iterator_set_current_rect (GimpChunkIterator *iter, + const GeglRectangle *rect); +static void gimp_chunk_iterator_merge_current_rect (GimpChunkIterator *iter); + +static void gimp_chunk_iterator_merge (GimpChunkIterator *iter); + +static gboolean gimp_chunk_iterator_prepare (GimpChunkIterator *iter); + +static void gimp_chunk_iterator_set_target_area (GimpChunkIterator *iter, + gdouble target_area); +static gdouble gimp_chunk_iterator_get_target_area (GimpChunkIterator *iter); +static void gimp_chunk_iterator_reset_target_area (GimpChunkIterator *iter); + +static void gimp_chunk_iterator_calc_rect (GimpChunkIterator *iter, + GeglRectangle *rect, + gboolean readjust_height); + + +/* private functions */ + +static void +gimp_chunk_iterator_set_current_rect (GimpChunkIterator *iter, + const GeglRectangle *rect) +{ + cairo_region_subtract_rectangle (iter->current_region, + (const cairo_rectangle_int_t *) rect); + + iter->current_rect = *rect; + + iter->current_x = rect->x; + iter->current_y = rect->y; + iter->current_height = 0; +} + +static void +gimp_chunk_iterator_merge_current_rect (GimpChunkIterator *iter) +{ + GeglRectangle rect; + + if (gegl_rectangle_is_empty (&iter->current_rect)) + return; + + /* merge the remainder of the current row */ + rect.x = iter->current_x; + rect.y = iter->current_y; + rect.width = iter->current_rect.x + iter->current_rect.width - + iter->current_x; + rect.height = iter->current_height; + + cairo_region_union_rectangle (iter->current_region, + (const cairo_rectangle_int_t *) &rect); + + /* merge the remainder of the current rect */ + rect.x = iter->current_rect.x; + rect.y = iter->current_y + iter->current_height; + rect.width = iter->current_rect.width; + rect.height = iter->current_rect.y + iter->current_rect.height - rect.y; + + cairo_region_union_rectangle (iter->current_region, + (const cairo_rectangle_int_t *) &rect); + + /* reset the current rect and coordinates */ + iter->current_rect.x = 0; + iter->current_rect.y = 0; + iter->current_rect.width = 0; + iter->current_rect.height = 0; + + iter->current_x = 0; + iter->current_y = 0; + iter->current_height = 0; +} + +static void +gimp_chunk_iterator_merge (GimpChunkIterator *iter) +{ + /* merge the current rect back to the current region */ + gimp_chunk_iterator_merge_current_rect (iter); + + /* merge the priority region back to the global region */ + if (iter->priority_region) + { + cairo_region_union (iter->region, iter->priority_region); + + g_clear_pointer (&iter->priority_region, cairo_region_destroy); + + iter->current_region = iter->region; + } +} + +static gboolean +gimp_chunk_iterator_prepare (GimpChunkIterator *iter) +{ + if (iter->current_x == iter->current_rect.x + iter->current_rect.width) + { + iter->current_x = iter->current_rect.x; + iter->current_y += iter->current_height; + iter->current_height = 0; + + if (iter->current_y == iter->current_rect.y + iter->current_rect.height) + { + GeglRectangle rect; + + if (! iter->priority_region && + ! gegl_rectangle_is_empty (&iter->priority_rect)) + { + iter->priority_region = cairo_region_copy (iter->region); + + cairo_region_intersect_rectangle ( + iter->priority_region, + (const cairo_rectangle_int_t *) &iter->priority_rect); + + cairo_region_subtract_rectangle ( + iter->region, + (const cairo_rectangle_int_t *) &iter->priority_rect); + } + + if (! iter->priority_region || + cairo_region_is_empty (iter->priority_region)) + { + iter->current_region = iter->region; + } + else + { + iter->current_region = iter->priority_region; + } + + if (cairo_region_is_empty (iter->current_region)) + { + iter->current_rect.x = 0; + iter->current_rect.y = 0; + iter->current_rect.width = 0; + iter->current_rect.height = 0; + + iter->current_x = 0; + iter->current_y = 0; + iter->current_height = 0; + + return FALSE; + } + + cairo_region_get_rectangle (iter->current_region, 0, + (cairo_rectangle_int_t *) &rect); + + gimp_chunk_iterator_set_current_rect (iter, &rect); + } + } + + return TRUE; +} + +static gint +compare_double (const gdouble *x, + const gdouble *y) +{ + return (*x > *y) - (*x < *y); +} + +static void +gimp_chunk_iterator_set_target_area (GimpChunkIterator *iter, + gdouble target_area) +{ + gdouble target_area_history[TARGET_AREA_HISTORY_SIZE]; + + iter->target_area_min = MIN (iter->target_area_min, target_area); + + iter->target_area_history[iter->target_area_history_i++] = target_area; + + iter->target_area_history_n = MAX (iter->target_area_history_n, + iter->target_area_history_i); + iter->target_area_history_i %= TARGET_AREA_HISTORY_SIZE; + + memcpy (target_area_history, iter->target_area_history, + iter->target_area_history_n * sizeof (gdouble)); + + qsort (target_area_history, iter->target_area_history_n, sizeof (gdouble), + (gpointer) compare_double); + + iter->target_area = target_area_history[iter->target_area_history_n / 2]; +} + +static gdouble +gimp_chunk_iterator_get_target_area (GimpChunkIterator *iter) +{ + if (iter->target_area) + return iter->target_area; + else + return iter->tile_rect.width * iter->tile_rect.height; +} + +static void +gimp_chunk_iterator_reset_target_area (GimpChunkIterator *iter) +{ + if (iter->target_area_history_n) + { + iter->target_area = iter->target_area_min; + iter->target_area_min = MAX_CHUNK_WIDTH * MAX_CHUNK_HEIGHT; + iter->target_area_history_i = 0; + iter->target_area_history_n = 0; + } +} + +static void +gimp_chunk_iterator_calc_rect (GimpChunkIterator *iter, + GeglRectangle *rect, + gboolean readjust_height) +{ + gdouble target_area; + gdouble aspect_ratio; + gint offset_x; + gint offset_y; + + if (readjust_height) + gimp_chunk_iterator_reset_target_area (iter); + + target_area = gimp_chunk_iterator_get_target_area (iter); + + aspect_ratio = (gdouble) iter->tile_rect.height / + (gdouble) iter->tile_rect.width; + + rect->x = iter->current_x; + rect->y = iter->current_y; + + offset_x = rect->x - iter->tile_rect.x; + offset_y = rect->y - iter->tile_rect.y; + + if (readjust_height) + { + rect->height = RINT ((offset_y + sqrt (target_area * aspect_ratio)) / + iter->tile_rect.height) * + iter->tile_rect.height - + offset_y; + + if (rect->height <= 0) + rect->height += iter->tile_rect.height; + + rect->height = MIN (rect->height, + iter->current_rect.y + iter->current_rect.height - + rect->y); + rect->height = MIN (rect->height, MAX_CHUNK_HEIGHT); + } + else + { + rect->height = iter->current_height; + } + + rect->width = RINT ((offset_x + (gdouble) target_area / + (gdouble) rect->height) / + iter->tile_rect.width) * + iter->tile_rect.width - + offset_x; + + if (rect->width <= 0) + rect->width += iter->tile_rect.width; + + rect->width = MIN (rect->width, + iter->current_rect.x + iter->current_rect.width - + rect->x); + rect->width = MIN (rect->width, MAX_CHUNK_WIDTH); +} + + +/* public functions */ + +GimpChunkIterator * +gimp_chunk_iterator_new (cairo_region_t *region) +{ + GimpChunkIterator *iter; + + g_return_val_if_fail (region != NULL, NULL); + + iter = g_slice_new0 (GimpChunkIterator); + + iter->region = region; + iter->current_region = region; + + g_object_get (gegl_config (), + "tile-width", &iter->tile_rect.width, + "tile-height", &iter->tile_rect.height, + NULL); + + iter->interval = DEFAULT_INTERVAL; + + return iter; +} + +void +gimp_chunk_iterator_set_tile_rect (GimpChunkIterator *iter, + const GeglRectangle *rect) +{ + g_return_if_fail (iter != NULL); + g_return_if_fail (rect != NULL); + g_return_if_fail (! gegl_rectangle_is_empty (rect)); + + iter->tile_rect = *rect; +} + +void +gimp_chunk_iterator_set_priority_rect (GimpChunkIterator *iter, + const GeglRectangle *rect) +{ + const GeglRectangle empty_rect = {}; + + g_return_if_fail (iter != NULL); + + if (! rect) + rect = &empty_rect; + + if (! gegl_rectangle_equal (rect, &iter->priority_rect)) + { + iter->priority_rect = *rect; + + gimp_chunk_iterator_merge (iter); + } +} + +void +gimp_chunk_iterator_set_interval (GimpChunkIterator *iter, + gdouble interval) +{ + g_return_if_fail (iter != NULL); + + interval = MAX (interval, 0.0); + + if (interval != iter->interval) + { + if (iter->interval) + { + gdouble ratio = interval / iter->interval; + gint i; + + iter->target_area *= ratio; + + for (i = 0; i < TARGET_AREA_HISTORY_SIZE; i++) + iter->target_area_history[i] *= ratio; + } + + iter->interval = interval; + } +} + +gboolean +gimp_chunk_iterator_next (GimpChunkIterator *iter) +{ + g_return_val_if_fail (iter != NULL, FALSE); + + if (! gimp_chunk_iterator_prepare (iter)) + { + gimp_chunk_iterator_stop (iter, TRUE); + + return FALSE; + } + + iter->iteration_time = g_get_monotonic_time (); + + iter->last_time = iter->iteration_time; + iter->last_area = 0; + + return TRUE; +} + +gboolean +gimp_chunk_iterator_get_rect (GimpChunkIterator *iter, + GeglRectangle *rect) +{ + gint64 time; + + g_return_val_if_fail (iter != NULL, FALSE); + g_return_val_if_fail (rect != NULL, FALSE); + + if (! gimp_chunk_iterator_prepare (iter)) + return FALSE; + + time = g_get_monotonic_time (); + + if (iter->last_area >= MIN_AREA_PER_ITERATION) + { + gdouble interval; + + interval = (gdouble) (time - iter->last_time) / G_TIME_SPAN_SECOND; + + gimp_chunk_iterator_set_target_area ( + iter, + iter->last_area * iter->interval / interval); + + interval = (gdouble) (time - iter->iteration_time) / G_TIME_SPAN_SECOND; + + if (interval > iter->interval) + return FALSE; + } + + if (iter->current_x == iter->current_rect.x) + { + gimp_chunk_iterator_calc_rect (iter, rect, TRUE); + } + else + { + gimp_chunk_iterator_calc_rect (iter, rect, FALSE); + + if (rect->width * rect->height >= + MAX_AREA_RATIO * gimp_chunk_iterator_get_target_area (iter)) + { + GeglRectangle old_rect = *rect; + + gimp_chunk_iterator_calc_rect (iter, rect, TRUE); + + if (rect->height >= old_rect.height) + *rect = old_rect; + } + } + + if (rect->height != iter->current_height) + { + /* if the chunk height changed in the middle of a row, merge the + * remaining area back into the current region, and reset the current + * area to the remainder of the row, using the new chunk height + */ + if (rect->x != iter->current_rect.x) + { + GeglRectangle rem; + + rem.x = rect->x; + rem.y = rect->y; + rem.width = iter->current_rect.x + iter->current_rect.width - + rect->x; + rem.height = rect->height; + + gimp_chunk_iterator_merge_current_rect (iter); + + gimp_chunk_iterator_set_current_rect (iter, &rem); + } + + iter->current_height = rect->height; + } + + iter->current_x += rect->width; + + iter->last_time = time; + iter->last_area = rect->width * rect->height; + + return TRUE; +} + +cairo_region_t * +gimp_chunk_iterator_stop (GimpChunkIterator *iter, + gboolean free_region) +{ + cairo_region_t *result = NULL; + + g_return_val_if_fail (iter != NULL, NULL); + + if (free_region) + { + cairo_region_destroy (iter->region); + } + else + { + gimp_chunk_iterator_merge (iter); + + result = iter->region; + } + + g_clear_pointer (&iter->priority_region, cairo_region_destroy); + + g_slice_free (GimpChunkIterator, iter); + + return result; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpchunkiterator.h gimp-2.10.14+om/app/core/gimpchunkiterator.h --- gimp-2.10.8+zorin2/app/core/gimpchunkiterator.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpchunkiterator.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,44 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpchunkiterator.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_CHUNK_ITEARTOR_H__ +#define __GIMP_CHUNK_ITEARTOR_H__ + + +GimpChunkIterator * gimp_chunk_iterator_new (cairo_region_t *region); + +void gimp_chunk_iterator_set_tile_rect (GimpChunkIterator *iter, + const GeglRectangle *rect); + +void gimp_chunk_iterator_set_priority_rect (GimpChunkIterator *iter, + const GeglRectangle *rect); + +void gimp_chunk_iterator_set_interval (GimpChunkIterator *iter, + gdouble interval); + +gboolean gimp_chunk_iterator_next (GimpChunkIterator *iter); +gboolean gimp_chunk_iterator_get_rect (GimpChunkIterator *iter, + GeglRectangle *rect); + +cairo_region_t * gimp_chunk_iterator_stop (GimpChunkIterator *iter, + gboolean free_region); + + +#endif /* __GIMP_CHUNK_ITEARTOR_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpcontext.c gimp-2.10.14+om/app/core/gimpcontext.c --- gimp-2.10.8+zorin2/app/core/gimpcontext.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpcontext.c 2019-01-03 14:13:22.000000000 +0000 @@ -57,10 +57,11 @@ #include "gimp-intl.h" +#define RGBA_EPSILON 1e-10 + typedef void (* GimpContextCopyPropFunc) (GimpContext *src, GimpContext *dest); - #define context_find_defined(context, prop) \ while (!(((context)->defined_props) & (1 << (prop))) && (context)->parent) \ (context) = (context)->parent @@ -2319,7 +2320,7 @@ gimp_context_real_set_foreground (GimpContext *context, const GimpRGB *color) { - if (gimp_rgba_distance (&context->foreground, color) < 0.0001) + if (gimp_rgba_distance (&context->foreground, color) < RGBA_EPSILON) return; context->foreground = *color; @@ -2370,7 +2371,7 @@ gimp_context_real_set_background (GimpContext *context, const GimpRGB *color) { - if (gimp_rgba_distance (&context->background, color) < 0.0001) + if (gimp_rgba_distance (&context->background, color) < RGBA_EPSILON) return; context->background = *color; diff -Nru gimp-2.10.8+zorin2/app/core/gimpcurve.c gimp-2.10.14+om/app/core/gimpcurve.c --- gimp-2.10.8+zorin2/app/core/gimpcurve.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpcurve.c 2019-10-26 18:49:18.000000000 +0000 @@ -37,12 +37,16 @@ #include "gimp-intl.h" +#define EPSILON 1e-6 + + enum { PROP_0, PROP_CURVE_TYPE, PROP_N_POINTS, PROP_POINTS, + PROP_POINT_TYPES, PROP_N_SAMPLES, PROP_SAMPLES }; @@ -155,7 +159,9 @@ "n-points", "Number of Points", "The number of points", - 17, 17, 17, 0); + 0, G_MAXINT, 0, + /* for backward compatibility */ + GIMP_CONFIG_PARAM_IGNORE); array_spec = g_param_spec_double ("point", NULL, NULL, -1.0, 1.0, 0.0, GIMP_PARAM_READWRITE); @@ -166,6 +172,17 @@ GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_FLAGS)); + array_spec = g_param_spec_enum ("point-type", NULL, NULL, + GIMP_TYPE_CURVE_POINT_TYPE, + GIMP_CURVE_POINT_SMOOTH, + GIMP_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_POINT_TYPES, + gimp_param_spec_value_array ("point-types", + NULL, NULL, + array_spec, + GIMP_PARAM_STATIC_STRINGS | + GIMP_CONFIG_PARAM_FLAGS)); + GIMP_CONFIG_PROP_INT (object_class, PROP_N_SAMPLES, "n-samples", "Number of Samples", @@ -207,17 +224,11 @@ { GimpCurve *curve = GIMP_CURVE (object); - if (curve->points) - { - g_free (curve->points); - curve->points = NULL; - } + g_clear_pointer (&curve->points, g_free); + curve->n_points = 0; - if (curve->samples) - { - g_free (curve->samples); - curve->samples = NULL; - } + g_clear_pointer (&curve->samples, g_free); + curve->n_samples = 0; G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -237,28 +248,108 @@ break; case PROP_N_POINTS: - gimp_curve_set_n_points (curve, g_value_get_int (value)); + /* ignored */ break; case PROP_POINTS: { GimpValueArray *array = g_value_get_boxed (value); + GimpCurvePoint *points; gint length; + gint n_points; gint i; if (! array) - break; + { + gimp_curve_clear_points (curve); - length = gimp_value_array_length (array); + break; + } + + length = gimp_value_array_length (array) / 2; + + n_points = 0; + points = g_new0 (GimpCurvePoint, length); - for (i = 0; i < curve->n_points && i * 2 < length; i++) + for (i = 0; i < length; i++) { GValue *x = gimp_value_array_index (array, i * 2); GValue *y = gimp_value_array_index (array, i * 2 + 1); - curve->points[i].x = g_value_get_double (x); - curve->points[i].y = g_value_get_double (y); + /* for backward compatibility */ + if (g_value_get_double (x) < 0.0) + continue; + + points[n_points].x = CLAMP (g_value_get_double (x), 0.0, 1.0); + points[n_points].y = CLAMP (g_value_get_double (y), 0.0, 1.0); + + if (n_points > 0) + { + points[n_points].x = MAX (points[n_points].x, + points[n_points - 1].x); + } + + if (n_points < curve->n_points) + points[n_points].type = curve->points[n_points].type; + else + points[n_points].type = GIMP_CURVE_POINT_SMOOTH; + + n_points++; } + + g_free (curve->points); + + curve->n_points = n_points; + curve->points = points; + + g_object_notify (object, "n-points"); + g_object_notify (object, "point-types"); + } + break; + + case PROP_POINT_TYPES: + { + GimpValueArray *array = g_value_get_boxed (value); + GimpCurvePoint *points; + gint length; + gdouble x = 0.0; + gdouble y = 0.0; + gint i; + + if (! array) + { + gimp_curve_clear_points (curve); + + break; + } + + length = gimp_value_array_length (array); + + points = g_new0 (GimpCurvePoint, length); + + for (i = 0; i < length; i++) + { + GValue *type = gimp_value_array_index (array, i); + + points[i].type = g_value_get_enum (type); + + if (i < curve->n_points) + { + x = curve->points[i].x; + y = curve->points[i].y; + } + + points[i].x = x; + points[i].y = y; + } + + g_free (curve->points); + + curve->n_points = length; + curve->points = points; + + g_object_notify (object, "n-points"); + g_object_notify (object, "points"); } break; @@ -281,7 +372,7 @@ { GValue *v = gimp_value_array_index (array, i); - curve->samples[i] = g_value_get_double (v); + curve->samples[i] = CLAMP (g_value_get_double (v), 0.0, 1.0); } } break; @@ -333,6 +424,26 @@ } break; + case PROP_POINT_TYPES: + { + GimpValueArray *array = gimp_value_array_new (curve->n_points); + GValue v = G_VALUE_INIT; + gint i; + + g_value_init (&v, GIMP_TYPE_CURVE_POINT_TYPE); + + for (i = 0; i < curve->n_points; i++) + { + g_value_set_enum (&v, curve->points[i].type); + gimp_value_array_append (array, &v); + } + + g_value_unset (&v); + + g_value_take_boxed (value, array); + } + break; + case PROP_N_SAMPLES: g_value_set_int (value, curve->n_samples); break; @@ -370,7 +481,7 @@ GimpCurve *curve = GIMP_CURVE (object); gint64 memsize = 0; - memsize += curve->n_points * sizeof (GimpVector2); + memsize += curve->n_points * sizeof (GimpCurvePoint); memsize += curve->n_samples * sizeof (gdouble); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, @@ -484,11 +595,19 @@ if (a_curve->curve_type != b_curve->curve_type) return FALSE; - if (memcmp (a_curve->points, b_curve->points, - sizeof (GimpVector2) * b_curve->n_points) || + if (a_curve->n_points != b_curve->n_points || + memcmp (a_curve->points, b_curve->points, + sizeof (GimpCurvePoint) * a_curve->n_points)) + { + return FALSE; + } + + if (a_curve->n_samples != b_curve->n_samples || memcmp (a_curve->samples, b_curve->samples, - sizeof (gdouble) * b_curve->n_samples)) - return FALSE; + sizeof (gdouble) * a_curve->n_samples)) + { + return FALSE; + } return TRUE; } @@ -564,19 +683,22 @@ g_object_notify (G_OBJECT (curve), "samples"); - curve->points[0].x = 0.0; - curve->points[0].y = 0.0; + g_free (curve->points); - for (i = 1; i < curve->n_points - 1; i++) - { - curve->points[i].x = -1.0; - curve->points[i].y = -1.0; - } + curve->n_points = 2; + curve->points = g_new0 (GimpCurvePoint, 2); - curve->points[curve->n_points - 1].x = 1.0; - curve->points[curve->n_points - 1].y = 1.0; + curve->points[0].x = 0.0; + curve->points[0].y = 0.0; + curve->points[0].type = GIMP_CURVE_POINT_SMOOTH; + curve->points[1].x = 1.0; + curve->points[1].y = 1.0; + curve->points[1].type = GIMP_CURVE_POINT_SMOOTH; + + g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); if (reset_type) { @@ -599,44 +721,48 @@ if (curve->curve_type != curve_type) { + gimp_data_freeze (GIMP_DATA (curve)); + g_object_freeze_notify (G_OBJECT (curve)); curve->curve_type = curve_type; if (curve_type == GIMP_CURVE_SMOOTH) { - gint n_points; gint i; - for (i = 0; i < curve->n_points; i++) - { - curve->points[i].x = -1; - curve->points[i].y = -1; - } + g_free (curve->points); /* pick some points from the curve and make them control * points */ - n_points = CLAMP (9, curve->n_points / 2, curve->n_points); + curve->n_points = 9; + curve->points = g_new0 (GimpCurvePoint, 9); - for (i = 0; i < n_points; i++) + for (i = 0; i < curve->n_points; i++) { - gint sample = i * (curve->n_samples - 1) / (n_points - 1); - gint point = i * (curve->n_points - 1) / (n_points - 1); + gint sample = i * (curve->n_samples - 1) / (curve->n_points - 1); - curve->points[point].x = ((gdouble) sample / - (gdouble) (curve->n_samples - 1)); - curve->points[point].y = curve->samples[sample]; + curve->points[i].x = (gdouble) sample / + (gdouble) (curve->n_samples - 1); + curve->points[i].y = curve->samples[sample]; + curve->points[i].type = GIMP_CURVE_POINT_SMOOTH; } + g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); + } + else + { + gimp_curve_clear_points (curve); } g_object_notify (G_OBJECT (curve), "curve-type"); g_object_thaw_notify (G_OBJECT (curve)); - gimp_data_dirty (GIMP_DATA (curve)); + gimp_data_thaw (GIMP_DATA (curve)); } } @@ -648,46 +774,6 @@ return curve->curve_type; } -void -gimp_curve_set_n_points (GimpCurve *curve, - gint n_points) -{ - g_return_if_fail (GIMP_IS_CURVE (curve)); - g_return_if_fail (n_points >= 2); - g_return_if_fail (n_points <= 1024); - - if (n_points != curve->n_points) - { - gint i; - - g_object_freeze_notify (G_OBJECT (curve)); - - curve->n_points = n_points; - g_object_notify (G_OBJECT (curve), "n-points"); - - curve->points = g_renew (GimpVector2, curve->points, curve->n_points); - - curve->points[0].x = 0.0; - curve->points[0].y = 0.0; - - for (i = 1; i < curve->n_points - 1; i++) - { - curve->points[i].x = -1.0; - curve->points[i].y = -1.0; - } - - curve->points[curve->n_points - 1].x = 1.0; - curve->points[curve->n_points - 1].y = 1.0; - - g_object_notify (G_OBJECT (curve), "points"); - - if (curve->curve_type == GIMP_CURVE_SMOOTH) - curve->identity = TRUE; - - g_object_thaw_notify (G_OBJECT (curve)); - } -} - gint gimp_curve_get_n_points (GimpCurve *curve) { @@ -736,66 +822,155 @@ } gint -gimp_curve_get_closest_point (GimpCurve *curve, - gdouble x) +gimp_curve_get_point_at (GimpCurve *curve, + gdouble x) { - gint closest_point = 0; - gdouble distance = G_MAXDOUBLE; + gint closest_point = -1; + gdouble distance = EPSILON; gint i; - g_return_val_if_fail (GIMP_IS_CURVE (curve), 0); + g_return_val_if_fail (GIMP_IS_CURVE (curve), -1); for (i = 0; i < curve->n_points; i++) { - if (curve->points[i].x >= 0.0 && - fabs (x - curve->points[i].x) < distance) + gdouble point_distance; + + point_distance = fabs (x - curve->points[i].x); + + if (point_distance <= distance) { - distance = fabs (x - curve->points[i].x); closest_point = i; + distance = point_distance; } } - if (distance > (1.0 / (curve->n_points * 2.0))) - closest_point = ROUND (x * (gdouble) (curve->n_points - 1)); + return closest_point; +} + +gint +gimp_curve_get_closest_point (GimpCurve *curve, + gdouble x, + gdouble y, + gdouble max_distance) +{ + gint closest_point = -1; + gdouble distance2 = G_MAXDOUBLE; + gint i; + + g_return_val_if_fail (GIMP_IS_CURVE (curve), -1); + + if (max_distance >= 0.0) + distance2 = SQR (max_distance); + + for (i = curve->n_points - 1; i >= 0; i--) + { + gdouble point_distance2; + + point_distance2 = SQR (x - curve->points[i].x) + + SQR (y - curve->points[i].y); + + if (point_distance2 <= distance2) + { + closest_point = i; + distance2 = point_distance2; + } + } return closest_point; } -void -gimp_curve_set_point (GimpCurve *curve, - gint point, +gint +gimp_curve_add_point (GimpCurve *curve, gdouble x, gdouble y) { + GimpCurvePoint *points; + gint point; + + g_return_val_if_fail (GIMP_IS_CURVE (curve), -1); + + if (curve->curve_type == GIMP_CURVE_FREE) + return -1; + + x = CLAMP (x, 0.0, 1.0); + y = CLAMP (y, 0.0, 1.0); + + for (point = 0; point < curve->n_points; point++) + { + if (curve->points[point].x > x) + break; + } + + points = g_new0 (GimpCurvePoint, curve->n_points + 1); + + memcpy (points, curve->points, + point * sizeof (GimpCurvePoint)); + memcpy (points + point + 1, curve->points + point, + (curve->n_points - point) * sizeof (GimpCurvePoint)); + + points[point].x = x; + points[point].y = y; + points[point].type = GIMP_CURVE_POINT_SMOOTH; + + g_free (curve->points); + + curve->n_points++; + curve->points = points; + + g_object_notify (G_OBJECT (curve), "n-points"); + g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); + + gimp_data_dirty (GIMP_DATA (curve)); + + return point; +} + +void +gimp_curve_delete_point (GimpCurve *curve, + gint point) +{ + GimpCurvePoint *points; + g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (point >= 0 && point < curve->n_points); - g_return_if_fail (x == -1.0 || (x >= 0 && x <= 1.0)); - g_return_if_fail (y == -1.0 || (y >= 0 && y <= 1.0)); - if (curve->curve_type == GIMP_CURVE_FREE) - return; + points = g_new0 (GimpCurvePoint, curve->n_points - 1); + + memcpy (points, curve->points, + point * sizeof (GimpCurvePoint)); + memcpy (points + point, curve->points + point + 1, + (curve->n_points - point - 1) * sizeof (GimpCurvePoint)); - curve->points[point].x = x; - curve->points[point].y = y; + g_free (curve->points); + curve->n_points--; + curve->points = points; + + g_object_notify (G_OBJECT (curve), "n-points"); g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); gimp_data_dirty (GIMP_DATA (curve)); } void -gimp_curve_move_point (GimpCurve *curve, - gint point, - gdouble y) +gimp_curve_set_point (GimpCurve *curve, + gint point, + gdouble x, + gdouble y) { g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (point >= 0 && point < curve->n_points); - g_return_if_fail (y >= 0 && y <= 1.0); - if (curve->curve_type == GIMP_CURVE_FREE) - return; + curve->points[point].x = CLAMP (x, 0.0, 1.0); + curve->points[point].y = CLAMP (y, 0.0, 1.0); + + if (point > 0) + curve->points[point].x = MAX (x, curve->points[point - 1].x); - curve->points[point].y = y; + if (point < curve->n_points - 1) + curve->points[point].x = MIN (x, curve->points[point + 1].x); g_object_notify (G_OBJECT (curve), "points"); @@ -803,27 +978,14 @@ } void -gimp_curve_delete_point (GimpCurve *curve, - gint point) +gimp_curve_move_point (GimpCurve *curve, + gint point, + gdouble y) { g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (point >= 0 && point < curve->n_points); - if (point == 0) - { - curve->points[0].x = 0.0; - curve->points[0].y = 0.0; - } - else if (point == curve->n_points - 1) - { - curve->points[curve->n_points - 1].x = 1.0; - curve->points[curve->n_points - 1].y = 1.0; - } - else - { - curve->points[point].x = -1.0; - curve->points[point].y = -1.0; - } + curve->points[point].y = CLAMP (y, 0.0, 1.0); g_object_notify (G_OBJECT (curve), "points"); @@ -839,16 +1001,51 @@ g_return_if_fail (GIMP_IS_CURVE (curve)); g_return_if_fail (point >= 0 && point < curve->n_points); - if (curve->curve_type == GIMP_CURVE_FREE) + if (x) *x = curve->points[point].x; + if (y) *y = curve->points[point].y; +} + +void +gimp_curve_set_point_type (GimpCurve *curve, + gint point, + GimpCurvePointType type) +{ + g_return_if_fail (GIMP_IS_CURVE (curve)); + g_return_if_fail (point >= 0 && point < curve->n_points); + + curve->points[point].type = type; + + g_object_notify (G_OBJECT (curve), "point-types"); + + gimp_data_dirty (GIMP_DATA (curve)); +} + +GimpCurvePointType +gimp_curve_get_point_type (GimpCurve *curve, + gint point) +{ + g_return_val_if_fail (GIMP_IS_CURVE (curve), GIMP_CURVE_POINT_SMOOTH); + g_return_val_if_fail (point >= 0 && point < curve->n_points, GIMP_CURVE_POINT_SMOOTH); + + return curve->points[point].type; +} + +void +gimp_curve_clear_points (GimpCurve *curve) +{ + g_return_if_fail (GIMP_IS_CURVE (curve)); + + if (curve->points) { - if (x) *x = -1.0; - if (y) *y = -1.0; + g_clear_pointer (&curve->points, g_free); + curve->n_points = 0; - return; - } + g_object_notify (G_OBJECT (curve), "n-points"); + g_object_notify (G_OBJECT (curve), "points"); + g_object_notify (G_OBJECT (curve), "point-types"); - if (x) *x = curve->points[point].x; - if (y) *y = curve->points[point].y; + gimp_data_dirty (GIMP_DATA (curve)); + } } void @@ -909,59 +1106,55 @@ static void gimp_curve_calculate (GimpCurve *curve) { - gint *points; - gint i; - gint num_pts; - gint p1, p2, p3, p4; + gint i; + gint p1, p2, p3, p4; if (gimp_data_is_frozen (GIMP_DATA (curve))) return; - points = g_newa (gint, curve->n_points); - switch (curve->curve_type) { case GIMP_CURVE_SMOOTH: - /* cycle through the curves */ - num_pts = 0; - for (i = 0; i < curve->n_points; i++) - if (curve->points[i].x >= 0.0) - points[num_pts++] = i; - /* Initialize boundary curve points */ - if (num_pts != 0) + if (curve->n_points > 0) { - GimpVector2 point; - gint boundary; + GimpCurvePoint point; + gint boundary; - point = curve->points[points[0]]; + point = curve->points[0]; boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1)); for (i = 0; i < boundary; i++) curve->samples[i] = point.y; - point = curve->points[points[num_pts - 1]]; + point = curve->points[curve->n_points - 1]; boundary = ROUND (point.x * (gdouble) (curve->n_samples - 1)); for (i = boundary; i < curve->n_samples; i++) curve->samples[i] = point.y; } - for (i = 0; i < num_pts - 1; i++) + for (i = 0; i < curve->n_points - 1; i++) { - p1 = points[MAX (i - 1, 0)]; - p2 = points[i]; - p3 = points[i + 1]; - p4 = points[MIN (i + 2, num_pts - 1)]; + p1 = MAX (i - 1, 0); + p2 = i; + p3 = i + 1; + p4 = MIN (i + 2, curve->n_points - 1); + + if (curve->points[p2].type == GIMP_CURVE_POINT_CORNER) + p1 = p2; + + if (curve->points[p3].type == GIMP_CURVE_POINT_CORNER) + p4 = p3; gimp_curve_plot (curve, p1, p2, p3, p4); } /* ensure that the control points are used exactly */ - for (i = 0; i < num_pts; i++) + for (i = 0; i < curve->n_points; i++) { - gdouble x = curve->points[points[i]].x; - gdouble y = curve->points[points[i]].y; + gdouble x = curve->points[i].x; + gdouble y = curve->points[i].y; curve->samples[ROUND (x * (gdouble) (curve->n_samples - 1))] = y; } @@ -1013,7 +1206,16 @@ dx = x3 - x0; dy = y3 - y0; - g_return_if_fail (dx > 0); + if (dx <= EPSILON) + { + gint index; + + index = ROUND (x0 * (gdouble) (curve->n_samples - 1)); + + curve->samples[index] = y3; + + return; + } if (p1 == p2 && p3 == p4) { @@ -1061,7 +1263,7 @@ /* * finally calculate the y(t) values for the given bezier values. We can - * use homogenously distributed values for t, since x(t) increases linearly. + * use homogeneously distributed values for t, since x(t) increases linearly. */ for (i = 0; i <= ROUND (dx * (gdouble) (curve->n_samples - 1)); i++) { diff -Nru gimp-2.10.8+zorin2/app/core/gimpcurve.h gimp-2.10.14+om/app/core/gimpcurve.h --- gimp-2.10.8+zorin2/app/core/gimpcurve.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpcurve.h 2019-06-12 16:43:38.000000000 +0000 @@ -30,21 +30,30 @@ #define GIMP_CURVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CURVE, GimpCurveClass)) +typedef struct _GimpCurvePoint GimpCurvePoint; typedef struct _GimpCurveClass GimpCurveClass; +struct _GimpCurvePoint +{ + gdouble x; + gdouble y; + + GimpCurvePointType type; +}; + struct _GimpCurve { - GimpData parent_instance; + GimpData parent_instance; - GimpCurveType curve_type; + GimpCurveType curve_type; - gint n_points; - GimpVector2 *points; + gint n_points; + GimpCurvePoint *points; - gint n_samples; - gdouble *samples; + gint n_samples; + gdouble *samples; - gboolean identity; /* whether the curve is an identity mapping */ + gboolean identity; /* whether the curve is an identity mapping */ }; struct _GimpCurveClass @@ -53,52 +62,63 @@ }; -GType gimp_curve_get_type (void) G_GNUC_CONST; +GType gimp_curve_get_type (void) G_GNUC_CONST; -GimpData * gimp_curve_new (const gchar *name); -GimpData * gimp_curve_get_standard (void); +GimpData * gimp_curve_new (const gchar *name); +GimpData * gimp_curve_get_standard (void); -void gimp_curve_reset (GimpCurve *curve, - gboolean reset_type); +void gimp_curve_reset (GimpCurve *curve, + gboolean reset_type); -void gimp_curve_set_curve_type (GimpCurve *curve, - GimpCurveType curve_type); -GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve); - -void gimp_curve_set_n_points (GimpCurve *curve, - gint n_points); -gint gimp_curve_get_n_points (GimpCurve *curve); - -void gimp_curve_set_n_samples (GimpCurve *curve, - gint n_samples); -gint gimp_curve_get_n_samples (GimpCurve *curve); - -gint gimp_curve_get_closest_point (GimpCurve *curve, - gdouble x); - -void gimp_curve_set_point (GimpCurve *curve, - gint point, - gdouble x, - gdouble y); -void gimp_curve_move_point (GimpCurve *curve, - gint point, - gdouble y); -void gimp_curve_delete_point (GimpCurve *curve, - gint point); -void gimp_curve_get_point (GimpCurve *curve, - gint point, - gdouble *x, - gdouble *y); - -void gimp_curve_set_curve (GimpCurve *curve, - gdouble x, - gdouble y); - -gboolean gimp_curve_is_identity (GimpCurve *curve); - -void gimp_curve_get_uchar (GimpCurve *curve, - gint n_samples, - guchar *samples); +void gimp_curve_set_curve_type (GimpCurve *curve, + GimpCurveType curve_type); +GimpCurveType gimp_curve_get_curve_type (GimpCurve *curve); + +gint gimp_curve_get_n_points (GimpCurve *curve); + +void gimp_curve_set_n_samples (GimpCurve *curve, + gint n_samples); +gint gimp_curve_get_n_samples (GimpCurve *curve); + +gint gimp_curve_get_point_at (GimpCurve *curve, + gdouble x); +gint gimp_curve_get_closest_point (GimpCurve *curve, + gdouble x, + gdouble y, + gdouble max_distance); + +gint gimp_curve_add_point (GimpCurve *curve, + gdouble x, + gdouble y); +void gimp_curve_delete_point (GimpCurve *curve, + gint point); +void gimp_curve_set_point (GimpCurve *curve, + gint point, + gdouble x, + gdouble y); +void gimp_curve_move_point (GimpCurve *curve, + gint point, + gdouble y); +void gimp_curve_get_point (GimpCurve *curve, + gint point, + gdouble *x, + gdouble *y); +void gimp_curve_set_point_type (GimpCurve *curve, + gint point, + GimpCurvePointType type); +GimpCurvePointType gimp_curve_get_point_type (GimpCurve *curve, + gint point); +void gimp_curve_clear_points (GimpCurve *curve); + +void gimp_curve_set_curve (GimpCurve *curve, + gdouble x, + gdouble y); + +gboolean gimp_curve_is_identity (GimpCurve *curve); + +void gimp_curve_get_uchar (GimpCurve *curve, + gint n_samples, + guchar *samples); #endif /* __GIMP_CURVE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpdata.c gimp-2.10.14+om/app/core/gimpdata.c --- gimp-2.10.8+zorin2/app/core/gimpdata.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdata.c 2019-10-26 18:49:18.000000000 +0000 @@ -52,8 +52,6 @@ }; -typedef struct _GimpDataPrivate GimpDataPrivate; - struct _GimpDataPrivate { GFile *file; @@ -73,16 +71,11 @@ GList *tags; }; -#define GIMP_DATA_GET_PRIVATE(data) \ - G_TYPE_INSTANCE_GET_PRIVATE (data, GIMP_TYPE_DATA, GimpDataPrivate) +#define GIMP_DATA_GET_PRIVATE(obj) (((GimpData *) (obj))->priv) -static void gimp_data_class_init (GimpDataClass *klass); static void gimp_data_tagged_iface_init (GimpTaggedInterface *iface); -static void gimp_data_init (GimpData *data, - GimpDataClass *data_class); - static void gimp_data_constructed (GObject *object); static void gimp_data_finalize (GObject *object); static void gimp_data_set_property (GObject *object, @@ -114,47 +107,15 @@ static gchar * gimp_data_get_checksum (GimpTagged *tagged); -static guint data_signals[LAST_SIGNAL] = { 0 }; - -static GimpViewableClass *parent_class = NULL; - - -GType -gimp_data_get_type (void) -{ - static GType data_type = 0; +G_DEFINE_TYPE_WITH_CODE (GimpData, gimp_data, GIMP_TYPE_VIEWABLE, + G_ADD_PRIVATE (GimpData) + G_IMPLEMENT_INTERFACE (GIMP_TYPE_TAGGED, + gimp_data_tagged_iface_init)) - if (! data_type) - { - const GTypeInfo data_info = - { - sizeof (GimpDataClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_data_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpData), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_data_init, - }; - - const GInterfaceInfo tagged_info = - { - (GInterfaceInitFunc) gimp_data_tagged_iface_init, - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - data_type = g_type_register_static (GIMP_TYPE_VIEWABLE, - "GimpData", - &data_info, 0); +#define parent_class gimp_data_parent_class - g_type_add_interface_static (data_type, GIMP_TYPE_TAGGED, &tagged_info); - } +static guint data_signals[LAST_SIGNAL] = { 0 }; - return data_type; -} static void gimp_data_class_init (GimpDataClass *klass) @@ -212,8 +173,6 @@ NULL, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (GimpDataPrivate)); } static void @@ -227,21 +186,16 @@ } static void -gimp_data_init (GimpData *data, - GimpDataClass *data_class) +gimp_data_init (GimpData *data) { - GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (data); + GimpDataPrivate *private = gimp_data_get_instance_private (data); + + data->priv = private; private->writable = TRUE; private->deletable = TRUE; private->dirty = TRUE; - /* look at the passed class pointer, not at GIMP_DATA_GET_CLASS(data) - * here, because the latter is always GimpDataClass itself - */ - if (! data_class->save) - private->writable = FALSE; - /* freeze the data object during construction */ gimp_data_freeze (data); } @@ -249,8 +203,13 @@ static void gimp_data_constructed (GObject *object) { + GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object); + G_OBJECT_CLASS (parent_class)->constructed (object); + if (! GIMP_DATA_GET_CLASS (object)->save) + private->writable = FALSE; + gimp_data_thaw (GIMP_DATA (object)); } @@ -592,17 +551,25 @@ success = FALSE; } } - else if (error && *error) - { - g_prefix_error (error, - _("Error saving '%s': "), - gimp_file_get_utf8_name (private->file)); - } else { - g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, - _("Error saving '%s'"), - gimp_file_get_utf8_name (private->file)); + GCancellable *cancellable = g_cancellable_new (); + + g_cancellable_cancel (cancellable); + if (error && *error) + { + g_prefix_error (error, + _("Error saving '%s': "), + gimp_file_get_utf8_name (private->file)); + } + else + { + g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, + _("Error saving '%s'"), + gimp_file_get_utf8_name (private->file)); + } + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); } g_object_unref (output); diff -Nru gimp-2.10.8+zorin2/app/core/gimp-data-factories.c gimp-2.10.14+om/app/core/gimp-data-factories.c --- gimp-2.10.8+zorin2/app/core/gimp-data-factories.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-data-factories.c 2019-04-07 11:38:14.000000000 +0000 @@ -77,7 +77,7 @@ "GIMP Brush", gimp_brush_load, GIMP_BRUSH_FILE_EXTENSION, - FALSE); + TRUE); gimp_data_loader_factory_add_loader (gimp->brush_factory, "GIMP Brush Pixmap", gimp_brush_load, @@ -102,7 +102,7 @@ "GIMP Brush Pipe", gimp_brush_pipe_load, GIMP_BRUSH_PIPE_FILE_EXTENSION, - FALSE); + TRUE); gimp->dynamics_factory = gimp_data_loader_factory_new (gimp, @@ -147,7 +147,7 @@ "GIMP Pattern", gimp_pattern_load, GIMP_PATTERN_FILE_EXTENSION, - FALSE); + TRUE); gimp_data_loader_factory_add_fallback (gimp->pattern_factory, "Pattern from GdkPixbuf", gimp_pattern_load_pixbuf); diff -Nru gimp-2.10.8+zorin2/app/core/gimpdata.h gimp-2.10.14+om/app/core/gimpdata.h --- gimp-2.10.8+zorin2/app/core/gimpdata.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdata.h 2019-10-26 18:49:18.000000000 +0000 @@ -42,11 +42,14 @@ #define GIMP_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DATA, GimpDataClass)) -typedef struct _GimpDataClass GimpDataClass; +typedef struct _GimpDataPrivate GimpDataPrivate; +typedef struct _GimpDataClass GimpDataClass; struct _GimpData { - GimpViewable parent_instance; + GimpViewable parent_instance; + + GimpDataPrivate *priv; }; struct _GimpDataClass diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-bucket-fill.c gimp-2.10.14+om/app/core/gimpdrawable-bucket-fill.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-bucket-fill.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-bucket-fill.c 2019-10-26 18:49:18.000000000 +0000 @@ -18,6 +18,7 @@ #include "config.h" #include +#define GEGL_ITERATOR2_API #include #include @@ -58,52 +59,170 @@ gdouble seed_x, gdouble seed_y) { + GimpImage *image; + GeglBuffer *buffer; + gdouble mask_x; + gdouble mask_y; + gint width, height; + + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + gimp_set_busy (image->gimp); + + buffer = gimp_drawable_get_bucket_fill_buffer (drawable, options, + fill_transparent, fill_criterion, + threshold, FALSE, sample_merged, + diagonal_neighbors, + seed_x, seed_y, NULL, + &mask_x, &mask_y, &width, &height); + + if (buffer) + { + /* Apply it to the image */ + gimp_drawable_apply_buffer (drawable, buffer, + GEGL_RECTANGLE (0, 0, width, height), + TRUE, C_("undo-type", "Bucket Fill"), + gimp_context_get_opacity (GIMP_CONTEXT (options)), + gimp_context_get_paint_mode (GIMP_CONTEXT (options)), + GIMP_LAYER_COLOR_SPACE_AUTO, + GIMP_LAYER_COLOR_SPACE_AUTO, + gimp_layer_mode_get_paint_composite_mode + (gimp_context_get_paint_mode (GIMP_CONTEXT (options))), + NULL, (gint) mask_x, mask_y); + g_object_unref (buffer); + + gimp_drawable_update (drawable, mask_x, mask_y, width, height); + } + + gimp_unset_busy (image->gimp); +} + +/** + * gimp_drawable_get_bucket_fill_buffer: + * @drawable: the #GimpDrawable to edit. + * @options: + * @fill_transparent: + * @fill_criterion: + * @threshold: + * @show_all: + * @sample_merged: + * @diagonal_neighbors: + * @seed_x: X coordinate to start the fill. + * @seed_y: Y coordinate to start the fill. + * @mask_buffer: mask of the fill in-progress when in an interactive + * filling process. Set to NULL if you need a one-time + * fill. + * @mask_x: returned x bound of @mask_buffer. + * @mask_y: returned x bound of @mask_buffer. + * @mask_width: returned width bound of @mask_buffer. + * @mask_height: returned height bound of @mask_buffer. + * + * Creates the fill buffer for a bucket fill operation on @drawable, + * without actually applying it (if you want to apply it directly as a + * one-time operation, use gimp_drawable_bucket_fill() instead). If + * @mask_buffer is not NULL, the intermediate fill mask will also be + * returned. This fill mask can later be reused in successive calls to + * gimp_drawable_get_bucket_fill_buffer() for interactive filling. + * + * Returns: a fill buffer which can be directly applied to @drawable, or + * used in a drawable filter as preview. + */ +GeglBuffer * +gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawable, + GimpFillOptions *options, + gboolean fill_transparent, + GimpSelectCriterion fill_criterion, + gdouble threshold, + gboolean show_all, + gboolean sample_merged, + gboolean diagonal_neighbors, + gdouble seed_x, + gdouble seed_y, + GeglBuffer **mask_buffer, + gdouble *mask_x, + gdouble *mask_y, + gint *mask_width, + gint *mask_height) +{ GimpImage *image; GimpPickable *pickable; GeglBuffer *buffer; - GeglBuffer *mask_buffer; + GeglBuffer *new_mask; gboolean antialias; gint x, y, width, height; gint mask_offset_x = 0; gint mask_offset_y = 0; gint sel_x, sel_y, sel_width, sel_height; - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); - g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &sel_x, &sel_y, &sel_width, &sel_height)) - return; + return NULL; + + if (mask_buffer && *mask_buffer && threshold == 0.0) + { + gfloat pixel; + + gegl_buffer_sample (*mask_buffer, seed_x, seed_y, NULL, &pixel, + babl_format ("Y float"), + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (pixel != 0.0) + /* Already selected. This seed won't change the selection. */ + return NULL; + } gimp_set_busy (image->gimp); if (sample_merged) - pickable = GIMP_PICKABLE (image); + { + if (! show_all) + pickable = GIMP_PICKABLE (image); + else + pickable = GIMP_PICKABLE (gimp_image_get_projection (image)); + } else - pickable = GIMP_PICKABLE (drawable); + { + pickable = GIMP_PICKABLE (drawable); + } antialias = gimp_fill_options_get_antialias (options); /* Do a seed bucket fill...To do this, calculate a new * contiguous region. */ - mask_buffer = gimp_pickable_contiguous_region_by_seed (pickable, - antialias, - threshold, - fill_transparent, - fill_criterion, - diagonal_neighbors, - (gint) seed_x, - (gint) seed_y); + new_mask = gimp_pickable_contiguous_region_by_seed (pickable, + antialias, + threshold, + fill_transparent, + fill_criterion, + diagonal_neighbors, + (gint) seed_x, + (gint) seed_y); + if (mask_buffer && *mask_buffer) + { + gimp_gegl_mask_combine_buffer (new_mask, *mask_buffer, + GIMP_CHANNEL_OP_ADD, 0, 0); + g_object_unref (*mask_buffer); + } + + if (mask_buffer) + *mask_buffer = new_mask; - gimp_gegl_mask_bounds (mask_buffer, &x, &y, &width, &height); + gimp_gegl_mask_bounds (new_mask, &x, &y, &width, &height); width -= x; height -= y; - /* If there is a selection, inersect the region bounds + /* If there is a selection, intersect the region bounds * with the selection bounds, to avoid processing areas * that are going to be masked out anyway. The actual * intersection of the fill region with the mask data @@ -127,11 +246,189 @@ { /* The fill region and the selection are disjoint; bail. */ - g_object_unref (mask_buffer); + if (! mask_buffer) + g_object_unref (new_mask); + + gimp_unset_busy (image->gimp); + + return NULL; + } + } + + /* make sure we handle the mask correctly if it was sample-merged */ + if (sample_merged) + { + GimpItem *item = GIMP_ITEM (drawable); + gint off_x, off_y; + + /* Limit the channel bounds to the drawable's extents */ + gimp_item_get_offset (item, &off_x, &off_y); + + gimp_rectangle_intersect (x, y, width, height, + + off_x, off_y, + gimp_item_get_width (item), + gimp_item_get_height (item), + + &x, &y, &width, &height); + + mask_offset_x = x; + mask_offset_y = y; + + /* translate mask bounds to drawable coords */ + x -= off_x; + y -= off_y; + } + else + { + mask_offset_x = x; + mask_offset_y = y; + } + + buffer = gimp_fill_options_create_buffer (options, drawable, + GEGL_RECTANGLE (0, 0, + width, height), + -x, -y); + + gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer, new_mask, + -mask_offset_x, -mask_offset_y, 1.0); + + if (mask_x) + *mask_x = x; + if (mask_y) + *mask_y = y; + if (mask_width) + *mask_width = width; + if (mask_height) + *mask_height = height; + + if (! mask_buffer) + g_object_unref (new_mask); + + gimp_unset_busy (image->gimp); + + return buffer; +} + +/** + * gimp_drawable_get_line_art_fill_buffer: + * @drawable: the #GimpDrawable to edit. + * @line_art: the #GimpLineArt computed as fill source. + * @options: the #GimpFillOptions. + * @sample_merged: + * @seed_x: X coordinate to start the fill. + * @seed_y: Y coordinate to start the fill. + * @mask_buffer: mask of the fill in-progress when in an interactive + * filling process. Set to NULL if you need a one-time + * fill. + * @mask_x: returned x bound of @mask_buffer. + * @mask_y: returned x bound of @mask_buffer. + * @mask_width: returned width bound of @mask_buffer. + * @mask_height: returned height bound of @mask_buffer. + * + * Creates the fill buffer for a bucket fill operation on @drawable + * based on @line_art and @options, without actually applying it. + * If @mask_buffer is not NULL, the intermediate fill mask will also be + * returned. This fill mask can later be reused in successive calls to + * gimp_drawable_get_bucket_fill_buffer() for interactive filling. + * + * Returns: a fill buffer which can be directly applied to @drawable, or + * used in a drawable filter as preview. + */ +GeglBuffer * +gimp_drawable_get_line_art_fill_buffer (GimpDrawable *drawable, + GimpLineArt *line_art, + GimpFillOptions *options, + gboolean sample_merged, + gdouble seed_x, + gdouble seed_y, + GeglBuffer **mask_buffer, + gdouble *mask_x, + gdouble *mask_y, + gint *mask_width, + gint *mask_height) +{ + GimpImage *image; + GeglBuffer *buffer; + GeglBuffer *new_mask; + gint x, y, width, height; + gint mask_offset_x = 0; + gint mask_offset_y = 0; + gint sel_x, sel_y, sel_width, sel_height; + gdouble feather_radius; + + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL); + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), + &sel_x, &sel_y, &sel_width, &sel_height)) + return NULL; + + if (mask_buffer && *mask_buffer) + { + gfloat pixel; + gegl_buffer_sample (*mask_buffer, seed_x, seed_y, NULL, &pixel, + babl_format ("Y float"), + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (pixel != 0.0) + /* Already selected. This seed won't change the selection. */ + return NULL; + } + + gimp_set_busy (image->gimp); + + /* Do a seed bucket fill...To do this, calculate a new + * contiguous region. + */ + new_mask = gimp_pickable_contiguous_region_by_line_art (NULL, line_art, + (gint) seed_x, + (gint) seed_y); + if (mask_buffer && *mask_buffer) + { + gimp_gegl_mask_combine_buffer (new_mask, *mask_buffer, + GIMP_CHANNEL_OP_ADD, 0, 0); + g_object_unref (*mask_buffer); + } + if (mask_buffer) + *mask_buffer = new_mask; + + gimp_gegl_mask_bounds (new_mask, &x, &y, &width, &height); + width -= x; + height -= y; + + /* If there is a selection, intersect the region bounds + * with the selection bounds, to avoid processing areas + * that are going to be masked out anyway. The actual + * intersection of the fill region with the mask data + * happens when combining the fill buffer, in + * gimp_drawable_apply_buffer(). + */ + if (! gimp_channel_is_empty (gimp_image_get_mask (image))) + { + gint off_x = 0; + gint off_y = 0; + + if (sample_merged) + gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); + + if (! gimp_rectangle_intersect (x, y, width, height, + + sel_x + off_x, sel_y + off_y, + sel_width, sel_height, + + &x, &y, &width, &height)) + { + if (! mask_buffer) + g_object_unref (new_mask); + /* The fill region and the selection are disjoint; bail. */ gimp_unset_busy (image->gimp); - return; + return NULL; } } @@ -155,7 +452,7 @@ mask_offset_x = x; mask_offset_y = y; - /* translate mask bounds to drawable coords */ + /* translate mask bounds to drawable coords */ x -= off_x; y -= off_y; } @@ -170,28 +467,33 @@ width, height), -x, -y); - gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer, - mask_buffer, - -mask_offset_x, - -mask_offset_y, - 1.0); - g_object_unref (mask_buffer); - - /* Apply it to the image */ - gimp_drawable_apply_buffer (drawable, buffer, - GEGL_RECTANGLE (0, 0, width, height), - TRUE, C_("undo-type", "Bucket Fill"), - gimp_context_get_opacity (GIMP_CONTEXT (options)), - gimp_context_get_paint_mode (GIMP_CONTEXT (options)), - GIMP_LAYER_COLOR_SPACE_AUTO, - GIMP_LAYER_COLOR_SPACE_AUTO, - gimp_layer_mode_get_paint_composite_mode ( - gimp_context_get_paint_mode (GIMP_CONTEXT (options))), - NULL, x, y); + gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer, new_mask, + -mask_offset_x, -mask_offset_y, 1.0); - g_object_unref (buffer); + if (gimp_fill_options_get_feather (options, &feather_radius)) + { + /* Feathering for the line art algorithm is not applied during + * mask creation because we just want to apply it on the borders + * of the mask at the end (since the mask can evolve, we don't + * want to actually touch it, but only the intermediate results). + */ + gimp_gegl_apply_feather (buffer, NULL, NULL, buffer, NULL, + feather_radius, feather_radius, TRUE); + } + + if (mask_x) + *mask_x = x; + if (mask_y) + *mask_y = y; + if (mask_width) + *mask_width = width; + if (mask_height) + *mask_height = height; - gimp_drawable_update (drawable, x, y, width, height); + if (! mask_buffer) + g_object_unref (new_mask); gimp_unset_busy (image->gimp); + + return buffer; } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-bucket-fill.h gimp-2.10.14+om/app/core/gimpdrawable-bucket-fill.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable-bucket-fill.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-bucket-fill.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,15 +19,41 @@ #define __GIMP_DRAWABLE_BUCKET_FILL_H__ -void gimp_drawable_bucket_fill (GimpDrawable *drawable, - GimpFillOptions *options, - gboolean fill_transparent, - GimpSelectCriterion fill_criterion, - gdouble threshold, - gboolean sample_merged, - gboolean diagonal_neighbors, - gdouble x, - gdouble y); +void gimp_drawable_bucket_fill (GimpDrawable *drawable, + GimpFillOptions *options, + gboolean fill_transparent, + GimpSelectCriterion fill_criterion, + gdouble threshold, + gboolean sample_merged, + gboolean diagonal_neighbors, + gdouble x, + gdouble y); +GeglBuffer * gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawable, + GimpFillOptions *options, + gboolean fill_transparent, + GimpSelectCriterion fill_criterion, + gdouble threshold, + gboolean show_all, + gboolean sample_merged, + gboolean diagonal_neighbors, + gdouble seed_x, + gdouble seed_y, + GeglBuffer **mask_buffer, + gdouble *mask_x, + gdouble *mask_y, + gint *mask_width, + gint *mask_height); +GeglBuffer * gimp_drawable_get_line_art_fill_buffer (GimpDrawable *drawable, + GimpLineArt *line_art, + GimpFillOptions *options, + gboolean sample_merged, + gdouble seed_x, + gdouble seed_y, + GeglBuffer **mask_buffer, + gdouble *mask_x, + gdouble *mask_y, + gint *mask_width, + gint *mask_height); #endif /* __GIMP_DRAWABLE_BUCKET_FILL_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable.c gimp-2.10.14+om/app/core/gimpdrawable.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable.c 2019-10-26 18:49:18.000000000 +0000 @@ -56,17 +56,16 @@ #include "gimp-intl.h" -#define PAINT_COPY_CHUNK_WIDTH 128 -#define PAINT_COPY_CHUNK_HEIGHT 128 - -#define PAINT_UPDATE_CHUNK_WIDTH 32 -#define PAINT_UPDATE_CHUNK_HEIGHT 32 +#define PAINT_UPDATE_CHUNK_WIDTH 32 +#define PAINT_UPDATE_CHUNK_HEIGHT 32 enum { UPDATE, + FORMAT_CHANGED, ALPHA_CHANGED, + BOUNDING_BOX_CHANGED, LAST_SIGNAL }; @@ -99,6 +98,8 @@ static gboolean gimp_drawable_get_size (GimpViewable *viewable, gint *width, gint *height); +static void gimp_drawable_preview_freeze (GimpViewable *viewable); +static void gimp_drawable_preview_thaw (GimpViewable *viewable); static GeglNode * gimp_drawable_get_node (GimpFilter *filter); @@ -166,6 +167,11 @@ gint width, gint height); +static void gimp_drawable_real_update_all (GimpDrawable *drawable); + +static GimpComponentMask + gimp_drawable_real_get_active_mask (GimpDrawable *drawable); + static void gimp_drawable_real_convert_type (GimpDrawable *drawable, GimpImage *dest_image, const Babl *new_format, @@ -180,8 +186,10 @@ gboolean push_undo, const gchar *undo_desc, GeglBuffer *buffer, - gint offset_x, - gint offset_y); + const GeglRectangle *bounds); + +static GeglRectangle gimp_drawable_real_get_bounding_box + (GimpDrawable *drawable); static void gimp_drawable_real_push_undo (GimpDrawable *drawable, const gchar *undo_desc, @@ -196,6 +204,9 @@ gint y); static GeglNode * gimp_drawable_real_get_source_node (GimpDrawable *drawable); +static void gimp_drawable_format_changed (GimpDrawable *drawable); +static void gimp_drawable_alpha_changed (GimpDrawable *drawable); + G_DEFINE_TYPE_WITH_CODE (GimpDrawable, gimp_drawable, GIMP_TYPE_ITEM, G_ADD_PRIVATE (GimpDrawable) @@ -231,6 +242,15 @@ G_TYPE_INT, G_TYPE_INT); + gimp_drawable_signals[FORMAT_CHANGED] = + g_signal_new ("format-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpDrawableClass, format_changed), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + gimp_drawable_signals[ALPHA_CHANGED] = g_signal_new ("alpha-changed", G_TYPE_FROM_CLASS (klass), @@ -240,6 +260,15 @@ gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); + gimp_drawable_signals[BOUNDING_BOX_CHANGED] = + g_signal_new ("bounding-box-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpDrawableClass, bounding_box_changed), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + object_class->dispose = gimp_drawable_dispose; object_class->finalize = gimp_drawable_finalize; object_class->set_property = gimp_drawable_set_property; @@ -250,6 +279,8 @@ viewable_class->get_size = gimp_drawable_get_size; viewable_class->get_new_preview = gimp_drawable_get_new_preview; viewable_class->get_new_pixbuf = gimp_drawable_get_new_pixbuf; + viewable_class->preview_freeze = gimp_drawable_preview_freeze; + viewable_class->preview_thaw = gimp_drawable_preview_thaw; filter_class->get_node = gimp_drawable_get_node; @@ -262,16 +293,19 @@ item_class->transform = gimp_drawable_transform; klass->update = gimp_drawable_real_update; + klass->format_changed = NULL; klass->alpha_changed = NULL; + klass->bounding_box_changed = NULL; klass->estimate_memsize = gimp_drawable_real_estimate_memsize; + klass->update_all = gimp_drawable_real_update_all; klass->invalidate_boundary = NULL; klass->get_active_components = NULL; - klass->get_active_mask = NULL; + klass->get_active_mask = gimp_drawable_real_get_active_mask; klass->convert_type = gimp_drawable_real_convert_type; klass->apply_buffer = gimp_drawable_real_apply_buffer; - klass->replace_buffer = gimp_drawable_real_replace_buffer; klass->get_buffer = gimp_drawable_real_get_buffer; klass->set_buffer = gimp_drawable_real_set_buffer; + klass->get_bounding_box = gimp_drawable_real_get_bounding_box; klass->push_undo = gimp_drawable_real_push_undo; klass->swap_pixels = gimp_drawable_real_swap_pixels; klass->get_source_node = gimp_drawable_real_get_source_node; @@ -400,6 +434,30 @@ return TRUE; } +static void +gimp_drawable_preview_freeze (GimpViewable *viewable) +{ + GimpViewable *parent = gimp_viewable_get_parent (viewable); + + if (! parent && gimp_item_is_attached (GIMP_ITEM (viewable))) + parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable))); + + if (parent) + gimp_viewable_preview_freeze (parent); +} + +static void +gimp_drawable_preview_thaw (GimpViewable *viewable) +{ + GimpViewable *parent = gimp_viewable_get_parent (viewable); + + if (! parent && gimp_item_is_attached (GIMP_ITEM (viewable))) + parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (viewable))); + + if (parent) + gimp_viewable_preview_thaw (parent); +} + static GeglNode * gimp_drawable_get_node (GimpFilter *filter) { @@ -455,7 +513,7 @@ GimpDrawable *new_drawable = GIMP_DRAWABLE (new_item); GeglBuffer *new_buffer; - new_buffer = gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); + new_buffer = gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); gimp_drawable_set_buffer (new_drawable, FALSE, NULL, new_buffer); g_object_unref (new_buffer); @@ -491,7 +549,8 @@ gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL, new_buffer, - new_offset_x, new_offset_y, + GEGL_RECTANGLE (new_offset_x, new_offset_y, + 0, 0), TRUE); g_object_unref (new_buffer); } @@ -570,7 +629,8 @@ gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL, new_buffer, - new_offset_x, new_offset_y, + GEGL_RECTANGLE (new_offset_x, new_offset_y, + 0, 0), TRUE); g_object_unref (new_buffer); } @@ -757,6 +817,19 @@ return (gint64) babl_format_get_bytes_per_pixel (format) * width * height; } +static void +gimp_drawable_real_update_all (GimpDrawable *drawable) +{ + gimp_drawable_update (drawable, 0, 0, -1, -1); +} + +static GimpComponentMask +gimp_drawable_real_get_active_mask (GimpDrawable *drawable) +{ + /* Return all, because that skips the component mask op when painting */ + return GIMP_COMPONENT_MASK_ALL; +} + /* FIXME: this default impl is currently unused because no subclass * chains up. the goal is to handle the almost identical subclass code * here again. @@ -794,15 +867,15 @@ } static void -gimp_drawable_real_set_buffer (GimpDrawable *drawable, - gboolean push_undo, - const gchar *undo_desc, - GeglBuffer *buffer, - gint offset_x, - gint offset_y) -{ - GimpItem *item = GIMP_ITEM (drawable); - gint old_has_alpha = -1; +gimp_drawable_real_set_buffer (GimpDrawable *drawable, + gboolean push_undo, + const gchar *undo_desc, + GeglBuffer *buffer, + const GeglRectangle *bounds) +{ + GimpItem *item = GIMP_ITEM (drawable); + const Babl *old_format = NULL; + gint old_has_alpha = -1; g_object_freeze_notify (G_OBJECT (drawable)); @@ -813,7 +886,10 @@ drawable, FALSE); if (drawable->private->buffer) - old_has_alpha = gimp_drawable_has_alpha (drawable); + { + old_format = gimp_drawable_get_format (drawable); + old_has_alpha = gimp_drawable_has_alpha (drawable); + } g_set_object (&drawable->private->buffer, buffer); @@ -822,25 +898,17 @@ "buffer", gimp_drawable_get_buffer (drawable), NULL); - if (drawable->private->convert_format) - { - const Babl *format = gimp_drawable_get_format (drawable); + gimp_item_set_offset (item, bounds->x, bounds->y); + gimp_item_set_size (item, + bounds->width ? bounds->width : + gegl_buffer_get_width (buffer), + bounds->height ? bounds->height : + gegl_buffer_get_height (buffer)); - if (babl_format_is_palette (format)) - gegl_node_set (drawable->private->convert_format, - "operation", "gegl:convert-format", - "format", gimp_drawable_get_format (drawable), - NULL); - else - gegl_node_set (drawable->private->convert_format, - "operation", "gegl:nop", - NULL); - } + gimp_drawable_update_bounding_box (drawable); - gimp_item_set_offset (item, offset_x, offset_y); - gimp_item_set_size (item, - gegl_buffer_get_width (buffer), - gegl_buffer_get_height (buffer)); + if (gimp_drawable_get_format (drawable) != old_format) + gimp_drawable_format_changed (drawable); if (gimp_drawable_has_alpha (drawable) != old_has_alpha) gimp_drawable_alpha_changed (drawable); @@ -850,6 +918,20 @@ g_object_thaw_notify (G_OBJECT (drawable)); } +static GeglRectangle +gimp_drawable_real_get_bounding_box (GimpDrawable *drawable) +{ + GimpItem *item = GIMP_ITEM (drawable); + GeglRectangle bounding_box; + + bounding_box.x = 0; + bounding_box.y = 0; + bounding_box.width = gimp_item_get_width (item); + bounding_box.height = gimp_item_get_height (item); + + return bounding_box; +} + static void gimp_drawable_real_push_undo (GimpDrawable *drawable, const gchar *undo_desc, @@ -859,14 +941,30 @@ gint width, gint height) { + GimpImage *image; + if (! buffer) { + GeglBuffer *drawable_buffer = gimp_drawable_get_buffer (drawable); + GeglRectangle drawable_rect; + + gegl_rectangle_align_to_buffer ( + &drawable_rect, + GEGL_RECTANGLE (x, y, width, height), + drawable_buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + x = drawable_rect.x; + y = drawable_rect.y; + width = drawable_rect.width; + height = drawable_rect.height; + buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), gimp_drawable_get_format (drawable)); gimp_gegl_buffer_copy ( - gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (x, y, width, height), GEGL_ABYSS_NONE, + drawable_buffer, + &drawable_rect, GEGL_ABYSS_NONE, buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } @@ -875,7 +973,9 @@ g_object_ref (buffer); } - gimp_image_undo_push_drawable (gimp_item_get_image (GIMP_ITEM (drawable)), + image = gimp_item_get_image (GIMP_ITEM (drawable)); + + gimp_image_undo_push_drawable (image, undo_desc, drawable, buffer, x, y); @@ -892,7 +992,7 @@ gint width = gegl_buffer_get_width (buffer); gint height = gegl_buffer_get_height (buffer); - tmp = gegl_buffer_dup (buffer); + tmp = gimp_gegl_buffer_dup (buffer); gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), GEGL_RECTANGLE (x, y, width, height), GEGL_ABYSS_NONE, @@ -922,6 +1022,18 @@ return g_object_ref (drawable->private->buffer_source_node); } +static void +gimp_drawable_format_changed (GimpDrawable *drawable) +{ + g_signal_emit (drawable, gimp_drawable_signals[FORMAT_CHANGED], 0); +} + +static void +gimp_drawable_alpha_changed (GimpDrawable *drawable) +{ + g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0); +} + /* public functions */ @@ -978,11 +1090,25 @@ { g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - if (width == -1) - width = gimp_item_get_width (GIMP_ITEM (drawable)); + if (width < 0) + { + GeglRectangle bounding_box; + + bounding_box = gimp_drawable_get_bounding_box (drawable); + + x = bounding_box.x; + width = bounding_box.width; + } + + if (height < 0) + { + GeglRectangle bounding_box; - if (height == -1) - height = gimp_item_get_height (GIMP_ITEM (drawable)); + bounding_box = gimp_drawable_get_bounding_box (drawable); + + y = bounding_box.y; + height = bounding_box.height; + } if (drawable->private->paint_count == 0) { @@ -993,58 +1119,60 @@ { GeglRectangle rect; - rect.x = floor ((gdouble) x / PAINT_COPY_CHUNK_WIDTH) * PAINT_COPY_CHUNK_WIDTH; - rect.y = floor ((gdouble) y / PAINT_COPY_CHUNK_HEIGHT) * PAINT_COPY_CHUNK_HEIGHT; - rect.width = ceil ((gdouble) (x + width) / PAINT_COPY_CHUNK_WIDTH) * PAINT_COPY_CHUNK_WIDTH - rect.x; - rect.height = ceil ((gdouble) (y + height) / PAINT_COPY_CHUNK_HEIGHT) * PAINT_COPY_CHUNK_HEIGHT - rect.y; - if (gegl_rectangle_intersect ( &rect, - &rect, + GEGL_RECTANGLE (x, y, width, height), GEGL_RECTANGLE (0, 0, gimp_item_get_width (GIMP_ITEM (drawable)), gimp_item_get_height (GIMP_ITEM (drawable))))) { + GeglRectangle aligned_rect; + + gegl_rectangle_align_to_buffer (&aligned_rect, &rect, + gimp_drawable_get_buffer (drawable), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + if (drawable->private->paint_copy_region) { cairo_region_union_rectangle ( drawable->private->paint_copy_region, - (const cairo_rectangle_int_t *) &rect); + (const cairo_rectangle_int_t *) &aligned_rect); } else { drawable->private->paint_copy_region = cairo_region_create_rectangle ( - (const cairo_rectangle_int_t *) &rect); + (const cairo_rectangle_int_t *) &aligned_rect); } - rect.x = floor ((gdouble) x / PAINT_UPDATE_CHUNK_WIDTH) * PAINT_UPDATE_CHUNK_WIDTH; - rect.y = floor ((gdouble) y / PAINT_UPDATE_CHUNK_HEIGHT) * PAINT_UPDATE_CHUNK_HEIGHT; - rect.width = ceil ((gdouble) (x + width) / PAINT_UPDATE_CHUNK_WIDTH) * PAINT_UPDATE_CHUNK_WIDTH - rect.x; - rect.height = ceil ((gdouble) (y + height) / PAINT_UPDATE_CHUNK_HEIGHT) * PAINT_UPDATE_CHUNK_HEIGHT - rect.y; - - if (drawable->private->paint_update_region) - { - cairo_region_union_rectangle ( - drawable->private->paint_update_region, - (const cairo_rectangle_int_t *) &rect); - } - else - { - drawable->private->paint_update_region = - cairo_region_create_rectangle ( - (const cairo_rectangle_int_t *) &rect); - } + gegl_rectangle_align (&aligned_rect, &rect, + GEGL_RECTANGLE (0, 0, + PAINT_UPDATE_CHUNK_WIDTH, + PAINT_UPDATE_CHUNK_HEIGHT), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + if (drawable->private->paint_update_region) + { + cairo_region_union_rectangle ( + drawable->private->paint_update_region, + (const cairo_rectangle_int_t *) &aligned_rect); + } + else + { + drawable->private->paint_update_region = + cairo_region_create_rectangle ( + (const cairo_rectangle_int_t *) &aligned_rect); + } } } } void -gimp_drawable_alpha_changed (GimpDrawable *drawable) +gimp_drawable_update_all (GimpDrawable *drawable) { g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_signal_emit (drawable, gimp_drawable_signals[ALPHA_CHANGED], 0); + GIMP_DRAWABLE_GET_CLASS (drawable)->update_all (drawable); } void @@ -1078,16 +1206,28 @@ GimpComponentMask gimp_drawable_get_active_mask (GimpDrawable *drawable) { - GimpDrawableClass *drawable_class; + GimpComponentMask mask; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), 0); - drawable_class = GIMP_DRAWABLE_GET_CLASS (drawable); + mask = GIMP_DRAWABLE_GET_CLASS (drawable)->get_active_mask (drawable); - if (drawable_class->get_active_mask) - return drawable_class->get_active_mask (drawable); + /* if the drawable doesn't have an alpha channel, the value of the mask's + * alpha-bit doesn't matter, however, we'd like to have a fully-clear or + * fully-set mask whenever possible, since it allows us to skip component + * masking altogether. we therefore set or clear the alpha bit, depending on + * the state of the other bits, so that it never gets in the way of a uniform + * mask. + */ + if (! gimp_drawable_has_alpha (drawable)) + { + if (mask & ~GIMP_COMPONENT_MASK_ALPHA) + mask |= GIMP_COMPONENT_MASK_ALPHA; + else + mask &= ~GIMP_COMPONENT_MASK_ALPHA; + } - return 0; + return mask; } void @@ -1184,31 +1324,6 @@ base_x, base_y); } -void -gimp_drawable_replace_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask, - const GeglRectangle *mask_region, - gint x, - gint y) -{ - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); - g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); - g_return_if_fail (GEGL_IS_BUFFER (buffer)); - g_return_if_fail (GEGL_IS_BUFFER (mask)); - - GIMP_DRAWABLE_GET_CLASS (drawable)->replace_buffer (drawable, buffer, - buffer_region, - push_undo, undo_desc, - opacity, - mask, mask_region, - x, y); -} - GeglBuffer * gimp_drawable_get_buffer (GimpDrawable *drawable) { @@ -1226,30 +1341,26 @@ const gchar *undo_desc, GeglBuffer *buffer) { - gint offset_x, offset_y; - g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (GEGL_IS_BUFFER (buffer)); if (! gimp_item_is_attached (GIMP_ITEM (drawable))) push_undo = FALSE; - gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y); - - gimp_drawable_set_buffer_full (drawable, push_undo, undo_desc, buffer, - offset_x, offset_y, TRUE); + gimp_drawable_set_buffer_full (drawable, push_undo, undo_desc, buffer, NULL, + TRUE); } void -gimp_drawable_set_buffer_full (GimpDrawable *drawable, - gboolean push_undo, - const gchar *undo_desc, - GeglBuffer *buffer, - gint offset_x, - gint offset_y, - gboolean update) +gimp_drawable_set_buffer_full (GimpDrawable *drawable, + gboolean push_undo, + const gchar *undo_desc, + GeglBuffer *buffer, + const GeglRectangle *bounds, + gboolean update) { - GimpItem *item; + GimpItem *item; + GeglRectangle curr_bounds; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (GEGL_IS_BUFFER (buffer)); @@ -1259,21 +1370,40 @@ if (! gimp_item_is_attached (GIMP_ITEM (drawable))) push_undo = FALSE; - if (update && - (gimp_item_get_width (item) != gegl_buffer_get_width (buffer) || - gimp_item_get_height (item) != gegl_buffer_get_height (buffer) || - gimp_item_get_offset_x (item) != offset_x || - gimp_item_get_offset_y (item) != offset_y)) + if (! bounds) + { + gimp_item_get_offset (GIMP_ITEM (drawable), + &curr_bounds.x, &curr_bounds.y); + + curr_bounds.width = 0; + curr_bounds.height = 0; + + bounds = &curr_bounds; + } + + if (update && gimp_drawable_get_buffer (drawable)) { - gimp_drawable_update (drawable, 0, 0, -1, -1); + GeglBuffer *old_buffer = gimp_drawable_get_buffer (drawable); + GeglRectangle old_extent; + GeglRectangle new_extent; + + old_extent = *gegl_buffer_get_extent (old_buffer); + old_extent.x += gimp_item_get_offset_x (item); + old_extent.y += gimp_item_get_offset_x (item); + + new_extent = *gegl_buffer_get_extent (buffer); + new_extent.x += bounds->x; + new_extent.y += bounds->y; + + if (! gegl_rectangle_equal (&old_extent, &new_extent)) + gimp_drawable_update (drawable, 0, 0, -1, -1); } g_object_freeze_notify (G_OBJECT (drawable)); GIMP_DRAWABLE_GET_CLASS (drawable)->set_buffer (drawable, push_undo, undo_desc, - buffer, - offset_x, offset_y); + buffer, bounds); g_object_thaw_notify (G_OBJECT (drawable)); @@ -1310,11 +1440,10 @@ GeglNode * gimp_drawable_get_source_node (GimpDrawable *drawable) { - const Babl *format; - GeglNode *input; - GeglNode *source; - GeglNode *filter; - GeglNode *output; + GeglNode *input; + GeglNode *source; + GeglNode *filter; + GeglNode *output; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); @@ -1344,27 +1473,10 @@ gegl_node_connect_to (source, "output", filter, "input"); - format = gimp_drawable_get_format (drawable); - - if (babl_format_is_palette (format)) - drawable->private->convert_format = - gegl_node_new_child (drawable->private->source_node, - "operation", "gegl:convert-format", - "format", gimp_drawable_get_format (drawable), - NULL); - else - drawable->private->convert_format = - gegl_node_new_child (drawable->private->source_node, - "operation", "gegl:nop", - NULL); - - gegl_node_connect_to (filter, "output", - drawable->private->convert_format, "input"); - output = gegl_node_get_output_proxy (drawable->private->source_node, "output"); - gegl_node_connect_to (drawable->private->convert_format, "output", - output, "input"); + gegl_node_connect_to (filter, "output", + output, "input"); if (gimp_drawable_get_floating_sel (drawable)) _gimp_drawable_add_floating_sel_filter (drawable); @@ -1383,6 +1495,71 @@ return drawable->private->mode_node; } +GeglRectangle +gimp_drawable_get_bounding_box (GimpDrawable *drawable) +{ + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), + *GEGL_RECTANGLE (0, 0, 0, 0)); + + if (gegl_rectangle_is_empty (&drawable->private->bounding_box)) + gimp_drawable_update_bounding_box (drawable); + + return drawable->private->bounding_box; +} + +gboolean +gimp_drawable_update_bounding_box (GimpDrawable *drawable) +{ + GeglRectangle bounding_box; + + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); + + bounding_box = + GIMP_DRAWABLE_GET_CLASS (drawable)->get_bounding_box (drawable); + + if (! gegl_rectangle_equal (&bounding_box, &drawable->private->bounding_box)) + { + GeglRectangle old_bounding_box = drawable->private->bounding_box; + GeglRectangle diff_rects[4]; + gint n_diff_rects; + gint i; + + n_diff_rects = gegl_rectangle_subtract (diff_rects, + &old_bounding_box, + &bounding_box); + + for (i = 0; i < n_diff_rects; i++) + { + gimp_drawable_update (drawable, + diff_rects[i].x, + diff_rects[i].y, + diff_rects[i].width, + diff_rects[i].height); + } + + drawable->private->bounding_box = bounding_box; + + g_signal_emit (drawable, gimp_drawable_signals[BOUNDING_BOX_CHANGED], 0); + + n_diff_rects = gegl_rectangle_subtract (diff_rects, + &bounding_box, + &old_bounding_box); + + for (i = 0; i < n_diff_rects; i++) + { + gimp_drawable_update (drawable, + diff_rects[i].x, + diff_rects[i].y, + diff_rects[i].width, + diff_rects[i].height); + } + + return TRUE; + } + + return FALSE; +} + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, @@ -1636,7 +1813,7 @@ g_return_if_fail (drawable->private->paint_copy_region == NULL); g_return_if_fail (drawable->private->paint_update_region == NULL); - drawable->private->paint_buffer = gegl_buffer_dup (buffer); + drawable->private->paint_buffer = gimp_gegl_buffer_dup (buffer); } drawable->private->paint_count++; diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-combine.c gimp-2.10.14+om/app/core/gimpdrawable-combine.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-combine.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-combine.c 2019-04-07 11:38:14.000000000 +0000 @@ -17,6 +17,7 @@ #include "config.h" +#include #include #include @@ -25,18 +26,12 @@ #include "core-types.h" #include "gegl/gimpapplicator.h" -#include "gegl/gimp-babl-compat.h" -#include "gegl/gimp-gegl-apply-operation.h" -#include "gegl/gimp-gegl-loops.h" -#include "gegl/gimp-gegl-utils.h" #include "gimp.h" #include "gimpchannel.h" +#include "gimpchunkiterator.h" #include "gimpdrawable-combine.h" -#include "gimpdrawableundo.h" #include "gimpimage.h" -#include "gimpimage-undo.h" -#include "gimptempbuf.h" void @@ -58,6 +53,7 @@ GimpImage *image = gimp_item_get_image (item); GimpChannel *mask = gimp_image_get_mask (image); GimpApplicator *applicator; + GimpChunkIterator *iter; gint x, y, width, height; gint offset_x, offset_y; @@ -102,37 +98,11 @@ if (push_undo) { - GimpDrawableUndo *undo; - gimp_drawable_push_undo (drawable, undo_desc, NULL, x, y, width, height); - - undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image)); - - if (undo) - { - undo->paint_mode = mode; - undo->blend_space = blend_space; - undo->composite_space = composite_space; - undo->composite_mode = composite_mode; - undo->opacity = opacity; - - undo->applied_buffer = - gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), - gegl_buffer_get_format (buffer)); - - gimp_gegl_buffer_copy ( - buffer, - GEGL_RECTANGLE (buffer_region->x + (x - base_x), - buffer_region->y + (y - base_y), - width, height), - GEGL_ABYSS_NONE, - undo->applied_buffer, - GEGL_RECTANGLE (0, 0, width, height)); - } } - applicator = gimp_applicator_new (NULL, FALSE, FALSE); + applicator = gimp_applicator_new (NULL); if (mask) { @@ -159,135 +129,16 @@ gimp_applicator_set_affect (applicator, gimp_drawable_get_active_mask (drawable)); - gimp_applicator_blit (applicator, GEGL_RECTANGLE (x, y, width, height)); - - g_object_unref (applicator); -} - -/* Similar to gimp_drawable_apply_region but works in "replace" mode (i.e. - * transparent pixels in src2 make the result transparent rather than - * opaque. - * - * Takes an additional mask pixel region as well. - */ -void -gimp_drawable_real_replace_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask_buffer, - const GeglRectangle *mask_buffer_region, - gint dest_x, - gint dest_y) -{ - GimpItem *item = GIMP_ITEM (drawable); - GimpImage *image = gimp_item_get_image (item); - GimpChannel *mask = gimp_image_get_mask (image); - GeglBuffer *drawable_buffer; - GeglRectangle buffer_rect = *buffer_region; - GeglRectangle mask_buffer_rect = *mask_buffer_region; - gint x, y, width, height; - gint offset_x, offset_y; - gboolean active_components[MAX_CHANNELS]; - - /* don't apply the mask to itself and don't apply an empty mask */ - if (GIMP_DRAWABLE (mask) == drawable || gimp_channel_is_empty (mask)) - mask = NULL; - - /* configure the active channel array */ - gimp_drawable_get_active_components (drawable, active_components); - - /* get the layer offsets */ - gimp_item_get_offset (item, &offset_x, &offset_y); - - /* make sure the image application coordinates are within drawable bounds */ - if (! gimp_rectangle_intersect (dest_x, dest_y, - buffer_rect.width, buffer_rect.height, - 0, 0, - gimp_item_get_width (item), - gimp_item_get_height (item), - &x, &y, &width, &height)) - { - return; - } + iter = gimp_chunk_iterator_new (cairo_region_create_rectangle ( + &(cairo_rectangle_int_t) {x, y, width, height})); - if (mask) + while (gimp_chunk_iterator_next (iter)) { - GimpItem *mask_item = GIMP_ITEM (mask); + GeglRectangle rect; - /* make sure coordinates are in mask bounds ... - * we need to add the layer offset to transform coords - * into the mask coordinate system - */ - if (! gimp_rectangle_intersect (x, y, width, height, - -offset_x, -offset_y, - gimp_item_get_width (mask_item), - gimp_item_get_height (mask_item), - &x, &y, &width, &height)) - { - return; - } + while (gimp_chunk_iterator_get_rect (iter, &rect)) + gimp_applicator_blit (applicator, &rect); } - /* adjust the original regions according to the application - * offset and size - */ - buffer_rect.x += x - dest_x; - buffer_rect.y += y - dest_y; - buffer_rect.width = width; - buffer_rect.height = height; - - mask_buffer_rect.x += x - dest_x; - mask_buffer_rect.y += y - dest_y; - mask_buffer_rect.width = width; - mask_buffer_rect.height = height; - - /* If the calling procedure specified an undo step... */ - if (push_undo) - gimp_drawable_push_undo (drawable, undo_desc, - NULL, x, y, width, height); - - drawable_buffer = gimp_drawable_get_buffer (drawable); - - if (mask) - { - GeglBuffer *src_buffer; - GeglBuffer *dest_buffer; - - src_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); - - dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), - gegl_buffer_get_format (src_buffer)); - - gimp_gegl_buffer_copy (src_buffer, - GEGL_RECTANGLE (x + offset_x, y + offset_y, - width, height), - GEGL_ABYSS_NONE, - dest_buffer, - GEGL_RECTANGLE (0, 0, 0, 0)); - - gimp_gegl_combine_mask (mask_buffer, &mask_buffer_rect, - dest_buffer, GEGL_RECTANGLE (0, 0, width, height), - 1.0); - - gimp_gegl_replace (buffer, &buffer_rect, - drawable_buffer, GEGL_RECTANGLE (x, y, width, height), - dest_buffer, GEGL_RECTANGLE (0, 0, width, height), - drawable_buffer, GEGL_RECTANGLE (x, y, width, height), - opacity, - active_components); - - g_object_unref (dest_buffer); - } - else - { - gimp_gegl_replace (buffer, &buffer_rect, - drawable_buffer, GEGL_RECTANGLE (x, y, width, height), - mask_buffer, &mask_buffer_rect, - drawable_buffer, GEGL_RECTANGLE (x, y, width, height), - opacity, - active_components); - } + g_object_unref (applicator); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-combine.h gimp-2.10.14+om/app/core/gimpdrawable-combine.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable-combine.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-combine.h 2019-04-07 11:38:14.000000000 +0000 @@ -21,29 +21,19 @@ /* virtual functions of GimpDrawable, don't call directly */ -void gimp_drawable_real_apply_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerMode mode, - GimpLayerColorSpace blend_space, - GimpLayerColorSpace composite_space, - GimpLayerCompositeMode composite_mode, - GeglBuffer *base_buffer, - gint base_x, - gint base_y); -void gimp_drawable_real_replace_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask, - const GeglRectangle *mask_region, - gint x, - gint y); +void gimp_drawable_real_apply_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerMode mode, + GimpLayerColorSpace blend_space, + GimpLayerColorSpace composite_space, + GimpLayerCompositeMode composite_mode, + GeglBuffer *base_buffer, + gint base_x, + gint base_y); #endif /* __GIMP_DRAWABLE_COMBINE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-edit.c gimp-2.10.14+om/app/core/gimpdrawable-edit.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-edit.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-edit.c 2019-04-07 11:38:14.000000000 +0000 @@ -24,14 +24,109 @@ #include "operations/layer-modes/gimp-layer-modes.h" +#include "gegl/gimp-gegl-loops.h" + +#include "gimpchannel.h" #include "gimpdrawable.h" #include "gimpdrawable-edit.h" +#include "gimpdrawablefilter.h" #include "gimpcontext.h" #include "gimpfilloptions.h" +#include "gimpimage.h" +#include "gimppattern.h" +#include "gimptempbuf.h" #include "gimp-intl.h" +/* local function prototypes */ + +static gboolean gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable, + GimpFillOptions *options); +static void gimp_drawable_edit_fill_direct (GimpDrawable *drawable, + GimpFillOptions *options, + const gchar *undo_desc); + + +/* private functions */ + +static gboolean +gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable, + GimpFillOptions *options) +{ + GimpImage *image; + GimpContext *context; + gdouble opacity; + GimpComponentMask affect; + GimpLayerMode mode; + GimpLayerCompositeMode composite_mode; + GimpLayerCompositeRegion composite_region; + + image = gimp_item_get_image (GIMP_ITEM (drawable)); + context = GIMP_CONTEXT (options); + opacity = gimp_context_get_opacity (context); + affect = gimp_drawable_get_active_mask (drawable); + mode = gimp_context_get_paint_mode (context); + composite_mode = gimp_layer_mode_get_paint_composite_mode (mode); + composite_region = gimp_layer_mode_get_included_region (mode, composite_mode); + + if (gimp_channel_is_empty (gimp_image_get_mask (image)) && + opacity == GIMP_OPACITY_OPAQUE && + affect == GIMP_COMPONENT_MASK_ALL && + gimp_layer_mode_is_trivial (mode) && + (! gimp_layer_mode_is_subtractive (mode) ^ + ! (composite_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE))) + { + switch (gimp_fill_options_get_style (options)) + { + case GIMP_FILL_STYLE_SOLID: + return TRUE; + + case GIMP_FILL_STYLE_PATTERN: + { + GimpPattern *pattern; + GimpTempBuf *mask; + const Babl *format; + + pattern = gimp_context_get_pattern (context); + mask = gimp_pattern_get_mask (pattern); + format = gimp_temp_buf_get_format (mask); + + return ! babl_format_has_alpha (format); + } + } + } + + return FALSE; +} + +static void +gimp_drawable_edit_fill_direct (GimpDrawable *drawable, + GimpFillOptions *options, + const gchar *undo_desc) +{ + GeglBuffer *buffer; + GimpContext *context; + GimpLayerMode mode; + gint width; + gint height; + + buffer = gimp_drawable_get_buffer (drawable); + context = GIMP_CONTEXT (options); + mode = gimp_context_get_paint_mode (context); + width = gimp_item_get_width (GIMP_ITEM (drawable)); + height = gimp_item_get_height (GIMP_ITEM (drawable)); + + gimp_drawable_push_undo (drawable, undo_desc, + NULL, 0, 0, width, height); + + if (! gimp_layer_mode_is_subtractive (mode)) + gimp_fill_options_fill_buffer (options, drawable, buffer, 0, 0); + else + gimp_gegl_clear (buffer, NULL); +} + + /* public functions */ void @@ -63,36 +158,74 @@ GimpFillOptions *options, const gchar *undo_desc) { - GeglBuffer *buffer; + GimpContext *context; gint x, y, width, height; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); - if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height)) - return; /* nothing to do, but the fill succeeded */ - - buffer = gimp_fill_options_create_buffer (options, drawable, - GEGL_RECTANGLE (0, 0, - width, height), - -x, -y); + if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), + &x, &y, &width, &height)) + { + return; /* nothing to do, but the fill succeeded */ + } + + context = GIMP_CONTEXT (options); + + if (gimp_layer_mode_is_alpha_only (gimp_context_get_paint_mode (context))) + { + if (! gimp_drawable_has_alpha (drawable) || + ! (gimp_drawable_get_active_mask (drawable) & + GIMP_COMPONENT_MASK_ALPHA)) + { + return; /* nothing to do, but the fill succeeded */ + } + } if (! undo_desc) undo_desc = gimp_fill_options_get_undo_desc (options); - gimp_drawable_apply_buffer (drawable, buffer, - GEGL_RECTANGLE (0, 0, width, height), - TRUE, undo_desc, - gimp_context_get_opacity (GIMP_CONTEXT (options)), - gimp_context_get_paint_mode (GIMP_CONTEXT (options)), - GIMP_LAYER_COLOR_SPACE_AUTO, - GIMP_LAYER_COLOR_SPACE_AUTO, - gimp_layer_mode_get_paint_composite_mode ( - gimp_context_get_paint_mode (GIMP_CONTEXT (options))), - NULL, x, y); + /* check if we can fill the drawable's buffer directly */ + if (gimp_drawable_edit_can_fill_direct (drawable, options)) + { + gimp_drawable_edit_fill_direct (drawable, options, undo_desc); - g_object_unref (buffer); - - gimp_drawable_update (drawable, x, y, width, height); + gimp_drawable_update (drawable, x, y, width, height); + } + else + { + GeglNode *operation; + GimpDrawableFilter *filter; + gdouble opacity; + GimpLayerMode mode; + GimpLayerMode composite_mode; + + opacity = gimp_context_get_opacity (context); + mode = gimp_context_get_paint_mode (context); + composite_mode = gimp_layer_mode_get_paint_composite_mode (mode); + + operation = gegl_node_new_child (NULL, + "operation", "gimp:fill-source", + "options", options, + "drawable", drawable, + "pattern-offset-x", -x, + "pattern-offset-y", -y, + NULL); + + filter = gimp_drawable_filter_new (drawable, undo_desc, operation, NULL); + + gimp_drawable_filter_set_opacity (filter, opacity); + gimp_drawable_filter_set_mode (filter, + mode, + GIMP_LAYER_COLOR_SPACE_AUTO, + GIMP_LAYER_COLOR_SPACE_AUTO, + composite_mode); + + gimp_drawable_filter_apply (filter, NULL); + gimp_drawable_filter_commit (filter, NULL, FALSE); + + g_object_unref (filter); + g_object_unref (operation); + } } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-fill.c gimp-2.10.14+om/app/core/gimpdrawable-fill.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-fill.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-fill.c 2019-04-07 11:38:14.000000000 +0000 @@ -92,26 +92,34 @@ if (pattern) { - const Babl *format; GeglBuffer *src_buffer; GeglBuffer *dest_buffer; GimpColorProfile *src_profile; GimpColorProfile *dest_profile; src_buffer = gimp_pattern_create_buffer (pattern); - format = gegl_buffer_get_format (src_buffer); - dest_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), - format); - - src_profile = gimp_babl_format_get_color_profile (format); - dest_profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (drawable)); - - gimp_gegl_convert_color_profile (src_buffer, NULL, src_profile, - dest_buffer, NULL, dest_profile, - GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, - TRUE, - NULL); + src_profile = gimp_babl_format_get_color_profile ( + gegl_buffer_get_format (src_buffer)); + dest_profile = gimp_color_managed_get_color_profile ( + GIMP_COLOR_MANAGED (drawable)); + + if (gimp_color_transform_can_gegl_copy (src_profile, dest_profile)) + { + dest_buffer = g_object_ref (src_buffer); + } + else + { + dest_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), + gegl_buffer_get_format (buffer)); + + gimp_gegl_convert_color_profile ( + src_buffer, NULL, src_profile, + dest_buffer, NULL, dest_profile, + GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, + TRUE, + NULL); + } gegl_buffer_set_pattern (buffer, NULL, dest_buffer, pattern_offset_x, pattern_offset_y); diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawablefilter.c gimp-2.10.14+om/app/core/gimpdrawablefilter.c --- gimp-2.10.8+zorin2/app/core/gimpdrawablefilter.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawablefilter.c 2019-10-26 18:49:18.000000000 +0000 @@ -44,6 +44,7 @@ #include "gimpdrawable-filters.h" #include "gimpdrawablefilter.h" #include "gimpimage.h" +#include "gimplayer.h" #include "gimpmarshal.h" #include "gimpprogress.h" @@ -64,7 +65,10 @@ gboolean has_input; + gboolean clip; GimpFilterRegion region; + gboolean crop_enabled; + GeglRectangle crop_rect; gboolean preview_enabled; GimpAlignmentType preview_alignment; gdouble preview_position; @@ -77,6 +81,7 @@ gboolean gamma_hack; GeglRectangle filter_area; + gboolean filter_clip; GeglNode *translate; GeglNode *crop_before; @@ -89,37 +94,49 @@ }; -static void gimp_drawable_filter_dispose (GObject *object); -static void gimp_drawable_filter_finalize (GObject *object); +static void gimp_drawable_filter_dispose (GObject *object); +static void gimp_drawable_filter_finalize (GObject *object); -static void gimp_drawable_filter_sync_region (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_preview (GimpDrawableFilter *filter, - gboolean old_enabled, - GimpAlignmentType old_alignment, - gdouble old_position); -static void gimp_drawable_filter_sync_opacity (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_mode (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_affect (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_mask (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_transform (GimpDrawableFilter *filter); -static void gimp_drawable_filter_sync_gamma_hack (GimpDrawableFilter *filter); - -static gboolean gimp_drawable_filter_is_filtering (GimpDrawableFilter *filter); -static gboolean gimp_drawable_filter_add_filter (GimpDrawableFilter *filter); -static gboolean gimp_drawable_filter_remove_filter (GimpDrawableFilter *filter); - -static void gimp_drawable_filter_update_drawable (GimpDrawableFilter *filter, - const GeglRectangle *area); - -static void gimp_drawable_filter_affect_changed (GimpImage *image, - GimpChannelType channel, - GimpDrawableFilter *filter); -static void gimp_drawable_filter_mask_changed (GimpImage *image, - GimpDrawableFilter *filter); -static void gimp_drawable_filter_profile_changed (GimpColorManaged *managed, - GimpDrawableFilter *filter); -static void gimp_drawable_filter_drawable_removed (GimpDrawable *drawable, - GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_clip (GimpDrawableFilter *filter, + gboolean sync_region); +static void gimp_drawable_filter_sync_region (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_crop (GimpDrawableFilter *filter, + gboolean old_crop_enabled, + const GeglRectangle *old_crop_rect, + gboolean old_preview_enabled, + GimpAlignmentType old_preview_alignment, + gdouble old_preview_position, + gboolean update); +static void gimp_drawable_filter_sync_opacity (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_mode (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_affect (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_format (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_mask (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_transform (GimpDrawableFilter *filter); +static void gimp_drawable_filter_sync_gamma_hack (GimpDrawableFilter *filter); + +static gboolean gimp_drawable_filter_is_filtering (GimpDrawableFilter *filter); +static gboolean gimp_drawable_filter_add_filter (GimpDrawableFilter *filter); +static gboolean gimp_drawable_filter_remove_filter (GimpDrawableFilter *filter); + +static void gimp_drawable_filter_update_drawable (GimpDrawableFilter *filter, + const GeglRectangle *area); + +static void gimp_drawable_filter_affect_changed (GimpImage *image, + GimpChannelType channel, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_mask_changed (GimpImage *image, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_profile_changed (GimpColorManaged *managed, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_lock_position_changed (GimpDrawable *drawable, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_format_changed (GimpDrawable *drawable, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_drawable_removed (GimpDrawable *drawable, + GimpDrawableFilter *filter); +static void gimp_drawable_filter_lock_alpha_changed (GimpLayer *layer, + GimpDrawableFilter *filter); G_DEFINE_TYPE (GimpDrawableFilter, gimp_drawable_filter, GIMP_TYPE_FILTER) @@ -150,6 +167,7 @@ static void gimp_drawable_filter_init (GimpDrawableFilter *drawable_filter) { + drawable_filter->clip = TRUE; drawable_filter->region = GIMP_FILTER_REGION_SELECTION; drawable_filter->preview_alignment = GIMP_ALIGN_LEFT; drawable_filter->preview_position = 1.0; @@ -208,11 +226,14 @@ node = gimp_filter_get_node (GIMP_FILTER (filter)); gegl_node_add_child (node, operation); + gimp_gegl_node_set_underlying_operation (node, operation); - filter->applicator = gimp_applicator_new (node, TRUE, TRUE); + filter->applicator = gimp_applicator_new (node); gimp_filter_set_applicator (GIMP_FILTER (filter), filter->applicator); + gimp_applicator_set_cache (filter->applicator, TRUE); + filter->has_input = gegl_node_has_pad (filter->operation, "input"); if (filter->has_input) @@ -271,6 +292,20 @@ } void +gimp_drawable_filter_set_clip (GimpDrawableFilter *filter, + gboolean clip) +{ + g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter)); + + if (clip != filter->clip) + { + filter->clip = clip; + + gimp_drawable_filter_sync_clip (filter, TRUE); + } +} + +void gimp_drawable_filter_set_region (GimpDrawableFilter *filter, GimpFilterRegion region) { @@ -288,6 +323,39 @@ } void +gimp_drawable_filter_set_crop (GimpDrawableFilter *filter, + const GeglRectangle *rect, + gboolean update) +{ + g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter)); + + if ((rect != NULL) != filter->crop_enabled || + (rect && ! gegl_rectangle_equal (rect, &filter->crop_rect))) + { + gboolean old_enabled = filter->crop_enabled; + GeglRectangle old_rect = filter->crop_rect; + + if (rect) + { + filter->crop_enabled = TRUE; + filter->crop_rect = *rect; + } + else + { + filter->crop_enabled = FALSE; + } + + gimp_drawable_filter_sync_crop (filter, + old_enabled, + &old_rect, + filter->preview_enabled, + filter->preview_alignment, + filter->preview_position, + update); + } +} + +void gimp_drawable_filter_set_preview (GimpDrawableFilter *filter, gboolean enabled, GimpAlignmentType alignment, @@ -313,9 +381,13 @@ filter->preview_alignment = alignment; filter->preview_position = position; - gimp_drawable_filter_sync_preview (filter, - old_enabled, - old_alignment, old_position); + gimp_drawable_filter_sync_crop (filter, + filter->crop_enabled, + &filter->crop_rect, + old_enabled, + old_alignment, + old_position, + TRUE); } } @@ -405,6 +477,11 @@ g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (filter->drawable))); gimp_drawable_filter_add_filter (filter); + + gimp_drawable_filter_sync_clip (filter, TRUE); + + gimp_drawable_update_bounding_box (filter->drawable); + gimp_drawable_filter_update_drawable (filter, area); } @@ -422,14 +499,23 @@ if (gimp_drawable_filter_is_filtering (filter)) { + gimp_drawable_filter_set_preview (filter, FALSE, + filter->preview_alignment, + filter->preview_position); + success = gimp_drawable_merge_filter (filter->drawable, GIMP_FILTER (filter), progress, gimp_object_get_name (filter), - cancellable); + filter->filter_clip, + cancellable, + FALSE); gimp_drawable_filter_remove_filter (filter); + if (! success) + gimp_drawable_filter_update_drawable (filter, NULL); + g_signal_emit (filter, drawable_filter_signals[FLUSH], 0); } @@ -451,6 +537,42 @@ /* private functions */ static void +gimp_drawable_filter_sync_clip (GimpDrawableFilter *filter, + gboolean sync_region) +{ + gboolean clip; + + clip = gimp_item_get_clip (GIMP_ITEM (filter->drawable), filter->clip); + + if (! clip) + { + GimpImage *image = gimp_item_get_image (GIMP_ITEM (filter->drawable)); + GimpChannel *mask = gimp_image_get_mask (image); + + if (! gimp_channel_is_empty (mask)) + clip = TRUE; + } + + if (! clip) + { + GeglRectangle bounding_box; + + bounding_box = gegl_node_get_bounding_box (filter->operation); + + if (gegl_rectangle_is_infinite_plane (&bounding_box)) + clip = TRUE; + } + + if (clip != filter->filter_clip) + { + filter->filter_clip = clip; + + if (sync_region) + gimp_drawable_filter_sync_region (filter); + } +} + +static void gimp_drawable_filter_sync_region (GimpDrawableFilter *filter) { if (filter->region == GIMP_FILTER_REGION_SELECTION) @@ -468,10 +590,22 @@ NULL); } - gegl_node_set (filter->crop_after, - "width", (gdouble) filter->filter_area.width, - "height", (gdouble) filter->filter_area.height, - NULL); + if (filter->filter_clip) + { + gegl_node_set (filter->crop_after, + "operation", "gegl:crop", + "x", 0.0, + "y", 0.0, + "width", (gdouble) filter->filter_area.width, + "height", (gdouble) filter->filter_area.height, + NULL); + } + else + { + gegl_node_set (filter->crop_after, + "operation", "gegl:nop", + NULL); + } gimp_applicator_set_apply_offset (filter->applicator, filter->filter_area.x, @@ -496,113 +630,137 @@ NULL); } - gegl_node_set (filter->crop_after, - "width", width, - "height", height, - NULL); + if (filter->filter_clip) + { + gegl_node_set (filter->crop_after, + "operation", "gegl:crop", + "x", (gdouble) filter->filter_area.x, + "y", (gdouble) filter->filter_area.y, + "width", (gdouble) filter->filter_area.width, + "height", (gdouble) filter->filter_area.height, + NULL); + } + else + { + gegl_node_set (filter->crop_after, + "operation", "gegl:nop", + NULL); + } gimp_applicator_set_apply_offset (filter->applicator, 0, 0); } + + if (gimp_drawable_filter_is_filtering (filter)) + { + if (gimp_drawable_update_bounding_box (filter->drawable)) + g_signal_emit (filter, drawable_filter_signals[FLUSH], 0); + } } -static void -gimp_drawable_filter_get_preview_rect (GimpDrawableFilter *filter, - gboolean enabled, - GimpAlignmentType alignment, - gdouble position, - GeglRectangle *rect) -{ - gint width; - gint height; - - rect->x = 0; - rect->y = 0; - rect->width = gimp_item_get_width (GIMP_ITEM (filter->drawable)); - rect->height = gimp_item_get_height (GIMP_ITEM (filter->drawable)); +static gboolean +gimp_drawable_filter_get_crop_rect (GimpDrawableFilter *filter, + gboolean crop_enabled, + const GeglRectangle *crop_rect, + gboolean preview_enabled, + GimpAlignmentType preview_alignment, + gdouble preview_position, + GeglRectangle *rect) +{ + GeglRectangle bounds; + gint width; + gint height; + gint x1, x2; + gint y1, y2; + + bounds = gegl_rectangle_infinite_plane (); + + width = gimp_item_get_width (GIMP_ITEM (filter->drawable)); + height = gimp_item_get_height (GIMP_ITEM (filter->drawable)); + + x1 = bounds.x; + x2 = bounds.x + bounds.width; - width = rect->width; - height = rect->height; + y1 = bounds.y; + y2 = bounds.y + bounds.height; - if (enabled) + if (preview_enabled) { - switch (alignment) + switch (preview_alignment) { case GIMP_ALIGN_LEFT: - rect->width *= position; + x2 = width * preview_position; break; case GIMP_ALIGN_RIGHT: - rect->width *= (1.0 - position); - rect->x = width - rect->width; + x1 = width * preview_position; break; case GIMP_ALIGN_TOP: - rect->height *= position; + y2 = height * preview_position; break; case GIMP_ALIGN_BOTTOM: - rect->height *= (1.0 - position); - rect->y = height - rect->height; + y1 = height * preview_position; break; default: - g_return_if_reached (); + g_return_val_if_reached (FALSE); } } + + gegl_rectangle_set (rect, x1, y1, x2 - x1, y2 - y1); + + if (crop_enabled) + gegl_rectangle_intersect (rect, rect, crop_rect); + + return ! gegl_rectangle_equal (rect, &bounds); } static void -gimp_drawable_filter_sync_preview (GimpDrawableFilter *filter, - gboolean old_enabled, - GimpAlignmentType old_alignment, - gdouble old_position) +gimp_drawable_filter_sync_crop (GimpDrawableFilter *filter, + gboolean old_crop_enabled, + const GeglRectangle *old_crop_rect, + gboolean old_preview_enabled, + GimpAlignmentType old_preview_alignment, + gdouble old_preview_position, + gboolean update) { GeglRectangle old_rect; GeglRectangle new_rect; + gboolean enabled; - gimp_drawable_filter_get_preview_rect (filter, - old_enabled, - old_alignment, - old_position, - &old_rect); - - gimp_drawable_filter_get_preview_rect (filter, - filter->preview_enabled, - filter->preview_alignment, - filter->preview_position, - &new_rect); + gimp_drawable_filter_get_crop_rect (filter, + old_crop_enabled, + old_crop_rect, + old_preview_enabled, + old_preview_alignment, + old_preview_position, + &old_rect); + + enabled = gimp_drawable_filter_get_crop_rect (filter, + filter->crop_enabled, + &filter->crop_rect, + filter->preview_enabled, + filter->preview_alignment, + filter->preview_position, + &new_rect); + + gimp_applicator_set_crop (filter->applicator, enabled ? &new_rect : NULL); + + if (update && + gimp_drawable_filter_is_filtering (filter) && + ! gegl_rectangle_equal (&old_rect, &new_rect)) + { + GeglRectangle diff_rects[4]; + gint n_diff_rects; + gint i; - gimp_applicator_set_preview (filter->applicator, - filter->preview_enabled, - &new_rect); + gimp_drawable_update_bounding_box (filter->drawable); - if (old_rect.x != new_rect.x || - old_rect.y != new_rect.y || - old_rect.width != new_rect.width || - old_rect.height != new_rect.height) - { - cairo_region_t *region; - gint n_rects; - gint i; - - region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) - &old_rect); - cairo_region_xor_rectangle (region, - (cairo_rectangle_int_t *) &new_rect); + n_diff_rects = gegl_rectangle_xor (diff_rects, &old_rect, &new_rect); - n_rects = cairo_region_num_rectangles (region); - - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (region, i, &rect); - - gimp_drawable_filter_update_drawable (filter, - (const GeglRectangle *) &rect); - } - - cairo_region_destroy (region); + for (i = 0; i < n_diff_rects; i++) + gimp_drawable_filter_update_drawable (filter, &diff_rects[i]); } } @@ -637,18 +795,17 @@ static void gimp_drawable_filter_sync_affect (GimpDrawableFilter *filter) { - GimpComponentMask active_mask; - - active_mask = gimp_drawable_get_active_mask (filter->drawable); - - /* don't let the filter affect the drawable projection's alpha, - * because it can't affect the drawable buffer's alpha either when - * finally merged (see bug #699279) - */ - if (! gimp_drawable_has_alpha (filter->drawable)) - active_mask &= ~GIMP_COMPONENT_MASK_ALPHA; + gimp_applicator_set_affect ( + filter->applicator, + gimp_drawable_get_active_mask (filter->drawable)); +} - gimp_applicator_set_affect (filter->applicator, active_mask); +static void +gimp_drawable_filter_sync_format (GimpDrawableFilter *filter) +{ + gimp_applicator_set_output_format ( + filter->applicator, + gimp_drawable_get_format (filter->drawable)); } static void @@ -846,20 +1003,27 @@ gimp_viewable_preview_freeze (GIMP_VIEWABLE (filter->drawable)); gimp_drawable_filter_sync_mask (filter); + gimp_drawable_filter_sync_clip (filter, FALSE); gimp_drawable_filter_sync_region (filter); - gimp_drawable_filter_sync_preview (filter, - filter->preview_enabled, - filter->preview_alignment, - filter->preview_position); + gimp_drawable_filter_sync_crop (filter, + filter->crop_enabled, + &filter->crop_rect, + filter->preview_enabled, + filter->preview_alignment, + filter->preview_position, + TRUE); gimp_drawable_filter_sync_opacity (filter); gimp_drawable_filter_sync_mode (filter); gimp_drawable_filter_sync_affect (filter); + gimp_drawable_filter_sync_format (filter); gimp_drawable_filter_sync_transform (filter); gimp_drawable_filter_sync_gamma_hack (filter); gimp_drawable_add_filter (filter->drawable, GIMP_FILTER (filter)); + gimp_drawable_update_bounding_box (filter->drawable); + g_signal_connect (image, "component-active-changed", G_CALLBACK (gimp_drawable_filter_affect_changed), filter); @@ -869,10 +1033,23 @@ g_signal_connect (image, "profile-changed", G_CALLBACK (gimp_drawable_filter_profile_changed), filter); + g_signal_connect (filter->drawable, "lock-position-changed", + G_CALLBACK (gimp_drawable_filter_lock_position_changed), + filter); + g_signal_connect (filter->drawable, "format-changed", + G_CALLBACK (gimp_drawable_filter_format_changed), + filter); g_signal_connect (filter->drawable, "removed", G_CALLBACK (gimp_drawable_filter_drawable_removed), filter); + if (GIMP_IS_LAYER (filter->drawable)) + { + g_signal_connect (filter->drawable, "lock-alpha-changed", + G_CALLBACK (gimp_drawable_filter_lock_alpha_changed), + filter); + } + return TRUE; } @@ -886,9 +1063,22 @@ { GimpImage *image = gimp_item_get_image (GIMP_ITEM (filter->drawable)); + if (GIMP_IS_LAYER (filter->drawable)) + { + g_signal_handlers_disconnect_by_func (filter->drawable, + gimp_drawable_filter_lock_alpha_changed, + filter); + } + g_signal_handlers_disconnect_by_func (filter->drawable, gimp_drawable_filter_drawable_removed, filter); + g_signal_handlers_disconnect_by_func (filter->drawable, + gimp_drawable_filter_format_changed, + filter); + g_signal_handlers_disconnect_by_func (filter->drawable, + gimp_drawable_filter_lock_position_changed, + filter); g_signal_handlers_disconnect_by_func (image, gimp_drawable_filter_profile_changed, filter); @@ -902,6 +1092,8 @@ gimp_drawable_remove_filter (filter->drawable, GIMP_FILTER (filter)); + gimp_drawable_update_bounding_box (filter->drawable); + gimp_viewable_preview_thaw (GIMP_VIEWABLE (filter->drawable)); return TRUE; @@ -914,29 +1106,34 @@ gimp_drawable_filter_update_drawable (GimpDrawableFilter *filter, const GeglRectangle *area) { + GeglRectangle bounding_box; GeglRectangle update_area; + bounding_box = gimp_drawable_get_bounding_box (filter->drawable); + if (area) { - if (! gimp_rectangle_intersect (area->x, - area->y, - area->width, - area->height, - filter->filter_area.x, - filter->filter_area.y, - filter->filter_area.width, - filter->filter_area.height, - &update_area.x, - &update_area.y, - &update_area.width, - &update_area.height)) + if (! gegl_rectangle_intersect (&update_area, + area, &bounding_box)) { return; } } else { - update_area = filter->filter_area; + gimp_drawable_filter_get_crop_rect (filter, + filter->crop_enabled, + &filter->crop_rect, + filter->preview_enabled, + filter->preview_alignment, + filter->preview_position, + &update_area); + + if (! gegl_rectangle_intersect (&update_area, + &update_area, &bounding_box)) + { + return; + } } if (update_area.width > 0 && @@ -968,6 +1165,7 @@ gimp_drawable_filter_update_drawable (filter, NULL); gimp_drawable_filter_sync_mask (filter); + gimp_drawable_filter_sync_clip (filter, FALSE); gimp_drawable_filter_sync_region (filter); gimp_drawable_filter_update_drawable (filter, NULL); @@ -982,8 +1180,32 @@ } static void +gimp_drawable_filter_lock_position_changed (GimpDrawable *drawable, + GimpDrawableFilter *filter) +{ + gimp_drawable_filter_sync_clip (filter, TRUE); + gimp_drawable_filter_update_drawable (filter, NULL); +} + +static void +gimp_drawable_filter_format_changed (GimpDrawable *drawable, + GimpDrawableFilter *filter) +{ + gimp_drawable_filter_sync_format (filter); + gimp_drawable_filter_update_drawable (filter, NULL); +} + +static void gimp_drawable_filter_drawable_removed (GimpDrawable *drawable, GimpDrawableFilter *filter) { gimp_drawable_filter_remove_filter (filter); } + +static void +gimp_drawable_filter_lock_alpha_changed (GimpLayer *layer, + GimpDrawableFilter *filter) +{ + gimp_drawable_filter_sync_affect (filter); + gimp_drawable_filter_update_drawable (filter, NULL); +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawablefilter.h gimp-2.10.14+om/app/core/gimpdrawablefilter.h --- gimp-2.10.8+zorin2/app/core/gimpdrawablefilter.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawablefilter.h 2019-10-26 18:49:18.000000000 +0000 @@ -55,8 +55,13 @@ GeglNode *operation, const gchar *icon_name); +void gimp_drawable_filter_set_clip (GimpDrawableFilter *filter, + gboolean clip); void gimp_drawable_filter_set_region (GimpDrawableFilter *filter, GimpFilterRegion region); +void gimp_drawable_filter_set_crop (GimpDrawableFilter *filter, + const GeglRectangle *rect, + gboolean update); void gimp_drawable_filter_set_preview (GimpDrawableFilter *filter, gboolean enabled, GimpAlignmentType alignment, diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-filters.c gimp-2.10.14+om/app/core/gimpdrawable-filters.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-filters.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-filters.c 2019-10-26 18:49:18.000000000 +0000 @@ -29,15 +29,16 @@ #include "gegl/gimp-gegl-apply-operation.h" #include "gegl/gimp-gegl-loops.h" +#include "gimp.h" #include "gimp-utils.h" #include "gimpdrawable.h" #include "gimpdrawable-filters.h" #include "gimpdrawable-private.h" -#include "gimpdrawableundo.h" #include "gimpfilter.h" #include "gimpfilterstack.h" #include "gimpimage.h" #include "gimpimage-undo.h" +#include "gimplayer.h" #include "gimpprogress.h" #include "gimpprojection.h" @@ -110,142 +111,201 @@ GimpFilter *filter, GimpProgress *progress, const gchar *undo_desc, - gboolean cancellable) + gboolean clip, + gboolean cancellable, + gboolean update) { - GeglRectangle rect; - gboolean success = TRUE; + GimpImage *image; + GimpApplicator *applicator; + gboolean applicator_cache = FALSE; + const Babl *applicator_output_format = NULL; + GeglBuffer *buffer = NULL; + GeglBuffer *dest_buffer; + GeglBuffer *undo_buffer; + GeglRectangle undo_rect; + GeglBuffer *cache = NULL; + GeglRectangle *rects = NULL; + gint n_rects = 0; + GeglRectangle rect; + gboolean success = TRUE; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); g_return_val_if_fail (GIMP_IS_FILTER (filter), FALSE); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE); - if (gimp_item_mask_intersect (GIMP_ITEM (drawable), - &rect.x, &rect.y, - &rect.width, &rect.height)) - { - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); - GeglBuffer *undo_buffer; - GimpApplicator *applicator; - GeglBuffer *apply_buffer = NULL; - GeglBuffer *cache = NULL; - GeglRectangle *rects = NULL; - gint n_rects = 0; + image = gimp_item_get_image (GIMP_ITEM (drawable)); + applicator = gimp_filter_get_applicator (filter); + dest_buffer = gimp_drawable_get_buffer (drawable); + + rect = gegl_node_get_bounding_box (gimp_filter_get_node (filter)); + + if (! clip && gegl_rectangle_equal (&rect, + gegl_buffer_get_extent (dest_buffer))) + { + clip = TRUE; + } + + if (clip) + { + if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), + &rect.x, &rect.y, + &rect.width, &rect.height)) + { + return TRUE; + } + } + else + { + buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height), + gimp_drawable_get_format (drawable)); + + dest_buffer = g_object_new (GEGL_TYPE_BUFFER, + "source", buffer, + "shift-x", -rect.x, + "shift-y", -rect.y, + NULL); + } + + if (applicator) + { + const GeglRectangle *crop_rect; + + crop_rect = gimp_applicator_get_crop (applicator); + + if (crop_rect && ! gegl_rectangle_intersect (&rect, &rect, crop_rect)) + return TRUE; + + /* the cache and its valid rectangles are the region that + * has already been processed by this applicator. + */ + cache = gimp_applicator_get_cache_buffer (applicator, + &rects, &n_rects); + + /* skip the cache and output-format conversion while processing + * the remaining area, so that the result is written directly to + * the drawable's buffer. + */ + applicator_cache = gimp_applicator_get_cache (applicator); + applicator_output_format = gimp_applicator_get_output_format (applicator); + + gimp_applicator_set_cache (applicator, FALSE); + if (applicator_output_format == gimp_drawable_get_format (drawable)) + gimp_applicator_set_output_format (applicator, NULL); + } + + if (clip) + { + gegl_rectangle_align_to_buffer ( + &undo_rect, + &rect, + gimp_drawable_get_buffer (drawable), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); undo_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, - rect.width, rect.height), + undo_rect.width, + undo_rect.height), gimp_drawable_get_format (drawable)); gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (rect.x, rect.y, - rect.width, rect.height), + &undo_rect, GEGL_ABYSS_NONE, undo_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); + } - applicator = gimp_filter_get_applicator (filter); - - if (applicator) - { - /* disable the preview crop, this will force-process the - * cached result from the preview cache into the result - * cache, involving only the layer and affect nodes - */ - gimp_applicator_set_preview (applicator, FALSE, - GEGL_RECTANGLE (0, 0, 0, 0)); - - /* the apply_buffer will make a copy of the region that is - * actually processed in gimp_gegl_apply_cached_operation() - * below. - */ - apply_buffer = gimp_applicator_dup_apply_buffer (applicator, &rect); - - /* the cache and its valid rectangles are the region that - * has already been processed by this applicator. - */ - cache = gimp_applicator_get_cache_buffer (applicator, - &rects, &n_rects); - - if (cache) - { - gint i; + gimp_projection_stop_rendering (gimp_image_get_projection (image)); - for (i = 0; i < n_rects; i++) - { - g_printerr ("valid: %d %d %d %d\n", - rects[i].x, rects[i].y, - rects[i].width, rects[i].height); - - /* we have to copy the cached region to the apply_buffer, - * because this region is not going to be processed. - */ - gimp_gegl_buffer_copy (cache, - &rects[i], - GEGL_ABYSS_NONE, - apply_buffer, - GEGL_RECTANGLE (rects[i].x - rect.x, - rects[i].y - rect.y, - 0, 0)); - } - } + if (gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable), + progress, undo_desc, + gimp_filter_get_node (filter), FALSE, + dest_buffer, &rect, FALSE, + cache, rects, n_rects, + cancellable)) + { + /* finished successfully */ + if (clip) + { + gimp_drawable_push_undo (drawable, undo_desc, undo_buffer, + undo_rect.x, undo_rect.y, + undo_rect.width, undo_rect.height); } - - gimp_projection_stop_rendering (gimp_image_get_projection (image)); - - if (gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable), - progress, undo_desc, - gimp_filter_get_node (filter), - gimp_drawable_get_buffer (drawable), - &rect, FALSE, - cache, rects, n_rects, - cancellable)) + else { - /* finished successfully */ + GimpLayerMask *mask = NULL; + gint offset_x; + gint offset_y; - gimp_drawable_push_undo (drawable, undo_desc, undo_buffer, - rect.x, rect.y, - rect.width, rect.height); + gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y); + + if (GIMP_IS_LAYER (drawable)) + mask = gimp_layer_get_mask (GIMP_LAYER (drawable)); - if (applicator) + if (mask) { - GimpDrawableUndo *undo; + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_DRAWABLE_MOD, + undo_desc); + } - undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image)); + gimp_drawable_set_buffer_full ( + drawable, TRUE, undo_desc, buffer, + GEGL_RECTANGLE (offset_x + rect.x, offset_y + rect.y, 0, 0), + FALSE); - if (undo) - { - undo->paint_mode = applicator->paint_mode; - undo->opacity = applicator->opacity; - - undo->applied_buffer = apply_buffer; - apply_buffer = NULL; - } + if (mask) + { + gimp_item_resize (GIMP_ITEM (mask), + gimp_get_default_context (image->gimp), + GIMP_FILL_TRANSPARENT, + rect.width, rect.height, + -rect.x, -rect.y); + + gimp_image_undo_group_end (image); } } - else - { - /* canceled by the user */ + } + else + { + /* canceled by the user */ + if (clip) + { gimp_gegl_buffer_copy (undo_buffer, - GEGL_RECTANGLE (0, 0, rect.width, rect.height), + GEGL_RECTANGLE (0, 0, + undo_rect.width, + undo_rect.height), GEGL_ABYSS_NONE, gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (rect.x, rect.y, 0, 0)); - - success = FALSE; + &undo_rect); } + success = FALSE; + } + + if (clip) + { g_object_unref (undo_buffer); + } + else + { + g_object_unref (buffer); + g_object_unref (dest_buffer); + } - if (apply_buffer) - g_object_unref (apply_buffer); + if (cache) + { + g_object_unref (cache); + g_free (rects); + } - if (cache) - { - g_object_unref (cache); - g_free (rects); - } + if (applicator) + { + gimp_applicator_set_cache (applicator, applicator_cache); + gimp_applicator_set_output_format (applicator, applicator_output_format); + } + if (update) + { gimp_drawable_update (drawable, rect.x, rect.y, rect.width, rect.height); diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-filters.h gimp-2.10.14+om/app/core/gimpdrawable-filters.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable-filters.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-filters.h 2019-10-26 18:49:18.000000000 +0000 @@ -37,7 +37,9 @@ GimpFilter *filter, GimpProgress *progress, const gchar *undo_desc, - gboolean cancellable); + gboolean clip, + gboolean cancellable, + gboolean update); #endif /* __GIMP_DRAWABLE_FILTERS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-floating-selection.c gimp-2.10.14+om/app/core/gimpdrawable-floating-selection.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-floating-selection.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-floating-selection.c 2019-10-26 18:49:18.000000000 +0000 @@ -44,9 +44,13 @@ static void gimp_drawable_remove_fs_filter (GimpDrawable *drawable); static void gimp_drawable_sync_fs_filter (GimpDrawable *drawable); -static void gimp_drawable_fs_notify (GimpLayer *fs, +static void gimp_drawable_fs_notify (GObject *object, const GParamSpec *pspec, GimpDrawable *drawable); +static void gimp_drawable_fs_lock_position_changed (GimpDrawable *signal_drawable, + GimpDrawable *drawable); +static void gimp_drawable_fs_format_changed (GimpDrawable *signal_drawable, + GimpDrawable *drawable); static void gimp_drawable_fs_affect_changed (GimpImage *image, GimpChannelType channel, GimpDrawable *drawable); @@ -56,6 +60,8 @@ GimpDrawable *drawable); static void gimp_drawable_fs_excludes_backdrop_changed (GimpLayer *fs, GimpDrawable *drawable); +static void gimp_drawable_fs_bounding_box_changed (GimpLayer *fs, + GimpDrawable *drawable); static void gimp_drawable_fs_update (GimpLayer *fs, gint x, gint y, @@ -106,6 +112,9 @@ g_signal_connect (fs, "excludes-backdrop-changed", G_CALLBACK (gimp_drawable_fs_excludes_backdrop_changed), drawable); + g_signal_connect (fs, "bounding-box-changed", + G_CALLBACK (gimp_drawable_fs_bounding_box_changed), + drawable); g_signal_connect (fs, "update", G_CALLBACK (gimp_drawable_fs_update), drawable); @@ -140,6 +149,9 @@ gimp_drawable_fs_excludes_backdrop_changed, drawable); g_signal_handlers_disconnect_by_func (fs, + gimp_drawable_fs_bounding_box_changed, + drawable); + g_signal_handlers_disconnect_by_func (fs, gimp_drawable_fs_update, drawable); @@ -206,12 +218,15 @@ gegl_node_add_child (node, fs_source); - private->fs_applicator = gimp_applicator_new (node, FALSE, FALSE); + private->fs_applicator = gimp_applicator_new (node); + + gimp_filter_set_applicator (private->fs_filter, private->fs_applicator); - private->fs_crop_node = - gegl_node_new_child (node, - "operation", "gegl:crop", - NULL); + gimp_applicator_set_cache (private->fs_applicator, TRUE); + + private->fs_crop_node = gegl_node_new_child (node, + "operation", "gegl:nop", + NULL); gegl_node_connect_to (fs_source, "output", private->fs_crop_node, "input"); @@ -223,6 +238,18 @@ g_signal_connect (fs, "notify", G_CALLBACK (gimp_drawable_fs_notify), drawable); + g_signal_connect (drawable, "notify::offset-x", + G_CALLBACK (gimp_drawable_fs_notify), + drawable); + g_signal_connect (drawable, "notify::offset-y", + G_CALLBACK (gimp_drawable_fs_notify), + drawable); + g_signal_connect (drawable, "lock-position-changed", + G_CALLBACK (gimp_drawable_fs_lock_position_changed), + drawable); + g_signal_connect (drawable, "format-changed", + G_CALLBACK (gimp_drawable_fs_format_changed), + drawable); g_signal_connect (image, "component-active-changed", G_CALLBACK (gimp_drawable_fs_affect_changed), drawable); @@ -251,6 +278,15 @@ g_signal_handlers_disconnect_by_func (fs, gimp_drawable_fs_notify, drawable); + g_signal_handlers_disconnect_by_func (drawable, + gimp_drawable_fs_notify, + drawable); + g_signal_handlers_disconnect_by_func (drawable, + gimp_drawable_fs_lock_position_changed, + drawable); + g_signal_handlers_disconnect_by_func (drawable, + gimp_drawable_fs_format_changed, + drawable); g_signal_handlers_disconnect_by_func (image, gimp_drawable_fs_affect_changed, drawable); @@ -279,6 +315,8 @@ g_clear_object (&private->fs_applicator); private->fs_crop_node = NULL; + + gimp_drawable_update_bounding_box (drawable); } } @@ -289,8 +327,8 @@ GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); GimpChannel *mask = gimp_image_get_mask (image); GimpLayer *fs = gimp_drawable_get_floating_sel (drawable); - gint off_x, off_y; - gint fs_off_x, fs_off_y; + gint off_x, off_y; + gint fs_off_x, fs_off_y; gimp_filter_set_active (private->fs_filter, gimp_item_get_visible (GIMP_ITEM (fs))); @@ -298,12 +336,26 @@ gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); gimp_item_get_offset (GIMP_ITEM (fs), &fs_off_x, &fs_off_y); - gegl_node_set (private->fs_crop_node, - "x", (gdouble) (off_x - fs_off_x), - "y", (gdouble) (off_y - fs_off_y), - "width", (gdouble) gimp_item_get_width (GIMP_ITEM (drawable)), - "height", (gdouble) gimp_item_get_height (GIMP_ITEM (drawable)), - NULL); + if (gimp_item_get_clip (GIMP_ITEM (drawable), GIMP_TRANSFORM_RESIZE_ADJUST) == + GIMP_TRANSFORM_RESIZE_CLIP || + ! gimp_drawable_has_alpha (drawable)) + { + gegl_node_set ( + private->fs_crop_node, + "operation", "gegl:crop", + "x", (gdouble) (off_x - fs_off_x), + "y", (gdouble) (off_y - fs_off_y), + "width", (gdouble) gimp_item_get_width (GIMP_ITEM (drawable)), + "height", (gdouble) gimp_item_get_height (GIMP_ITEM (drawable)), + NULL); + } + else + { + gegl_node_set ( + private->fs_crop_node, + "operation", "gegl:nop", + NULL); + } gimp_applicator_set_apply_offset (private->fs_applicator, fs_off_x - off_x, @@ -331,10 +383,14 @@ gimp_layer_get_composite_mode (fs)); gimp_applicator_set_affect (private->fs_applicator, gimp_drawable_get_active_mask (drawable)); + gimp_applicator_set_output_format (private->fs_applicator, + gimp_drawable_get_format (drawable)); + + gimp_drawable_update_bounding_box (drawable); } static void -gimp_drawable_fs_notify (GimpLayer *fs, +gimp_drawable_fs_notify (GObject *object, const GParamSpec *pspec, GimpDrawable *drawable) { @@ -352,6 +408,28 @@ } static void +gimp_drawable_fs_lock_position_changed (GimpDrawable *signal_drawable, + GimpDrawable *drawable) +{ + GimpLayer *fs = gimp_drawable_get_floating_sel (drawable); + + gimp_drawable_sync_fs_filter (drawable); + + gimp_drawable_update (GIMP_DRAWABLE (fs), 0, 0, -1, -1); +} + +static void +gimp_drawable_fs_format_changed (GimpDrawable *signal_drawable, + GimpDrawable *drawable) +{ + GimpLayer *fs = gimp_drawable_get_floating_sel (drawable); + + gimp_drawable_sync_fs_filter (drawable); + + gimp_drawable_update (GIMP_DRAWABLE (fs), 0, 0, -1, -1); +} + +static void gimp_drawable_fs_affect_changed (GimpImage *image, GimpChannelType channel, GimpDrawable *drawable) @@ -393,6 +471,13 @@ } static void +gimp_drawable_fs_bounding_box_changed (GimpLayer *fs, + GimpDrawable *drawable) +{ + gimp_drawable_update_bounding_box (drawable); +} + +static void gimp_drawable_fs_update (GimpLayer *fs, gint x, gint y, @@ -400,28 +485,28 @@ gint height, GimpDrawable *drawable) { - gint fs_off_x, fs_off_y; - gint off_x, off_y; - gint dr_x, dr_y, dr_width, dr_height; + GeglRectangle bounding_box; + GeglRectangle rect; + gint fs_off_x, fs_off_y; + gint off_x, off_y; gimp_item_get_offset (GIMP_ITEM (fs), &fs_off_x, &fs_off_y); gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); - if (gimp_rectangle_intersect (x + fs_off_x, - y + fs_off_y, - width, - height, - off_x, - off_y, - gimp_item_get_width (GIMP_ITEM (drawable)), - gimp_item_get_height (GIMP_ITEM (drawable)), - &dr_x, - &dr_y, - &dr_width, - &dr_height)) + bounding_box = gimp_drawable_get_bounding_box (drawable); + + bounding_box.x += off_x; + bounding_box.y += off_y; + + rect.x = x + fs_off_x; + rect.y = y + fs_off_y; + rect.width = width; + rect.height = height; + + if (gegl_rectangle_intersect (&rect, &rect, &bounding_box)) { gimp_drawable_update (drawable, - dr_x - off_x, dr_y - off_y, - dr_width, dr_height); + rect.x - off_x, rect.y - off_y, + rect.width, rect.height); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable.h gimp-2.10.14+om/app/core/gimpdrawable.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable.h 2019-10-26 18:49:18.000000000 +0000 @@ -50,13 +50,16 @@ gint y, gint width, gint height); + void (* format_changed) (GimpDrawable *drawable); void (* alpha_changed) (GimpDrawable *drawable); + void (* bounding_box_changed) (GimpDrawable *drawable); /* virtual functions */ gint64 (* estimate_memsize) (GimpDrawable *drawable, GimpComponentType component_type, gint width, gint height); + void (* update_all) (GimpDrawable *drawable); void (* invalidate_boundary) (GimpDrawable *drawable); void (* get_active_components) (GimpDrawable *drawable, gboolean *active); @@ -82,23 +85,13 @@ GeglBuffer *base_buffer, gint base_x, gint base_y); - void (* replace_buffer) (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask, - const GeglRectangle *mask_region, - gint x, - gint y); GeglBuffer * (* get_buffer) (GimpDrawable *drawable); void (* set_buffer) (GimpDrawable *drawable, gboolean push_undo, const gchar *undo_desc, GeglBuffer *buffer, - gint offset_x, - gint offset_y); + const GeglRectangle *bounds); + GeglRectangle (* get_bounding_box) (GimpDrawable *drawable); void (* push_undo) (GimpDrawable *drawable, const gchar *undo_desc, GeglBuffer *buffer, @@ -135,7 +128,7 @@ gint y, gint width, gint height); -void gimp_drawable_alpha_changed (GimpDrawable *drawable); +void gimp_drawable_update_all (GimpDrawable *drawable); void gimp_drawable_invalidate_boundary (GimpDrawable *drawable); void gimp_drawable_get_active_components (GimpDrawable *drawable, @@ -166,16 +159,6 @@ GeglBuffer *base_buffer, gint base_x, gint base_y); -void gimp_drawable_replace_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask, - const GeglRectangle *mask_region, - gint x, - gint y); GeglBuffer * gimp_drawable_get_buffer (GimpDrawable *drawable); void gimp_drawable_set_buffer (GimpDrawable *drawable, @@ -186,8 +169,7 @@ gboolean push_undo, const gchar *undo_desc, GeglBuffer *buffer, - gint offset_x, - gint offset_y, + const GeglRectangle *bounds, gboolean update); void gimp_drawable_steal_buffer (GimpDrawable *drawable, @@ -196,6 +178,10 @@ GeglNode * gimp_drawable_get_source_node (GimpDrawable *drawable); GeglNode * gimp_drawable_get_mode_node (GimpDrawable *drawable); +GeglRectangle gimp_drawable_get_bounding_box (GimpDrawable *drawable); +gboolean gimp_drawable_update_bounding_box + (GimpDrawable *drawable); + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, gint x, diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawablemodundo.c gimp-2.10.14+om/app/core/gimpdrawablemodundo.c --- gimp-2.10.8+zorin2/app/core/gimpdrawablemodundo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawablemodundo.c 2019-10-26 18:49:18.000000000 +0000 @@ -108,7 +108,7 @@ if (drawable_mod_undo->copy_buffer) { drawable_mod_undo->buffer = - gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); + gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); } else { @@ -198,7 +198,9 @@ &drawable_mod_undo->offset_y); gimp_drawable_set_buffer_full (drawable, FALSE, NULL, - buffer, offset_x, offset_y, TRUE); + buffer, + GEGL_RECTANGLE (offset_x, offset_y, 0, 0), + TRUE); g_object_unref (buffer); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-offset.c gimp-2.10.14+om/app/core/gimpdrawable-offset.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-offset.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-offset.c 2019-10-26 18:49:18.000000000 +0000 @@ -23,20 +23,13 @@ #include #include -#include "libgimpcolor/gimpcolor.h" -#include "libgimpmath/gimpmath.h" - #include "core-types.h" -#include "gegl/gimp-gegl-loops.h" -#include "gegl/gimp-gegl-utils.h" - #include "gimp.h" #include "gimpcontext.h" #include "gimpdrawable.h" #include "gimpdrawable-offset.h" -#include "gimpimage.h" -#include "gimppickable.h" +#include "gimpdrawable-operation.h" #include "gimp-intl.h" @@ -49,206 +42,42 @@ gint offset_x, gint offset_y) { - GimpItem *item; - GeglBuffer *src_buffer; - GeglBuffer *new_buffer; - GeglRectangle src_rect; - GeglRectangle dest_rect; - gint width, height; - gint src_x, src_y; - gint dest_x, dest_y; + GeglNode *node; + gint width; + gint height; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (GIMP_IS_CONTEXT (context)); - item = GIMP_ITEM (drawable); - - width = gimp_item_get_width (item); - height = gimp_item_get_height (item); + if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), + NULL, NULL, &width, &height)) + { + return; + } if (wrap_around) - { - /* avoid modulo operation on negative values */ - while (offset_x < 0) - offset_x += width; - while (offset_y < 0) - offset_y += height; + fill_type = GIMP_OFFSET_WRAP_AROUND; + if (fill_type == GIMP_OFFSET_WRAP_AROUND) + { offset_x %= width; offset_y %= height; } - else - { - offset_x = CLAMP (offset_x, -width, width); - offset_y = CLAMP (offset_y, -height, height); - } if (offset_x == 0 && offset_y == 0) return; - src_buffer = gimp_drawable_get_buffer (drawable); - - new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), - gimp_drawable_get_format (drawable)); - - if (! wrap_around) - { - if (fill_type == GIMP_OFFSET_BACKGROUND) - { - GimpRGB bg; - GeglColor *color; - - gimp_context_get_background (context, &bg); - gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable), - &bg, &bg); - - color = gimp_gegl_color_new (&bg); - gegl_buffer_set_color (new_buffer, NULL, color); - g_object_unref (color); - } - } - - if (offset_x >= 0) - { - src_x = 0; - dest_x = offset_x; - width = CLAMP ((width - offset_x), 0, width); - } - else - { - src_x = -offset_x; - dest_x = 0; - width = CLAMP ((width + offset_x), 0, width); - } - - if (offset_y >= 0) - { - src_y = 0; - dest_y = offset_y; - height = CLAMP ((height - offset_y), 0, height); - } - else - { - src_y = -offset_y; - dest_y = 0; - height = CLAMP ((height + offset_y), 0, height); - } - - /* Copy the center region */ - if (width && height) - { - gimp_gegl_buffer_copy (src_buffer, - GEGL_RECTANGLE (src_x, src_y, width, height), - GEGL_ABYSS_NONE, - new_buffer, - GEGL_RECTANGLE (dest_x,dest_y, width, height)); - } - - if (wrap_around) - { - /* Copy appropriately for wrap around */ - - if (offset_x >= 0 && offset_y >= 0) - { - src_x = gimp_item_get_width (item) - offset_x; - src_y = gimp_item_get_height (item) - offset_y; - } - else if (offset_x >= 0 && offset_y < 0) - { - src_x = gimp_item_get_width (item) - offset_x; - src_y = 0; - } - else if (offset_x < 0 && offset_y >= 0) - { - src_x = 0; - src_y = gimp_item_get_height (item) - offset_y; - } - else if (offset_x < 0 && offset_y < 0) - { - src_x = 0; - src_y = 0; - } - - dest_x = (src_x + offset_x) % gimp_item_get_width (item); - if (dest_x < 0) - dest_x = gimp_item_get_width (item) + dest_x; - - dest_y = (src_y + offset_y) % gimp_item_get_height (item); - if (dest_y < 0) - dest_y = gimp_item_get_height (item) + dest_y; - - /* intersecting region */ - if (offset_x != 0 && offset_y != 0) - { - gimp_gegl_buffer_copy ( - src_buffer, - GEGL_RECTANGLE (src_x, src_y, - ABS (offset_x), ABS (offset_y)), - GEGL_ABYSS_NONE, - new_buffer, - GEGL_RECTANGLE (dest_x, dest_y, 0, 0)); - } - - /* X offset */ - if (offset_x != 0) - { - if (offset_y >= 0) - { - src_rect.x = src_x; - src_rect.y = 0; - src_rect.width = ABS (offset_x); - src_rect.height = gimp_item_get_height (item) - ABS (offset_y); - - dest_rect.x = dest_x; - dest_rect.y = dest_y + offset_y; - } - else if (offset_y < 0) - { - src_rect.x = src_x; - src_rect.y = src_y - offset_y; - src_rect.width = ABS (offset_x); - src_rect.height = gimp_item_get_height (item) - ABS (offset_y); - - dest_rect.x = dest_x; - dest_rect.y = 0; - } - - gimp_gegl_buffer_copy (src_buffer, &src_rect, GEGL_ABYSS_NONE, - new_buffer, &dest_rect); - } - - /* X offset */ - if (offset_y != 0) - { - if (offset_x >= 0) - { - src_rect.x = 0; - src_rect.y = src_y; - src_rect.width = gimp_item_get_width (item) - ABS (offset_x); - src_rect.height = ABS (offset_y); - - dest_rect.x = dest_x + offset_x; - dest_rect.y = dest_y; - } - else if (offset_x < 0) - { - src_rect.x = src_x - offset_x; - src_rect.y = src_y; - src_rect.width = gimp_item_get_width (item) - ABS (offset_x); - src_rect.height = ABS (offset_y); - - dest_rect.x = 0; - dest_rect.y = dest_y; - } - - gimp_gegl_buffer_copy (src_buffer, &src_rect, GEGL_ABYSS_NONE, - new_buffer, &dest_rect); - } - } + node = gegl_node_new_child (NULL, + "operation", "gimp:offset", + "context", context, + "type", fill_type, + "x", offset_x, + "y", offset_y, + NULL); + + gimp_drawable_apply_operation (drawable, NULL, + C_("undo-type", "Offset Drawable"), + node); - gimp_drawable_set_buffer (drawable, - gimp_item_is_attached (item), - C_("undo-type", "Offset Drawable"), - new_buffer); - g_object_unref (new_buffer); + g_object_unref (node); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-operation.c gimp-2.10.14+om/app/core/gimpdrawable-operation.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-operation.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-operation.c 2019-04-07 11:38:14.000000000 +0000 @@ -27,11 +27,9 @@ #include "core-types.h" -#include "gegl/gimp-gegl-apply-operation.h" - #include "gimpdrawable.h" #include "gimpdrawable-operation.h" -#include "gimpdrawable-shadow.h" +#include "gimpdrawablefilter.h" #include "gimpprogress.h" #include "gimpsettings.h" @@ -44,8 +42,7 @@ const gchar *undo_desc, GeglNode *operation) { - GeglBuffer *dest_buffer; - GeglRectangle rect; + GimpDrawableFilter *filter; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); @@ -54,21 +51,17 @@ g_return_if_fail (GEGL_IS_NODE (operation)); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), - &rect.x, &rect.y, - &rect.width, &rect.height)) - return; - - dest_buffer = gimp_drawable_get_shadow_buffer (drawable); + NULL, NULL, NULL, NULL)) + { + return; + } - gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable), - progress, undo_desc, - operation, - dest_buffer, &rect, FALSE); + filter = gimp_drawable_filter_new (drawable, undo_desc, operation, NULL); - gimp_drawable_merge_shadow_buffer (drawable, TRUE, undo_desc); - gimp_drawable_free_shadow_buffer (drawable); + gimp_drawable_filter_apply (filter, NULL); + gimp_drawable_filter_commit (filter, progress, TRUE); - gimp_drawable_update (drawable, rect.x, rect.y, rect.width, rect.height); + g_object_unref (filter); if (progress) gimp_progress_end (progress); diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-private.h gimp-2.10.14+om/app/core/gimpdrawable-private.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable-private.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-private.h 2019-10-26 18:49:18.000000000 +0000 @@ -26,7 +26,7 @@ GeglNode *source_node; GeglNode *buffer_source_node; GimpContainer *filter_stack; - GeglNode *convert_format; + GeglRectangle bounding_box; GimpLayer *floating_selection; GimpFilter *fs_filter; diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawablestack.c gimp-2.10.14+om/app/core/gimpdrawablestack.c --- gimp-2.10.8+zorin2/app/core/gimpdrawablestack.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawablestack.c 2019-10-26 18:49:18.000000000 +0000 @@ -211,13 +211,14 @@ gimp_drawable_stack_drawable_active (GimpItem *item, GimpDrawableStack *stack) { - gint offset_x; - gint offset_y; + GeglRectangle bounding_box; - gimp_item_get_offset (item, &offset_x, &offset_y); + bounding_box = gimp_drawable_get_bounding_box (GIMP_DRAWABLE (item)); + + bounding_box.x += gimp_item_get_offset_x (item); + bounding_box.y += gimp_item_get_offset_y (item); gimp_drawable_stack_update (stack, - offset_x, offset_y, - gimp_item_get_width (item), - gimp_item_get_height (item)); + bounding_box.x, bounding_box.y, + bounding_box.width, bounding_box.height); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-transform.c gimp-2.10.14+om/app/core/gimpdrawable-transform.c --- gimp-2.10.8+zorin2/app/core/gimpdrawable-transform.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-transform.c 2019-10-26 18:49:18.000000000 +0000 @@ -15,8 +15,6 @@ * along with this program. If not, see . */ -#define GEGL_ITERATOR2_API - #include "config.h" #include @@ -66,37 +64,6 @@ /* public functions */ -GimpTransformResize -gimp_drawable_transform_get_effective_clip (GimpDrawable *drawable, - GeglBuffer *orig_buffer, - GimpTransformResize clip_result) -{ - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), clip_result); - g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), - clip_result); - g_return_val_if_fail (orig_buffer == NULL || GEGL_IS_BUFFER (orig_buffer), - clip_result); - - /* Always clip unfloated buffers since they must keep their size */ - if (GIMP_IS_CHANNEL (drawable)) - { - if (orig_buffer) - { - if (! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) - clip_result = GIMP_TRANSFORM_RESIZE_CLIP; - } - else - { - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); - - if (gimp_channel_is_empty (gimp_image_get_mask (image))) - clip_result = GIMP_TRANSFORM_RESIZE_CLIP; - } - } - - return clip_result; -} - GeglBuffer * gimp_drawable_transform_buffer_affine (GimpDrawable *drawable, GimpContext *context, @@ -144,10 +111,6 @@ u2 = u1 + gegl_buffer_get_width (orig_buffer); v2 = v1 + gegl_buffer_get_height (orig_buffer); - clip_result = gimp_drawable_transform_get_effective_clip (drawable, - orig_buffer, - clip_result); - /* Find the bounding coordinates of target */ gimp_transform_resize_boundary (&m, clip_result, u1, v1, u2, v2, @@ -779,10 +742,6 @@ gint new_offset_y; GimpColorProfile *profile; - clip_result = gimp_drawable_transform_get_effective_clip (drawable, - orig_buffer, - clip_result); - /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && @@ -867,11 +826,6 @@ gint new_offset_y; GimpColorProfile *profile; - /* always clip unfloated buffers so they keep their size */ - if (GIMP_IS_CHANNEL (drawable) && - ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) - clip_result = TRUE; - /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && @@ -952,11 +906,6 @@ gint new_offset_y; GimpColorProfile *profile; - /* always clip unfloated buffers so they keep their size */ - if (GIMP_IS_CHANNEL (drawable) && - ! babl_format_has_alpha (gegl_buffer_get_format (orig_buffer))) - clip_result = TRUE; - /* also transform the mask if we are transforming an entire layer */ if (GIMP_IS_LAYER (drawable) && gimp_layer_get_mask (GIMP_LAYER (drawable)) && @@ -1111,7 +1060,7 @@ { gimp_drawable_set_buffer_full (drawable, TRUE, NULL, buffer, - offset_x, offset_y, + GEGL_RECTANGLE (offset_x, offset_y, 0, 0), TRUE); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawable-transform.h gimp-2.10.14+om/app/core/gimpdrawable-transform.h --- gimp-2.10.8+zorin2/app/core/gimpdrawable-transform.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawable-transform.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,6 @@ #define __GIMP_DRAWABLE_TRANSFORM_H__ -GimpTransformResize gimp_drawable_transform_get_effective_clip (GimpDrawable *drawable, - GeglBuffer *orig_buffer, - GimpTransformResize clip_result); - GeglBuffer * gimp_drawable_transform_buffer_affine (GimpDrawable *drawable, GimpContext *context, GeglBuffer *orig_buffer, diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawableundo.c gimp-2.10.14+om/app/core/gimpdrawableundo.c --- gimp-2.10.8+zorin2/app/core/gimpdrawableundo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawableundo.c 2019-01-03 14:13:22.000000000 +0000 @@ -202,7 +202,6 @@ GimpDrawableUndo *drawable_undo = GIMP_DRAWABLE_UNDO (undo); g_clear_object (&drawable_undo->buffer); - g_clear_object (&drawable_undo->applied_buffer); GIMP_UNDO_CLASS (parent_class)->free (undo, undo_mode); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpdrawableundo.h gimp-2.10.14+om/app/core/gimpdrawableundo.h --- gimp-2.10.8+zorin2/app/core/gimpdrawableundo.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpdrawableundo.h 2019-01-03 14:13:22.000000000 +0000 @@ -40,14 +40,6 @@ GeglBuffer *buffer; gint x; gint y; - - /* stuff for "Fade" */ - GeglBuffer *applied_buffer; - GimpLayerMode paint_mode; - GimpLayerColorSpace blend_space; - GimpLayerColorSpace composite_space; - GimpLayerCompositeMode composite_mode; - gdouble opacity; }; struct _GimpDrawableUndoClass diff -Nru gimp-2.10.8+zorin2/app/core/gimp-edit.c gimp-2.10.14+om/app/core/gimp-edit.c --- gimp-2.10.8+zorin2/app/core/gimp-edit.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-edit.c 2019-06-12 16:43:38.000000000 +0000 @@ -30,11 +30,11 @@ #include "gimp-edit.h" #include "gimpbuffer.h" #include "gimpcontext.h" +#include "gimpgrouplayer.h" #include "gimpimage.h" #include "gimpimage-duplicate.h" #include "gimpimage-new.h" #include "gimpimage-undo.h" -#include "gimplayer.h" #include "gimplayer-floating-selection.h" #include "gimplayer-new.h" #include "gimplist.h" @@ -207,6 +207,25 @@ g_return_val_if_reached (FALSE); } +static gboolean +gimp_edit_paste_is_floating (GimpPasteType paste_type) +{ + switch (paste_type) + { + case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_INTO: + case GIMP_PASTE_TYPE_FLOATING_IN_PLACE: + case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE: + return TRUE; + + case GIMP_PASTE_TYPE_NEW_LAYER: + case GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE: + return FALSE; + } + + g_return_val_if_reached (FALSE); +} + static GimpLayer * gimp_edit_paste_get_layer (GimpImage *image, GimpDrawable *drawable, @@ -232,7 +251,7 @@ /* floating pastes always have the pasted-to drawable's format with * alpha; if drawable == NULL, user is pasting into an empty image */ - if (drawable) + if (drawable && gimp_edit_paste_is_floating (*paste_type)) floating_format = gimp_drawable_get_format_with_alpha (drawable); else floating_format = gimp_image_get_layer_format (image, TRUE); @@ -249,11 +268,15 @@ case GIMP_PASTE_TYPE_FLOATING_IN_PLACE: case GIMP_PASTE_TYPE_FLOATING_INTO: case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE: - /* when pasting as floating selection, force creation of a - * plain layer, so gimp_item_convert() will collapse a - * group layer + /* when pasting as floating make sure gimp_item_convert() + * will turn group layers into normal layers, otherwise use + * the same layer type so e.g. text information gets + * preserved. See issue #2667. */ - layer_type = GIMP_TYPE_LAYER; + if (GIMP_IS_GROUP_LAYER (layer)) + layer_type = GIMP_TYPE_LAYER; + else + layer_type = G_TYPE_FROM_INSTANCE (layer); break; case GIMP_PASTE_TYPE_NEW_LAYER: diff -Nru gimp-2.10.8+zorin2/app/core/gimpfilloptions.c gimp-2.10.14+om/app/core/gimpfilloptions.c --- gimp-2.10.8+zorin2/app/core/gimpfilloptions.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpfilloptions.c 2019-06-12 16:43:38.000000000 +0000 @@ -29,6 +29,8 @@ #include "core-types.h" +#include "operations/layer-modes/gimp-layer-modes.h" + #include "gimp.h" #include "gimp-palettes.h" #include "gimpdrawable.h" @@ -45,6 +47,8 @@ PROP_0, PROP_STYLE, PROP_ANTIALIAS, + PROP_FEATHER, + PROP_FEATHER_RADIUS, PROP_PATTERN_VIEW_TYPE, PROP_PATTERN_VIEW_SIZE }; @@ -56,6 +60,8 @@ { GimpFillStyle style; gboolean antialias; + gboolean feather; + gdouble feather_radius; GimpViewType pattern_view_type; GimpViewSize pattern_view_size; @@ -112,6 +118,20 @@ TRUE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_FEATHER, + "feather", + _("Feather edges"), + _("Enable feathering of fill edges"), + FALSE, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_FEATHER_RADIUS, + "feather-radius", + _("Radius"), + _("Radius of feathering"), + 0.0, 100.0, 10.0, + GIMP_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_PATTERN_VIEW_TYPE, g_param_spec_enum ("pattern-view-type", NULL, NULL, @@ -158,6 +178,12 @@ case PROP_ANTIALIAS: private->antialias = g_value_get_boolean (value); break; + case PROP_FEATHER: + private->feather = g_value_get_boolean (value); + break; + case PROP_FEATHER_RADIUS: + private->feather_radius = g_value_get_double (value); + break; case PROP_PATTERN_VIEW_TYPE: private->pattern_view_type = g_value_get_enum (value); @@ -188,6 +214,12 @@ case PROP_ANTIALIAS: g_value_set_boolean (value, private->antialias); break; + case PROP_FEATHER: + g_value_set_boolean (value, private->feather); + break; + case PROP_FEATHER_RADIUS: + g_value_set_double (value, private->feather_radius); + break; case PROP_PATTERN_VIEW_TYPE: g_value_set_enum (value, private->pattern_view_type); @@ -276,6 +308,29 @@ } gboolean +gimp_fill_options_get_feather (GimpFillOptions *options, + gdouble *radius) +{ + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), FALSE); + + if (radius) + *radius = GET_PRIVATE (options)->feather_radius; + + return GET_PRIVATE (options)->feather; +} + +void +gimp_fill_options_set_feather (GimpFillOptions *options, + gboolean feather, + gdouble radius) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + + g_object_set (options, "feather", feather, NULL); + g_object_set (options, "feather-radius", radius, NULL); +} + +gboolean gimp_fill_options_set_by_fill_type (GimpFillOptions *options, GimpContext *context, GimpFillType fill_type, @@ -404,6 +459,25 @@ g_return_val_if_reached (NULL); } +const Babl * +gimp_fill_options_get_format (GimpFillOptions *options, + GimpDrawable *drawable) +{ + GimpContext *context; + + g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + + context = GIMP_CONTEXT (options); + + return gimp_layer_mode_get_format (gimp_context_get_paint_mode (context), + GIMP_LAYER_COLOR_SPACE_AUTO, + GIMP_LAYER_COLOR_SPACE_AUTO, + gimp_layer_mode_get_paint_composite_mode ( + gimp_context_get_paint_mode (context)), + gimp_drawable_get_format (drawable)); +} + GeglBuffer * gimp_fill_options_create_buffer (GimpFillOptions *options, GimpDrawable *drawable, @@ -411,7 +485,7 @@ gint pattern_offset_x, gint pattern_offset_y) { - GeglBuffer *buffer; + GeglBuffer *buffer; g_return_val_if_fail (GIMP_IS_FILL_OPTIONS (options), NULL); g_return_val_if_fail (gimp_fill_options_get_style (options) != @@ -422,7 +496,27 @@ g_return_val_if_fail (rect != NULL, NULL); buffer = gegl_buffer_new (rect, - gimp_drawable_get_format_with_alpha (drawable)); + gimp_fill_options_get_format (options, drawable)); + + gimp_fill_options_fill_buffer (options, drawable, buffer, + pattern_offset_x, pattern_offset_y); + + return buffer; +} + +void +gimp_fill_options_fill_buffer (GimpFillOptions *options, + GimpDrawable *drawable, + GeglBuffer *buffer, + gint pattern_offset_x, + gint pattern_offset_y) +{ + g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); + g_return_if_fail (gimp_fill_options_get_style (options) != + GIMP_FILL_STYLE_PATTERN || + gimp_context_get_pattern (GIMP_CONTEXT (options)) != NULL); + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (GEGL_IS_BUFFER (buffer)); switch (gimp_fill_options_get_style (options)) { @@ -451,6 +545,4 @@ } break; } - - return buffer; } diff -Nru gimp-2.10.8+zorin2/app/core/gimpfilloptions.h gimp-2.10.14+om/app/core/gimpfilloptions.h --- gimp-2.10.8+zorin2/app/core/gimpfilloptions.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpfilloptions.h 2019-04-07 11:38:14.000000000 +0000 @@ -60,6 +60,12 @@ void gimp_fill_options_set_antialias (GimpFillOptions *options, gboolean antialias); +gboolean gimp_fill_options_get_feather (GimpFillOptions *options, + gdouble *radius); +void gimp_fill_options_set_feather (GimpFillOptions *options, + gboolean feather, + gdouble radius); + gboolean gimp_fill_options_set_by_fill_type (GimpFillOptions *options, GimpContext *context, GimpFillType fill_type, @@ -71,11 +77,19 @@ const gchar * gimp_fill_options_get_undo_desc (GimpFillOptions *options); +const Babl * gimp_fill_options_get_format (GimpFillOptions *options, + GimpDrawable *drawable); + GeglBuffer * gimp_fill_options_create_buffer (GimpFillOptions *options, GimpDrawable *drawable, const GeglRectangle *rect, gint pattern_offset_x, gint pattern_offset_y); +void gimp_fill_options_fill_buffer (GimpFillOptions *options, + GimpDrawable *drawable, + GeglBuffer *buffer, + gint pattern_offset_x, + gint pattern_offset_y); #endif /* __GIMP_FILL_OPTIONS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpgradient.c gimp-2.10.14+om/app/core/gimpgradient.c --- gimp-2.10.8+zorin2/app/core/gimpgradient.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpgradient.c 2019-01-03 14:13:22.000000000 +0000 @@ -70,7 +70,7 @@ static gchar * gimp_gradient_get_checksum (GimpTagged *tagged); -static GimpGradientSegment * +static inline GimpGradientSegment * gimp_gradient_get_segment_at_internal (GimpGradient *gradient, GimpGradientSegment *seg, gdouble pos); @@ -460,7 +460,8 @@ GimpRGB right_color; GimpRGB rgb; - g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL); + /* type-check disabled to improve speed */ + /* g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL); */ g_return_val_if_fail (color != NULL, NULL); pos = CLAMP (pos, 0.0, 1.0); @@ -516,11 +517,19 @@ /* Get left/right colors */ - gimp_gradient_segment_get_left_flat_color (gradient, - context, seg, &left_color); + if (context) + { + gimp_gradient_segment_get_left_flat_color (gradient, + context, seg, &left_color); - gimp_gradient_segment_get_right_flat_color (gradient, - context, seg, &right_color); + gimp_gradient_segment_get_right_flat_color (gradient, + context, seg, &right_color); + } + else + { + left_color = seg->left_color; + right_color = seg->right_color; + } /* Calculate color components */ @@ -2160,7 +2169,7 @@ /* private functions */ -static GimpGradientSegment * +static inline GimpGradientSegment * gimp_gradient_get_segment_at_internal (GimpGradient *gradient, GimpGradientSegment *seg, gdouble pos) diff -Nru gimp-2.10.8+zorin2/app/core/gimpgradient-save.c gimp-2.10.14+om/app/core/gimpgradient-save.c --- gimp-2.10.8+zorin2/app/core/gimpgradient-save.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpgradient-save.c 2019-10-26 18:49:18.000000000 +0000 @@ -72,28 +72,17 @@ { gchar buf[11][G_ASCII_DTOSTR_BUF_SIZE]; - g_ascii_formatd (buf[0], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->left); - g_ascii_formatd (buf[1], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->middle); - g_ascii_formatd (buf[2], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->right); - g_ascii_formatd (buf[3], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->left_color.r); - g_ascii_formatd (buf[4], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->left_color.g); - g_ascii_formatd (buf[5], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->left_color.b); - g_ascii_formatd (buf[6], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->left_color.a); - g_ascii_formatd (buf[7], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->right_color.r); - g_ascii_formatd (buf[8], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->right_color.g); - g_ascii_formatd (buf[9], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->right_color.b); - g_ascii_formatd (buf[10], G_ASCII_DTOSTR_BUF_SIZE, - "%f", seg->right_color.a); + g_ascii_dtostr (buf[0], G_ASCII_DTOSTR_BUF_SIZE, seg->left); + g_ascii_dtostr (buf[1], G_ASCII_DTOSTR_BUF_SIZE, seg->middle); + g_ascii_dtostr (buf[2], G_ASCII_DTOSTR_BUF_SIZE, seg->right); + g_ascii_dtostr (buf[3], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.r); + g_ascii_dtostr (buf[4], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.g); + g_ascii_dtostr (buf[5], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.b); + g_ascii_dtostr (buf[6], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.a); + g_ascii_dtostr (buf[7], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.r); + g_ascii_dtostr (buf[8], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.g); + g_ascii_dtostr (buf[9], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.b); + g_ascii_dtostr (buf[10], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.a); g_string_append_printf (string, "%s %s %s %s %s %s %s %s %s %s %s %d %d %d %d\n", @@ -148,16 +137,16 @@ for (seg = gradient->segments; seg; seg = seg->next) { /* Left */ - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->left); - g_ascii_formatd (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->left_color.r); - g_ascii_formatd (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->left_color.g); - g_ascii_formatd (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->left_color.b); - g_ascii_formatd (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, "%f", - 1.0 - seg->left_color.a); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + seg->left); + g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, + seg->left_color.r); + g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, + seg->left_color.g); + g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, + seg->left_color.b); + g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, + 1.0 - seg->left_color.a); g_string_append_printf (string, "\t[%s color rgbt <%s, %s, %s, %s>]\n", @@ -166,16 +155,16 @@ color_buf[2], color_buf[3]); /* Middle */ - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->middle); - g_ascii_formatd (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, "%f", - (seg->left_color.r + seg->right_color.r) / 2.0); - g_ascii_formatd (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, "%f", - (seg->left_color.g + seg->right_color.g) / 2.0); - g_ascii_formatd (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, "%f", - (seg->left_color.b + seg->right_color.b) / 2.0); - g_ascii_formatd (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, "%f", - 1.0 - (seg->left_color.a + seg->right_color.a) / 2.0); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + seg->middle); + g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, + (seg->left_color.r + seg->right_color.r) / 2.0); + g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, + (seg->left_color.g + seg->right_color.g) / 2.0); + g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, + (seg->left_color.b + seg->right_color.b) / 2.0); + g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, + 1.0 - (seg->left_color.a + seg->right_color.a) / 2.0); g_string_append_printf (string, "\t[%s color rgbt <%s, %s, %s, %s>]\n", @@ -184,16 +173,16 @@ color_buf[2], color_buf[3]); /* Right */ - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->right); - g_ascii_formatd (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->right_color.r); - g_ascii_formatd (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->right_color.g); - g_ascii_formatd (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, "%f", - seg->right_color.b); - g_ascii_formatd (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, "%f", - 1.0 - seg->right_color.a); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + seg->right); + g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, + seg->right_color.r); + g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, + seg->right_color.g); + g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, + seg->right_color.b); + g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, + 1.0 - seg->right_color.a); g_string_append_printf (string, "\t[%s color rgbt <%s, %s, %s, %s>]\n", @@ -207,13 +196,21 @@ if (! g_output_stream_write_all (output, string->str, string->len, NULL, NULL, &my_error)) { + GCancellable *cancellable = g_cancellable_new (); + g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, _("Writing POV file '%s' failed: %s"), gimp_file_get_utf8_name (file), my_error->message); g_clear_error (&my_error); g_string_free (string, TRUE); + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); g_object_unref (output); + return FALSE; } diff -Nru gimp-2.10.8+zorin2/app/core/gimpgrouplayer.c gimp-2.10.14+om/app/core/gimpgrouplayer.c --- gimp-2.10.8+zorin2/app/core/gimpgrouplayer.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpgrouplayer.c 2019-10-26 18:49:18.000000000 +0000 @@ -58,6 +58,7 @@ GeglNode *parent_source_node; GeglNode *graph; GeglNode *offset_node; + GeglRectangle bounding_box; gint suspend_resize; gint suspend_mask; GeglBuffer *suspended_mask_buffer; @@ -70,8 +71,6 @@ /* hackish temp states to make the projection/tiles stuff work */ const Babl *convert_format; gboolean reallocate_projection; - gint reallocate_width; - gint reallocate_height; }; #define GET_PRIVATE(item) ((GimpGroupLayerPrivate *) gimp_group_layer_get_instance_private ((GimpGroupLayer *) (item))) @@ -124,6 +123,7 @@ GimpComponentType component_type, gint width, gint height); +static void gimp_group_layer_update_all (GimpDrawable *drawable); static void gimp_group_layer_translate (GimpLayer *layer, gint offset_x, @@ -177,6 +177,8 @@ gimp_group_layer_get_excludes_backdrop (GimpLayer *layer); static const Babl * gimp_group_layer_get_format (GimpProjectable *projectable); +static GeglRectangle + gimp_group_layer_get_bounding_box (GimpProjectable *projectable); static GeglNode * gimp_group_layer_get_graph (GimpProjectable *projectable); static void gimp_group_layer_begin_render (GimpProjectable *projectable); static void gimp_group_layer_end_render (GimpProjectable *projectable); @@ -285,6 +287,7 @@ item_class->transform_desc = C_("undo-type", "Transform Layer Group"); drawable_class->estimate_memsize = gimp_group_layer_estimate_memsize; + drawable_class->update_all = gimp_group_layer_update_all; drawable_class->get_source_node = gimp_group_layer_get_source_node; layer_class->opacity_changed = gimp_group_layer_opacity_changed; @@ -310,7 +313,7 @@ iface->get_image = (GimpImage * (*) (GimpProjectable *)) gimp_item_get_image; iface->get_format = gimp_group_layer_get_format; iface->get_offset = (void (*) (GimpProjectable*, gint*, gint*)) gimp_item_get_offset; - iface->get_size = (void (*) (GimpProjectable*, gint*, gint*)) gimp_viewable_get_size; + iface->get_bounding_box = gimp_group_layer_get_bounding_box; iface->get_graph = gimp_group_layer_get_graph; iface->begin_render = gimp_group_layer_begin_render; iface->end_render = gimp_group_layer_end_render; @@ -347,6 +350,9 @@ gimp_container_add_handler (private->children, "size-changed", G_CALLBACK (gimp_group_layer_child_resize), group); + gimp_container_add_handler (private->children, "bounding-box-changed", + G_CALLBACK (gimp_group_layer_child_resize), + group); gimp_container_add_handler (private->children, "active-changed", G_CALLBACK (gimp_group_layer_child_active_changed), group); @@ -456,21 +462,14 @@ { GimpGroupLayerPrivate *private = GET_PRIVATE (viewable); - if (private->reallocate_width != 0 && - private->reallocate_height != 0) + /* return the size only if there are children ... */ + if (! gimp_container_is_empty (private->children)) { - *width = private->reallocate_width; - *height = private->reallocate_height; - - return TRUE; + return GIMP_VIEWABLE_CLASS (parent_class)->get_size (viewable, + width, height); } - /* return the size only if there are children... */ - if (gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children))) - return GIMP_VIEWABLE_CLASS (parent_class)->get_size (viewable, - width, height); - - /* ...otherwise return "no content" */ + /* ... otherwise, return "no content" */ return FALSE; } @@ -740,6 +739,29 @@ } static void +gimp_group_layer_update_all (GimpDrawable *drawable) +{ + GimpGroupLayerPrivate *private = GET_PRIVATE (drawable); + GList *list; + + /* redirect stack updates to the drawable, rather than to the projection */ + private->direct_update++; + + for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children)); + list; + list = g_list_next (list)) + { + GimpFilter *child = list->data; + + if (gimp_filter_get_active (child)) + gimp_drawable_update_all (GIMP_DRAWABLE (child)); + } + + /* redirect stack updates back to the projection */ + private->direct_update--; +} + +static void gimp_group_layer_translate (GimpLayer *layer, gint offset_x, gint offset_y) @@ -758,6 +780,26 @@ /* redirect stack updates to the drawable, rather than to the projection */ private->direct_update++; + /* translate the child layers *before* updating the group's offset, so that, + * if this is a nested group, the parent's bounds still reflect the original + * layer positions. This prevents the original area of the child layers, + * which is updated as part of their translation, from being clipped to the + * post-translation parent bounds (see issue #3484). The new area of the + * child layers, which is likewise updated as part of translation, *may* get + * clipped to the old parent bounds, but the corresponding region will be + * updated anyway when the parent is resized, once we update the group's + * offset. + */ + for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children)); + list; + list = g_list_next (list)) + { + GimpItem *child = list->data; + + /* don't push an undo here because undo will call us again */ + gimp_item_translate (child, offset_x, offset_y, FALSE); + } + gimp_item_get_offset (GIMP_ITEM (group), &x, &y); x += offset_x; @@ -776,16 +818,6 @@ /* update the group layer offset */ gimp_item_set_offset (GIMP_ITEM (group), x, y); - for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children)); - list; - list = g_list_next (list)) - { - GimpItem *child = list->data; - - /* don't push an undo here because undo will call us again */ - gimp_item_translate (child, offset_x, offset_y, FALSE); - } - /* redirect stack updates back to the projection */ private->direct_update--; @@ -1006,12 +1038,6 @@ gimp_image_undo_push_group_layer_convert (image, NULL, group); } - /* Force allocation of a same-size projection, in case the group - * layer is empty - */ - private->reallocate_width = gimp_item_get_width (GIMP_ITEM (group)); - private->reallocate_height = gimp_item_get_height (GIMP_ITEM (group)); - /* Need to temporarily set the projectable's format to the new * values so the projection will create its tiles with the right * depth @@ -1027,16 +1053,11 @@ gimp_drawable_set_buffer_full (GIMP_DRAWABLE (group), FALSE, NULL, - buffer, - gimp_item_get_offset_x (GIMP_ITEM (group)), - gimp_item_get_offset_y (GIMP_ITEM (group)), + buffer, NULL, TRUE); /* reset, the actual format is right now */ private->convert_format = NULL; - - private->reallocate_width = 0; - private->reallocate_height = 0; } static GeglNode * @@ -1129,10 +1150,22 @@ static void gimp_group_layer_mask_changed (GimpLayer *layer) { + GimpGroupLayer *group = GIMP_GROUP_LAYER (layer); + GimpGroupLayerPrivate *private = GET_PRIVATE (layer); + g_warn_if_fail (GET_PRIVATE (layer)->suspend_mask == 0); gimp_layer_update_effective_mode (layer); + /* if we've already computed a bounding box, update it now, since the mask + * limits the bounding box to the group's size. if we haven't computed a + * bounding box yet we can skip this, and, in fact, we have to, or else the + * mask will be improperly clipped when the group is duplicated, discarding + * its data. + */ + if (! gegl_rectangle_is_empty (&private->bounding_box)) + gimp_group_layer_update (group); + if (GIMP_LAYER_CLASS (parent_class)->mask_changed) GIMP_LAYER_CLASS (parent_class)->mask_changed (layer); } @@ -1302,6 +1335,14 @@ return get_projection_format (projectable, base_type, precision); } +static GeglRectangle +gimp_group_layer_get_bounding_box (GimpProjectable *projectable) +{ + GimpGroupLayerPrivate *private = GET_PRIVATE (projectable); + + return private->bounding_box; +} + static GeglNode * gimp_group_layer_get_graph (GimpProjectable *projectable) { @@ -1838,29 +1879,38 @@ GimpItem *item = GIMP_ITEM (group); GimpLayer *layer = GIMP_LAYER (group); GimpItem *mask = GIMP_ITEM (gimp_layer_get_mask (layer)); - gint old_x = gimp_item_get_offset_x (item); - gint old_y = gimp_item_get_offset_y (item); - gint old_width = gimp_item_get_width (item); - gint old_height = gimp_item_get_height (item); - gint x = 0; - gint y = 0; - gint width = 1; - gint height = 1; + GeglRectangle old_bounds; + GeglRectangle bounds; + GeglRectangle old_bounding_box; + GeglRectangle bounding_box; gboolean first = TRUE; gboolean size_changed; gboolean resize_mask; GList *list; + old_bounds.x = gimp_item_get_offset_x (item); + old_bounds.y = gimp_item_get_offset_y (item); + old_bounds.width = gimp_item_get_width (item); + old_bounds.height = gimp_item_get_height (item); + + bounds.x = 0; + bounds.y = 0; + bounds.width = 1; + bounds.height = 1; + + old_bounding_box = private->bounding_box; + bounding_box = bounds; + for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (private->children)); list; list = g_list_next (list)) { - GimpItem *child = list->data; - gint child_width; - gint child_height; + GimpItem *child = list->data; + GeglRectangle child_bounds; + GeglRectangle child_bounding_box; if (! gimp_viewable_get_size (GIMP_VIEWABLE (child), - &child_width, &child_height)) + &child_bounds.width, &child_bounds.height)) { /* ignore children without content (empty group layers); * see bug 777017 @@ -1868,39 +1918,47 @@ continue; } + gimp_item_get_offset (child, &child_bounds.x, &child_bounds.y); + + child_bounding_box = + gimp_drawable_get_bounding_box (GIMP_DRAWABLE (child)); + + child_bounding_box.x += child_bounds.x; + child_bounding_box.y += child_bounds.y; + if (first) { - x = gimp_item_get_offset_x (child); - y = gimp_item_get_offset_y (child); - width = child_width; - height = child_height; + bounds = child_bounds; + bounding_box = child_bounding_box; first = FALSE; } else { - gimp_rectangle_union (x, y, width, height, - gimp_item_get_offset_x (child), - gimp_item_get_offset_y (child), - child_width, - child_height, - &x, &y, &width, &height); + gegl_rectangle_bounding_box (&bounds, + &bounds, &child_bounds); + gegl_rectangle_bounding_box (&bounding_box, + &bounding_box, &child_bounding_box); } } - size_changed = (x != old_x || - y != old_y || - width != old_width || - height != old_height); + if (mask) + bounding_box = bounds; + + bounding_box.x -= bounds.x; + bounding_box.y -= bounds.y; - resize_mask = mask && size_changed; + size_changed = ! (gegl_rectangle_equal (&bounds, &old_bounds) && + gegl_rectangle_equal (&bounding_box, &old_bounding_box)); + + resize_mask = mask && ! gegl_rectangle_equal (&bounds, &old_bounds); /* if we show the mask, invalidate the old mask area */ if (resize_mask && gimp_layer_get_show_mask (layer)) { gimp_drawable_update (GIMP_DRAWABLE (group), - gimp_item_get_offset_x (mask) - old_x, - gimp_item_get_offset_y (mask) - old_y, + gimp_item_get_offset_x (mask) - old_bounds.x, + gimp_item_get_offset_y (mask) - old_bounds.y, gimp_item_get_width (mask), gimp_item_get_height (mask)); } @@ -1915,21 +1973,20 @@ */ if (private->offset_node) gegl_node_set (private->offset_node, - "x", (gdouble) -x, - "y", (gdouble) -y, + "x", (gdouble) -bounds.x, + "y", (gdouble) -bounds.y, NULL); /* update our offset *before* calling gimp_pickable_get_buffer(), so * that if our graph isn't constructed yet, the offset node picks * up the right coordinates in gimp_group_layer_get_graph(). */ - gimp_item_set_offset (item, x, y); + gimp_item_set_offset (item, bounds.x, bounds.y); - /* temporarily change the return values of gimp_viewable_get_size() - * so the projection allocates itself correctly + /* update the bounding box before updating the projection, so that it + * picks up the right size. */ - private->reallocate_width = width; - private->reallocate_height = height; + private->bounding_box = bounding_box; if (private->reallocate_projection) { @@ -1945,25 +2002,20 @@ * new buffer with an offset, rather than re-renders the graph. */ gimp_projectable_bounds_changed (GIMP_PROJECTABLE (group), - old_x, old_y, old_width, old_height); + old_bounds.x, old_bounds.y); } buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (private->projection)); gimp_drawable_set_buffer_full (GIMP_DRAWABLE (group), FALSE, NULL, - buffer, - x, y, + buffer, &bounds, FALSE /* don't update the drawable, the * flush() below will take care of * that. */); gimp_group_layer_flush (group); - - /* reset, the actual size is correct now */ - private->reallocate_width = 0; - private->reallocate_height = 0; } /* resize the mask if not transforming (in which case, GimpLayer takes care @@ -1976,8 +2028,8 @@ if (resize_mask && gimp_layer_get_show_mask (layer)) { gimp_drawable_update (GIMP_DRAWABLE (group), - gimp_item_get_offset_x (mask) - x, - gimp_item_get_offset_y (mask) - y, + gimp_item_get_offset_x (mask) - bounds.x, + gimp_item_get_offset_y (mask) - bounds.y, gimp_item_get_width (mask), gimp_item_get_height (mask)); } @@ -2059,7 +2111,7 @@ gimp_drawable_set_buffer_full (GIMP_DRAWABLE (mask), FALSE, NULL, - buffer, bounds.x, bounds.y, + buffer, &bounds, TRUE); g_object_unref (buffer); diff -Nru gimp-2.10.8+zorin2/app/core/gimpgrouplayerundo.c gimp-2.10.14+om/app/core/gimpgrouplayerundo.c --- gimp-2.10.8+zorin2/app/core/gimpgrouplayerundo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpgrouplayerundo.c 2019-10-26 18:49:18.000000000 +0000 @@ -158,8 +158,7 @@ gimp_drawable_set_buffer_full (GIMP_DRAWABLE (mask), FALSE, NULL, group_layer_undo->mask_buffer, - group_layer_undo->mask_bounds.x, - group_layer_undo->mask_bounds.y, + &group_layer_undo->mask_bounds, TRUE); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimphistogram.c gimp-2.10.14+om/app/core/gimphistogram.c --- gimp-2.10.8+zorin2/app/core/gimphistogram.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimphistogram.c 2019-10-26 18:49:18.000000000 +0000 @@ -17,8 +17,6 @@ * along with this program. If not, see . */ -#define GEGL_ITERATOR2_API - #include "config.h" #include @@ -41,14 +39,17 @@ #include "gimpwaitable.h" -#define MIN_PARALLEL_SUB_SIZE 64 -#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE) +#define MAX_N_COMPONENTS 4 +#define N_DERIVED_CHANNELS 2 + +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) enum { PROP_0, - PROP_N_CHANNELS, + PROP_N_COMPONENTS, PROP_N_BINS, PROP_VALUES }; @@ -89,30 +90,33 @@ /* local function prototypes */ -static void gimp_histogram_finalize (GObject *object); -static void gimp_histogram_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_histogram_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static gint64 gimp_histogram_get_memsize (GimpObject *object, - gint64 *gui_size); - -static void gimp_histogram_set_values (GimpHistogram *histogram, - gint n_components, - gint n_bins, - gdouble *values); - -static void gimp_histogram_calculate_internal (GimpAsync *async, - CalculateContext *context); -static void gimp_histogram_calculate_area (const GeglRectangle *area, - CalculateData *data); -static void gimp_histogram_calculate_async_callback (GimpAsync *async, - CalculateContext *context); +static void gimp_histogram_finalize (GObject *object); +static void gimp_histogram_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_histogram_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gint64 gimp_histogram_get_memsize (GimpObject *object, + gint64 *gui_size); + +static gboolean gimp_histogram_map_channel (GimpHistogram *histogram, + GimpHistogramChannel *channel); + +static void gimp_histogram_set_values (GimpHistogram *histogram, + gint n_components, + gint n_bins, + gdouble *values); + +static void gimp_histogram_calculate_internal (GimpAsync *async, + CalculateContext *context); +static void gimp_histogram_calculate_area (const GeglRectangle *area, + CalculateData *data); +static void gimp_histogram_calculate_async_callback (GimpAsync *async, + CalculateContext *context); G_DEFINE_TYPE_WITH_PRIVATE (GimpHistogram, gimp_histogram, GIMP_TYPE_OBJECT) @@ -132,9 +136,9 @@ gimp_object_class->get_memsize = gimp_histogram_get_memsize; - g_object_class_install_property (object_class, PROP_N_CHANNELS, - g_param_spec_int ("n-channels", NULL, NULL, - 0, 6, 0, + g_object_class_install_property (object_class, PROP_N_COMPONENTS, + g_param_spec_int ("n-components", NULL, NULL, + 0, MAX_N_COMPONENTS, 0, GIMP_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_N_BINS, @@ -162,7 +166,7 @@ { GimpHistogram *histogram = GIMP_HISTOGRAM (object); - gimp_histogram_clear_values (histogram); + gimp_histogram_clear_values (histogram, 0); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -191,8 +195,8 @@ switch (property_id) { - case PROP_N_CHANNELS: - g_value_set_int (value, histogram->priv->n_channels); + case PROP_N_COMPONENTS: + g_value_set_int (value, gimp_histogram_n_components (histogram)); break; case PROP_N_BINS: @@ -313,6 +317,7 @@ const GeglRectangle *mask_rect) { CalculateContext *context; + GeglRectangle rect; g_return_val_if_fail (GIMP_IS_HISTOGRAM (histogram), NULL); g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); @@ -321,14 +326,17 @@ if (histogram->priv->calculate_async) gimp_async_cancel_and_wait (histogram->priv->calculate_async); + gegl_rectangle_align_to_buffer (&rect, buffer_rect, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + context = g_slice_new0 (CalculateContext); context->histogram = histogram; - context->buffer = gegl_buffer_new (buffer_rect, + context->buffer = gegl_buffer_new (&rect, gegl_buffer_get_format (buffer)); context->buffer_rect = *buffer_rect; - gimp_gegl_buffer_copy (buffer, buffer_rect, GEGL_ABYSS_NONE, + gimp_gegl_buffer_copy (buffer, &rect, GEGL_ABYSS_NONE, context->buffer, NULL); if (mask) @@ -338,10 +346,12 @@ else context->mask_rect = *gegl_buffer_get_extent (mask); - context->mask = gegl_buffer_new (&context->mask_rect, - gegl_buffer_get_format (mask)); + gegl_rectangle_align_to_buffer (&rect, &context->mask_rect, mask, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + context->mask = gegl_buffer_new (&rect, gegl_buffer_get_format (mask)); - gimp_gegl_buffer_copy (mask, &context->mask_rect, GEGL_ABYSS_NONE, + gimp_gegl_buffer_copy (mask, &rect, GEGL_ABYSS_NONE, context->mask, NULL); } @@ -358,27 +368,15 @@ } void -gimp_histogram_clear_values (GimpHistogram *histogram) +gimp_histogram_clear_values (GimpHistogram *histogram, + gint n_components) { g_return_if_fail (GIMP_IS_HISTOGRAM (histogram)); if (histogram->priv->calculate_async) gimp_async_cancel_and_wait (histogram->priv->calculate_async); - if (histogram->priv->values) - { - g_free (histogram->priv->values); - histogram->priv->values = NULL; - - g_object_notify (G_OBJECT (histogram), "values"); - } - - if (histogram->priv->n_channels) - { - histogram->priv->n_channels = 0; - - g_object_notify (G_OBJECT (histogram), "n-channels"); - } + gimp_histogram_set_values (histogram, n_components, 0, NULL); } @@ -397,16 +395,11 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - if (! priv->values || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0.0; + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } if (channel == GIMP_HISTOGRAM_RGB) { @@ -439,18 +432,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - - if (! priv->values || - bin < 0 || bin >= priv->n_bins || - (channel == GIMP_HISTOGRAM_RGB && priv->n_channels < 4) || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0.0; + if (! priv->values || + (bin < 0 || bin >= priv->n_bins) || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } if (channel == GIMP_HISTOGRAM_RGB) { @@ -473,18 +460,21 @@ { g_return_val_if_fail (GIMP_IS_HISTOGRAM (histogram), 0.0); - if (histogram->priv->n_channels > 4) + if (gimp_histogram_n_components (histogram) > 2) component++; return gimp_histogram_get_value (histogram, component, bin); } gint -gimp_histogram_n_channels (GimpHistogram *histogram) +gimp_histogram_n_components (GimpHistogram *histogram) { g_return_val_if_fail (GIMP_IS_HISTOGRAM (histogram), 0); - return histogram->priv->n_channels - 2; + if (histogram->priv->n_channels > 0) + return histogram->priv->n_channels - N_DERIVED_CHANNELS; + else + return 0; } gint @@ -495,6 +485,32 @@ return histogram->priv->n_bins; } +gboolean +gimp_histogram_has_channel (GimpHistogram *histogram, + GimpHistogramChannel channel) +{ + g_return_val_if_fail (GIMP_IS_HISTOGRAM (histogram), FALSE); + + switch (channel) + { + case GIMP_HISTOGRAM_VALUE: + return TRUE; + + case GIMP_HISTOGRAM_RED: + case GIMP_HISTOGRAM_GREEN: + case GIMP_HISTOGRAM_BLUE: + case GIMP_HISTOGRAM_LUMINANCE: + case GIMP_HISTOGRAM_RGB: + return gimp_histogram_n_components (histogram) >= 3; + + case GIMP_HISTOGRAM_ALPHA: + return gimp_histogram_n_components (histogram) == 2 || + gimp_histogram_n_components (histogram) == 4; + } + + g_return_val_if_reached (FALSE); +} + gdouble gimp_histogram_get_count (GimpHistogram *histogram, GimpHistogramChannel channel, @@ -509,12 +525,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; + if (! priv->values || + start > end || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } if (channel == GIMP_HISTOGRAM_RGB) return (gimp_histogram_get_count (histogram, @@ -524,11 +540,6 @@ gimp_histogram_get_count (histogram, GIMP_HISTOGRAM_BLUE, start, end)); - if (! priv->values || - start > end || - channel >= priv->n_channels) - return 0.0; - start = CLAMP (start, 0, priv->n_bins - 1); end = CLAMP (end, 0, priv->n_bins - 1); @@ -553,18 +564,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - if (! priv->values || - start > end || - (channel == GIMP_HISTOGRAM_RGB && priv->n_channels < 5) || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0.0; + start > end || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } start = CLAMP (start, 0, priv->n_bins - 1); end = CLAMP (end, 0, priv->n_bins - 1); @@ -613,18 +618,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - if (! priv->values || - start > end || - (channel == GIMP_HISTOGRAM_RGB && priv->n_channels < 5) || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0.0; + start > end || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } start = CLAMP (start, 0, priv->n_bins - 1); end = CLAMP (end, 0, priv->n_bins - 1); @@ -685,18 +684,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - if (! priv->values || - start > end || - (channel == GIMP_HISTOGRAM_RGB && priv->n_channels < 5) || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0; + start > end || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0; + } start = CLAMP (start, 0, priv->n_bins - 1); end = CLAMP (end, 0, priv->n_bins - 1); @@ -776,18 +769,12 @@ priv = histogram->priv; - /* the gray alpha channel is in slot 1 */ - if (priv->n_channels == 4 && channel == GIMP_HISTOGRAM_ALPHA) - channel = 1; - /* the luminance channel is in slot 4 */ - else if (priv->n_channels == 5 && channel == GIMP_HISTOGRAM_LUMINANCE) - channel = 4; - if (! priv->values || - start > end || - (channel == GIMP_HISTOGRAM_RGB && priv->n_channels < 5) || - (channel != GIMP_HISTOGRAM_RGB && channel >= priv->n_channels)) - return 0.0; + start > end || + ! gimp_histogram_map_channel (histogram, &channel)) + { + return 0.0; + } mean = gimp_histogram_get_mean (histogram, channel, start, end); count = gimp_histogram_get_count (histogram, channel, start, end); @@ -819,21 +806,52 @@ /* private functions */ +static gboolean +gimp_histogram_map_channel (GimpHistogram *histogram, + GimpHistogramChannel *channel) +{ + GimpHistogramPrivate *priv = histogram->priv; + + if (*channel == GIMP_HISTOGRAM_RGB) + return gimp_histogram_n_components (histogram) >= 3; + + switch (*channel) + { + case GIMP_HISTOGRAM_ALPHA: + if (gimp_histogram_n_components (histogram) == 2) + *channel = 1; + break; + + case GIMP_HISTOGRAM_LUMINANCE: + *channel = gimp_histogram_n_components (histogram) + 1; + break; + + default: + break; + } + + return *channel < priv->n_channels; +} + static void gimp_histogram_set_values (GimpHistogram *histogram, gint n_components, gint n_bins, gdouble *values) { - GimpHistogramPrivate *priv = histogram->priv; - gboolean notify_n_channels = FALSE; - gboolean notify_n_bins = FALSE; + GimpHistogramPrivate *priv = histogram->priv; + gint n_channels = n_components; + gboolean notify_n_components = FALSE; + gboolean notify_n_bins = FALSE; + + if (n_channels > 0) + n_channels += N_DERIVED_CHANNELS; - if (n_components + 2 != priv->n_channels) + if (n_channels != priv->n_channels) { - priv->n_channels = n_components + 2; + priv->n_channels = n_channels; - notify_n_channels = TRUE; + notify_n_components = TRUE; } if (n_bins != priv->n_bins) @@ -851,8 +869,8 @@ priv->values = values; } - if (notify_n_channels) - g_object_notify (G_OBJECT (histogram), "n-channels"); + if (notify_n_components) + g_object_notify (G_OBJECT (histogram), "n-components"); if (notify_n_bins) g_object_notify (G_OBJECT (histogram), "n-bins"); @@ -946,15 +964,16 @@ data.format = format; data.values_list = NULL; - gimp_parallel_distribute_area ( - &context->buffer_rect, MIN_PARALLEL_SUB_AREA, - (GimpParallelDistributeAreaFunc) gimp_histogram_calculate_area, + gegl_parallel_distribute_area ( + &context->buffer_rect, PIXELS_PER_THREAD, GEGL_SPLIT_STRATEGY_AUTO, + (GeglParallelDistributeAreaFunc) gimp_histogram_calculate_area, &data); if (! async || ! gimp_async_is_canceled (async)) { gdouble *total_values = NULL; - gint n_values = (context->n_components + 2) * context->n_bins; + gint n_values = (context->n_components + N_DERIVED_CHANNELS) * + context->n_bins; GSList *iter; for (iter = data.values_list; iter; iter = g_slist_next (iter)) @@ -1011,7 +1030,7 @@ n_bins = context->n_bins; n_components = context->n_components; - values = g_new0 (gdouble, (n_components + 2) * n_bins); + values = g_new0 (gdouble, (n_components + N_DERIVED_CHANNELS) * n_bins); gimp_atomic_slist_push_head (&data->values_list, values); iter = gegl_buffer_iterator_new (context->buffer, area, 0, diff -Nru gimp-2.10.8+zorin2/app/core/gimphistogram.h gimp-2.10.14+om/app/core/gimphistogram.h --- gimp-2.10.8+zorin2/app/core/gimphistogram.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimphistogram.h 2019-10-26 18:49:18.000000000 +0000 @@ -65,7 +65,8 @@ GeglBuffer *mask, const GeglRectangle *mask_rect); -void gimp_histogram_clear_values (GimpHistogram *histogram); +void gimp_histogram_clear_values (GimpHistogram *histogram, + gint n_components); gdouble gimp_histogram_get_maximum (GimpHistogram *histogram, GimpHistogramChannel channel); @@ -95,8 +96,10 @@ gdouble gimp_histogram_get_component (GimpHistogram *histogram, gint component, gint bin); -gint gimp_histogram_n_channels (GimpHistogram *histogram); +gint gimp_histogram_n_components (GimpHistogram *histogram); gint gimp_histogram_n_bins (GimpHistogram *histogram); +gboolean gimp_histogram_has_channel (GimpHistogram *histogram, + GimpHistogramChannel channel); #endif /* __GIMP_HISTOGRAM_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-arrange.c gimp-2.10.14+om/app/core/gimpimage-arrange.c --- gimp-2.10.8+zorin2/app/core/gimpimage-arrange.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-arrange.c 2019-10-26 18:49:18.000000000 +0000 @@ -158,14 +158,14 @@ (reference, "align-width")); /* The offset parameter works as an internal margin */ fill_offset = (distr_width - 2 * offset) / - g_list_length (object_list); + (gint) g_list_length (object_list); } if (reference_alignment == GIMP_ARRANGE_VFILL) { distr_height = GPOINTER_TO_INT (g_object_get_data (reference, "align-height")); fill_offset = (distr_height - 2 * offset) / - g_list_length (object_list); + (gint) g_list_length (object_list); } /* FIXME: undo group type is wrong */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage.c gimp-2.10.14+om/app/core/gimpimage.c --- gimp-2.10.8+zorin2/app/core/gimpimage.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage.c 2019-10-26 18:49:18.000000000 +0000 @@ -37,6 +37,7 @@ #include "operations/layer-modes/gimp-layer-modes.h" #include "gegl/gimp-babl.h" +#include "gegl/gimp-gegl-loops.h" #include "gimp.h" #include "gimp-memsize.h" @@ -194,6 +195,7 @@ static void gimp_image_projectable_flush (GimpProjectable *projectable, gboolean invalidate_preview); +static GeglRectangle gimp_image_get_bounding_box (GimpProjectable *projectable); static GeglNode * gimp_image_get_graph (GimpProjectable *projectable); static GimpImage * gimp_image_get_image (GimpProjectable *projectable); static const Babl * gimp_image_get_proj_format (GimpProjectable *projectable); @@ -221,12 +223,25 @@ const Babl *format, gpointer pixel); +static void gimp_image_projection_buffer_notify + (GimpProjection *projection, + const GParamSpec *pspec, + GimpImage *image); static void gimp_image_mask_update (GimpDrawable *drawable, gint x, gint y, gint width, gint height, GimpImage *image); +static void gimp_image_layers_changed (GimpContainer *container, + GimpChannel *channel, + GimpImage *image); +static void gimp_image_layer_offset_changed (GimpDrawable *drawable, + const GParamSpec *pspec, + GimpImage *image); +static void gimp_image_layer_bounding_box_changed + (GimpDrawable *drawable, + GimpImage *image); static void gimp_image_layer_alpha_changed (GimpDrawable *drawable, GimpImage *image); static void gimp_image_channel_add (GimpContainer *container, @@ -249,6 +264,10 @@ const GParamSpec *pspec, GimpImage *image); +static void gimp_image_freeze_bounding_box (GimpImage *image); +static void gimp_image_thaw_bounding_box (GimpImage *image); +static void gimp_image_update_bounding_box (GimpImage *image); + G_DEFINE_TYPE_WITH_CODE (GimpImage, gimp_image, GIMP_TYPE_VIEWABLE, G_ADD_PRIVATE (GimpImage) @@ -678,7 +697,7 @@ iface->flush = gimp_image_projectable_flush; iface->get_image = gimp_image_get_image; iface->get_format = gimp_image_get_proj_format; - iface->get_size = (void (*) (GimpProjectable*, gint*, gint*)) gimp_image_get_size; + iface->get_bounding_box = gimp_image_get_bounding_box; iface->get_graph = gimp_image_get_graph; iface->invalidate_preview = (void (*) (GimpProjectable*)) gimp_viewable_invalidate_preview; } @@ -715,11 +734,19 @@ private->height = 0; private->xresolution = 1.0; private->yresolution = 1.0; + private->resolution_set = FALSE; private->resolution_unit = GIMP_UNIT_INCH; private->base_type = GIMP_RGB; private->precision = GIMP_PRECISION_U8_GAMMA; private->new_layer_mode = -1; + private->show_all = 0; + private->bounding_box.x = 0; + private->bounding_box.y = 0; + private->bounding_box.width = 0; + private->bounding_box.height = 0; + private->pickable_buffer = NULL; + private->colormap = NULL; private->n_colors = 0; private->palette = NULL; @@ -759,6 +786,10 @@ GIMP_TYPE_VECTORS); private->layer_stack = NULL; + g_signal_connect (private->projection, "notify::buffer", + G_CALLBACK (gimp_image_projection_buffer_notify), + image); + g_signal_connect (private->layers, "notify::active-item", G_CALLBACK (gimp_image_active_layer_notify), image); @@ -773,11 +804,30 @@ G_CALLBACK (gimp_image_invalidate), image); + private->layer_offset_x_handler = + gimp_container_add_handler (private->layers->container, "notify::offset-x", + G_CALLBACK (gimp_image_layer_offset_changed), + image); + private->layer_offset_y_handler = + gimp_container_add_handler (private->layers->container, "notify::offset-y", + G_CALLBACK (gimp_image_layer_offset_changed), + image); + private->layer_bounding_box_handler = + gimp_container_add_handler (private->layers->container, "bounding-box-changed", + G_CALLBACK (gimp_image_layer_bounding_box_changed), + image); private->layer_alpha_handler = gimp_container_add_handler (private->layers->container, "alpha-changed", G_CALLBACK (gimp_image_layer_alpha_changed), image); + g_signal_connect (private->layers->container, "add", + G_CALLBACK (gimp_image_layers_changed), + image); + g_signal_connect (private->layers->container, "remove", + G_CALLBACK (gimp_image_layers_changed), + image); + g_signal_connect_swapped (private->channels->container, "update", G_CALLBACK (gimp_image_invalidate), image); @@ -851,6 +901,8 @@ private->quick_mask_color = config->quick_mask_color; + gimp_image_update_bounding_box (image); + if (private->base_type == GIMP_INDEXED) gimp_image_colormap_init (image); @@ -1016,8 +1068,18 @@ image); gimp_container_remove_handler (private->layers->container, + private->layer_offset_x_handler); + gimp_container_remove_handler (private->layers->container, + private->layer_offset_y_handler); + gimp_container_remove_handler (private->layers->container, + private->layer_bounding_box_handler); + gimp_container_remove_handler (private->layers->container, private->layer_alpha_handler); + g_signal_handlers_disconnect_by_func (private->layers->container, + gimp_image_layers_changed, + image); + g_signal_handlers_disconnect_by_func (private->channels->container, gimp_image_invalidate, image); @@ -1034,12 +1096,9 @@ gimp_image_channel_remove, image); - gimp_container_foreach (private->layers->container, - (GFunc) gimp_item_removed, NULL); - gimp_container_foreach (private->channels->container, - (GFunc) gimp_item_removed, NULL); - gimp_container_foreach (private->vectors->container, - (GFunc) gimp_item_removed, NULL); + g_object_run_dispose (G_OBJECT (private->layers)); + g_object_run_dispose (G_OBJECT (private->channels)); + g_object_run_dispose (G_OBJECT (private->vectors)); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -1060,6 +1119,7 @@ if (private->color_profile) _gimp_image_free_color_profile (image); + g_clear_object (&private->pickable_buffer); g_clear_object (&private->metadata); g_clear_object (&private->file); g_clear_object (&private->imported_file); @@ -1210,10 +1270,9 @@ static void gimp_image_size_changed (GimpViewable *viewable) { - GimpImage *image = GIMP_IMAGE (viewable); - GimpMetadata *metadata; - GList *all_items; - GList *list; + GimpImage *image = GIMP_IMAGE (viewable); + GList *all_items; + GList *list; if (GIMP_VIEWABLE_CLASS (parent_class)->size_changed) GIMP_VIEWABLE_CLASS (parent_class)->size_changed (viewable); @@ -1238,13 +1297,11 @@ gimp_viewable_size_changed (GIMP_VIEWABLE (gimp_image_get_mask (image))); - metadata = gimp_image_get_metadata (image); - if (metadata) - gimp_metadata_set_pixel_size (metadata, - gimp_image_get_width (image), - gimp_image_get_height (image)); + gimp_image_metadata_update_pixel_size (image); - gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); + g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer); + + gimp_image_update_bounding_box (image); } static gchar * @@ -1270,32 +1327,7 @@ static void gimp_image_real_precision_changed (GimpImage *image) { - GimpMetadata *metadata; - - metadata = gimp_image_get_metadata (image); - if (metadata) - { - switch (gimp_image_get_component_type (image)) - { - case GIMP_COMPONENT_TYPE_U8: - gimp_metadata_set_bits_per_sample (metadata, 8); - break; - - case GIMP_COMPONENT_TYPE_U16: - case GIMP_COMPONENT_TYPE_HALF: - gimp_metadata_set_bits_per_sample (metadata, 16); - break; - - case GIMP_COMPONENT_TYPE_U32: - case GIMP_COMPONENT_TYPE_FLOAT: - gimp_metadata_set_bits_per_sample (metadata, 32); - break; - - case GIMP_COMPONENT_TYPE_DOUBLE: - gimp_metadata_set_bits_per_sample (metadata, 64); - break; - } - } + gimp_image_metadata_update_bits_per_sample (image); gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); } @@ -1303,17 +1335,7 @@ static void gimp_image_real_resolution_changed (GimpImage *image) { - GimpMetadata *metadata; - - metadata = gimp_image_get_metadata (image); - if (metadata) - { - gdouble xres, yres; - - gimp_image_get_resolution (image, &xres, &yres); - gimp_metadata_set_resolution (metadata, xres, yres, - gimp_image_get_unit (image)); - } + gimp_image_metadata_update_resolution (image); } static void @@ -1333,17 +1355,7 @@ static void gimp_image_real_unit_changed (GimpImage *image) { - GimpMetadata *metadata; - - metadata = gimp_image_get_metadata (image); - if (metadata) - { - gdouble xres, yres; - - gimp_image_get_resolution (image, &xres, &yres); - gimp_metadata_set_resolution (metadata, xres, yres, - gimp_image_get_unit (image)); - } + gimp_image_metadata_update_resolution (image); } static void @@ -1369,10 +1381,7 @@ if (gimp_image_get_base_type (image) == GIMP_INDEXED) { /* A colormap alteration affects the whole image */ - gimp_image_invalidate (image, - 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image)); + gimp_image_invalidate_all (image); gimp_item_stack_invalidate_previews (GIMP_ITEM_STACK (private->layers->container)); } @@ -1406,6 +1415,9 @@ GimpImage *image = GIMP_IMAGE (managed); GimpItemStack *layers = GIMP_ITEM_STACK (gimp_image_get_layers (image)); + gimp_image_metadata_update_colorspace (image); + + gimp_projectable_structure_changed (GIMP_PROJECTABLE (image)); gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image)); gimp_item_stack_profile_changed (layers); } @@ -1482,9 +1494,30 @@ static GeglBuffer * gimp_image_get_buffer (GimpPickable *pickable) { - GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (pickable); + GimpImage *image = GIMP_IMAGE (pickable); + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + + if (! private->pickable_buffer) + { + GeglBuffer *buffer; + + buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (private->projection)); + + if (! private->show_all) + { + private->pickable_buffer = g_object_ref (buffer); + } + else + { + private->pickable_buffer = gegl_buffer_create_sub_buffer ( + buffer, + GEGL_RECTANGLE (0, 0, + gimp_image_get_width (image), + gimp_image_get_height (image))); + } + } - return gimp_pickable_get_buffer (GIMP_PICKABLE (private->projection)); + return private->pickable_buffer; } static gboolean @@ -1494,10 +1527,19 @@ const Babl *format, gpointer pixel) { - GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (pickable); + GimpImage *image = GIMP_IMAGE (pickable); + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + + if (x >= 0 && + y >= 0 && + x < gimp_image_get_width (image) && + y < gimp_image_get_height (image)) + { + return gimp_pickable_get_pixel_at (GIMP_PICKABLE (private->projection), + x, y, format, pixel); + } - return gimp_pickable_get_pixel_at (GIMP_PICKABLE (private->projection), - x, y, format, pixel); + return FALSE; } static gdouble @@ -1505,10 +1547,19 @@ gint x, gint y) { - GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (pickable); + GimpImage *image = GIMP_IMAGE (pickable); + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); - return gimp_pickable_get_opacity_at (GIMP_PICKABLE (private->projection), - x, y); + if (x >= 0 && + y >= 0 && + x < gimp_image_get_width (image) && + y < gimp_image_get_height (image)) + { + return gimp_pickable_get_opacity_at (GIMP_PICKABLE (private->projection), + x, y); + } + + return FALSE; } static void @@ -1517,10 +1568,10 @@ const Babl *format, gpointer pixel) { - GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (pickable); + GeglBuffer *buffer = gimp_pickable_get_buffer (pickable); - return gimp_pickable_get_pixel_average (GIMP_PICKABLE (private->projection), - rect, format, pixel); + return gimp_gegl_average_color (buffer, rect, TRUE, GEGL_ABYSS_NONE, format, + pixel); } static void @@ -1543,6 +1594,14 @@ color, format, pixel); } +static GeglRectangle +gimp_image_get_bounding_box (GimpProjectable *projectable) +{ + GimpImage *image = GIMP_IMAGE (projectable); + + return GIMP_IMAGE_GET_PRIVATE (image)->bounding_box; +} + static GeglNode * gimp_image_get_graph (GimpProjectable *projectable) { @@ -1569,6 +1628,7 @@ gegl_node_new_child (private->graph, "operation", "gimp:mask-components", "mask", mask, + "alpha", 1.0, NULL); gegl_node_connect_to (layers_node, "output", @@ -1591,6 +1651,14 @@ } static void +gimp_image_projection_buffer_notify (GimpProjection *projection, + const GParamSpec *pspec, + GimpImage *image) +{ + g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer); +} + +static void gimp_image_mask_update (GimpDrawable *drawable, gint x, gint y, @@ -1602,6 +1670,29 @@ } static void +gimp_image_layers_changed (GimpContainer *container, + GimpChannel *channel, + GimpImage *image) +{ + gimp_image_update_bounding_box (image); +} + +static void +gimp_image_layer_offset_changed (GimpDrawable *drawable, + const GParamSpec *pspec, + GimpImage *image) +{ + gimp_image_update_bounding_box (image); +} + +static void +gimp_image_layer_bounding_box_changed (GimpDrawable *drawable, + GimpImage *image) +{ + gimp_image_update_bounding_box (image); +} + +static void gimp_image_layer_alpha_changed (GimpDrawable *drawable, GimpImage *image) { @@ -1704,6 +1795,82 @@ g_signal_emit (image, gimp_image_signals[ACTIVE_VECTORS_CHANGED], 0); } +static void +gimp_image_freeze_bounding_box (GimpImage *image) +{ + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + + private->bounding_box_freeze_count++; +} + +static void +gimp_image_thaw_bounding_box (GimpImage *image) +{ + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + + private->bounding_box_freeze_count--; + + if (private->bounding_box_freeze_count == 0 && + private->bounding_box_update_pending) + { + private->bounding_box_update_pending = FALSE; + + gimp_image_update_bounding_box (image); + } +} + +static void +gimp_image_update_bounding_box (GimpImage *image) +{ + GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); + GeglRectangle bounding_box; + + if (private->bounding_box_freeze_count > 0) + { + private->bounding_box_update_pending = TRUE; + + return; + } + + bounding_box.x = 0; + bounding_box.y = 0; + bounding_box.width = gimp_image_get_width (image); + bounding_box.height = gimp_image_get_height (image); + + if (private->show_all) + { + GList *iter; + + for (iter = gimp_image_get_layer_iter (image); + iter; + iter = g_list_next (iter)) + { + GimpLayer *layer = iter->data; + GeglRectangle layer_bounding_box; + gint offset_x; + gint offset_y; + + gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y); + + layer_bounding_box = gimp_drawable_get_bounding_box ( + GIMP_DRAWABLE (layer)); + + layer_bounding_box.x += offset_x; + layer_bounding_box.y += offset_y; + + gegl_rectangle_bounding_box (&bounding_box, + &bounding_box, &layer_bounding_box); + } + } + + if (! gegl_rectangle_equal (&bounding_box, &private->bounding_box)) + { + private->bounding_box = bounding_box; + + gimp_projectable_bounds_changed (GIMP_PROJECTABLE (image), 0, 0); + } +} + /* public functions */ @@ -2136,6 +2303,24 @@ { gimp_object_name_changed (GIMP_OBJECT (image)); } + + if (! private->resolution_set) + { + /* Unlike new files (which follow technological progress and will + * use higher default resolution, or explicitly chosen templates), + * imported files have a more backward-compatible value. + * + * 72 PPI is traditionnally the default value when none other had + * been explicitly set (for instance it is the default when no + * resolution metadata was set in Exif version 2.32, and below, + * standard). This historical value will only ever apply to loaded + * images. New images will continue having more modern or + * templated defaults. + */ + private->xresolution = 72.0; + private->yresolution = 72.0; + private->resolution_unit = GIMP_UNIT_INCH; + } } /** @@ -2633,8 +2818,9 @@ gimp_image_undo_push_image_resolution (image, C_("undo-type", "Change Image Resolution")); - private->xresolution = xresolution; - private->yresolution = yresolution; + private->xresolution = xresolution; + private->yresolution = yresolution; + private->resolution_set = TRUE; gimp_image_resolution_changed (image); gimp_image_size_changed_detailed (image, @@ -3012,10 +3198,7 @@ gimp_image_signals[COMPONENT_VISIBILITY_CHANGED], 0, channel); - gimp_image_invalidate (image, - 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image)); + gimp_image_invalidate_all (image); } } @@ -3125,6 +3308,20 @@ } void +gimp_image_invalidate_all (GimpImage *image) +{ + const GeglRectangle *bounding_box; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + + bounding_box = &GIMP_IMAGE_GET_PRIVATE (image)->bounding_box; + + gimp_image_invalidate (image, + bounding_box->x, bounding_box->y, + bounding_box->width, bounding_box->height); +} + +void gimp_image_guide_added (GimpImage *image, GimpGuide *guide) { @@ -3510,6 +3707,36 @@ GIMP_IMAGE_GET_PRIVATE (image)->instance_count++; } +void +gimp_image_inc_show_all_count (GimpImage *image) +{ + g_return_if_fail (GIMP_IS_IMAGE (image)); + + GIMP_IMAGE_GET_PRIVATE (image)->show_all++; + + if (GIMP_IMAGE_GET_PRIVATE (image)->show_all == 1) + { + g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer); + + gimp_image_update_bounding_box (image); + } +} + +void +gimp_image_dec_show_all_count (GimpImage *image) +{ + g_return_if_fail (GIMP_IS_IMAGE (image)); + + GIMP_IMAGE_GET_PRIVATE (image)->show_all--; + + if (GIMP_IMAGE_GET_PRIVATE (image)->show_all == 0) + { + g_clear_object (&GIMP_IMAGE_GET_PRIVATE (image)->pickable_buffer); + + gimp_image_update_bounding_box (image); + } +} + /* parasites */ @@ -3596,7 +3823,8 @@ void gimp_image_parasite_attach (GimpImage *image, - const GimpParasite *parasite) + const GimpParasite *parasite, + gboolean push_undo) { GimpImagePrivate *private; GimpParasite copy; @@ -3622,7 +3850,13 @@ builtin = gimp_image_get_builtin_color_profile (image); if (gimp_color_profile_is_equal (profile, builtin)) - gimp_image_parasite_detach (image, GIMP_ICC_PROFILE_PARASITE_NAME); + { + /* setting the builtin profile is equal to removing the profile */ + gimp_image_parasite_detach (image, GIMP_ICC_PROFILE_PARASITE_NAME, + push_undo); + g_object_unref (profile); + return; + } g_object_unref (profile); } @@ -3635,7 +3869,7 @@ /* only set the dirty bit manually if we can be saved and the new * parasite differs from the current one and we aren't undoable */ - if (gimp_parasite_is_undoable (©)) + if (push_undo && gimp_parasite_is_undoable (©)) gimp_image_undo_push_image_parasite (image, C_("undo-type", "Attach Parasite to Image"), ©); @@ -3648,22 +3882,23 @@ */ gimp_parasite_list_add (private->parasites, ©); - if (gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_PARENT)) + if (push_undo && gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_PARENT)) { gimp_parasite_shift_parent (©); gimp_parasite_attach (image->gimp, ©); } - g_signal_emit (image, gimp_image_signals[PARASITE_ATTACHED], 0, - name); - if (strcmp (name, GIMP_ICC_PROFILE_PARASITE_NAME) == 0) _gimp_image_update_color_profile (image, parasite); + + g_signal_emit (image, gimp_image_signals[PARASITE_ATTACHED], 0, + name); } void gimp_image_parasite_detach (GimpImage *image, - const gchar *name) + const gchar *name, + gboolean push_undo) { GimpImagePrivate *private; const GimpParasite *parasite; @@ -3676,18 +3911,18 @@ if (! (parasite = gimp_parasite_list_find (private->parasites, name))) return; - if (gimp_parasite_is_undoable (parasite)) + if (push_undo && gimp_parasite_is_undoable (parasite)) gimp_image_undo_push_image_parasite_remove (image, C_("undo-type", "Remove Parasite from Image"), name); gimp_parasite_list_remove (private->parasites, name); - g_signal_emit (image, gimp_image_signals[PARASITE_DETACHED], 0, - name); - if (strcmp (name, GIMP_ICC_PROFILE_PARASITE_NAME) == 0) _gimp_image_update_color_profile (image, NULL); + + g_signal_emit (image, gimp_image_signals[PARASITE_DETACHED], 0, + name); } @@ -4262,6 +4497,8 @@ undo_desc); } + gimp_image_freeze_bounding_box (image); + gimp_item_start_move (item, push_undo); /* item and new_parent are type-checked in GimpItemTree @@ -4272,6 +4509,8 @@ gimp_item_end_move (item, push_undo); + gimp_image_thaw_bounding_box (image); + if (push_undo) gimp_image_undo_group_end (image); @@ -4815,6 +5054,7 @@ gboolean gimp_image_coords_in_active_pickable (GimpImage *image, const GimpCoords *coords, + gboolean show_all, gboolean sample_merged, gboolean selected_only) { @@ -4828,9 +5068,11 @@ if (sample_merged) { - if (x >= 0 && x < gimp_image_get_width (image) && - y >= 0 && y < gimp_image_get_height (image)) - in_pickable = TRUE; + if (show_all || (x >= 0 && x < gimp_image_get_width (image) && + y >= 0 && y < gimp_image_get_height (image))) + { + in_pickable = TRUE; + } } else { diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-colormap.c gimp-2.10.14+om/app/core/gimpimage-colormap.c --- gimp-2.10.8+zorin2/app/core/gimpimage-colormap.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-colormap.c 2019-04-07 11:38:14.000000000 +0000 @@ -41,8 +41,9 @@ /* local function prototype */ -static void gimp_image_colormap_set_palette_entry (GimpImage *image, - gint index); +static void gimp_image_colormap_set_palette_entry (GimpImage *image, + const GimpRGB *color, + gint index); /* public functions */ @@ -213,7 +214,7 @@ gimp_palette_delete_entry (private->palette, entry); for (i = 0; i < private->n_colors; i++) - gimp_image_colormap_set_palette_entry (image, i); + gimp_image_colormap_set_palette_entry (image, NULL, i); gimp_data_thaw (GIMP_DATA (private->palette)); @@ -293,7 +294,7 @@ &private->colormap[color_index * 3 + 2]); if (private->palette) - gimp_image_colormap_set_palette_entry (image, color_index); + gimp_image_colormap_set_palette_entry (image, color, color_index); gimp_image_colormap_changed (image, color_index); } @@ -323,7 +324,7 @@ private->n_colors++; if (private->palette) - gimp_image_colormap_set_palette_entry (image, private->n_colors - 1); + gimp_image_colormap_set_palette_entry (image, color, private->n_colors - 1); gimp_image_colormap_changed (image, -1); } @@ -332,18 +333,25 @@ /* private functions */ static void -gimp_image_colormap_set_palette_entry (GimpImage *image, - gint index) +gimp_image_colormap_set_palette_entry (GimpImage *image, + const GimpRGB *c, + gint index) { GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); GimpRGB color; gchar name[64]; - gimp_rgba_set_uchar (&color, - private->colormap[3 * index + 0], - private->colormap[3 * index + 1], - private->colormap[3 * index + 2], - 255); + /* Avoid converting to char then back to double if we have the + * original GimpRGB color. + */ + if (c) + color = *c; + else + gimp_rgba_set_uchar (&color, + private->colormap[3 * index + 0], + private->colormap[3 * index + 1], + private->colormap[3 * index + 2], + 255); g_snprintf (name, sizeof (name), "#%d", index); diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-color-profile.c gimp-2.10.14+om/app/core/gimpimage-color-profile.c --- gimp-2.10.8+zorin2/app/core/gimpimage-color-profile.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-color-profile.c 2019-06-12 16:43:38.000000000 +0000 @@ -159,11 +159,11 @@ g_return_if_fail (gimp_image_validate_icc_parasite (image, icc_parasite, NULL, NULL) == TRUE); - gimp_image_parasite_attach (image, icc_parasite); + gimp_image_parasite_attach (image, icc_parasite, TRUE); } else { - gimp_image_parasite_detach (image, GIMP_ICC_PROFILE_PARASITE_NAME); + gimp_image_parasite_detach (image, GIMP_ICC_PROFILE_PARASITE_NAME, TRUE); } } @@ -421,7 +421,7 @@ gimp_image_set_is_color_managed (image, TRUE, TRUE); gimp_image_set_color_profile (image, dest_profile, NULL); /* omg... */ - gimp_image_parasite_detach (image, "icc-profile-name"); + gimp_image_parasite_detach (image, "icc-profile-name", TRUE); gimp_image_undo_group_end (image); diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-convert-indexed.c gimp-2.10.14+om/app/core/gimpimage-convert-indexed.c --- gimp-2.10.8+zorin2/app/core/gimpimage-convert-indexed.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-convert-indexed.c 2019-04-07 11:38:14.000000000 +0000 @@ -136,7 +136,6 @@ #include #include -#define GEGL_ITERATOR2_API #include #include "libgimpcolor/gimpcolor.h" @@ -3595,7 +3594,7 @@ /* Allocate and fill in the error_limiter table */ { gint *table; - gint in, out; + gint inp, out; /* #define STEPSIZE 16 */ /* #define STEPSIZE 200 */ @@ -3609,16 +3608,16 @@ const gint STEPSIZE = 190; - for (in = 0; in < STEPSIZE; in++) + for (inp = 0; inp < STEPSIZE; inp++) { - table[in] = in; - table[-in] = -in; + table[inp] = inp; + table[-inp] = -inp; } - for (; in <= 255; in++) + for (; inp <= 255; inp++) { - table[in] = STEPSIZE; - table[-in] = -STEPSIZE; + table[inp] = STEPSIZE; + table[-inp] = -STEPSIZE; } return (table); @@ -3631,24 +3630,24 @@ /* Map errors 1:1 up to +- STEPSIZE */ out = 0; - for (in = 0; in < STEPSIZE; in++, out++) + for (inp = 0; inp < STEPSIZE; inp++, out++) { - table[in] = out; - table[-in] = -out; + table[inp] = out; + table[-inp] = -out; } /* Map errors 1:2 up to +- 3*STEPSIZE */ - for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) + for (; inp < STEPSIZE*3; inp++, out += (inp&1) ? 0 : 1) { - table[in] = out; - table[-in] = -out; + table[inp] = out; + table[-inp] = -out; } /* Clamp the rest to final out value (which is STEPSIZE*2) */ - for (; in <= 255; in++) + for (; inp <= 255; inp++) { - table[in] = out; - table[-in] = -out; + table[inp] = out; + table[-inp] = -out; } return table; diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-fade.c gimp-2.10.14+om/app/core/gimpimage-fade.c --- gimp-2.10.8+zorin2/app/core/gimpimage-fade.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-fade.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include -#include - -#include "core-types.h" - -#include "operations/layer-modes/gimp-layer-modes.h" - -#include "gimpcontext.h" -#include "gimpdrawable.h" -#include "gimpdrawableundo.h" -#include "gimpimage.h" -#include "gimpimage-fade.h" -#include "gimpimage-undo.h" - - -/* public functions */ - -gboolean -gimp_image_fade (GimpImage *image, - GimpContext *context) -{ - GimpDrawableUndo *undo; - - g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); - g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE); - - undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image)); - - if (undo && undo->applied_buffer) - { - GimpDrawable *drawable; - GeglBuffer *buffer; - - drawable = GIMP_DRAWABLE (GIMP_ITEM_UNDO (undo)->item); - - g_object_ref (undo); - buffer = g_object_ref (undo->applied_buffer); - - gimp_image_undo (image); - - gimp_drawable_apply_buffer (drawable, buffer, - GEGL_RECTANGLE (0, 0, - gegl_buffer_get_width (undo->buffer), - gegl_buffer_get_height (undo->buffer)), - TRUE, - gimp_object_get_name (undo), - gimp_context_get_opacity (context), - gimp_context_get_paint_mode (context), - GIMP_LAYER_COLOR_SPACE_AUTO, - GIMP_LAYER_COLOR_SPACE_AUTO, - gimp_layer_mode_get_paint_composite_mode ( - gimp_context_get_paint_mode (context)), - NULL, undo->x, undo->y); - - g_object_unref (buffer); - g_object_unref (undo); - - return TRUE; - } - - return FALSE; -} diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-fade.h gimp-2.10.14+om/app/core/gimpimage-fade.h --- gimp-2.10.8+zorin2/app/core/gimpimage-fade.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-fade.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __GIMP_IMAGE_FADE_H__ -#define __GIMP_IMAGE_FADE_H__ - - -gboolean gimp_image_fade (GimpImage *image, - GimpContext *context); - - -#endif /* __GIMP_IMAGE_FADE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-flip.c gimp-2.10.14+om/app/core/gimpimage-flip.c --- gimp-2.10.8+zorin2/app/core/gimpimage-flip.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-flip.c 2019-10-26 18:49:18.000000000 +0000 @@ -20,9 +20,12 @@ #include #include +#include "libgimpmath/gimpmath.h" + #include "core-types.h" #include "gimp.h" +#include "gimpchannel.h" #include "gimpcontainer.h" #include "gimpcontext.h" #include "gimpguide.h" @@ -38,38 +41,185 @@ #include "gimpsamplepoint.h" +/* local function prototypes */ + +static void gimp_image_flip_guides (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis); +static void gimp_image_flip_sample_points (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis); + + +/* private functions */ + +static void +gimp_image_flip_guides (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis) +{ + gint width = gimp_image_get_width (image); + gint height = gimp_image_get_height (image); + GList *iter; + + for (iter = gimp_image_get_guides (image); iter;) + { + GimpGuide *guide = iter->data; + gint position = gimp_guide_get_position (guide); + + iter = g_list_next (iter); + + position = SIGNED_ROUND (2.0 * axis - position); + + switch (gimp_guide_get_orientation (guide)) + { + case GIMP_ORIENTATION_HORIZONTAL: + if (flip_type == GIMP_ORIENTATION_VERTICAL) + { + if (position >= 0 && position <= height) + gimp_image_move_guide (image, guide, position, TRUE); + else + gimp_image_remove_guide (image, guide, TRUE); + } + break; + + case GIMP_ORIENTATION_VERTICAL: + if (flip_type == GIMP_ORIENTATION_HORIZONTAL) + { + if (position >= 0 && position <= width) + gimp_image_move_guide (image, guide, position, TRUE); + else + gimp_image_remove_guide (image, guide, TRUE); + } + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + } +} + +static void +gimp_image_flip_sample_points (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis) +{ + gint width = gimp_image_get_width (image); + gint height = gimp_image_get_height (image); + GList *iter; + + for (iter = gimp_image_get_sample_points (image); iter;) + { + GimpSamplePoint *sample_point = iter->data; + gint x; + gint y; + + iter = g_list_next (iter); + + gimp_sample_point_get_position (sample_point, &x, &y); + + switch (flip_type) + { + case GIMP_ORIENTATION_HORIZONTAL: + x = SIGNED_ROUND (2.0 * axis - x); + break; + + case GIMP_ORIENTATION_VERTICAL: + y = SIGNED_ROUND (2.0 * axis - y); + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + + if (x >= 0 && x < width && + y >= 0 && y < height) + { + gimp_image_move_sample_point (image, sample_point, x, y, TRUE); + } + else + { + gimp_image_remove_sample_point (image, sample_point, TRUE); + } + } +} + + +/* public functions */ + void gimp_image_flip (GimpImage *image, GimpContext *context, GimpOrientationType flip_type, GimpProgress *progress) { - GimpObjectQueue *queue; - GimpItem *item; - GList *list; - gdouble axis; + gdouble axis = 0.0; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_CONTEXT (context)); g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); - gimp_set_busy (image->gimp); - switch (flip_type) { case GIMP_ORIENTATION_HORIZONTAL: - axis = (gdouble) gimp_image_get_width (image) / 2.0; + axis = gimp_image_get_width (image) / 2.0; break; case GIMP_ORIENTATION_VERTICAL: - axis = (gdouble) gimp_image_get_height (image) / 2.0; + axis = gimp_image_get_height (image) / 2.0; break; - default: - g_warning ("%s: unknown flip_type", G_STRFUNC); - return; + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); } + gimp_image_flip_full (image, context, flip_type, axis, + GIMP_TRANSFORM_RESIZE_CLIP, progress); +} + +void +gimp_image_flip_full (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + gdouble axis, + gboolean clip_result, + GimpProgress *progress) +{ + GimpObjectQueue *queue; + GimpItem *item; + gint width; + gint height; + gint offset_x = 0; + gint offset_y = 0; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (GIMP_IS_CONTEXT (context)); + g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); + + width = gimp_image_get_width (image); + height = gimp_image_get_height (image); + + if (! clip_result) + { + switch (flip_type) + { + case GIMP_ORIENTATION_HORIZONTAL: + offset_x = SIGNED_ROUND (2.0 * axis - width); + axis = width / 2.0; + break; + + case GIMP_ORIENTATION_VERTICAL: + offset_y = SIGNED_ROUND (2.0 * axis - height); + axis = height / 2.0; + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + } + + gimp_set_busy (image->gimp); + queue = gimp_object_queue_new (progress); progress = GIMP_PROGRESS (queue); @@ -83,67 +233,44 @@ /* Flip all layers, channels (including selection mask), and vectors */ while ((item = gimp_object_queue_pop (queue))) { - gimp_item_flip (item, context, flip_type, axis, FALSE); + gboolean clip = FALSE; + + if (GIMP_IS_CHANNEL (item)) + clip = clip_result; + + gimp_item_flip (item, context, flip_type, axis, clip); gimp_progress_set_value (progress, 1.0); } /* Flip all Guides */ - for (list = gimp_image_get_guides (image); - list; - list = g_list_next (list)) - { - GimpGuide *guide = list->data; - gint position = gimp_guide_get_position (guide); - - switch (gimp_guide_get_orientation (guide)) - { - case GIMP_ORIENTATION_HORIZONTAL: - if (flip_type == GIMP_ORIENTATION_VERTICAL) - gimp_image_move_guide (image, guide, - gimp_image_get_height (image) - position, - TRUE); - break; - - case GIMP_ORIENTATION_VERTICAL: - if (flip_type == GIMP_ORIENTATION_HORIZONTAL) - gimp_image_move_guide (image, guide, - gimp_image_get_width (image) - position, - TRUE); - break; - - default: - break; - } - } + gimp_image_flip_guides (image, flip_type, axis); /* Flip all sample points */ - for (list = gimp_image_get_sample_points (image); - list; - list = g_list_next (list)) - { - GimpSamplePoint *sample_point = list->data; - gint x; - gint y; + gimp_image_flip_sample_points (image, flip_type, axis); - gimp_sample_point_get_position (sample_point, &x, &y); - - if (flip_type == GIMP_ORIENTATION_VERTICAL) - gimp_image_move_sample_point (image, sample_point, - x, - gimp_image_get_height (image) - y, - TRUE); - - if (flip_type == GIMP_ORIENTATION_HORIZONTAL) - gimp_image_move_sample_point (image, sample_point, - gimp_image_get_width (image) - x, - y, - TRUE); + if (offset_x || offset_y) + { + gimp_image_undo_push_image_size (image, + NULL, + offset_x, + offset_y, + width, + height); } gimp_image_undo_group_end (image); g_object_unref (queue); + if (offset_x || offset_y) + { + gimp_image_size_changed_detailed (image, + -offset_x, + -offset_y, + width, + height); + } + gimp_unset_busy (image->gimp); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-flip.h gimp-2.10.14+om/app/core/gimpimage-flip.h --- gimp-2.10.8+zorin2/app/core/gimpimage-flip.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-flip.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,16 @@ #define __GIMP_IMAGE_FLIP_H__ -void gimp_image_flip (GimpImage *image, - GimpContext *context, - GimpOrientationType flip_type, - GimpProgress *progress); +void gimp_image_flip (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + GimpProgress *progress); +void gimp_image_flip_full (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + gdouble axis, + gboolean clip_result, + GimpProgress *progress); #endif /* __GIMP_IMAGE_FLIP_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage.h gimp-2.10.14+om/app/core/gimpimage.h --- gimp-2.10.8+zorin2/app/core/gimpimage.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage.h 2019-10-26 18:49:18.000000000 +0000 @@ -250,6 +250,7 @@ gint y, gint width, gint height); +void gimp_image_invalidate_all (GimpImage *image); void gimp_image_guide_added (GimpImage *image, GimpGuide *guide); void gimp_image_guide_removed (GimpImage *image, @@ -304,6 +305,9 @@ gint gimp_image_get_instance_count (GimpImage *image); void gimp_image_inc_instance_count (GimpImage *image); +void gimp_image_inc_show_all_count (GimpImage *image); +void gimp_image_dec_show_all_count (GimpImage *image); + /* parasites */ @@ -315,9 +319,11 @@ const GimpParasite *parasite, GError **error); void gimp_image_parasite_attach (GimpImage *image, - const GimpParasite *parasite); + const GimpParasite *parasite, + gboolean push_undo); void gimp_image_parasite_detach (GimpImage *image, - const gchar *name); + const gchar *name, + gboolean push_undo); /* tattoos */ @@ -441,6 +447,7 @@ gboolean gimp_image_coords_in_active_pickable (GimpImage *image, const GimpCoords *coords, + gboolean show_all, gboolean sample_merged, gboolean selected_only); diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-item-list.c gimp-2.10.14+om/app/core/gimpimage-item-list.c --- gimp-2.10.8+zorin2/app/core/gimpimage-item-list.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-item-list.c 2019-10-26 18:49:18.000000000 +0000 @@ -161,8 +161,13 @@ } for (l = list; l; l = g_list_next (l)) - gimp_item_flip (GIMP_ITEM (l->data), context, - flip_type, axis, clip_result); + { + GimpItem *item = l->data; + + gimp_item_flip (item, context, + flip_type, axis, + gimp_item_get_clip (item, clip_result)); + } if (list->next) { @@ -200,8 +205,13 @@ } for (l = list; l; l = g_list_next (l)) - gimp_item_rotate (GIMP_ITEM (l->data), context, - rotate_type, center_x, center_y, clip_result); + { + GimpItem *item = l->data; + + gimp_item_rotate (item, context, + rotate_type, center_x, center_y, + gimp_item_get_clip (item, clip_result)); + } if (list->next) { @@ -251,13 +261,16 @@ for (l = list; l; l = g_list_next (l)) { + GimpItem *item = l->data; + if (queue) gimp_object_queue_pop (queue); - gimp_item_transform (GIMP_ITEM (l->data), context, + gimp_item_transform (item, context, matrix, direction, interpolation_type, - clip_result, progress); + gimp_item_get_clip (item, clip_result), + progress); } if (list->next) diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-merge.c gimp-2.10.14+om/app/core/gimpimage-merge.c --- gimp-2.10.8+zorin2/app/core/gimpimage-merge.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-merge.c 2019-04-07 11:38:14.000000000 +0000 @@ -48,6 +48,7 @@ #include "gimpmarshal.h" #include "gimpparasitelist.h" #include "gimppickable.h" +#include "gimpprogress.h" #include "gimpprojectable.h" #include "gimpundostack.h" @@ -58,7 +59,9 @@ GimpContainer *container, GSList *merge_list, GimpContext *context, - GimpMergeType merge_type); + GimpMergeType merge_type, + const gchar *undo_desc, + GimpProgress *progress); /* public functions */ @@ -68,7 +71,8 @@ GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, - gboolean discard_invisible) + gboolean discard_invisible, + GimpProgress *progress) { GimpContainer *container; GList *list; @@ -77,6 +81,7 @@ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); if (merge_active_group) { @@ -126,13 +131,14 @@ if (merge_list) { - GimpLayer *layer; + GimpLayer *layer; + const gchar *undo_desc = C_("undo-type", "Merge Visible Layers"); gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, - C_("undo-type", "Merge Visible Layers")); + undo_desc); /* if there's a floating selection, anchor it */ if (gimp_image_get_floating_selection (image)) @@ -140,7 +146,8 @@ layer = gimp_image_merge_layers (image, container, - merge_list, context, merge_type); + merge_list, context, merge_type, + undo_desc, progress); g_slist_free (merge_list); if (invisible_list) @@ -164,9 +171,10 @@ } GimpLayer * -gimp_image_flatten (GimpImage *image, - GimpContext *context, - GError **error) +gimp_image_flatten (GimpImage *image, + GimpContext *context, + GimpProgress *progress, + GError **error) { GList *list; GSList *merge_list = NULL; @@ -174,6 +182,7 @@ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); for (list = gimp_image_get_layer_iter (image); @@ -191,11 +200,13 @@ if (merge_list) { + const gchar *undo_desc = C_("undo-type", "Flatten Image"); + gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, - C_("undo-type", "Flatten Image")); + undo_desc); /* if there's a floating selection, anchor it */ if (gimp_image_get_floating_selection (image)) @@ -204,7 +215,8 @@ layer = gimp_image_merge_layers (image, gimp_image_get_layers (image), merge_list, context, - GIMP_FLATTEN_IMAGE); + GIMP_FLATTEN_IMAGE, + undo_desc, progress); g_slist_free (merge_list); gimp_image_alpha_changed (image); @@ -226,17 +238,20 @@ GimpLayer *current_layer, GimpContext *context, GimpMergeType merge_type, + GimpProgress *progress, GError **error) { - GimpLayer *layer; - GList *list; - GList *layer_list = NULL; - GSList *merge_list = NULL; + GimpLayer *layer; + GList *list; + GList *layer_list = NULL; + GSList *merge_list = NULL; + const gchar *undo_desc; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_LAYER (current_layer), NULL); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (current_layer)), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); if (gimp_layer_is_floating_sel (current_layer)) @@ -299,15 +314,18 @@ merge_list = g_slist_prepend (merge_list, current_layer); + undo_desc = C_("undo-type", "Merge Down"); + gimp_set_busy (image->gimp); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, - C_("undo-type", "Merge Down")); + undo_desc); layer = gimp_image_merge_layers (image, gimp_item_get_container (GIMP_ITEM (current_layer)), - merge_list, context, merge_type); + merge_list, context, merge_type, + undo_desc, progress); g_slist_free (merge_list); gimp_image_undo_group_end (image); @@ -457,7 +475,9 @@ GimpContainer *container, GSList *merge_list, GimpContext *context, - GimpMergeType merge_type) + GimpMergeType merge_type, + const gchar *undo_desc, + GimpProgress *progress) { GimpLayer *parent; gint x1, y1; @@ -478,6 +498,7 @@ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); + g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); top_layer = merge_list->data; parent = gimp_layer_get_parent (top_layer); @@ -658,9 +679,10 @@ gegl_node_disconnect (last_node, "input"); /* Render the graph into the merge layer */ - gegl_node_blit_buffer (offset_node, - gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)), - NULL, 0, GEGL_ABYSS_NONE); + gimp_gegl_apply_operation (NULL, progress, undo_desc, offset_node, + gimp_drawable_get_buffer ( + GIMP_DRAWABLE (merge_layer)), + NULL, FALSE); /* Reconnect the bottom-layer node's input */ if (last_node_source) diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-merge.h gimp-2.10.14+om/app/core/gimpimage-merge.h --- gimp-2.10.8+zorin2/app/core/gimpimage-merge.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-merge.h 2019-04-07 11:38:14.000000000 +0000 @@ -23,17 +23,20 @@ GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, - gboolean discard_invisible); + gboolean discard_invisible, + GimpProgress *progress); GimpLayer * gimp_image_merge_down (GimpImage *image, GimpLayer *current_layer, GimpContext *context, GimpMergeType merge_type, + GimpProgress *progress, GError **error); GimpLayer * gimp_image_merge_group_layer (GimpImage *image, GimpGroupLayer *group); GimpLayer * gimp_image_flatten (GimpImage *image, GimpContext *context, + GimpProgress *progress, GError **error); GimpVectors * gimp_image_merge_visible_vectors (GimpImage *image, diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-metadata.c gimp-2.10.14+om/app/core/gimpimage-metadata.c --- gimp-2.10.8+zorin2/app/core/gimpimage-metadata.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-metadata.c 2019-10-26 18:49:18.000000000 +0000 @@ -17,14 +17,17 @@ #include "config.h" +#include #include #include #include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" #include "core-types.h" #include "gimpimage.h" +#include "gimpimage-color-profile.h" #include "gimpimage-metadata.h" #include "gimpimage-private.h" #include "gimpimage-undo-push.h" @@ -65,38 +68,117 @@ if (private->metadata) { - gdouble xres, yres; - - gimp_metadata_set_pixel_size (metadata, - gimp_image_get_width (image), - gimp_image_get_height (image)); - - switch (gimp_image_get_component_type (image)) - { - case GIMP_COMPONENT_TYPE_U8: - gimp_metadata_set_bits_per_sample (metadata, 8); - break; - - case GIMP_COMPONENT_TYPE_U16: - case GIMP_COMPONENT_TYPE_HALF: - gimp_metadata_set_bits_per_sample (metadata, 16); - break; - - case GIMP_COMPONENT_TYPE_U32: - case GIMP_COMPONENT_TYPE_FLOAT: - gimp_metadata_set_bits_per_sample (metadata, 32); - break; - - case GIMP_COMPONENT_TYPE_DOUBLE: - gimp_metadata_set_bits_per_sample (metadata, 64); - break; - } - - gimp_image_get_resolution (image, &xres, &yres); - gimp_metadata_set_resolution (metadata, xres, yres, - gimp_image_get_unit (image)); + gimp_image_metadata_update_pixel_size (image); + gimp_image_metadata_update_bits_per_sample (image); + gimp_image_metadata_update_resolution (image); + gimp_image_metadata_update_colorspace (image); } g_object_notify (G_OBJECT (image), "metadata"); } } + +void +gimp_image_metadata_update_pixel_size (GimpImage *image) +{ + GimpMetadata *metadata; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + + metadata = gimp_image_get_metadata (image); + + if (metadata) + { + gimp_metadata_set_pixel_size (metadata, + gimp_image_get_width (image), + gimp_image_get_height (image)); + } +} + +void +gimp_image_metadata_update_bits_per_sample (GimpImage *image) +{ + GimpMetadata *metadata; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + + metadata = gimp_image_get_metadata (image); + + if (metadata) + { + switch (gimp_image_get_component_type (image)) + { + case GIMP_COMPONENT_TYPE_U8: + gimp_metadata_set_bits_per_sample (metadata, 8); + break; + + case GIMP_COMPONENT_TYPE_U16: + case GIMP_COMPONENT_TYPE_HALF: + gimp_metadata_set_bits_per_sample (metadata, 16); + break; + + case GIMP_COMPONENT_TYPE_U32: + case GIMP_COMPONENT_TYPE_FLOAT: + gimp_metadata_set_bits_per_sample (metadata, 32); + break; + + case GIMP_COMPONENT_TYPE_DOUBLE: + gimp_metadata_set_bits_per_sample (metadata, 64); + break; + } + } +} + +void +gimp_image_metadata_update_resolution (GimpImage *image) +{ + GimpMetadata *metadata; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + + metadata = gimp_image_get_metadata (image); + + if (metadata) + { + gdouble xres, yres; + + gimp_image_get_resolution (image, &xres, &yres); + gimp_metadata_set_resolution (metadata, xres, yres, + gimp_image_get_unit (image)); + } +} + +void +gimp_image_metadata_update_colorspace (GimpImage *image) +{ + GimpMetadata *metadata; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + + metadata = gimp_image_get_metadata (image); + + if (metadata) + { + /* See the discussions in issue #3532 and issue #301 */ + + GimpColorProfile *profile = gimp_image_get_color_profile (image); + GimpMetadataColorspace space = GIMP_METADATA_COLORSPACE_UNSPECIFIED; + + if (profile) + { + static GimpColorProfile *adobe = NULL; + + if (! adobe) + adobe = gimp_color_profile_new_rgb_adobe (); + + if (gimp_color_profile_is_equal (profile, adobe)) + space = GIMP_METADATA_COLORSPACE_ADOBERGB; + } + else + { + space = GIMP_METADATA_COLORSPACE_SRGB; + } + + gimp_metadata_set_colorspace (metadata, space); + } +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-metadata.h gimp-2.10.14+om/app/core/gimpimage-metadata.h --- gimp-2.10.8+zorin2/app/core/gimpimage-metadata.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-metadata.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,10 +19,15 @@ #define __GIMP_IMAGE_METADATA_H__ -GimpMetadata * gimp_image_get_metadata (GimpImage *image); -void gimp_image_set_metadata (GimpImage *image, - GimpMetadata *metadata, - gboolean push_undo); +GimpMetadata * gimp_image_get_metadata (GimpImage *image); +void gimp_image_set_metadata (GimpImage *image, + GimpMetadata *metadata, + gboolean push_undo); + +void gimp_image_metadata_update_pixel_size (GimpImage *image); +void gimp_image_metadata_update_bits_per_sample (GimpImage *image); +void gimp_image_metadata_update_resolution (GimpImage *image); +void gimp_image_metadata_update_colorspace (GimpImage *image); #endif /* __GIMP_IMAGE_METADATA_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-new.c gimp-2.10.14+om/app/core/gimpimage-new.c --- gimp-2.10.8+zorin2/app/core/gimpimage-new.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-new.c 2019-06-12 16:43:38.000000000 +0000 @@ -120,7 +120,7 @@ GIMP_PARASITE_PERSISTENT, strlen (comment) + 1, comment); - gimp_image_parasite_attach (image, parasite); + gimp_image_parasite_attach (image, parasite, FALSE); gimp_parasite_free (parasite); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-pick-color.c gimp-2.10.14+om/app/core/gimpimage-pick-color.c --- gimp-2.10.8+zorin2/app/core/gimpimage-pick-color.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-pick-color.c 2019-10-26 18:49:18.000000000 +0000 @@ -20,11 +20,17 @@ #include #include +#include "libgimpmath/gimpmath.h" + #include "core-types.h" +#include "gegl/gimp-gegl-loops.h" + +#include "gimpchannel.h" #include "gimpdrawable.h" #include "gimpimage.h" #include "gimpimage-pick-color.h" +#include "gimplayer.h" #include "gimppickable.h" @@ -33,6 +39,7 @@ GimpDrawable *drawable, gint x, gint y, + gboolean show_all, gboolean sample_merged, gboolean sample_average, gdouble average_radius, @@ -41,6 +48,7 @@ GimpRGB *color) { GimpPickable *pickable; + gboolean result; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), FALSE); @@ -48,6 +56,25 @@ gimp_item_get_image (GIMP_ITEM (drawable)) == image, FALSE); + if (sample_merged && drawable) + { + if ((GIMP_IS_LAYER (drawable) && + gimp_image_get_n_layers (image) == 1) || + (GIMP_IS_CHANNEL (drawable) && + gimp_image_get_n_channels (image) == 1)) + { + /* Let's add a special exception when an image has only one + * layer. This was useful in particular for indexed image as + * it allows to pick the right index value even when "Sample + * merged" is checked. There are more possible exceptions, but + * we can't just take them all in considerations unless we + * want to make code extra-complicated). + * See #3041. + */ + sample_merged = FALSE; + } + } + if (! sample_merged) { if (! drawable) @@ -59,7 +86,10 @@ if (sample_merged) { - pickable = GIMP_PICKABLE (image); + if (! show_all) + pickable = GIMP_PICKABLE (image); + else + pickable = GIMP_PICKABLE (gimp_image_get_projection (image)); } else { @@ -80,7 +110,38 @@ if (sample_format) *sample_format = gimp_pickable_get_format (pickable); - return gimp_pickable_pick_color (pickable, x, y, - sample_average, average_radius, - pixel, color); + result = gimp_pickable_pick_color (pickable, x, y, + sample_average && + ! (show_all && sample_merged), + average_radius, + pixel, color); + + if (show_all && sample_merged) + { + const Babl *format = babl_format ("RaGaBaA double"); + gdouble sample[4] = {}; + + if (! result) + memset (pixel, 0, babl_format_get_bytes_per_pixel (*sample_format)); + + if (sample_average) + { + GeglBuffer *buffer = gimp_pickable_get_buffer (pickable); + gint radius = floor (average_radius); + + gimp_gegl_average_color (buffer, + GEGL_RECTANGLE (x - radius, + y - radius, + 2 * radius + 1, + 2 * radius + 1), + FALSE, GEGL_ABYSS_NONE, format, sample); + } + + if (! result || sample_average) + gimp_pickable_pixel_to_srgb (pickable, format, sample, color); + + result = TRUE; + } + + return result; } diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-pick-color.h gimp-2.10.14+om/app/core/gimpimage-pick-color.h --- gimp-2.10.8+zorin2/app/core/gimpimage-pick-color.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-pick-color.h 2019-10-26 18:49:18.000000000 +0000 @@ -23,6 +23,7 @@ GimpDrawable *drawable, gint x, gint y, + gboolean show_all, gboolean sample_merged, gboolean sample_average, gdouble average_radius, diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-pick-item.c gimp-2.10.14+om/app/core/gimpimage-pick-item.c --- gimp-2.10.8+zorin2/app/core/gimpimage-pick-item.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-pick-item.c 2019-06-12 16:43:38.000000000 +0000 @@ -41,29 +41,55 @@ GimpLayer * gimp_image_pick_layer (GimpImage *image, gint x, - gint y) + gint y, + GimpLayer *previously_picked) { GList *all_layers; GList *list; + gint off_x, off_y; + gint tries = 1; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); all_layers = gimp_image_get_layer_list (image); - for (list = all_layers; list; list = g_list_next (list)) + if (previously_picked) { - GimpLayer *layer = list->data; - gint off_x, off_y; - - gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y); + gimp_item_get_offset (GIMP_ITEM (previously_picked), &off_x, &off_y); + if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (previously_picked), + x - off_x, y - off_y) <= 0.25) + previously_picked = NULL; + else + tries++; + } - if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (layer), - x - off_x, y - off_y) > 0.25) + while (tries) + { + for (list = all_layers; list; list = g_list_next (list)) { - g_list_free (all_layers); + GimpLayer *layer = list->data; + + if (previously_picked) + { + /* Take the first layer with a pixel at given coordinates + * after the previously picked one. + */ + if (layer == previously_picked) + previously_picked = NULL; + continue; + } + + gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y); + + if (gimp_pickable_get_opacity_at (GIMP_PICKABLE (layer), + x - off_x, y - off_y) > 0.25) + { + g_list_free (all_layers); - return layer; + return layer; + } } + tries--; } g_list_free (all_layers); @@ -209,20 +235,18 @@ return ret; } -GimpGuide * -gimp_image_pick_guide (GimpImage *image, - gdouble x, - gdouble y, - gdouble epsilon_x, - gdouble epsilon_y) +static GimpGuide * +gimp_image_pick_guide_internal (GimpImage *image, + gdouble x, + gdouble y, + gdouble epsilon_x, + gdouble epsilon_y, + GimpOrientationType orientation) { GList *list; GimpGuide *ret = NULL; gdouble mindist = G_MAXDOUBLE; - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); - g_return_val_if_fail (epsilon_x > 0 && epsilon_y > 0, NULL); - for (list = GIMP_IMAGE_GET_PRIVATE (image)->guides; list; list = g_list_next (list)) @@ -234,33 +258,82 @@ switch (gimp_guide_get_orientation (guide)) { case GIMP_ORIENTATION_HORIZONTAL: - dist = ABS (position - y); - if (dist < MIN (epsilon_y, mindist)) + if (orientation == GIMP_ORIENTATION_HORIZONTAL || + orientation == GIMP_ORIENTATION_UNKNOWN) { - mindist = dist; - ret = guide; + dist = ABS (position - y); + if (dist < MIN (epsilon_y, mindist)) + { + mindist = dist; + ret = guide; + } } break; /* mindist always is in vertical resolution to make it comparable */ case GIMP_ORIENTATION_VERTICAL: - dist = ABS (position - x); - if (dist < MIN (epsilon_x, mindist / epsilon_y * epsilon_x)) + if (orientation == GIMP_ORIENTATION_VERTICAL || + orientation == GIMP_ORIENTATION_UNKNOWN) { - mindist = dist * epsilon_y / epsilon_x; - ret = guide; + dist = ABS (position - x); + if (dist < MIN (epsilon_x, mindist / epsilon_y * epsilon_x)) + { + mindist = dist * epsilon_y / epsilon_x; + ret = guide; + } } break; default: continue; } - } return ret; } +GimpGuide * +gimp_image_pick_guide (GimpImage *image, + gdouble x, + gdouble y, + gdouble epsilon_x, + gdouble epsilon_y) +{ + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (epsilon_x > 0 && epsilon_y > 0, NULL); + + return gimp_image_pick_guide_internal (image, x, y, epsilon_x, epsilon_y, + GIMP_ORIENTATION_UNKNOWN); +} + +GList * +gimp_image_pick_guides (GimpImage *image, + gdouble x, + gdouble y, + gdouble epsilon_x, + gdouble epsilon_y) +{ + GimpGuide *guide; + GList *result = NULL; + + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (epsilon_x > 0 && epsilon_y > 0, NULL); + + guide = gimp_image_pick_guide_internal (image, x, y, epsilon_x, epsilon_y, + GIMP_ORIENTATION_HORIZONTAL); + + if (guide) + result = g_list_append (result, guide); + + guide = gimp_image_pick_guide_internal (image, x, y, epsilon_x, epsilon_y, + GIMP_ORIENTATION_VERTICAL); + + if (guide) + result = g_list_append (result, guide); + + return result; +} + GimpSamplePoint * gimp_image_pick_sample_point (GimpImage *image, gdouble x, diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-pick-item.h gimp-2.10.14+om/app/core/gimpimage-pick-item.h --- gimp-2.10.8+zorin2/app/core/gimpimage-pick-item.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-pick-item.h 2019-06-12 16:43:38.000000000 +0000 @@ -21,7 +21,8 @@ GimpLayer * gimp_image_pick_layer (GimpImage *image, gint x, - gint y); + gint y, + GimpLayer *previously_picked); GimpLayer * gimp_image_pick_layer_by_bounds (GimpImage *image, gint x, gint y); @@ -40,6 +41,12 @@ gdouble y, gdouble epsilon_x, gdouble epsilon_y); +GList * gimp_image_pick_guides (GimpImage *image, + gdouble x, + gdouble y, + gdouble epsilon_x, + gdouble epsilon_y); + GimpSamplePoint * gimp_image_pick_sample_point (GimpImage *image, gdouble x, gdouble y, diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-private.h gimp-2.10.14+om/app/core/gimpimage-private.h --- gimp-2.10.8+zorin2/app/core/gimpimage-private.h 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-private.h 2019-10-26 18:49:18.000000000 +0000 @@ -45,10 +45,17 @@ gdouble xresolution; /* image x-res, in dpi */ gdouble yresolution; /* image y-res, in dpi */ GimpUnit resolution_unit; /* resolution unit */ + gboolean resolution_set; /* resolution explicitly set */ GimpImageBaseType base_type; /* base gimp_image type */ GimpPrecision precision; /* image's precision */ GimpLayerMode new_layer_mode; /* default mode of new layers */ + gint show_all; /* render full image content */ + GeglRectangle bounding_box; /* image content bounding box */ + gint bounding_box_freeze_count; + gboolean bounding_box_update_pending; + GeglBuffer *pickable_buffer; + guchar *colormap; /* colormap (for indexed) */ gint n_colors; /* # of colors (for indexed) */ GimpPalette *palette; /* palette of colormap */ @@ -103,6 +110,9 @@ GimpItemTree *vectors; /* the tree of vectors */ GSList *layer_stack; /* the layers in MRU order */ + GQuark layer_offset_x_handler; + GQuark layer_offset_y_handler; + GQuark layer_bounding_box_handler; GQuark layer_alpha_handler; GQuark channel_name_changed_handler; GQuark channel_color_changed_handler; diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-resize.c gimp-2.10.14+om/app/core/gimpimage-resize.c --- gimp-2.10.8+zorin2/app/core/gimpimage-resize.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-resize.c 2019-10-26 18:49:18.000000000 +0000 @@ -224,11 +224,11 @@ gimp_sample_point_get_position (sample_point, &old_x, &old_y); new_y = old_y + offset_y; - if ((new_y < 0) || (new_y > new_height)) + if ((new_y < 0) || (new_y >= new_height)) remove_sample_point = TRUE; new_x = old_x + offset_x; - if ((new_x < 0) || (new_x > new_width)) + if ((new_x < 0) || (new_x >= new_width)) remove_sample_point = TRUE; if (remove_sample_point) diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-transform.c gimp-2.10.14+om/app/core/gimpimage-transform.c --- gimp-2.10.8+zorin2/app/core/gimpimage-transform.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-transform.c 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,338 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpimage-transform.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpmath/gimpmath.h" + +#include "core-types.h" + +#include "vectors/gimpvectors.h" + +#include "gimp.h" +#include "gimp-transform-resize.h" +#include "gimp-transform-utils.h" +#include "gimpchannel.h" +#include "gimpcontext.h" +#include "gimpguide.h" +#include "gimpimage.h" +#include "gimpimage-guides.h" +#include "gimpimage-sample-points.h" +#include "gimpimage-transform.h" +#include "gimpimage-undo.h" +#include "gimpimage-undo-push.h" +#include "gimpitem.h" +#include "gimpobjectqueue.h" +#include "gimpprogress.h" +#include "gimpsamplepoint.h" + + +#define EPSILON 1e-6 + + +/* local function prototypes */ + +static void gimp_image_transform_guides (GimpImage *image, + const GimpMatrix3 *matrix, + const GeglRectangle *old_bounds); +static void gimp_image_transform_sample_points (GimpImage *image, + const GimpMatrix3 *matrix, + const GeglRectangle *old_bounds); + + +/* private functions */ + +static void +gimp_image_transform_guides (GimpImage *image, + const GimpMatrix3 *matrix, + const GeglRectangle *old_bounds) +{ + GList *iter; + + for (iter = gimp_image_get_guides (image); iter;) + { + GimpGuide *guide = iter->data; + GimpOrientationType old_orientation = gimp_guide_get_orientation (guide); + gint old_position = gimp_guide_get_position (guide); + GimpOrientationType new_orientation; + gint new_position; + GimpVector2 vertices[2]; + gint n_vertices; + GimpVector2 diff; + + iter = g_list_next (iter); + + switch (old_orientation) + { + case GIMP_ORIENTATION_HORIZONTAL: + vertices[0].x = old_bounds->x; + vertices[0].y = old_bounds->y + old_position; + + vertices[1].x = old_bounds->x + old_bounds->width / 2.0; + vertices[1].y = old_bounds->y + old_position; + break; + + case GIMP_ORIENTATION_VERTICAL: + vertices[0].x = old_bounds->x + old_position; + vertices[0].y = old_bounds->y; + + vertices[1].x = old_bounds->x + old_position; + vertices[1].y = old_bounds->y + old_bounds->height / 2.0; + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + + gimp_transform_polygon (matrix, + vertices, 2, FALSE, + vertices, &n_vertices); + + if (n_vertices < 2) + { + gimp_image_remove_guide (image, guide, TRUE); + + continue; + } + + gimp_vector2_sub (&diff, &vertices[1], &vertices[0]); + + if (gimp_vector2_length (&diff) <= EPSILON) + { + gimp_image_remove_guide (image, guide, TRUE); + + continue; + } + + if (fabs (diff.x) >= fabs (diff.y)) + { + new_orientation = GIMP_ORIENTATION_HORIZONTAL; + new_position = SIGNED_ROUND (vertices[1].y); + + if (new_position < 0 || new_position > gimp_image_get_height (image)) + { + gimp_image_remove_guide (image, guide, TRUE); + + continue; + } + } + else + { + new_orientation = GIMP_ORIENTATION_VERTICAL; + new_position = SIGNED_ROUND (vertices[1].x); + + if (new_position < 0 || new_position > gimp_image_get_width (image)) + { + gimp_image_remove_guide (image, guide, TRUE); + + continue; + } + } + + if (new_orientation != old_orientation || + new_position != old_position) + { + gimp_image_undo_push_guide (image, NULL, guide); + + gimp_guide_set_orientation (guide, new_orientation); + gimp_guide_set_position (guide, new_position); + + gimp_image_guide_moved (image, guide); + } + } +} + +static void +gimp_image_transform_sample_points (GimpImage *image, + const GimpMatrix3 *matrix, + const GeglRectangle *old_bounds) +{ + GList *iter; + + for (iter = gimp_image_get_sample_points (image); iter;) + { + GimpSamplePoint *sample_point = iter->data; + gint old_x; + gint old_y; + gint new_x; + gint new_y; + GimpVector2 vertices[1]; + gint n_vertices; + + iter = g_list_next (iter); + + gimp_sample_point_get_position (sample_point, &old_x, &old_y); + + vertices[0].x = old_x; + vertices[0].y = old_y; + + gimp_transform_polygon (matrix, + vertices, 1, FALSE, + vertices, &n_vertices); + + if (n_vertices < 1) + { + gimp_image_remove_sample_point (image, sample_point, TRUE); + + continue; + } + + new_x = SIGNED_ROUND (vertices[0].x); + new_y = SIGNED_ROUND (vertices[0].y); + + if (new_x < 0 || new_x >= gimp_image_get_width (image) || + new_y < 0 || new_y >= gimp_image_get_height (image)) + { + gimp_image_remove_sample_point (image, sample_point, TRUE); + + continue; + } + + if (new_x != old_x || new_y != old_y) + gimp_image_move_sample_point (image, sample_point, new_x, new_y, TRUE); + } +} + + +/* public functions */ + +void +gimp_image_transform (GimpImage *image, + GimpContext *context, + const GimpMatrix3 *matrix, + GimpTransformDirection direction, + GimpInterpolationType interpolation_type, + GimpTransformResize clip_result, + GimpProgress *progress) +{ + GimpObjectQueue *queue; + GimpItem *item; + GimpMatrix3 transform; + GeglRectangle old_bounds; + GeglRectangle new_bounds; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (GIMP_IS_CONTEXT (context)); + g_return_if_fail (matrix != NULL); + g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); + + gimp_set_busy (image->gimp); + + old_bounds.x = 0; + old_bounds.y = 0; + old_bounds.width = gimp_image_get_width (image); + old_bounds.height = gimp_image_get_height (image); + + transform = *matrix; + + if (direction == GIMP_TRANSFORM_BACKWARD) + gimp_matrix3_invert (&transform); + + gimp_transform_resize_boundary (&transform, clip_result, + + old_bounds.x, + old_bounds.y, + old_bounds.x + old_bounds.width, + old_bounds.y + old_bounds.height, + + &new_bounds.x, + &new_bounds.y, + &new_bounds.width, + &new_bounds.height); + + new_bounds.width -= new_bounds.x; + new_bounds.height -= new_bounds.y; + + gimp_matrix3_translate (&transform, + old_bounds.x - new_bounds.x, + old_bounds.y - new_bounds.y); + + queue = gimp_object_queue_new (progress); + progress = GIMP_PROGRESS (queue); + + gimp_object_queue_push_container (queue, gimp_image_get_layers (image)); + gimp_object_queue_push (queue, gimp_image_get_mask (image)); + gimp_object_queue_push_container (queue, gimp_image_get_channels (image)); + gimp_object_queue_push_container (queue, gimp_image_get_vectors (image)); + + g_object_freeze_notify (G_OBJECT (image)); + + gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_IMAGE_TRANSFORM, NULL); + + /* Transform all layers, channels (including selection mask), and vectors */ + while ((item = gimp_object_queue_pop (queue))) + { + GimpTransformResize clip = GIMP_TRANSFORM_RESIZE_ADJUST; + + if (GIMP_IS_CHANNEL (item)) + clip = clip_result; + + gimp_item_transform (item, + context, + &transform, direction, + interpolation_type, clip, + progress); + + if (GIMP_IS_VECTORS (item)) + gimp_item_set_size (item, new_bounds.width, new_bounds.height); + } + + /* Resize the image (if needed) */ + if (! gegl_rectangle_equal (&new_bounds, &old_bounds)) + { + gimp_image_undo_push_image_size (image, + NULL, + new_bounds.x, + new_bounds.y, + new_bounds.width, + new_bounds.height); + + g_object_set (image, + "width", new_bounds.width, + "height", new_bounds.height, + NULL); + } + + /* Transform all Guides */ + gimp_image_transform_guides (image, &transform, &old_bounds); + + /* Transform all sample points */ + gimp_image_transform_sample_points (image, &transform, &old_bounds); + + gimp_image_undo_group_end (image); + + g_object_unref (queue); + + if (! gegl_rectangle_equal (&new_bounds, &old_bounds)) + { + gimp_image_size_changed_detailed (image, + old_bounds.x - new_bounds.x, + old_bounds.y - new_bounds.y, + old_bounds.width, + old_bounds.height); + } + + g_object_thaw_notify (G_OBJECT (image)); + + gimp_unset_busy (image->gimp); +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-transform.h gimp-2.10.14+om/app/core/gimpimage-transform.h --- gimp-2.10.8+zorin2/app/core/gimpimage-transform.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-transform.h 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,34 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattisbvf + * + * gimpimage-transform.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_IMAGE_TRANSFORM_H__ +#define __GIMP_IMAGE_TRANSFORM_H__ + + +void gimp_image_transform (GimpImage *image, + GimpContext *context, + const GimpMatrix3 *matrix, + GimpTransformDirection direction, + GimpInterpolationType interpolation_type, + GimpTransformResize clip_result, + GimpProgress *progress); + + +#endif /* __GIMP_IMAGE_TRANSFORM_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-undo.c gimp-2.10.14+om/app/core/gimpimage-undo.c --- gimp-2.10.8+zorin2/app/core/gimpimage-undo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-undo.c 2019-10-26 18:49:18.000000000 +0000 @@ -26,7 +26,6 @@ #include "gimp.h" #include "gimp-utils.h" -#include "gimpdrawableundo.h" #include "gimpimage.h" #include "gimpimage-private.h" #include "gimpimage-undo.h" @@ -461,34 +460,6 @@ return NULL; } -GimpUndo * -gimp_image_undo_get_fadeable (GimpImage *image) -{ - GimpImagePrivate *private; - GimpUndo *undo; - - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); - - private = GIMP_IMAGE_GET_PRIVATE (image); - - undo = gimp_undo_stack_peek (private->undo_stack); - - if (GIMP_IS_UNDO_STACK (undo) && undo->undo_type == GIMP_UNDO_GROUP_PAINT) - { - GimpUndoStack *stack = GIMP_UNDO_STACK (undo); - - if (gimp_undo_stack_get_depth (stack) == 2) - { - undo = gimp_undo_stack_peek (stack); - } - } - - if (GIMP_IS_DRAWABLE_UNDO (undo)) - return undo; - - return NULL; -} - /* private functions */ @@ -643,6 +614,7 @@ case GIMP_UNDO_GROUP_IMAGE_RESIZE: case GIMP_UNDO_GROUP_IMAGE_FLIP: case GIMP_UNDO_GROUP_IMAGE_ROTATE: + case GIMP_UNDO_GROUP_IMAGE_TRANSFORM: case GIMP_UNDO_GROUP_IMAGE_CROP: return GIMP_DIRTY_IMAGE | GIMP_DIRTY_IMAGE_SIZE; diff -Nru gimp-2.10.8+zorin2/app/core/gimpimageundo.c gimp-2.10.14+om/app/core/gimpimageundo.c --- gimp-2.10.8+zorin2/app/core/gimpimageundo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimageundo.c 2019-06-12 16:43:38.000000000 +0000 @@ -39,7 +39,6 @@ #include "gimpimage-metadata.h" #include "gimpimage-private.h" #include "gimpimageundo.h" -#include "gimpparasitelist.h" enum @@ -501,21 +500,14 @@ case GIMP_UNDO_PARASITE_REMOVE: { GimpParasite *parasite = image_undo->parasite; - const gchar *name; image_undo->parasite = gimp_parasite_copy (gimp_image_parasite_find (image, image_undo->parasite_name)); if (parasite) - gimp_parasite_list_add (private->parasites, parasite); + gimp_image_parasite_attach (image, parasite, FALSE); else - gimp_parasite_list_remove (private->parasites, - image_undo->parasite_name); - - name = parasite ? parasite->name : image_undo->parasite_name; - - if (strcmp (name, GIMP_ICC_PROFILE_PARASITE_NAME) == 0) - _gimp_image_update_color_profile (image, parasite); + gimp_image_parasite_detach (image, image_undo->parasite_name, FALSE); if (parasite) gimp_parasite_free (parasite); diff -Nru gimp-2.10.8+zorin2/app/core/gimpimage-undo.h gimp-2.10.14+om/app/core/gimpimage-undo.h --- gimp-2.10.8+zorin2/app/core/gimpimage-undo.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimage-undo.h 2019-01-03 14:13:22.000000000 +0000 @@ -53,7 +53,5 @@ GType object_type, GimpUndoType undo_type); -GimpUndo * gimp_image_undo_get_fadeable (GimpImage *image); - #endif /* __GIMP_IMAGE__UNDO_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpimageviewable.c gimp-2.10.14+om/app/core/gimpimageviewable.c --- gimp-2.10.8+zorin2/app/core/gimpimageviewable.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimageviewable.c 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,653 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpimageviewable.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "libgimpcolor/gimpcolor.h" + +#include "core-types.h" + +#include "gegl/gimp-babl.h" +#include "gegl/gimp-gegl-loops.h" + +#include "gimpimage.h" +#include "gimpimage-color-profile.h" +#include "gimpimageviewable.h" +#include "gimppickable.h" +#include "gimpprojectable.h" +#include "gimptempbuf.h" + + +enum +{ + PROP_0, + PROP_IMAGE, + PROP_SHOW_ALL +}; + + +struct _GimpImageViewablePrivate +{ + GimpImage *image; + gboolean show_all; + + GeglRectangle bounding_box; + gboolean frozen; +}; + + +/* local function prototypes */ + +static void gimp_image_viewable_finalize (GObject *object); +static void gimp_image_viewable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_image_viewable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean gimp_image_viewable_get_size (GimpViewable *viewable, + gint *width, + gint *height); +static void gimp_image_viewable_get_preview_size (GimpViewable *viewable, + gint size, + gboolean is_popup, + gboolean dot_for_dot, + gint *width, + gint *height); +static gboolean gimp_image_viewable_get_popup_size (GimpViewable *viewable, + gint width, + gint height, + gboolean dot_for_dot, + gint *popup_width, + gint *popup_height); +static GimpTempBuf * gimp_image_viewable_get_new_preview (GimpViewable *viewable, + GimpContext *context, + gint width, + gint height); +static GdkPixbuf * gimp_image_viewable_get_new_pixbuf (GimpViewable *viewable, + GimpContext *context, + gint width, + gint height); +static gchar * gimp_image_viewable_get_description (GimpViewable *viewable, + gchar **tooltip); + +static void gimp_image_viewable_image_frozen_notify (GimpImage *image, + const GParamSpec *pspec, + GimpImageViewable *image_viewable); +static void gimp_image_viewable_image_invalidate_preview (GimpImage *image, + GimpImageViewable *image_viewable); +static void gimp_image_viewable_image_size_changed (GimpImage *image, + GimpImageViewable *image_viewable); +static void gimp_image_viewable_image_bounds_changed (GimpImage *image, + gint old_x, + gint old_y, + GimpImageViewable *image_viewable); + +static void gimp_image_viewable_set_image (GimpImageViewable *image_viewable, + GimpImage *image); +static void gimp_image_viewable_update_bounding_box (GimpImageViewable *image_viewable); +static void gimp_image_viewable_update_frozen (GimpImageViewable *image_viewable); + + +G_DEFINE_TYPE_WITH_PRIVATE (GimpImageViewable, gimp_image_viewable, + GIMP_TYPE_VIEWABLE) + +#define parent_class gimp_image_viewable_parent_class + + +/* private functions */ + + +static void +gimp_image_viewable_class_init (GimpImageViewableClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); + + object_class->finalize = gimp_image_viewable_finalize; + object_class->set_property = gimp_image_viewable_set_property; + object_class->get_property = gimp_image_viewable_get_property; + + viewable_class->default_icon_name = "gimp-image"; + viewable_class->get_size = gimp_image_viewable_get_size; + viewable_class->get_preview_size = gimp_image_viewable_get_preview_size; + viewable_class->get_popup_size = gimp_image_viewable_get_popup_size; + viewable_class->get_new_preview = gimp_image_viewable_get_new_preview; + viewable_class->get_new_pixbuf = gimp_image_viewable_get_new_pixbuf; + viewable_class->get_description = gimp_image_viewable_get_description; + + g_object_class_install_property (object_class, PROP_IMAGE, + g_param_spec_object ("image", + NULL, NULL, + GIMP_TYPE_IMAGE, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_SHOW_ALL, + g_param_spec_boolean ("show-all", + NULL, NULL, + FALSE, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +gimp_image_viewable_init (GimpImageViewable *image_viewable) +{ + image_viewable->priv = gimp_image_viewable_get_instance_private (image_viewable); +} + +static void +gimp_image_viewable_finalize (GObject *object) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (object); + + gimp_image_viewable_set_image (image_viewable, NULL); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_image_viewable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (object); + + switch (property_id) + { + case PROP_IMAGE: + gimp_image_viewable_set_image (image_viewable, + g_value_get_object (value)); + break; + + case PROP_SHOW_ALL: + gimp_image_viewable_set_show_all (image_viewable, + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_image_viewable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (object); + + switch (property_id) + { + case PROP_IMAGE: + g_value_set_object (value, + gimp_image_viewable_get_image (image_viewable)); + break; + + case PROP_SHOW_ALL: + g_value_set_boolean (value, + gimp_image_viewable_get_show_all (image_viewable)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +gimp_image_viewable_get_size (GimpViewable *viewable, + gint *width, + gint *height) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (viewable); + + *width = image_viewable->priv->bounding_box.width; + *height = image_viewable->priv->bounding_box.height; + + return TRUE; +} + +static void +gimp_image_viewable_get_preview_size (GimpViewable *viewable, + gint size, + gboolean is_popup, + gboolean dot_for_dot, + gint *width, + gint *height) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (viewable); + GimpImage *image = image_viewable->priv->image; + gdouble xres; + gdouble yres; + gint viewable_width; + gint viewable_height; + + gimp_image_get_resolution (image, &xres, &yres); + + gimp_viewable_get_size (viewable, &viewable_width, &viewable_height); + + gimp_viewable_calc_preview_size (viewable_width, + viewable_height, + size, + size, + dot_for_dot, + xres, + yres, + width, + height, + NULL); +} + +static gboolean +gimp_image_viewable_get_popup_size (GimpViewable *viewable, + gint width, + gint height, + gboolean dot_for_dot, + gint *popup_width, + gint *popup_height) +{ + gint viewable_width; + gint viewable_height; + + gimp_viewable_get_size (viewable, &viewable_width, &viewable_height); + + if (viewable_width > width || viewable_height > height) + { + gboolean scaling_up; + + gimp_viewable_calc_preview_size (viewable_width, + viewable_height, + width * 2, + height * 2, + dot_for_dot, 1.0, 1.0, + popup_width, + popup_height, + &scaling_up); + + if (scaling_up) + { + *popup_width = viewable_width; + *popup_height = viewable_height; + } + + return TRUE; + } + + return FALSE; +} + +static GimpTempBuf * +gimp_image_viewable_get_new_preview (GimpViewable *viewable, + GimpContext *context, + gint width, + gint height) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (viewable); + GimpImage *image = image_viewable->priv->image; + GimpPickable *pickable; + const Babl *format; + GeglRectangle bounding_box; + gboolean linear; + GimpTempBuf *buf; + gdouble scale_x; + gdouble scale_y; + gdouble scale; + + if (! image_viewable->priv->show_all) + pickable = GIMP_PICKABLE (image); + else + pickable = GIMP_PICKABLE (gimp_image_get_projection (image)); + + bounding_box = gimp_image_viewable_get_bounding_box (image_viewable); + + scale_x = (gdouble) width / (gdouble) bounding_box.width; + scale_y = (gdouble) height / (gdouble) bounding_box.height; + + scale = MIN (scale_x, scale_y); + + format = gimp_projectable_get_format (GIMP_PROJECTABLE (image)); + linear = gimp_babl_format_get_linear (format); + + format = gimp_babl_format (gimp_babl_format_get_base_type (format), + gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, + linear), + babl_format_has_alpha (format)); + + buf = gimp_temp_buf_new (width, height, format); + + gegl_buffer_get (gimp_pickable_get_buffer (pickable), + GEGL_RECTANGLE (bounding_box.x * scale, + bounding_box.y * scale, + width, + height), + scale, + gimp_temp_buf_get_format (buf), + gimp_temp_buf_get_data (buf), + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); + + return buf; +} + +static GdkPixbuf * +gimp_image_viewable_get_new_pixbuf (GimpViewable *viewable, + GimpContext *context, + gint width, + gint height) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (viewable); + GimpImage *image = image_viewable->priv->image; + GimpPickable *pickable; + GeglRectangle bounding_box; + GdkPixbuf *pixbuf; + gdouble scale_x; + gdouble scale_y; + gdouble scale; + GimpColorTransform *transform; + + if (! image_viewable->priv->show_all) + pickable = GIMP_PICKABLE (image); + else + pickable = GIMP_PICKABLE (gimp_image_get_projection (image)); + + bounding_box = gimp_image_viewable_get_bounding_box (image_viewable); + + scale_x = (gdouble) width / (gdouble) bounding_box.width; + scale_y = (gdouble) height / (gdouble) bounding_box.height; + + scale = MIN (scale_x, scale_y); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, + width, height); + + transform = gimp_image_get_color_transform_to_srgb_u8 (image); + + if (transform) + { + GimpTempBuf *temp_buf; + GeglBuffer *src_buf; + GeglBuffer *dest_buf; + + temp_buf = gimp_temp_buf_new (width, height, + gimp_pickable_get_format (pickable)); + + gegl_buffer_get (gimp_pickable_get_buffer (pickable), + GEGL_RECTANGLE (bounding_box.x * scale, + bounding_box.y * scale, + width, + height), + scale, + gimp_temp_buf_get_format (temp_buf), + gimp_temp_buf_get_data (temp_buf), + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); + + src_buf = gimp_temp_buf_create_buffer (temp_buf); + dest_buf = gimp_pixbuf_create_buffer (pixbuf); + + gimp_temp_buf_unref (temp_buf); + + gimp_color_transform_process_buffer (transform, + src_buf, + GEGL_RECTANGLE (0, 0, + width, height), + dest_buf, + GEGL_RECTANGLE (0, 0, 0, 0)); + + g_object_unref (src_buf); + g_object_unref (dest_buf); + } + else + { + gegl_buffer_get (gimp_pickable_get_buffer (pickable), + GEGL_RECTANGLE (bounding_box.x * scale, + bounding_box.y * scale, + width, + height), + scale, + gimp_pixbuf_get_format (pixbuf), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf), + GEGL_ABYSS_CLAMP); + } + + return pixbuf; +} + +static gchar * +gimp_image_viewable_get_description (GimpViewable *viewable, + gchar **tooltip) +{ + GimpImageViewable *image_viewable = GIMP_IMAGE_VIEWABLE (viewable); + GimpImage *image = image_viewable->priv->image; + + if (tooltip) + *tooltip = g_strdup (gimp_image_get_display_path (image)); + + return g_strdup_printf ("%s-%d", + gimp_image_get_display_name (image), + gimp_image_get_ID (image)); +} + +static void +gimp_image_viewable_image_frozen_notify (GimpImage *image, + const GParamSpec *pspec, + GimpImageViewable *image_viewable) +{ + gimp_image_viewable_update_frozen (image_viewable); +} + +static void +gimp_image_viewable_image_invalidate_preview (GimpImage *image, + GimpImageViewable *image_viewable) +{ + gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image_viewable)); +} + +static void +gimp_image_viewable_image_size_changed (GimpImage *image, + GimpImageViewable *image_viewable) +{ + gimp_image_viewable_update_bounding_box (image_viewable); +} + +static void +gimp_image_viewable_image_bounds_changed (GimpImage *image, + gint old_x, + gint old_y, + GimpImageViewable *image_viewable) +{ + gimp_image_viewable_update_bounding_box (image_viewable); +} + +static void +gimp_image_viewable_set_image (GimpImageViewable *image_viewable, + GimpImage *image) +{ + if (image_viewable->priv->image) + { + g_signal_handlers_disconnect_by_func ( + image_viewable->priv->image, + gimp_image_viewable_image_frozen_notify, + image_viewable); + g_signal_handlers_disconnect_by_func ( + image_viewable->priv->image, + gimp_image_viewable_image_invalidate_preview, + image_viewable); + g_signal_handlers_disconnect_by_func ( + image_viewable->priv->image, + gimp_image_viewable_image_size_changed, + image_viewable); + g_signal_handlers_disconnect_by_func ( + image_viewable->priv->image, + gimp_image_viewable_image_bounds_changed, + image_viewable); + + g_object_unref (image_viewable->priv->image); + } + + image_viewable->priv->image = image; + + if (image_viewable->priv->image) + { + g_object_ref (image_viewable->priv->image); + + g_signal_connect ( + image_viewable->priv->image, "notify::frozen", + G_CALLBACK (gimp_image_viewable_image_frozen_notify), + image_viewable); + g_signal_connect ( + image_viewable->priv->image, "invalidate-preview", + G_CALLBACK (gimp_image_viewable_image_invalidate_preview), + image_viewable); + g_signal_connect ( + image_viewable->priv->image, "size-changed", + G_CALLBACK (gimp_image_viewable_image_size_changed), + image_viewable); + g_signal_connect ( + image_viewable->priv->image, "bounds-changed", + G_CALLBACK (gimp_image_viewable_image_bounds_changed), + image_viewable); + + gimp_image_viewable_update_bounding_box (image_viewable); + gimp_image_viewable_update_frozen (image_viewable); + + gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image_viewable)); + } +} + +static void +gimp_image_viewable_update_bounding_box (GimpImageViewable *image_viewable) +{ + GimpImage *image = image_viewable->priv->image; + GeglRectangle bounding_box; + + if (gimp_viewable_preview_is_frozen (GIMP_VIEWABLE (image_viewable))) + return; + + if (! image_viewable->priv->show_all) + { + bounding_box.x = 0; + bounding_box.y = 0; + bounding_box.width = gimp_image_get_width (image); + bounding_box.height = gimp_image_get_height (image); + } + else + { + bounding_box = gimp_projectable_get_bounding_box ( + GIMP_PROJECTABLE (image)); + } + + if (! gegl_rectangle_equal (&bounding_box, + &image_viewable->priv->bounding_box)) + { + image_viewable->priv->bounding_box = bounding_box; + + gimp_viewable_size_changed (GIMP_VIEWABLE (image_viewable)); + } +} + +static void +gimp_image_viewable_update_frozen (GimpImageViewable *image_viewable) +{ + gboolean frozen; + + frozen = gimp_viewable_preview_is_frozen ( + GIMP_VIEWABLE (image_viewable->priv->image)); + + if (frozen != image_viewable->priv->frozen) + { + image_viewable->priv->frozen = frozen; + + if (frozen) + { + gimp_viewable_preview_freeze (GIMP_VIEWABLE (image_viewable)); + } + else + { + gimp_viewable_preview_thaw (GIMP_VIEWABLE (image_viewable)); + + gimp_image_viewable_update_bounding_box (image_viewable); + } + } +} + + +/* public functions */ + + +GimpImageViewable * +gimp_image_viewable_new (GimpImage *image) +{ + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + + return g_object_new (GIMP_TYPE_IMAGE_VIEWABLE, + "image", image, + NULL); +} + +GimpImage * +gimp_image_viewable_get_image (GimpImageViewable *image_viewable) +{ + g_return_val_if_fail (GIMP_IS_IMAGE_VIEWABLE (image_viewable), NULL); + + return image_viewable->priv->image; +} + +void +gimp_image_viewable_set_show_all (GimpImageViewable *image_viewable, + gboolean show_all) +{ + g_return_if_fail (GIMP_IS_IMAGE_VIEWABLE (image_viewable)); + + if (show_all != image_viewable->priv->show_all) + { + image_viewable->priv->show_all = show_all; + + gimp_image_viewable_update_bounding_box (image_viewable); + } +} + +gboolean +gimp_image_viewable_get_show_all (GimpImageViewable *image_viewable) +{ + g_return_val_if_fail (GIMP_IS_IMAGE_VIEWABLE (image_viewable), FALSE); + + return image_viewable->priv->show_all; +} + +GeglRectangle +gimp_image_viewable_get_bounding_box (GimpImageViewable *image_viewable) +{ + g_return_val_if_fail (GIMP_IS_IMAGE_VIEWABLE (image_viewable), + *GEGL_RECTANGLE (0, 0, 0, 0)); + + return image_viewable->priv->bounding_box; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimpimageviewable.h gimp-2.10.14+om/app/core/gimpimageviewable.h --- gimp-2.10.8+zorin2/app/core/gimpimageviewable.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpimageviewable.h 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,65 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpimageviewable.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_IMAGE_VIEWABLE_H__ +#define __GIMP_IMAGE_VIEWABLE_H__ + + +#include "gimpviewable.h" + + +#define GIMP_TYPE_IMAGE_VIEWABLE (gimp_image_viewable_get_type ()) +#define GIMP_IMAGE_VIEWABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_IMAGE_VIEWABLE, GimpImageViewable)) +#define GIMP_IMAGE_VIEWABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_IMAGE_VIEWABLE, GimpImageViewableClass)) +#define GIMP_IS_IMAGE_VIEWABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_IMAGE_VIEWABLE)) +#define GIMP_IS_IMAGE_VIEWABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_IMAGE_VIEWABLE)) +#define GIMP_IMAGE_VIEWABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_IMAGE_VIEWABLE, GimpImageViewableClass)) + + +typedef struct _GimpImageViewablePrivate GimpImageViewablePrivate; +typedef struct _GimpImageViewableClass GimpImageViewableClass; + +struct _GimpImageViewable +{ + GimpViewable parent_instance; + + GimpImageViewablePrivate *priv; +}; + +struct _GimpImageViewableClass +{ + GimpViewableClass parent_class; +}; + + +GType gimp_image_viewable_get_type (void) G_GNUC_CONST; + +GimpImageViewable * gimp_image_viewable_new (GimpImage *image); + +GimpImage * gimp_image_viewable_get_image (GimpImageViewable *image_viewable); + +void gimp_image_viewable_set_show_all (GimpImageViewable *image_viewable, + gboolean show_all); +gboolean gimp_image_viewable_get_show_all (GimpImageViewable *image_viewable); + +GeglRectangle gimp_image_viewable_get_bounding_box (GimpImageViewable *image_viewable); + + +#endif /* __GIMP_IMAGE_VIEWABLE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimp-internal-data.c gimp-2.10.14+om/app/core/gimp-internal-data.c --- gimp-2.10.8+zorin2/app/core/gimp-internal-data.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-internal-data.c 2019-01-03 14:13:22.000000000 +0000 @@ -288,17 +288,25 @@ success = FALSE; } } - else if (error && *error) - { - g_prefix_error (error, - _("Error saving '%s': "), - gimp_file_get_utf8_name (file)); - } else { - g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, - _("Error saving '%s'"), - gimp_file_get_utf8_name (file)); + GCancellable *cancellable = g_cancellable_new (); + + g_cancellable_cancel (cancellable); + if (error && *error) + { + g_prefix_error (error, + _("Error saving '%s': "), + gimp_file_get_utf8_name (file)); + } + else + { + g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE, + _("Error saving '%s'"), + gimp_file_get_utf8_name (file)); + } + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); } g_object_unref (output); diff -Nru gimp-2.10.8+zorin2/app/core/gimpitem.c gimp-2.10.14+om/app/core/gimpitem.c --- gimp-2.10.8+zorin2/app/core/gimpitem.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpitem.c 2019-10-26 18:49:18.000000000 +0000 @@ -163,6 +163,9 @@ gint new_height, gint offset_x, gint offset_y); +static GimpTransformResize + gimp_item_real_get_clip (GimpItem *item, + GimpTransformResize clip_result); @@ -271,6 +274,7 @@ klass->flip = NULL; klass->rotate = NULL; klass->transform = NULL; + klass->get_clip = gimp_item_real_get_clip; klass->fill = NULL; klass->stroke = NULL; klass->to_selection = NULL; @@ -687,6 +691,16 @@ private->offset_y - offset_y); } +static GimpTransformResize +gimp_item_real_get_clip (GimpItem *item, + GimpTransformResize clip_result) +{ + if (gimp_item_get_lock_position (item)) + return GIMP_TRANSFORM_RESIZE_CLIP; + else + return clip_result; +} + /* public functions */ @@ -1729,6 +1743,15 @@ gimp_image_undo_group_end (image); } +GimpTransformResize +gimp_item_get_clip (GimpItem *item, + GimpTransformResize clip_result) +{ + g_return_val_if_fail (GIMP_IS_ITEM (item), GIMP_TRANSFORM_RESIZE_ADJUST); + + return GIMP_ITEM_GET_CLASS (item)->get_clip (item, clip_result); +} + gboolean gimp_item_fill (GimpItem *item, GimpDrawable *drawable, @@ -2133,7 +2156,7 @@ if (gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_PARENT)) { gimp_parasite_shift_parent (©); - gimp_image_parasite_attach (private->image, ©); + gimp_image_parasite_attach (private->image, ©, TRUE); } else if (gimp_parasite_has_flag (©, GIMP_PARASITE_ATTACH_GRANDPARENT)) { diff -Nru gimp-2.10.8+zorin2/app/core/gimpitem.h gimp-2.10.14+om/app/core/gimpitem.h --- gimp-2.10.8+zorin2/app/core/gimpitem.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpitem.h 2019-10-26 18:49:18.000000000 +0000 @@ -113,6 +113,8 @@ GimpInterpolationType interpolation_type, GimpTransformResize clip_result, GimpProgress *progress); + GimpTransformResize (* get_clip) (GimpItem *item, + GimpTransformResize clip_result); gboolean (* fill) (GimpItem *item, GimpDrawable *drawable, GimpFillOptions *fill_options, @@ -288,6 +290,8 @@ GimpInterpolationType interpolation_type, GimpTransformResize clip_result, GimpProgress *progress); +GimpTransformResize gimp_item_get_clip (GimpItem *item, + GimpTransformResize clip_result); gboolean gimp_item_fill (GimpItem *item, GimpDrawable *drawable, diff -Nru gimp-2.10.8+zorin2/app/core/gimpitem-linked.c gimp-2.10.14+om/app/core/gimpitem-linked.c --- gimp-2.10.8+zorin2/app/core/gimpitem-linked.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpitem-linked.c 2019-10-26 18:49:18.000000000 +0000 @@ -134,7 +134,6 @@ { GimpImage *image; GList *items; - GList *channels; g_return_if_fail (GIMP_IS_ITEM (item)); g_return_if_fail (GIMP_IS_CONTEXT (context)); @@ -144,30 +143,14 @@ image = gimp_item_get_image (item); items = gimp_image_item_list_get_list (image, - GIMP_ITEM_TYPE_LAYERS | - GIMP_ITEM_TYPE_VECTORS, + GIMP_ITEM_TYPE_ALL, GIMP_ITEM_SET_LINKED); items = gimp_image_item_list_filter (items); - channels = gimp_image_item_list_get_list (image, - GIMP_ITEM_TYPE_CHANNELS, - GIMP_ITEM_SET_LINKED); - channels = gimp_image_item_list_filter (channels); - - if (items && channels) - gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_TRANSFORM, - C_("undo-type", "Rotate Items")); - gimp_image_item_list_rotate (image, items, context, rotate_type, center_x, center_y, clip_result); - gimp_image_item_list_rotate (image, channels, context, - rotate_type, center_x, center_y, TRUE); - - if (items && channels) - gimp_image_undo_group_end (image); g_list_free (items); - g_list_free (channels); } void diff -Nru gimp-2.10.8+zorin2/app/core/gimpitemtree.c gimp-2.10.14+om/app/core/gimpitemtree.c --- gimp-2.10.8+zorin2/app/core/gimpitemtree.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpitemtree.c 2019-04-07 11:38:14.000000000 +0000 @@ -66,6 +66,7 @@ /* local function prototypes */ static void gimp_item_tree_constructed (GObject *object); +static void gimp_item_tree_dispose (GObject *object); static void gimp_item_tree_finalize (GObject *object); static void gimp_item_tree_set_property (GObject *object, guint property_id, @@ -96,6 +97,7 @@ GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); object_class->constructed = gimp_item_tree_constructed; + object_class->dispose = gimp_item_tree_dispose; object_class->finalize = gimp_item_tree_finalize; object_class->set_property = gimp_item_tree_set_property; object_class->get_property = gimp_item_tree_get_property; @@ -159,6 +161,23 @@ } static void +gimp_item_tree_dispose (GObject *object) +{ + GimpItemTree *tree = GIMP_ITEM_TREE (object); + GimpItemTreePrivate *private = GIMP_ITEM_TREE_GET_PRIVATE (tree); + + gimp_item_tree_set_active_item (tree, NULL); + + gimp_container_foreach (tree->container, + (GFunc) gimp_item_removed, NULL); + + gimp_container_clear (tree->container); + g_hash_table_remove_all (private->name_hash); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void gimp_item_tree_finalize (GObject *object) { GimpItemTree *tree = GIMP_ITEM_TREE (object); diff -Nru gimp-2.10.8+zorin2/app/core/gimplayer.c gimp-2.10.14+om/app/core/gimplayer.c --- gimp-2.10.8+zorin2/app/core/gimplayer.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplayer.c 2019-10-26 18:49:18.000000000 +0000 @@ -200,8 +200,9 @@ gboolean push_undo, const gchar *undo_desc, GeglBuffer *buffer, - gint offset_x, - gint offset_y); + const GeglRectangle *bounds); +static GeglRectangle + gimp_layer_get_bounding_box (GimpDrawable *drawable); static GimpColorProfile * gimp_layer_get_color_profile (GimpColorManaged *managed); @@ -461,6 +462,7 @@ drawable_class->get_active_components = gimp_layer_get_active_components; drawable_class->get_active_mask = gimp_layer_get_active_mask; drawable_class->set_buffer = gimp_layer_set_buffer; + drawable_class->get_bounding_box = gimp_layer_get_bounding_box; klass->opacity_changed = NULL; klass->mode_changed = NULL; @@ -1425,24 +1427,23 @@ static void gimp_layer_invalidate_boundary (GimpDrawable *drawable) { - GimpLayer *layer = GIMP_LAYER (drawable); - GimpImage *image; - GimpChannel *mask; - - if (! (image = gimp_item_get_image (GIMP_ITEM (layer)))) - return; + GimpLayer *layer = GIMP_LAYER (drawable); - /* Turn the current selection off */ - gimp_image_selection_invalidate (image); + if (gimp_item_is_attached (GIMP_ITEM (drawable)) && + gimp_item_is_visible (GIMP_ITEM (drawable))) + { + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpChannel *mask = gimp_image_get_mask (image); - /* get the selection mask channel */ - mask = gimp_image_get_mask (image); + /* Turn the current selection off */ + gimp_image_selection_invalidate (image); - /* Only bother with the bounds if there is a selection */ - if (! gimp_channel_is_empty (mask)) - { - mask->bounds_known = FALSE; - mask->boundary_known = FALSE; + /* Only bother with the bounds if there is a selection */ + if (! gimp_channel_is_empty (mask)) + { + mask->bounds_known = FALSE; + mask->boundary_known = FALSE; + } } if (gimp_layer_is_floating_sel (layer)) @@ -1478,12 +1479,11 @@ } static void -gimp_layer_set_buffer (GimpDrawable *drawable, - gboolean push_undo, - const gchar *undo_desc, - GeglBuffer *buffer, - gint offset_x, - gint offset_y) +gimp_layer_set_buffer (GimpDrawable *drawable, + gboolean push_undo, + const gchar *undo_desc, + GeglBuffer *buffer, + const GeglRectangle *bounds) { GeglBuffer *old_buffer = gimp_drawable_get_buffer (drawable); gint old_linear = -1; @@ -1493,8 +1493,7 @@ GIMP_DRAWABLE_CLASS (parent_class)->set_buffer (drawable, push_undo, undo_desc, - buffer, - offset_x, offset_y); + buffer, bounds); if (gimp_filter_peek_node (GIMP_FILTER (drawable))) { @@ -1503,6 +1502,17 @@ } } +static GeglRectangle +gimp_layer_get_bounding_box (GimpDrawable *drawable) +{ + GimpLayer *layer = GIMP_LAYER (drawable); + + if (gimp_layer_get_mask (layer)) + return GIMP_DRAWABLE_CLASS (parent_class)->get_bounding_box (drawable); + + return gegl_node_get_bounding_box (gimp_drawable_get_source_node (drawable)); +} + static GimpColorProfile * gimp_layer_get_color_profile (GimpColorManaged *managed) { @@ -1870,6 +1880,8 @@ gimp_layer_update_mode_node (layer); } + gimp_drawable_update_bounding_box (GIMP_DRAWABLE (layer)); + if (gimp_layer_get_apply_mask (layer) || gimp_layer_get_show_mask (layer)) { @@ -2187,6 +2199,8 @@ gimp_layer_update_mode_node (layer); } + gimp_drawable_update_bounding_box (GIMP_DRAWABLE (layer)); + /* If applying actually changed the view */ if (view_changed) { @@ -2458,8 +2472,7 @@ { if (layer->fs.segs) { - g_free (layer->fs.segs); - layer->fs.segs = NULL; + g_clear_pointer (&layer->fs.segs, g_free); layer->fs.num_segs = 0; } diff -Nru gimp-2.10.8+zorin2/app/core/gimplayer-floating-selection.c gimp-2.10.14+om/app/core/gimplayer-floating-selection.c --- gimp-2.10.8+zorin2/app/core/gimplayer-floating-selection.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplayer-floating-selection.c 2019-10-26 18:49:18.000000000 +0000 @@ -100,11 +100,13 @@ void floating_sel_anchor (GimpLayer *layer) { - GimpImage *image; - GimpDrawable *drawable; - GimpFilter *filter = NULL; - gint off_x, off_y; - gint dr_off_x, dr_off_y; + GimpImage *image; + GimpDrawable *drawable; + GimpFilter *filter = NULL; + GeglRectangle bounding_box; + GeglRectangle dr_bounding_box; + gint off_x, off_y; + gint dr_off_x, dr_off_y; g_return_if_fail (GIMP_IS_LAYER (layer)); g_return_if_fail (gimp_layer_is_floating_sel (layer)); @@ -122,30 +124,29 @@ gimp_item_get_offset (GIMP_ITEM (layer), &off_x, &off_y); gimp_item_get_offset (GIMP_ITEM (drawable), &dr_off_x, &dr_off_y); + bounding_box = gimp_drawable_get_bounding_box (GIMP_DRAWABLE (layer)); + dr_bounding_box = gimp_drawable_get_bounding_box (drawable); + + bounding_box.x += off_x; + bounding_box.y += off_y; + + dr_bounding_box.x += dr_off_x; + dr_bounding_box.y += dr_off_y; + if (gimp_item_get_visible (GIMP_ITEM (layer)) && - gimp_rectangle_intersect (off_x, off_y, - gimp_item_get_width (GIMP_ITEM (layer)), - gimp_item_get_height (GIMP_ITEM (layer)), - dr_off_x, dr_off_y, - gimp_item_get_width (GIMP_ITEM (drawable)), - gimp_item_get_height (GIMP_ITEM (drawable)), - NULL, NULL, NULL, NULL)) + gegl_rectangle_intersect (NULL, &bounding_box, &dr_bounding_box)) { filter = gimp_drawable_get_floating_sel_filter (drawable); - g_object_ref (filter); } - /* first remove the filter, then merge it, or we will get warnings - * about already connected nodes - */ - gimp_image_remove_layer (image, layer, TRUE, NULL); - if (filter) { - gimp_drawable_merge_filter (drawable, filter, NULL, NULL, FALSE); - g_object_unref (filter); + gimp_drawable_merge_filter (drawable, filter, NULL, NULL, + FALSE, FALSE, FALSE); } + gimp_image_remove_layer (image, layer, TRUE, NULL); + gimp_image_undo_group_end (image); /* invalidate the boundaries */ diff -Nru gimp-2.10.8+zorin2/app/core/gimplayermask.c gimp-2.10.14+om/app/core/gimplayermask.c --- gimp-2.10.8+zorin2/app/core/gimplayermask.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplayermask.c 2019-04-07 11:38:14.000000000 +0000 @@ -32,6 +32,9 @@ #include "gimp-intl.h" +static void gimp_layer_mask_preview_freeze (GimpViewable *viewable); +static void gimp_layer_mask_preview_thaw (GimpViewable *viewable); + static gboolean gimp_layer_mask_is_attached (GimpItem *item); static gboolean gimp_layer_mask_is_content_locked (GimpItem *item); static gboolean gimp_layer_mask_is_position_locked (GimpItem *item); @@ -67,6 +70,9 @@ viewable_class->default_icon_name = "gimp-layer-mask"; + viewable_class->preview_freeze = gimp_layer_mask_preview_freeze; + viewable_class->preview_thaw = gimp_layer_mask_preview_thaw; + item_class->is_attached = gimp_layer_mask_is_attached; item_class->is_content_locked = gimp_layer_mask_is_content_locked; item_class->is_position_locked = gimp_layer_mask_is_position_locked; @@ -85,6 +91,42 @@ layer_mask->layer = NULL; } +static void +gimp_layer_mask_preview_freeze (GimpViewable *viewable) +{ + GimpLayerMask *mask = GIMP_LAYER_MASK (viewable); + GimpLayer *layer = gimp_layer_mask_get_layer (mask); + + if (layer) + { + GimpViewable *parent = gimp_viewable_get_parent (GIMP_VIEWABLE (layer)); + + if (! parent && gimp_item_is_attached (GIMP_ITEM (layer))) + parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (layer))); + + if (parent) + gimp_viewable_preview_freeze (parent); + } +} + +static void +gimp_layer_mask_preview_thaw (GimpViewable *viewable) +{ + GimpLayerMask *mask = GIMP_LAYER_MASK (viewable); + GimpLayer *layer = gimp_layer_mask_get_layer (mask); + + if (layer) + { + GimpViewable *parent = gimp_viewable_get_parent (GIMP_VIEWABLE (layer)); + + if (! parent && gimp_item_is_attached (GIMP_ITEM (layer))) + parent = GIMP_VIEWABLE (gimp_item_get_image (GIMP_ITEM (layer))); + + if (parent) + gimp_viewable_preview_thaw (parent); + } +} + static gboolean gimp_layer_mask_is_content_locked (GimpItem *item) { diff -Nru gimp-2.10.8+zorin2/app/core/gimplayer-new.c gimp-2.10.14+om/app/core/gimplayer-new.c --- gimp-2.10.8+zorin2/app/core/gimplayer-new.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplayer-new.c 2019-10-26 18:49:18.000000000 +0000 @@ -130,7 +130,8 @@ GimpLayerMode mode, GimpColorProfile *buffer_profile) { - GimpLayer *layer; + GimpLayer *layer; + const GeglRectangle *extent; g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL); @@ -138,15 +139,19 @@ g_return_val_if_fail (buffer_profile == NULL || GIMP_IS_COLOR_PROFILE (buffer_profile), NULL); + extent = gegl_buffer_get_extent (buffer); + /* do *not* use the buffer's format because this function gets * buffers of any format passed, and converts them */ layer = gimp_layer_new (dest_image, - gegl_buffer_get_width (buffer), - gegl_buffer_get_height (buffer), + extent->width, extent->height, format, name, opacity, mode); + if (extent->x != 0 || extent->y != 0) + gimp_item_translate (GIMP_ITEM (layer), extent->x, extent->y, FALSE); + gimp_layer_new_convert_buffer (layer, buffer, buffer_profile, NULL); return layer; diff -Nru gimp-2.10.8+zorin2/app/core/gimplayerstack.c gimp-2.10.14+om/app/core/gimplayerstack.c --- gimp-2.10.8+zorin2/app/core/gimplayerstack.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplayerstack.c 2019-10-26 18:49:18.000000000 +0000 @@ -228,15 +228,16 @@ if (gimp_filter_get_active (GIMP_FILTER (item))) { - gint offset_x; - gint offset_y; + GeglRectangle bounding_box; - gimp_item_get_offset (item, &offset_x, &offset_y); + bounding_box = gimp_drawable_get_bounding_box (GIMP_DRAWABLE (item)); + + bounding_box.x += gimp_item_get_offset_x (item); + bounding_box.y += gimp_item_get_offset_y (item); gimp_drawable_stack_update (GIMP_DRAWABLE_STACK (stack), - offset_x, offset_y, - gimp_item_get_width (item), - gimp_item_get_height (item)); + bounding_box.x, bounding_box.y, + bounding_box.width, bounding_box.height); } } } diff -Nru gimp-2.10.8+zorin2/app/core/gimplineart.c gimp-2.10.14+om/app/core/gimplineart.c --- gimp-2.10.8+zorin2/app/core/gimplineart.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplineart.c 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,2942 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Copyright (C) 2017 Sébastien Fourey & David Tchumperlé + * Copyright (C) 2018 Jehan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpmath/gimpmath.h" + +#include "core-types.h" + +#include "gegl/gimp-gegl-loops.h" +#include "gegl/gimp-gegl-utils.h" + +#include "gimp-parallel.h" +#include "gimp-priorities.h" +#include "gimp-utils.h" /* GIMP_TIMER */ +#include "gimpasync.h" +#include "gimpcancelable.h" +#include "gimpdrawable.h" +#include "gimpimage.h" +#include "gimplineart.h" +#include "gimpmarshal.h" +#include "gimppickable.h" +#include "gimpprojection.h" +#include "gimpviewable.h" +#include "gimpwaitable.h" + +#include "gimp-intl.h" + +enum +{ + COMPUTING_START, + COMPUTING_END, + LAST_SIGNAL, +}; + +enum +{ + PROP_0, + PROP_SELECT_TRANSPARENT, + PROP_MAX_GROW, + PROP_THRESHOLD, + PROP_SPLINE_MAX_LEN, + PROP_SEGMENT_MAX_LEN, +}; + +typedef struct _GimpLineArtPrivate GimpLineArtPrivate; + +struct _GimpLineArtPrivate +{ + gboolean frozen; + gboolean compute_after_thaw; + + GimpAsync *async; + + gint idle_id; + + GimpPickable *input; + GeglBuffer *closed; + gfloat *distmap; + + /* Used in the closing step. */ + gboolean select_transparent; + gdouble threshold; + gint spline_max_len; + gint segment_max_len; + gboolean max_len_bound; + + /* Used in the grow step. */ + gint max_grow; +}; + +typedef struct +{ + GeglBuffer *buffer; + + gboolean select_transparent; + gdouble threshold; + gint spline_max_len; + gint segment_max_len; +} LineArtData; + +typedef struct +{ + GeglBuffer *closed; + gfloat *distmap; +} LineArtResult; + +static int DeltaX[4] = {+1, -1, 0, 0}; +static int DeltaY[4] = {0, 0, +1, -1}; + +static const GimpVector2 Direction2Normal[4] = +{ + { 1.0f, 0.0f }, + { -1.0f, 0.0f }, + { 0.0f, 1.0f }, + { 0.0f, -1.0f } +}; + +typedef enum _Direction +{ + XPlusDirection = 0, + XMinusDirection = 1, + YPlusDirection = 2, + YMinusDirection = 3 +} Direction; + +typedef GimpVector2 Pixel; + +typedef struct _SplineCandidate +{ + Pixel p1; + Pixel p2; + float quality; +} SplineCandidate; + +typedef struct _Edgel +{ + gint x, y; + Direction direction; + + gfloat x_normal; + gfloat y_normal; + gfloat curvature; + guint next, previous; +} Edgel; + + +static void gimp_line_art_finalize (GObject *object); +static void gimp_line_art_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_line_art_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +/* Functions for asynchronous computation. */ + +static void gimp_line_art_compute (GimpLineArt *line_art); +static void gimp_line_art_compute_cb (GimpAsync *async, + GimpLineArt *line_art); + +static GimpAsync * gimp_line_art_prepare_async (GimpLineArt *line_art, + gint priority); +static void gimp_line_art_prepare_async_func (GimpAsync *async, + LineArtData *data); +static LineArtData * line_art_data_new (GeglBuffer *buffer, + GimpLineArt *line_art); +static void line_art_data_free (LineArtData *data); +static LineArtResult * line_art_result_new (GeglBuffer *line_art, + gfloat *distmap); +static void line_art_result_free (LineArtResult *result); + +static gboolean gimp_line_art_idle (GimpLineArt *line_art); +static void gimp_line_art_input_invalidate_preview (GimpViewable *viewable, + GimpLineArt *line_art); + + +/* All actual computation functions. */ + +static GeglBuffer * gimp_line_art_close (GeglBuffer *buffer, + gboolean select_transparent, + gdouble stroke_threshold, + gint spline_max_length, + gint segment_max_length, + gint minimal_lineart_area, + gint normal_estimate_mask_size, + gfloat end_point_rate, + gfloat spline_max_angle, + gint end_point_connectivity, + gfloat spline_roundness, + gboolean allow_self_intersections, + gint created_regions_significant_area, + gint created_regions_minimum_area, + gboolean small_segments_from_spline_sources, + gfloat **lineart_distmap, + GimpAsync *async); + +static void gimp_lineart_denoise (GeglBuffer *buffer, + int size, + GimpAsync *async); +static void gimp_lineart_compute_normals_curvatures (GeglBuffer *mask, + gfloat *normals, + gfloat *curvatures, + gfloat *smoothed_curvatures, + int normal_estimate_mask_size, + GimpAsync *async); +static gfloat * gimp_lineart_get_smooth_curvatures (GArray *edgelset, + GimpAsync *async); +static GArray * gimp_lineart_curvature_extremums (gfloat *curvatures, + gfloat *smoothed_curvatures, + gint curvatures_width, + gint curvatures_height, + GimpAsync *async); +static gint gimp_spline_candidate_cmp (const SplineCandidate *a, + const SplineCandidate *b, + gpointer user_data); +static GList * gimp_lineart_find_spline_candidates (GArray *max_positions, + gfloat *normals, + gint width, + gint distance_threshold, + gfloat max_angle_deg, + GimpAsync *async); + +static GArray * gimp_lineart_discrete_spline (Pixel p0, + GimpVector2 n0, + Pixel p1, + GimpVector2 n1); + +static gint gimp_number_of_transitions (GArray *pixels, + GeglBuffer *buffer); +static gboolean gimp_line_art_allow_closure (GeglBuffer *mask, + GArray *pixels, + GList **fill_pixels, + int significant_size, + int minimum_size); +static GArray * gimp_lineart_line_segment_until_hit (const GeglBuffer *buffer, + Pixel start, + GimpVector2 direction, + int size); +static gfloat * gimp_lineart_estimate_strokes_radii (GeglBuffer *mask, + GimpAsync *async); +static void gimp_line_art_simple_fill (GeglBuffer *buffer, + gint x, + gint y); + +/* Some callback-type functions. */ + +static guint visited_hash_fun (Pixel *key); +static gboolean visited_equal_fun (Pixel *e1, + Pixel *e2); + +static inline gboolean border_in_direction (GeglBuffer *mask, + Pixel p, + int direction); +static inline GimpVector2 pair2normal (Pixel p, + gfloat *normals, + gint width); + +/* Edgel */ + +static Edgel * gimp_edgel_new (int x, + int y, + Direction direction); +static void gimp_edgel_init (Edgel *edgel); +static void gimp_edgel_clear (Edgel **edgel); +static int gimp_edgel_cmp (const Edgel *e1, + const Edgel *e2); +static guint edgel2index_hash_fun (Edgel *key); +static gboolean edgel2index_equal_fun (Edgel *e1, + Edgel *e2); + +static glong gimp_edgel_track_mark (GeglBuffer *mask, + Edgel edgel, + long size_limit); +static glong gimp_edgel_region_area (const GeglBuffer *mask, + Edgel start_edgel); + +/* Edgel set */ + +static GArray * gimp_edgelset_new (GeglBuffer *buffer, + GimpAsync *async); +static void gimp_edgelset_add (GArray *set, + int x, + int y, + Direction direction, + GHashTable *edgel2index); +static void gimp_edgelset_init_normals (GArray *set); +static void gimp_edgelset_smooth_normals (GArray *set, + int mask_size, + GimpAsync *async); +static void gimp_edgelset_compute_curvature (GArray *set, + GimpAsync *async); + +static void gimp_edgelset_build_graph (GArray *set, + GeglBuffer *buffer, + GHashTable *edgel2index, + GimpAsync *async); +static void gimp_edgelset_next8 (const GeglBuffer *buffer, + Edgel *it, + Edgel *n); + +G_DEFINE_TYPE_WITH_CODE (GimpLineArt, gimp_line_art, GIMP_TYPE_OBJECT, + G_ADD_PRIVATE (GimpLineArt)) + +static guint gimp_line_art_signals[LAST_SIGNAL] = { 0 }; + +static void +gimp_line_art_class_init (GimpLineArtClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + gimp_line_art_signals[COMPUTING_START] = + g_signal_new ("computing-start", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpLineArtClass, computing_start), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + gimp_line_art_signals[COMPUTING_END] = + g_signal_new ("computing-end", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpLineArtClass, computing_end), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + object_class->finalize = gimp_line_art_finalize; + object_class->set_property = gimp_line_art_set_property; + object_class->get_property = gimp_line_art_get_property; + + g_object_class_install_property (object_class, PROP_SELECT_TRANSPARENT, + g_param_spec_boolean ("select-transparent", + _("Select transparent pixels instead of gray ones"), + _("Select transparent pixels instead of gray ones"), + TRUE, + G_PARAM_CONSTRUCT | GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_THRESHOLD, + g_param_spec_double ("threshold", + _("Line art detection threshold"), + _("Threshold to detect contour (higher values will include more pixels)"), + 0.0, 1.0, 0.92, + G_PARAM_CONSTRUCT | GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_MAX_GROW, + g_param_spec_int ("max-grow", + _("Maximum growing size"), + _("Maximum number of pixels grown under the line art"), + 1, 100, 3, + G_PARAM_CONSTRUCT | GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SPLINE_MAX_LEN, + g_param_spec_int ("spline-max-length", + _("Maximum curved closing length"), + _("Maximum curved length (in pixels) to close the line art"), + 0, 1000, 100, + G_PARAM_CONSTRUCT | GIMP_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_SEGMENT_MAX_LEN, + g_param_spec_int ("segment-max-length", + _("Maximum straight closing length"), + _("Maximum straight length (in pixels) to close the line art"), + 0, 1000, 100, + G_PARAM_CONSTRUCT | GIMP_PARAM_READWRITE)); +} + +static void +gimp_line_art_init (GimpLineArt *line_art) +{ + line_art->priv = gimp_line_art_get_instance_private (line_art); +} + +static void +gimp_line_art_finalize (GObject *object) +{ + GimpLineArt *line_art = GIMP_LINE_ART (object); + + line_art->priv->frozen = FALSE; + + gimp_line_art_set_input (line_art, NULL); +} + +static void +gimp_line_art_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpLineArt *line_art = GIMP_LINE_ART (object); + + switch (property_id) + { + case PROP_SELECT_TRANSPARENT: + if (line_art->priv->select_transparent != g_value_get_boolean (value)) + { + line_art->priv->select_transparent = g_value_get_boolean (value); + gimp_line_art_compute (line_art); + } + break; + case PROP_MAX_GROW: + line_art->priv->max_grow = g_value_get_int (value); + break; + case PROP_THRESHOLD: + if (line_art->priv->threshold != g_value_get_double (value)) + { + line_art->priv->threshold = g_value_get_double (value); + gimp_line_art_compute (line_art); + } + break; + case PROP_SPLINE_MAX_LEN: + if (line_art->priv->spline_max_len != g_value_get_int (value)) + { + line_art->priv->spline_max_len = g_value_get_int (value); + if (line_art->priv->max_len_bound) + line_art->priv->segment_max_len = line_art->priv->spline_max_len; + gimp_line_art_compute (line_art); + } + break; + case PROP_SEGMENT_MAX_LEN: + if (line_art->priv->segment_max_len != g_value_get_int (value)) + { + line_art->priv->segment_max_len = g_value_get_int (value); + if (line_art->priv->max_len_bound) + line_art->priv->spline_max_len = line_art->priv->segment_max_len; + gimp_line_art_compute (line_art); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_line_art_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpLineArt *line_art = GIMP_LINE_ART (object); + + switch (property_id) + { + case PROP_SELECT_TRANSPARENT: + g_value_set_boolean (value, line_art->priv->select_transparent); + break; + case PROP_MAX_GROW: + g_value_set_int (value, line_art->priv->max_grow); + break; + case PROP_THRESHOLD: + g_value_set_double (value, line_art->priv->threshold); + break; + case PROP_SPLINE_MAX_LEN: + g_value_set_int (value, line_art->priv->spline_max_len); + break; + case PROP_SEGMENT_MAX_LEN: + g_value_set_int (value, line_art->priv->segment_max_len); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* Public functions */ + +GimpLineArt * +gimp_line_art_new (void) +{ + return g_object_new (GIMP_TYPE_LINE_ART, + NULL); +} + +void +gimp_line_art_bind_gap_length (GimpLineArt *line_art, + gboolean bound) +{ + line_art->priv->max_len_bound = bound; +} + +void +gimp_line_art_set_input (GimpLineArt *line_art, + GimpPickable *pickable) +{ + g_return_if_fail (pickable == NULL || GIMP_IS_VIEWABLE (pickable)); + + if (pickable != line_art->priv->input) + { + if (line_art->priv->input) + g_signal_handlers_disconnect_by_data (line_art->priv->input, line_art); + + line_art->priv->input = pickable; + + gimp_line_art_compute (line_art); + + if (pickable) + { + g_signal_connect (pickable, "invalidate-preview", + G_CALLBACK (gimp_line_art_input_invalidate_preview), + line_art); + } + } +} + +GimpPickable * +gimp_line_art_get_input (GimpLineArt *line_art) +{ + return line_art->priv->input; +} + +void +gimp_line_art_freeze (GimpLineArt *line_art) +{ + g_return_if_fail (! line_art->priv->frozen); + + line_art->priv->frozen = TRUE; + line_art->priv->compute_after_thaw = FALSE; +} + +void +gimp_line_art_thaw (GimpLineArt *line_art) +{ + g_return_if_fail (line_art->priv->frozen); + + line_art->priv->frozen = FALSE; + if (line_art->priv->compute_after_thaw) + { + gimp_line_art_compute (line_art); + line_art->priv->compute_after_thaw = FALSE; + } +} + +gboolean +gimp_line_art_is_frozen (GimpLineArt *line_art) +{ + return line_art->priv->frozen; +} + +GeglBuffer * +gimp_line_art_get (GimpLineArt *line_art, + gfloat **distmap) +{ + g_return_val_if_fail (line_art->priv->input, NULL); + + if (line_art->priv->async) + { + gimp_waitable_wait (GIMP_WAITABLE (line_art->priv->async)); + } + else if (! line_art->priv->closed) + { + gimp_line_art_compute (line_art); + if (line_art->priv->async) + gimp_waitable_wait (GIMP_WAITABLE (line_art->priv->async)); + } + + g_return_val_if_fail (line_art->priv->closed, NULL); + + if (distmap) + *distmap = line_art->priv->distmap; + + return line_art->priv->closed; +} + +/* Functions for asynchronous computation. */ + +static void +gimp_line_art_compute (GimpLineArt *line_art) +{ + if (line_art->priv->frozen) + { + line_art->priv->compute_after_thaw = TRUE; + return; + } + + if (line_art->priv->async) + { + /* we cancel the async, but don't wait for it to finish, since + * it might take a while to respond. instead gimp_line_art_compute_cb() + * bails if the async has been canceled, to avoid accessing the line art. + */ + g_signal_emit (line_art, gimp_line_art_signals[COMPUTING_END], 0); + gimp_cancelable_cancel (GIMP_CANCELABLE (line_art->priv->async)); + g_clear_object (&line_art->priv->async); + } + + if (line_art->priv->idle_id) + { + g_source_remove (line_art->priv->idle_id); + line_art->priv->idle_id = 0; + } + + g_clear_object (&line_art->priv->closed); + g_clear_pointer (&line_art->priv->distmap, g_free); + + if (line_art->priv->input) + { + /* gimp_line_art_prepare_async() will flush the pickable, which + * may trigger this signal handler, and will leak a line art (as + * line_art->priv->async has not been set yet). + */ + g_signal_handlers_block_by_func ( + line_art->priv->input, + G_CALLBACK (gimp_line_art_input_invalidate_preview), + line_art); + line_art->priv->async = gimp_line_art_prepare_async (line_art, +1); + g_signal_emit (line_art, gimp_line_art_signals[COMPUTING_START], 0); + g_signal_handlers_unblock_by_func ( + line_art->priv->input, + G_CALLBACK (gimp_line_art_input_invalidate_preview), + line_art); + + gimp_async_add_callback_for_object (line_art->priv->async, + (GimpAsyncCallback) gimp_line_art_compute_cb, + line_art, line_art); + } +} + +static void +gimp_line_art_compute_cb (GimpAsync *async, + GimpLineArt *line_art) +{ + if (gimp_async_is_canceled (async)) + return; + + if (gimp_async_is_finished (async)) + { + LineArtResult *result; + + result = gimp_async_get_result (async); + + line_art->priv->closed = g_object_ref (result->closed); + line_art->priv->distmap = result->distmap; + result->distmap = NULL; + g_signal_emit (line_art, gimp_line_art_signals[COMPUTING_END], 0); + } + + g_clear_object (&line_art->priv->async); +} + +static GimpAsync * +gimp_line_art_prepare_async (GimpLineArt *line_art, + gint priority) +{ + GeglBuffer *buffer; + GimpAsync *async; + LineArtData *data; + + g_return_val_if_fail (GIMP_IS_PICKABLE (line_art->priv->input), NULL); + + gimp_pickable_flush (line_art->priv->input); + + buffer = gimp_gegl_buffer_dup ( + gimp_pickable_get_buffer (line_art->priv->input)); + + data = line_art_data_new (buffer, line_art); + + g_object_unref (buffer); + + async = gimp_parallel_run_async_full ( + priority, + (GimpParallelRunAsyncFunc) gimp_line_art_prepare_async_func, + data, (GDestroyNotify) line_art_data_free); + + return async; +} + +static void +gimp_line_art_prepare_async_func (GimpAsync *async, + LineArtData *data) +{ + GeglBuffer *closed = NULL; + gfloat *distmap = NULL; + gboolean has_alpha; + gboolean select_transparent = FALSE; + + has_alpha = babl_format_has_alpha (gegl_buffer_get_format (data->buffer)); + + if (has_alpha) + { + if (data->select_transparent) + { + /* don't select transparent regions if there are no fully + * transparent pixels. + */ + GeglBufferIterator *gi; + + gi = gegl_buffer_iterator_new (data->buffer, NULL, 0, + babl_format ("A u8"), + GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 3); + while (gegl_buffer_iterator_next (gi)) + { + guint8 *p = (guint8*) gi->items[0].data; + gint k; + + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + line_art_data_free (data); + + return; + } + + for (k = 0; k < gi->length; k++) + { + if (! *p) + { + select_transparent = TRUE; + break; + } + p++; + } + if (select_transparent) + break; + } + if (select_transparent) + gegl_buffer_iterator_stop (gi); + } + } + + /* For smart selection, we generate a binarized image with close + * regions, then run a composite selection with no threshold on + * this intermediate buffer. + */ + GIMP_TIMER_START(); + + closed = gimp_line_art_close (data->buffer, + select_transparent, + data->threshold, + data->spline_max_len, + data->segment_max_len, + /*minimal_lineart_area,*/ + 5, + /*normal_estimate_mask_size,*/ + 5, + /*end_point_rate,*/ + 0.85, + /*spline_max_angle,*/ + 90.0, + /*end_point_connectivity,*/ + 2, + /*spline_roundness,*/ + 1.0, + /*allow_self_intersections,*/ + TRUE, + /*created_regions_significant_area,*/ + 4, + /*created_regions_minimum_area,*/ + 100, + /*small_segments_from_spline_sources,*/ + TRUE, + &distmap, + async); + + GIMP_TIMER_END("close line-art"); + + if (! gimp_async_is_stopped (async)) + { + gimp_async_finish_full (async, + line_art_result_new (closed, distmap), + (GDestroyNotify) line_art_result_free); + } + + line_art_data_free (data); +} + +static LineArtData * +line_art_data_new (GeglBuffer *buffer, + GimpLineArt *line_art) +{ + LineArtData *data = g_slice_new (LineArtData); + + data->buffer = g_object_ref (buffer); + data->select_transparent = line_art->priv->select_transparent; + data->threshold = line_art->priv->threshold; + data->spline_max_len = line_art->priv->spline_max_len; + data->segment_max_len = line_art->priv->segment_max_len; + + return data; +} + +static void +line_art_data_free (LineArtData *data) +{ + g_object_unref (data->buffer); + + g_slice_free (LineArtData, data); +} + +static LineArtResult * +line_art_result_new (GeglBuffer *closed, + gfloat *distmap) +{ + LineArtResult *data; + + data = g_slice_new (LineArtResult); + data->closed = closed; + data->distmap = distmap; + + return data; +} + +static void +line_art_result_free (LineArtResult *data) +{ + g_object_unref (data->closed); + g_clear_pointer (&data->distmap, g_free); + + g_slice_free (LineArtResult, data); +} + +static gboolean +gimp_line_art_idle (GimpLineArt *line_art) +{ + line_art->priv->idle_id = 0; + + gimp_line_art_compute (line_art); + + return G_SOURCE_REMOVE; +} + +static void +gimp_line_art_input_invalidate_preview (GimpViewable *viewable, + GimpLineArt *line_art) +{ + if (! line_art->priv->idle_id) + { + line_art->priv->idle_id = g_idle_add_full ( + GIMP_PRIORITY_VIEWABLE_IDLE, + (GSourceFunc) gimp_line_art_idle, + line_art, NULL); + } +} + +/* All actual computation functions. */ + +/** + * gimp_line_art_close: + * @buffer: the input #GeglBuffer. + * @select_transparent: whether we binarize the alpha channel or the + * luminosity. + * @stroke_threshold: [0-1] threshold value for detecting stroke pixels + * (higher values will detect more stroke pixels). + * @spline_max_length: the maximum length for creating splines between + * end points. + * @segment_max_length: the maximum length for creating segments + * between end points. Unlike splines, segments + * are straight lines. + * @minimal_lineart_area: the minimum size in number pixels for area to + * be considered as line art. + * @normal_estimate_mask_size: + * @end_point_rate: threshold to estimate if a curvature is an end-point + * in [0-1] range value. + * @spline_max_angle: the maximum angle between end point normals for + * creating splines between them. + * @end_point_connectivity: + * @spline_roundness: + * @allow_self_intersections: whether to allow created splines and + * segments to intersect. + * @created_regions_significant_area: + * @created_regions_minimum_area: + * @small_segments_from_spline_sources: + * @closed_distmap: a distance map of the closed line art pixels. + * @async: the #GimpAsync associated with the computation + * + * Creates a binarized version of the strokes of @buffer, detected either + * with luminosity (light means background) or alpha values depending on + * @select_transparent. This binary version of the strokes will have closed + * regions allowing adequate selection of "nearly closed regions". + * This algorithm is meant for digital painting (and in particular on the + * sketch-only step), and therefore will likely produce unexpected results on + * other types of input. + * + * The algorithm is the first step from the research paper "A Fast and + * Efficient Semi-guided Algorithm for Flat Coloring Line-arts", by Sébastian + * Fourey, David Tschumperlé, David Revoy. + * https://hal.archives-ouvertes.fr/hal-01891876 + * + * Returns: a new #GeglBuffer of format "Y u8" representing the + * binarized @line_art. If @lineart_distmap is not #NULL, a + * newly allocated float buffer is returned, which can be used + * for overflowing created masks later. + */ +static GeglBuffer * +gimp_line_art_close (GeglBuffer *buffer, + gboolean select_transparent, + gdouble stroke_threshold, + gint spline_max_length, + gint segment_max_length, + gint minimal_lineart_area, + gint normal_estimate_mask_size, + gfloat end_point_rate, + gfloat spline_max_angle, + gint end_point_connectivity, + gfloat spline_roundness, + gboolean allow_self_intersections, + gint created_regions_significant_area, + gint created_regions_minimum_area, + gboolean small_segments_from_spline_sources, + gfloat **closed_distmap, + GimpAsync *async) +{ + const Babl *gray_format; + GeglBufferIterator *gi; + GeglBuffer *closed = NULL; + GeglBuffer *strokes = NULL; + guchar max_value = 0; + gint width = gegl_buffer_get_width (buffer); + gint height = gegl_buffer_get_height (buffer); + gint i; + + if (select_transparent) + /* Keep alpha channel as gray levels */ + gray_format = babl_format ("A u8"); + else + /* Keep luminance */ + gray_format = babl_format ("Y' u8"); + + /* Transform the line art from any format to gray. */ + strokes = gegl_buffer_new (gegl_buffer_get_extent (buffer), + gray_format); + gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, strokes, NULL); + gegl_buffer_set_format (strokes, babl_format ("Y' u8")); + + if (! select_transparent) + { + /* Compute the biggest value */ + gi = gegl_buffer_iterator_new (strokes, NULL, 0, NULL, + GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1); + while (gegl_buffer_iterator_next (gi)) + { + guchar *data = (guchar*) gi->items[0].data; + gint k; + + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + goto end1; + } + + for (k = 0; k < gi->length; k++) + { + if (*data > max_value) + max_value = *data; + data++; + } + } + } + + /* Make the image binary: 1 is stroke, 0 background */ + gi = gegl_buffer_iterator_new (strokes, NULL, 0, NULL, + GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 1); + while (gegl_buffer_iterator_next (gi)) + { + guchar *data = (guchar*) gi->items[0].data; + gint k; + + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + goto end1; + } + + for (k = 0; k < gi->length; k++) + { + if (! select_transparent) + /* Negate the value. */ + *data = max_value - *data; + /* Apply a threshold. */ + if (*data > (guchar) (255.0f * (1.0f - stroke_threshold))) + *data = 1; + else + *data = 0; + data++; + } + } + + /* Denoise (remove small connected components) */ + gimp_lineart_denoise (strokes, minimal_lineart_area, async); + if (gimp_async_is_stopped (async)) + goto end1; + + closed = g_object_ref (strokes); + + if (spline_max_length > 0 || segment_max_length > 0) + { + GArray *keypoints = NULL; + GHashTable *visited = NULL; + gfloat *radii = NULL; + gfloat *normals = NULL; + gfloat *curvatures = NULL; + gfloat *smoothed_curvatures = NULL; + gfloat threshold; + gfloat clamped_threshold; + GList *fill_pixels = NULL; + GList *iter; + + normals = g_new0 (gfloat, width * height * 2); + curvatures = g_new0 (gfloat, width * height); + smoothed_curvatures = g_new0 (gfloat, width * height); + + /* Estimate normals & curvature */ + gimp_lineart_compute_normals_curvatures (strokes, normals, curvatures, + smoothed_curvatures, + normal_estimate_mask_size, + async); + if (gimp_async_is_stopped (async)) + goto end2; + + radii = gimp_lineart_estimate_strokes_radii (strokes, async); + if (gimp_async_is_stopped (async)) + goto end2; + threshold = 1.0f - end_point_rate; + clamped_threshold = MAX (0.25f, threshold); + for (i = 0; i < width; i++) + { + gint j; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end2; + } + + for (j = 0; j < height; j++) + { + if (smoothed_curvatures[i + j * width] >= (threshold / MAX (1.0f, radii[i + j * width])) || + curvatures[i + j * width] >= clamped_threshold) + curvatures[i + j * width] = 1.0; + else + curvatures[i + j * width] = 0.0; + } + } + g_clear_pointer (&radii, g_free); + + keypoints = gimp_lineart_curvature_extremums (curvatures, smoothed_curvatures, + width, height, async); + if (gimp_async_is_stopped (async)) + goto end2; + + visited = g_hash_table_new_full ((GHashFunc) visited_hash_fun, + (GEqualFunc) visited_equal_fun, + (GDestroyNotify) g_free, NULL); + + if (spline_max_length > 0) + { + GList *candidates; + SplineCandidate *candidate; + + candidates = gimp_lineart_find_spline_candidates (keypoints, normals, width, + spline_max_length, + spline_max_angle, + async); + if (gimp_async_is_stopped (async)) + goto end3; + + g_object_unref (closed); + closed = gimp_gegl_buffer_dup (strokes); + + /* Draw splines */ + while (candidates) + { + Pixel *p1; + Pixel *p2; + gboolean inserted = FALSE; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end3; + } + + p1 = g_new (Pixel, 1); + p2 = g_new (Pixel, 1); + + candidate = (SplineCandidate *) candidates->data; + p1->x = candidate->p1.x; + p1->y = candidate->p1.y; + p2->x = candidate->p2.x; + p2->y = candidate->p2.y; + + g_free (candidate); + candidates = g_list_delete_link (candidates, candidates); + + if ((! g_hash_table_contains (visited, p1) || + GPOINTER_TO_INT (g_hash_table_lookup (visited, p1)) < end_point_connectivity) && + (! g_hash_table_contains (visited, p2) || + GPOINTER_TO_INT (g_hash_table_lookup (visited, p2)) < end_point_connectivity)) + { + GArray *discrete_curve; + GimpVector2 vect1 = pair2normal (*p1, normals, width); + GimpVector2 vect2 = pair2normal (*p2, normals, width); + gfloat distance = gimp_vector2_length_val (gimp_vector2_sub_val (*p1, *p2)); + gint transitions; + + gimp_vector2_mul (&vect1, distance); + gimp_vector2_mul (&vect1, spline_roundness); + gimp_vector2_mul (&vect2, distance); + gimp_vector2_mul (&vect2, spline_roundness); + + discrete_curve = gimp_lineart_discrete_spline (*p1, vect1, *p2, vect2); + + transitions = allow_self_intersections ? + gimp_number_of_transitions (discrete_curve, strokes) : + gimp_number_of_transitions (discrete_curve, closed); + + if (transitions == 2 && + gimp_line_art_allow_closure (closed, discrete_curve, + &fill_pixels, + created_regions_significant_area, + created_regions_minimum_area - 1)) + { + for (i = 0; i < discrete_curve->len; i++) + { + Pixel p = g_array_index (discrete_curve, Pixel, i); + + if (p.x >= 0 && p.x < gegl_buffer_get_width (closed) && + p.y >= 0 && p.y < gegl_buffer_get_height (closed)) + { + guchar val = 2; + + gegl_buffer_set (closed, GEGL_RECTANGLE ((gint) p.x, (gint) p.y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + } + g_hash_table_replace (visited, p1, + GINT_TO_POINTER (GPOINTER_TO_INT (g_hash_table_lookup (visited, p1)) + 1)); + g_hash_table_replace (visited, p2, + GINT_TO_POINTER (GPOINTER_TO_INT (g_hash_table_lookup (visited, p2)) + 1)); + inserted = TRUE; + } + g_array_free (discrete_curve, TRUE); + } + if (! inserted) + { + g_free (p1); + g_free (p2); + } + } + + end3: + g_list_free_full (candidates, g_free); + + if (gimp_async_is_stopped (async)) + goto end2; + } + + g_clear_object (&strokes); + + /* Draw straight line segments */ + if (segment_max_length > 0) + { + Pixel *point; + + point = (Pixel *) keypoints->data; + for (i = 0; i < keypoints->len; i++) + { + Pixel *p; + gboolean inserted = FALSE; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end2; + } + + p = g_new (Pixel, 1); + *p = *point; + + if (! g_hash_table_contains (visited, p) || + (small_segments_from_spline_sources && + GPOINTER_TO_INT (g_hash_table_lookup (visited, p)) < end_point_connectivity)) + { + GArray *segment = gimp_lineart_line_segment_until_hit (closed, *point, + pair2normal (*point, normals, width), + segment_max_length); + + if (segment->len && + gimp_line_art_allow_closure (closed, segment, &fill_pixels, + created_regions_significant_area, + created_regions_minimum_area - 1)) + { + gint j; + + for (j = 0; j < segment->len; j++) + { + Pixel p2 = g_array_index (segment, Pixel, j); + guchar val = 2; + + gegl_buffer_set (closed, GEGL_RECTANGLE ((gint) p2.x, (gint) p2.y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + g_hash_table_replace (visited, p, + GINT_TO_POINTER (GPOINTER_TO_INT (g_hash_table_lookup (visited, p)) + 1)); + inserted = TRUE; + } + g_array_free (segment, TRUE); + } + if (! inserted) + g_free (p); + point++; + } + } + + for (iter = fill_pixels; iter; iter = iter->next) + { + Pixel *p = iter->data; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end2; + } + + /* XXX A best approach would be to generalize + * gimp_drawable_bucket_fill() to work on any buffer (the code + * is already mostly there) rather than reimplementing a naive + * bucket fill. + * This is mostly a quick'n dirty first implementation which I + * will improve later. + */ + gimp_line_art_simple_fill (closed, (gint) p->x, (gint) p->y); + } + + end2: + g_list_free_full (fill_pixels, g_free); + g_free (normals); + g_free (curvatures); + g_free (smoothed_curvatures); + g_clear_pointer (&radii, g_free); + if (keypoints) + g_array_free (keypoints, TRUE); + g_clear_pointer (&visited, g_hash_table_destroy); + + if (gimp_async_is_stopped (async)) + goto end1; + } + else + { + g_clear_object (&strokes); + } + + if (closed_distmap) + { + GeglNode *graph; + GeglNode *input; + GeglNode *op; + + /* Flooding needs a distance map for closed line art. */ + *closed_distmap = g_new (gfloat, width * height); + + graph = gegl_node_new (); + input = gegl_node_new_child (graph, + "operation", "gegl:buffer-source", + "buffer", closed, + NULL); + op = gegl_node_new_child (graph, + "operation", "gegl:distance-transform", + "metric", GEGL_DISTANCE_METRIC_EUCLIDEAN, + "normalize", FALSE, + NULL); + gegl_node_connect_to (input, "output", + op, "input"); + gegl_node_blit (op, 1.0, gegl_buffer_get_extent (closed), + NULL, *closed_distmap, + GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_DEFAULT); + g_object_unref (graph); + } + + end1: + g_clear_object (&strokes); + + if (gimp_async_is_stopped (async)) + g_clear_object (&closed); + + return closed; +} + +static void +gimp_lineart_denoise (GeglBuffer *buffer, + int minimum_area, + GimpAsync *async) +{ + /* Keep connected regions with significant area. */ + GArray *region; + GQueue *q = g_queue_new (); + gint width = gegl_buffer_get_width (buffer); + gint height = gegl_buffer_get_height (buffer); + gboolean *visited = g_new0 (gboolean, width * height); + gint x, y; + + region = g_array_sized_new (TRUE, TRUE, sizeof (Pixel *), minimum_area); + + for (y = 0; y < height; ++y) + for (x = 0; x < width; ++x) + { + guchar has_stroke; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + gegl_buffer_sample (buffer, x, y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[x + y * width]) + { + Pixel *p = g_new (Pixel, 1); + gint regionSize = 0; + + p->x = x; + p->y = y; + + g_queue_push_tail (q, p); + visited[x + y * width] = TRUE; + + while (! g_queue_is_empty (q)) + { + Pixel *p; + gint p2x; + gint p2y; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + p = (Pixel *) g_queue_pop_head (q); + + p2x = p->x + 1; + p2y = p->y; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x +p2y * width] = TRUE; + } + } + p2x = p->x - 1; + p2y = p->y; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x + 1; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x - 1; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x - 1; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + p2x = p->x + 1; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && p2y >= 0 && p2y < height) + { + gegl_buffer_sample (buffer, p2x, p2y, NULL, &has_stroke, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (has_stroke && ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + } + + ++regionSize; + if (regionSize < minimum_area) + g_array_append_val (region, *p); + g_free (p); + } + if (regionSize < minimum_area) + { + Pixel *pixel = (Pixel *) region->data; + gint i = 0; + + for (; i < region->len; i++) + { + guchar val = 0; + gegl_buffer_set (buffer, GEGL_RECTANGLE (pixel->x, pixel->y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + pixel++; + } + } + g_array_remove_range (region, 0, region->len); + } + } + + end: + g_array_free (region, TRUE); + g_queue_free_full (q, g_free); + g_free (visited); +} + +static void +gimp_lineart_compute_normals_curvatures (GeglBuffer *mask, + gfloat *normals, + gfloat *curvatures, + gfloat *smoothed_curvatures, + int normal_estimate_mask_size, + GimpAsync *async) +{ + gfloat *edgels_curvatures = NULL; + gfloat *smoothed_curvature; + GArray *es = NULL; + Edgel **e; + gint width = gegl_buffer_get_width (mask); + + es = gimp_edgelset_new (mask, async); + if (gimp_async_is_stopped (async)) + goto end; + + e = (Edgel **) es->data; + + gimp_edgelset_smooth_normals (es, normal_estimate_mask_size, async); + if (gimp_async_is_stopped (async)) + goto end; + + gimp_edgelset_compute_curvature (es, async); + if (gimp_async_is_stopped (async)) + goto end; + + while (*e) + { + const float curvature = ((*e)->curvature > 0.0f) ? (*e)->curvature : 0.0f; + const float w = MAX (1e-8f, curvature * curvature); + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + normals[((*e)->x + (*e)->y * width) * 2] += w * (*e)->x_normal; + normals[((*e)->x + (*e)->y * width) * 2 + 1] += w * (*e)->y_normal; + curvatures[(*e)->x + (*e)->y * width] = MAX (curvature, + curvatures[(*e)->x + (*e)->y * width]); + e++; + } + for (int y = 0; y < gegl_buffer_get_height (mask); ++y) + { + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + for (int x = 0; x < gegl_buffer_get_width (mask); ++x) + { + const float _angle = atan2f (normals[(x + y * width) * 2 + 1], + normals[(x + y * width) * 2]); + normals[(x + y * width) * 2] = cosf (_angle); + normals[(x + y * width) * 2 + 1] = sinf (_angle); + } + } + + /* Smooth curvatures on edgels, then take maximum on each pixel. */ + edgels_curvatures = gimp_lineart_get_smooth_curvatures (es, async); + if (gimp_async_is_stopped (async)) + goto end; + + smoothed_curvature = edgels_curvatures; + + e = (Edgel **) es->data; + while (*e) + { + gfloat *pixel_curvature = &smoothed_curvatures[(*e)->x + (*e)->y * width]; + + if (*pixel_curvature < *smoothed_curvature) + *pixel_curvature = *smoothed_curvature; + + ++smoothed_curvature; + e++; + } + + end: + g_free (edgels_curvatures); + + if (es) + g_array_free (es, TRUE); +} + +static gfloat * +gimp_lineart_get_smooth_curvatures (GArray *edgelset, + GimpAsync *async) +{ + Edgel **e; + gfloat *smoothed_curvatures = g_new0 (gfloat, edgelset->len); + gfloat weights[9]; + gfloat smoothed_curvature; + gfloat weights_sum; + gint idx = 0; + + weights[0] = 1.0f; + for (int i = 1; i <= 8; ++i) + weights[i] = expf (-(i * i) / 30.0f); + + e = (Edgel **) edgelset->data; + while (*e) + { + Edgel *edgel_before = g_array_index (edgelset, Edgel*, (*e)->previous); + Edgel *edgel_after = g_array_index (edgelset, Edgel*, (*e)->next); + int n = 5; + int i = 1; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + g_free (smoothed_curvatures); + + return NULL; + } + + smoothed_curvature = (*e)->curvature; + weights_sum = weights[0]; + while (n-- && (edgel_after != edgel_before)) + { + smoothed_curvature += weights[i] * edgel_before->curvature; + smoothed_curvature += weights[i] * edgel_after->curvature; + edgel_before = g_array_index (edgelset, Edgel*, edgel_before->previous); + edgel_after = g_array_index (edgelset, Edgel*, edgel_after->next); + weights_sum += 2 * weights[i]; + i++; + } + smoothed_curvature /= weights_sum; + smoothed_curvatures[idx++] = smoothed_curvature; + + e++; + } + + return smoothed_curvatures; +} + +/** + * Keep one pixel per connected component of curvature extremums. + */ +static GArray * +gimp_lineart_curvature_extremums (gfloat *curvatures, + gfloat *smoothed_curvatures, + gint width, + gint height, + GimpAsync *async) +{ + gboolean *visited = g_new0 (gboolean, width * height); + GQueue *q = g_queue_new (); + GArray *max_positions; + + max_positions = g_array_new (FALSE, TRUE, sizeof (Pixel)); + + for (int y = 0; y < height; ++y) + { + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + for (int x = 0; x < width; ++x) + { + if ((curvatures[x + y * width] > 0.0) && ! visited[x + y * width]) + { + Pixel *p = g_new (Pixel, 1); + Pixel max_smoothed_curvature_pixel; + Pixel max_raw_curvature_pixel; + gfloat max_smoothed_curvature; + gfloat max_raw_curvature; + + max_smoothed_curvature_pixel = gimp_vector2_new (-1.0, -1.0); + max_smoothed_curvature = 0.0f; + + max_raw_curvature_pixel = gimp_vector2_new (x, y); + max_raw_curvature = curvatures[x + y * width]; + + p->x = x; + p->y = y; + g_queue_push_tail (q, p); + visited[x + y * width] = TRUE; + + while (! g_queue_is_empty (q)) + { + gfloat sc; + gfloat c; + gint p2x; + gint p2y; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + goto end; + } + + p = (Pixel *) g_queue_pop_head (q); + sc = smoothed_curvatures[(gint) p->x + (gint) p->y * width]; + c = curvatures[(gint) p->x + (gint) p->y * width]; + + curvatures[(gint) p->x + (gint) p->y * width] = 0.0f; + + p2x = (gint) p->x + 1; + p2y = (gint) p->y; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x - 1; + p2y = p->y; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x + 1; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x - 1; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x - 1; + p2y = p->y + 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + p2x = p->x + 1; + p2y = p->y - 1; + if (p2x >= 0 && p2x < width && + p2y >= 0 && p2y < height && + curvatures[p2x + p2y * width] > 0.0 && + ! visited[p2x + p2y * width]) + { + Pixel *p2 = g_new (Pixel, 1); + + p2->x = p2x; + p2->y = p2y; + g_queue_push_tail (q, p2); + visited[p2x + p2y * width] = TRUE; + } + + if (sc > max_smoothed_curvature) + { + max_smoothed_curvature_pixel = *p; + max_smoothed_curvature = sc; + } + if (c > max_raw_curvature) + { + max_raw_curvature_pixel = *p; + max_raw_curvature = c; + } + g_free (p); + } + if (max_smoothed_curvature > 0.0f) + { + curvatures[(gint) max_smoothed_curvature_pixel.x + (gint) max_smoothed_curvature_pixel.y * width] = max_smoothed_curvature; + g_array_append_val (max_positions, max_smoothed_curvature_pixel); + } + else + { + curvatures[(gint) max_raw_curvature_pixel.x + (gint) max_raw_curvature_pixel.y * width] = max_raw_curvature; + g_array_append_val (max_positions, max_raw_curvature_pixel); + } + } + } + } + + end: + g_queue_free_full (q, g_free); + g_free (visited); + + if (gimp_async_is_stopped (async)) + { + g_array_free (max_positions, TRUE); + max_positions = NULL; + } + + return max_positions; +} + +static gint +gimp_spline_candidate_cmp (const SplineCandidate *a, + const SplineCandidate *b, + gpointer user_data) +{ + /* This comparison actually returns the opposite of common comparison + * functions on purpose, as we want the first element on the list to + * be the "bigger". + */ + if (a->quality < b->quality) + return 1; + else if (a->quality > b->quality) + return -1; + else + return 0; +} + +static GList * +gimp_lineart_find_spline_candidates (GArray *max_positions, + gfloat *normals, + gint width, + gint distance_threshold, + gfloat max_angle_deg, + GimpAsync *async) +{ + GList *candidates = NULL; + const float CosMin = cosf (M_PI * (max_angle_deg / 180.0)); + gint i; + + for (i = 0; i < max_positions->len; i++) + { + Pixel p1 = g_array_index (max_positions, Pixel, i); + gint j; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + g_list_free_full (candidates, g_free); + + return NULL; + } + + for (j = i + 1; j < max_positions->len; j++) + { + Pixel p2 = g_array_index (max_positions, Pixel, j); + const float distance = gimp_vector2_length_val (gimp_vector2_sub_val (p1, p2)); + + if (distance <= distance_threshold) + { + GimpVector2 normalP1; + GimpVector2 normalP2; + GimpVector2 p1f; + GimpVector2 p2f; + GimpVector2 p1p2; + float cosN; + float qualityA; + float qualityB; + float qualityC; + float quality; + + normalP1 = gimp_vector2_new (normals[((gint) p1.x + (gint) p1.y * width) * 2], + normals[((gint) p1.x + (gint) p1.y * width) * 2 + 1]); + normalP2 = gimp_vector2_new (normals[((gint) p2.x + (gint) p2.y * width) * 2], + normals[((gint) p2.x + (gint) p2.y * width) * 2 + 1]); + p1f = gimp_vector2_new (p1.x, p1.y); + p2f = gimp_vector2_new (p2.x, p2.y); + p1p2 = gimp_vector2_sub_val (p2f, p1f); + + cosN = gimp_vector2_inner_product_val (normalP1, (gimp_vector2_neg_val (normalP2))); + qualityA = MAX (0.0f, 1 - distance / distance_threshold); + qualityB = MAX (0.0f, + (float) (gimp_vector2_inner_product_val (normalP1, p1p2) - gimp_vector2_inner_product_val (normalP2, p1p2)) / + distance); + qualityC = MAX (0.0f, cosN - CosMin); + quality = qualityA * qualityB * qualityC; + if (quality > 0) + { + SplineCandidate *candidate = g_new (SplineCandidate, 1); + + candidate->p1 = p1; + candidate->p2 = p2; + candidate->quality = quality; + + candidates = g_list_insert_sorted_with_data (candidates, candidate, + (GCompareDataFunc) gimp_spline_candidate_cmp, + NULL); + } + } + } + } + return candidates; +} + +static GArray * +gimp_lineart_discrete_spline (Pixel p0, + GimpVector2 n0, + Pixel p1, + GimpVector2 n1) +{ + GArray *points = g_array_new (FALSE, TRUE, sizeof (Pixel)); + const double a0 = 2 * p0.x - 2 * p1.x + n0.x - n1.x; + const double b0 = -3 * p0.x + 3 * p1.x - 2 * n0.x + n1.x; + const double c0 = n0.x; + const double d0 = p0.x; + const double a1 = 2 * p0.y - 2 * p1.y + n0.y - n1.y; + const double b1 = -3 * p0.y + 3 * p1.y - 2 * n0.y + n1.y; + const double c1 = n0.y; + const double d1 = p0.y; + + double t = 0.0; + const double dtMin = 1.0 / MAX (fabs (p0.x - p1.x), fabs (p0.y - p1.y)); + Pixel point = gimp_vector2_new ((gint) round (d0), (gint) round (d1)); + + g_array_append_val (points, point); + + while (t <= 1.0) + { + const double t2 = t * t; + const double t3 = t * t2; + double dx; + double dy; + Pixel p = gimp_vector2_new ((gint) round (a0 * t3 + b0 * t2 + c0 * t + d0), + (gint) round (a1 * t3 + b1 * t2 + c1 * t + d1)); + + /* create gimp_vector2_neq () ? */ + if (g_array_index (points, Pixel, points->len - 1).x != p.x || + g_array_index (points, Pixel, points->len - 1).y != p.y) + { + g_array_append_val (points, p); + } + dx = fabs (3 * a0 * t * t + 2 * b0 * t + c0) + 1e-8; + dy = fabs (3 * a1 * t * t + 2 * b1 * t + c1) + 1e-8; + t += MIN (dtMin, 0.75 / MAX (dx, dy)); + } + if (g_array_index (points, Pixel, points->len - 1).x != p1.x || + g_array_index (points, Pixel, points->len - 1).y != p1.y) + { + g_array_append_val (points, p1); + } + return points; +} + +static gint +gimp_number_of_transitions (GArray *pixels, + GeglBuffer *buffer) +{ + int result = 0; + + if (pixels->len > 0) + { + Pixel it = g_array_index (pixels, Pixel, 0); + guchar value; + gboolean previous; + gint i; + + gegl_buffer_sample (buffer, (gint) it.x, (gint) it.y, NULL, &value, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + previous = (gboolean) value; + + /* Starts at the second element. */ + for (i = 1; i < pixels->len; i++) + { + it = g_array_index (pixels, Pixel, i); + + gegl_buffer_sample (buffer, (gint) it.x, (gint) it.y, NULL, &value, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + result += ((gboolean) value != previous); + previous = (gboolean) value; + } + } + + return result; +} + +/** + * gimp_line_art_allow_closure: + * @mask: the current state of line art closure. + * @pixels: the pixels of a candidate closure (spline or segment). + * @fill_pixels: #GList of unsignificant pixels to bucket fill. + * @significant_size: number of pixels for area to be considered + * "significant". + * @minimum_size: number of pixels for area to be allowed. + * + * Checks whether adding the set of points @pixels to @mask will create + * 4-connected background regions whose size (i.e. number of pixels) + * will be below @minimum_size. If it creates such small areas, the + * function will refuse this candidate spline/segment, with the + * exception of very small areas under @significant_size. These + * micro-area are considered "unsignificant" and accepted (because they + * can be created in some conditions, for instance when created curves + * cross or start from a same endpoint), and one pixel for each + * micro-area will be added to @fill_pixels to be later filled along + * with the candidate pixels. + * + * Returns: #TRUE if @pixels should be added to @mask, #FALSE otherwise. + */ +static gboolean +gimp_line_art_allow_closure (GeglBuffer *mask, + GArray *pixels, + GList **fill_pixels, + int significant_size, + int minimum_size) +{ + /* A theorem from the paper is that a zone with more than + * `2 * (@minimum_size - 1)` edgels (border pixels) will have more + * than @minimum_size pixels. + * Since we are following the edges of the area, we can therefore stop + * earlier if we reach this number of edgels. + */ + const glong max_edgel_count = 2 * (minimum_size + 1); + + Pixel *p = (Pixel*) pixels->data; + GList *fp = NULL; + gint i; + + /* Mark pixels */ + for (i = 0; i < pixels->len; i++) + { + if (p->x >= 0 && p->x < gegl_buffer_get_width (mask) && + p->y >= 0 && p->y < gegl_buffer_get_height (mask)) + { + guchar val; + + gegl_buffer_sample (mask, (gint) p->x, (gint) p->y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + val = val ? 3 : 2; + gegl_buffer_set (mask, GEGL_RECTANGLE ((gint) p->x, (gint) p->y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + p++; + } + + for (i = 0; i < pixels->len; i++) + { + Pixel p = g_array_index (pixels, Pixel, i); + + for (int direction = 0; direction < 4; ++direction) + { + if (p.x >= 0 && p.x < gegl_buffer_get_width (mask) && + p.y >= 0 && p.y < gegl_buffer_get_height (mask) && + border_in_direction (mask, p, direction)) + { + Edgel e; + guchar val; + glong count; + glong area; + + gegl_buffer_sample (mask, (gint) p.x, (gint) p.y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if ((gboolean) (val & (4 << direction))) + continue; + + gimp_edgel_init (&e); + e.x = p.x; + e.y = p.y; + e.direction = direction; + + count = gimp_edgel_track_mark (mask, e, max_edgel_count); + if ((count != -1) && (count <= max_edgel_count)) + { + area = gimp_edgel_region_area (mask, e); + + if (area >= significant_size && area <= minimum_size) + { + gint j; + + /* Remove marks */ + for (j = 0; j < pixels->len; j++) + { + Pixel p2 = g_array_index (pixels, Pixel, j); + + if (p2.x >= 0 && p2.x < gegl_buffer_get_width (mask) && + p2.y >= 0 && p2.y < gegl_buffer_get_height (mask)) + { + guchar val; + + gegl_buffer_sample (mask, (gint) p2.x, (gint) p2.y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + val &= 1; + gegl_buffer_set (mask, GEGL_RECTANGLE ((gint) p2.x, (gint) p2.y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + } + g_list_free_full (fp, g_free); + + return FALSE; + } + else if (area > 0 && area < significant_size) + { + Pixel *np = g_new (Pixel, 1); + + np->x = direction == XPlusDirection ? p.x + 1 : (direction == XMinusDirection ? p.x - 1 : p.x); + np->y = direction == YPlusDirection ? p.y + 1 : (direction == YMinusDirection ? p.y - 1 : p.y); + + if (np->x >= 0 && np->x < gegl_buffer_get_width (mask) && + np->y >= 0 && np->y < gegl_buffer_get_height (mask)) + fp = g_list_prepend (fp, np); + else + g_free (np); + } + } + } + } + } + + *fill_pixels = g_list_concat (*fill_pixels, fp); + /* Remove marks */ + for (i = 0; i < pixels->len; i++) + { + Pixel p = g_array_index (pixels, Pixel, i); + + if (p.x >= 0 && p.x < gegl_buffer_get_width (mask) && + p.y >= 0 && p.y < gegl_buffer_get_height (mask)) + { + guchar val; + + gegl_buffer_sample (mask, (gint) p.x, (gint) p.y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + val &= 1; + gegl_buffer_set (mask, GEGL_RECTANGLE ((gint) p.x, (gint) p.y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + } + return TRUE; +} + +static GArray * +gimp_lineart_line_segment_until_hit (const GeglBuffer *mask, + Pixel start, + GimpVector2 direction, + int size) +{ + GeglBuffer *buffer = (GeglBuffer *) mask; + gboolean out = FALSE; + GArray *points = g_array_new (FALSE, TRUE, sizeof (Pixel)); + int tmax; + GimpVector2 p0 = gimp_vector2_new (start.x, start.y); + + gimp_vector2_mul (&direction, (gdouble) size); + direction.x = round (direction.x); + direction.y = round (direction.y); + + tmax = MAX (abs ((int) direction.x), abs ((int) direction.y)); + + for (int t = 0; t <= tmax; ++t) + { + GimpVector2 v = gimp_vector2_add_val (p0, gimp_vector2_mul_val (direction, (float)t / tmax)); + Pixel p; + + p.x = (gint) round (v.x); + p.y = (gint) round (v.y); + if (p.x >= 0 && p.x < gegl_buffer_get_width (buffer) && + p.y >= 0 && p.y < gegl_buffer_get_height (buffer)) + { + guchar val; + gegl_buffer_sample (buffer, p.x, p.y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (out && val) + { + return points; + } + out = ! val; + } + else if (out) + { + return points; + } + else + { + g_array_free (points, TRUE); + return g_array_new (FALSE, TRUE, sizeof (Pixel)); + } + g_array_append_val (points, p); + } + + g_array_free (points, TRUE); + return g_array_new (FALSE, TRUE, sizeof (Pixel)); +} + +static gfloat * +gimp_lineart_estimate_strokes_radii (GeglBuffer *mask, + GimpAsync *async) +{ + GeglBufferIterator *gi; + gfloat *dist; + gfloat *thickness; + GeglNode *graph; + GeglNode *input; + GeglNode *op; + gint width = gegl_buffer_get_width (mask); + gint height = gegl_buffer_get_height (mask); + + /* Compute a distance map for the line art. */ + dist = g_new (gfloat, width * height); + + graph = gegl_node_new (); + input = gegl_node_new_child (graph, + "operation", "gegl:buffer-source", + "buffer", mask, + NULL); + op = gegl_node_new_child (graph, + "operation", "gegl:distance-transform", + "metric", GEGL_DISTANCE_METRIC_EUCLIDEAN, + "normalize", FALSE, + NULL); + gegl_node_connect_to (input, "output", op, "input"); + gegl_node_blit (op, 1.0, gegl_buffer_get_extent (mask), + NULL, dist, GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_DEFAULT); + g_object_unref (graph); + + thickness = g_new0 (gfloat, width * height); + gi = gegl_buffer_iterator_new (mask, NULL, 0, NULL, + GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1); + while (gegl_buffer_iterator_next (gi)) + { + guint8 *m = (guint8*) gi->items[0].data; + gint startx = gi->items[0].roi.x; + gint starty = gi->items[0].roi.y; + gint endy = starty + gi->items[0].roi.height; + gint endx = startx + gi->items[0].roi.width; + gint x; + gint y; + + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + goto end; + } + + for (y = starty; y < endy; y++) + for (x = startx; x < endx; x++) + { + if (*m && dist[x + y * width] == 1.0) + { + gint dx = x; + gint dy = y; + gfloat d = 1.0; + gfloat nd; + gboolean neighbour_thicker = TRUE; + + while (neighbour_thicker) + { + gint px = dx - 1; + gint py = dy - 1; + gint nx = dx + 1; + gint ny = dy + 1; + + neighbour_thicker = FALSE; + if (px >= 0) + { + if ((nd = dist[px + dy * width]) > d) + { + d = nd; + dx = px; + neighbour_thicker = TRUE; + continue; + } + if (py >= 0 && (nd = dist[px + py * width]) > d) + { + d = nd; + dx = px; + dy = py; + neighbour_thicker = TRUE; + continue; + } + if (ny < height && (nd = dist[px + ny * width]) > d) + { + d = nd; + dx = px; + dy = ny; + neighbour_thicker = TRUE; + continue; + } + } + if (nx < width) + { + if ((nd = dist[nx + dy * width]) > d) + { + d = nd; + dx = nx; + neighbour_thicker = TRUE; + continue; + } + if (py >= 0 && (nd = dist[nx + py * width]) > d) + { + d = nd; + dx = nx; + dy = py; + neighbour_thicker = TRUE; + continue; + } + if (ny < height && (nd = dist[nx + ny * width]) > d) + { + d = nd; + dx = nx; + dy = ny; + neighbour_thicker = TRUE; + continue; + } + } + if (py > 0 && (nd = dist[dx + py * width]) > d) + { + d = nd; + dy = py; + neighbour_thicker = TRUE; + continue; + } + if (ny < height && (nd = dist[dx + ny * width]) > d) + { + d = nd; + dy = ny; + neighbour_thicker = TRUE; + continue; + } + } + thickness[(gint) x + (gint) y * width] = d; + } + m++; + } + } + + end: + g_free (dist); + + if (gimp_async_is_stopped (async)) + g_clear_pointer (&thickness, g_free); + + return thickness; +} + +static void +gimp_line_art_simple_fill (GeglBuffer *buffer, + gint x, + gint y) +{ + guchar val; + + if (x < 0 || x >= gegl_buffer_get_width (buffer) || + y < 0 || y >= gegl_buffer_get_height (buffer)) + return; + + gegl_buffer_sample (buffer, x, y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (! val) + { + val = 1; + gegl_buffer_set (buffer, GEGL_RECTANGLE (x, y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + gimp_line_art_simple_fill (buffer, x + 1, y); + gimp_line_art_simple_fill (buffer, x - 1, y); + gimp_line_art_simple_fill (buffer, x, y + 1); + gimp_line_art_simple_fill (buffer, x, y - 1); + } +} + +static guint +visited_hash_fun (Pixel *key) +{ + /* Cantor pairing function. */ + return (key->x + key->y) * (key->x + key->y + 1) / 2 + key->y; +} + +static gboolean +visited_equal_fun (Pixel *e1, + Pixel *e2) +{ + return (e1->x == e2->x && e1->y == e2->y); +} + +static inline gboolean +border_in_direction (GeglBuffer *mask, + Pixel p, + int direction) +{ + gint px = (gint) p.x + DeltaX[direction]; + gint py = (gint) p.y + DeltaY[direction]; + + if (px >= 0 && px < gegl_buffer_get_width (mask) && + py >= 0 && py < gegl_buffer_get_height (mask)) + { + guchar val; + + gegl_buffer_sample (mask, px, py, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + return ! ((gboolean) val); + } + return TRUE; +} + +static inline GimpVector2 +pair2normal (Pixel p, + gfloat *normals, + gint width) +{ + return gimp_vector2_new (normals[((gint) p.x + (gint) p.y * width) * 2], + normals[((gint) p.x + (gint) p.y * width) * 2 + 1]); +} +/* Edgel functions */ + +static Edgel * +gimp_edgel_new (int x, + int y, + Direction direction) +{ + Edgel *edgel = g_new (Edgel, 1); + + edgel->x = x; + edgel->y = y; + edgel->direction = direction; + + gimp_edgel_init (edgel); + + return edgel; +} + +static void +gimp_edgel_init (Edgel *edgel) +{ + edgel->x_normal = 0; + edgel->y_normal = 0; + edgel->curvature = 0; + edgel->next = edgel->previous = G_MAXUINT; +} + +static void +gimp_edgel_clear (Edgel **edgel) +{ + g_clear_pointer (edgel, g_free); +} + +static int +gimp_edgel_cmp (const Edgel* e1, + const Edgel* e2) +{ + gimp_assert (e1 && e2); + + if ((e1->x == e2->x) && (e1->y == e2->y) && + (e1->direction == e2->direction)) + return 0; + else if ((e1->y < e2->y) || (e1->y == e2->y && e1->x < e2->x) || + (e1->y == e2->y && e1->x == e2->x && e1->direction < e2->direction)) + return -1; + else + return 1; +} + +static guint +edgel2index_hash_fun (Edgel *key) +{ + /* Cantor pairing function. + * Was not sure how to use the direction though. :-/ + */ + return (key->x + key->y) * (key->x + key->y + 1) / 2 + key->y * key->direction; +} + +static gboolean +edgel2index_equal_fun (Edgel *e1, + Edgel *e2) +{ + return (e1->x == e2->x && e1->y == e2->y && + e1->direction == e2->direction); +} + +/** + * @mask; + * @edgel: + * @size_limit: + * + * Track a border, marking inner pixels with a bit corresponding to the + * edgel traversed (4 << direction) for direction in {0,1,2,3}. + * Stop tracking after @size_limit edgels have been visited. + * + * Returns: Number of visited edgels, or -1 if an already visited edgel + * has been encountered. + */ +static glong +gimp_edgel_track_mark (GeglBuffer *mask, + Edgel edgel, + long size_limit) +{ + Edgel start = edgel; + long count = 1; + + do + { + guchar val; + + gimp_edgelset_next8 (mask, &edgel, &edgel); + gegl_buffer_sample (mask, edgel.x, edgel.y, NULL, &val, + NULL, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + if (val & 2) + { + /* Only mark pixels of the spline/segment */ + if (val & (4 << edgel.direction)) + return -1; + + /* Mark edgel in pixel (1 == In Mask, 2 == Spline/Segment) */ + val |= (4 << edgel.direction); + gegl_buffer_set (mask, GEGL_RECTANGLE (edgel.x, edgel.y, 1, 1), 0, + NULL, &val, GEGL_AUTO_ROWSTRIDE); + } + if (gimp_edgel_cmp (&edgel, &start) != 0) + ++count; + } + while (gimp_edgel_cmp (&edgel, &start) != 0 && count <= size_limit); + + return count; +} + +/** + * gimp_edgel_region_area: + * @mask: current state of closed line art buffer. + * @start_edgel: edgel to follow. + * + * Follows a line border, starting from @start_edgel to compute the area + * enclosed by this border. + * Unfortunately this may return a negative area when the line does not + * close a zone. In this case, there is an uncertaincy on the size of + * the created zone, and we should consider it a big size. + * + * Returns: the area enclosed by the followed line, or a negative value + * if the zone is not closed (hence actual area unknown). + */ +static glong +gimp_edgel_region_area (const GeglBuffer *mask, + Edgel start_edgel) +{ + Edgel edgel = start_edgel; + glong area = 0; + + do + { + if (edgel.direction == XPlusDirection) + area -= edgel.x; + else if (edgel.direction == XMinusDirection) + area += edgel.x - 1; + + gimp_edgelset_next8 (mask, &edgel, &edgel); + } + while (gimp_edgel_cmp (&edgel, &start_edgel) != 0); + + return area; +} + +/* Edgel sets */ + +static GArray * +gimp_edgelset_new (GeglBuffer *buffer, + GimpAsync *async) +{ + GeglBufferIterator *gi; + GArray *set; + GHashTable *edgel2index; + gint width = gegl_buffer_get_width (buffer); + gint height = gegl_buffer_get_height (buffer); + + set = g_array_new (TRUE, TRUE, sizeof (Edgel *)); + g_array_set_clear_func (set, (GDestroyNotify) gimp_edgel_clear); + + if (width <= 1 || height <= 1) + return set; + + edgel2index = g_hash_table_new ((GHashFunc) edgel2index_hash_fun, + (GEqualFunc) edgel2index_equal_fun); + + gi = gegl_buffer_iterator_new (buffer, GEGL_RECTANGLE (0, 0, width, height), + 0, NULL, GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 5); + gegl_buffer_iterator_add (gi, buffer, GEGL_RECTANGLE (0, -1, width, height), + 0, NULL, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + gegl_buffer_iterator_add (gi, buffer, GEGL_RECTANGLE (0, 1, width, height), + 0, NULL, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + gegl_buffer_iterator_add (gi, buffer, GEGL_RECTANGLE (-1, 0, width, height), + 0, NULL, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + gegl_buffer_iterator_add (gi, buffer, GEGL_RECTANGLE (1, 0, width, height), + 0, NULL, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + while (gegl_buffer_iterator_next (gi)) + { + guint8 *p = (guint8*) gi->items[0].data; + guint8 *prevy = (guint8*) gi->items[1].data; + guint8 *nexty = (guint8*) gi->items[2].data; + guint8 *prevx = (guint8*) gi->items[3].data; + guint8 *nextx = (guint8*) gi->items[4].data; + gint startx = gi->items[0].roi.x; + gint starty = gi->items[0].roi.y; + gint endy = starty + gi->items[0].roi.height; + gint endx = startx + gi->items[0].roi.width; + gint x; + gint y; + + if (gimp_async_is_canceled (async)) + { + gegl_buffer_iterator_stop (gi); + + gimp_async_abort (async); + + goto end; + } + + for (y = starty; y < endy; y++) + for (x = startx; x < endx; x++) + { + if (*(p++)) + { + if (! *prevy) + gimp_edgelset_add (set, x, y, YMinusDirection, edgel2index); + if (! *nexty) + gimp_edgelset_add (set, x, y, YPlusDirection, edgel2index); + if (! *prevx) + gimp_edgelset_add (set, x, y, XMinusDirection, edgel2index); + if (! *nextx) + gimp_edgelset_add (set, x, y, XPlusDirection, edgel2index); + } + prevy++; + nexty++; + prevx++; + nextx++; + } + } + + gimp_edgelset_build_graph (set, buffer, edgel2index, async); + if (gimp_async_is_stopped (async)) + goto end; + + gimp_edgelset_init_normals (set); + + end: + g_hash_table_destroy (edgel2index); + + if (gimp_async_is_stopped (async)) + { + g_array_free (set, TRUE); + set = NULL; + } + + return set; +} + +static void +gimp_edgelset_add (GArray *set, + int x, + int y, + Direction direction, + GHashTable *edgel2index) +{ + Edgel *edgel = gimp_edgel_new (x, y, direction); + unsigned long position = set->len; + + g_array_append_val (set, edgel); + g_hash_table_insert (edgel2index, edgel, GUINT_TO_POINTER (position)); +} + +static void +gimp_edgelset_init_normals (GArray *set) +{ + Edgel **e = (Edgel**) set->data; + + while (*e) + { + GimpVector2 n = Direction2Normal[(*e)->direction]; + + (*e)->x_normal = n.x; + (*e)->y_normal = n.y; + e++; + } +} + +static void +gimp_edgelset_smooth_normals (GArray *set, + int mask_size, + GimpAsync *async) +{ + const gfloat sigma = mask_size * 0.775; + const gfloat den = 2 * sigma * sigma; + gfloat weights[65]; + GimpVector2 smoothed_normal; + gint i; + + gimp_assert (mask_size <= 65); + + weights[0] = 1.0f; + for (int i = 1; i <= mask_size; ++i) + weights[i] = expf (-(i * i) / den); + + for (i = 0; i < set->len; i++) + { + Edgel *it = g_array_index (set, Edgel*, i); + Edgel *edgel_before = g_array_index (set, Edgel*, it->previous); + Edgel *edgel_after = g_array_index (set, Edgel*, it->next); + int n = mask_size; + int i = 1; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + return; + } + + smoothed_normal = Direction2Normal[it->direction]; + while (n-- && (edgel_after != edgel_before)) + { + smoothed_normal = gimp_vector2_add_val (smoothed_normal, + gimp_vector2_mul_val (Direction2Normal[edgel_before->direction], weights[i])); + smoothed_normal = gimp_vector2_add_val (smoothed_normal, + gimp_vector2_mul_val (Direction2Normal[edgel_after->direction], weights[i])); + edgel_before = g_array_index (set, Edgel *, edgel_before->previous); + edgel_after = g_array_index (set, Edgel *, edgel_after->next); + ++i; + } + gimp_vector2_normalize (&smoothed_normal); + it->x_normal = smoothed_normal.x; + it->y_normal = smoothed_normal.y; + } +} + +static void +gimp_edgelset_compute_curvature (GArray *set, + GimpAsync *async) +{ + gint i; + + for (i = 0; i < set->len; i++) + { + Edgel *it = g_array_index (set, Edgel*, i); + Edgel *previous = g_array_index (set, Edgel *, it->previous); + Edgel *next = g_array_index (set, Edgel *, it->next); + GimpVector2 n_prev = gimp_vector2_new (previous->x_normal, previous->y_normal); + GimpVector2 n_next = gimp_vector2_new (next->x_normal, next->y_normal); + GimpVector2 diff = gimp_vector2_mul_val (gimp_vector2_sub_val (n_next, n_prev), + 0.5); + const float c = gimp_vector2_length_val (diff); + const float crossp = n_prev.x * n_next.y - n_prev.y * n_next.x; + + it->curvature = (crossp > 0.0f) ? c : -c; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + return; + } + } +} + +static void +gimp_edgelset_build_graph (GArray *set, + GeglBuffer *buffer, + GHashTable *edgel2index, + GimpAsync *async) +{ + Edgel edgel; + gint i; + + for (i = 0; i < set->len; i++) + { + Edgel *neighbor; + Edgel *it = g_array_index (set, Edgel *, i); + guint neighbor_pos; + + if (gimp_async_is_canceled (async)) + { + gimp_async_abort (async); + + return; + } + + gimp_edgelset_next8 (buffer, it, &edgel); + + gimp_assert (g_hash_table_contains (edgel2index, &edgel)); + neighbor_pos = GPOINTER_TO_UINT (g_hash_table_lookup (edgel2index, &edgel)); + it->next = neighbor_pos; + neighbor = g_array_index (set, Edgel *, neighbor_pos); + neighbor->previous = i; + } +} + +static void +gimp_edgelset_next8 (const GeglBuffer *buffer, + Edgel *it, + Edgel *n) +{ + guint8 pixels[9]; + + n->x = it->x; + n->y = it->y; + n->direction = it->direction; + + gegl_buffer_get ((GeglBuffer *) buffer, + GEGL_RECTANGLE (n->x - 1, n->y - 1, 3, 3), + 1.0, NULL, pixels, GEGL_AUTO_ROWSTRIDE, + GEGL_ABYSS_NONE); + switch (n->direction) + { + case XPlusDirection: + if (pixels[8]) + { + ++(n->y); + ++(n->x); + n->direction = YMinusDirection; + } + else if (pixels[7]) + { + ++(n->y); + } + else + { + n->direction = YPlusDirection; + } + break; + case YMinusDirection: + if (pixels[2]) + { + ++(n->x); + --(n->y); + n->direction = XMinusDirection; + } + else if (pixels[5]) + { + ++(n->x); + } + else + { + n->direction = XPlusDirection; + } + break; + case XMinusDirection: + if (pixels[0]) + { + --(n->x); + --(n->y); + n->direction = YPlusDirection; + } + else if (pixels[1]) + { + --(n->y); + } + else + { + n->direction = YMinusDirection; + } + break; + case YPlusDirection: + if (pixels[6]) + { + --(n->x); + ++(n->y); + n->direction = XPlusDirection; + } + else if (pixels[3]) + { + --(n->x); + } + else + { + n->direction = XMinusDirection; + } + break; + default: + g_return_if_reached (); + break; + } +} diff -Nru gimp-2.10.8+zorin2/app/core/gimplineart.h gimp-2.10.14+om/app/core/gimplineart.h --- gimp-2.10.8+zorin2/app/core/gimplineart.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimplineart.h 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,73 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * Copyright (C) 2017 Sébastien Fourey & David Tchumperlé + * Copyright (C) 2018 Jehan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_LINEART__ +#define __GIMP_LINEART__ + + +#include "gimpobject.h" + +#define GIMP_TYPE_LINE_ART (gimp_line_art_get_type ()) +#define GIMP_LINE_ART(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_LINE_ART, GimpLineArt)) +#define GIMP_LINE_ART_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_LINE_ART, GimpLineArtClass)) +#define GIMP_IS_LINE_ART(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_LINE_ART)) +#define GIMP_IS_LINE_ART_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_LINE_ART)) +#define GIMP_LINE_ART_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_LINE_ART, GimpLineArtClass)) + + +typedef struct _GimpLineArtClass GimpLineArtClass; +typedef struct _GimpLineArtPrivate GimpLineArtPrivate; + +struct _GimpLineArt +{ + GimpObject parent_instance; + + GimpLineArtPrivate *priv; +}; + +struct _GimpLineArtClass +{ + GimpObjectClass parent_class; + + /* Signals */ + + void (* computing_start) (GimpLineArt *line_art); + void (* computing_end) (GimpLineArt *line_art); +}; + + +GType gimp_line_art_get_type (void) G_GNUC_CONST; + +GimpLineArt * gimp_line_art_new (void); + +void gimp_line_art_bind_gap_length (GimpLineArt *line_art, + gboolean bound); + +void gimp_line_art_set_input (GimpLineArt *line_art, + GimpPickable *pickable); +GimpPickable * gimp_line_art_get_input (GimpLineArt *line_art); +void gimp_line_art_freeze (GimpLineArt *line_art); +void gimp_line_art_thaw (GimpLineArt *line_art); +gboolean gimp_line_art_is_frozen (GimpLineArt *line_art); + +GeglBuffer * gimp_line_art_get (GimpLineArt *line_art, + gfloat **distmap); + +#endif /* __GIMP_LINEART__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpmarshal.c gimp-2.10.14+om/app/core/gimpmarshal.c --- gimp-2.10.8+zorin2/app/core/gimpmarshal.c 2018-11-08 14:45:53.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmarshal.c 2019-10-26 19:20:35.000000000 +0000 @@ -1893,6 +1893,9 @@ data2); } -/* VOID: VOID (./gimpmarshal.list:73) */ +/* VOID: VARIANT (./gimpmarshal.list:73) */ +#define gimp_marshal_VOID__VARIANT g_cclosure_marshal_VOID__VARIANT + +/* VOID: VOID (./gimpmarshal.list:74) */ #define gimp_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID diff -Nru gimp-2.10.8+zorin2/app/core/gimpmarshal.h gimp-2.10.14+om/app/core/gimpmarshal.h --- gimp-2.10.8+zorin2/app/core/gimpmarshal.h 2018-11-08 14:45:53.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmarshal.h 2019-10-26 19:20:35.000000000 +0000 @@ -366,7 +366,10 @@ gpointer invocation_hint, gpointer marshal_data); -/* VOID: VOID (./gimpmarshal.list:73) */ +/* VOID: VARIANT (./gimpmarshal.list:73) */ +#define gimp_marshal_VOID__VARIANT g_cclosure_marshal_VOID__VARIANT + +/* VOID: VOID (./gimpmarshal.list:74) */ #define gimp_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID diff -Nru gimp-2.10.8+zorin2/app/core/gimpmarshal.list gimp-2.10.14+om/app/core/gimpmarshal.list --- gimp-2.10.8+zorin2/app/core/gimpmarshal.list 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmarshal.list 2019-10-26 18:49:18.000000000 +0000 @@ -70,4 +70,5 @@ VOID: STRING, DOUBLE, STRING, DOUBLE, STRING VOID: STRING, FLAGS VOID: STRING, STRING, STRING +VOID: VARIANT VOID: VOID diff -Nru gimp-2.10.8+zorin2/app/core/gimpmaskundo.c gimp-2.10.14+om/app/core/gimpmaskundo.c --- gimp-2.10.8+zorin2/app/core/gimpmaskundo.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmaskundo.c 2019-10-26 18:49:18.000000000 +0000 @@ -23,7 +23,6 @@ #include "core-types.h" #include "gegl/gimp-gegl-loops.h" -#include "gegl/gimp-gegl-utils.h" #include "gimp-memsize.h" #include "gimpchannel.h" @@ -97,7 +96,6 @@ GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (object); GimpItem *item; GimpDrawable *drawable; - gint x, y, w, h; G_OBJECT_CLASS (parent_class)->constructed (object); @@ -106,22 +104,31 @@ item = GIMP_ITEM_UNDO (object)->item; drawable = GIMP_DRAWABLE (item); - if (gimp_item_bounds (item, &x, &y, &w, &h)) + mask_undo->format = gimp_drawable_get_format (drawable); + + if (gimp_item_bounds (item, + &mask_undo->bounds.x, + &mask_undo->bounds.y, + &mask_undo->bounds.width, + &mask_undo->bounds.height)) { - mask_undo->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), - gimp_drawable_get_format (drawable)); + GeglBuffer *buffer = gimp_drawable_get_buffer (drawable); + GeglRectangle rect; - gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (x, y, w, h), - GEGL_ABYSS_NONE, - mask_undo->buffer, - GEGL_RECTANGLE (0, 0, 0, 0)); + gegl_rectangle_align_to_buffer (&rect, &mask_undo->bounds, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); - mask_undo->x = x; - mask_undo->y = y; - } + mask_undo->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, + rect.width, + rect.height), + mask_undo->format); - mask_undo->format = gimp_drawable_get_format (drawable); + gimp_gegl_buffer_copy (buffer, &rect, GEGL_ABYSS_NONE, + mask_undo->buffer, GEGL_RECTANGLE (0, 0, 0, 0)); + + mask_undo->x = rect.x; + mask_undo->y = rect.y; + } } static void @@ -182,38 +189,39 @@ GimpUndoMode undo_mode, GimpUndoAccumulator *accum) { - GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (undo); - GimpItem *item = GIMP_ITEM_UNDO (undo)->item; - GimpDrawable *drawable = GIMP_DRAWABLE (item); - GimpChannel *channel = GIMP_CHANNEL (item); - GeglBuffer *new_buffer; - const Babl *format; - gint x, y, w, h; - gint width = 0; - gint height = 0; + GimpMaskUndo *mask_undo = GIMP_MASK_UNDO (undo); + GimpItem *item = GIMP_ITEM_UNDO (undo)->item; + GimpDrawable *drawable = GIMP_DRAWABLE (item); + GimpChannel *channel = GIMP_CHANNEL (item); + GeglBuffer *new_buffer = NULL; + GeglRectangle bounds = {}; + GeglRectangle rect = {}; + const Babl *format; GIMP_UNDO_CLASS (parent_class)->pop (undo, undo_mode, accum); - if (gimp_item_bounds (item, &x, &y, &w, &h)) + format = gimp_drawable_get_format (drawable); + + if (gimp_item_bounds (item, + &bounds.x, + &bounds.y, + &bounds.width, + &bounds.height)) { - new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, w, h), - gimp_drawable_get_format (drawable)); + GeglBuffer *buffer = gimp_drawable_get_buffer (drawable); - gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (x, y, w, h), - GEGL_ABYSS_NONE, - new_buffer, - GEGL_RECTANGLE (0, 0, 0, 0)); + gegl_rectangle_align_to_buffer (&rect, &bounds, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); - gegl_buffer_clear (gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (x, y, w, h)); - } - else - { - new_buffer = NULL; - } + new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, + rect.width, rect.height), + format); - format = gimp_drawable_get_format (drawable); + gimp_gegl_buffer_copy (buffer, &rect, GEGL_ABYSS_NONE, + new_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); + + gegl_buffer_clear (buffer, &rect); + } if (mask_undo->convert_format) { @@ -223,7 +231,6 @@ buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), mask_undo->format); - gegl_buffer_clear (buffer, NULL); gimp_drawable_set_buffer (drawable, FALSE, NULL, buffer); g_object_unref (buffer); @@ -231,9 +238,6 @@ if (mask_undo->buffer) { - width = gegl_buffer_get_width (mask_undo->buffer); - height = gegl_buffer_get_height (mask_undo->buffer); - gimp_gegl_buffer_copy (mask_undo->buffer, NULL, GEGL_ABYSS_NONE, @@ -249,10 +253,10 @@ if (mask_undo->buffer) { channel->empty = FALSE; - channel->x1 = mask_undo->x; - channel->y1 = mask_undo->y; - channel->x2 = mask_undo->x + width; - channel->y2 = mask_undo->y + height; + channel->x1 = mask_undo->bounds.x; + channel->y1 = mask_undo->bounds.y; + channel->x2 = mask_undo->bounds.x + mask_undo->bounds.width; + channel->y2 = mask_undo->bounds.y + mask_undo->bounds.height; } else { @@ -267,10 +271,11 @@ channel->bounds_known = TRUE; /* set the new mask undo parameters */ - mask_undo->buffer = new_buffer; - mask_undo->x = x; - mask_undo->y = y; mask_undo->format = format; + mask_undo->buffer = new_buffer; + mask_undo->bounds = bounds; + mask_undo->x = rect.x; + mask_undo->y = rect.y; gimp_drawable_update (drawable, 0, 0, -1, -1); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpmaskundo.h gimp-2.10.14+om/app/core/gimpmaskundo.h --- gimp-2.10.8+zorin2/app/core/gimpmaskundo.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmaskundo.h 2019-04-07 11:38:14.000000000 +0000 @@ -35,14 +35,15 @@ struct _GimpMaskUndo { - GimpItemUndo parent_instance; + GimpItemUndo parent_instance; - gboolean convert_format; + gboolean convert_format; - GeglBuffer *buffer; - gint x; - gint y; - const Babl *format; + const Babl *format; + GeglBuffer *buffer; + GeglRectangle bounds; + gint x; + gint y; }; struct _GimpMaskUndoClass diff -Nru gimp-2.10.8+zorin2/app/core/gimpmybrush.c gimp-2.10.14+om/app/core/gimpmybrush.c --- gimp-2.10.8+zorin2/app/core/gimpmybrush.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpmybrush.c 2019-06-12 16:43:38.000000000 +0000 @@ -109,11 +109,7 @@ { GimpMybrush *brush = GIMP_MYBRUSH (object); - if (brush->priv->brush_json) - { - g_free (brush->priv->brush_json); - brush->priv->brush_json = NULL; - } + g_clear_pointer (&brush->priv->brush_json, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } diff -Nru gimp-2.10.8+zorin2/app/core/gimpobject.c gimp-2.10.14+om/app/core/gimpobject.c --- gimp-2.10.8+zorin2/app/core/gimpobject.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpobject.c 2019-10-26 18:49:18.000000000 +0000 @@ -56,9 +56,7 @@ }; -static void gimp_object_class_init (GimpObjectClass *klass); -static void gimp_object_init (GimpObject *object, - GimpObjectClass *klass); +static void gimp_object_constructed (GObject *object); static void gimp_object_dispose (GObject *object); static void gimp_object_finalize (GObject *object); static void gimp_object_set_property (GObject *object, @@ -74,38 +72,13 @@ static void gimp_object_name_normalize (GimpObject *object); -static GObjectClass *parent_class = NULL; +G_DEFINE_TYPE_WITH_CODE (GimpObject, gimp_object, G_TYPE_OBJECT, + G_ADD_PRIVATE (GimpObject)) -static guint object_signals[LAST_SIGNAL] = { 0 }; - - -GType -gimp_object_get_type (void) -{ - static GType object_type = 0; +#define parent_class gimp_object_parent_class - if (! object_type) - { - const GTypeInfo object_info = - { - sizeof (GimpObjectClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gimp_object_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GimpObject), - 0, /* n_preallocs */ - (GInstanceInitFunc) gimp_object_init, - }; - - object_type = g_type_register_static (G_TYPE_OBJECT, - "GimpObject", - &object_info, 0); - } +static guint object_signals[LAST_SIGNAL] = { 0 }; - return object_type; -} static void gimp_object_class_init (GimpObjectClass *klass) @@ -132,6 +105,7 @@ gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); + object_class->constructed = gimp_object_constructed; object_class->dispose = gimp_object_dispose; object_class->finalize = gimp_object_finalize; object_class->set_property = gimp_object_set_property; @@ -147,21 +121,23 @@ NULL, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_type_class_add_private (klass, - sizeof (GimpObjectPrivate)); } static void -gimp_object_init (GimpObject *object, - GimpObjectClass *klass) +gimp_object_init (GimpObject *object) { - object->p = G_TYPE_INSTANCE_GET_PRIVATE (object, - GIMP_TYPE_OBJECT, - GimpObjectPrivate); + object->p = gimp_object_get_instance_private (object); + object->p->name = NULL; object->p->normalized = NULL; +} + +static void +gimp_object_constructed (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->constructed (object); - gimp_debug_add_instance (G_OBJECT (object), G_OBJECT_CLASS (klass)); + gimp_debug_add_instance (object, G_OBJECT_GET_CLASS (object)); } static void diff -Nru gimp-2.10.8+zorin2/app/core/gimppalette.c gimp-2.10.14+om/app/core/gimppalette.c --- gimp-2.10.8+zorin2/app/core/gimppalette.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppalette.c 2019-01-03 14:13:22.000000000 +0000 @@ -37,7 +37,9 @@ #include "gimp-intl.h" -#define EPSILON 1e-10 + +#define RGB_EPSILON 1e-6 + /* local function prototypes */ @@ -648,11 +650,11 @@ for (list = palette->colors; list; list = g_list_next (list)) { entry = (GimpPaletteEntry *) list->data; - if (gimp_rgb_distance (&entry->color, color) < EPSILON) + if (gimp_rgb_distance (&entry->color, color) < RGB_EPSILON) return entry; } } - else if (gimp_rgb_distance (&start_from->color, color) < EPSILON) + else if (gimp_rgb_distance (&start_from->color, color) < RGB_EPSILON) { return start_from; } @@ -674,7 +676,7 @@ if (next) { entry = (GimpPaletteEntry *) next->data; - if (gimp_rgb_distance (&entry->color, color) < EPSILON) + if (gimp_rgb_distance (&entry->color, color) < RGB_EPSILON) return entry; next = next->next; @@ -683,7 +685,7 @@ if (prev) { entry = (GimpPaletteEntry *) prev->data; - if (gimp_rgb_distance (&entry->color, color) < EPSILON) + if (gimp_rgb_distance (&entry->color, color) < RGB_EPSILON) return entry; prev = prev->prev; diff -Nru gimp-2.10.8+zorin2/app/core/gimppalette-import.c gimp-2.10.14+om/app/core/gimppalette-import.c --- gimp-2.10.8+zorin2/app/core/gimppalette-import.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppalette-import.c 2019-01-03 14:13:22.000000000 +0000 @@ -18,7 +18,6 @@ #include "config.h" #include -#define GEGL_ITERATOR2_API #include #include diff -Nru gimp-2.10.8+zorin2/app/core/gimppalettemru.c gimp-2.10.14+om/app/core/gimppalettemru.c --- gimp-2.10.8+zorin2/app/core/gimppalettemru.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppalettemru.c 2019-10-26 18:49:18.000000000 +0000 @@ -34,6 +34,9 @@ #include "gimp-intl.h" +#define MAX_N_COLORS 256 +#define RGBA_EPSILON 1e-4 + enum { COLOR_HISTORY = 1 @@ -114,10 +117,13 @@ GimpRGB color; if (! gimp_scanner_parse_color (scanner, &color)) - goto error; + goto end; gimp_palette_add_entry (palette, -1, _("History Color"), &color); + + if (gimp_palette_get_n_colors (palette) == MAX_N_COLORS) + goto end; } } token = G_TOKEN_RIGHT_PAREN; @@ -132,7 +138,7 @@ } } - error: + end: gimp_scanner_destroy (scanner); } @@ -165,14 +171,10 @@ GimpPaletteEntry *entry = list->data; gchar buf[4][G_ASCII_DTOSTR_BUF_SIZE]; - g_ascii_formatd (buf[0], - G_ASCII_DTOSTR_BUF_SIZE, "%f", entry->color.r); - g_ascii_formatd (buf[1], - G_ASCII_DTOSTR_BUF_SIZE, "%f", entry->color.g); - g_ascii_formatd (buf[2], - G_ASCII_DTOSTR_BUF_SIZE, "%f", entry->color.b); - g_ascii_formatd (buf[3], - G_ASCII_DTOSTR_BUF_SIZE, "%f", entry->color.a); + g_ascii_dtostr (buf[0], G_ASCII_DTOSTR_BUF_SIZE, entry->color.r); + g_ascii_dtostr (buf[1], G_ASCII_DTOSTR_BUF_SIZE, entry->color.g); + g_ascii_dtostr (buf[2], G_ASCII_DTOSTR_BUF_SIZE, entry->color.b); + g_ascii_dtostr (buf[3], G_ASCII_DTOSTR_BUF_SIZE, entry->color.a); gimp_config_writer_open (writer, "color-rgba"); gimp_config_writer_printf (writer, "%s %s %s %s", @@ -189,9 +191,8 @@ gimp_palette_mru_add (GimpPaletteMru *mru, const GimpRGB *color) { - GimpPalette *palette; - GimpPaletteEntry *found = NULL; - GList *list; + GimpPalette *palette; + GList *list; g_return_if_fail (GIMP_IS_PALETTE_MRU (mru)); g_return_if_fail (color != NULL); @@ -205,52 +206,25 @@ { GimpPaletteEntry *entry = list->data; - if (gimp_rgba_distance (&entry->color, color) < 0.0001) - { - found = entry; - - goto doit; - } - } - - /* if not, are there two equal colors? */ - if (! found) - { - for (list = gimp_palette_get_colors (palette); - list; - list = g_list_next (list)) + if (gimp_rgba_distance (&entry->color, color) < RGBA_EPSILON) { - GimpPaletteEntry *entry = list->data; - GList *list2; + gimp_palette_move_entry (palette, entry, 0); - for (list2 = g_list_next (list); list2; list2 = g_list_next (list2)) - { - GimpPaletteEntry *entry2 = list2->data; + /* Even though they are nearly the same color, let's make them + * exactly equal. + */ + gimp_palette_set_entry_color (palette, 0, color); - if (gimp_rgba_distance (&entry->color, - &entry2->color) < 0.0001) - { - found = entry2; - - goto doit; - } - } + return; } } - doit: - - if (found) + if (gimp_palette_get_n_colors (palette) == MAX_N_COLORS) { - gimp_palette_move_entry (palette, found, 0); - /* Even though they are nearly the same color, let's make them exactly - * equal. */ - gimp_palette_set_entry_color (palette, - 0, - color); - } - else - { - gimp_palette_add_entry (palette, 0, _("History Color"), color); + gimp_palette_delete_entry (palette, + gimp_palette_get_entry (palette, + MAX_N_COLORS - 1)); } + + gimp_palette_add_entry (palette, 0, _("History Color"), color); } diff -Nru gimp-2.10.8+zorin2/app/core/gimp-parallel.cc gimp-2.10.14+om/app/core/gimp-parallel.cc --- gimp-2.10.8+zorin2/app/core/gimp-parallel.cc 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-parallel.cc 2019-10-26 18:49:18.000000000 +0000 @@ -45,9 +45,8 @@ #include "gimpcancelable.h" -#define GIMP_PARALLEL_MAX_THREADS 64 +#define GIMP_PARALLEL_MAX_THREADS 64 #define GIMP_PARALLEL_RUN_ASYNC_MAX_THREADS 1 -#define GIMP_PARALLEL_DISTRIBUTE_MAX_THREADS GIMP_PARALLEL_MAX_THREADS typedef struct @@ -68,62 +67,33 @@ GimpAsync *current_async; } GimpParallelRunAsyncThread; -typedef struct -{ - GimpParallelDistributeFunc func; - gint n; - gpointer user_data; -} GimpParallelDistributeTask; - -typedef struct -{ - GThread *thread; - GMutex mutex; - GCond cond; - - gboolean quit; - - GimpParallelDistributeTask *volatile task; - volatile gint i; -} GimpParallelDistributeThread; - /* local function prototypes */ -static void gimp_parallel_notify_num_processors (GimpGeglConfig *config); - -static void gimp_parallel_set_n_threads (gint n_threads, - gboolean finish_tasks); +static void gimp_parallel_notify_num_processors (GimpGeglConfig *config); -static void gimp_parallel_run_async_set_n_threads (gint n_threads, - gboolean finish_tasks); -static gpointer gimp_parallel_run_async_thread_func (GimpParallelRunAsyncThread *thread); -static void gimp_parallel_run_async_enqueue_task (GimpParallelRunAsyncTask *task); -static GimpParallelRunAsyncTask * gimp_parallel_run_async_dequeue_task (void); -static gboolean gimp_parallel_run_async_execute_task (GimpParallelRunAsyncTask *task); -static void gimp_parallel_run_async_abort_task (GimpParallelRunAsyncTask *task); -static void gimp_parallel_run_async_cancel (GimpAsync *async); +static void gimp_parallel_set_n_threads (gint n_threads, + gboolean finish_tasks); -static void gimp_parallel_distribute_set_n_threads (gint n_threads); -static gpointer gimp_parallel_distribute_thread_func (GimpParallelDistributeThread *thread); +static void gimp_parallel_run_async_set_n_threads (gint n_threads, + gboolean finish_tasks); +static gpointer gimp_parallel_run_async_thread_func (GimpParallelRunAsyncThread *thread); +static void gimp_parallel_run_async_enqueue_task (GimpParallelRunAsyncTask *task); +static GimpParallelRunAsyncTask * gimp_parallel_run_async_dequeue_task (void); +static gboolean gimp_parallel_run_async_execute_task (GimpParallelRunAsyncTask *task); +static void gimp_parallel_run_async_abort_task (GimpParallelRunAsyncTask *task); +static void gimp_parallel_run_async_cancel (GimpAsync *async); +static void gimp_parallel_run_async_waiting (GimpAsync *async); /* local variables */ -static gint gimp_parallel_run_async_n_threads = 0; -static GimpParallelRunAsyncThread gimp_parallel_run_async_threads[GIMP_PARALLEL_RUN_ASYNC_MAX_THREADS]; +static gint gimp_parallel_run_async_n_threads = 0; +static GimpParallelRunAsyncThread gimp_parallel_run_async_threads[GIMP_PARALLEL_RUN_ASYNC_MAX_THREADS]; -static GMutex gimp_parallel_run_async_mutex; -static GCond gimp_parallel_run_async_cond; -static GQueue gimp_parallel_run_async_queue = G_QUEUE_INIT; - -static gint gimp_parallel_distribute_n_threads = 1; -static GimpParallelDistributeThread gimp_parallel_distribute_threads[GIMP_PARALLEL_DISTRIBUTE_MAX_THREADS - 1]; - -static GMutex gimp_parallel_distribute_completion_mutex; -static GCond gimp_parallel_distribute_completion_cond; -static volatile gint gimp_parallel_distribute_completion_counter; -static volatile gint gimp_parallel_distribute_busy; +static GMutex gimp_parallel_run_async_mutex; +static GCond gimp_parallel_run_async_cond; +static GQueue gimp_parallel_run_async_queue = G_QUEUE_INIT; /* public functions */ @@ -191,6 +161,9 @@ g_signal_connect_after (async, "cancel", G_CALLBACK (gimp_parallel_run_async_cancel), NULL); + g_signal_connect_after (async, "waiting", + G_CALLBACK (gimp_parallel_run_async_waiting), + NULL); g_mutex_lock (&gimp_parallel_run_async_mutex); @@ -212,6 +185,14 @@ gimp_parallel_run_async_independent (GimpParallelRunAsyncFunc func, gpointer user_data) { + return gimp_parallel_run_async_independent_full (0, func, user_data); +} + +GimpAsync * +gimp_parallel_run_async_independent_full (gint priority, + GimpParallelRunAsyncFunc func, + gpointer user_data) +{ GimpAsync *async; GimpParallelRunAsyncTask *task; GThread *thread; @@ -223,6 +204,7 @@ task = g_slice_new0 (GimpParallelRunAsyncTask); task->async = GIMP_ASYNC (g_object_ref (async)); + task->priority = priority; task->func = func; task->user_data = user_data; @@ -232,12 +214,22 @@ { GimpParallelRunAsyncTask *task = (GimpParallelRunAsyncTask *) data; - /* lower the thread's priority */ + /* adjust the thread's priority */ #if defined (G_OS_WIN32) - SetThreadPriority (GetCurrentThread (), THREAD_MODE_BACKGROUND_BEGIN); + if (task->priority < 0) + { + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_ABOVE_NORMAL); + } + else if (task->priority > 0) + { + SetThreadPriority (GetCurrentThread (), THREAD_MODE_BACKGROUND_BEGIN); + } #elif defined (HAVE_UNISTD_H) && defined (__gnu_linux__) - nice (+10) != -1; - /* ^-- avoid "unused result" warning */ + if (task->priority) + { + (nice (task->priority) != -1); + /* ^-- avoid "unused result" warning */ + } #endif while (gimp_parallel_run_async_execute_task (task)); @@ -257,154 +249,6 @@ return async; } -void -gimp_parallel_distribute (gint max_n, - GimpParallelDistributeFunc func, - gpointer user_data) -{ - GimpParallelDistributeTask task; - gint i; - - g_return_if_fail (func != NULL); - - if (max_n == 0) - return; - - if (max_n < 0) - max_n = gimp_parallel_distribute_n_threads; - else - max_n = MIN (max_n, gimp_parallel_distribute_n_threads); - - if (max_n == 1 || - ! g_atomic_int_compare_and_exchange (&gimp_parallel_distribute_busy, - 0, 1)) - { - func (0, 1, user_data); - - return; - } - - task.n = max_n; - task.func = func; - task.user_data = user_data; - - g_atomic_int_set (&gimp_parallel_distribute_completion_counter, task.n - 1); - - for (i = 0; i < task.n - 1; i++) - { - GimpParallelDistributeThread *thread = - &gimp_parallel_distribute_threads[i]; - - g_mutex_lock (&thread->mutex); - - thread->task = &task; - thread->i = i; - - g_cond_signal (&thread->cond); - - g_mutex_unlock (&thread->mutex); - } - - func (i, task.n, user_data); - - if (g_atomic_int_get (&gimp_parallel_distribute_completion_counter)) - { - g_mutex_lock (&gimp_parallel_distribute_completion_mutex); - - while (g_atomic_int_get (&gimp_parallel_distribute_completion_counter)) - { - g_cond_wait (&gimp_parallel_distribute_completion_cond, - &gimp_parallel_distribute_completion_mutex); - } - - g_mutex_unlock (&gimp_parallel_distribute_completion_mutex); - } - - g_atomic_int_set (&gimp_parallel_distribute_busy, 0); -} - -void -gimp_parallel_distribute_range (gsize size, - gsize min_sub_size, - GimpParallelDistributeRangeFunc func, - gpointer user_data) -{ - gsize n = size; - - g_return_if_fail (func != NULL); - - if (size == 0) - return; - - if (min_sub_size > 1) - n /= min_sub_size; - - n = CLAMP (n, 1, gimp_parallel_distribute_n_threads); - - gimp_parallel_distribute (n, [=] (gint i, gint n) - { - gsize offset; - gsize sub_size; - - offset = (2 * i * size + n) / (2 * n); - sub_size = (2 * (i + 1) * size + n) / (2 * n) - offset; - - func (offset, sub_size, user_data); - }); -} - -void -gimp_parallel_distribute_area (const GeglRectangle *area, - gsize min_sub_area, - GimpParallelDistributeAreaFunc func, - gpointer user_data) -{ - gsize n; - - g_return_if_fail (area != NULL); - g_return_if_fail (func != NULL); - - if (area->width <= 0 || area->height <= 0) - return; - - n = (gsize) area->width * (gsize) area->height; - - if (min_sub_area > 1) - n /= min_sub_area; - - n = CLAMP (n, 1, gimp_parallel_distribute_n_threads); - - gimp_parallel_distribute (n, [=] (gint i, gint n) - { - GeglRectangle sub_area; - - if (area->width <= area->height) - { - sub_area.x = area->x; - sub_area.width = area->width; - - sub_area.y = (2 * i * area->height + n) / (2 * n); - sub_area.height = (2 * (i + 1) * area->height + n) / (2 * n); - - sub_area.height -= sub_area.y; - sub_area.y += area->y; - } - else - { - sub_area.y = area->y; - sub_area.height = area->height; - - sub_area.x = (2 * i * area->width + n) / (2 * n); - sub_area.width = (2 * (i + 1) * area->width + n) / (2 * n); - - sub_area.width -= sub_area.x; - sub_area.x += area->x; - } - - func (&sub_area, user_data); - }); -} - /* private functions */ @@ -421,7 +265,6 @@ gboolean finish_tasks) { gimp_parallel_run_async_set_n_threads (n_threads, finish_tasks); - gimp_parallel_distribute_set_n_threads (n_threads); } static void @@ -679,95 +522,32 @@ } static void -gimp_parallel_distribute_set_n_threads (gint n_threads) +gimp_parallel_run_async_waiting (GimpAsync *async) { - gint i; - - while (! g_atomic_int_compare_and_exchange (&gimp_parallel_distribute_busy, - 0, 1)); - - n_threads = CLAMP (n_threads, 1, GIMP_PARALLEL_DISTRIBUTE_MAX_THREADS); - - if (n_threads > gimp_parallel_distribute_n_threads) /* need more threads */ - { - for (i = gimp_parallel_distribute_n_threads - 1; i < n_threads - 1; i++) - { - GimpParallelDistributeThread *thread = - &gimp_parallel_distribute_threads[i]; - - thread->quit = FALSE; - thread->task = NULL; - - thread->thread = g_thread_new ( - "worker", - (GThreadFunc) gimp_parallel_distribute_thread_func, - thread); - } - } - else if (n_threads < gimp_parallel_distribute_n_threads) /* need less threads */ - { - for (i = n_threads - 1; i < gimp_parallel_distribute_n_threads - 1; i++) - { - GimpParallelDistributeThread *thread = - &gimp_parallel_distribute_threads[i]; - - g_mutex_lock (&thread->mutex); - - thread->quit = TRUE; - g_cond_signal (&thread->cond); - - g_mutex_unlock (&thread->mutex); - } - - for (i = n_threads - 1; i < gimp_parallel_distribute_n_threads - 1; i++) - { - GimpParallelDistributeThread *thread = - &gimp_parallel_distribute_threads[i]; + GList *link; - g_thread_join (thread->thread); - } - } + link = (GList *) g_object_get_data (G_OBJECT (async), + "gimp-parallel-run-async-link"); - gimp_parallel_distribute_n_threads = n_threads; + if (! link) + return; - g_atomic_int_set (&gimp_parallel_distribute_busy, 0); -} + g_mutex_lock (&gimp_parallel_run_async_mutex); -static gpointer -gimp_parallel_distribute_thread_func (GimpParallelDistributeThread *thread) -{ - g_mutex_lock (&thread->mutex); + link = (GList *) g_object_get_data (G_OBJECT (async), + "gimp-parallel-run-async-link"); - while (TRUE) + if (link) { - if (thread->quit) - { - break; - } - else if (thread->task) - { - thread->task->func (thread->i, thread->task->n, - thread->task->user_data); - - if (g_atomic_int_dec_and_test ( - &gimp_parallel_distribute_completion_counter)) - { - g_mutex_lock (&gimp_parallel_distribute_completion_mutex); + GimpParallelRunAsyncTask *task = (GimpParallelRunAsyncTask *) link->data; - g_cond_signal (&gimp_parallel_distribute_completion_cond); + task->priority = G_MININT; - g_mutex_unlock (&gimp_parallel_distribute_completion_mutex); - } - - thread->task = NULL; - } - - g_cond_wait (&thread->cond, &thread->mutex); + g_queue_unlink (&gimp_parallel_run_async_queue, link); + g_queue_push_head_link (&gimp_parallel_run_async_queue, link); } - g_mutex_unlock (&thread->mutex); - - return NULL; + g_mutex_unlock (&gimp_parallel_run_async_mutex); } } /* extern "C" */ diff -Nru gimp-2.10.8+zorin2/app/core/gimp-parallel.h gimp-2.10.14+om/app/core/gimp-parallel.h --- gimp-2.10.8+zorin2/app/core/gimp-parallel.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-parallel.h 2019-04-07 11:38:14.000000000 +0000 @@ -22,42 +22,25 @@ #define __GIMP_PARALLEL_H__ -typedef void (* GimpParallelRunAsyncFunc) (GimpAsync *async, - gpointer user_data); +typedef void (* GimpParallelRunAsyncFunc) (GimpAsync *async, + gpointer user_data); + + +void gimp_parallel_init (Gimp *gimp); +void gimp_parallel_exit (Gimp *gimp); + +GimpAsync * gimp_parallel_run_async (GimpParallelRunAsyncFunc func, + gpointer user_data); +GimpAsync * gimp_parallel_run_async_full (gint priority, + GimpParallelRunAsyncFunc func, + gpointer user_data, + GDestroyNotify user_data_destroy_func); +GimpAsync * gimp_parallel_run_async_independent (GimpParallelRunAsyncFunc func, + gpointer user_data); +GimpAsync * gimp_parallel_run_async_independent_full (gint priority, + GimpParallelRunAsyncFunc func, + gpointer user_data); -typedef void (* GimpParallelDistributeFunc) (gint i, - gint n, - gpointer user_data); -typedef void (* GimpParallelDistributeRangeFunc) (gsize offset, - gsize size, - gpointer user_data); -typedef void (* GimpParallelDistributeAreaFunc) (const GeglRectangle *area, - gpointer user_data); - - -void gimp_parallel_init (Gimp *gimp); -void gimp_parallel_exit (Gimp *gimp); - -GimpAsync * gimp_parallel_run_async (GimpParallelRunAsyncFunc func, - gpointer user_data); -GimpAsync * gimp_parallel_run_async_full (gint priority, - GimpParallelRunAsyncFunc func, - gpointer user_data, - GDestroyNotify user_data_destroy_func); -GimpAsync * gimp_parallel_run_async_independent (GimpParallelRunAsyncFunc func, - gpointer user_data); - -void gimp_parallel_distribute (gint max_n, - GimpParallelDistributeFunc func, - gpointer user_data); -void gimp_parallel_distribute_range (gsize size, - gsize min_sub_size, - GimpParallelDistributeRangeFunc func, - gpointer user_data); -void gimp_parallel_distribute_area (const GeglRectangle *area, - gsize min_sub_area, - GimpParallelDistributeAreaFunc func, - gpointer user_data); #ifdef __cplusplus @@ -141,79 +124,33 @@ template inline GimpAsync * -gimp_parallel_run_async_independent (ParallelRunAsyncFunc func) +gimp_parallel_run_async_independent_full (gint priority, + ParallelRunAsyncFunc func) { ParallelRunAsyncFunc *func_copy = g_new (ParallelRunAsyncFunc, 1); new (func_copy) ParallelRunAsyncFunc (func); - return gimp_parallel_run_async_independent ([] (GimpAsync *async, - gpointer user_data) - { - ParallelRunAsyncFunc *func_copy = - (ParallelRunAsyncFunc *) user_data; - - (*func_copy) (async); - - func_copy->~ParallelRunAsyncFunc (); - g_free (func_copy); - }, - func_copy); -} - -template -inline void -gimp_parallel_distribute (gint max_n, - ParallelDistributeFunc func) -{ - gimp_parallel_distribute (max_n, - [] (gint i, - gint n, - gpointer user_data) - { - ParallelDistributeFunc func_copy ( - *(const ParallelDistributeFunc *) user_data); - - func_copy (i, n); - }, - &func); + return gimp_parallel_run_async_independent_full (priority, + [] (GimpAsync *async, + gpointer user_data) + { + ParallelRunAsyncFunc *func_copy = + (ParallelRunAsyncFunc *) user_data; + + (*func_copy) (async); + + func_copy->~ParallelRunAsyncFunc (); + g_free (func_copy); + }, + func_copy); } -template -inline void -gimp_parallel_distribute_range (gsize size, - gsize min_sub_size, - ParallelDistributeRangeFunc func) -{ - gimp_parallel_distribute_range (size, min_sub_size, - [] (gsize offset, - gsize size, - gpointer user_data) - { - ParallelDistributeRangeFunc func_copy ( - *(const ParallelDistributeRangeFunc *) user_data); - - func_copy (offset, size); - }, - &func); -} - -template -inline void -gimp_parallel_distribute_area (const GeglRectangle *area, - gsize min_sub_area, - ParallelDistributeAreaFunc func) +template +inline GimpAsync * +gimp_parallel_run_async_independent (ParallelRunAsyncFunc func) { - gimp_parallel_distribute_area (area, min_sub_area, - [] (const GeglRectangle *area, - gpointer user_data) - { - ParallelDistributeAreaFunc func_copy ( - *(const ParallelDistributeAreaFunc *) user_data); - - func_copy (area); - }, - &func); + return gimp_parallel_run_async_independent_full (0, func); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimppattern.c gimp-2.10.14+om/app/core/gimppattern.c --- gimp-2.10.8+zorin2/app/core/gimppattern.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppattern.c 2019-04-07 11:38:14.000000000 +0000 @@ -30,6 +30,7 @@ #include "gimppattern.h" #include "gimppattern-load.h" +#include "gimppattern-save.h" #include "gimptagged.h" #include "gimptempbuf.h" @@ -83,6 +84,7 @@ viewable_class->get_new_preview = gimp_pattern_get_new_preview; viewable_class->get_description = gimp_pattern_get_description; + data_class->save = gimp_pattern_save; data_class->get_extension = gimp_pattern_get_extension; data_class->copy = gimp_pattern_copy; } @@ -193,8 +195,7 @@ GimpPattern *pattern = GIMP_PATTERN (data); GimpPattern *src_pattern = GIMP_PATTERN (src_data); - gimp_temp_buf_unref (pattern->mask); - + g_clear_pointer (&pattern->mask, gimp_temp_buf_unref); pattern->mask = gimp_temp_buf_copy (src_pattern->mask); gimp_data_dirty (data); diff -Nru gimp-2.10.8+zorin2/app/core/gimppatternclipboard.c gimp-2.10.14+om/app/core/gimppatternclipboard.c --- gimp-2.10.8+zorin2/app/core/gimppatternclipboard.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppatternclipboard.c 2019-04-07 11:38:14.000000000 +0000 @@ -55,9 +55,7 @@ guint property_id, GValue *value, GParamSpec *pspec); -#if 0 static GimpData * gimp_pattern_clipboard_duplicate (GimpData *data); -#endif static void gimp_pattern_clipboard_changed (Gimp *gimp, GimpPattern *pattern); @@ -72,17 +70,13 @@ gimp_pattern_clipboard_class_init (GimpPatternClipboardClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); -#if 0 GimpDataClass *data_class = GIMP_DATA_CLASS (klass); -#endif object_class->constructed = gimp_pattern_clipboard_constructed; object_class->set_property = gimp_pattern_clipboard_set_property; object_class->get_property = gimp_pattern_clipboard_get_property; -#if 0 data_class->duplicate = gimp_pattern_clipboard_duplicate; -#endif g_object_class_install_property (object_class, PROP_GIMP, g_param_spec_object ("gimp", NULL, NULL, @@ -150,15 +144,15 @@ } } -#if 0 static GimpData * gimp_pattern_clipboard_duplicate (GimpData *data) { - GimpPatternClipboard *pattern = GIMP_PATTERN_CLIPBOARD (data); + GimpData *new = g_object_new (GIMP_TYPE_PATTERN, NULL); - return gimp_pattern_clipboard_new (pattern->gimp); + gimp_data_copy (new, data); + + return new; } -#endif GimpData * gimp_pattern_clipboard_new (Gimp *gimp) diff -Nru gimp-2.10.8+zorin2/app/core/gimppattern-header.h gimp-2.10.14+om/app/core/gimppattern-header.h --- gimp-2.10.8+zorin2/app/core/gimppattern-header.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppattern-header.h 2019-06-12 16:43:38.000000000 +0000 @@ -19,11 +19,10 @@ #define __GIMP_PATTERN_HEADER_H__ -#define GIMP_PATTERN_FILE_VERSION 1 -#define GIMP_PATTERN_MAGIC (('G' << 24) + ('P' << 16) + \ - ('A' << 8) + ('T' << 0)) -#define GIMP_PATTERN_MAX_SIZE 10000 /* Max size in either dimension in px */ -#define GIMP_PATTERN_MAX_NAME 256 /* Max length of the pattern's name */ +#define GIMP_PATTERN_MAGIC (('G' << 24) + ('P' << 16) + \ + ('A' << 8) + ('T' << 0)) +#define GIMP_PATTERN_MAX_SIZE 10000 /* Max size in either dimension in px */ +#define GIMP_PATTERN_MAX_NAME 256 /* Max length of the pattern's name */ /* All field entries are MSB */ @@ -40,9 +39,10 @@ guint32 magic_number; /* GIMP pattern magic number */ }; -/* In a pattern file, next comes the pattern name, null-terminated. After that - * comes the pattern data--width * height * bytes bytes of it... +/* In a pattern file, next comes the pattern name, null-terminated. + * After that comes the pattern data -- width * height * bytes bytes + * of it... */ -#endif /* __GIMP_PATTERN_HEADER_H__ */ +#endif /* __GIMP_PATTERN_HEADER_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimppattern-save.c gimp-2.10.14+om/app/core/gimppattern-save.c --- gimp-2.10.8+zorin2/app/core/gimppattern-save.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppattern-save.c 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,76 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "gimppattern.h" +#include "gimppattern-header.h" +#include "gimppattern-save.h" +#include "gimptempbuf.h" + + +gboolean +gimp_pattern_save (GimpData *data, + GOutputStream *output, + GError **error) +{ + GimpPattern *pattern = GIMP_PATTERN (data); + GimpTempBuf *mask = gimp_pattern_get_mask (pattern); + const Babl *format = gimp_temp_buf_get_format (mask); + GimpPatternHeader header; + const gchar *name; + gint width; + gint height; + + name = gimp_object_get_name (pattern); + width = gimp_temp_buf_get_width (mask); + height = gimp_temp_buf_get_height (mask); + + header.header_size = g_htonl (sizeof (GimpPatternHeader) + + strlen (name) + 1); + header.version = g_htonl (1); + header.width = g_htonl (width); + header.height = g_htonl (height); + header.bytes = g_htonl (babl_format_get_bytes_per_pixel (format)); + header.magic_number = g_htonl (GIMP_PATTERN_MAGIC); + + if (! g_output_stream_write_all (output, &header, sizeof (header), + NULL, NULL, error)) + { + return FALSE; + } + + if (! g_output_stream_write_all (output, name, strlen (name) + 1, + NULL, NULL, error)) + { + return FALSE; + } + + if (! g_output_stream_write_all (output, + gimp_temp_buf_get_data (mask), + gimp_temp_buf_get_data_size (mask), + NULL, NULL, error)) + { + return FALSE; + } + + return TRUE; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimppattern-save.h gimp-2.10.14+om/app/core/gimppattern-save.h --- gimp-2.10.8+zorin2/app/core/gimppattern-save.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppattern-save.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,28 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_PATTERN_SAVE_H__ +#define __GIMP_PATTERN_SAVE_H__ + + +/* don't call this function directly, use gimp_data_save() instead */ +gboolean gimp_pattern_save (GimpData *data, + GOutputStream *output, + GError **error); + + +#endif /* __GIMP_PATTERN_SAVE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.c gimp-2.10.14+om/app/core/gimppickable-contiguous-region.c --- gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppickable-contiguous-region.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,698 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include - -#include -#define GEGL_ITERATOR2_API -#include -#include - -#include "libgimpcolor/gimpcolor.h" -#include "libgimpmath/gimpmath.h" - -#include "core-types.h" - -#include "gegl/gimp-babl.h" - -#include "gimp-utils.h" /* GIMP_TIMER */ -#include "gimppickable.h" -#include "gimppickable-contiguous-region.h" - - -/* local function prototypes */ - -static const Babl * choose_format (GeglBuffer *buffer, - GimpSelectCriterion select_criterion, - gint *n_components, - gboolean *has_alpha); -static gfloat pixel_difference (const gfloat *col1, - const gfloat *col2, - gboolean antialias, - gfloat threshold, - gint n_components, - gboolean has_alpha, - gboolean select_transparent, - GimpSelectCriterion select_criterion); -static void push_segment (GQueue *segment_queue, - gint y, - gint old_y, - gint start, - gint end, - gint new_y, - gint new_start, - gint new_end); -static void pop_segment (GQueue *segment_queue, - gint *y, - gint *old_y, - gint *start, - gint *end); -static gboolean find_contiguous_segment (const gfloat *col, - GeglBuffer *src_buffer, - GeglSampler *src_sampler, - GeglBuffer *mask_buffer, - const Babl *src_format, - const Babl *mask_format, - gint n_components, - gboolean has_alpha, - gint width, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean antialias, - gfloat threshold, - gint initial_x, - gint initial_y, - gint *start, - gint *end, - gfloat *row); -static void find_contiguous_region (GeglBuffer *src_buffer, - GeglBuffer *mask_buffer, - const Babl *format, - gint n_components, - gboolean has_alpha, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean antialias, - gfloat threshold, - gboolean diagonal_neighbors, - gint x, - gint y, - const gfloat *col); - - -/* public functions */ - -GeglBuffer * -gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, - gboolean antialias, - gfloat threshold, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean diagonal_neighbors, - gint x, - gint y) -{ - GeglBuffer *src_buffer; - GeglBuffer *mask_buffer; - const Babl *format; - GeglRectangle extent; - gint n_components; - gboolean has_alpha; - gfloat start_col[MAX_CHANNELS]; - - g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); - - gimp_pickable_flush (pickable); - - src_buffer = gimp_pickable_get_buffer (pickable); - - format = choose_format (src_buffer, select_criterion, - &n_components, &has_alpha); - - gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format, - GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); - - if (has_alpha) - { - if (select_transparent) - { - /* don't select transparent regions if the start pixel isn't - * fully transparent - */ - if (start_col[n_components - 1] > 0) - select_transparent = FALSE; - } - } - else - { - select_transparent = FALSE; - } - - extent = *gegl_buffer_get_extent (src_buffer); - - mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float")); - - if (x >= extent.x && x < (extent.x + extent.width) && - y >= extent.y && y < (extent.y + extent.height)) - { - GIMP_TIMER_START(); - - find_contiguous_region (src_buffer, mask_buffer, - format, n_components, has_alpha, - select_transparent, select_criterion, - antialias, threshold, diagonal_neighbors, - x, y, start_col); - - GIMP_TIMER_END("foo"); - } - - return mask_buffer; -} - -GeglBuffer * -gimp_pickable_contiguous_region_by_color (GimpPickable *pickable, - gboolean antialias, - gfloat threshold, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - const GimpRGB *color) -{ - /* Scan over the pickable's active layer, finding pixels within the - * specified threshold from the given R, G, & B values. If - * antialiasing is on, use the same antialiasing scheme as in - * fuzzy_select. Modify the pickable's mask to reflect the - * additional selection - */ - GeglBufferIterator *iter; - GeglBuffer *src_buffer; - GeglBuffer *mask_buffer; - const Babl *format; - gint n_components; - gboolean has_alpha; - gfloat start_col[MAX_CHANNELS]; - - g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); - g_return_val_if_fail (color != NULL, NULL); - - gimp_pickable_flush (pickable); - - src_buffer = gimp_pickable_get_buffer (pickable); - - format = choose_format (src_buffer, select_criterion, - &n_components, &has_alpha); - - gimp_rgba_get_pixel (color, format, start_col); - - if (has_alpha) - { - if (select_transparent) - { - /* don't select transparency if "color" isn't fully transparent - */ - if (start_col[n_components - 1] > 0.0) - select_transparent = FALSE; - } - } - else - { - select_transparent = FALSE; - } - - mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), - babl_format ("Y float")); - - iter = gegl_buffer_iterator_new (src_buffer, - NULL, 0, format, - GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2); - - gegl_buffer_iterator_add (iter, mask_buffer, - NULL, 0, babl_format ("Y float"), - GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); - - while (gegl_buffer_iterator_next (iter)) - { - const gfloat *src = iter->items[0].data; - gfloat *dest = iter->items[1].data; - gint count = iter->length; - - while (count--) - { - /* Find how closely the colors match */ - *dest = pixel_difference (start_col, src, - antialias, - threshold, - n_components, - has_alpha, - select_transparent, - select_criterion); - - src += n_components; - dest += 1; - } - } - - return mask_buffer; -} - - -/* private functions */ - -static const Babl * -choose_format (GeglBuffer *buffer, - GimpSelectCriterion select_criterion, - gint *n_components, - gboolean *has_alpha) -{ - const Babl *format = gegl_buffer_get_format (buffer); - - *has_alpha = babl_format_has_alpha (format); - - switch (select_criterion) - { - case GIMP_SELECT_CRITERION_COMPOSITE: - if (babl_format_is_palette (format)) - format = babl_format ("R'G'B'A float"); - else - format = gimp_babl_format (gimp_babl_format_get_base_type (format), - GIMP_PRECISION_FLOAT_GAMMA, - *has_alpha); - break; - - case GIMP_SELECT_CRITERION_R: - case GIMP_SELECT_CRITERION_G: - case GIMP_SELECT_CRITERION_B: - case GIMP_SELECT_CRITERION_A: - format = babl_format ("R'G'B'A float"); - break; - - case GIMP_SELECT_CRITERION_H: - case GIMP_SELECT_CRITERION_S: - case GIMP_SELECT_CRITERION_V: - format = babl_format ("HSVA float"); - break; - - case GIMP_SELECT_CRITERION_LCH_L: - format = babl_format ("CIE L alpha float"); - break; - - case GIMP_SELECT_CRITERION_LCH_C: - case GIMP_SELECT_CRITERION_LCH_H: - format = babl_format ("CIE LCH(ab) alpha float"); - break; - - default: - g_return_val_if_reached (NULL); - break; - } - - *n_components = babl_format_get_n_components (format); - - return format; -} - -static gfloat -pixel_difference (const gfloat *col1, - const gfloat *col2, - gboolean antialias, - gfloat threshold, - gint n_components, - gboolean has_alpha, - gboolean select_transparent, - GimpSelectCriterion select_criterion) -{ - gfloat max = 0.0; - - /* if there is an alpha channel, never select transparent regions */ - if (! select_transparent && has_alpha && col2[n_components - 1] == 0.0) - return 0.0; - - if (select_transparent && has_alpha) - { - max = fabs (col1[n_components - 1] - col2[n_components - 1]); - } - else - { - gfloat diff; - gint b; - - if (has_alpha) - n_components--; - - switch (select_criterion) - { - case GIMP_SELECT_CRITERION_COMPOSITE: - for (b = 0; b < n_components; b++) - { - diff = fabs (col1[b] - col2[b]); - if (diff > max) - max = diff; - } - break; - - case GIMP_SELECT_CRITERION_R: - max = fabs (col1[0] - col2[0]); - break; - - case GIMP_SELECT_CRITERION_G: - max = fabs (col1[1] - col2[1]); - break; - - case GIMP_SELECT_CRITERION_B: - max = fabs (col1[2] - col2[2]); - break; - - case GIMP_SELECT_CRITERION_A: - max = fabs (col1[3] - col2[3]); - break; - - case GIMP_SELECT_CRITERION_H: - max = fabs (col1[0] - col2[0]); - max = MIN (max, 1.0 - max); - break; - - case GIMP_SELECT_CRITERION_S: - max = fabs (col1[1] - col2[1]); - break; - - case GIMP_SELECT_CRITERION_V: - max = fabs (col1[2] - col2[2]); - break; - - case GIMP_SELECT_CRITERION_LCH_L: - max = fabs (col1[0] - col2[0]) / 100.0; - break; - - case GIMP_SELECT_CRITERION_LCH_C: - max = fabs (col1[1] - col2[1]) / 100.0; - break; - - case GIMP_SELECT_CRITERION_LCH_H: - max = fabs (col1[2] - col2[2]) / 360.0; - max = MIN (max, 1.0 - max); - break; - } - } - - if (antialias && threshold > 0.0) - { - gfloat aa = 1.5 - (max / threshold); - - if (aa <= 0.0) - return 0.0; - else if (aa < 0.5) - return aa * 2.0; - else - return 1.0; - } - else - { - if (max > threshold) - return 0.0; - else - return 1.0; - } -} - -static void -push_segment (GQueue *segment_queue, - gint y, - gint old_y, - gint start, - gint end, - gint new_y, - gint new_start, - gint new_end) -{ - /* To avoid excessive memory allocation (y, old_y, start, end) tuples are - * stored in interleaved format: - * - * [y1] [old_y1] [start1] [end1] [y2] [old_y2] [start2] [end2] - */ - - if (new_y != old_y) - { - /* If the new segment's y-coordinate is different than the old (source) - * segment's y-coordinate, push the entire segment. - */ - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_start)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_end)); - } - else - { - /* Otherwise, only push the set-difference between the new segment and - * the source segment (since we've already scanned the source segment.) - * Note that the `+ 1` and `- 1` terms of the end/start coordinates below - * are only necessary when `diagonal_neighbors` is on (and otherwise make - * the segments slightly larger than necessary), but, meh... - */ - if (new_start < start) - { - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_start)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (start + 1)); - } - - if (new_end > end) - { - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (end - 1)); - g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_end)); - } - } -} - -static void -pop_segment (GQueue *segment_queue, - gint *y, - gint *old_y, - gint *start, - gint *end) -{ - *y = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); - *old_y = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); - *start = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); - *end = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); -} - -/* #define FETCH_ROW 1 */ - -static gboolean -find_contiguous_segment (const gfloat *col, - GeglBuffer *src_buffer, - GeglSampler *src_sampler, - GeglBuffer *mask_buffer, - const Babl *src_format, - const Babl *mask_format, - gint n_components, - gboolean has_alpha, - gint width, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean antialias, - gfloat threshold, - gint initial_x, - gint initial_y, - gint *start, - gint *end, - gfloat *row) -{ - gfloat *s; - gfloat mask_row[width]; - gfloat diff; - -#ifdef FETCH_ROW - gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, initial_y, width, 1), 1.0, - src_format, - row, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); - s = row + initial_x * n_components; -#else - s = g_alloca (n_components * sizeof (gfloat)); - - gegl_sampler_get (src_sampler, - initial_x, initial_y, NULL, s, GEGL_ABYSS_NONE); -#endif - - diff = pixel_difference (col, s, antialias, threshold, - n_components, has_alpha, select_transparent, - select_criterion); - - /* check the starting pixel */ - if (! diff) - return FALSE; - - mask_row[initial_x] = diff; - - *start = initial_x - 1; -#ifdef FETCH_ROW - s = row + *start * n_components; -#endif - - while (*start >= 0) - { -#ifndef FETCH_ROW - gegl_sampler_get (src_sampler, - *start, initial_y, NULL, s, GEGL_ABYSS_NONE); -#endif - - diff = pixel_difference (col, s, antialias, threshold, - n_components, has_alpha, select_transparent, - select_criterion); - if (diff == 0.0) - break; - - mask_row[*start] = diff; - - (*start)--; -#ifdef FETCH_ROW - s -= n_components; -#endif - } - - *end = initial_x + 1; -#ifdef FETCH_ROW - s = row + *end * n_components; -#endif - - while (*end < width) - { -#ifndef FETCH_ROW - gegl_sampler_get (src_sampler, - *end, initial_y, NULL, s, GEGL_ABYSS_NONE); -#endif - - diff = pixel_difference (col, s, antialias, threshold, - n_components, has_alpha, select_transparent, - select_criterion); - if (diff == 0.0) - break; - - mask_row[*end] = diff; - - (*end)++; -#ifdef FETCH_ROW - s += n_components; -#endif - } - - gegl_buffer_set (mask_buffer, GEGL_RECTANGLE (*start + 1, initial_y, - *end - *start - 1, 1), - 0, mask_format, &mask_row[*start + 1], - GEGL_AUTO_ROWSTRIDE); - - return TRUE; -} - -static void -find_contiguous_region (GeglBuffer *src_buffer, - GeglBuffer *mask_buffer, - const Babl *format, - gint n_components, - gboolean has_alpha, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean antialias, - gfloat threshold, - gboolean diagonal_neighbors, - gint x, - gint y, - const gfloat *col) -{ - const Babl *mask_format = babl_format ("Y float"); - GeglSampler *src_sampler; - gint old_y; - gint start, end; - gint new_start, new_end; - GQueue *segment_queue; - gfloat *row = NULL; - -#ifdef FETCH_ROW - row = g_new (gfloat, gegl_buffer_get_width (src_buffer) * n_components); -#endif - - src_sampler = gegl_buffer_sampler_new (src_buffer, - format, GEGL_SAMPLER_NEAREST); - - segment_queue = g_queue_new (); - - push_segment (segment_queue, - y, /* dummy values: */ -1, 0, 0, - y, x - 1, x + 1); - - do - { - pop_segment (segment_queue, - &y, &old_y, &start, &end); - - for (x = start + 1; x < end; x++) - { - gfloat val; - - gegl_buffer_get (mask_buffer, GEGL_RECTANGLE (x, y, 1, 1), 1.0, - mask_format, &val, GEGL_AUTO_ROWSTRIDE, - GEGL_ABYSS_NONE); - - if (val != 0.0) - { - /* If the current pixel is selected, then we've already visited - * the next pixel. (Note that we assume that the maximal image - * width is sufficiently low that `x` won't overflow.) - */ - x++; - continue; - } - - if (! find_contiguous_segment (col, - src_buffer, src_sampler, mask_buffer, - format, mask_format, - n_components, - has_alpha, - gegl_buffer_get_width (src_buffer), - select_transparent, select_criterion, - antialias, threshold, x, y, - &new_start, &new_end, - row)) - continue; - - /* We can skip directly to `new_end + 1` on the next iteration, since - * we've just selected all pixels in the range `[x, new_end)`, and - * the pixel at `new_end` is above threshold. (Note that we assume - * that the maximal image width is sufficiently low that `x` won't - * overflow.) - */ - x = new_end; - - if (diagonal_neighbors) - { - if (new_start >= 0) - new_start--; - - if (new_end < gegl_buffer_get_width (src_buffer)) - new_end++; - } - - if (y + 1 < gegl_buffer_get_height (src_buffer)) - { - push_segment (segment_queue, - y, old_y, start, end, - y + 1, new_start, new_end); - } - - if (y - 1 >= 0) - { - push_segment (segment_queue, - y, old_y, start, end, - y - 1, new_start, new_end); - } - - } - } - while (! g_queue_is_empty (segment_queue)); - - g_queue_free (segment_queue); - - g_object_unref (src_sampler); - -#ifdef FETCH_ROW - g_free (row); -#endif -} diff -Nru gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.cc gimp-2.10.14+om/app/core/gimppickable-contiguous-region.cc --- gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.cc 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppickable-contiguous-region.cc 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,1123 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpmath/gimpmath.h" + +extern "C" +{ + +#include "core-types.h" + +#include "gegl/gimp-babl.h" + +#include "gimp-parallel.h" +#include "gimp-utils.h" /* GIMP_TIMER */ +#include "gimpasync.h" +#include "gimplineart.h" +#include "gimppickable.h" +#include "gimppickable-contiguous-region.h" + + +#define EPSILON 1e-6 + +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) + + +typedef struct +{ + gint x; + gint y; + gint level; +} BorderPixel; + + +/* local function prototypes */ + +static const Babl * choose_format (GeglBuffer *buffer, + GimpSelectCriterion select_criterion, + gint *n_components, + gboolean *has_alpha); +static gfloat pixel_difference (const gfloat *col1, + const gfloat *col2, + gboolean antialias, + gfloat threshold, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion); +static void push_segment (GQueue *segment_queue, + gint y, + gint old_y, + gint start, + gint end, + gint new_y, + gint new_start, + gint new_end); +static void pop_segment (GQueue *segment_queue, + gint *y, + gint *old_y, + gint *start, + gint *end); +static gboolean find_contiguous_segment (const gfloat *col, + GeglBuffer *src_buffer, + GeglSampler *src_sampler, + const GeglRectangle *src_extent, + GeglBuffer *mask_buffer, + const Babl *src_format, + const Babl *mask_format, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean antialias, + gfloat threshold, + gint initial_x, + gint initial_y, + gint *start, + gint *end, + gfloat *row); +static void find_contiguous_region (GeglBuffer *src_buffer, + GeglBuffer *mask_buffer, + const Babl *format, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean antialias, + gfloat threshold, + gboolean diagonal_neighbors, + gint x, + gint y, + const gfloat *col); + +static void line_art_queue_pixel (GQueue *queue, + gint x, + gint y, + gint level); + + +/* public functions */ + +GeglBuffer * +gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, + gboolean antialias, + gfloat threshold, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean diagonal_neighbors, + gint x, + gint y) +{ + GeglBuffer *src_buffer; + GeglBuffer *mask_buffer; + const Babl *format; + GeglRectangle extent; + gint n_components; + gboolean has_alpha; + gfloat start_col[MAX_CHANNELS]; + + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); + + gimp_pickable_flush (pickable); + src_buffer = gimp_pickable_get_buffer (pickable); + + format = choose_format (src_buffer, select_criterion, + &n_components, &has_alpha); + gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (has_alpha) + { + if (select_transparent) + { + /* don't select transparent regions if the start pixel isn't + * fully transparent + */ + if (start_col[n_components - 1] > 0) + select_transparent = FALSE; + } + } + else + { + select_transparent = FALSE; + } + + extent = *gegl_buffer_get_extent (src_buffer); + + mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float")); + + if (x >= extent.x && x < (extent.x + extent.width) && + y >= extent.y && y < (extent.y + extent.height)) + { + GIMP_TIMER_START(); + + find_contiguous_region (src_buffer, mask_buffer, + format, n_components, has_alpha, + select_transparent, select_criterion, + antialias, threshold, diagonal_neighbors, + x, y, start_col); + + GIMP_TIMER_END("foo"); + } + + return mask_buffer; +} + +GeglBuffer * +gimp_pickable_contiguous_region_by_color (GimpPickable *pickable, + gboolean antialias, + gfloat threshold, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + const GimpRGB *color) +{ + /* Scan over the pickable's active layer, finding pixels within the + * specified threshold from the given R, G, & B values. If + * antialiasing is on, use the same antialiasing scheme as in + * fuzzy_select. Modify the pickable's mask to reflect the + * additional selection + */ + GeglBuffer *src_buffer; + GeglBuffer *mask_buffer; + const Babl *format; + gint n_components; + gboolean has_alpha; + gfloat start_col[MAX_CHANNELS]; + + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); + g_return_val_if_fail (color != NULL, NULL); + + /* increase the threshold by EPSILON, to allow for conversion errors, + * especially when threshold == 0 (see issue #1554.) we need to do this + * here, but not in the other functions, since the input color gets converted + * to the format in which we perform the comparison through a different path + * than the pickable's pixels, which can introduce error. + */ + threshold += EPSILON; + + gimp_pickable_flush (pickable); + + src_buffer = gimp_pickable_get_buffer (pickable); + + format = choose_format (src_buffer, select_criterion, + &n_components, &has_alpha); + + gimp_rgba_get_pixel (color, format, start_col); + + if (has_alpha) + { + if (select_transparent) + { + /* don't select transparency if "color" isn't fully transparent + */ + if (start_col[n_components - 1] > 0.0) + select_transparent = FALSE; + } + } + else + { + select_transparent = FALSE; + } + + mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), + babl_format ("Y float")); + + gegl_parallel_distribute_area ( + gegl_buffer_get_extent (src_buffer), PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) + { + GeglBufferIterator *iter; + + iter = gegl_buffer_iterator_new (src_buffer, + area, 0, format, + GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 2); + + gegl_buffer_iterator_add (iter, mask_buffer, + area, 0, babl_format ("Y float"), + GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); + + while (gegl_buffer_iterator_next (iter)) + { + const gfloat *src = (const gfloat *) iter->items[0].data; + gfloat *dest = ( gfloat *) iter->items[1].data; + gint count = iter->length; + + while (count--) + { + /* Find how closely the colors match */ + *dest = pixel_difference (start_col, src, + antialias, + threshold, + n_components, + has_alpha, + select_transparent, + select_criterion); + + src += n_components; + dest += 1; + } + } + }); + + return mask_buffer; +} + +GeglBuffer * +gimp_pickable_contiguous_region_by_line_art (GimpPickable *pickable, + GimpLineArt *line_art, + gint x, + gint y) +{ + GeglBuffer *src_buffer; + GeglBuffer *mask_buffer; + const Babl *format = babl_format ("Y float"); + gfloat *distmap = NULL; + GeglRectangle extent; + gboolean free_line_art = FALSE; + gboolean filled = FALSE; + guchar start_col; + + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable) || GIMP_IS_LINE_ART (line_art), NULL); + + if (! line_art) + { + /* It is much better experience to pre-compute the line art, + * but it may not be always possible (for instance when + * selecting/filling through a PDB call). + */ + line_art = gimp_line_art_new (); + gimp_line_art_set_input (line_art, pickable); + free_line_art = TRUE; + } + + src_buffer = gimp_line_art_get (line_art, &distmap); + g_return_val_if_fail (src_buffer && distmap, NULL); + + gegl_buffer_sample (src_buffer, x, y, NULL, &start_col, NULL, + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + extent = *gegl_buffer_get_extent (src_buffer); + + mask_buffer = gegl_buffer_new (&extent, format); + + if (start_col) + { + if (start_col == 1) + { + /* As a special exception, if you fill over a line art pixel, only + * fill the pixel and exit + */ + gfloat col = 1.0; + + gegl_buffer_set (mask_buffer, GEGL_RECTANGLE (x, y, 1, 1), + 0, format, &col, GEGL_AUTO_ROWSTRIDE); + } + else /* start_col == 2 */ + { + /* If you fill over a closure pixel, let's fill on all sides + * of the start point. Otherwise we get a very weird result + * with only a single pixel filled in the middle of an empty + * region (since closure pixels are invisible by nature). + */ + gfloat col = 0.0; + + if (x - 1 >= extent.x && x - 1 < extent.x + extent.width && + y - 1 >= extent.y && y - 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x - 1, y - 1, &col); + if (x - 1 >= extent.x && x - 1 < extent.x + extent.width && + y >= extent.y && y < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x - 1, y, &col); + if (x - 1 >= extent.x && x - 1 < extent.x + extent.width && + y + 1 >= extent.y && y + 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x - 1, y + 1, &col); + if (x >= extent.x && x < extent.x + extent.width && + y - 1 >= extent.y && y - 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x, y - 1, &col); + if (x >= extent.x && x < extent.x + extent.width && + y + 1 >= extent.y && y + 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x, y + 1, &col); + if (x + 1 >= extent.x && x + 1 < extent.x + extent.width && + y - 1 >= extent.y && y - 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x + 1, y - 1, &col); + if (x + 1 >= extent.x && x + 1 < extent.x + extent.width && + y >= extent.y && y < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x + 1, y, &col); + if (x + 1 >= extent.x && x + 1 < extent.x + extent.width && + y + 1 >= extent.y && y + 1 < (extent.y + extent.height)) + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x + 1, y + 1, &col); + filled = TRUE; + } + } + else if (x >= extent.x && x < (extent.x + extent.width) && + y >= extent.y && y < (extent.y + extent.height)) + { + gfloat col = 0.0; + + find_contiguous_region (src_buffer, mask_buffer, + format, 1, FALSE, + FALSE, GIMP_SELECT_CRITERION_COMPOSITE, + FALSE, 0.0, FALSE, + x, y, &col); + filled = TRUE; + } + + if (filled) + { + GQueue *queue = g_queue_new (); + gfloat *mask; + gint width = gegl_buffer_get_width (src_buffer); + gint height = gegl_buffer_get_height (src_buffer); + gint line_art_max_grow; + gint nx, ny; + + GIMP_TIMER_START(); + /* The last step of the line art algorithm is to make sure that + * selections does not leave "holes" between its borders and the + * line arts, while not stepping over as well. + * I used to run the "gegl:watershed-transform" operation to flood + * the stroke pixels, but for such simple need, this simple code + * is so much faster while producing better results. + */ + mask = g_new (gfloat, width * height); + gegl_buffer_get (mask_buffer, NULL, 1.0, NULL, + mask, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + if (distmap[x + y * width] == 1.0) + { + if (x > 0) + { + nx = x - 1; + if (y > 0) + { + ny = y - 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + ny = y; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + if (y < height - 1) + { + ny = y + 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + } + if (x < width - 1) + { + nx = x + 1; + if (y > 0) + { + ny = y - 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + ny = y; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + if (y < height - 1) + { + ny = y + 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + } + nx = x; + if (y > 0) + { + ny = y - 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + if (y < height - 1) + { + ny = y + 1; + if (mask[nx + ny * width] != 0.0) + { + line_art_queue_pixel (queue, x, y, 1); + continue; + } + } + } + } + + g_object_get (line_art, + "max-grow", &line_art_max_grow, + NULL); + while (! g_queue_is_empty (queue)) + { + BorderPixel *c = (BorderPixel *) g_queue_pop_head (queue); + + if (mask[c->x + c->y * width] != 1.0) + { + mask[c->x + c->y * width] = 1.0; + if (c->level >= line_art_max_grow) + /* Do not overflood under line arts. */ + continue; + if (c->x > 0) + { + nx = c->x - 1; + if (c->y > 0) + { + ny = c->y - 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + ny = c->y; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + if (c->y < height - 1) + { + ny = c->y + 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + } + if (c->x < width - 1) + { + nx = c->x + 1; + if (c->y > 0) + { + ny = c->y - 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + ny = c->y; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + if (c->y < height - 1) + { + ny = c->y + 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + } + nx = c->x; + if (c->y > 0) + { + ny = c->y - 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + if (c->y < height - 1) + { + ny = c->y + 1; + if (mask[nx + ny * width] == 0.0 && + distmap[nx + ny * width] > distmap[c->x + c->y * width]) + line_art_queue_pixel (queue, nx, ny, c->level + 1); + } + } + g_free (c); + } + g_queue_free (queue); + gegl_buffer_set (mask_buffer, gegl_buffer_get_extent (mask_buffer), + 0, NULL, mask, GEGL_AUTO_ROWSTRIDE); + g_free (mask); + + GIMP_TIMER_END("watershed line art"); + } + if (free_line_art) + g_clear_object (&line_art); + + return mask_buffer; +} + +/* private functions */ + +static const Babl * +choose_format (GeglBuffer *buffer, + GimpSelectCriterion select_criterion, + gint *n_components, + gboolean *has_alpha) +{ + const Babl *format = gegl_buffer_get_format (buffer); + + *has_alpha = babl_format_has_alpha (format); + + switch (select_criterion) + { + case GIMP_SELECT_CRITERION_COMPOSITE: + if (babl_format_is_palette (format)) + format = babl_format ("R'G'B'A float"); + else + format = gimp_babl_format (gimp_babl_format_get_base_type (format), + GIMP_PRECISION_FLOAT_GAMMA, + *has_alpha); + break; + + case GIMP_SELECT_CRITERION_R: + case GIMP_SELECT_CRITERION_G: + case GIMP_SELECT_CRITERION_B: + case GIMP_SELECT_CRITERION_A: + format = babl_format ("R'G'B'A float"); + break; + + case GIMP_SELECT_CRITERION_H: + case GIMP_SELECT_CRITERION_S: + case GIMP_SELECT_CRITERION_V: + format = babl_format ("HSVA float"); + break; + + case GIMP_SELECT_CRITERION_LCH_L: + format = babl_format ("CIE L alpha float"); + break; + + case GIMP_SELECT_CRITERION_LCH_C: + case GIMP_SELECT_CRITERION_LCH_H: + format = babl_format ("CIE LCH(ab) alpha float"); + break; + + default: + g_return_val_if_reached (NULL); + break; + } + + *n_components = babl_format_get_n_components (format); + + return format; +} + +static gfloat +pixel_difference (const gfloat *col1, + const gfloat *col2, + gboolean antialias, + gfloat threshold, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion) +{ + gfloat max = 0.0; + + /* if there is an alpha channel, never select transparent regions */ + if (! select_transparent && has_alpha && col2[n_components - 1] == 0.0) + return 0.0; + + if (select_transparent && has_alpha) + { + max = fabs (col1[n_components - 1] - col2[n_components - 1]); + } + else + { + gfloat diff; + gint b; + + if (has_alpha) + n_components--; + + switch (select_criterion) + { + case GIMP_SELECT_CRITERION_COMPOSITE: + for (b = 0; b < n_components; b++) + { + diff = fabs (col1[b] - col2[b]); + if (diff > max) + max = diff; + } + break; + + case GIMP_SELECT_CRITERION_R: + max = fabs (col1[0] - col2[0]); + break; + + case GIMP_SELECT_CRITERION_G: + max = fabs (col1[1] - col2[1]); + break; + + case GIMP_SELECT_CRITERION_B: + max = fabs (col1[2] - col2[2]); + break; + + case GIMP_SELECT_CRITERION_A: + max = fabs (col1[3] - col2[3]); + break; + + case GIMP_SELECT_CRITERION_H: + if (col1[1] > EPSILON) + { + if (col2[1] > EPSILON) + { + max = fabs (col1[0] - col2[0]); + max = MIN (max, 1.0 - max); + } + else + { + /* "infinite" difference. anything >> 1 will do. */ + max = 10.0; + } + } + else + { + if (col2[1] > EPSILON) + { + /* "infinite" difference. anything >> 1 will do. */ + max = 10.0; + } + else + { + max = 0.0; + } + } + break; + + case GIMP_SELECT_CRITERION_S: + max = fabs (col1[1] - col2[1]); + break; + + case GIMP_SELECT_CRITERION_V: + max = fabs (col1[2] - col2[2]); + break; + + case GIMP_SELECT_CRITERION_LCH_L: + max = fabs (col1[0] - col2[0]) / 100.0; + break; + + case GIMP_SELECT_CRITERION_LCH_C: + max = fabs (col1[1] - col2[1]) / 100.0; + break; + + case GIMP_SELECT_CRITERION_LCH_H: + if (col1[1] > 100.0 * EPSILON) + { + if (col2[1] > 100.0 * EPSILON) + { + max = fabs (col1[2] - col2[2]) / 360.0; + max = MIN (max, 1.0 - max); + } + else + { + /* "infinite" difference. anything >> 1 will do. */ + max = 10.0; + } + } + else + { + if (col2[1] > 100.0 * EPSILON) + { + /* "infinite" difference. anything >> 1 will do. */ + max = 10.0; + } + else + { + max = 0.0; + } + } + break; + } + } + + if (antialias && threshold > 0.0) + { + gfloat aa = 1.5 - (max / threshold); + + if (aa <= 0.0) + return 0.0; + else if (aa < 0.5) + return aa * 2.0; + else + return 1.0; + } + else + { + if (max > threshold) + return 0.0; + else + return 1.0; + } +} + +static void +push_segment (GQueue *segment_queue, + gint y, + gint old_y, + gint start, + gint end, + gint new_y, + gint new_start, + gint new_end) +{ + /* To avoid excessive memory allocation (y, old_y, start, end) tuples are + * stored in interleaved format: + * + * [y1] [old_y1] [start1] [end1] [y2] [old_y2] [start2] [end2] + */ + + if (new_y != old_y) + { + /* If the new segment's y-coordinate is different than the old (source) + * segment's y-coordinate, push the entire segment. + */ + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_start)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_end)); + } + else + { + /* Otherwise, only push the set-difference between the new segment and + * the source segment (since we've already scanned the source segment.) + * Note that the `+ 1` and `- 1` terms of the end/start coordinates below + * are only necessary when `diagonal_neighbors` is on (and otherwise make + * the segments slightly larger than necessary), but, meh... + */ + if (new_start < start) + { + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_start)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (start + 1)); + } + + if (new_end > end) + { + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (y)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (end - 1)); + g_queue_push_tail (segment_queue, GINT_TO_POINTER (new_end)); + } + } +} + +static void +pop_segment (GQueue *segment_queue, + gint *y, + gint *old_y, + gint *start, + gint *end) +{ + *y = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); + *old_y = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); + *start = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); + *end = GPOINTER_TO_INT (g_queue_pop_head (segment_queue)); +} + +/* #define FETCH_ROW 1 */ + +static gboolean +find_contiguous_segment (const gfloat *col, + GeglBuffer *src_buffer, + GeglSampler *src_sampler, + const GeglRectangle *src_extent, + GeglBuffer *mask_buffer, + const Babl *src_format, + const Babl *mask_format, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean antialias, + gfloat threshold, + gint initial_x, + gint initial_y, + gint *start, + gint *end, + gfloat *row) +{ + gfloat *s; + gfloat mask_row_buf[src_extent->width]; + gfloat *mask_row = mask_row_buf - src_extent->x; + gfloat diff; + +#ifdef FETCH_ROW + gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, initial_y, width, 1), 1.0, + src_format, + row, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + s = row + initial_x * n_components; +#else + s = (gfloat *) g_alloca (n_components * sizeof (gfloat)); + + gegl_sampler_get (src_sampler, + initial_x, initial_y, NULL, s, GEGL_ABYSS_NONE); +#endif + + diff = pixel_difference (col, s, antialias, threshold, + n_components, has_alpha, select_transparent, + select_criterion); + + /* check the starting pixel */ + if (! diff) + return FALSE; + + mask_row[initial_x] = diff; + + *start = initial_x - 1; +#ifdef FETCH_ROW + s = row + *start * n_components; +#endif + + while (*start >= src_extent->x) + { +#ifndef FETCH_ROW + gegl_sampler_get (src_sampler, + *start, initial_y, NULL, s, GEGL_ABYSS_NONE); +#endif + + diff = pixel_difference (col, s, antialias, threshold, + n_components, has_alpha, select_transparent, + select_criterion); + if (diff == 0.0) + break; + + mask_row[*start] = diff; + + (*start)--; +#ifdef FETCH_ROW + s -= n_components; +#endif + } + + *end = initial_x + 1; +#ifdef FETCH_ROW + s = row + *end * n_components; +#endif + + while (*end < src_extent->x + src_extent->width) + { +#ifndef FETCH_ROW + gegl_sampler_get (src_sampler, + *end, initial_y, NULL, s, GEGL_ABYSS_NONE); +#endif + + diff = pixel_difference (col, s, antialias, threshold, + n_components, has_alpha, select_transparent, + select_criterion); + if (diff == 0.0) + break; + + mask_row[*end] = diff; + + (*end)++; +#ifdef FETCH_ROW + s += n_components; +#endif + } + + gegl_buffer_set (mask_buffer, GEGL_RECTANGLE (*start + 1, initial_y, + *end - *start - 1, 1), + 0, mask_format, &mask_row[*start + 1], + GEGL_AUTO_ROWSTRIDE); + + return TRUE; +} + +static void +find_contiguous_region (GeglBuffer *src_buffer, + GeglBuffer *mask_buffer, + const Babl *format, + gint n_components, + gboolean has_alpha, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean antialias, + gfloat threshold, + gboolean diagonal_neighbors, + gint x, + gint y, + const gfloat *col) +{ + const Babl *mask_format = babl_format ("Y float"); + GeglSampler *src_sampler; + const GeglRectangle *src_extent; + gint old_y; + gint start, end; + gint new_start, new_end; + GQueue *segment_queue; + gfloat *row = NULL; + + src_extent = gegl_buffer_get_extent (src_buffer); + +#ifdef FETCH_ROW + row = g_new (gfloat, src_extent->width * n_components); +#endif + + src_sampler = gegl_buffer_sampler_new (src_buffer, + format, GEGL_SAMPLER_NEAREST); + + segment_queue = g_queue_new (); + + push_segment (segment_queue, + y, /* dummy values: */ -1, 0, 0, + y, x - 1, x + 1); + + do + { + pop_segment (segment_queue, + &y, &old_y, &start, &end); + + for (x = start + 1; x < end; x++) + { + gfloat val; + + gegl_buffer_get (mask_buffer, GEGL_RECTANGLE (x, y, 1, 1), 1.0, + mask_format, &val, GEGL_AUTO_ROWSTRIDE, + GEGL_ABYSS_NONE); + + if (val != 0.0) + { + /* If the current pixel is selected, then we've already visited + * the next pixel. (Note that we assume that the maximal image + * width is sufficiently low that `x` won't overflow.) + */ + x++; + continue; + } + + if (! find_contiguous_segment (col, + src_buffer, src_sampler, src_extent, + mask_buffer, + format, mask_format, + n_components, + has_alpha, + select_transparent, select_criterion, + antialias, threshold, x, y, + &new_start, &new_end, + row)) + continue; + + /* We can skip directly to `new_end + 1` on the next iteration, since + * we've just selected all pixels in the range `[x, new_end)`, and + * the pixel at `new_end` is above threshold. (Note that we assume + * that the maximal image width is sufficiently low that `x` won't + * overflow.) + */ + x = new_end; + + if (diagonal_neighbors) + { + if (new_start >= src_extent->x) + new_start--; + + if (new_end < src_extent->x + src_extent->width) + new_end++; + } + + if (y + 1 < src_extent->y + src_extent->height) + { + push_segment (segment_queue, + y, old_y, start, end, + y + 1, new_start, new_end); + } + + if (y - 1 >= src_extent->y) + { + push_segment (segment_queue, + y, old_y, start, end, + y - 1, new_start, new_end); + } + + } + } + while (! g_queue_is_empty (segment_queue)); + + g_queue_free (segment_queue); + + g_object_unref (src_sampler); + +#ifdef FETCH_ROW + g_free (row); +#endif +} + +static void +line_art_queue_pixel (GQueue *queue, + gint x, + gint y, + gint level) +{ + BorderPixel *p = g_new (BorderPixel, 1); + + p->x = x; + p->y = y; + p->level = level; + + g_queue_push_head (queue, p); +} + +} /* extern "C" */ diff -Nru gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.h gimp-2.10.14+om/app/core/gimppickable-contiguous-region.h --- gimp-2.10.8+zorin2/app/core/gimppickable-contiguous-region.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimppickable-contiguous-region.h 2019-01-03 14:13:22.000000000 +0000 @@ -19,21 +19,25 @@ #define __GIMP_PICKABLE_CONTIGUOUS_REGION_H__ -GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, - gboolean antialias, - gfloat threshold, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - gboolean diagonal_neighbors, - gint x, - gint y); +GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, + gboolean antialias, + gfloat threshold, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + gboolean diagonal_neighbors, + gint x, + gint y); -GeglBuffer * gimp_pickable_contiguous_region_by_color (GimpPickable *pickable, - gboolean antialias, - gfloat threshold, - gboolean select_transparent, - GimpSelectCriterion select_criterion, - const GimpRGB *color); +GeglBuffer * gimp_pickable_contiguous_region_by_color (GimpPickable *pickable, + gboolean antialias, + gfloat threshold, + gboolean select_transparent, + GimpSelectCriterion select_criterion, + const GimpRGB *color); +GeglBuffer * gimp_pickable_contiguous_region_by_line_art (GimpPickable *pickable, + GimpLineArt *line_art, + gint x, + gint y); #endif /* __GIMP_PICKABLE_CONTIGUOUS_REGION_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimpprojectable.c gimp-2.10.14+om/app/core/gimpprojectable.c --- gimp-2.10.8+zorin2/app/core/gimpprojectable.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpprojectable.c 2019-10-26 18:49:18.000000000 +0000 @@ -90,10 +90,8 @@ G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GimpProjectableInterface, bounds_changed), NULL, NULL, - gimp_marshal_VOID__INT_INT_INT_INT, - G_TYPE_NONE, 4, - G_TYPE_INT, - G_TYPE_INT, + gimp_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); } @@ -135,14 +133,12 @@ void gimp_projectable_bounds_changed (GimpProjectable *projectable, gint old_x, - gint old_y, - gint old_width, - gint old_height) + gint old_y) { g_return_if_fail (GIMP_IS_PROJECTABLE (projectable)); g_signal_emit (projectable, projectable_signals[BOUNDS_CHANGED], 0, - old_x, old_y, old_width, old_height); + old_x, old_y); } GimpImage * @@ -195,24 +191,20 @@ iface->get_offset (projectable, x, y); } -void -gimp_projectable_get_size (GimpProjectable *projectable, - gint *width, - gint *height) +GeglRectangle +gimp_projectable_get_bounding_box (GimpProjectable *projectable) { GimpProjectableInterface *iface; + GeglRectangle result = {}; - g_return_if_fail (GIMP_IS_PROJECTABLE (projectable)); - g_return_if_fail (width != NULL); - g_return_if_fail (height != NULL); + g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), result); iface = GIMP_PROJECTABLE_GET_INTERFACE (projectable); - *width = 0; - *height = 0; + if (iface->get_bounding_box) + result = iface->get_bounding_box (projectable); - if (iface->get_size) - iface->get_size (projectable, width, height); + return result; } GeglNode * diff -Nru gimp-2.10.8+zorin2/app/core/gimpprojectable.h gimp-2.10.14+om/app/core/gimpprojectable.h --- gimp-2.10.8+zorin2/app/core/gimpprojectable.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpprojectable.h 2019-10-26 18:49:18.000000000 +0000 @@ -45,9 +45,7 @@ void (* structure_changed) (GimpProjectable *projectable); void (* bounds_changed) (GimpProjectable *projectable, gint old_x, - gint old_y, - gint old_width, - gint old_height); + gint old_y); /* virtual functions */ GimpImage * (* get_image) (GimpProjectable *projectable); @@ -55,9 +53,7 @@ void (* get_offset) (GimpProjectable *projectable, gint *x, gint *y); - void (* get_size) (GimpProjectable *projectable, - gint *width, - gint *height); + GeglRectangle (* get_bounding_box) (GimpProjectable *projectable); GeglNode * (* get_graph) (GimpProjectable *projectable); void (* begin_render) (GimpProjectable *projectable); void (* end_render) (GimpProjectable *projectable); @@ -77,18 +73,14 @@ void gimp_projectable_structure_changed (GimpProjectable *projectable); void gimp_projectable_bounds_changed (GimpProjectable *projectable, gint old_x, - gint old_y, - gint old_width, - gint old_height); + gint old_y); GimpImage * gimp_projectable_get_image (GimpProjectable *projectable); const Babl * gimp_projectable_get_format (GimpProjectable *projectable); void gimp_projectable_get_offset (GimpProjectable *projectable, gint *x, gint *y); -void gimp_projectable_get_size (GimpProjectable *projectable, - gint *width, - gint *height); +GeglRectangle gimp_projectable_get_bounding_box (GimpProjectable *projectable); GeglNode * gimp_projectable_get_graph (GimpProjectable *projectable); void gimp_projectable_begin_render (GimpProjectable *projectable); void gimp_projectable_end_render (GimpProjectable *projectable); diff -Nru gimp-2.10.8+zorin2/app/core/gimpprojection.c gimp-2.10.14+om/app/core/gimpprojection.c --- gimp-2.10.8+zorin2/app/core/gimpprojection.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpprojection.c 2019-10-26 18:49:18.000000000 +0000 @@ -35,6 +35,7 @@ #include "gimp.h" #include "gimp-memsize.h" +#include "gimpchunkiterator.h" #include "gimpimage.h" #include "gimpmarshal.h" #include "gimppickable.h" @@ -46,36 +47,9 @@ #include "gimp-priorities.h" -/* whether to use adaptive render-chunk size */ -static gboolean GIMP_PROJECTION_ADAPTIVE_CHUNK_SIZE = TRUE; - -/* chunk size for one iteration of the chunk renderer, when the use - * of adaptive chunk size is disabled - */ -static gint GIMP_PROJECTION_CHUNK_WIDTH = 256; -static gint GIMP_PROJECTION_CHUNK_HEIGHT = 128; - -/* the min/max adaptive chunk size */ -#define GIMP_PROJECTION_CHUNK_MIN_WIDTH 128 -#define GIMP_PROJECTION_CHUNK_MIN_HEIGHT 128 - -#define GIMP_PROJECTION_CHUNK_MAX_WIDTH 2048 -#define GIMP_PROJECTION_CHUNK_MAX_HEIGHT 2048 - -/* the minimal number of processed pixels on the current frame, - * above which we calculate a new target pixel count to render - * on the next frame - */ -#define GIMP_PROJECTION_MIN_PIXELS_PER_UPDATE 1024 - /* chunk size for area updates */ -static gint GIMP_PROJECTION_UPDATE_CHUNK_WIDTH = 32; -static gint GIMP_PROJECTION_UPDATE_CHUNK_HEIGHT = 32; - -/* how much time, in seconds, do we allow chunk rendering to take, - * aiming for 15fps - */ -static gdouble GIMP_PROJECTION_CHUNK_TIME = 0.0666; +#define GIMP_PROJECTION_UPDATE_CHUNK_WIDTH 32 +#define GIMP_PROJECTION_UPDATE_CHUNK_HEIGHT 32 enum @@ -91,27 +65,6 @@ }; -typedef struct _GimpProjectionChunkRender GimpProjectionChunkRender; - -struct _GimpProjectionChunkRender -{ - guint idle_id; - - gint x; - gint y; - gint width; - gint height; - - gint work_x; - gint work_y; - gint work_height; - - gint n_pixels; - gint target_n_pixels; - - cairo_region_t *update_region; /* flushed update region */ -}; - struct _GimpProjectionPrivate { GimpProjectable *projectable; @@ -122,8 +75,9 @@ gint priority; cairo_region_t *update_region; - GimpProjectionChunkRender chunk_render; - cairo_rectangle_int_t priority_rect; + GeglRectangle priority_rect; + GimpChunkIterator *iter; + guint idle_id; gboolean invalidate_preview; }; @@ -179,15 +133,14 @@ gint w, gint h); static void gimp_projection_flush_whenever (GimpProjection *proj, - gboolean now); + gboolean now, + gboolean direct); +static void gimp_projection_update_priority_rect (GimpProjection *proj); static void gimp_projection_chunk_render_start (GimpProjection *proj); -static void gimp_projection_chunk_render_stop (GimpProjection *proj); -static gboolean gimp_projection_chunk_render_callback (gpointer data); -static void gimp_projection_chunk_render_init (GimpProjection *proj); -static void gimp_projection_chunk_render_reinit (GimpProjection *proj); -static gboolean gimp_projection_chunk_render_iteration(GimpProjection *proj, - gboolean chunk); -static gboolean gimp_projection_chunk_render_next_area(GimpProjection *proj); +static void gimp_projection_chunk_render_stop (GimpProjection *proj, + gboolean merge); +static gboolean gimp_projection_chunk_render_callback (GimpProjection *proj); +static gboolean gimp_projection_chunk_render_iteration(GimpProjection *proj); static void gimp_projection_paint_area (GimpProjection *proj, gboolean now, gint x, @@ -210,15 +163,8 @@ static void gimp_projection_projectable_bounds_changed (GimpProjectable *projectable, gint old_x, gint old_y, - gint old_w, - gint old_h, GimpProjection *proj); -static gint gimp_projection_round_chunk_size (gdouble size, - gboolean toward_zero); -static gint gimp_projection_round_chunk_width (gdouble width); -static gint gimp_projection_round_chunk_height (gdouble height); - G_DEFINE_TYPE_WITH_CODE (GimpProjection, gimp_projection, GIMP_TYPE_OBJECT, G_ADD_PRIVATE (GimpProjection) @@ -235,7 +181,6 @@ { GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); - const gchar *env; projection_signals[UPDATE] = g_signal_new ("update", @@ -258,27 +203,6 @@ gimp_object_class->get_memsize = gimp_projection_get_memsize; g_object_class_override_property (object_class, PROP_BUFFER, "buffer"); - - if (g_getenv ("GIMP_NO_ADAPTIVE_CHUNK_SIZE")) - GIMP_PROJECTION_ADAPTIVE_CHUNK_SIZE = FALSE; - - env = g_getenv ("GIMP_DISPLAY_RENDER_BUF_SIZE"); - if (env) - { - gint width = atoi (env); - gint height = width; - - env = strchr (env, 'x'); - if (env) - height = atoi (env + 1); - - if (width > 0 && width <= 8192 && - height > 0 && height <= 8192) - { - GIMP_PROJECTION_CHUNK_WIDTH = width; - GIMP_PROJECTION_CHUNK_HEIGHT = height; - } - } } static void @@ -403,7 +327,7 @@ gimp_projection_get_buffer (pickable); gimp_projection_finish_draw (proj); - gimp_projection_flush_now (proj); + gimp_projection_flush_now (proj, FALSE); if (proj->priv->invalidate_preview) { @@ -439,10 +363,10 @@ if (! proj->priv->buffer) { - gint width; - gint height; + GeglRectangle bounding_box; - gimp_projectable_get_size (proj->priv->projectable, &width, &height); + bounding_box = + gimp_projectable_get_bounding_box (proj->priv->projectable); gimp_projection_allocate_buffer (proj); @@ -453,7 +377,9 @@ * image appear incrementally, but it keeps everything * responsive. */ - gimp_projection_add_update_area (proj, 0, 0, width, height); + gimp_projection_add_update_area (proj, + bounding_box.x, bounding_box.y, + bounding_box.width, bounding_box.height); proj->priv->invalidate_preview = TRUE; gimp_projection_flush (proj); } @@ -468,13 +394,19 @@ const Babl *format, gpointer pixel) { - GeglBuffer *buffer = gimp_projection_get_buffer (pickable); - - if (x < 0 || - y < 0 || - x >= gegl_buffer_get_width (buffer) || - y >= gegl_buffer_get_height (buffer)) - return FALSE; + GimpProjection *proj = GIMP_PROJECTION (pickable); + GeglBuffer *buffer = gimp_projection_get_buffer (pickable); + GeglRectangle bounding_box; + + bounding_box = gimp_projectable_get_bounding_box (proj->priv->projectable); + + if (x < bounding_box.x || + y < bounding_box.y || + x >= bounding_box.x + bounding_box.width || + y >= bounding_box.y + bounding_box.height) + { + return FALSE; + } gegl_buffer_sample (buffer, x, y, NULL, pixel, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); @@ -580,74 +512,19 @@ gint w, gint h) { - cairo_rectangle_int_t rect; - gint off_x, off_y; - gint width, height; - g_return_if_fail (GIMP_IS_PROJECTION (proj)); - gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y); - gimp_projectable_get_size (proj->priv->projectable, &width, &height); + proj->priv->priority_rect = *GEGL_RECTANGLE (x, y, w, h); - /* subtract the projectable's offsets because the list of update - * areas is in tile-pyramid coordinates, but our external API is - * always in terms of image coordinates. - */ - x -= off_x; - y -= off_y; - - if (gimp_rectangle_intersect (x, y, w, h, - 0, 0, width, height, - &rect.x, &rect.y, &rect.width, &rect.height)) - { - proj->priv->priority_rect = rect; - - if (proj->priv->chunk_render.idle_id) - gimp_projection_chunk_render_reinit (proj); - } + gimp_projection_update_priority_rect (proj); } void gimp_projection_stop_rendering (GimpProjection *proj) { - GimpProjectionChunkRender *chunk_render; - cairo_rectangle_int_t rect; - g_return_if_fail (GIMP_IS_PROJECTION (proj)); - chunk_render = &proj->priv->chunk_render; - - if (! chunk_render->idle_id) - return; - - if (chunk_render->update_region) - { - if (proj->priv->update_region) - { - cairo_region_union (proj->priv->update_region, - chunk_render->update_region); - } - else - { - proj->priv->update_region = - cairo_region_copy (chunk_render->update_region); - } - - g_clear_pointer (&chunk_render->update_region, cairo_region_destroy); - } - - rect.x = chunk_render->x; - rect.y = chunk_render->work_y; - rect.width = chunk_render->width; - rect.height = chunk_render->height - (chunk_render->work_y - chunk_render->y); - - /* FIXME this is too much, the entire current row */ - if (proj->priv->update_region) - cairo_region_union_rectangle (proj->priv->update_region, &rect); - else - proj->priv->update_region = cairo_region_create_rectangle (&rect); - - gimp_projection_chunk_render_stop (proj); + gimp_projection_chunk_render_stop (proj, TRUE); } void @@ -656,16 +533,17 @@ g_return_if_fail (GIMP_IS_PROJECTION (proj)); /* Construct in chunks */ - gimp_projection_flush_whenever (proj, FALSE); + gimp_projection_flush_whenever (proj, FALSE, FALSE); } void -gimp_projection_flush_now (GimpProjection *proj) +gimp_projection_flush_now (GimpProjection *proj, + gboolean direct) { g_return_if_fail (GIMP_IS_PROJECTION (proj)); /* Construct NOW */ - gimp_projection_flush_whenever (proj, TRUE); + gimp_projection_flush_whenever (proj, TRUE, direct); } void @@ -673,15 +551,17 @@ { g_return_if_fail (GIMP_IS_PROJECTION (proj)); - if (proj->priv->chunk_render.idle_id) + if (proj->priv->iter) { - gimp_projection_chunk_render_stop (proj); + gimp_chunk_iterator_set_priority_rect (proj->priv->iter, NULL); - gimp_projectable_begin_render (proj->priv->projectable); + gimp_tile_handler_validate_begin_validate (proj->priv->validate_handler); - while (gimp_projection_chunk_render_iteration (proj, FALSE)); + while (gimp_projection_chunk_render_iteration (proj)); - gimp_projectable_end_render (proj->priv->projectable); + gimp_tile_handler_validate_end_validate (proj->priv->validate_handler); + + gimp_projection_chunk_render_stop (proj, FALSE); } } @@ -691,18 +571,17 @@ static void gimp_projection_allocate_buffer (GimpProjection *proj) { - const Babl *format; - gint width; - gint height; + const Babl *format; + GeglRectangle bounding_box; if (proj->priv->buffer) return; - format = gimp_projection_get_format (GIMP_PICKABLE (proj)); - gimp_projectable_get_size (proj->priv->projectable, &width, &height); + format = gimp_projection_get_format (GIMP_PICKABLE (proj)); + bounding_box = + gimp_projectable_get_bounding_box (proj->priv->projectable); - proj->priv->buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), - format); + proj->priv->buffer = gegl_buffer_new (&bounding_box, format); proj->priv->validate_handler = GIMP_TILE_HANDLER_VALIDATE ( @@ -717,24 +596,20 @@ static void gimp_projection_free_buffer (GimpProjection *proj) { - if (proj->priv->chunk_render.idle_id) - gimp_projection_chunk_render_stop (proj); + gimp_projection_chunk_render_stop (proj, FALSE); g_clear_pointer (&proj->priv->update_region, cairo_region_destroy); - g_clear_pointer (&proj->priv->chunk_render.update_region, cairo_region_destroy); if (proj->priv->buffer) { - if (proj->priv->validate_handler) - { - gimp_tile_handler_validate_unassign (proj->priv->validate_handler, - proj->priv->buffer); - } + gimp_tile_handler_validate_unassign (proj->priv->validate_handler, + proj->priv->buffer); g_clear_object (&proj->priv->buffer); - } + g_clear_object (&proj->priv->validate_handler); - g_clear_object (&proj->priv->validate_handler); + g_object_notify (G_OBJECT (proj), "buffer"); + } } static void @@ -745,9 +620,9 @@ gint h) { cairo_rectangle_int_t rect; - gint width, height; + GeglRectangle bounding_box; - gimp_projectable_get_size (proj->priv->projectable, &width, &height); + bounding_box = gimp_projectable_get_bounding_box (proj->priv->projectable); /* align the rectangle to the UPDATE_CHUNK_WIDTH x UPDATE_CHUNK_HEIGHT grid, * to decrease the complexity of the update area. @@ -760,9 +635,8 @@ w -= x; h -= y; - if (gimp_rectangle_intersect (x, y, w, h, - 0, 0, width, height, - &rect.x, &rect.y, &rect.width, &rect.height)) + if (gegl_rectangle_intersect ((GeglRectangle *) &rect, + GEGL_RECTANGLE (x, y, w, h), &bounding_box)) { if (proj->priv->update_region) cairo_region_union_rectangle (proj->priv->update_region, &rect); @@ -773,10 +647,14 @@ static void gimp_projection_flush_whenever (GimpProjection *proj, - gboolean now) + gboolean now, + gboolean direct) { if (proj->priv->update_region) { + /* Make sure we have a buffer */ + gimp_projection_allocate_buffer (proj); + if (now) /* Synchronous */ { gint n_rects = cairo_region_num_rectangles (proj->priv->update_region); @@ -790,22 +668,23 @@ i, &rect); gimp_projection_paint_area (proj, - FALSE, /* sic! */ + direct, rect.x, rect.y, rect.width, rect.height); } + + /* Free the update region */ + g_clear_pointer (&proj->priv->update_region, cairo_region_destroy); } else /* Asynchronous */ { - gimp_projection_chunk_render_init (proj); + /* Consumes the update region */ + gimp_projection_chunk_render_start (proj); } - - /* Free the update region */ - g_clear_pointer (&proj->priv->update_region, cairo_region_destroy); } - else if (! now && proj->priv->invalidate_preview) + else if (! now && ! proj->priv->iter && proj->priv->invalidate_preview) { /* invalidate the preview here since it is constructed from * the projection @@ -817,307 +696,184 @@ } static void -gimp_projection_chunk_render_start (GimpProjection *proj) +gimp_projection_update_priority_rect (GimpProjection *proj) { - g_return_if_fail (proj->priv->chunk_render.idle_id == 0); - - proj->priv->chunk_render.idle_id = - g_idle_add_full (GIMP_PRIORITY_PROJECTION_IDLE + proj->priv->priority, - gimp_projection_chunk_render_callback, proj, - NULL); -} - -static void -gimp_projection_chunk_render_stop (GimpProjection *proj) -{ - g_return_if_fail (proj->priv->chunk_render.idle_id != 0); - - g_source_remove (proj->priv->chunk_render.idle_id); - proj->priv->chunk_render.idle_id = 0; -} - -static gboolean -gimp_projection_chunk_render_callback (gpointer data) -{ - GimpProjection *proj = data; - GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render; - GTimer *timer = g_timer_new (); - gint chunks = 0; - gboolean retval = TRUE; - - /* reset the rendered pixel count, so that we count the number of pixels - * processed during this frame - */ - chunk_render->n_pixels = 0; - - gimp_projectable_begin_render (proj->priv->projectable); - - do + if (proj->priv->iter) { - if (! gimp_projection_chunk_render_iteration (proj, TRUE)) - { - gimp_projection_chunk_render_stop (proj); + GeglRectangle rect; + GeglRectangle bounding_box; + gint off_x, off_y; - retval = FALSE; + rect = proj->priv->priority_rect; - break; - } + gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y); + bounding_box = gimp_projectable_get_bounding_box (proj->priv->projectable); - chunks++; - } - while (g_timer_elapsed (timer, NULL) < GIMP_PROJECTION_CHUNK_TIME); + /* subtract the projectable's offsets because the list of update + * areas is in tile-pyramid coordinates, but our external API is + * always in terms of image coordinates. + */ + rect.x -= off_x; + rect.y -= off_y; - gimp_projectable_end_render (proj->priv->projectable); + gegl_rectangle_intersect (&rect, &rect, &bounding_box); - /* adjust the target number of pixels to be processed on the next frame, - * according to the number of pixels processed during this frame and the - * elapsed time, in order to match the desired frame rate. - */ - if (chunk_render->n_pixels >= GIMP_PROJECTION_MIN_PIXELS_PER_UPDATE) - { - chunk_render->target_n_pixels = floor (chunk_render->n_pixels * - GIMP_PROJECTION_CHUNK_TIME / - g_timer_elapsed (timer, NULL)); + gimp_chunk_iterator_set_priority_rect (proj->priv->iter, &rect); } - - GIMP_LOG (PROJECTION, "%d chunks in %f seconds\n", - chunks, g_timer_elapsed (timer, NULL)); - g_timer_destroy (timer); - - return retval; } static void -gimp_projection_chunk_render_init (GimpProjection *proj) +gimp_projection_chunk_render_start (GimpProjection *proj) { - GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render; + cairo_region_t *region = proj->priv->update_region; + gboolean invalidate_preview = FALSE; - chunk_render->target_n_pixels = GIMP_PROJECTION_CHUNK_WIDTH * - GIMP_PROJECTION_CHUNK_HEIGHT; + if (proj->priv->iter) + { + region = gimp_chunk_iterator_stop (proj->priv->iter, FALSE); - gimp_projection_chunk_render_reinit (proj); -} + proj->priv->iter = NULL; -static void -gimp_projection_chunk_render_reinit (GimpProjection *proj) -{ - GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render; + if (cairo_region_is_empty (region)) + invalidate_preview = proj->priv->invalidate_preview; - /* We need to merge the ChunkRender's and the GimpProjection's - * update_regions list to keep track of which of the updates have - * been flushed and hence need to be drawn. - */ - if (proj->priv->update_region) - { - if (chunk_render->update_region) - { - cairo_region_union (chunk_render->update_region, - proj->priv->update_region); - } - else + if (proj->priv->update_region) { - chunk_render->update_region = - cairo_region_copy (proj->priv->update_region); + cairo_region_union (region, proj->priv->update_region); + + cairo_region_destroy (proj->priv->update_region); } } - /* If a chunk renderer was already running, merge the remainder of - * its unrendered area with the update_areas list, and make it start - * work on the next unrendered area in the list. - */ - if (chunk_render->idle_id) + proj->priv->update_region = NULL; + + if (region && ! cairo_region_is_empty (region)) { - cairo_rectangle_int_t rect; - gint work_h = 0; + proj->priv->iter = gimp_chunk_iterator_new (region); - if (chunk_render->work_x != chunk_render->x) - { - work_h = MIN (chunk_render->work_height, - chunk_render->y + chunk_render->height - - chunk_render->work_y); - - rect.x = chunk_render->work_x; - rect.y = chunk_render->work_y; - rect.width = chunk_render->x + chunk_render->width - - chunk_render->work_x; - rect.height = work_h; + gimp_projection_update_priority_rect (proj); - if (chunk_render->update_region) - cairo_region_union_rectangle (chunk_render->update_region, &rect); - else - chunk_render->update_region = cairo_region_create_rectangle (&rect); + if (! proj->priv->idle_id) + { + proj->priv->idle_id = g_idle_add_full ( + GIMP_PRIORITY_PROJECTION_IDLE + proj->priv->priority, + (GSourceFunc) gimp_projection_chunk_render_callback, + proj, NULL); } - - rect.x = chunk_render->x; - rect.y = chunk_render->work_y + work_h; - rect.width = chunk_render->width; - rect.height = chunk_render->y + chunk_render->height - rect.y; - - if (chunk_render->update_region) - cairo_region_union_rectangle (chunk_render->update_region, &rect); - else - chunk_render->update_region = cairo_region_create_rectangle (&rect); - - gimp_projection_chunk_render_next_area (proj); } else { - if (chunk_render->update_region == NULL) + if (region) + cairo_region_destroy (region); + + if (proj->priv->idle_id) { - g_warning ("%s: wanted to start chunk render with no update_region", - G_STRFUNC); - return; + g_source_remove (proj->priv->idle_id); + proj->priv->idle_id = 0; } - proj->priv->chunk_render.target_n_pixels = GIMP_PROJECTION_CHUNK_WIDTH * - GIMP_PROJECTION_CHUNK_HEIGHT; - - gimp_projection_chunk_render_next_area (proj); + if (invalidate_preview) + { + /* invalidate the preview here since it is constructed from + * the projection + */ + proj->priv->invalidate_preview = FALSE; - gimp_projection_chunk_render_start (proj); + gimp_projectable_invalidate_preview (proj->priv->projectable); + } } } -/* Unless specified otherwise, projection re-rendering is organised by - * ChunkRender, which amalgamates areas to be re-rendered and breaks - * them into bite-sized chunks which are chewed on in an idle - * function. This greatly improves responsiveness for many GIMP - * operations. -- Adam - */ -static gboolean -gimp_projection_chunk_render_iteration (GimpProjection *proj, - gboolean chunk) +static void +gimp_projection_chunk_render_stop (GimpProjection *proj, + gboolean merge) { - GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render; - gint work_x = chunk_render->work_x; - gint work_y = chunk_render->work_y; - gint work_w; - gint work_h; - - work_w = chunk_render->x + chunk_render->width - work_x; - work_h = chunk_render->y + chunk_render->height - work_y; + if (proj->priv->idle_id) + { + g_source_remove (proj->priv->idle_id); + proj->priv->idle_id = 0; + } - if (chunk) + if (proj->priv->iter) { - if (GIMP_PROJECTION_ADAPTIVE_CHUNK_SIZE) + if (merge) { - gint chunk_w; - gint chunk_h; - - /* try to render in square chunks */ - chunk_h = gimp_projection_round_chunk_height ( - sqrt (chunk_render->target_n_pixels)); + cairo_region_t *region; - work_h = MIN (work_h, chunk_h); + region = gimp_chunk_iterator_stop (proj->priv->iter, FALSE); - chunk_w = gimp_projection_round_chunk_width ( - chunk_render->target_n_pixels / work_h); + if (proj->priv->update_region) + { + cairo_region_union (proj->priv->update_region, region); - work_w = MIN (work_w, chunk_w); + cairo_region_destroy (region); + } + else + { + proj->priv->update_region = region; + } } else { - work_w = MIN (work_w, GIMP_PROJECTION_CHUNK_WIDTH); - work_h = MIN (work_h, GIMP_PROJECTION_CHUNK_HEIGHT); + gimp_chunk_iterator_stop (proj->priv->iter, TRUE); } + + proj->priv->iter = NULL; } - else - { - if (work_x != chunk_render->x) - work_h = MIN (work_h, chunk_render->work_height); - } +} - if (work_h != chunk_render->work_height) +static gboolean +gimp_projection_chunk_render_callback (GimpProjection *proj) +{ + if (gimp_projection_chunk_render_iteration (proj)) { - /* if the chunk height changed in the middle of a row, refetch the - * current area, so that we're back at the beginning of a row - */ - if (work_x != chunk_render->x) - gimp_projection_chunk_render_reinit (proj); - - chunk_render->work_height = work_h; + return G_SOURCE_CONTINUE; } - - gimp_projection_paint_area (proj, TRUE /* sic! */, - work_x, work_y, work_w, work_h); - - chunk_render->n_pixels += work_w * work_h; - - chunk_render->work_x += work_w; - - if (chunk_render->work_x >= chunk_render->x + chunk_render->width) + else { - chunk_render->work_x = chunk_render->x; - - chunk_render->work_y += work_h; + proj->priv->idle_id = 0; - if (chunk_render->work_y >= chunk_render->y + chunk_render->height) - { - if (! gimp_projection_chunk_render_next_area (proj)) - { - if (proj->priv->invalidate_preview) - { - /* invalidate the preview here since it is constructed from - * the projection - */ - proj->priv->invalidate_preview = FALSE; - - gimp_projectable_invalidate_preview (proj->priv->projectable); - } - - /* FINISHED */ - return FALSE; - } - } + return G_SOURCE_REMOVE; } - - /* Still work to do. */ - return TRUE; } static gboolean -gimp_projection_chunk_render_next_area (GimpProjection *proj) +gimp_projection_chunk_render_iteration (GimpProjection *proj) { - GimpProjectionChunkRender *chunk_render = &proj->priv->chunk_render; - cairo_region_t *next_region; - cairo_rectangle_int_t rect; - - if (! chunk_render->update_region) - return FALSE; - - if (cairo_region_is_empty (chunk_render->update_region)) + if (gimp_chunk_iterator_next (proj->priv->iter)) { - g_clear_pointer (&chunk_render->update_region, cairo_region_destroy); + GeglRectangle rect; - return FALSE; - } - - next_region = cairo_region_copy (chunk_render->update_region); - cairo_region_intersect_rectangle (next_region, &proj->priv->priority_rect); - - if (cairo_region_is_empty (next_region)) - cairo_region_get_rectangle (chunk_render->update_region, 0, &rect); - else - cairo_region_get_rectangle (next_region, 0, &rect); + gimp_tile_handler_validate_begin_validate (proj->priv->validate_handler); - cairo_region_destroy (next_region); + while (gimp_chunk_iterator_get_rect (proj->priv->iter, &rect)) + { + gimp_projection_paint_area (proj, TRUE, + rect.x, rect.y, rect.width, rect.height); + } - cairo_region_subtract_rectangle (chunk_render->update_region, &rect); + gimp_tile_handler_validate_end_validate (proj->priv->validate_handler); - if (cairo_region_is_empty (chunk_render->update_region)) - { - g_clear_pointer (&chunk_render->update_region, cairo_region_destroy); + /* Still work to do. */ + return TRUE; } + else + { + proj->priv->iter = NULL; - chunk_render->x = rect.x; - chunk_render->y = rect.y; - chunk_render->width = rect.width; - chunk_render->height = rect.height; + if (proj->priv->invalidate_preview) + { + /* invalidate the preview here since it is constructed from + * the projection + */ + proj->priv->invalidate_preview = FALSE; - chunk_render->work_x = chunk_render->x; - chunk_render->work_y = chunk_render->y; + gimp_projectable_invalidate_preview (proj->priv->projectable); + } - return TRUE; + /* FINISHED */ + return FALSE; + } } static void @@ -1128,29 +884,29 @@ gint w, gint h) { - gint off_x, off_y; - gint width, height; + gint off_x, off_y; + GeglRectangle bounding_box; + GeglRectangle rect; gimp_projectable_get_offset (proj->priv->projectable, &off_x, &off_y); - gimp_projectable_get_size (proj->priv->projectable, &width, &height); + bounding_box = gimp_projectable_get_bounding_box (proj->priv->projectable); - if (gimp_rectangle_intersect (x, y, w, h, - 0, 0, width, height, - &x, &y, &w, &h)) - { - if (proj->priv->validate_handler) - gimp_tile_handler_validate_invalidate (proj->priv->validate_handler, - GEGL_RECTANGLE (x, y, w, h)); + if (gegl_rectangle_intersect (&rect, + GEGL_RECTANGLE (x, y, w, h), &bounding_box)) + { if (now) { - GeglNode *graph = gimp_projectable_get_graph (proj->priv->projectable); - - if (proj->priv->validate_handler) - gimp_tile_handler_validate_undo_invalidate (proj->priv->validate_handler, - GEGL_RECTANGLE (x, y, w, h)); - - gegl_node_blit_buffer (graph, proj->priv->buffer, - GEGL_RECTANGLE (x, y, w, h), 0, GEGL_ABYSS_NONE); + gimp_tile_handler_validate_validate ( + proj->priv->validate_handler, + proj->priv->buffer, + &rect, + FALSE); + } + else + { + gimp_tile_handler_validate_invalidate ( + proj->priv->validate_handler, + &rect); } /* add the projectable's offsets because the list of update areas @@ -1159,10 +915,10 @@ */ g_signal_emit (proj, projection_signals[UPDATE], 0, now, - x + off_x, - y + off_y, - w, - h); + rect.x + off_x, + rect.y + off_y, + rect.width, + rect.height); } } @@ -1206,31 +962,31 @@ gimp_projection_projectable_structure_changed (GimpProjectable *projectable, GimpProjection *proj) { - gint width, height; + GeglRectangle bounding_box; gimp_projection_free_buffer (proj); - gimp_projectable_get_size (projectable, &width, &height); - - gimp_projection_add_update_area (proj, 0, 0, width, height); + bounding_box = gimp_projectable_get_bounding_box (projectable); - proj->priv->priority_rect.x = 0; - proj->priv->priority_rect.y = 0; - proj->priv->priority_rect.width = width; - proj->priv->priority_rect.height = height; + gimp_projection_add_update_area (proj, + bounding_box.x, bounding_box.y, + bounding_box.width, bounding_box.height); } static void gimp_projection_projectable_bounds_changed (GimpProjectable *projectable, gint old_x, gint old_y, - gint old_w, - gint old_h, GimpProjection *proj) { GeglBuffer *old_buffer = proj->priv->buffer; GimpTileHandlerValidate *old_validate_handler; - gint x, y, w, h; + GeglRectangle old_bounding_box; + GeglRectangle bounding_box; + GeglRectangle old_bounds; + GeglRectangle bounds; + GeglRectangle int_bounds; + gint x, y; gint dx, dy; if (! old_buffer) @@ -1240,23 +996,34 @@ return; } + old_bounding_box = *gegl_buffer_get_extent (old_buffer); + gimp_projectable_get_offset (projectable, &x, &y); - gimp_projectable_get_size (projectable, &w, &h); + bounding_box = gimp_projectable_get_bounding_box (projectable); - if (x == old_x && y == old_y && w == old_w && h == old_h) - return; + if (x == old_x && y == old_y && + gegl_rectangle_equal (&bounding_box, &old_bounding_box)) + { + return; + } - if (! gimp_rectangle_intersect (x, y, w, h, - old_x, old_y, old_w, old_h, - NULL, NULL, NULL, NULL)) + old_bounds = old_bounding_box; + old_bounds.x += old_x; + old_bounds.y += old_y; + + bounds = bounding_box; + bounds.x += x; + bounds.y += y; + + if (! gegl_rectangle_intersect (&int_bounds, &bounds, &old_bounds)) { gimp_projection_projectable_structure_changed (projectable, proj); return; } - dx = old_x - x; - dy = old_y - y; + dx = x - old_x; + dy = y - old_y; #if 1 /* FIXME: when there's an offset between the new bounds and the old bounds, @@ -1278,152 +1045,88 @@ #endif /* reallocate the buffer, and copy the old buffer to the corresponding - * region of the new buffer. additionally, shift and clip all outstanding - * update regions as necessary. + * region of the new buffer. */ - old_validate_handler = proj->priv->validate_handler; - - proj->priv->buffer = NULL; - proj->priv->validate_handler = NULL; + gimp_projection_chunk_render_stop (proj, TRUE); - gimp_projection_allocate_buffer (proj); - - gimp_tile_handler_validate_buffer_copy (old_buffer, - GEGL_RECTANGLE (0, 0, old_w, old_h), - proj->priv->buffer, - GEGL_RECTANGLE (dx, dy, old_w, old_h)); - - if (old_validate_handler) + if (dx == 0 && dy == 0) { - gimp_tile_handler_validate_unassign (old_validate_handler, old_buffer); - - g_object_unref (old_validate_handler); + gimp_tile_handler_validate_buffer_set_extent (old_buffer, &bounding_box); } - - g_object_unref (old_buffer); - - if (proj->priv->update_region) + else { - const cairo_rectangle_int_t bounds = {0, 0, w, h}; - - cairo_region_translate (proj->priv->update_region, dx, dy); - cairo_region_intersect_rectangle (proj->priv->update_region, &bounds); - } + old_validate_handler = proj->priv->validate_handler; - if (proj->priv->chunk_render.idle_id) - { - const cairo_rectangle_int_t bounds = {0, 0, w, h}; + proj->priv->buffer = NULL; + proj->priv->validate_handler = NULL; - proj->priv->chunk_render.x += dx; - proj->priv->chunk_render.y += dy; + gimp_projection_allocate_buffer (proj); - proj->priv->chunk_render.work_x += dx; - proj->priv->chunk_render.work_y += dx; + gimp_tile_handler_validate_buffer_copy ( + old_buffer, + GEGL_RECTANGLE (int_bounds.x - old_x, + int_bounds.y - old_y, + int_bounds.width, + int_bounds.height), + proj->priv->buffer, + GEGL_RECTANGLE (int_bounds.x - x, + int_bounds.y - y, + int_bounds.width, + int_bounds.height)); - if (proj->priv->chunk_render.update_region) - { - cairo_region_translate - (proj->priv->chunk_render.update_region, dx, dy); - cairo_region_intersect_rectangle - (proj->priv->chunk_render.update_region, &bounds); - } + gimp_tile_handler_validate_unassign (old_validate_handler, + old_buffer); - if (! gimp_rectangle_intersect (proj->priv->chunk_render.x, - proj->priv->chunk_render.y, - proj->priv->chunk_render.width, - proj->priv->chunk_render.height, - - 0, 0, w, h, - - &proj->priv->chunk_render.x, - &proj->priv->chunk_render.y, - &proj->priv->chunk_render.width, - &proj->priv->chunk_render.height)) - { - if (! gimp_projection_chunk_render_next_area (proj)) - gimp_projection_chunk_render_stop (proj); - } + g_object_unref (old_validate_handler); + g_object_unref (old_buffer); } - if (proj->priv->priority_rect.width > 0 && - proj->priv->priority_rect.height > 0) - { - proj->priv->priority_rect.x += dx; - proj->priv->priority_rect.y += dy; - - gimp_rectangle_intersect (proj->priv->priority_rect.x, - proj->priv->priority_rect.y, - proj->priv->priority_rect.width, - proj->priv->priority_rect.height, - - 0, 0, w, h, - - &proj->priv->priority_rect.x, - &proj->priv->priority_rect.y, - &proj->priv->priority_rect.width, - &proj->priv->priority_rect.height); - } - - if (dx > 0) - gimp_projection_add_update_area (proj, 0, 0, dx, h); - if (dy > 0) - gimp_projection_add_update_area (proj, 0, 0, w, dy); - if (dx + old_w < w) - gimp_projection_add_update_area (proj, dx + old_w, 0, w - (dx + old_w), h); - if (dy + old_h < h) - gimp_projection_add_update_area (proj, 0, dy + old_h, w, h - (dy + old_h)); - - proj->priv->invalidate_preview = TRUE; -} - -static gint -gimp_projection_round_chunk_size (gdouble size, - gboolean toward_zero) -{ - /* round 'size' (up or down, depending on 'toward_zero') to the closest power - * of 2 - */ - - if (size < 0.0) - { - return -gimp_projection_round_chunk_size (-size, toward_zero); - } - else if (size == 0.0) - { - return 0; - } - else if (size < 1.0) - { - return toward_zero ? 0 : 1; - } - else + if (proj->priv->update_region) { - gdouble log2_size = log (size) / G_LN2; - - if (toward_zero) - log2_size = floor (log2_size); - else - log2_size = ceil (log2_size); - - return 1 << (gint) log2_size; + cairo_region_translate (proj->priv->update_region, dx, dy); + cairo_region_intersect_rectangle ( + proj->priv->update_region, + (const cairo_rectangle_int_t *) &bounding_box); + } + + int_bounds.x -= x; + int_bounds.y -= y; + + if (int_bounds.x > bounding_box.x) + { + gimp_projection_add_update_area (proj, + bounding_box.x, + bounding_box.y, + int_bounds.x - bounding_box.x, + bounding_box.height); + } + if (int_bounds.y > bounding_box.y) + { + gimp_projection_add_update_area (proj, + bounding_box.x, + bounding_box.y, + bounding_box.width, + int_bounds.y - bounding_box.y); + } + if (int_bounds.x + int_bounds.width < bounding_box.x + bounding_box.width) + { + gimp_projection_add_update_area (proj, + int_bounds.x + int_bounds.width, + bounding_box.y, + bounding_box.x + bounding_box.width - + (int_bounds.x + int_bounds.width), + bounding_box.height); + } + if (int_bounds.y + int_bounds.height < bounding_box.y + bounding_box.height) + { + gimp_projection_add_update_area (proj, + bounding_box.x, + int_bounds.y + int_bounds.height, + bounding_box.width, + bounding_box.y + bounding_box.height - + (int_bounds.y + int_bounds.height)); } -} -static gint -gimp_projection_round_chunk_width (gdouble width) -{ - gint w = gimp_projection_round_chunk_size (width, FALSE); - - return CLAMP (w, GIMP_PROJECTION_CHUNK_MIN_WIDTH, - GIMP_PROJECTION_CHUNK_MAX_WIDTH); -} - -static gint -gimp_projection_round_chunk_height (gdouble height) -{ - gint h = gimp_projection_round_chunk_size (height, TRUE); - - return CLAMP (h, GIMP_PROJECTION_CHUNK_MIN_HEIGHT, - GIMP_PROJECTION_CHUNK_MAX_HEIGHT); + proj->priv->invalidate_preview = TRUE; } diff -Nru gimp-2.10.8+zorin2/app/core/gimpprojection.h gimp-2.10.14+om/app/core/gimpprojection.h --- gimp-2.10.8+zorin2/app/core/gimpprojection.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpprojection.h 2019-01-03 14:13:22.000000000 +0000 @@ -70,7 +70,8 @@ void gimp_projection_stop_rendering (GimpProjection *proj); void gimp_projection_flush (GimpProjection *proj); -void gimp_projection_flush_now (GimpProjection *proj); +void gimp_projection_flush_now (GimpProjection *proj, + gboolean direct); void gimp_projection_finish_draw (GimpProjection *proj); gint64 gimp_projection_estimate_memsize (GimpImageBaseType type, diff -Nru gimp-2.10.8+zorin2/app/core/gimpscanconvert.c gimp-2.10.14+om/app/core/gimpscanconvert.c --- gimp-2.10.8+zorin2/app/core/gimpscanconvert.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpscanconvert.c 2019-01-03 14:13:22.000000000 +0000 @@ -20,7 +20,6 @@ #include #include -#define GEGL_ITERATOR2_API #include #include diff -Nru gimp-2.10.8+zorin2/app/core/gimpselection.c gimp-2.10.14+om/app/core/gimpselection.c --- gimp-2.10.8+zorin2/app/core/gimpselection.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpselection.c 2019-10-26 18:49:18.000000000 +0000 @@ -113,6 +113,7 @@ static void gimp_selection_feather (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo); static void gimp_selection_sharpen (GimpChannel *channel, gboolean push_undo); @@ -507,10 +508,11 @@ gimp_selection_feather (GimpChannel *channel, gdouble radius_x, gdouble radius_y, + gboolean edge_lock, gboolean push_undo) { GIMP_CHANNEL_CLASS (parent_class)->feather (channel, radius_x, radius_y, - push_undo); + edge_lock, push_undo); } static void diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry.c gimp-2.10.14+om/app/core/gimpsymmetry.c --- gimp-2.10.8+zorin2/app/core/gimpsymmetry.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry.c 2019-06-12 16:43:38.000000000 +0000 @@ -27,9 +27,12 @@ #include "libgimpbase/gimpbase.h" #include "libgimpconfig/gimpconfig.h" +#include "libgimpmath/gimpmath.h" #include "core-types.h" +#include "gegl/gimp-gegl-nodes.h" + #include "gimpdrawable.h" #include "gimpimage.h" #include "gimpimage-symmetry.h" @@ -71,10 +74,10 @@ static void gimp_symmetry_real_update_strokes (GimpSymmetry *sym, GimpDrawable *drawable, GimpCoords *origin); -static GeglNode * gimp_symmetry_real_get_op (GimpSymmetry *sym, +static void gimp_symmetry_real_get_transform (GimpSymmetry *sym, gint stroke, - gint paint_width, - gint paint_height); + gdouble *angle, + gboolean *reflect); static gboolean gimp_symmetry_real_update_version (GimpSymmetry *sym); @@ -133,7 +136,7 @@ klass->label = _("None"); klass->update_strokes = gimp_symmetry_real_update_strokes; - klass->get_operation = gimp_symmetry_real_get_op; + klass->get_transform = gimp_symmetry_real_get_transform; klass->active_changed = NULL; klass->update_version = gimp_symmetry_real_update_version; @@ -235,15 +238,14 @@ g_memdup (origin, sizeof (GimpCoords))); } -static GeglNode * -gimp_symmetry_real_get_op (GimpSymmetry *sym, - gint stroke, - gint paint_width, - gint paint_height) +static void +gimp_symmetry_real_get_transform (GimpSymmetry *sym, + gint stroke, + gdouble *angle, + gboolean *reflect) { - /* The basic symmetry just returns NULL, since no transformation of the + /* The basic symmetry does nothing, since no transformation of the * brush painting happen. */ - return NULL; } static gboolean @@ -396,27 +398,88 @@ } /** + * gimp_symmetry_get_transform: + * @sym: the #GimpSymmetry + * @stroke: the stroke number + * @angle: output pointer to the transformation rotation angle, + * in degrees (ccw) + * @reflect: output pointer to the transformation reflection flag + * + * Returns: the transformation to apply to the paint content for stroke + * number @stroke. The transformation is comprised of rotation, possibly + * followed by horizontal reflection, around the stroke coordinates. + **/ +void +gimp_symmetry_get_transform (GimpSymmetry *sym, + gint stroke, + gdouble *angle, + gboolean *reflect) +{ + g_return_if_fail (GIMP_IS_SYMMETRY (sym)); + g_return_if_fail (angle != NULL); + g_return_if_fail (reflect != NULL); + + *angle = 0.0; + *reflect = FALSE; + + GIMP_SYMMETRY_GET_CLASS (sym)->get_transform (sym, + stroke, + angle, + reflect); +} + +/** + * gimp_symmetry_get_matrix: + * @sym: the #GimpSymmetry + * @stroke: the stroke number + * @matrix: output pointer to the transformation matrix + * + * Returns: the transformation matrix to apply to the paint content for stroke + * number @stroke. + **/ +void +gimp_symmetry_get_matrix (GimpSymmetry *sym, + gint stroke, + GimpMatrix3 *matrix) +{ + gdouble angle; + gboolean reflect; + + g_return_if_fail (GIMP_IS_SYMMETRY (sym)); + g_return_if_fail (matrix != NULL); + + gimp_symmetry_get_transform (sym, stroke, &angle, &reflect); + + gimp_matrix3_identity (matrix); + gimp_matrix3_rotate (matrix, -gimp_deg_to_rad (angle)); + if (reflect) + gimp_matrix3_scale (matrix, -1.0, 1.0); +} + +/** * gimp_symmetry_get_operation: * @sym: the #GimpSymmetry * @stroke: the stroke number - * @paint_width: the width of the painting area - * @paint_height: the height of the painting area * - * Returns: the operation to apply to the paint buffer for stroke number @stroke. - * NULL means to copy the original stroke as-is. + * Returns: the transformation operation to apply to the paint content for + * stroke number @stroke, or NULL for the identity transformation. + * + * The returned #GeglNode should be freed by the caller. **/ GeglNode * gimp_symmetry_get_operation (GimpSymmetry *sym, - gint stroke, - gint paint_width, - gint paint_height) + gint stroke) { + GimpMatrix3 matrix; + g_return_val_if_fail (GIMP_IS_SYMMETRY (sym), NULL); - return GIMP_SYMMETRY_GET_CLASS (sym)->get_operation (sym, - stroke, - paint_width, - paint_height); + gimp_symmetry_get_matrix (sym, stroke, &matrix); + + if (gimp_matrix3_is_identity (&matrix)) + return NULL; + + return gimp_gegl_create_transform_node (&matrix); } /* diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry.h gimp-2.10.14+om/app/core/gimpsymmetry.h --- gimp-2.10.8+zorin2/app/core/gimpsymmetry.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry.h 2019-06-12 16:43:38.000000000 +0000 @@ -63,10 +63,10 @@ void (* update_strokes) (GimpSymmetry *symmetry, GimpDrawable *drawable, GimpCoords *origin); - GeglNode * (* get_operation) (GimpSymmetry *symmetry, + void (* get_transform) (GimpSymmetry *symmetry, gint stroke, - gint paint_width, - gint paint_height); + gdouble *angle, + gboolean *reflect); void (* active_changed) (GimpSymmetry *symmetry); gboolean (* update_version) (GimpSymmetry *symmetry); @@ -86,10 +86,15 @@ gint gimp_symmetry_get_size (GimpSymmetry *symmetry); GimpCoords * gimp_symmetry_get_coords (GimpSymmetry *symmetry, gint stroke); -GeglNode * gimp_symmetry_get_operation (GimpSymmetry *symmetry, +void gimp_symmetry_get_transform (GimpSymmetry *symmetry, + gint stroke, + gdouble *angle, + gboolean *reflect); +void gimp_symmetry_get_matrix (GimpSymmetry *symmetry, gint stroke, - gint paint_width, - gint paint_height); + GimpMatrix3 *matrix); +GeglNode * gimp_symmetry_get_operation (GimpSymmetry *symmetry, + gint stroke); gchar * gimp_symmetry_parasite_name (GType type); GimpParasite * gimp_symmetry_to_parasite (const GimpSymmetry *symmetry); diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry-mandala.c gimp-2.10.14+om/app/core/gimpsymmetry-mandala.c --- gimp-2.10.8+zorin2/app/core/gimpsymmetry-mandala.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry-mandala.c 2019-06-12 16:43:38.000000000 +0000 @@ -81,10 +81,10 @@ static void gimp_mandala_update_strokes (GimpSymmetry *mandala, GimpDrawable *drawable, GimpCoords *origin); -static GeglNode * gimp_mandala_get_operation (GimpSymmetry *mandala, +static void gimp_mandala_get_transform (GimpSymmetry *mandala, gint stroke, - gint paint_width, - gint paint_height); + gdouble *angle, + gboolean *reflect); static void gimp_mandala_image_size_changed_cb (GimpImage *image, gint previous_origin_x, gint previous_origin_y, @@ -112,7 +112,7 @@ symmetry_class->label = _("Mandala"); symmetry_class->update_strokes = gimp_mandala_update_strokes; - symmetry_class->get_operation = gimp_mandala_get_operation; + symmetry_class->get_transform = gimp_mandala_get_transform; symmetry_class->active_changed = gimp_mandala_active_changed; GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_CENTER_X, @@ -179,20 +179,6 @@ g_clear_object (&mandala->horizontal_guide); g_clear_object (&mandala->vertical_guide); - if (mandala->ops) - { - GList *iter; - - for (iter = mandala->ops; iter; iter = g_list_next (iter)) - { - if (iter->data) - g_object_unref (G_OBJECT (iter->data)); - } - - g_list_free (mandala->ops); - mandala->ops = NULL; - } - G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -490,66 +476,18 @@ g_signal_emit_by_name (sym, "strokes-updated", sym->image); } -static GeglNode * -gimp_mandala_get_operation (GimpSymmetry *sym, +static void +gimp_mandala_get_transform (GimpSymmetry *sym, gint stroke, - gint paint_width, - gint paint_height) + gdouble *angle, + gboolean *reflect) { GimpMandala *mandala = GIMP_MANDALA (sym); - GeglNode *op = NULL; - gint i; - if (! mandala->disable_transformation && - stroke != 0 && - paint_width != 0 && - paint_height != 0) - { - if (mandala->size != mandala->cached_size || - mandala->cached_paint_width != paint_width || - mandala->cached_paint_height != paint_height) - { - GList *iter; - - if (mandala->ops) - { - for (iter = mandala->ops; iter; iter = g_list_next (iter)) - { - if (iter->data) - g_object_unref (G_OBJECT (iter->data)); - } - - g_list_free (mandala->ops); - mandala->ops = NULL; - } - - mandala->ops = g_list_prepend (mandala->ops, NULL); - - for (i = 1; i < mandala->size; i++) - { - op = gegl_node_new_child (NULL, - "operation", "gegl:rotate", - "origin-x", - (gdouble) paint_width / 2.0, - "origin-y", - (gdouble) paint_height / 2.0, - "degrees", - i * 360.0 / (gdouble) mandala->size, - NULL); - mandala->ops = g_list_prepend (mandala->ops, op); - } - - mandala->ops = g_list_reverse (mandala->ops); - - mandala->cached_size = mandala->size; - mandala->cached_paint_width = paint_width; - mandala->cached_paint_height = paint_height; - } - - op = g_list_nth_data (mandala->ops, stroke); - } + if (mandala->disable_transformation) + return; - return op; + *angle = 360.0 * stroke / mandala->size; } static void diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry-mandala.h gimp-2.10.14+om/app/core/gimpsymmetry-mandala.h --- gimp-2.10.8+zorin2/app/core/gimpsymmetry-mandala.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry-mandala.h 2019-06-12 16:43:38.000000000 +0000 @@ -46,11 +46,6 @@ GimpGuide *horizontal_guide; GimpGuide *vertical_guide; - - GList *ops; - gint cached_size; - gint cached_paint_width; - gint cached_paint_height; }; struct _GimpMandalaClass diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry-mirror.c gimp-2.10.14+om/app/core/gimpsymmetry-mirror.c --- gimp-2.10.8+zorin2/app/core/gimpsymmetry-mirror.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry-mirror.c 2019-06-12 16:43:38.000000000 +0000 @@ -71,13 +71,10 @@ static void gimp_mirror_update_strokes (GimpSymmetry *mirror, GimpDrawable *drawable, GimpCoords *origin); -static void gimp_mirror_prepare_operations (GimpMirror *mirror, - gint paint_width, - gint paint_height); -static GeglNode * gimp_mirror_get_operation (GimpSymmetry *mirror, +static void gimp_mirror_get_transform (GimpSymmetry *mirror, gint stroke, - gint paint_width, - gint paint_height); + gdouble *angle, + gboolean *reflect); static void gimp_mirror_reset (GimpMirror *mirror); static void gimp_mirror_add_guide (GimpMirror *mirror, GimpOrientationType orientation); @@ -122,7 +119,7 @@ symmetry_class->label = _("Mirror"); symmetry_class->update_strokes = gimp_mirror_update_strokes; - symmetry_class->get_operation = gimp_mirror_get_operation; + symmetry_class->get_transform = gimp_mirror_get_transform; symmetry_class->active_changed = gimp_mirror_active_changed; GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_HORIZONTAL_SYMMETRY, @@ -205,10 +202,6 @@ g_clear_object (&mirror->horizontal_guide); g_clear_object (&mirror->vertical_guide); - g_clear_object (&mirror->horizontal_op); - g_clear_object (&mirror->vertical_op); - g_clear_object (&mirror->central_op); - G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -365,78 +358,47 @@ } static void -gimp_mirror_prepare_operations (GimpMirror *mirror, - gint paint_width, - gint paint_height) +gimp_mirror_get_transform (GimpSymmetry *sym, + gint stroke, + gdouble *angle, + gboolean *reflect) { - if (paint_width == mirror->last_paint_width && - paint_height == mirror->last_paint_height) - return; + GimpMirror *mirror = GIMP_MIRROR (sym); - mirror->last_paint_width = paint_width; - mirror->last_paint_height = paint_height; + if (mirror->disable_transformation) + return; - if (mirror->horizontal_op) - g_object_unref (mirror->horizontal_op); + if (! mirror->horizontal_mirror && stroke >= 1) + stroke++; - mirror->horizontal_op = gegl_node_new_child (NULL, - "operation", "gegl:reflect", - "origin-x", 0.0, - "origin-y", paint_height / 2.0, - "x", 1.0, - "y", 0.0, - NULL); - - if (mirror->vertical_op) - g_object_unref (mirror->vertical_op); - - mirror->vertical_op = gegl_node_new_child (NULL, - "operation", "gegl:reflect", - "origin-x", paint_width / 2.0, - "origin-y", 0.0, - "x", 0.0, - "y", 1.0, - NULL); - - if (mirror->central_op) - g_object_unref (mirror->central_op); - - mirror->central_op = gegl_node_new_child (NULL, - "operation", "gegl:rotate", - "origin-x", paint_width / 2.0, - "origin-y", paint_height / 2.0, - "degrees", 180.0, - NULL); -} + if (! mirror->vertical_mirror && stroke >= 2) + stroke++; -static GeglNode * -gimp_mirror_get_operation (GimpSymmetry *sym, - gint stroke, - gint paint_width, - gint paint_height) -{ - GimpMirror *mirror = GIMP_MIRROR (sym); - GeglNode *op; + switch (stroke) + { + /* original */ + case 0: + break; - g_return_val_if_fail (stroke >= 0 && - stroke < g_list_length (sym->strokes), NULL); + /* horizontal */ + case 1: + *angle = 180.0; + *reflect = TRUE; + break; - gimp_mirror_prepare_operations (mirror, paint_width, paint_height); + /* vertical */ + case 2: + *reflect = TRUE; + break; - if (mirror->disable_transformation || stroke == 0 || - paint_width == 0 || paint_height == 0) - op = NULL; - else if (stroke == 1 && mirror->horizontal_mirror) - op = g_object_ref (mirror->horizontal_op); - else if ((stroke == 2 && mirror->horizontal_mirror && - mirror->vertical_mirror) || - (stroke == 1 && mirror->vertical_mirror && - ! mirror->horizontal_mirror)) - op = g_object_ref (mirror->vertical_op); - else - op = g_object_ref (mirror->central_op); + /* central */ + case 3: + *angle = 180.0; + break; - return op; + default: + g_return_if_reached (); + } } static void diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry-mirror.h gimp-2.10.14+om/app/core/gimpsymmetry-mirror.h --- gimp-2.10.8+zorin2/app/core/gimpsymmetry-mirror.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry-mirror.h 2019-06-12 16:43:38.000000000 +0000 @@ -37,24 +37,17 @@ struct _GimpMirror { - GimpSymmetry parent_instance; + GimpSymmetry parent_instance; - gboolean horizontal_mirror; - gboolean vertical_mirror; - gboolean point_symmetry; - gboolean disable_transformation; + gboolean horizontal_mirror; + gboolean vertical_mirror; + gboolean point_symmetry; + gboolean disable_transformation; - gdouble mirror_position_y; - gdouble mirror_position_x; - GimpGuide *horizontal_guide; - GimpGuide *vertical_guide; - - /* Cached data */ - gint last_paint_width; - gint last_paint_height; - GeglNode *horizontal_op; - GeglNode *vertical_op; - GeglNode *central_op; + gdouble mirror_position_y; + gdouble mirror_position_x; + GimpGuide *horizontal_guide; + GimpGuide *vertical_guide; }; struct _GimpMirrorClass diff -Nru gimp-2.10.8+zorin2/app/core/gimpsymmetry-tiling.c gimp-2.10.14+om/app/core/gimpsymmetry-tiling.c --- gimp-2.10.8+zorin2/app/core/gimpsymmetry-tiling.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpsymmetry-tiling.c 2019-06-12 16:43:38.000000000 +0000 @@ -70,10 +70,6 @@ static void gimp_tiling_update_strokes (GimpSymmetry *tiling, GimpDrawable *drawable, GimpCoords *origin); -static GeglNode * gimp_tiling_get_operation (GimpSymmetry *tiling, - gint stroke, - gint paint_width, - gint paint_height); static void gimp_tiling_image_size_changed_cb (GimpImage *image, gint previous_origin_x, gint previous_origin_y, @@ -101,7 +97,6 @@ symmetry_class->label = _("Tiling"); symmetry_class->update_strokes = gimp_tiling_update_strokes; - symmetry_class->get_operation = gimp_tiling_get_operation; GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_INTERVAL_X, "interval-x", @@ -431,16 +426,6 @@ g_signal_emit_by_name (sym, "strokes-updated", sym->image); } -static GeglNode * -gimp_tiling_get_operation (GimpSymmetry *sym, - gint stroke, - gint paint_width, - gint paint_height) -{ - /* No buffer transformation happens for tiling. */ - return NULL; -} - static void gimp_tiling_image_size_changed_cb (GimpImage *image, gint previous_origin_x, diff -Nru gimp-2.10.8+zorin2/app/core/gimptagcache.c gimp-2.10.14+om/app/core/gimptagcache.c --- gimp-2.10.8+zorin2/app/core/gimptagcache.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimptagcache.c 2019-01-03 14:13:22.000000000 +0000 @@ -430,11 +430,22 @@ g_printerr ("%s\n", error->message); } else if (! g_output_stream_write_all (output, buf->str, buf->len, - NULL, NULL, &error) || - ! g_output_stream_close (output, NULL, &error)) + NULL, NULL, &error)) { + GCancellable *cancellable = g_cancellable_new (); + g_printerr (_("Error writing '%s': %s\n"), gimp_file_get_utf8_name (file), error->message); + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); + } + else if (! g_output_stream_close (output, NULL, &error)) + { + g_printerr (_("Error closing '%s': %s\n"), + gimp_file_get_utf8_name (file), error->message); } if (output) diff -Nru gimp-2.10.8+zorin2/app/core/gimp-tags.c gimp-2.10.14+om/app/core/gimp-tags.c --- gimp-2.10.8+zorin2/app/core/gimp-tags.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-tags.c 2019-01-03 14:13:22.000000000 +0000 @@ -138,12 +138,24 @@ else if (! g_output_stream_write_all (output, tags_installer.buf->str, tags_installer.buf->len, - NULL, NULL, &error) || - ! g_output_stream_close (output, NULL, &error)) + NULL, NULL, &error)) { + GCancellable *cancellable = g_cancellable_new (); + g_printerr (_("Error writing '%s': %s"), gimp_file_get_utf8_name (file), error->message); result = FALSE; + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); + } + else if (! g_output_stream_close (output, NULL, &error)) + { + g_printerr (_("Error closing '%s': %s"), + gimp_file_get_utf8_name (file), error->message); + result = FALSE; } if (output) diff -Nru gimp-2.10.8+zorin2/app/core/gimptempbuf.c gimp-2.10.14+om/app/core/gimptempbuf.c --- gimp-2.10.8+zorin2/app/core/gimptempbuf.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimptempbuf.c 2019-04-07 11:38:14.000000000 +0000 @@ -32,6 +32,9 @@ #include "gimptempbuf.h" +#define LOCK_DATA_ALIGNMENT 16 + + struct _GimpTempBuf { gint ref_count; @@ -41,6 +44,21 @@ guchar *data; }; +typedef struct +{ + const Babl *format; + GeglAccessMode access_mode; +} LockData; + +G_STATIC_ASSERT (sizeof (LockData) <= LOCK_DATA_ALIGNMENT); + + +/* local variables */ + +static guintptr gimp_temp_buf_total_memsize = 0; + + +/* public functions */ GimpTempBuf * gimp_temp_buf_new (gint width, @@ -65,6 +83,9 @@ temp->format = format; temp->data = gegl_malloc ((gsize) width * height * bpp); + g_atomic_pointer_add (&gimp_temp_buf_total_memsize, + +gimp_temp_buf_get_memsize (temp)); + return temp; } @@ -132,29 +153,31 @@ } GimpTempBuf * -gimp_temp_buf_ref (GimpTempBuf *buf) +gimp_temp_buf_ref (const GimpTempBuf *buf) { g_return_val_if_fail (buf != NULL, NULL); - buf->ref_count++; + g_atomic_int_inc ((gint *) &buf->ref_count); - return buf; + return (GimpTempBuf *) buf; } void -gimp_temp_buf_unref (GimpTempBuf *buf) +gimp_temp_buf_unref (const GimpTempBuf *buf) { g_return_if_fail (buf != NULL); g_return_if_fail (buf->ref_count > 0); - buf->ref_count--; - - if (buf->ref_count < 1) + if (g_atomic_int_dec_and_test ((gint *) &buf->ref_count)) { + g_atomic_pointer_add (&gimp_temp_buf_total_memsize, + -gimp_temp_buf_get_memsize (buf)); + + if (buf->data) gegl_free (buf->data); - g_slice_free (GimpTempBuf, buf); + g_slice_free (GimpTempBuf, (GimpTempBuf *) buf); } } @@ -262,6 +285,75 @@ return buf->data; } +gpointer +gimp_temp_buf_lock (const GimpTempBuf *buf, + const Babl *format, + GeglAccessMode access_mode) +{ + guchar *data; + LockData *lock_data; + gint n_pixels; + gint bpp; + + g_return_val_if_fail (buf != NULL, NULL); + + if (! format || format == buf->format) + return gimp_temp_buf_get_data (buf); + + n_pixels = buf->width * buf->height; + bpp = babl_format_get_bytes_per_pixel (format); + + data = gegl_scratch_alloc (LOCK_DATA_ALIGNMENT + n_pixels * bpp); + + if ((guintptr) data % LOCK_DATA_ALIGNMENT) + { + g_free (data); + + g_return_val_if_reached (NULL); + } + + lock_data = (LockData *) data; + lock_data->format = format; + lock_data->access_mode = access_mode; + + data += LOCK_DATA_ALIGNMENT; + + if (access_mode & GEGL_ACCESS_READ) + { + babl_process (babl_fish (buf->format, format), + gimp_temp_buf_get_data (buf), + data, + n_pixels); + } + + return data; +} + +void +gimp_temp_buf_unlock (const GimpTempBuf *buf, + gconstpointer data) +{ + LockData *lock_data; + + g_return_if_fail (buf != NULL); + g_return_if_fail (data != NULL); + + if (data == buf->data) + return; + + lock_data = (LockData *) ((const guint8 *) data - LOCK_DATA_ALIGNMENT); + + if (lock_data->access_mode & GEGL_ACCESS_WRITE) + { + babl_process (babl_fish (lock_data->format, buf->format), + data, + gimp_temp_buf_get_data (buf), + buf->width * buf->height); + } + + gegl_scratch_free (lock_data); +} + gsize gimp_temp_buf_get_memsize (const GimpTempBuf *buf) { @@ -271,8 +363,8 @@ return 0; } -GeglBuffer * -gimp_temp_buf_create_buffer (GimpTempBuf *temp_buf) +GeglBuffer * +gimp_temp_buf_create_buffer (const GimpTempBuf *temp_buf) { GeglBuffer *buffer; @@ -288,13 +380,14 @@ (GDestroyNotify) gimp_temp_buf_unref, gimp_temp_buf_ref (temp_buf)); - g_object_set_data (G_OBJECT (buffer), "gimp-temp-buf", temp_buf); + g_object_set_data (G_OBJECT (buffer), + "gimp-temp-buf", (GimpTempBuf *) temp_buf); return buffer; } GdkPixbuf * -gimp_temp_buf_create_pixbuf (GimpTempBuf *temp_buf) +gimp_temp_buf_create_pixbuf (const GimpTempBuf *temp_buf) { GdkPixbuf *pixbuf; const Babl *format; @@ -346,3 +439,12 @@ return g_object_get_data (G_OBJECT (buffer), "gimp-temp-buf"); } + + +/* public functions (stats) */ + +guint64 +gimp_temp_buf_get_total_memsize (void) +{ + return gimp_temp_buf_total_memsize; +} diff -Nru gimp-2.10.8+zorin2/app/core/gimptempbuf.h gimp-2.10.14+om/app/core/gimptempbuf.h --- gimp-2.10.8+zorin2/app/core/gimptempbuf.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimptempbuf.h 2019-04-07 11:38:14.000000000 +0000 @@ -19,39 +19,49 @@ #define __GIMP_TEMP_BUF_H__ -GimpTempBuf * gimp_temp_buf_new (gint width, - gint height, - const Babl *format) G_GNUC_WARN_UNUSED_RESULT; -GimpTempBuf * gimp_temp_buf_new_from_pixbuf (GdkPixbuf *pixbuf, - const Babl *f_or_null) G_GNUC_WARN_UNUSED_RESULT; -GimpTempBuf * gimp_temp_buf_copy (const GimpTempBuf *src) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_temp_buf_new (gint width, + gint height, + const Babl *format) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_temp_buf_new_from_pixbuf (GdkPixbuf *pixbuf, + const Babl *f_or_null) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_temp_buf_copy (const GimpTempBuf *src) G_GNUC_WARN_UNUSED_RESULT; -GimpTempBuf * gimp_temp_buf_ref (GimpTempBuf *buf); -void gimp_temp_buf_unref (GimpTempBuf *buf); +GimpTempBuf * gimp_temp_buf_ref (const GimpTempBuf *buf); +void gimp_temp_buf_unref (const GimpTempBuf *buf); -GimpTempBuf * gimp_temp_buf_scale (const GimpTempBuf *buf, - gint width, - gint height) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_temp_buf_scale (const GimpTempBuf *buf, + gint width, + gint height) G_GNUC_WARN_UNUSED_RESULT; -gint gimp_temp_buf_get_width (const GimpTempBuf *buf); -gint gimp_temp_buf_get_height (const GimpTempBuf *buf); +gint gimp_temp_buf_get_width (const GimpTempBuf *buf); +gint gimp_temp_buf_get_height (const GimpTempBuf *buf); -const Babl * gimp_temp_buf_get_format (const GimpTempBuf *buf); -void gimp_temp_buf_set_format (GimpTempBuf *buf, - const Babl *format); +const Babl * gimp_temp_buf_get_format (const GimpTempBuf *buf); +void gimp_temp_buf_set_format (GimpTempBuf *buf, + const Babl *format); -guchar * gimp_temp_buf_get_data (const GimpTempBuf *buf); -gsize gimp_temp_buf_get_data_size (const GimpTempBuf *buf); +guchar * gimp_temp_buf_get_data (const GimpTempBuf *buf); +gsize gimp_temp_buf_get_data_size (const GimpTempBuf *buf); -guchar * gimp_temp_buf_data_clear (GimpTempBuf *buf); +guchar * gimp_temp_buf_data_clear (GimpTempBuf *buf); -gsize gimp_temp_buf_get_memsize (const GimpTempBuf *buf); +gpointer gimp_temp_buf_lock (const GimpTempBuf *buf, + const Babl *format, + GeglAccessMode access_mode) G_GNUC_WARN_UNUSED_RESULT; +void gimp_temp_buf_unlock (const GimpTempBuf *buf, + gconstpointer data); -GeglBuffer * gimp_temp_buf_create_buffer (GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; -GdkPixbuf * gimp_temp_buf_create_pixbuf (GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; +gsize gimp_temp_buf_get_memsize (const GimpTempBuf *buf); -GimpTempBuf * gimp_gegl_buffer_get_temp_buf (GeglBuffer *buffer); +GeglBuffer * gimp_temp_buf_create_buffer (const GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; +GdkPixbuf * gimp_temp_buf_create_pixbuf (const GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_gegl_buffer_get_temp_buf (GeglBuffer *buffer); + + +/* stats */ + +guint64 gimp_temp_buf_get_total_memsize (void); #endif /* __GIMP_TEMP_BUF_H__ */ diff -Nru gimp-2.10.8+zorin2/app/core/gimptilehandlerprojectable.c gimp-2.10.14+om/app/core/gimptilehandlerprojectable.c --- gimp-2.10.8+zorin2/app/core/gimptilehandlerprojectable.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimptilehandlerprojectable.c 2019-01-03 14:13:22.000000000 +0000 @@ -27,11 +27,8 @@ #include "gimptilehandlerprojectable.h" -static void gimp_tile_handler_projectable_validate (GimpTileHandlerValidate *validate, - const GeglRectangle *rect, - const Babl *format, - gpointer dest_buf, - gint dest_stride); +static void gimp_tile_handler_projectable_begin_validate (GimpTileHandlerValidate *validate); +static void gimp_tile_handler_projectable_end_validate (GimpTileHandlerValidate *validate); G_DEFINE_TYPE (GimpTileHandlerProjectable, gimp_tile_handler_projectable, @@ -47,7 +44,8 @@ validate_class = GIMP_TILE_HANDLER_VALIDATE_CLASS (klass); - validate_class->validate = gimp_tile_handler_projectable_validate; + validate_class->begin_validate = gimp_tile_handler_projectable_begin_validate; + validate_class->end_validate = gimp_tile_handler_projectable_end_validate; } static void @@ -56,24 +54,23 @@ } static void -gimp_tile_handler_projectable_validate (GimpTileHandlerValidate *validate, - const GeglRectangle *rect, - const Babl *format, - gpointer dest_buf, - gint dest_stride) +gimp_tile_handler_projectable_begin_validate (GimpTileHandlerValidate *validate) { GimpTileHandlerProjectable *handler = GIMP_TILE_HANDLER_PROJECTABLE (validate); - GeglNode *graph; - graph = gimp_projectable_get_graph (handler->projectable); + GIMP_TILE_HANDLER_VALIDATE_CLASS (parent_class)->begin_validate (validate); gimp_projectable_begin_render (handler->projectable); +} - gegl_node_blit (graph, 1.0, rect, format, - dest_buf, dest_stride, - GEGL_BLIT_DEFAULT); +static void +gimp_tile_handler_projectable_end_validate (GimpTileHandlerValidate *validate) +{ + GimpTileHandlerProjectable *handler = GIMP_TILE_HANDLER_PROJECTABLE (validate); gimp_projectable_end_render (handler->projectable); + + GIMP_TILE_HANDLER_VALIDATE_CLASS (parent_class)->end_validate (validate); } GeglTileHandler * @@ -85,6 +82,9 @@ handler = g_object_new (GIMP_TYPE_TILE_HANDLER_PROJECTABLE, NULL); + GIMP_TILE_HANDLER_VALIDATE (handler)->graph = + g_object_ref (gimp_projectable_get_graph (projectable)); + handler->projectable = projectable; return GEGL_TILE_HANDLER (handler); diff -Nru gimp-2.10.8+zorin2/app/core/gimptoolpreset.c gimp-2.10.14+om/app/core/gimptoolpreset.c --- gimp-2.10.8+zorin2/app/core/gimptoolpreset.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimptoolpreset.c 2019-06-12 16:43:38.000000000 +0000 @@ -174,7 +174,7 @@ "use-pattern", _("Apply stored pattern"), NULL, - TRUE, + DEFAULT_USE_PATTERN, GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_USE_PALETTE, @@ -208,7 +208,6 @@ static void gimp_tool_preset_init (GimpToolPreset *tool_preset) { - tool_preset->tool_options = NULL; } static void diff -Nru gimp-2.10.8+zorin2/app/core/gimp-transform-utils.c gimp-2.10.14+om/app/core/gimp-transform-utils.c --- gimp-2.10.8+zorin2/app/core/gimp-transform-utils.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-transform-utils.c 2019-04-07 11:38:14.000000000 +0000 @@ -441,8 +441,9 @@ { GimpMatrix3 trafo; gdouble coeff[8 * 9]; - gboolean negative; + gboolean negative = -1; gint i; + gboolean result = TRUE; g_return_val_if_fail (matrix != NULL, FALSE); g_return_val_if_fail (input_points != NULL, FALSE); @@ -494,21 +495,26 @@ trafo.coeff[2][2]; if (fabs (w) <= EPSILON) - return FALSE; + result = FALSE; neg = (w < 0.0); - if (i == 0) - negative = neg; + if (negative < 0) + { + negative = neg; + } else if (neg != negative) - return FALSE; + { + result = FALSE; + break; + } } /* if the output points are all behind the camera, negate the matrix, which * would map the input points to the corresponding points in front of the * camera. */ - if (negative) + if (negative > 0) { gint r; gint c; @@ -525,7 +531,7 @@ /* append the transformation to 'matrix' */ gimp_matrix3_mult (&trafo, matrix); - return TRUE; + return result; } gboolean diff -Nru gimp-2.10.8+zorin2/app/core/gimp-units.c gimp-2.10.14+om/app/core/gimp-units.c --- gimp-2.10.8+zorin2/app/core/gimp-units.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-units.c 2019-10-26 18:49:18.000000000 +0000 @@ -334,8 +334,8 @@ gimp_config_writer_open (writer, "factor"); gimp_config_writer_print (writer, - g_ascii_formatd (buf, sizeof (buf), "%f", - _gimp_unit_get_factor (gimp, i)), + g_ascii_dtostr (buf, sizeof (buf), + _gimp_unit_get_factor (gimp, i)), -1); gimp_config_writer_close (writer); diff -Nru gimp-2.10.8+zorin2/app/core/gimp-user-install.c gimp-2.10.14+om/app/core/gimp-user-install.c --- gimp-2.10.8+zorin2/app/core/gimp-user-install.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-user-install.c 2019-04-07 11:38:14.000000000 +0000 @@ -88,7 +88,6 @@ } gimp_user_install_items[] = { - { "gtkrc", USER_INSTALL_COPY }, { "menurc", USER_INSTALL_COPY }, { "brushes", USER_INSTALL_MKDIR }, { "dynamics", USER_INSTALL_MKDIR }, diff -Nru gimp-2.10.8+zorin2/app/core/gimp-utils.c gimp-2.10.14+om/app/core/gimp-utils.c --- gimp-2.10.8+zorin2/app/core/gimp-utils.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-utils.c 2019-06-12 16:43:38.000000000 +0000 @@ -858,6 +858,29 @@ return TRUE; } +gint +gimp_g_list_compare (GList *list1, + GList *list2) +{ + while (list1 && list2) + { + if (list1->data < list2->data) + return -1; + else if (list1->data > list2->data) + return +1; + + list1 = g_list_next (list1); + list2 = g_list_next (list2); + } + + if (! list1) + return -1; + else if (! list2) + return +1; + + return 0; +} + /* debug stuff */ diff -Nru gimp-2.10.8+zorin2/app/core/gimp-utils.h gimp-2.10.14+om/app/core/gimp-utils.h --- gimp-2.10.8+zorin2/app/core/gimp-utils.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimp-utils.h 2019-06-12 16:43:38.000000000 +0000 @@ -98,6 +98,9 @@ gchar **endptr, gdouble *result); +gint gimp_g_list_compare (GList *list1, + GList *list2); + GimpImage * gimp_create_image_from_buffer (Gimp *gimp, GeglBuffer *buffer, const gchar *image_name); diff -Nru gimp-2.10.8+zorin2/app/core/gimpviewable.c gimp-2.10.14+om/app/core/gimpviewable.c --- gimp-2.10.8+zorin2/app/core/gimpviewable.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpviewable.c 2019-10-26 18:49:18.000000000 +0000 @@ -68,6 +68,8 @@ gchar *icon_name; GdkPixbuf *icon_pixbuf; gint freeze_count; + gboolean invalidate_pending; + gboolean size_changed_prending; GimpViewable *parent; gint depth; @@ -206,6 +208,8 @@ klass->get_new_pixbuf = gimp_viewable_real_get_new_pixbuf; klass->get_description = gimp_viewable_real_get_description; klass->is_name_editable = gimp_viewable_real_is_name_editable; + klass->preview_freeze = NULL; + klass->preview_thaw = NULL; klass->get_children = gimp_viewable_real_get_children; klass->set_expanded = NULL; klass->get_expanded = NULL; @@ -586,6 +590,8 @@ if (private->freeze_count == 0) g_signal_emit (viewable, viewable_signals[INVALIDATE_PREVIEW], 0); + else + private->invalidate_pending = TRUE; } /** @@ -599,9 +605,16 @@ void gimp_viewable_size_changed (GimpViewable *viewable) { + GimpViewablePrivate *private; + g_return_if_fail (GIMP_IS_VIEWABLE (viewable)); - g_signal_emit (viewable, viewable_signals[SIZE_CHANGED], 0); + private = GET_PRIVATE (viewable); + + if (private->freeze_count == 0) + g_signal_emit (viewable, viewable_signals[SIZE_CHANGED], 0); + else + private->size_changed_prending = TRUE; } /** @@ -1251,8 +1264,7 @@ private = GET_PRIVATE (viewable); - g_free (private->icon_name); - private->icon_name = NULL; + g_clear_pointer (&private->icon_name, g_free); viewable_class = GIMP_VIEWABLE_GET_CLASS (viewable); @@ -1280,7 +1292,12 @@ private->freeze_count++; if (private->freeze_count == 1) - g_object_notify (G_OBJECT (viewable), "frozen"); + { + if (GIMP_VIEWABLE_GET_CLASS (viewable)->preview_freeze) + GIMP_VIEWABLE_GET_CLASS (viewable)->preview_freeze (viewable); + + g_object_notify (G_OBJECT (viewable), "frozen"); + } } void @@ -1298,8 +1315,24 @@ if (private->freeze_count == 0) { - gimp_viewable_invalidate_preview (viewable); + if (private->size_changed_prending) + { + private->size_changed_prending = FALSE; + + gimp_viewable_size_changed (viewable); + } + + if (private->invalidate_pending) + { + private->invalidate_pending = FALSE; + + gimp_viewable_invalidate_preview (viewable); + } + g_object_notify (G_OBJECT (viewable), "frozen"); + + if (GIMP_VIEWABLE_GET_CLASS (viewable)->preview_thaw) + GIMP_VIEWABLE_GET_CLASS (viewable)->preview_thaw (viewable); } } diff -Nru gimp-2.10.8+zorin2/app/core/gimpviewable.h gimp-2.10.14+om/app/core/gimpviewable.h --- gimp-2.10.8+zorin2/app/core/gimpviewable.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/core/gimpviewable.h 2019-04-07 11:38:14.000000000 +0000 @@ -97,6 +97,9 @@ gboolean (* is_name_editable) (GimpViewable *viewable); + void (* preview_freeze) (GimpViewable *viewable); + void (* preview_thaw) (GimpViewable *viewable); + GimpContainer * (* get_children) (GimpViewable *viewable); void (* set_expanded) (GimpViewable *viewable, diff -Nru gimp-2.10.8+zorin2/app/core/Makefile.am gimp-2.10.14+om/app/core/Makefile.am --- gimp-2.10.8+zorin2/app/core/Makefile.am 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/core/Makefile.am 2019-10-26 18:49:18.000000000 +0000 @@ -111,6 +111,8 @@ gimpbrush-load.c \ gimpbrush-load.h \ gimpbrush-private.h \ + gimpbrush-save.c \ + gimpbrush-save.h \ gimpbrush-transform.cc \ gimpbrush-transform.h \ gimpbrushcache.c \ @@ -127,6 +129,8 @@ gimpbrushpipe.h \ gimpbrushpipe-load.c \ gimpbrushpipe-load.h \ + gimpbrushpipe-save.c \ + gimpbrushpipe-save.h \ gimpbuffer.c \ gimpbuffer.h \ gimpcancelable.c \ @@ -141,6 +145,8 @@ gimpchannelpropundo.h \ gimpchannelundo.c \ gimpchannelundo.h \ + gimpchunkiterator.c \ + gimpchunkiterator.h \ gimpcontainer.c \ gimpcontainer.h \ gimpcontainer-filter.c \ @@ -274,8 +280,6 @@ gimpimage-crop.h \ gimpimage-duplicate.c \ gimpimage-duplicate.h \ - gimpimage-fade.c \ - gimpimage-fade.h \ gimpimage-flip.c \ gimpimage-flip.h \ gimpimage-grid.h \ @@ -311,12 +315,16 @@ gimpimage-snap.h \ gimpimage-symmetry.c \ gimpimage-symmetry.h \ + gimpimage-transform.c \ + gimpimage-transform.h \ gimpimage-undo.c \ gimpimage-undo.h \ gimpimage-undo-push.c \ gimpimage-undo-push.h \ gimpimageundo.c \ gimpimageundo.h \ + gimpimageviewable.c \ + gimpimageviewable.h \ gimpimagefile.c \ gimpimagefile.h \ gimpitem.c \ @@ -353,6 +361,8 @@ gimplayerstack.h \ gimplayerundo.c \ gimplayerundo.h \ + gimplineart.c \ + gimplineart.h \ gimplist.c \ gimplist.h \ gimpmaskundo.c \ @@ -373,6 +383,8 @@ gimppattern-header.h \ gimppattern-load.c \ gimppattern-load.h \ + gimppattern-save.c \ + gimppattern-save.h \ gimppatternclipboard.c \ gimppatternclipboard.h \ gimppalette.c \ @@ -399,7 +411,7 @@ gimppickable.h \ gimppickable-auto-shrink.c \ gimppickable-auto-shrink.h \ - gimppickable-contiguous-region.c \ + gimppickable-contiguous-region.cc \ gimppickable-contiguous-region.h \ gimpprogress.c \ gimpprogress.h \ diff -Nru gimp-2.10.8+zorin2/app/core/Makefile.in gimp-2.10.14+om/app/core/Makefile.in --- gimp-2.10.8+zorin2/app/core/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/core/Makefile.in 2019-10-27 17:12:52.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -140,14 +139,15 @@ gimpbacktrace-windows.$(OBJEXT) gimpbezierdesc.$(OBJEXT) \ gimpboundary.$(OBJEXT) gimpbrush.$(OBJEXT) \ gimpbrush-boundary.$(OBJEXT) gimpbrush-load.$(OBJEXT) \ - gimpbrush-transform.$(OBJEXT) gimpbrushcache.$(OBJEXT) \ - gimpbrushclipboard.$(OBJEXT) gimpbrushgenerated.$(OBJEXT) \ - gimpbrushgenerated-load.$(OBJEXT) \ + gimpbrush-save.$(OBJEXT) gimpbrush-transform.$(OBJEXT) \ + gimpbrushcache.$(OBJEXT) gimpbrushclipboard.$(OBJEXT) \ + gimpbrushgenerated.$(OBJEXT) gimpbrushgenerated-load.$(OBJEXT) \ gimpbrushgenerated-save.$(OBJEXT) gimpbrushpipe.$(OBJEXT) \ - gimpbrushpipe-load.$(OBJEXT) gimpbuffer.$(OBJEXT) \ - gimpcancelable.$(OBJEXT) gimpchannel.$(OBJEXT) \ - gimpchannel-combine.$(OBJEXT) gimpchannel-select.$(OBJEXT) \ - gimpchannelpropundo.$(OBJEXT) gimpchannelundo.$(OBJEXT) \ + gimpbrushpipe-load.$(OBJEXT) gimpbrushpipe-save.$(OBJEXT) \ + gimpbuffer.$(OBJEXT) gimpcancelable.$(OBJEXT) \ + gimpchannel.$(OBJEXT) gimpchannel-combine.$(OBJEXT) \ + gimpchannel-select.$(OBJEXT) gimpchannelpropundo.$(OBJEXT) \ + gimpchannelundo.$(OBJEXT) gimpchunkiterator.$(OBJEXT) \ gimpcontainer.$(OBJEXT) gimpcontainer-filter.$(OBJEXT) \ gimpcontext.$(OBJEXT) gimpcoords.$(OBJEXT) \ gimpcoords-interpolate.$(OBJEXT) gimpcurve.$(OBJEXT) \ @@ -183,35 +183,36 @@ gimpimage-convert-indexed.$(OBJEXT) \ gimpimage-convert-precision.$(OBJEXT) \ gimpimage-convert-type.$(OBJEXT) gimpimage-crop.$(OBJEXT) \ - gimpimage-duplicate.$(OBJEXT) gimpimage-fade.$(OBJEXT) \ - gimpimage-flip.$(OBJEXT) gimpimage-grid.$(OBJEXT) \ - gimpimage-guides.$(OBJEXT) gimpimage-item-list.$(OBJEXT) \ - gimpimage-merge.$(OBJEXT) gimpimage-metadata.$(OBJEXT) \ - gimpimage-new.$(OBJEXT) gimpimage-pick-color.$(OBJEXT) \ - gimpimage-pick-item.$(OBJEXT) gimpimage-preview.$(OBJEXT) \ - gimpimage-quick-mask.$(OBJEXT) gimpimage-resize.$(OBJEXT) \ - gimpimage-rotate.$(OBJEXT) gimpimage-sample-points.$(OBJEXT) \ - gimpimage-scale.$(OBJEXT) gimpimage-snap.$(OBJEXT) \ - gimpimage-symmetry.$(OBJEXT) gimpimage-undo.$(OBJEXT) \ + gimpimage-duplicate.$(OBJEXT) gimpimage-flip.$(OBJEXT) \ + gimpimage-grid.$(OBJEXT) gimpimage-guides.$(OBJEXT) \ + gimpimage-item-list.$(OBJEXT) gimpimage-merge.$(OBJEXT) \ + gimpimage-metadata.$(OBJEXT) gimpimage-new.$(OBJEXT) \ + gimpimage-pick-color.$(OBJEXT) gimpimage-pick-item.$(OBJEXT) \ + gimpimage-preview.$(OBJEXT) gimpimage-quick-mask.$(OBJEXT) \ + gimpimage-resize.$(OBJEXT) gimpimage-rotate.$(OBJEXT) \ + gimpimage-sample-points.$(OBJEXT) gimpimage-scale.$(OBJEXT) \ + gimpimage-snap.$(OBJEXT) gimpimage-symmetry.$(OBJEXT) \ + gimpimage-transform.$(OBJEXT) gimpimage-undo.$(OBJEXT) \ gimpimage-undo-push.$(OBJEXT) gimpimageundo.$(OBJEXT) \ - gimpimagefile.$(OBJEXT) gimpitem.$(OBJEXT) \ - gimpitem-exclusive.$(OBJEXT) gimpitem-linked.$(OBJEXT) \ - gimpitem-preview.$(OBJEXT) gimpitempropundo.$(OBJEXT) \ - gimpitemstack.$(OBJEXT) gimpitemtree.$(OBJEXT) \ - gimpitemundo.$(OBJEXT) gimplayer.$(OBJEXT) \ - gimplayer-floating-selection.$(OBJEXT) gimplayer-new.$(OBJEXT) \ - gimplayermask.$(OBJEXT) gimplayermaskpropundo.$(OBJEXT) \ - gimplayermaskundo.$(OBJEXT) gimplayerpropundo.$(OBJEXT) \ - gimplayerstack.$(OBJEXT) gimplayerundo.$(OBJEXT) \ + gimpimageviewable.$(OBJEXT) gimpimagefile.$(OBJEXT) \ + gimpitem.$(OBJEXT) gimpitem-exclusive.$(OBJEXT) \ + gimpitem-linked.$(OBJEXT) gimpitem-preview.$(OBJEXT) \ + gimpitempropundo.$(OBJEXT) gimpitemstack.$(OBJEXT) \ + gimpitemtree.$(OBJEXT) gimpitemundo.$(OBJEXT) \ + gimplayer.$(OBJEXT) gimplayer-floating-selection.$(OBJEXT) \ + gimplayer-new.$(OBJEXT) gimplayermask.$(OBJEXT) \ + gimplayermaskpropundo.$(OBJEXT) gimplayermaskundo.$(OBJEXT) \ + gimplayerpropundo.$(OBJEXT) gimplayerstack.$(OBJEXT) \ + gimplayerundo.$(OBJEXT) gimplineart.$(OBJEXT) \ gimplist.$(OBJEXT) gimpmaskundo.$(OBJEXT) \ gimpmybrush.$(OBJEXT) gimpmybrush-load.$(OBJEXT) \ gimpobject.$(OBJEXT) gimpobjectqueue.$(OBJEXT) \ gimppaintinfo.$(OBJEXT) gimppattern.$(OBJEXT) \ - gimppattern-load.$(OBJEXT) gimppatternclipboard.$(OBJEXT) \ - gimppalette.$(OBJEXT) gimppalette-import.$(OBJEXT) \ - gimppalette-load.$(OBJEXT) gimppalette-save.$(OBJEXT) \ - gimppalettemru.$(OBJEXT) gimpparamspecs.$(OBJEXT) \ - gimpparamspecs-desc.$(OBJEXT) \ + gimppattern-load.$(OBJEXT) gimppattern-save.$(OBJEXT) \ + gimppatternclipboard.$(OBJEXT) gimppalette.$(OBJEXT) \ + gimppalette-import.$(OBJEXT) gimppalette-load.$(OBJEXT) \ + gimppalette-save.$(OBJEXT) gimppalettemru.$(OBJEXT) \ + gimpparamspecs.$(OBJEXT) gimpparamspecs-desc.$(OBJEXT) \ gimpparamspecs-duplicate.$(OBJEXT) gimpparasitelist.$(OBJEXT) \ gimppdbprogress.$(OBJEXT) gimppickable.$(OBJEXT) \ gimppickable-auto-shrink.$(OBJEXT) \ @@ -272,19 +273,21 @@ ./$(DEPDIR)/gimpbacktrace-windows.Po \ ./$(DEPDIR)/gimpbezierdesc.Po ./$(DEPDIR)/gimpboundary.Po \ ./$(DEPDIR)/gimpbrush-boundary.Po \ - ./$(DEPDIR)/gimpbrush-load.Po \ + ./$(DEPDIR)/gimpbrush-load.Po ./$(DEPDIR)/gimpbrush-save.Po \ ./$(DEPDIR)/gimpbrush-transform.Po ./$(DEPDIR)/gimpbrush.Po \ ./$(DEPDIR)/gimpbrushcache.Po \ ./$(DEPDIR)/gimpbrushclipboard.Po \ ./$(DEPDIR)/gimpbrushgenerated-load.Po \ ./$(DEPDIR)/gimpbrushgenerated-save.Po \ ./$(DEPDIR)/gimpbrushgenerated.Po \ - ./$(DEPDIR)/gimpbrushpipe-load.Po ./$(DEPDIR)/gimpbrushpipe.Po \ + ./$(DEPDIR)/gimpbrushpipe-load.Po \ + ./$(DEPDIR)/gimpbrushpipe-save.Po ./$(DEPDIR)/gimpbrushpipe.Po \ ./$(DEPDIR)/gimpbuffer.Po ./$(DEPDIR)/gimpcancelable.Po \ ./$(DEPDIR)/gimpchannel-combine.Po \ ./$(DEPDIR)/gimpchannel-select.Po ./$(DEPDIR)/gimpchannel.Po \ ./$(DEPDIR)/gimpchannelpropundo.Po \ ./$(DEPDIR)/gimpchannelundo.Po \ + ./$(DEPDIR)/gimpchunkiterator.Po \ ./$(DEPDIR)/gimpcontainer-filter.Po \ ./$(DEPDIR)/gimpcontainer.Po ./$(DEPDIR)/gimpcontext.Po \ ./$(DEPDIR)/gimpcoords-interpolate.Po \ @@ -335,8 +338,8 @@ ./$(DEPDIR)/gimpimage-convert-type.Po \ ./$(DEPDIR)/gimpimage-crop.Po \ ./$(DEPDIR)/gimpimage-duplicate.Po \ - ./$(DEPDIR)/gimpimage-fade.Po ./$(DEPDIR)/gimpimage-flip.Po \ - ./$(DEPDIR)/gimpimage-grid.Po ./$(DEPDIR)/gimpimage-guides.Po \ + ./$(DEPDIR)/gimpimage-flip.Po ./$(DEPDIR)/gimpimage-grid.Po \ + ./$(DEPDIR)/gimpimage-guides.Po \ ./$(DEPDIR)/gimpimage-item-list.Po \ ./$(DEPDIR)/gimpimage-merge.Po \ ./$(DEPDIR)/gimpimage-metadata.Po ./$(DEPDIR)/gimpimage-new.Po \ @@ -349,9 +352,11 @@ ./$(DEPDIR)/gimpimage-sample-points.Po \ ./$(DEPDIR)/gimpimage-scale.Po ./$(DEPDIR)/gimpimage-snap.Po \ ./$(DEPDIR)/gimpimage-symmetry.Po \ + ./$(DEPDIR)/gimpimage-transform.Po \ ./$(DEPDIR)/gimpimage-undo-push.Po \ ./$(DEPDIR)/gimpimage-undo.Po ./$(DEPDIR)/gimpimage.Po \ ./$(DEPDIR)/gimpimagefile.Po ./$(DEPDIR)/gimpimageundo.Po \ + ./$(DEPDIR)/gimpimageviewable.Po \ ./$(DEPDIR)/gimpitem-exclusive.Po \ ./$(DEPDIR)/gimpitem-linked.Po ./$(DEPDIR)/gimpitem-preview.Po \ ./$(DEPDIR)/gimpitem.Po ./$(DEPDIR)/gimpitempropundo.Po \ @@ -363,18 +368,20 @@ ./$(DEPDIR)/gimplayermaskpropundo.Po \ ./$(DEPDIR)/gimplayermaskundo.Po \ ./$(DEPDIR)/gimplayerpropundo.Po ./$(DEPDIR)/gimplayerstack.Po \ - ./$(DEPDIR)/gimplayerundo.Po ./$(DEPDIR)/gimplist.Po \ - ./$(DEPDIR)/gimpmarshal.Po ./$(DEPDIR)/gimpmaskundo.Po \ - ./$(DEPDIR)/gimpmybrush-load.Po ./$(DEPDIR)/gimpmybrush.Po \ - ./$(DEPDIR)/gimpobject.Po ./$(DEPDIR)/gimpobjectqueue.Po \ - ./$(DEPDIR)/gimppaintinfo.Po ./$(DEPDIR)/gimppalette-import.Po \ + ./$(DEPDIR)/gimplayerundo.Po ./$(DEPDIR)/gimplineart.Po \ + ./$(DEPDIR)/gimplist.Po ./$(DEPDIR)/gimpmarshal.Po \ + ./$(DEPDIR)/gimpmaskundo.Po ./$(DEPDIR)/gimpmybrush-load.Po \ + ./$(DEPDIR)/gimpmybrush.Po ./$(DEPDIR)/gimpobject.Po \ + ./$(DEPDIR)/gimpobjectqueue.Po ./$(DEPDIR)/gimppaintinfo.Po \ + ./$(DEPDIR)/gimppalette-import.Po \ ./$(DEPDIR)/gimppalette-load.Po \ ./$(DEPDIR)/gimppalette-save.Po ./$(DEPDIR)/gimppalette.Po \ ./$(DEPDIR)/gimppalettemru.Po \ ./$(DEPDIR)/gimpparamspecs-desc.Po \ ./$(DEPDIR)/gimpparamspecs-duplicate.Po \ ./$(DEPDIR)/gimpparamspecs.Po ./$(DEPDIR)/gimpparasitelist.Po \ - ./$(DEPDIR)/gimppattern-load.Po ./$(DEPDIR)/gimppattern.Po \ + ./$(DEPDIR)/gimppattern-load.Po \ + ./$(DEPDIR)/gimppattern-save.Po ./$(DEPDIR)/gimppattern.Po \ ./$(DEPDIR)/gimppatternclipboard.Po \ ./$(DEPDIR)/gimppdbprogress.Po \ ./$(DEPDIR)/gimppickable-auto-shrink.Po \ @@ -493,8 +500,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -624,7 +629,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -763,8 +767,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -994,6 +996,8 @@ gimpbrush-load.c \ gimpbrush-load.h \ gimpbrush-private.h \ + gimpbrush-save.c \ + gimpbrush-save.h \ gimpbrush-transform.cc \ gimpbrush-transform.h \ gimpbrushcache.c \ @@ -1010,6 +1014,8 @@ gimpbrushpipe.h \ gimpbrushpipe-load.c \ gimpbrushpipe-load.h \ + gimpbrushpipe-save.c \ + gimpbrushpipe-save.h \ gimpbuffer.c \ gimpbuffer.h \ gimpcancelable.c \ @@ -1024,6 +1030,8 @@ gimpchannelpropundo.h \ gimpchannelundo.c \ gimpchannelundo.h \ + gimpchunkiterator.c \ + gimpchunkiterator.h \ gimpcontainer.c \ gimpcontainer.h \ gimpcontainer-filter.c \ @@ -1157,8 +1165,6 @@ gimpimage-crop.h \ gimpimage-duplicate.c \ gimpimage-duplicate.h \ - gimpimage-fade.c \ - gimpimage-fade.h \ gimpimage-flip.c \ gimpimage-flip.h \ gimpimage-grid.h \ @@ -1194,12 +1200,16 @@ gimpimage-snap.h \ gimpimage-symmetry.c \ gimpimage-symmetry.h \ + gimpimage-transform.c \ + gimpimage-transform.h \ gimpimage-undo.c \ gimpimage-undo.h \ gimpimage-undo-push.c \ gimpimage-undo-push.h \ gimpimageundo.c \ gimpimageundo.h \ + gimpimageviewable.c \ + gimpimageviewable.h \ gimpimagefile.c \ gimpimagefile.h \ gimpitem.c \ @@ -1236,6 +1246,8 @@ gimplayerstack.h \ gimplayerundo.c \ gimplayerundo.h \ + gimplineart.c \ + gimplineart.h \ gimplist.c \ gimplist.h \ gimpmaskundo.c \ @@ -1256,6 +1268,8 @@ gimppattern-header.h \ gimppattern-load.c \ gimppattern-load.h \ + gimppattern-save.c \ + gimppattern-save.h \ gimppatternclipboard.c \ gimppatternclipboard.h \ gimppalette.c \ @@ -1282,7 +1296,7 @@ gimppickable.h \ gimppickable-auto-shrink.c \ gimppickable-auto-shrink.h \ - gimppickable-contiguous-region.c \ + gimppickable-contiguous-region.cc \ gimppickable-contiguous-region.h \ gimpprogress.c \ gimpprogress.h \ @@ -1460,6 +1474,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpboundary.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrush-boundary.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrush-load.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrush-save.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrush-transform.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrush.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushcache.Po@am__quote@ # am--include-marker @@ -1468,6 +1483,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushgenerated-save.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushgenerated.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushpipe-load.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushpipe-save.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbrushpipe.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbuffer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcancelable.Po@am__quote@ # am--include-marker @@ -1476,6 +1492,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpchannel.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpchannelpropundo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpchannelundo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpchunkiterator.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcontainer-filter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcontainer.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcontext.Po@am__quote@ # am--include-marker @@ -1540,7 +1557,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-convert-type.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-crop.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-duplicate.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-fade.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-flip.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-grid.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-guides.Po@am__quote@ # am--include-marker @@ -1558,11 +1574,13 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-scale.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-snap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-symmetry.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-transform.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-undo-push.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage-undo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimage.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimagefile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimageundo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpimageviewable.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpitem-exclusive.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpitem-linked.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpitem-preview.Po@am__quote@ # am--include-marker @@ -1580,6 +1598,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimplayerpropundo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimplayerstack.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimplayerundo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimplineart.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimplist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmarshal.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmaskundo.Po@am__quote@ # am--include-marker @@ -1598,6 +1617,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpparamspecs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpparasitelist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimppattern-load.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimppattern-save.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimppattern.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimppatternclipboard.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimppdbprogress.Po@am__quote@ # am--include-marker @@ -1858,6 +1878,7 @@ -rm -f ./$(DEPDIR)/gimpboundary.Po -rm -f ./$(DEPDIR)/gimpbrush-boundary.Po -rm -f ./$(DEPDIR)/gimpbrush-load.Po + -rm -f ./$(DEPDIR)/gimpbrush-save.Po -rm -f ./$(DEPDIR)/gimpbrush-transform.Po -rm -f ./$(DEPDIR)/gimpbrush.Po -rm -f ./$(DEPDIR)/gimpbrushcache.Po @@ -1866,6 +1887,7 @@ -rm -f ./$(DEPDIR)/gimpbrushgenerated-save.Po -rm -f ./$(DEPDIR)/gimpbrushgenerated.Po -rm -f ./$(DEPDIR)/gimpbrushpipe-load.Po + -rm -f ./$(DEPDIR)/gimpbrushpipe-save.Po -rm -f ./$(DEPDIR)/gimpbrushpipe.Po -rm -f ./$(DEPDIR)/gimpbuffer.Po -rm -f ./$(DEPDIR)/gimpcancelable.Po @@ -1874,6 +1896,7 @@ -rm -f ./$(DEPDIR)/gimpchannel.Po -rm -f ./$(DEPDIR)/gimpchannelpropundo.Po -rm -f ./$(DEPDIR)/gimpchannelundo.Po + -rm -f ./$(DEPDIR)/gimpchunkiterator.Po -rm -f ./$(DEPDIR)/gimpcontainer-filter.Po -rm -f ./$(DEPDIR)/gimpcontainer.Po -rm -f ./$(DEPDIR)/gimpcontext.Po @@ -1938,7 +1961,6 @@ -rm -f ./$(DEPDIR)/gimpimage-convert-type.Po -rm -f ./$(DEPDIR)/gimpimage-crop.Po -rm -f ./$(DEPDIR)/gimpimage-duplicate.Po - -rm -f ./$(DEPDIR)/gimpimage-fade.Po -rm -f ./$(DEPDIR)/gimpimage-flip.Po -rm -f ./$(DEPDIR)/gimpimage-grid.Po -rm -f ./$(DEPDIR)/gimpimage-guides.Po @@ -1956,11 +1978,13 @@ -rm -f ./$(DEPDIR)/gimpimage-scale.Po -rm -f ./$(DEPDIR)/gimpimage-snap.Po -rm -f ./$(DEPDIR)/gimpimage-symmetry.Po + -rm -f ./$(DEPDIR)/gimpimage-transform.Po -rm -f ./$(DEPDIR)/gimpimage-undo-push.Po -rm -f ./$(DEPDIR)/gimpimage-undo.Po -rm -f ./$(DEPDIR)/gimpimage.Po -rm -f ./$(DEPDIR)/gimpimagefile.Po -rm -f ./$(DEPDIR)/gimpimageundo.Po + -rm -f ./$(DEPDIR)/gimpimageviewable.Po -rm -f ./$(DEPDIR)/gimpitem-exclusive.Po -rm -f ./$(DEPDIR)/gimpitem-linked.Po -rm -f ./$(DEPDIR)/gimpitem-preview.Po @@ -1978,6 +2002,7 @@ -rm -f ./$(DEPDIR)/gimplayerpropundo.Po -rm -f ./$(DEPDIR)/gimplayerstack.Po -rm -f ./$(DEPDIR)/gimplayerundo.Po + -rm -f ./$(DEPDIR)/gimplineart.Po -rm -f ./$(DEPDIR)/gimplist.Po -rm -f ./$(DEPDIR)/gimpmarshal.Po -rm -f ./$(DEPDIR)/gimpmaskundo.Po @@ -1996,6 +2021,7 @@ -rm -f ./$(DEPDIR)/gimpparamspecs.Po -rm -f ./$(DEPDIR)/gimpparasitelist.Po -rm -f ./$(DEPDIR)/gimppattern-load.Po + -rm -f ./$(DEPDIR)/gimppattern-save.Po -rm -f ./$(DEPDIR)/gimppattern.Po -rm -f ./$(DEPDIR)/gimppatternclipboard.Po -rm -f ./$(DEPDIR)/gimppdbprogress.Po @@ -2117,6 +2143,7 @@ -rm -f ./$(DEPDIR)/gimpboundary.Po -rm -f ./$(DEPDIR)/gimpbrush-boundary.Po -rm -f ./$(DEPDIR)/gimpbrush-load.Po + -rm -f ./$(DEPDIR)/gimpbrush-save.Po -rm -f ./$(DEPDIR)/gimpbrush-transform.Po -rm -f ./$(DEPDIR)/gimpbrush.Po -rm -f ./$(DEPDIR)/gimpbrushcache.Po @@ -2125,6 +2152,7 @@ -rm -f ./$(DEPDIR)/gimpbrushgenerated-save.Po -rm -f ./$(DEPDIR)/gimpbrushgenerated.Po -rm -f ./$(DEPDIR)/gimpbrushpipe-load.Po + -rm -f ./$(DEPDIR)/gimpbrushpipe-save.Po -rm -f ./$(DEPDIR)/gimpbrushpipe.Po -rm -f ./$(DEPDIR)/gimpbuffer.Po -rm -f ./$(DEPDIR)/gimpcancelable.Po @@ -2133,6 +2161,7 @@ -rm -f ./$(DEPDIR)/gimpchannel.Po -rm -f ./$(DEPDIR)/gimpchannelpropundo.Po -rm -f ./$(DEPDIR)/gimpchannelundo.Po + -rm -f ./$(DEPDIR)/gimpchunkiterator.Po -rm -f ./$(DEPDIR)/gimpcontainer-filter.Po -rm -f ./$(DEPDIR)/gimpcontainer.Po -rm -f ./$(DEPDIR)/gimpcontext.Po @@ -2197,7 +2226,6 @@ -rm -f ./$(DEPDIR)/gimpimage-convert-type.Po -rm -f ./$(DEPDIR)/gimpimage-crop.Po -rm -f ./$(DEPDIR)/gimpimage-duplicate.Po - -rm -f ./$(DEPDIR)/gimpimage-fade.Po -rm -f ./$(DEPDIR)/gimpimage-flip.Po -rm -f ./$(DEPDIR)/gimpimage-grid.Po -rm -f ./$(DEPDIR)/gimpimage-guides.Po @@ -2215,11 +2243,13 @@ -rm -f ./$(DEPDIR)/gimpimage-scale.Po -rm -f ./$(DEPDIR)/gimpimage-snap.Po -rm -f ./$(DEPDIR)/gimpimage-symmetry.Po + -rm -f ./$(DEPDIR)/gimpimage-transform.Po -rm -f ./$(DEPDIR)/gimpimage-undo-push.Po -rm -f ./$(DEPDIR)/gimpimage-undo.Po -rm -f ./$(DEPDIR)/gimpimage.Po -rm -f ./$(DEPDIR)/gimpimagefile.Po -rm -f ./$(DEPDIR)/gimpimageundo.Po + -rm -f ./$(DEPDIR)/gimpimageviewable.Po -rm -f ./$(DEPDIR)/gimpitem-exclusive.Po -rm -f ./$(DEPDIR)/gimpitem-linked.Po -rm -f ./$(DEPDIR)/gimpitem-preview.Po @@ -2237,6 +2267,7 @@ -rm -f ./$(DEPDIR)/gimplayerpropundo.Po -rm -f ./$(DEPDIR)/gimplayerstack.Po -rm -f ./$(DEPDIR)/gimplayerundo.Po + -rm -f ./$(DEPDIR)/gimplineart.Po -rm -f ./$(DEPDIR)/gimplist.Po -rm -f ./$(DEPDIR)/gimpmarshal.Po -rm -f ./$(DEPDIR)/gimpmaskundo.Po @@ -2255,6 +2286,7 @@ -rm -f ./$(DEPDIR)/gimpparamspecs.Po -rm -f ./$(DEPDIR)/gimpparasitelist.Po -rm -f ./$(DEPDIR)/gimppattern-load.Po + -rm -f ./$(DEPDIR)/gimppattern-save.Po -rm -f ./$(DEPDIR)/gimppattern.Po -rm -f ./$(DEPDIR)/gimppatternclipboard.Po -rm -f ./$(DEPDIR)/gimppdbprogress.Po diff -Nru gimp-2.10.8+zorin2/app/dialogs/action-search-dialog.c gimp-2.10.14+om/app/dialogs/action-search-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/action-search-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/action-search-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,6 +36,7 @@ #include "core/gimp.h" #include "widgets/gimpaction.h" +#include "widgets/gimpactiongroup.h" #include "widgets/gimpaction-history.h" #include "widgets/gimpdialogfactory.h" #include "widgets/gimpsearchpopup.h" @@ -49,7 +50,7 @@ static void action_search_history_and_actions (GimpSearchPopup *popup, const gchar *keyword, gpointer data); -static gboolean action_search_match_keyword (GtkAction *action, +static gboolean action_search_match_keyword (GimpAction *action, const gchar* keyword, gint *section, Gimp *gimp); @@ -97,11 +98,11 @@ /* First put on top of the list any matching action of user history. */ for (list = history_actions; list; list = g_list_next (list)) { - gimp_search_popup_add_result (popup, GTK_ACTION (list->data), 0); + gimp_search_popup_add_result (popup, list->data, 0); } /* Now check other actions. */ - for (list = gtk_ui_manager_get_action_groups (GTK_UI_MANAGER (manager)); + for (list = gimp_ui_manager_get_action_groups (manager); list; list = g_list_next (list)) { @@ -109,17 +110,17 @@ GimpActionGroup *group = list->data; GList *actions = NULL; - actions = gtk_action_group_list_actions (GTK_ACTION_GROUP (group)); + actions = gimp_action_group_list_actions (group); actions = g_list_sort (actions, (GCompareFunc) gimp_action_name_compare); for (list2 = actions; list2; list2 = g_list_next (list2)) { const gchar *name; - GtkAction *action = list2->data; + GimpAction *action = list2->data; gboolean is_redundant = FALSE; gint section; - name = gtk_action_get_name (action); + name = gimp_action_get_name (action); /* The action search dialog doesn't show any non-historized * actions, with a few exceptions. See the difference between @@ -129,8 +130,8 @@ if (gimp_action_history_is_blacklisted_action (name)) continue; - if (! gtk_action_is_visible (action) || - (! gtk_action_is_sensitive (action) && + if (! gimp_action_is_visible (action) || + (! gimp_action_is_sensitive (action) && ! GIMP_GUI_CONFIG (gimp->config)->search_show_unavailable)) continue; @@ -143,7 +144,7 @@ */ for (list3 = history_actions; list3; list3 = g_list_next (list3)) { - if (strcmp (gtk_action_get_name (GTK_ACTION (list3->data)), + if (strcmp (gimp_action_get_name (list3->data), name) == 0) { is_redundant = TRUE; @@ -165,7 +166,7 @@ } static gboolean -action_search_match_keyword (GtkAction *action, +action_search_match_keyword (GimpAction *action, const gchar *keyword, gint *section, Gimp *gimp) @@ -189,7 +190,7 @@ } key_tokens = g_str_tokenize_and_fold (keyword, gimp->config->language, NULL); - tmp = gimp_strip_uline (gtk_action_get_label (action)); + tmp = gimp_strip_uline (gimp_action_get_label (action)); label_tokens = g_str_tokenize_and_fold (tmp, gimp->config->language, &label_alternates); g_free (tmp); @@ -283,14 +284,14 @@ } if (! matched && key_tokens[0] && g_utf8_strlen (key_tokens[0], -1) > 2 && - gtk_action_get_tooltip (action) != NULL) + gimp_action_get_tooltip (action) != NULL) { gchar **tooltip_tokens; gchar **tooltip_alternates = NULL; gboolean mixed_match; gint i; - tooltip_tokens = g_str_tokenize_and_fold (gtk_action_get_tooltip (action), + tooltip_tokens = g_str_tokenize_and_fold (gimp_action_get_tooltip (action), gimp->config->language, &tooltip_alternates); if (g_strv_length (tooltip_tokens) > 0) diff -Nru gimp-2.10.8+zorin2/app/dialogs/authors.h gimp-2.10.14+om/app/dialogs/authors.h --- gimp-2.10.8+zorin2/app/dialogs/authors.h 2018-11-08 14:56:52.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/authors.h 2019-10-26 19:23:44.000000000 +0000 @@ -42,6 +42,7 @@ "Daniel Eddeland", "Ulf-D. Ehlert", "Gil Eliyahu", + "Tobias Ellinghaus", "Ell", "Dirk Farin", "Richard Gitschlag", @@ -102,10 +103,10 @@ "David Odin", "Nelson A. de Oliveira", "Victor Oliveira", + "Yoshio Ono", "Nathan Osman", "Benjamin Otte", "Petr Ovtchenkov", - "Jehan Pagès", "Juan Palacios", "Ville Pätsi", "Akkana Peck", @@ -120,6 +121,7 @@ "Marco Rossini", "Karthikeyan S", "Daniel Sabo", + "Oleksii Samorukov", "Enrico Schröder", "Michael Schumacher", "shark0r", @@ -144,6 +146,7 @@ "Clayton Walker", "Rupert Weber", "Alexis Wilhelm", + "woob", "Andrew Wyatt", "Yoshinori Yamakawa", "Mihail Zenkov", diff -Nru gimp-2.10.8+zorin2/app/dialogs/color-profile-import-dialog.c gimp-2.10.14+om/app/dialogs/color-profile-import-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/color-profile-import-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/color-profile-import-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -83,12 +83,12 @@ if (gimp_image_get_base_type (image) == GIMP_GRAY) { title = _("Convert to Grayscale Working Space?"); - frame_title = _("Convert the image to the grayscale working space?"); + frame_title = _("Convert the image to the built-in grayscale color profile?"); } else { title = _("Convert to RGB Working Space?"); - frame_title = _("Convert the image to the RGB working space?"); + frame_title = _("Convert the image to the built-in sRGB color profile?"); } dialog = diff -Nru gimp-2.10.8+zorin2/app/dialogs/convert-indexed-dialog.c gimp-2.10.14+om/app/dialogs/convert-indexed-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/convert-indexed-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/convert-indexed-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -200,7 +200,7 @@ adjustment = (GtkAdjustment *) gtk_adjustment_new (private->max_colors, 2, 256, 1, 8, 0); - spinbutton = gtk_spin_button_new (adjustment, 1.0, 0); + spinbutton = gimp_spin_button_new (adjustment, 1.0, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); @@ -277,7 +277,7 @@ toggle = - gtk_check_button_new_with_mnemonic (_("Enable dithering of text layers")); + gtk_check_button_new_with_mnemonic (_("Enable dithering of text _layers")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), private->dither_text_layers); gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); diff -Nru gimp-2.10.8+zorin2/app/dialogs/dialogs.c gimp-2.10.14+om/app/dialogs/dialogs.c --- gimp-2.10.8+zorin2/app/dialogs/dialogs.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/dialogs.c 2019-06-12 16:43:38.000000000 +0000 @@ -236,6 +236,7 @@ FOREIGN ("gimp-hue-saturation-tool-dialog", TRUE, FALSE), FOREIGN ("gimp-levels-tool-dialog", TRUE, TRUE), FOREIGN ("gimp-measure-tool-dialog", TRUE, FALSE), + FOREIGN ("gimp-offset-tool-dialog", TRUE, FALSE), FOREIGN ("gimp-operation-tool-dialog", TRUE, FALSE), FOREIGN ("gimp-posterize-tool-dialog", TRUE, FALSE), FOREIGN ("gimp-rotate-tool-dialog", TRUE, FALSE), diff -Nru gimp-2.10.8+zorin2/app/dialogs/fade-dialog.c gimp-2.10.14+om/app/dialogs/fade-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/fade-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/fade-dialog.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,214 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include -#include - -#include "libgimpbase/gimpbase.h" -#include "libgimpwidgets/gimpwidgets.h" - -#include "dialogs-types.h" - -#include "core/gimpcontext.h" -#include "core/gimpimage.h" -#include "core/gimpimage-fade.h" -#include "core/gimpimage-undo.h" -#include "core/gimpdrawable.h" -#include "core/gimpdrawableundo.h" -#include "core/gimpundostack.h" - -#include "widgets/gimplayermodebox.h" -#include "widgets/gimppropwidgets.h" -#include "widgets/gimphelp-ids.h" -#include "widgets/gimpviewabledialog.h" - -#include "fade-dialog.h" - -#include "gimp-intl.h" - - -typedef struct -{ - GimpImage *image; - GimpDrawable *drawable; - GimpContext *context; - - gboolean applied; - GimpLayerMode orig_paint_mode; - gdouble orig_opacity; -} FadeDialog; - - -/* local function prototypes */ - -static void fade_dialog_free (FadeDialog *private); -static void fade_dialog_response (GtkWidget *dialog, - gint response_id, - FadeDialog *private); -static void fade_dialog_context_changed (FadeDialog *private); - - -/* public functions */ - -GtkWidget * -fade_dialog_new (GimpImage *image, - GtkWidget *parent) -{ - FadeDialog *private; - GimpDrawableUndo *undo; - GimpDrawable *drawable; - GimpItem *item; - - GtkWidget *dialog; - GtkWidget *main_vbox; - GtkWidget *menu; - GtkWidget *scale; - gchar *title; - - g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); - g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); - - undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image)); - - if (! (undo && undo->applied_buffer)) - return NULL; - - item = GIMP_ITEM_UNDO (undo)->item; - drawable = GIMP_DRAWABLE (item); - - private = g_slice_new0 (FadeDialog); - - private->image = image; - private->drawable = drawable; - private->context = gimp_context_new (image->gimp, - "fade-dialog", NULL); - private->applied = FALSE; - private->orig_paint_mode = undo->paint_mode; - private->orig_opacity = undo->opacity; - - g_object_set (private->context, - "paint-mode", undo->paint_mode, - "opacity", undo->opacity, - NULL); - - title = g_strdup_printf (_("Fade %s"), gimp_object_get_name (undo)); - - dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (drawable), - private->context, - title, "gimp-edit-fade", - "edit-undo", title, - parent, - gimp_standard_help_func, - GIMP_HELP_EDIT_FADE, - - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_Fade"), GTK_RESPONSE_OK, - - NULL); - - g_free (title); - - gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - GTK_RESPONSE_CANCEL, - -1); - - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - g_object_weak_ref (G_OBJECT (dialog), - (GWeakNotify) fade_dialog_free, private); - - g_signal_connect (dialog, "response", - G_CALLBACK (fade_dialog_response), - private); - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), - main_vbox, TRUE, TRUE, 0); - gtk_widget_show (main_vbox); - - /* the paint mode menu */ - menu = gimp_prop_layer_mode_box_new (G_OBJECT (private->context), - "paint-mode", - GIMP_LAYER_MODE_CONTEXT_FADE); - gimp_layer_mode_box_set_label (GIMP_LAYER_MODE_BOX (menu), _("Mode")); - gtk_box_pack_start (GTK_BOX (main_vbox), menu, FALSE, FALSE, 0); - gtk_widget_show (menu); - - /* the opacity scale */ - scale = gimp_prop_spin_scale_new (G_OBJECT (private->context), - "opacity", - _("Opacity"), - 0.01, 0.1, 2); - gimp_prop_widget_set_factor (scale, 100, 1.0, 10.0, 1); - gtk_box_pack_start (GTK_BOX (main_vbox), scale, FALSE, FALSE, 0); - gtk_widget_show (scale); - - g_signal_connect_swapped (private->context, "paint-mode-changed", - G_CALLBACK (fade_dialog_context_changed), - private); - g_signal_connect_swapped (private->context, "opacity-changed", - G_CALLBACK (fade_dialog_context_changed), - private); - - return dialog; -} - - -/* private functions */ - -static void -fade_dialog_free (FadeDialog *private) -{ - g_slice_free (FadeDialog, private); -} - -static void -fade_dialog_response (GtkWidget *dialog, - gint response_id, - FadeDialog *private) -{ - g_signal_handlers_disconnect_by_func (private->context, - fade_dialog_context_changed, - private); - - if (response_id != GTK_RESPONSE_OK && private->applied) - { - g_object_set (private->context, - "paint-mode", private->orig_paint_mode, - "opacity", private->orig_opacity, - NULL); - - fade_dialog_context_changed (private); - } - - g_object_unref (private->context); - gtk_widget_destroy (dialog); -} - -static void -fade_dialog_context_changed (FadeDialog *private) -{ - if (gimp_image_fade (private->image, private->context)) - { - private->applied = TRUE; - gimp_image_flush (private->image); - } -} diff -Nru gimp-2.10.8+zorin2/app/dialogs/fade-dialog.h gimp-2.10.14+om/app/dialogs/fade-dialog.h --- gimp-2.10.8+zorin2/app/dialogs/fade-dialog.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/fade-dialog.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __FADE_DIALOG_H__ -#define __FADE_DIALOG_H__ - - -GtkWidget * fade_dialog_new (GimpImage *image, - GtkWidget *parent); - - -#endif /* __FADE_DIALOG_H__ */ diff -Nru gimp-2.10.8+zorin2/app/dialogs/file-open-dialog.c gimp-2.10.14+om/app/dialogs/file-open-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/file-open-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/file-open-dialog.c 2019-06-12 16:43:38.000000000 +0000 @@ -128,6 +128,9 @@ if (! open_dialog->open_as_layers) gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL); + if (file_dialog->image) + g_object_ref (file_dialog->image); + for (list = files; list; list = g_slist_next (list)) { GFile *file = list->data; @@ -136,13 +139,19 @@ { if (! file_dialog->image) { - file_dialog->image = file_open_dialog_open_image (dialog, - gimp, - file, - file_dialog->file_proc); + gimp_open_dialog_set_image ( + open_dialog, + file_open_dialog_open_image (dialog, + gimp, + file, + file_dialog->file_proc), + TRUE); if (file_dialog->image) - success = TRUE; + { + g_object_ref (file_dialog->image); + success = TRUE; + } } else if (file_open_dialog_open_layers (dialog, file_dialog->image, @@ -174,13 +183,21 @@ if (success) { - if (open_dialog->open_as_layers && file_dialog->image) - gimp_image_flush (file_dialog->image); + if (file_dialog->image) + { + if (open_dialog->open_as_layers) + gimp_image_flush (file_dialog->image); + + g_object_unref (file_dialog->image); + } gtk_widget_destroy (dialog); } else { + if (file_dialog->image) + g_object_unref (file_dialog->image); + gimp_file_dialog_set_sensitive (file_dialog, TRUE); } diff -Nru gimp-2.10.8+zorin2/app/dialogs/file-open-location-dialog.c gimp-2.10.14+om/app/dialogs/file-open-location-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/file-open-location-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/file-open-location-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -198,6 +198,10 @@ { GFile *entered_file = g_file_new_for_uri (text); + /* should not fail but does, see issue #3093 */ + if (! entered_file) + entered_file = g_object_ref (file); + gtk_widget_show (box); gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE); @@ -237,7 +241,9 @@ { gimp_message (gimp, G_OBJECT (box), GIMP_MESSAGE_ERROR, _("Opening '%s' failed:\n\n%s"), - text, error->message); + text, + /* error should never be NULL, also issue #3093 */ + error ? error->message : _("Invalid URI")); g_clear_error (&error); } } diff -Nru gimp-2.10.8+zorin2/app/dialogs/image-merge-layers-dialog.c gimp-2.10.14+om/app/dialogs/image-merge-layers-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/image-merge-layers-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/image-merge-layers-dialog.c 2019-04-07 11:38:14.000000000 +0000 @@ -182,7 +182,8 @@ private->context, private->merge_type, private->merge_active_group, - private->discard_invisible); + private->discard_invisible, + private->user_data); } else { diff -Nru gimp-2.10.8+zorin2/app/dialogs/image-merge-layers-dialog.h gimp-2.10.14+om/app/dialogs/image-merge-layers-dialog.h --- gimp-2.10.8+zorin2/app/dialogs/image-merge-layers-dialog.h 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/image-merge-layers-dialog.h 2019-04-07 11:38:14.000000000 +0000 @@ -24,7 +24,8 @@ GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, - gboolean discard_invisible); + gboolean discard_invisible, + gpointer user_data); GtkWidget * diff -Nru gimp-2.10.8+zorin2/app/dialogs/image-new-dialog.c gimp-2.10.14+om/app/dialogs/image-new-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/image-new-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/image-new-dialog.c 2019-06-12 16:43:38.000000000 +0000 @@ -347,7 +347,7 @@ gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("An image of the chosen size will use more " "memory than what is configured as " - "\"Maximum Image Size\" in the Preferences " + "\"Maximum new image size\" in the Preferences " "dialog (currently %s)."), size); g_free (size); diff -Nru gimp-2.10.8+zorin2/app/dialogs/image-properties-dialog.c gimp-2.10.14+om/app/dialogs/image-properties-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/image-properties-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/image-properties-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -81,17 +81,17 @@ view = gimp_image_prop_view_new (image); gtk_container_set_border_width (GTK_CONTAINER (view), 12); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - view, gtk_label_new (_("Properties"))); + view, gtk_label_new_with_mnemonic (_("_Properties"))); gtk_widget_show (view); view = gimp_image_profile_view_new (image); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - view, gtk_label_new (_("Color Profile"))); + view, gtk_label_new_with_mnemonic (_("C_olor Profile"))); gtk_widget_show (view); view = gimp_image_comment_editor_new (image); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), - view, gtk_label_new (_("Comment"))); + view, gtk_label_new_with_mnemonic (_("Co_mment"))); gtk_widget_show (view); gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0); diff -Nru gimp-2.10.8+zorin2/app/dialogs/input-devices-dialog.c gimp-2.10.14+om/app/dialogs/input-devices-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/input-devices-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/input-devices-dialog.c 2019-06-12 16:43:38.000000000 +0000 @@ -35,6 +35,9 @@ #include "gimp-intl.h" +#define RESPONSE_SAVE 1 + + /* local function prototypes */ static void input_devices_dialog_response (GtkWidget *dialog, @@ -59,16 +62,11 @@ gimp_standard_help_func, GIMP_HELP_INPUT_DEVICES, + _("_Save"), RESPONSE_SAVE, _("_Close"), GTK_RESPONSE_CLOSE, - _("_Save"), GTK_RESPONSE_OK, NULL); - gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - GTK_RESPONSE_CLOSE, - -1); - g_signal_connect (dialog, "response", G_CALLBACK (input_devices_dialog_response), gimp); @@ -93,7 +91,7 @@ { switch (response_id) { - case GTK_RESPONSE_OK: + case RESPONSE_SAVE: gimp_devices_save (gimp, TRUE); break; diff -Nru gimp-2.10.8+zorin2/app/dialogs/keyboard-shortcuts-dialog.c gimp-2.10.14+om/app/dialogs/keyboard-shortcuts-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/keyboard-shortcuts-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/keyboard-shortcuts-dialog.c 2019-06-12 16:43:38.000000000 +0000 @@ -30,11 +30,25 @@ #include "widgets/gimphelp-ids.h" #include "widgets/gimpuimanager.h" +#include "menus/menus.h" + #include "keyboard-shortcuts-dialog.h" #include "gimp-intl.h" +#define RESPONSE_SAVE 1 + + +/* local function prototypes */ + +static void keyboard_shortcuts_dialog_response (GtkWidget *dialog, + gint response, + Gimp *gimp); + + +/* public functions */ + GtkWidget * keyboard_shortcuts_dialog_new (Gimp *gimp) { @@ -52,13 +66,14 @@ gimp_standard_help_func, GIMP_HELP_KEYBOARD_SHORTCUTS, - _("_Close"), GTK_RESPONSE_OK, + _("_Save"), RESPONSE_SAVE, + _("_Close"), GTK_RESPONSE_CLOSE, NULL); g_signal_connect (dialog, "response", - G_CALLBACK (gtk_widget_destroy), - NULL); + G_CALLBACK (keyboard_shortcuts_dialog_response), + gimp); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); @@ -85,3 +100,23 @@ return dialog; } + + +/* private functions */ + +static void +keyboard_shortcuts_dialog_response (GtkWidget *dialog, + gint response, + Gimp *gimp) +{ + switch (response) + { + case RESPONSE_SAVE: + menus_save (gimp, TRUE); + break; + + default: + gtk_widget_destroy (dialog); + break; + } +} diff -Nru gimp-2.10.8+zorin2/app/dialogs/layer-options-dialog.c gimp-2.10.14+om/app/dialogs/layer-options-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/layer-options-dialog.c 2018-08-19 16:47:17.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/layer-options-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -200,7 +200,7 @@ private->blend_space_combo = combo = gimp_enum_combo_box_new_with_model (GIMP_ENUM_STORE (space_model)); - item_options_dialog_add_widget (dialog, _("Blend space:"), combo); + item_options_dialog_add_widget (dialog, _("_Blend space:"), combo); gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (combo), "gimp-layer-color-space"); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), @@ -210,7 +210,7 @@ private->composite_space_combo = combo = gimp_enum_combo_box_new_with_model (GIMP_ENUM_STORE (space_model)); - item_options_dialog_add_widget (dialog, _("Composite space:"), combo); + item_options_dialog_add_widget (dialog, _("Compos_ite space:"), combo); gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (combo), "gimp-layer-color-space"); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), @@ -222,7 +222,7 @@ private->composite_mode_combo = combo = gimp_enum_combo_box_new (GIMP_TYPE_LAYER_COMPOSITE_MODE); - item_options_dialog_add_widget (dialog, _("Composite mode:"), combo); + item_options_dialog_add_widget (dialog, _("Composite mo_de:"), combo); gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (combo), "gimp-layer-composite"); gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), @@ -264,7 +264,7 @@ /* The size sizeentry */ adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - spinbutton = gtk_spin_button_new (adjustment, 1.0, 2); + spinbutton = gimp_spin_button_new (adjustment, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); @@ -328,7 +328,7 @@ /* The offset sizeentry */ adjustment = (GtkAdjustment *) gtk_adjustment_new (0, 1, 1, 1, 10, 0); - spinbutton = gtk_spin_button_new (adjustment, 1.0, 2); + spinbutton = gimp_spin_button_new (adjustment, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); diff -Nru gimp-2.10.8+zorin2/app/dialogs/Makefile.am gimp-2.10.14+om/app/dialogs/Makefile.am --- gimp-2.10.8+zorin2/app/dialogs/Makefile.am 2018-03-25 12:35:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/Makefile.am 2019-06-12 16:43:38.000000000 +0000 @@ -35,8 +35,6 @@ convert-precision-dialog.h \ data-delete-dialog.c \ data-delete-dialog.h \ - fade-dialog.c \ - fade-dialog.h \ file-open-dialog.c \ file-open-dialog.h \ file-open-location-dialog.c \ @@ -69,8 +67,6 @@ lebl-dialog.h \ module-dialog.c \ module-dialog.h \ - offset-dialog.c \ - offset-dialog.h \ palette-import-dialog.c \ palette-import-dialog.h \ preferences-dialog.c \ diff -Nru gimp-2.10.8+zorin2/app/dialogs/Makefile.in gimp-2.10.14+om/app/dialogs/Makefile.in --- gimp-2.10.8+zorin2/app/dialogs/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -129,18 +128,16 @@ color-profile-import-dialog.$(OBJEXT) \ convert-indexed-dialog.$(OBJEXT) \ convert-precision-dialog.$(OBJEXT) \ - data-delete-dialog.$(OBJEXT) fade-dialog.$(OBJEXT) \ - file-open-dialog.$(OBJEXT) file-open-location-dialog.$(OBJEXT) \ - file-save-dialog.$(OBJEXT) fill-dialog.$(OBJEXT) \ - grid-dialog.$(OBJEXT) image-merge-layers-dialog.$(OBJEXT) \ - image-new-dialog.$(OBJEXT) image-properties-dialog.$(OBJEXT) \ - image-scale-dialog.$(OBJEXT) input-devices-dialog.$(OBJEXT) \ - item-options-dialog.$(OBJEXT) \ + data-delete-dialog.$(OBJEXT) file-open-dialog.$(OBJEXT) \ + file-open-location-dialog.$(OBJEXT) file-save-dialog.$(OBJEXT) \ + fill-dialog.$(OBJEXT) grid-dialog.$(OBJEXT) \ + image-merge-layers-dialog.$(OBJEXT) image-new-dialog.$(OBJEXT) \ + image-properties-dialog.$(OBJEXT) image-scale-dialog.$(OBJEXT) \ + input-devices-dialog.$(OBJEXT) item-options-dialog.$(OBJEXT) \ keyboard-shortcuts-dialog.$(OBJEXT) \ layer-add-mask-dialog.$(OBJEXT) layer-options-dialog.$(OBJEXT) \ lebl-dialog.$(OBJEXT) module-dialog.$(OBJEXT) \ - offset-dialog.$(OBJEXT) palette-import-dialog.$(OBJEXT) \ - preferences-dialog.$(OBJEXT) \ + palette-import-dialog.$(OBJEXT) preferences-dialog.$(OBJEXT) \ preferences-dialog-utils.$(OBJEXT) print-size-dialog.$(OBJEXT) \ quit-dialog.$(OBJEXT) resize-dialog.$(OBJEXT) \ resolution-calibrate-dialog.$(OBJEXT) scale-dialog.$(OBJEXT) \ @@ -175,7 +172,7 @@ ./$(DEPDIR)/convert-precision-dialog.Po \ ./$(DEPDIR)/data-delete-dialog.Po \ ./$(DEPDIR)/dialogs-constructors.Po ./$(DEPDIR)/dialogs.Po \ - ./$(DEPDIR)/fade-dialog.Po ./$(DEPDIR)/file-open-dialog.Po \ + ./$(DEPDIR)/file-open-dialog.Po \ ./$(DEPDIR)/file-open-location-dialog.Po \ ./$(DEPDIR)/file-save-dialog.Po ./$(DEPDIR)/fill-dialog.Po \ ./$(DEPDIR)/grid-dialog.Po \ @@ -188,7 +185,7 @@ ./$(DEPDIR)/keyboard-shortcuts-dialog.Po \ ./$(DEPDIR)/layer-add-mask-dialog.Po \ ./$(DEPDIR)/layer-options-dialog.Po ./$(DEPDIR)/lebl-dialog.Po \ - ./$(DEPDIR)/module-dialog.Po ./$(DEPDIR)/offset-dialog.Po \ + ./$(DEPDIR)/module-dialog.Po \ ./$(DEPDIR)/palette-import-dialog.Po \ ./$(DEPDIR)/preferences-dialog-utils.Po \ ./$(DEPDIR)/preferences-dialog.Po \ @@ -275,8 +272,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -406,7 +401,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -545,8 +539,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -703,8 +695,6 @@ convert-precision-dialog.h \ data-delete-dialog.c \ data-delete-dialog.h \ - fade-dialog.c \ - fade-dialog.h \ file-open-dialog.c \ file-open-dialog.h \ file-open-location-dialog.c \ @@ -737,8 +727,6 @@ lebl-dialog.h \ module-dialog.c \ module-dialog.h \ - offset-dialog.c \ - offset-dialog.h \ palette-import-dialog.c \ palette-import-dialog.h \ preferences-dialog.c \ @@ -839,7 +827,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-delete-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dialogs-constructors.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dialogs.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fade-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-open-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-open-location-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-save-dialog.Po@am__quote@ # am--include-marker @@ -856,7 +843,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer-options-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lebl-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module-dialog.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/offset-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palette-import-dialog.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preferences-dialog-utils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preferences-dialog.Po@am__quote@ # am--include-marker @@ -1042,7 +1028,6 @@ -rm -f ./$(DEPDIR)/data-delete-dialog.Po -rm -f ./$(DEPDIR)/dialogs-constructors.Po -rm -f ./$(DEPDIR)/dialogs.Po - -rm -f ./$(DEPDIR)/fade-dialog.Po -rm -f ./$(DEPDIR)/file-open-dialog.Po -rm -f ./$(DEPDIR)/file-open-location-dialog.Po -rm -f ./$(DEPDIR)/file-save-dialog.Po @@ -1059,7 +1044,6 @@ -rm -f ./$(DEPDIR)/layer-options-dialog.Po -rm -f ./$(DEPDIR)/lebl-dialog.Po -rm -f ./$(DEPDIR)/module-dialog.Po - -rm -f ./$(DEPDIR)/offset-dialog.Po -rm -f ./$(DEPDIR)/palette-import-dialog.Po -rm -f ./$(DEPDIR)/preferences-dialog-utils.Po -rm -f ./$(DEPDIR)/preferences-dialog.Po @@ -1131,7 +1115,6 @@ -rm -f ./$(DEPDIR)/data-delete-dialog.Po -rm -f ./$(DEPDIR)/dialogs-constructors.Po -rm -f ./$(DEPDIR)/dialogs.Po - -rm -f ./$(DEPDIR)/fade-dialog.Po -rm -f ./$(DEPDIR)/file-open-dialog.Po -rm -f ./$(DEPDIR)/file-open-location-dialog.Po -rm -f ./$(DEPDIR)/file-save-dialog.Po @@ -1148,7 +1131,6 @@ -rm -f ./$(DEPDIR)/layer-options-dialog.Po -rm -f ./$(DEPDIR)/lebl-dialog.Po -rm -f ./$(DEPDIR)/module-dialog.Po - -rm -f ./$(DEPDIR)/offset-dialog.Po -rm -f ./$(DEPDIR)/palette-import-dialog.Po -rm -f ./$(DEPDIR)/preferences-dialog-utils.Po -rm -f ./$(DEPDIR)/preferences-dialog.Po diff -Nru gimp-2.10.8+zorin2/app/dialogs/offset-dialog.c gimp-2.10.14+om/app/dialogs/offset-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/offset-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/offset-dialog.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,343 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include -#include - -#include "libgimpmath/gimpmath.h" -#include "libgimpwidgets/gimpwidgets.h" - -#include "dialogs-types.h" - -#include "core/gimp.h" -#include "core/gimpcontext.h" -#include "core/gimpdrawable.h" -#include "core/gimpitem.h" -#include "core/gimplayer.h" -#include "core/gimplayermask.h" -#include "core/gimpimage.h" - -#include "widgets/gimphelp-ids.h" -#include "widgets/gimpviewabledialog.h" - -#include "offset-dialog.h" - -#include "gimp-intl.h" - - -#define WRAP_AROUND (1 << 3) -#define FILL_MASK (GIMP_OFFSET_BACKGROUND | GIMP_OFFSET_TRANSPARENT) - - -typedef struct _OffsetDialog OffsetDialog; - -struct _OffsetDialog -{ - GimpDrawable *drawable; - GimpContext *context; - GimpOffsetType fill_type; - GimpOffsetCallback callback; - gpointer user_data; - - GtkWidget *off_se; -}; - - -/* local function prototypes */ - -static void offset_dialog_free (OffsetDialog *private); -static void offset_dialog_response (GtkWidget *dialog, - gint response_id, - OffsetDialog *private); -static void offset_dialog_half_xy_callback (GtkWidget *widget, - OffsetDialog *private); -static void offset_dialog_half_x_callback (GtkWidget *widget, - OffsetDialog *private); -static void offset_dialog_half_y_callback (GtkWidget *widget, - OffsetDialog *private); - - -/* public functions */ - -GtkWidget * -offset_dialog_new (GimpDrawable *drawable, - GimpContext *context, - GtkWidget *parent, - GimpOffsetCallback callback, - gpointer user_data) -{ - OffsetDialog *private; - GimpImage *image; - GimpItem *item; - GtkWidget *dialog; - GtkWidget *main_vbox; - GtkWidget *vbox; - GtkWidget *hbox; - GtkWidget *button; - GtkWidget *spinbutton; - GtkWidget *frame; - GtkWidget *radio_button; - GtkAdjustment *adjustment; - gdouble xres; - gdouble yres; - const gchar *title = NULL; - - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); - g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); - g_return_val_if_fail (GTK_IS_WIDGET (parent), NULL); - g_return_val_if_fail (callback != NULL, NULL); - - item = GIMP_ITEM (drawable); - image = gimp_item_get_image (item); - - private = g_slice_new0 (OffsetDialog); - - private->drawable = drawable; - private->context = context; - private->fill_type = gimp_drawable_has_alpha (drawable) | WRAP_AROUND; - private->callback = callback; - private->user_data = user_data; - - gimp_image_get_resolution (image, &xres, &yres); - - if (GIMP_IS_LAYER (drawable)) - title = _("Offset Layer"); - else if (GIMP_IS_LAYER_MASK (drawable)) - title = _("Offset Layer Mask"); - else if (GIMP_IS_CHANNEL (drawable)) - title = _("Offset Channel"); - else - g_warning ("%s: unexpected drawable type", G_STRFUNC); - - dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (drawable), context, - _("Offset"), "gimp-drawable-offset", - GIMP_ICON_TOOL_MOVE, - title, - parent, - gimp_standard_help_func, - GIMP_HELP_LAYER_OFFSET, - - _("_Cancel"), GTK_RESPONSE_CANCEL, - /* offset, used as a verb */ - _("_Offset"), GTK_RESPONSE_OK, - - NULL); - - gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), - GTK_RESPONSE_OK, - GTK_RESPONSE_CANCEL, - -1); - - gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); - - g_object_weak_ref (G_OBJECT (dialog), - (GWeakNotify) offset_dialog_free, private); - - g_signal_connect (dialog, "response", - G_CALLBACK (offset_dialog_response), - private); - - main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); - gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); - gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), - main_vbox, TRUE, TRUE, 0); - gtk_widget_show (main_vbox); - - /* The offset frame */ - frame = gimp_frame_new (_("Offset")); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - adjustment = (GtkAdjustment *) - gtk_adjustment_new (1, 1, 1, 1, 10, 0); - spinbutton = gtk_spin_button_new (adjustment, 1.0, 2); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); - gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); - - private->off_se = gimp_size_entry_new (1, GIMP_UNIT_PIXEL, "%a", - TRUE, TRUE, FALSE, 10, - GIMP_SIZE_ENTRY_UPDATE_SIZE); - - gtk_table_set_col_spacing (GTK_TABLE (private->off_se), 0, 4); - gtk_table_set_col_spacing (GTK_TABLE (private->off_se), 1, 4); - gtk_table_set_row_spacing (GTK_TABLE (private->off_se), 0, 2); - - gimp_size_entry_add_field (GIMP_SIZE_ENTRY (private->off_se), - GTK_SPIN_BUTTON (spinbutton), NULL); - gtk_table_attach_defaults (GTK_TABLE (private->off_se), spinbutton, - 1, 2, 0, 1); - gtk_widget_show (spinbutton); - - gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (private->off_se), - _("_X:"), 0, 0, 0.0); - gimp_size_entry_attach_label (GIMP_SIZE_ENTRY (private->off_se), - _("_Y:"), 1, 0, 0.0); - - gtk_box_pack_start (GTK_BOX (vbox), private->off_se, FALSE, FALSE, 0); - gtk_widget_show (private->off_se); - - gimp_size_entry_set_unit (GIMP_SIZE_ENTRY (private->off_se), GIMP_UNIT_PIXEL); - - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->off_se), 0, - xres, FALSE); - gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->off_se), 1, - yres, FALSE); - - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (private->off_se), 0, - - gimp_item_get_width (item), - gimp_item_get_width (item)); - gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (private->off_se), 1, - - gimp_item_get_height (item), - gimp_item_get_height (item)); - - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (private->off_se), 0, - 0, gimp_item_get_width (item)); - gimp_size_entry_set_size (GIMP_SIZE_ENTRY (private->off_se), 1, - 0, gimp_item_get_height (item)); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), 0, 0); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), 1, 0); - - button = gtk_button_new_with_mnemonic (_("By width/_2, height/2")); - gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); - gtk_widget_show (button); - - g_signal_connect (button, "clicked", - G_CALLBACK (offset_dialog_half_xy_callback), - private); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - button = gtk_button_new_with_mnemonic ("By _width/2"); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - - g_signal_connect (button, "clicked", - G_CALLBACK (offset_dialog_half_x_callback), - private); - - button = gtk_button_new_with_mnemonic ("By _height/2"); - gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); - gtk_widget_show (button); - - g_signal_connect (button, "clicked", - G_CALLBACK (offset_dialog_half_y_callback), - private); - - /* The edge behavior frame */ - frame = gimp_int_radio_group_new (TRUE, _("Edge Behavior"), - G_CALLBACK (gimp_radio_button_update), - &private->fill_type, private->fill_type, - - _("W_rap around"), - WRAP_AROUND, NULL, - - _("Fill with _background color"), - GIMP_OFFSET_BACKGROUND, NULL, - - _("Make _transparent"), - GIMP_OFFSET_TRANSPARENT, &radio_button, - NULL); - - if (! gimp_drawable_has_alpha (drawable)) - gtk_widget_set_sensitive (radio_button, FALSE); - - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); - gtk_widget_show (frame); - - return dialog; -} - - -/* private functions */ - -static void -offset_dialog_free (OffsetDialog *private) -{ - g_slice_free (OffsetDialog, private); -} - -static void -offset_dialog_response (GtkWidget *dialog, - gint response_id, - OffsetDialog *private) -{ - if (response_id == GTK_RESPONSE_OK) - { - gint offset_x; - gint offset_y; - - offset_x = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (private->off_se), - 0)); - offset_y = - RINT (gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (private->off_se), - 1)); - - private->callback (dialog, - private->drawable, - private->context, - private->fill_type & WRAP_AROUND ? TRUE : FALSE, - private->fill_type & FILL_MASK, - offset_x, - offset_y); - } - else - { - gtk_widget_destroy (dialog); - } -} - -static void -offset_dialog_half_xy_callback (GtkWidget *widget, - OffsetDialog *private) -{ - GimpItem *item = GIMP_ITEM (private->drawable); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), - 0, gimp_item_get_width (item) / 2); - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), - 1, gimp_item_get_height (item) / 2); -} - -static void -offset_dialog_half_x_callback (GtkWidget *widget, - OffsetDialog *private) -{ - GimpItem *item = GIMP_ITEM (private->drawable); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), - 0, gimp_item_get_width (item) / 2); -} - -static void -offset_dialog_half_y_callback (GtkWidget *widget, - OffsetDialog *private) -{ - GimpItem *item = GIMP_ITEM (private->drawable); - - gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (private->off_se), - 1, gimp_item_get_height (item) / 2); -} diff -Nru gimp-2.10.8+zorin2/app/dialogs/offset-dialog.h gimp-2.10.14+om/app/dialogs/offset-dialog.h --- gimp-2.10.8+zorin2/app/dialogs/offset-dialog.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/offset-dialog.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __OFFSET_DIALOG_H__ -#define __OFFSET_DIALOG_H__ - - -typedef void (* GimpOffsetCallback) (GtkWidget *dialog, - GimpDrawable *drawable, - GimpContext *context, - gboolean wrap_around, - GimpOffsetType fill_type, - gint offset_x, - gint offset_y); - - -GtkWidget * offset_dialog_new (GimpDrawable *drawable, - GimpContext *context, - GtkWidget *parent, - GimpOffsetCallback callback, - gpointer user_data); - - -#endif /* __OFFSET_DIALOG_H__ */ diff -Nru gimp-2.10.8+zorin2/app/dialogs/preferences-dialog.c gimp-2.10.14+om/app/dialogs/preferences-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/preferences-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/preferences-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -98,6 +98,10 @@ GObject *config); static void prefs_dialog_defaults_reset (GtkWidget *widget, GObject *config); +static void prefs_folders_reset (GtkWidget *widget, + GObject *config); +static void prefs_path_reset (GtkWidget *widget, + GObject *config); static void prefs_import_raw_procedure_callback (GtkWidget *widget, GObject *config); @@ -486,6 +490,30 @@ } static void +prefs_folders_reset (GtkWidget *widget, + GObject *config) +{ + gimp_config_reset_property (config, "temp-path"); + gimp_config_reset_property (config, "swap-path"); +} + +static void +prefs_path_reset (GtkWidget *widget, + GObject *config) +{ + const gchar *path_property; + const gchar *writable_property; + + path_property = g_object_get_data (G_OBJECT (widget), "path"); + writable_property = g_object_get_data (G_OBJECT (widget), "path-writable"); + + gimp_config_reset_property (config, path_property); + + if (writable_property) + gimp_config_reset_property (config, writable_property); +} + +static void prefs_template_select_callback (GimpContainerView *view, GimpTemplate *template, gpointer insert_data, @@ -929,6 +957,29 @@ gtk_box_pack_start (GTK_BOX (hbox), checks_vbox, TRUE, TRUE, 0); gtk_widget_show (checks_vbox); + prefs_check_button_add (object, "show-selection", + _("Show s_election"), + GTK_BOX (checks_vbox)); + prefs_check_button_add (object, "show-layer-boundary", + _("Show _layer boundary"), + GTK_BOX (checks_vbox)); + prefs_check_button_add (object, "show-canvas-boundary", + _("Show can_vas boundary"), + GTK_BOX (checks_vbox)); + prefs_check_button_add (object, "show-guides", + _("Show _guides"), + GTK_BOX (checks_vbox)); + prefs_check_button_add (object, "show-grid", + _("Show gri_d"), + GTK_BOX (checks_vbox)); + prefs_check_button_add (object, "show-sample-points", + _("Show _sample points"), + GTK_BOX (checks_vbox)); + + checks_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); + gtk_box_pack_start (GTK_BOX (hbox), checks_vbox, TRUE, TRUE, 0); + gtk_widget_show (checks_vbox); + #ifndef GDK_WINDOWING_QUARTZ prefs_check_button_add (object, "show-menubar", _("Show _menubar"), @@ -944,23 +995,6 @@ _("Show s_tatusbar"), GTK_BOX (checks_vbox)); - checks_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); - gtk_box_pack_start (GTK_BOX (hbox), checks_vbox, TRUE, TRUE, 0); - gtk_widget_show (checks_vbox); - - prefs_check_button_add (object, "show-selection", - _("Show s_election"), - GTK_BOX (checks_vbox)); - prefs_check_button_add (object, "show-layer-boundary", - _("Show _layer boundary"), - GTK_BOX (checks_vbox)); - prefs_check_button_add (object, "show-guides", - _("Show _guides"), - GTK_BOX (checks_vbox)); - prefs_check_button_add (object, "show-grid", - _("Show gri_d"), - GTK_BOX (checks_vbox)); - table = prefs_table_new (2, GTK_CONTAINER (vbox)); combo = prefs_enum_combo_box_add (object, "padding-mode", 0, 0, @@ -977,6 +1011,10 @@ g_signal_connect (button, "color-changed", G_CALLBACK (prefs_canvas_padding_color_changed), combo); + + prefs_check_button_add (object, "padding-in-show-all", + _("_Keep canvas padding in \"Show All\" mode"), + GTK_BOX (vbox)); } static void @@ -1000,10 +1038,10 @@ gtk_widget_show (checks_vbox); prefs_check_button_add (object, "snap-to-guides", - _("Snap to Guides"), + _("Snap to _Guides"), GTK_BOX (checks_vbox)); prefs_check_button_add (object, "snap-to-grid", - _("Snap to Grid"), + _("S_nap to Grid"), GTK_BOX (checks_vbox)); checks_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); @@ -1011,10 +1049,10 @@ gtk_widget_show (checks_vbox); prefs_check_button_add (object, "snap-to-canvas", - _("Snap to Canvas Edges"), + _("Snap to Canvas _Edges"), GTK_BOX (checks_vbox)); prefs_check_button_add (object, "snap-to-path", - _("Snap to Active Path"), + _("Snap to _Active Path"), GTK_BOX (checks_vbox)); } @@ -1134,9 +1172,9 @@ GTK_CONTAINER (vbox), FALSE); #ifdef ENABLE_MP - table = prefs_table_new (5, GTK_CONTAINER (vbox2)); + table = prefs_table_new (6, GTK_CONTAINER (vbox2)); #else - table = prefs_table_new (4, GTK_CONTAINER (vbox2)); + table = prefs_table_new (5, GTK_CONTAINER (vbox2)); #endif /* ENABLE_MP */ prefs_spin_button_add (object, "undo-levels", 1.0, 5.0, 0, @@ -1152,10 +1190,14 @@ _("Maximum _new image size:"), GTK_TABLE (table), 3, size_group); + prefs_compression_combo_box_add (object, "swap-compression", + _("S_wap compression:"), + GTK_TABLE (table), 4, size_group); + #ifdef ENABLE_MP prefs_spin_button_add (object, "num-processors", 1.0, 4.0, 0, _("Number of _threads to use:"), - GTK_TABLE (table), 4, size_group); + GTK_TABLE (table), 5, size_group); #endif /* ENABLE_MP */ /* Hardware Acceleration */ @@ -1163,9 +1205,15 @@ FALSE); prefs_check_button_add (object, "use-opencl", - _("Use OpenCL"), + _("Use O_penCL"), GTK_BOX (vbox2)); + hbox = prefs_hint_box_new (GIMP_ICON_DIALOG_WARNING, + _("OpenCL drivers and support are experimental, " + "expect slowdowns and possible crashes " + "(please report).")); + gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); + /* Image Thumbnails */ vbox2 = prefs_frame_new (_("Image Thumbnails"), GTK_CONTAINER (vbox), FALSE); @@ -1179,16 +1227,15 @@ _("Maximum _filesize for thumbnailing:"), GTK_TABLE (table), 1, size_group); - g_object_unref (size_group); - size_group = NULL; - /* Document History */ vbox2 = prefs_frame_new (_("Document History"), GTK_CONTAINER (vbox), FALSE); prefs_check_button_add (object, "save-document-history", - _("Keep record of used files in the Recent Documents list"), + _("_Keep record of used files in the Recent Documents list"), GTK_BOX (vbox2)); + g_clear_object (&size_group); + /***************/ /* Debugging */ @@ -1221,12 +1268,11 @@ vbox2 = prefs_frame_new (_("Bug Reporting"), GTK_CONTAINER (vbox), FALSE); - size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); table = prefs_table_new (1, GTK_CONTAINER (vbox2)); button = prefs_enum_combo_box_add (object, "debug-policy", 0, 0, _("Debug _policy:"), - GTK_TABLE (table), 0, size_group); + GTK_TABLE (table), 0, NULL); /* Check existence of gdb or lldb to activate the preference, as a * good hint of its prerequisite, unless backtrace() API exists, in @@ -1264,7 +1310,7 @@ button = gimp_prefs_box_set_page_resettable (GIMP_PREFS_BOX (prefs_box), vbox, - _("Reset Color Management")); + _("R_eset Color Management")); g_signal_connect (button, "clicked", G_CALLBACK (prefs_color_management_reset), config); @@ -1376,7 +1422,7 @@ row++; button = gimp_prop_check_button_new (color_config, "simulation-gamut-check", - _("Mark out of gamut colors")); + _("Mar_k out of gamut colors")); gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0); gtk_widget_show (button); @@ -1428,7 +1474,7 @@ table = prefs_table_new (1, GTK_CONTAINER (vbox2)); button = prefs_enum_combo_box_add (object, "color-profile-policy", 0, 0, - _("File Open behaviour:"), + _("_File Open behaviour:"), GTK_TABLE (table), 0, size_group); /* Filter Dialogs */ @@ -1436,10 +1482,10 @@ FALSE); button = prefs_check_button_add (object, "filter-tool-show-color-options", - _("Show advanced color options"), + _("Show _advanced color options"), GTK_BOX (vbox2)); - g_object_unref (size_group); + g_clear_object (&size_group); g_object_unref (store); } @@ -1456,6 +1502,10 @@ NULL, &top_iter); + gimp_prefs_box_set_page_scrollable (GIMP_PREFS_BOX (prefs_box), vbox, TRUE); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + /* Import Policies */ vbox2 = prefs_frame_new (_("Import Policies"), GTK_CONTAINER (vbox), FALSE); @@ -1470,48 +1520,61 @@ vbox3, "sensitive", G_BINDING_SYNC_CREATE); button = prefs_check_button_add (object, "import-promote-dither", - _("Dither images when promoting to " + _("_Dither images when promoting to " "floating point"), GTK_BOX (vbox3)); button = prefs_check_button_add (object, "import-add-alpha", - _("Add an alpha channel to imported images"), + _("_Add an alpha channel to imported images"), GTK_BOX (vbox2)); table = prefs_table_new (1, GTK_CONTAINER (vbox2)); button = prefs_enum_combo_box_add (object, "color-profile-policy", 0, 0, - _("Color profile policy:"), - GTK_TABLE (table), 0, NULL); + _("Color _profile policy:"), + GTK_TABLE (table), 0, size_group); /* Export Policies */ vbox2 = prefs_frame_new (_("Export Policies"), GTK_CONTAINER (vbox), FALSE); button = prefs_check_button_add (object, "export-color-profile", - _("Export the image's color profile by default"), + _("Export the i_mage's color profile by default"), GTK_BOX (vbox2)); button = prefs_check_button_add (object, "export-metadata-exif", - /* Translators: label for configuration option (checkbox). - * It determines how file export plug-ins handle Exif by default. + /* Translators: label for + * configuration option (checkbox). + * It determines how file export + * plug-ins handle Exif by default. */ - _("Export Exif metadata by default when available"), + _("Export _Exif metadata by default when available"), GTK_BOX (vbox2)); button = prefs_check_button_add (object, "export-metadata-xmp", - /* Translators: label for configuration option (checkbox). - * It determines how file export plug-ins handle XMP by default. + /* Translators: label for + * configuration option (checkbox). + * It determines how file export + * plug-ins handle XMP by default. */ - _("Export XMP metadata by default when available"), + _("Export _XMP metadata by default when available"), GTK_BOX (vbox2)); button = prefs_check_button_add (object, "export-metadata-iptc", - /* Translators: label for configuration option (checkbox). - * It determines how file export plug-ins handle IPTC by default. + /* Translators: label for + * configuration option (checkbox). + * It determines how file export + * plug-ins handle IPTC by default. */ - _("Export IPTC metadata by default when available"), + _("Export _IPTC metadata by default when available"), GTK_BOX (vbox2)); hbox = prefs_hint_box_new (GIMP_ICON_DIALOG_WARNING, _("Metadata can contain sensitive information.")); gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); + /* Export File Type */ + vbox2 = prefs_frame_new (_("Export File Type"), GTK_CONTAINER (vbox), FALSE); + table = prefs_table_new (1, GTK_CONTAINER (vbox2)); + + prefs_enum_combo_box_add (object, "export-file-type", 0, 0, + _("Default export file t_ype:"), + GTK_TABLE (table), 0, size_group); /* Raw Image Importer */ vbox2 = prefs_frame_new (_("Raw Image Importer"), @@ -1540,6 +1603,9 @@ config); } + g_clear_object (&size_group); + + /****************/ /* Playground */ /****************/ @@ -1592,6 +1658,10 @@ /* General */ vbox2 = prefs_frame_new (_("General"), GTK_CONTAINER (vbox), FALSE); + prefs_check_button_add (object, "edit-non-visible", + _("Allow _editing on non-visible layers"), + GTK_BOX (vbox2)); + prefs_check_button_add (object, "save-tool-options", _("_Save tool options on exit"), GTK_BOX (vbox2)); @@ -1622,6 +1692,7 @@ GTK_TABLE (table), 0, size_group); g_object_unref (size_group); + size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); /* Global Brush, Pattern, ... */ @@ -1646,12 +1717,11 @@ GTK_CONTAINER (vbox), FALSE); prefs_check_button_add_with_icon (object, "move-tool-changes-active", - _("Set layer or path as active"), + _("Set _layer or path as active"), GIMP_ICON_TOOL_MOVE, GTK_BOX (vbox2), size_group); - g_object_unref (size_group); - size_group = NULL; + g_clear_object (&size_group); /*******************/ @@ -1761,13 +1831,13 @@ prefs_enum_combo_box_add (object, "layer-preview-size", 0, 0, _("_Default layer & channel preview size:"), - GTK_TABLE (table), 0, size_group); + GTK_TABLE (table), 0, NULL); prefs_enum_combo_box_add (object, "undo-preview-size", 0, 0, _("_Undo preview size:"), - GTK_TABLE (table), 1, size_group); + GTK_TABLE (table), 1, NULL); prefs_enum_combo_box_add (object, "navigation-preview-size", 0, 0, _("Na_vigation preview size:"), - GTK_TABLE (table), 2, size_group); + GTK_TABLE (table), 2, NULL); /* Keyboard Shortcuts */ vbox2 = prefs_frame_new (_("Keyboard Shortcuts"), @@ -2033,6 +2103,7 @@ gtk_widget_show (icon_size_scale); } + /*************************/ /* Interface / Toolbox */ /*************************/ @@ -2067,8 +2138,7 @@ GIMP_ICON_IMAGE, GTK_BOX (vbox2), size_group); - g_object_unref (size_group); - size_group = NULL; + g_clear_object (&size_group); /* Tool Editor */ vbox2 = prefs_frame_new (_("Tools Configuration"), @@ -2097,7 +2167,7 @@ button = gimp_prefs_box_set_page_resettable (GIMP_PREFS_BOX (prefs_box), vbox, - _("Reset Dialog Defaults")); + _("Reset Dialog _Defaults")); g_signal_connect (button, "clicked", G_CALLBACK (prefs_dialog_defaults_reset), config); @@ -2335,6 +2405,10 @@ _("Feather radius:"), GTK_TABLE (table), 0, size_group); + prefs_check_button_add (object, "selection-feather-edge-lock", + _("Selected areas continue outside the image"), + GTK_BOX (vbox2)); + /* Grow Selection Dialog */ vbox2 = prefs_frame_new (_("Grow Selection Dialog"), GTK_CONTAINER (vbox), FALSE); @@ -2399,7 +2473,7 @@ gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0); gtk_widget_show (table); - g_object_unref (size_group); + g_clear_object (&size_group); /*****************************/ @@ -2429,7 +2503,7 @@ button = prefs_boolean_combo_box_add (object, "user-manual-online", _("Use the online version"), _("Use a locally installed copy"), - _("User manual:"), + _("U_ser manual:"), GTK_TABLE (table), 0, size_group); gimp_help_set_help_data (button, NULL, NULL); @@ -2536,18 +2610,17 @@ _("Show _unavailable actions"), GTK_BOX (vbox2)); prefs_spin_button_add (object, "action-history-size", 1.0, 10.0, 0, - _("Maximum History Size:"), + _("_Maximum History Size:"), GTK_TABLE (table), 0, size_group); button = prefs_button_add (GIMP_ICON_SHRED, - _("Clear Action History"), + _("C_lear Action History"), GTK_BOX (vbox2)); g_signal_connect (button, "clicked", G_CALLBACK (prefs_search_clear_callback), gimp); - g_object_unref (size_group); - size_group = NULL; + g_clear_object (&size_group); /*************************/ @@ -2671,8 +2744,7 @@ G_CALLBACK (prefs_resolution_calibrate_callback), entry); - g_object_unref (size_group); - size_group = NULL; + g_clear_object (&size_group); /***********************************/ @@ -2693,7 +2765,7 @@ prefs_enum_combo_box_add (object, "dock-window-hint", 0, 0, _("Hint for _docks and toolbox:"), - GTK_TABLE (table), 1, size_group); + GTK_TABLE (table), 1, NULL); vbox2 = prefs_frame_new (_("Focus"), GTK_CONTAINER (vbox), FALSE); @@ -2746,6 +2818,10 @@ /* General */ vbox2 = prefs_frame_new (_("General"), GTK_CONTAINER (vbox), FALSE); + prefs_check_button_add (object, "default-show-all", + _("Use \"Show _all\" by default"), + GTK_BOX (vbox2)); + prefs_check_button_add (object, "default-dot-for-dot", _("Use \"_Dot for dot\" by default"), GTK_BOX (vbox2)); @@ -2753,7 +2829,7 @@ table = prefs_table_new (1, GTK_CONTAINER (vbox2)); prefs_spin_button_add (object, "marching-ants-speed", 1.0, 10.0, 0, - _("Marching _ants speed:"), + _("Marching ants s_peed:"), GTK_TABLE (table), 0, size_group); /* Zoom & Resize Behavior */ @@ -2805,8 +2881,7 @@ _("Pointer _handedness:"), GTK_TABLE (table), 1, NULL); - g_object_unref (size_group); - size_group = NULL; + g_clear_object (&size_group); /********************************/ @@ -2954,6 +3029,7 @@ } } + /******************************/ /* Image Windows / Snapping */ /******************************/ @@ -2981,7 +3057,7 @@ prefs_spin_button_add (object, "snap-distance", 1.0, 5.0, 0, _("_Snapping distance:"), - GTK_TABLE (table), 0, size_group); + GTK_TABLE (table), 0, NULL); /*******************/ @@ -3059,6 +3135,13 @@ NULL, &top_iter); + button = gimp_prefs_box_set_page_resettable (GIMP_PREFS_BOX (prefs_box), + vbox, + _("Reset _Folders")); + g_signal_connect (button, "clicked", + G_CALLBACK (prefs_folders_reset), + config); + { static const struct { @@ -3070,12 +3153,12 @@ { { "temp-path", - N_("Temporary folder:"), + N_("_Temporary folder:"), N_("Select Folder for Temporary Files") }, { "swap-path", - N_("Swap folder:"), + N_("_Swap folder:"), N_("Select Swap Folder") } }; @@ -3102,70 +3185,101 @@ const gchar *label; const gchar *icon; const gchar *help_data; + const gchar *reset_label; const gchar *fs_label; const gchar *path_property_name; const gchar *writable_property_name; } paths[] = { - { N_("Brushes"), N_("Brush Folders"), "folders-brushes", + { N_("Brushes"), N_("Brush Folders"), + "folders-brushes", GIMP_HELP_PREFS_FOLDERS_BRUSHES, + N_("Reset Brush _Folders"), N_("Select Brush Folders"), "brush-path", "brush-path-writable" }, - { N_("Dynamics"), N_("Dynamics Folders"), "folders-dynamics", + { N_("Dynamics"), N_("Dynamics Folders"), + "folders-dynamics", GIMP_HELP_PREFS_FOLDERS_DYNAMICS, + N_("Reset Dynamics _Folders"), N_("Select Dynamics Folders"), "dynamics-path", "dynamics-path-writable" }, - { N_("Patterns"), N_("Pattern Folders"), "folders-patterns", + { N_("Patterns"), N_("Pattern Folders"), + "folders-patterns", GIMP_HELP_PREFS_FOLDERS_PATTERNS, + N_("Reset Pattern _Folders"), N_("Select Pattern Folders"), "pattern-path", "pattern-path-writable" }, - { N_("Palettes"), N_("Palette Folders"), "folders-palettes", + { N_("Palettes"), N_("Palette Folders"), + "folders-palettes", GIMP_HELP_PREFS_FOLDERS_PALETTES, + N_("Reset Palette _Folders"), N_("Select Palette Folders"), "palette-path", "palette-path-writable" }, - { N_("Gradients"), N_("Gradient Folders"), "folders-gradients", + { N_("Gradients"), N_("Gradient Folders"), + "folders-gradients", GIMP_HELP_PREFS_FOLDERS_GRADIENTS, + N_("Reset Gradient _Folders"), N_("Select Gradient Folders"), "gradient-path", "gradient-path-writable" }, - { N_("Fonts"), N_("Font Folders"), "folders-fonts", + { N_("Fonts"), N_("Font Folders"), + "folders-fonts", GIMP_HELP_PREFS_FOLDERS_FONTS, + N_("Reset Font _Folders"), N_("Select Font Folders"), "font-path", NULL }, - { N_("Tool Presets"), N_("Tool Preset Folders"), "folders-tool-presets", + { N_("Tool Presets"), N_("Tool Preset Folders"), + "folders-tool-presets", GIMP_HELP_PREFS_FOLDERS_TOOL_PRESETS, + N_("Reset Tool Preset _Folders"), N_("Select Tool Preset Folders"), "tool-preset-path", "tool-preset-path-writable" }, - { N_("MyPaint Brushes"), N_("MyPaint Brush Folders"), "folders-mypaint-brushes", + { N_("MyPaint Brushes"), N_("MyPaint Brush Folders"), + "folders-mypaint-brushes", GIMP_HELP_PREFS_FOLDERS_MYPAINT_BRUSHES, + N_("Reset MyPaint Brush _Folders"), N_("Select MyPaint Brush Folders"), "mypaint-brush-path", "mypaint-brush-path-writable" }, - { N_("Plug-ins"), N_("Plug-in Folders"), "folders-plug-ins", + { N_("Plug-ins"), N_("Plug-in Folders"), + "folders-plug-ins", GIMP_HELP_PREFS_FOLDERS_PLUG_INS, + N_("Reset plug-in _Folders"), N_("Select plug-in Folders"), "plug-in-path", NULL }, - { N_("Scripts"), N_("Script-Fu Folders"), "folders-scripts", + { N_("Scripts"), N_("Script-Fu Folders"), + "folders-scripts", GIMP_HELP_PREFS_FOLDERS_SCRIPTS, + N_("Reset Script-Fu _Folders"), N_("Select Script-Fu Folders"), "script-fu-path", NULL }, - { N_("Modules"), N_("Module Folders"), "folders-modules", + { N_("Modules"), N_("Module Folders"), + "folders-modules", GIMP_HELP_PREFS_FOLDERS_MODULES, + N_("Reset Module _Folders"), N_("Select Module Folders"), "module-path", NULL }, - { N_("Interpreters"), N_("Interpreter Folders"), "folders-interp", + { N_("Interpreters"), N_("Interpreter Folders"), + "folders-interp", GIMP_HELP_PREFS_FOLDERS_INTERPRETERS, + N_("Reset Interpreter _Folders"), N_("Select Interpreter Folders"), "interpreter-path", NULL }, - { N_("Environment"), N_("Environment Folders"), "folders-environ", + { N_("Environment"), N_("Environment Folders"), + "folders-environ", GIMP_HELP_PREFS_FOLDERS_ENVIRONMENT, + N_("Reset Environment _Folders"), N_("Select Environment Folders"), "environ-path", NULL }, - { N_("Themes"), N_("Theme Folders"), "folders-themes", + { N_("Themes"), N_("Theme Folders"), + "folders-themes", GIMP_HELP_PREFS_FOLDERS_THEMES, + N_("Reset Theme _Folders"), N_("Select Theme Folders"), "theme-path", NULL }, - { N_("Icon Themes"), N_("Icon Theme Folders"), "folders-icon-themes", + { N_("Icon Themes"), N_("Icon Theme Folders"), + "folders-icon-themes", GIMP_HELP_PREFS_FOLDERS_ICON_THEMES, + N_("Reset Icon Theme _Folders"), N_("Select Icon Theme Folders"), "icon-theme-path", NULL } }; @@ -3185,6 +3299,17 @@ &child_iter); g_free (icon_name); + button = gimp_prefs_box_set_page_resettable (GIMP_PREFS_BOX (prefs_box), + vbox, + gettext (paths[i].reset_label)); + g_object_set_data (G_OBJECT (button), "path", + (gpointer) paths[i].path_property_name); + g_object_set_data (G_OBJECT (button), "path-writable", + (gpointer) paths[i].writable_property_name); + g_signal_connect (button, "clicked", + G_CALLBACK (prefs_path_reset), + config); + editor = gimp_prop_path_editor_new (object, paths[i].path_property_name, paths[i].writable_property_name, diff -Nru gimp-2.10.8+zorin2/app/dialogs/preferences-dialog-utils.c gimp-2.10.14+om/app/dialogs/preferences-dialog-utils.c --- gimp-2.10.8+zorin2/app/dialogs/preferences-dialog-utils.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/preferences-dialog-utils.c 2019-10-26 18:49:18.000000000 +0000 @@ -383,3 +383,20 @@ return combo; } + +GtkWidget * +prefs_compression_combo_box_add (GObject *config, + const gchar *property_name, + const gchar *label, + GtkTable *table, + gint table_row, + GtkSizeGroup *group) +{ + GtkWidget *combo = gimp_prop_compression_combo_box_new (config, + property_name); + + if (combo) + prefs_widget_add_aligned (combo, label, table, table_row, FALSE, group); + + return combo; +} diff -Nru gimp-2.10.8+zorin2/app/dialogs/preferences-dialog-utils.h gimp-2.10.14+om/app/dialogs/preferences-dialog-utils.h --- gimp-2.10.8+zorin2/app/dialogs/preferences-dialog-utils.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/preferences-dialog-utils.h 2019-10-26 18:49:18.000000000 +0000 @@ -123,6 +123,12 @@ GtkSizeGroup *group, GObject *profile_path_config, const gchar *profile_path_property_name); +GtkWidget * prefs_compression_combo_box_add (GObject *config, + const gchar *property_name, + const gchar *label, + GtkTable *table, + gint table_row, + GtkSizeGroup *group); #endif /* __PREFERENCES_DIALOG_H__ */ diff -Nru gimp-2.10.8+zorin2/app/dialogs/print-size-dialog.c gimp-2.10.14+om/app/dialogs/print-size-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/print-size-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/print-size-dialog.c 2019-04-07 11:38:14.000000000 +0000 @@ -158,12 +158,12 @@ /* the print size entry */ adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - width = gtk_spin_button_new (adj, 1.0, 2); + width = gimp_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH); adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - height = gtk_spin_button_new (adj, 1.0, 2); + height = gimp_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH); @@ -224,12 +224,12 @@ /* the resolution entry */ adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - width = gtk_spin_button_new (adj, 1.0, 2); + width = gimp_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH); adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - height = gtk_spin_button_new (adj, 1.0, 2); + height = gimp_spin_button_new (adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH); diff -Nru gimp-2.10.8+zorin2/app/dialogs/resize-dialog.c gimp-2.10.14+om/app/dialogs/resize-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/resize-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/resize-dialog.c 2019-04-07 11:38:14.000000000 +0000 @@ -237,7 +237,7 @@ /* the offset sizeentry */ adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); - spinbutton = gtk_spin_button_new (adjustment, 1.0, 2); + spinbutton = gimp_spin_button_new (adjustment, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), SB_WIDTH); diff -Nru gimp-2.10.8+zorin2/app/dialogs/stroke-dialog.c gimp-2.10.14+om/app/dialogs/stroke-dialog.c --- gimp-2.10.8+zorin2/app/dialogs/stroke-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/dialogs/stroke-dialog.c 2019-10-26 18:49:18.000000000 +0000 @@ -235,7 +235,7 @@ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); gtk_widget_show (hbox); - label = gtk_label_new (_("Paint tool:")); + label = gtk_label_new_with_mnemonic (_("P_aint tool:")); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvasboundary.c gimp-2.10.14+om/app/display/gimpcanvasboundary.c --- gimp-2.10.8+zorin2/app/display/gimpcanvasboundary.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvasboundary.c 2019-06-12 16:43:38.000000000 +0000 @@ -130,18 +130,10 @@ { GimpCanvasBoundaryPrivate *private = GET_PRIVATE (object); - if (private->segs) - { - g_free (private->segs); - private->segs = NULL; - private->n_segs = 0; - } + g_clear_pointer (&private->segs, g_free); + private->n_segs = 0; - if (private->transform) - { - g_free (private->transform); - private->transform = NULL; - } + g_clear_pointer (&private->transform, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvascanvasboundary.c gimp-2.10.14+om/app/display/gimpcanvascanvasboundary.c --- gimp-2.10.8+zorin2/app/display/gimpcanvascanvasboundary.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvascanvasboundary.c 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,270 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcanvascanvasboundary.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpmath/gimpmath.h" + +#include "display-types.h" + +#include "core/gimpimage.h" + +#include "gimpcanvas-style.h" +#include "gimpcanvascanvasboundary.h" +#include "gimpdisplayshell.h" + + +enum +{ + PROP_0, + PROP_IMAGE +}; + + +typedef struct _GimpCanvasCanvasBoundaryPrivate GimpCanvasCanvasBoundaryPrivate; + +struct _GimpCanvasCanvasBoundaryPrivate +{ + GimpImage *image; +}; + +#define GET_PRIVATE(canvas_boundary) \ + ((GimpCanvasCanvasBoundaryPrivate *) gimp_canvas_canvas_boundary_get_instance_private ((GimpCanvasCanvasBoundary *) (canvas_boundary))) + + +/* local function prototypes */ + +static void gimp_canvas_canvas_boundary_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_canvas_canvas_boundary_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_canvas_canvas_boundary_finalize (GObject *object); +static void gimp_canvas_canvas_boundary_draw (GimpCanvasItem *item, + cairo_t *cr); +static cairo_region_t * gimp_canvas_canvas_boundary_get_extents (GimpCanvasItem *item); +static void gimp_canvas_canvas_boundary_stroke (GimpCanvasItem *item, + cairo_t *cr); + + +G_DEFINE_TYPE_WITH_PRIVATE (GimpCanvasCanvasBoundary, gimp_canvas_canvas_boundary, + GIMP_TYPE_CANVAS_RECTANGLE) + +#define parent_class gimp_canvas_canvas_boundary_parent_class + + +static void +gimp_canvas_canvas_boundary_class_init (GimpCanvasCanvasBoundaryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpCanvasItemClass *item_class = GIMP_CANVAS_ITEM_CLASS (klass); + + object_class->set_property = gimp_canvas_canvas_boundary_set_property; + object_class->get_property = gimp_canvas_canvas_boundary_get_property; + object_class->finalize = gimp_canvas_canvas_boundary_finalize; + + item_class->draw = gimp_canvas_canvas_boundary_draw; + item_class->get_extents = gimp_canvas_canvas_boundary_get_extents; + item_class->stroke = gimp_canvas_canvas_boundary_stroke; + + g_object_class_install_property (object_class, PROP_IMAGE, + g_param_spec_object ("image", NULL, NULL, + GIMP_TYPE_IMAGE, + GIMP_PARAM_READWRITE)); +} + +static void +gimp_canvas_canvas_boundary_init (GimpCanvasCanvasBoundary *canvas_boundary) +{ +} + +static void +gimp_canvas_canvas_boundary_finalize (GObject *object) +{ + GimpCanvasCanvasBoundaryPrivate *private = GET_PRIVATE (object); + + if (private->image) + g_object_remove_weak_pointer (G_OBJECT (private->image), + (gpointer) &private->image); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_canvas_canvas_boundary_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpCanvasCanvasBoundaryPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_IMAGE: + if (private->image) + g_object_remove_weak_pointer (G_OBJECT (private->image), + (gpointer) &private->image); + private->image = g_value_get_object (value); /* don't ref */ + if (private->image) + g_object_add_weak_pointer (G_OBJECT (private->image), + (gpointer) &private->image); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_canvas_canvas_boundary_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpCanvasCanvasBoundaryPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_IMAGE: + g_value_set_object (value, private->image); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_canvas_canvas_boundary_draw (GimpCanvasItem *item, + cairo_t *cr) +{ + GimpCanvasCanvasBoundaryPrivate *private = GET_PRIVATE (item); + + if (private->image) + GIMP_CANVAS_ITEM_CLASS (parent_class)->draw (item, cr); +} + +static cairo_region_t * +gimp_canvas_canvas_boundary_get_extents (GimpCanvasItem *item) +{ + GimpCanvasCanvasBoundaryPrivate *private = GET_PRIVATE (item); + + if (private->image) + return GIMP_CANVAS_ITEM_CLASS (parent_class)->get_extents (item); + + return NULL; +} + +static void +gimp_canvas_canvas_boundary_stroke (GimpCanvasItem *item, + cairo_t *cr) +{ + GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); + + gimp_canvas_set_canvas_style (gimp_canvas_item_get_canvas (item), cr, + shell->offset_x, shell->offset_y); + cairo_stroke (cr); +} + +GimpCanvasItem * +gimp_canvas_canvas_boundary_new (GimpDisplayShell *shell) +{ + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); + + return g_object_new (GIMP_TYPE_CANVAS_CANVAS_BOUNDARY, + "shell", shell, + NULL); +} + +void +gimp_canvas_canvas_boundary_set_image (GimpCanvasCanvasBoundary *boundary, + GimpImage *image) +{ + GimpCanvasCanvasBoundaryPrivate *private; + + g_return_if_fail (GIMP_IS_CANVAS_CANVAS_BOUNDARY (boundary)); + g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image)); + + private = GET_PRIVATE (boundary); + + if (image != private->image) + { + gimp_canvas_item_begin_change (GIMP_CANVAS_ITEM (boundary)); + + if (image) + { + g_object_set (boundary, + "x", (gdouble) 0, + "y", (gdouble) 0, + "width", (gdouble) gimp_image_get_width (image), + "height", (gdouble) gimp_image_get_height (image), + NULL); + } + + g_object_set (boundary, + "image", image, + NULL); + + gimp_canvas_item_end_change (GIMP_CANVAS_ITEM (boundary)); + } + else if (image && image == private->image) + { + gint lx, ly, lw, lh; + gdouble x, y, w ,h; + + lx = 0; + ly = 0; + lw = gimp_image_get_width (image); + lh = gimp_image_get_height (image); + + g_object_get (boundary, + "x", &x, + "y", &y, + "width", &w, + "height", &h, + NULL); + + if (lx != (gint) x || + ly != (gint) y || + lw != (gint) w || + lh != (gint) h) + { + gimp_canvas_item_begin_change (GIMP_CANVAS_ITEM (boundary)); + + g_object_set (boundary, + "x", (gdouble) lx, + "y", (gdouble) ly, + "width", (gdouble) lw, + "height", (gdouble) lh, + NULL); + + gimp_canvas_item_end_change (GIMP_CANVAS_ITEM (boundary)); + } + } +} diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvascanvasboundary.h gimp-2.10.14+om/app/display/gimpcanvascanvasboundary.h --- gimp-2.10.8+zorin2/app/display/gimpcanvascanvasboundary.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvascanvasboundary.h 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,58 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpcanvascanvasvboundary.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_CANVAS_CANVAS_BOUNDARY_H__ +#define __GIMP_CANVAS_CANVAS_BOUNDARY_H__ + + +#include "gimpcanvasrectangle.h" + + +#define GIMP_TYPE_CANVAS_CANVAS_BOUNDARY (gimp_canvas_canvas_boundary_get_type ()) +#define GIMP_CANVAS_CANVAS_BOUNDARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_CANVAS_CANVAS_BOUNDARY, GimpCanvasCanvasBoundary)) +#define GIMP_CANVAS_CANVAS_BOUNDARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_CANVAS_CANVAS_BOUNDARY, GimpCanvasCanvasBoundaryClass)) +#define GIMP_IS_CANVAS_CANVAS_BOUNDARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_CANVAS_CANVAS_BOUNDARY)) +#define GIMP_IS_CANVAS_CANVAS_BOUNDARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_CANVAS_CANVAS_BOUNDARY)) +#define GIMP_CANVAS_CANVAS_BOUNDARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_CANVAS_CANVAS_BOUNDARY, GimpCanvasCanvasBoundaryClass)) + + +typedef struct _GimpCanvasCanvasBoundary GimpCanvasCanvasBoundary; +typedef struct _GimpCanvasCanvasBoundaryClass GimpCanvasCanvasBoundaryClass; + +struct _GimpCanvasCanvasBoundary +{ + GimpCanvasRectangle parent_instance; +}; + +struct _GimpCanvasCanvasBoundaryClass +{ + GimpCanvasRectangleClass parent_class; +}; + + +GType gimp_canvas_canvas_boundary_get_type (void) G_GNUC_CONST; + +GimpCanvasItem * gimp_canvas_canvas_boundary_new (GimpDisplayShell *shell); + +void gimp_canvas_canvas_boundary_set_image (GimpCanvasCanvasBoundary *boundary, + GimpImage *image); + + +#endif /* __GIMP_CANVAS_CANVAS_BOUNDARY_H__ */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvasgrid.c gimp-2.10.14+om/app/display/gimpcanvasgrid.c --- gimp-2.10.8+zorin2/app/display/gimpcanvasgrid.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvasgrid.c 2019-10-26 18:49:18.000000000 +0000 @@ -34,7 +34,9 @@ #include "gimpcanvas-style.h" #include "gimpcanvasgrid.h" +#include "gimpcanvasitem-utils.h" #include "gimpdisplayshell.h" +#include "gimpdisplayshell-scale.h" enum @@ -181,16 +183,13 @@ { GimpCanvasGridPrivate *private = GET_PRIVATE (item); GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); - GimpImage *image = gimp_canvas_item_get_image (item); gdouble xspacing, yspacing; gdouble xoffset, yoffset; gboolean vert, horz; - gdouble x, y; gdouble dx1, dy1, dx2, dy2; - gint x0, x1, x2, x3; - gint y0, y1, y2, y3; - gint x_real, y_real; - gint width, height; + gint x1, y1, x2, y2; + gdouble dx, dy; + gint x, y; #define CROSSHAIR 2 @@ -200,55 +199,90 @@ g_return_if_fail (xspacing >= 0.0 && yspacing >= 0.0); + xspacing *= shell->scale_x; + yspacing *= shell->scale_y; + + xoffset *= shell->scale_x; + yoffset *= shell->scale_y; + /* skip grid drawing when the space between grid lines starts * disappearing, see bug #599267. */ - vert = (xspacing * shell->scale_x >= 2.0); - horz = (yspacing * shell->scale_y >= 2.0); + vert = (xspacing >= 2.0); + horz = (yspacing >= 2.0); if (! vert && ! horz) return; cairo_clip_extents (cr, &dx1, &dy1, &dx2, &dy2); - x1 = floor (dx1); - y1 = floor (dy1); - x2 = ceil (dx2); - y2 = ceil (dy2); + x1 = floor (dx1) - 1; + y1 = floor (dy1) - 1; + x2 = ceil (dx2) + 1; + y2 = ceil (dy2) + 1; + + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + GeglRectangle bounds; + + gimp_display_shell_scale_get_image_unrotated_bounds ( + shell, + &bounds.x, &bounds.y, &bounds.width, &bounds.height); + + if (! gegl_rectangle_intersect (&bounds, + &bounds, + GEGL_RECTANGLE (x1, y1, + x2 - x1, y2 - y1))) + { + return; + } + + x1 = bounds.x; + y1 = bounds.y; + x2 = bounds.x + bounds.width; + y2 = bounds.y + bounds.height; + } + + switch (gimp_grid_get_style (private->grid)) + { + case GIMP_GRID_INTERSECTIONS: + x1 -= CROSSHAIR; + y1 -= CROSSHAIR; + x2 += CROSSHAIR; + y2 += CROSSHAIR; + break; + + case GIMP_GRID_DOTS: + case GIMP_GRID_ON_OFF_DASH: + case GIMP_GRID_DOUBLE_DASH: + case GIMP_GRID_SOLID: + break; + } + + xoffset = fmod (xoffset - shell->offset_x - x1, xspacing); + yoffset = fmod (yoffset - shell->offset_y - y1, yspacing); - width = gimp_image_get_width (image); - height = gimp_image_get_height (image); + if (xoffset < 0.0) + xoffset += xspacing; - xoffset = fmod (xoffset, xspacing); - yoffset = fmod (yoffset, yspacing); + if (yoffset < 0.0) + yoffset += yspacing; switch (gimp_grid_get_style (private->grid)) { case GIMP_GRID_DOTS: if (vert && horz) { - for (x = xoffset; x <= width; x += xspacing) + for (dx = x1 + xoffset; dx <= x2; dx += xspacing) { - if (x < 0) - continue; + x = RINT (dx); - gimp_canvas_item_transform_xy (item, x, 0, &x_real, &y_real); - - if (x_real < x1 || x_real >= x2) - continue; - - for (y = yoffset; y <= height; y += yspacing) + for (dy = y1 + yoffset; dy <= y2; dy += yspacing) { - if (y < 0) - continue; - - gimp_canvas_item_transform_xy (item, x, y, &x_real, &y_real); + y = RINT (dy); - if (y_real >= y1 && y_real < y2) - { - cairo_move_to (cr, x_real, y_real + 0.5); - cairo_line_to (cr, x_real + 1, y_real + 0.5); - } + cairo_move_to (cr, x, y + 0.5); + cairo_line_to (cr, x + 1.0, y + 0.5); } } } @@ -257,49 +291,19 @@ case GIMP_GRID_INTERSECTIONS: if (vert && horz) { - for (x = xoffset; x <= width; x += xspacing) + for (dx = x1 + xoffset; dx <= x2; dx += xspacing) { - if (x < 0) - continue; + x = RINT (dx); - gimp_canvas_item_transform_xy (item, x, 0, &x_real, &y_real); - - if (x_real + CROSSHAIR < x1 || x_real - CROSSHAIR >= x2) - continue; - - for (y = yoffset; y <= height; y += yspacing) + for (dy = y1 + yoffset; dy <= y2; dy += yspacing) { - if (y < 0) - continue; - - gimp_canvas_item_transform_xy (item, x, y, &x_real, &y_real); + y = RINT (dy); - if (y_real + CROSSHAIR < y1 || y_real - CROSSHAIR >= y2) - continue; + cairo_move_to (cr, x + 0.5, y - CROSSHAIR); + cairo_line_to (cr, x + 0.5, y + CROSSHAIR + 1.0); - if (x_real >= x1 && x_real < x2) - { - cairo_move_to (cr, - x_real + 0.5, - CLAMP (y_real - CROSSHAIR, - y1, y2 - 1)); - cairo_line_to (cr, - x_real + 0.5, - CLAMP (y_real + CROSSHAIR, - y1, y2 - 1) + 1); - } - - if (y_real >= y1 && y_real < y2) - { - cairo_move_to (cr, - CLAMP (x_real - CROSSHAIR, - x1, x2 - 1), - y_real + 0.5); - cairo_line_to (cr, - CLAMP (x_real + CROSSHAIR, - x1, x2 - 1) + 1, - y_real + 0.5); - } + cairo_move_to (cr, x - CROSSHAIR, y + 0.5); + cairo_line_to (cr, x + CROSSHAIR + 1.0, y + 0.5); } } } @@ -308,40 +312,25 @@ case GIMP_GRID_ON_OFF_DASH: case GIMP_GRID_DOUBLE_DASH: case GIMP_GRID_SOLID: - gimp_canvas_item_transform_xy (item, 0, 0, &x0, &y0); - gimp_canvas_item_transform_xy (item, width, height, &x3, &y3); - if (vert) { - for (x = xoffset; x < width; x += xspacing) + for (dx = x1 + xoffset; dx < x2; dx += xspacing) { - if (x < 0) - continue; - - gimp_canvas_item_transform_xy (item, x, 0, &x_real, &y_real); - - if (x_real >= x1 && x_real < x2) - { - cairo_move_to (cr, x_real + 0.5, y0); - cairo_line_to (cr, x_real + 0.5, y3 + 1); - } + x = RINT (dx); + + cairo_move_to (cr, x + 0.5, y1); + cairo_line_to (cr, x + 0.5, y2); } } if (horz) { - for (y = yoffset; y < height; y += yspacing) + for (dy = y1 + yoffset; dy < y2; dy += yspacing) { - if (y < 0) - continue; - - gimp_canvas_item_transform_xy (item, 0, y, &x_real, &y_real); - - if (y_real >= y1 && y_real < y2) - { - cairo_move_to (cr, x0, y_real + 0.5); - cairo_line_to (cr, x3 + 1, y_real + 0.5); - } + y = RINT (dy); + + cairo_move_to (cr, x1, y + 0.5); + cairo_line_to (cr, x2, y + 0.5); } } break; @@ -353,25 +342,39 @@ static cairo_region_t * gimp_canvas_grid_get_extents (GimpCanvasItem *item) { + GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); GimpImage *image = gimp_canvas_item_get_image (item); cairo_rectangle_int_t rectangle; - gdouble x1, y1; - gdouble x2, y2; - gint w, h; if (! image) return NULL; - w = gimp_image_get_width (image); - h = gimp_image_get_height (image); - - gimp_canvas_item_transform_xy_f (item, 0, 0, &x1, &y1); - gimp_canvas_item_transform_xy_f (item, w, h, &x2, &y2); - - rectangle.x = floor (x1); - rectangle.y = floor (y1); - rectangle.width = ceil (x2) - rectangle.x; - rectangle.height = ceil (y2) - rectangle.y; + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + + gdouble x1, y1; + gdouble x2, y2; + gint w, h; + + w = gimp_image_get_width (image); + h = gimp_image_get_height (image); + + gimp_canvas_item_transform_xy_f (item, 0, 0, &x1, &y1); + gimp_canvas_item_transform_xy_f (item, w, h, &x2, &y2); + + rectangle.x = floor (x1); + rectangle.y = floor (y1); + rectangle.width = ceil (x2) - rectangle.x; + rectangle.height = ceil (y2) - rectangle.y; + } + else + { + gimp_canvas_item_untransform_viewport (item, + &rectangle.x, + &rectangle.y, + &rectangle.width, + &rectangle.height); + } return cairo_region_create_rectangle (&rectangle); } diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvashandle.c gimp-2.10.14+om/app/display/gimpcanvashandle.c --- gimp-2.10.8+zorin2/app/display/gimpcanvashandle.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvashandle.c 2019-10-26 18:49:18.000000000 +0000 @@ -390,10 +390,10 @@ break; case GIMP_HANDLE_CROSS: - cairo_move_to (cr, x - private->width / 2, y); - cairo_line_to (cr, x + private->width / 2 - 0.5, y); - cairo_move_to (cr, x, y - private->height / 2); - cairo_line_to (cr, x, y + private->height / 2 - 0.5); + cairo_move_to (cr, x - private->width / 2.0, y); + cairo_line_to (cr, x + private->width / 2.0 - 0.5, y); + cairo_move_to (cr, x, y - private->height / 2.0); + cairo_line_to (cr, x, y + private->height / 2.0 - 0.5); _gimp_canvas_item_stroke (item, cr); break; @@ -413,7 +413,7 @@ cairo_save (cr); - circ = 2.0 * G_PI * (private->width / 2); + circ = 2.0 * G_PI * (private->width / 2.0); dashes[0] = (circ / N_DASHES) * DASH_ON_RATIO; dashes[1] = (circ / N_DASHES) * DASH_OFF_RATIO; @@ -421,7 +421,7 @@ cairo_set_dash (cr, dashes, 2, dashes[0] / 2.0); } - gimp_cairo_arc (cr, x, y, private->width / 2, + gimp_cairo_arc (cr, x, y, private->width / 2.0, private->start_angle, private->slice_angle); @@ -442,16 +442,16 @@ break; case GIMP_HANDLE_CROSSHAIR: - cairo_move_to (cr, x - private->width / 2, y); + cairo_move_to (cr, x - private->width / 2.0, y); cairo_line_to (cr, x - private->width * 0.4, y); - cairo_move_to (cr, x + private->width / 2 - 0.5, y); + cairo_move_to (cr, x + private->width / 2.0 - 0.5, y); cairo_line_to (cr, x + private->width * 0.4, y); - cairo_move_to (cr, x, y - private->height / 2); + cairo_move_to (cr, x, y - private->height / 2.0); cairo_line_to (cr, x, y - private->height * 0.4 - 0.5); - cairo_move_to (cr, x, y + private->height / 2 - 0.5); + cairo_move_to (cr, x, y + private->height / 2.0 - 0.5); cairo_line_to (cr, x, y + private->height * 0.4 - 0.5); _gimp_canvas_item_stroke (item, cr); @@ -493,8 +493,8 @@ case GIMP_HANDLE_DIAMOND: case GIMP_HANDLE_DASHED_DIAMOND: case GIMP_HANDLE_FILLED_DIAMOND: - rectangle.x = x - private->width / 2 - 2.0; - rectangle.y = y - private->height / 2 - 2.0; + rectangle.x = x - private->width / 2.0 - 2.0; + rectangle.y = y - private->height / 2.0 - 2.0; rectangle.width = private->width + 4.0; rectangle.height = private->height + 4.0; break; diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvasitem.c gimp-2.10.14+om/app/display/gimpcanvasitem.c --- gimp-2.10.8+zorin2/app/display/gimpcanvasitem.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvasitem.c 2019-10-26 18:49:18.000000000 +0000 @@ -651,6 +651,33 @@ return SQR (tx2 - tx1) + SQR (ty2 - ty1); } +void +gimp_canvas_item_untransform_viewport (GimpCanvasItem *item, + gint *x, + gint *y, + gint *w, + gint *h) +{ + GimpDisplayShell *shell; + gdouble x1, y1; + gdouble x2, y2; + + g_return_if_fail (GIMP_IS_CANVAS_ITEM (item)); + + shell = item->private->shell; + + gimp_display_shell_unrotate_bounds (shell, + 0.0, 0.0, + shell->disp_width, shell->disp_height, + &x1, &y1, + &x2, &y2); + + *x = floor (x1); + *y = floor (y1); + *w = ceil (x2) - *x; + *h = ceil (y2) - *y; +} + /* protected functions */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvasitem.h gimp-2.10.14+om/app/display/gimpcanvasitem.h --- gimp-2.10.8+zorin2/app/display/gimpcanvasitem.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvasitem.h 2019-10-26 18:49:18.000000000 +0000 @@ -125,6 +125,12 @@ gdouble y1, gdouble x2, gdouble y2); +void gimp_canvas_item_untransform_viewport + (GimpCanvasItem *item, + gint *x, + gint *y, + gint *w, + gint *h); /* protected */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvaspassepartout.c gimp-2.10.14+om/app/display/gimpcanvaspassepartout.c --- gimp-2.10.8+zorin2/app/display/gimpcanvaspassepartout.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvaspassepartout.c 2019-10-26 18:49:18.000000000 +0000 @@ -26,6 +26,7 @@ #include "display-types.h" #include "gimpcanvas-style.h" +#include "gimpcanvasitem-utils.h" #include "gimpcanvaspassepartout.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-scale.h" @@ -142,10 +143,22 @@ cairo_t *cr) { GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); + gint x, y; gint w, h; - gimp_display_shell_scale_get_image_size (shell, &w, &h); - cairo_rectangle (cr, - shell->offset_x, - shell->offset_y, w, h); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + x = -shell->offset_x; + y = -shell->offset_y; + + gimp_display_shell_scale_get_image_size (shell, &w, &h); + } + else + { + gimp_canvas_item_untransform_viewport (item, &x, &y, &w, &h); + } + + cairo_rectangle (cr, x, y, w, h); GIMP_CANVAS_ITEM_CLASS (parent_class)->draw (item, cr); } @@ -155,22 +168,38 @@ { GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); cairo_rectangle_int_t rectangle; - cairo_region_t *inner; - cairo_region_t *outer; - rectangle.x = - shell->offset_x; - rectangle.y = - shell->offset_y; - gimp_display_shell_scale_get_image_size (shell, - &rectangle.width, - &rectangle.height); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + cairo_region_t *inner; + cairo_region_t *outer; - outer = cairo_region_create_rectangle (&rectangle); + rectangle.x = - shell->offset_x; + rectangle.y = - shell->offset_y; + gimp_display_shell_scale_get_image_size (shell, + &rectangle.width, + &rectangle.height); - inner = GIMP_CANVAS_ITEM_CLASS (parent_class)->get_extents (item); + outer = cairo_region_create_rectangle (&rectangle); - cairo_region_xor (outer, inner); + inner = GIMP_CANVAS_ITEM_CLASS (parent_class)->get_extents (item); - return outer; + cairo_region_xor (outer, inner); + + cairo_region_destroy (inner); + + return outer; + } + else + { + gimp_canvas_item_untransform_viewport (item, + &rectangle.x, + &rectangle.y, + &rectangle.width, + &rectangle.height); + + return cairo_region_create_rectangle (&rectangle); + } } static void diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvaspolygon.c gimp-2.10.14+om/app/display/gimpcanvaspolygon.c --- gimp-2.10.8+zorin2/app/display/gimpcanvaspolygon.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvaspolygon.c 2019-06-12 16:43:38.000000000 +0000 @@ -121,18 +121,10 @@ { GimpCanvasPolygonPrivate *private = GET_PRIVATE (object); - if (private->points) - { - g_free (private->points); - private->points = NULL; - private->n_points = 0; - } + g_clear_pointer (&private->points, g_free); + private->n_points = 0; - if (private->transform) - { - g_free (private->transform); - private->transform = NULL; - } + g_clear_pointer (&private->transform, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -151,8 +143,7 @@ { GimpArray *array = g_value_get_boxed (value); - g_free (private->points); - private->points = NULL; + g_clear_pointer (&private->points, g_free); private->n_points = 0; if (array) diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvasprogress.c gimp-2.10.14+om/app/display/gimpcanvasprogress.c --- gimp-2.10.8+zorin2/app/display/gimpcanvasprogress.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvasprogress.c 2019-06-12 16:43:38.000000000 +0000 @@ -173,11 +173,7 @@ { GimpCanvasProgressPrivate *private = GET_PRIVATE (object); - if (private->text) - { - g_free (private->text); - private->text = NULL; - } + g_clear_pointer (&private->text, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvas-style.c gimp-2.10.14+om/app/display/gimpcanvas-style.c --- gimp-2.10.8+zorin2/app/display/gimpcanvas-style.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvas-style.c 2019-10-26 18:49:18.000000000 +0000 @@ -68,6 +68,9 @@ static const GimpRGB layer_mask_fg = { 0.0, 0.0, 0.0, 1.0 }; static const GimpRGB layer_mask_bg = { 0.0, 1.0, 0.0, 1.0 }; +static const GimpRGB canvas_fg = { 0.0, 0.0, 0.0, 1.0 }; +static const GimpRGB canvas_bg = { 1.0, 0.5, 0.0, 1.0 }; + static const GimpRGB selection_out_fg = { 1.0, 1.0, 1.0, 1.0 }; static const GimpRGB selection_out_bg = { 0.5, 0.5, 0.5, 1.0 }; @@ -288,6 +291,29 @@ cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); +} + +void +gimp_canvas_set_canvas_style (GtkWidget *canvas, + cairo_t *cr, + gdouble offset_x, + gdouble offset_y) +{ + cairo_pattern_t *pattern; + + g_return_if_fail (GTK_IS_WIDGET (canvas)); + g_return_if_fail (cr != NULL); + + cairo_set_line_width (cr, 1.0); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); + + pattern = gimp_cairo_pattern_create_stipple (&canvas_fg, + &canvas_bg, + 0, + offset_x, offset_y); + + cairo_set_source (cr, pattern); + cairo_pattern_destroy (pattern); } void diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvas-style.h gimp-2.10.14+om/app/display/gimpcanvas-style.h --- gimp-2.10.8+zorin2/app/display/gimpcanvas-style.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvas-style.h 2019-10-26 18:49:18.000000000 +0000 @@ -45,6 +45,10 @@ GimpLayer *layer, gdouble offset_x, gdouble offset_y); +void gimp_canvas_set_canvas_style (GtkWidget *canvas, + cairo_t *cr, + gdouble offset_x, + gdouble offset_y); void gimp_canvas_set_selection_out_style (GtkWidget *canvas, cairo_t *cr, gdouble offset_x, diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvastransformpreview.c gimp-2.10.14+om/app/display/gimpcanvastransformpreview.c --- gimp-2.10.8+zorin2/app/display/gimpcanvastransformpreview.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvastransformpreview.c 2019-10-26 18:49:18.000000000 +0000 @@ -32,13 +32,16 @@ #include "display/display-types.h" +#include "gegl/gimp-gegl-nodes.h" +#include "gegl/gimp-gegl-utils.h" +#include "gegl/gimptilehandlervalidate.h" + +#include "core/gimp-transform-utils.h" +#include "core/gimp-utils.h" #include "core/gimpchannel.h" #include "core/gimpimage.h" #include "core/gimplayer.h" -#include "core/gimp-transform-utils.h" -#include "core/gimp-utils.h" - -#include "gegl/gimp-gegl-nodes.h" +#include "core/gimppickable.h" #include "gimpcanvas.h" #include "gimpcanvastransformpreview.h" @@ -48,7 +51,7 @@ enum { PROP_0, - PROP_DRAWABLE, + PROP_PICKABLE, PROP_TRANSFORM, PROP_X1, PROP_Y1, @@ -62,7 +65,7 @@ struct _GimpCanvasTransformPreviewPrivate { - GimpDrawable *drawable; + GimpPickable *pickable; GimpMatrix3 transform; gdouble x1, y1; gdouble x2, y2; @@ -80,7 +83,7 @@ GeglNode *cache_node; GeglNode *transform_node; - GimpDrawable *node_drawable; + GimpPickable *node_pickable; GimpDrawable *node_layer_mask; GimpDrawable *node_mask; GeglRectangle node_rect; @@ -112,8 +115,8 @@ static void gimp_canvas_transform_preview_layer_changed (GimpLayer *layer, GimpCanvasTransformPreview *transform_preview); -static void gimp_canvas_transform_preview_set_drawable (GimpCanvasTransformPreview *transform_preview, - GimpDrawable *drawable); +static void gimp_canvas_transform_preview_set_pickable (GimpCanvasTransformPreview *transform_preview, + GimpPickable *pickable); static void gimp_canvas_transform_preview_sync_node (GimpCanvasTransformPreview *transform_preview); @@ -140,10 +143,10 @@ item_class->draw = gimp_canvas_transform_preview_draw; item_class->get_extents = gimp_canvas_transform_preview_get_extents; - g_object_class_install_property (object_class, PROP_DRAWABLE, - g_param_spec_object ("drawable", + g_object_class_install_property (object_class, PROP_PICKABLE, + g_param_spec_object ("pickable", NULL, NULL, - GIMP_TYPE_DRAWABLE, + GIMP_TYPE_PICKABLE, GIMP_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TRANSFORM, @@ -204,7 +207,7 @@ g_clear_object (&private->node); - gimp_canvas_transform_preview_set_drawable (transform_preview, NULL); + gimp_canvas_transform_preview_set_pickable (transform_preview, NULL); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -220,8 +223,8 @@ switch (property_id) { - case PROP_DRAWABLE: - gimp_canvas_transform_preview_set_drawable (transform_preview, + case PROP_PICKABLE: + gimp_canvas_transform_preview_set_pickable (transform_preview, g_value_get_object (value)); break; @@ -272,8 +275,8 @@ switch (property_id) { - case PROP_DRAWABLE: - g_value_set_object (value, private->drawable); + case PROP_PICKABLE: + g_value_set_object (value, private->pickable); break; case PROP_TRANSFORM: @@ -450,33 +453,33 @@ } static void -gimp_canvas_transform_preview_set_drawable (GimpCanvasTransformPreview *transform_preview, - GimpDrawable *drawable) +gimp_canvas_transform_preview_set_pickable (GimpCanvasTransformPreview *transform_preview, + GimpPickable *pickable) { GimpCanvasTransformPreviewPrivate *private = GET_PRIVATE (transform_preview); - if (private->drawable && GIMP_IS_LAYER (private->drawable)) + if (private->pickable && GIMP_IS_LAYER (private->pickable)) { g_signal_handlers_disconnect_by_func ( - private->drawable, + private->pickable, gimp_canvas_transform_preview_layer_changed, transform_preview); } - g_set_object (&private->drawable, drawable); + g_set_object (&private->pickable, pickable); - if (drawable && GIMP_IS_LAYER (drawable)) + if (pickable && GIMP_IS_LAYER (pickable)) { - g_signal_connect (drawable, "opacity-changed", + g_signal_connect (pickable, "opacity-changed", G_CALLBACK (gimp_canvas_transform_preview_layer_changed), transform_preview); - g_signal_connect (drawable, "mask-changed", + g_signal_connect (pickable, "mask-changed", G_CALLBACK (gimp_canvas_transform_preview_layer_changed), transform_preview); - g_signal_connect (drawable, "apply-mask-changed", + g_signal_connect (pickable, "apply-mask-changed", G_CALLBACK (gimp_canvas_transform_preview_layer_changed), transform_preview); - g_signal_connect (drawable, "show-mask-changed", + g_signal_connect (pickable, "show-mask-changed", G_CALLBACK (gimp_canvas_transform_preview_layer_changed), transform_preview); } @@ -489,11 +492,12 @@ GimpCanvasItem *item = GIMP_CANVAS_ITEM (transform_preview); GimpDisplayShell *shell = gimp_canvas_item_get_shell (item); GimpImage *image = gimp_canvas_item_get_image (item); - GimpDrawable *drawable = private->drawable; + GimpPickable *pickable = private->pickable; GimpDrawable *layer_mask = NULL; GimpDrawable *mask = NULL; gdouble opacity = private->opacity; - gint offset_x, offset_y; + gint offset_x = 0; + gint offset_y = 0; GimpMatrix3 matrix; if (! private->node) @@ -567,7 +571,7 @@ private->mask_crop_node, NULL); - private->node_drawable = NULL; + private->node_pickable = NULL; private->node_layer_mask = NULL; private->node_mask = NULL; private->node_rect = *GEGL_RECTANGLE (0, 0, 0, 0); @@ -576,49 +580,66 @@ private->node_output = private->transform_node; } - gimp_item_get_offset (GIMP_ITEM (private->drawable), &offset_x, &offset_y); - - gimp_matrix3_identity (&matrix); - gimp_matrix3_translate (&matrix, offset_x, offset_y); - gimp_matrix3_mult (&private->transform, &matrix); - gimp_matrix3_scale (&matrix, shell->scale_x, shell->scale_y); - - if (gimp_item_mask_bounds (GIMP_ITEM (private->drawable), - NULL, NULL, NULL, NULL)) + if (GIMP_IS_ITEM (pickable)) { - mask = GIMP_DRAWABLE (gimp_image_get_mask (image)); - } + gimp_item_get_offset (GIMP_ITEM (private->pickable), + &offset_x, &offset_y); - if (GIMP_IS_LAYER (drawable)) - { - GimpLayer *layer = GIMP_LAYER (drawable); + if (gimp_item_mask_bounds (GIMP_ITEM (pickable), + NULL, NULL, NULL, NULL)) + { + mask = GIMP_DRAWABLE (gimp_image_get_mask (image)); + } - opacity *= gimp_layer_get_opacity (layer); + if (GIMP_IS_LAYER (pickable)) + { + GimpLayer *layer = GIMP_LAYER (pickable); - layer_mask = GIMP_DRAWABLE (gimp_layer_get_mask (layer)); + opacity *= gimp_layer_get_opacity (layer); - if (layer_mask) - { - if (gimp_layer_get_show_mask (layer) && ! mask) - { - drawable = layer_mask; - layer_mask = NULL; - } - else if (! gimp_layer_get_apply_mask (layer)) + layer_mask = GIMP_DRAWABLE (gimp_layer_get_mask (layer)); + + if (layer_mask) { - layer_mask = NULL; + if (gimp_layer_get_show_mask (layer) && ! mask) + { + pickable = GIMP_PICKABLE (layer_mask); + layer_mask = NULL; + } + else if (! gimp_layer_get_apply_mask (layer)) + { + layer_mask = NULL; + } } } } - if (drawable != private->node_drawable) + gimp_matrix3_identity (&matrix); + gimp_matrix3_translate (&matrix, offset_x, offset_y); + gimp_matrix3_mult (&private->transform, &matrix); + gimp_matrix3_scale (&matrix, shell->scale_x, shell->scale_y); + + if (pickable != private->node_pickable) { + GeglBuffer *buffer; + + gimp_pickable_flush (pickable); + + buffer = gimp_pickable_get_buffer (pickable); + + if (gimp_tile_handler_validate_get_assigned (buffer)) + buffer = gimp_gegl_buffer_dup (buffer); + else + buffer = g_object_ref (buffer); + gegl_node_set (private->source_node, - "buffer", gimp_drawable_get_buffer (drawable), + "buffer", buffer, NULL); gegl_node_set (private->convert_format_node, - "format", gimp_drawable_get_format_with_alpha (drawable), + "format", gimp_pickable_get_format_with_alpha (pickable), NULL); + + g_object_unref (buffer); } if (layer_mask != private->node_layer_mask) @@ -636,8 +657,8 @@ rect.x = offset_x; rect.y = offset_y; - rect.width = gimp_item_get_width (GIMP_ITEM (private->drawable)); - rect.height = gimp_item_get_height (GIMP_ITEM (private->drawable)); + rect.width = gimp_item_get_width (GIMP_ITEM (private->pickable)); + rect.height = gimp_item_get_height (GIMP_ITEM (private->pickable)); if (mask != private->node_mask) { @@ -739,7 +760,7 @@ gimp_gegl_node_set_matrix (private->transform_node, &matrix); } - private->node_drawable = drawable; + private->node_pickable = pickable; private->node_layer_mask = layer_mask; private->node_mask = mask; private->node_opacity = opacity; @@ -751,7 +772,7 @@ GimpCanvasItem * gimp_canvas_transform_preview_new (GimpDisplayShell *shell, - GimpDrawable *drawable, + GimpPickable *pickable, const GimpMatrix3 *transform, gdouble x1, gdouble y1, @@ -759,12 +780,12 @@ gdouble y2) { g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); - g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); g_return_val_if_fail (transform != NULL, NULL); return g_object_new (GIMP_TYPE_CANVAS_TRANSFORM_PREVIEW, "shell", shell, - "drawable", drawable, + "pickable", pickable, "transform", transform, "x1", x1, "y1", y1, diff -Nru gimp-2.10.8+zorin2/app/display/gimpcanvastransformpreview.h gimp-2.10.14+om/app/display/gimpcanvastransformpreview.h --- gimp-2.10.8+zorin2/app/display/gimpcanvastransformpreview.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcanvastransformpreview.h 2019-10-26 18:49:18.000000000 +0000 @@ -50,7 +50,7 @@ GType gimp_canvas_transform_preview_get_type (void) G_GNUC_CONST; GimpCanvasItem * gimp_canvas_transform_preview_new (GimpDisplayShell *shell, - GimpDrawable *drawable, + GimpPickable *pickable, const GimpMatrix3 *transform, gdouble x1, gdouble y1, diff -Nru gimp-2.10.8+zorin2/app/display/gimpcursorview.c gimp-2.10.14+om/app/display/gimpcursorview.c --- gimp-2.10.8+zorin2/app/display/gimpcursorview.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpcursorview.c 2019-10-26 18:49:18.000000000 +0000 @@ -763,6 +763,7 @@ if (gimp_image_pick_color (image, NULL, int_x, int_y, + view->priv->shell->show_all, view->priv->sample_merged, FALSE, 0.0, &sample_format, pixel, &color)) diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplay.c gimp-2.10.14+om/app/display/gimpdisplay.c --- gimp-2.10.8+zorin2/app/display/gimpdisplay.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplay.c 2019-10-26 18:49:18.000000000 +0000 @@ -44,6 +44,8 @@ #include "gimpdisplayshell-expose.h" #include "gimpdisplayshell-handlers.h" #include "gimpdisplayshell-icon.h" +#include "gimpdisplayshell-scroll.h" +#include "gimpdisplayshell-scrollbars.h" #include "gimpdisplayshell-transform.h" #include "gimpimagewindow.h" @@ -76,6 +78,8 @@ gint instance; /* the instance # of this display as * taken from the image at creation */ + GeglRectangle bounding_box; + GtkWidget *shell; cairo_region_t *update_region; @@ -450,6 +454,8 @@ shell = gimp_display_get_shell (display); + gimp_display_update_bounding_box (display); + gimp_image_window_add_shell (window, shell); gimp_display_shell_present (shell); @@ -685,6 +691,8 @@ if (old_image) g_object_unref (old_image); + gimp_display_update_bounding_box (display); + if (shell) { if (image) @@ -725,6 +733,7 @@ gimp_display_empty (GimpDisplay *display) { GimpDisplayPrivate *private; + GList *iter; g_return_if_fail (GIMP_IS_DISPLAY (display)); @@ -732,6 +741,14 @@ g_return_if_fail (GIMP_IS_IMAGE (private->image)); + for (iter = display->gimp->context_list; iter; iter = g_list_next (iter)) + { + GimpContext *context = iter->data; + + if (gimp_context_get_display (context) == display) + gimp_context_set_image (context, NULL); + } + gimp_display_set_image (display, NULL); gimp_display_shell_empty (gimp_display_get_shell (display)); @@ -759,6 +776,51 @@ } void +gimp_display_update_bounding_box (GimpDisplay *display) +{ + GimpDisplayPrivate *private; + GimpDisplayShell *shell; + GeglRectangle bounding_box = {}; + + g_return_if_fail (GIMP_IS_DISPLAY (display)); + + private = GIMP_DISPLAY_GET_PRIVATE (display); + shell = gimp_display_get_shell (display); + + if (shell) + { + bounding_box = gimp_display_shell_get_bounding_box (shell); + + if (! gegl_rectangle_equal (&bounding_box, &private->bounding_box)) + { + GeglRectangle diff_rects[4]; + gint n_diff_rects; + gint i; + + n_diff_rects = gegl_rectangle_subtract (diff_rects, + &private->bounding_box, + &bounding_box); + + for (i = 0; i < n_diff_rects; i++) + { + gimp_display_paint_area (display, + diff_rects[i].x, diff_rects[i].y, + diff_rects[i].width, diff_rects[i].height); + } + + private->bounding_box = bounding_box; + + gimp_display_shell_scroll_clamp_and_update (shell); + gimp_display_shell_scrollbars_update (shell); + } + } + else + { + private->bounding_box = bounding_box; + } +} + +void gimp_display_update_area (GimpDisplay *display, gboolean now, gint x, @@ -868,27 +930,25 @@ gint w, gint h) { - GimpDisplayPrivate *private = GIMP_DISPLAY_GET_PRIVATE (display); - GimpDisplayShell *shell = gimp_display_get_shell (display); - gint image_width = gimp_image_get_width (private->image); - gint image_height = gimp_image_get_height (private->image); + GimpDisplayPrivate *private = GIMP_DISPLAY_GET_PRIVATE (display); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GeglRectangle rect; gint x1, y1, x2, y2; gdouble x1_f, y1_f, x2_f, y2_f; - /* Bounds check */ - x1 = CLAMP (x, 0, image_width); - y1 = CLAMP (y, 0, image_height); - x2 = CLAMP (x + w, 0, image_width); - y2 = CLAMP (y + h, 0, image_height); - - x = x1; - y = y1; - w = (x2 - x1); - h = (y2 - y1); + if (! gegl_rectangle_intersect (&rect, + &private->bounding_box, + GEGL_RECTANGLE (x, y, w, h))) + { + return; + } /* display the area */ gimp_display_shell_transform_bounds (shell, - x, y, x + w, y + h, + rect.x, + rect.y, + rect.x + rect.width, + rect.y + rect.height, &x1_f, &y1_f, &x2_f, &y2_f); /* make sure to expose a superset of the transformed sub-pixel expose diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplay.h gimp-2.10.14+om/app/display/gimpdisplay.h --- gimp-2.10.8+zorin2/app/display/gimpdisplay.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplay.h 2019-10-26 18:49:18.000000000 +0000 @@ -82,6 +82,9 @@ GimpUnit unit, gdouble scale); +void gimp_display_update_bounding_box + (GimpDisplay *display); + void gimp_display_update_area (GimpDisplay *display, gboolean now, gint x, diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplay-handlers.c gimp-2.10.14+om/app/display/gimpdisplay-handlers.c --- gimp-2.10.8+zorin2/app/display/gimpdisplay-handlers.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplay-handlers.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,16 +30,21 @@ /* local function prototypes */ -static void gimp_display_update_handler (GimpProjection *projection, - gboolean now, - gint x, - gint y, - gint w, - gint h, - GimpDisplay *display); -static void gimp_display_flush_handler (GimpImage *image, - gboolean invalidate_preview, - GimpDisplay *display); +static void gimp_display_update_handler (GimpProjection *projection, + gboolean now, + gint x, + gint y, + gint w, + gint h, + GimpDisplay *display); + +static void gimp_display_bounds_changed_handler (GimpImage *image, + gint old_x, + gint old_y, + GimpDisplay *display); +static void gimp_display_flush_handler (GimpImage *image, + gboolean invalidate_preview, + GimpDisplay *display); /* public functions */ @@ -59,6 +64,9 @@ G_CALLBACK (gimp_display_update_handler), display); + g_signal_connect (image, "bounds-changed", + G_CALLBACK (gimp_display_bounds_changed_handler), + display); g_signal_connect (image, "flush", G_CALLBACK (gimp_display_flush_handler), display); @@ -78,6 +86,9 @@ g_signal_handlers_disconnect_by_func (image, gimp_display_flush_handler, display); + g_signal_handlers_disconnect_by_func (image, + gimp_display_bounds_changed_handler, + display); g_signal_handlers_disconnect_by_func (gimp_image_get_projection (image), gimp_display_update_handler, @@ -100,6 +111,15 @@ } static void +gimp_display_bounds_changed_handler (GimpImage *image, + gint old_x, + gint old_y, + GimpDisplay *display) +{ + gimp_display_update_bounding_box (display); +} + +static void gimp_display_flush_handler (GimpImage *image, gboolean invalidate_preview, GimpDisplay *display) diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-appearance.c gimp-2.10.14+om/app/display/gimpdisplayshell-appearance.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-appearance.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-appearance.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,7 +36,10 @@ #include "gimpdisplayshell.h" #include "gimpdisplayshell-actions.h" #include "gimpdisplayshell-appearance.h" +#include "gimpdisplayshell-expose.h" #include "gimpdisplayshell-selection.h" +#include "gimpdisplayshell-scroll.h" +#include "gimpdisplayshell-scrollbars.h" #include "gimpimagewindow.h" #include "gimpstatusbar.h" @@ -82,28 +85,32 @@ has_grip); } - gimp_display_shell_set_show_menubar (shell, - options->show_menubar); - gimp_display_shell_set_show_statusbar (shell, - options->show_statusbar); - - gimp_display_shell_set_show_rulers (shell, - options->show_rulers); - gimp_display_shell_set_show_scrollbars (shell, - options->show_scrollbars); - gimp_display_shell_set_show_selection (shell, - options->show_selection); - gimp_display_shell_set_show_layer (shell, - options->show_layer_boundary); - gimp_display_shell_set_show_guides (shell, - options->show_guides); - gimp_display_shell_set_show_grid (shell, - options->show_grid); - gimp_display_shell_set_show_sample_points (shell, - options->show_sample_points); - gimp_display_shell_set_padding (shell, - options->padding_mode, - &options->padding_color); + gimp_display_shell_set_show_menubar (shell, + options->show_menubar); + gimp_display_shell_set_show_statusbar (shell, + options->show_statusbar); + + gimp_display_shell_set_show_rulers (shell, + options->show_rulers); + gimp_display_shell_set_show_scrollbars (shell, + options->show_scrollbars); + gimp_display_shell_set_show_selection (shell, + options->show_selection); + gimp_display_shell_set_show_layer (shell, + options->show_layer_boundary); + gimp_display_shell_set_show_canvas (shell, + options->show_canvas_boundary); + gimp_display_shell_set_show_guides (shell, + options->show_guides); + gimp_display_shell_set_show_grid (shell, + options->show_grid); + gimp_display_shell_set_show_sample_points (shell, + options->show_sample_points); + gimp_display_shell_set_padding (shell, + options->padding_mode, + &options->padding_color); + gimp_display_shell_set_padding_in_show_all (shell, + options->padding_in_show_all); } void @@ -272,6 +279,46 @@ } void +gimp_display_shell_set_show_canvas (GimpDisplayShell *shell, + gboolean show) +{ + GimpDisplayOptions *options; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + options = appearance_get_options (shell); + + g_object_set (options, "show-canvas-boundary", show, NULL); + + gimp_canvas_item_set_visible (shell->canvas_boundary, + show && shell->show_all); + + gimp_display_shell_set_action_active (shell, "view-show-canvas-boundary", show); +} + +gboolean +gimp_display_shell_get_show_canvas (GimpDisplayShell *shell) +{ + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); + + return appearance_get_options (shell)->show_canvas_boundary; +} + +void +gimp_display_shell_update_show_canvas (GimpDisplayShell *shell) +{ + GimpDisplayOptions *options; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + options = appearance_get_options (shell); + + gimp_canvas_item_set_visible (shell->canvas_boundary, + options->show_canvas_boundary && + shell->show_all); +} + +void gimp_display_shell_set_show_guides (GimpDisplayShell *shell, gboolean show) { @@ -501,6 +548,44 @@ *padding_color = options->padding_color; } +void +gimp_display_shell_set_padding_in_show_all (GimpDisplayShell *shell, + gboolean keep) +{ + GimpDisplayOptions *options; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + options = appearance_get_options (shell); + + if (options->padding_in_show_all != keep) + { + g_object_set (options, "padding-in-show-all", keep, NULL); + + if (shell->display) + { + gimp_display_shell_scroll_clamp_and_update (shell); + gimp_display_shell_scrollbars_update (shell); + + gimp_display_shell_expose_full (shell); + } + + gimp_display_shell_set_action_active (shell, + "view-padding-color-in-show-all", + keep); + + g_object_notify (G_OBJECT (shell), "infinite-canvas"); + } +} + +gboolean +gimp_display_shell_get_padding_in_show_all (GimpDisplayShell *shell) +{ + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); + + return appearance_get_options (shell)->padding_in_show_all; +} + /* private functions */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-appearance.h gimp-2.10.14+om/app/display/gimpdisplayshell-appearance.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-appearance.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-appearance.h 2019-10-26 18:49:18.000000000 +0000 @@ -19,66 +19,74 @@ #define __GIMP_DISPLAY_SHELL_APPEARANCE_H__ -void gimp_display_shell_appearance_update (GimpDisplayShell *shell); +void gimp_display_shell_appearance_update (GimpDisplayShell *shell); -void gimp_display_shell_set_show_menubar (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_menubar (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_statusbar (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_statusbar (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_rulers (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_rulers (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_scrollbars (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_scrollbars (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_selection (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_selection (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_layer (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_layer (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_grid (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_grid (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_guides (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_guides (GimpDisplayShell *shell); - -void gimp_display_shell_set_snap_to_grid (GimpDisplayShell *shell, - gboolean snap); -gboolean gimp_display_shell_get_snap_to_grid (GimpDisplayShell *shell); - -void gimp_display_shell_set_show_sample_points (GimpDisplayShell *shell, - gboolean show); -gboolean gimp_display_shell_get_show_sample_points (GimpDisplayShell *shell); - -void gimp_display_shell_set_snap_to_guides (GimpDisplayShell *shell, - gboolean snap); -gboolean gimp_display_shell_get_snap_to_guides (GimpDisplayShell *shell); - -void gimp_display_shell_set_snap_to_canvas (GimpDisplayShell *shell, - gboolean snap); -gboolean gimp_display_shell_get_snap_to_canvas (GimpDisplayShell *shell); - -void gimp_display_shell_set_snap_to_vectors (GimpDisplayShell *shell, - gboolean snap); -gboolean gimp_display_shell_get_snap_to_vectors (GimpDisplayShell *shell); - -void gimp_display_shell_set_padding (GimpDisplayShell *shell, - GimpCanvasPaddingMode mode, - const GimpRGB *color); -void gimp_display_shell_get_padding (GimpDisplayShell *shell, - GimpCanvasPaddingMode *mode, - GimpRGB *color); +void gimp_display_shell_set_show_menubar (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_menubar (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_statusbar (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_statusbar (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_rulers (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_rulers (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_scrollbars (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_scrollbars (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_selection (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_selection (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_layer (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_layer (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_canvas (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_canvas (GimpDisplayShell *shell); +void gimp_display_shell_update_show_canvas (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_grid (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_grid (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_guides (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_guides (GimpDisplayShell *shell); + +void gimp_display_shell_set_snap_to_grid (GimpDisplayShell *shell, + gboolean snap); +gboolean gimp_display_shell_get_snap_to_grid (GimpDisplayShell *shell); + +void gimp_display_shell_set_show_sample_points (GimpDisplayShell *shell, + gboolean show); +gboolean gimp_display_shell_get_show_sample_points (GimpDisplayShell *shell); + +void gimp_display_shell_set_snap_to_guides (GimpDisplayShell *shell, + gboolean snap); +gboolean gimp_display_shell_get_snap_to_guides (GimpDisplayShell *shell); + +void gimp_display_shell_set_snap_to_canvas (GimpDisplayShell *shell, + gboolean snap); +gboolean gimp_display_shell_get_snap_to_canvas (GimpDisplayShell *shell); + +void gimp_display_shell_set_snap_to_vectors (GimpDisplayShell *shell, + gboolean snap); +gboolean gimp_display_shell_get_snap_to_vectors (GimpDisplayShell *shell); + +void gimp_display_shell_set_padding (GimpDisplayShell *shell, + GimpCanvasPaddingMode mode, + const GimpRGB *color); +void gimp_display_shell_get_padding (GimpDisplayShell *shell, + GimpCanvasPaddingMode *mode, + GimpRGB *color); +void gimp_display_shell_set_padding_in_show_all (GimpDisplayShell *shell, + gboolean keep); +gboolean gimp_display_shell_get_padding_in_show_all (GimpDisplayShell *shell); #endif /* __GIMP_DISPLAY_SHELL_APPEARANCE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell.c gimp-2.10.14+om/app/display/gimpdisplayshell.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell.c 2019-10-26 18:49:18.000000000 +0000 @@ -43,6 +43,8 @@ #include "core/gimpimage-grid.h" #include "core/gimpimage-guides.h" #include "core/gimpimage-snap.h" +#include "core/gimppickable.h" +#include "core/gimpprojectable.h" #include "core/gimpprojection.h" #include "core/gimpmarshal.h" #include "core/gimptemplate.h" @@ -55,6 +57,7 @@ #include "tools/tool_manager.h" #include "gimpcanvas.h" +#include "gimpcanvascanvasboundary.h" #include "gimpcanvaslayerboundary.h" #include "gimpdisplay.h" #include "gimpdisplayshell.h" @@ -73,6 +76,7 @@ #include "gimpdisplayshell-rulers.h" #include "gimpdisplayshell-scale.h" #include "gimpdisplayshell-scroll.h" +#include "gimpdisplayshell-scrollbars.h" #include "gimpdisplayshell-selection.h" #include "gimpdisplayshell-title.h" #include "gimpdisplayshell-tool-events.h" @@ -98,7 +102,8 @@ PROP_UNIT, PROP_TITLE, PROP_STATUS, - PROP_ICON + PROP_ICON, + PROP_INFINITE_CANVAS }; enum @@ -303,6 +308,12 @@ GDK_TYPE_PIXBUF, GIMP_PARAM_READWRITE)); + g_object_class_install_property (object_class, PROP_INFINITE_CANVAS, + g_param_spec_boolean ("infinite-canvas", + NULL, NULL, + FALSE, + GIMP_PARAM_READABLE)); + gtk_rc_parse_string (display_rc_style); } @@ -326,6 +337,10 @@ shell->scale_x = 1.0; shell->scale_y = 1.0; + shell->show_image = TRUE; + + shell->show_all = FALSE; + gimp_display_shell_items_init (shell); shell->icon_size = 128; @@ -381,21 +396,20 @@ static void gimp_display_shell_constructed (GObject *object) { - GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (object); - GimpDisplayConfig *config; - GimpImage *image; - GimpColorDisplayStack *filter; - GtkWidget *main_vbox; - GtkWidget *upper_hbox; - GtkWidget *right_vbox; - GtkWidget *lower_hbox; - GtkWidget *inner_table; - GtkWidget *gtk_image; - GtkAction *action; - gint image_width; - gint image_height; - gint shell_width; - gint shell_height; + GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (object); + GimpDisplayConfig *config; + GimpImage *image; + GtkWidget *main_vbox; + GtkWidget *upper_hbox; + GtkWidget *right_vbox; + GtkWidget *lower_hbox; + GtkWidget *inner_table; + GtkWidget *gtk_image; + GimpAction *action; + gint image_width; + gint image_height; + gint shell_width; + gint shell_height; G_OBJECT_CLASS (parent_class)->constructed (object); @@ -763,16 +777,6 @@ gtk_widget_show (GTK_WIDGET (shell->canvas)); - /* add display filters */ - - filter = gimp_display_shell_filter_new (shell); - - if (filter) - { - gimp_display_shell_filter_set (shell, filter); - g_object_unref (filter); - } - if (image) { gimp_display_shell_connect (shell); @@ -799,6 +803,8 @@ /* make sure the information is up-to-date */ gimp_display_shell_scale_update (shell); + + gimp_display_shell_set_show_all (shell, config->default_show_all); } static void @@ -814,8 +820,7 @@ if (shell->selection) gimp_display_shell_selection_free (shell); - if (shell->filter_stack) - gimp_display_shell_filter_set (shell, NULL); + gimp_display_shell_filter_set (shell, NULL); if (shell->filter_idle_id) { @@ -962,6 +967,10 @@ case PROP_ICON: g_value_set_object (value, shell->icon); break; + case PROP_INFINITE_CANVAS: + g_value_set_boolean (value, + gimp_display_shell_get_infinite_canvas (shell)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -1031,22 +1040,6 @@ } static void -gimp_display_shell_set_priority_viewport (GimpDisplayShell *shell) -{ - GimpImage *image = gimp_display_get_image (shell->display); - - if (image) - { - GimpProjection *projection = gimp_image_get_projection (image); - gint x, y; - gint width, height; - - gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); - gimp_projection_set_priority_rect (projection, x, y, width, height); - } -} - -static void gimp_display_shell_real_scaled (GimpDisplayShell *shell) { GimpContext *user_context; @@ -1060,7 +1053,7 @@ if (shell->display == gimp_context_get_display (user_context)) { - gimp_display_shell_set_priority_viewport (shell); + gimp_display_shell_update_priority_rect (shell); gimp_ui_manager_update (shell->popup_manager, shell->display); } @@ -1080,7 +1073,7 @@ if (shell->display == gimp_context_get_display (user_context)) { - gimp_display_shell_set_priority_viewport (shell); + gimp_display_shell_update_priority_rect (shell); } } @@ -1099,7 +1092,7 @@ if (shell->display == gimp_context_get_display (user_context)) { - gimp_display_shell_set_priority_viewport (shell); + gimp_display_shell_update_priority_rect (shell); gimp_ui_manager_update (shell->popup_manager, shell->display); } @@ -1510,6 +1503,8 @@ config = shell->display->config; window = gimp_display_shell_get_window (shell); + shell->show_image = TRUE; + shell->dot_for_dot = config->default_dot_for_dot; gimp_display_shell_set_unit (shell, unit); @@ -1544,6 +1539,8 @@ g_idle_add_full (GIMP_PRIORITY_DISPLAY_SHELL_FILL_IDLE, (GSourceFunc) gimp_display_shell_fill_idle, shell, NULL); + + gimp_display_shell_set_show_all (shell, config->default_show_all); } void @@ -1797,6 +1794,163 @@ } void +gimp_display_shell_set_show_image (GimpDisplayShell *shell, + gboolean show_image) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + if (show_image != shell->show_image) + { + shell->show_image = show_image; + + gimp_display_shell_expose_full (shell); + } +} + +void +gimp_display_shell_set_show_all (GimpDisplayShell *shell, + gboolean show_all) +{ + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + if (show_all != shell->show_all) + { + shell->show_all = show_all; + + if (shell->display && gimp_display_get_image (shell->display)) + { + GimpImage *image = gimp_display_get_image (shell->display); + GimpContext *user_context; + + if (show_all) + gimp_image_inc_show_all_count (image); + else + gimp_image_dec_show_all_count (image); + + gimp_image_flush (image); + + gimp_display_update_bounding_box (shell->display); + + gimp_display_shell_update_show_canvas (shell); + + gimp_display_shell_scroll_clamp_and_update (shell); + gimp_display_shell_scrollbars_update (shell); + + gimp_display_shell_expose_full (shell); + + user_context = gimp_get_user_context (shell->display->gimp); + + if (shell->display == gimp_context_get_display (user_context)) + { + gimp_display_shell_update_priority_rect (shell); + + gimp_ui_manager_update (shell->popup_manager, shell->display); + } + } + + g_object_notify (G_OBJECT (shell), "infinite-canvas"); + } +} + + +GimpPickable * +gimp_display_shell_get_pickable (GimpDisplayShell *shell) +{ + GimpImage *image; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); + + image = gimp_display_get_image (shell->display); + + if (image) + { + if (! shell->show_all) + return GIMP_PICKABLE (image); + else + return GIMP_PICKABLE (gimp_image_get_projection (image)); + } + + return NULL; +} + +GimpPickable * +gimp_display_shell_get_canvas_pickable (GimpDisplayShell *shell) +{ + GimpImage *image; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); + + image = gimp_display_get_image (shell->display); + + if (image) + { + if (! gimp_display_shell_get_infinite_canvas (shell)) + return GIMP_PICKABLE (image); + else + return GIMP_PICKABLE (gimp_image_get_projection (image)); + } + + return NULL; +} + +GeglRectangle +gimp_display_shell_get_bounding_box (GimpDisplayShell *shell) +{ + GeglRectangle bounding_box = {}; + GimpImage *image; + + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), bounding_box); + + image = gimp_display_get_image (shell->display); + + if (image) + { + if (! shell->show_all) + { + bounding_box.width = gimp_image_get_width (image); + bounding_box.height = gimp_image_get_height (image); + } + else + { + bounding_box = gimp_projectable_get_bounding_box ( + GIMP_PROJECTABLE (image)); + } + } + + return bounding_box; +} + +gboolean +gimp_display_shell_get_infinite_canvas (GimpDisplayShell *shell) +{ + g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); + + return shell->show_all && + ! gimp_display_shell_get_padding_in_show_all (shell); +} + +void +gimp_display_shell_update_priority_rect (GimpDisplayShell *shell) +{ + GimpImage *image; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + image = gimp_display_get_image (shell->display); + + if (image) + { + GimpProjection *projection = gimp_image_get_projection (image); + gint x, y; + gint width, height; + + gimp_display_shell_untransform_viewport (shell, ! shell->show_all, + &x, &y, &width, &height); + gimp_projection_set_priority_rect (projection, x, y, width, height); + } +} + +void gimp_display_shell_flush (GimpDisplayShell *shell, gboolean now) { @@ -1817,6 +1971,9 @@ gimp_canvas_layer_boundary_set_layer (GIMP_CANVAS_LAYER_BOUNDARY (shell->layer_boundary), gimp_image_get_active_layer (gimp_display_get_image (shell->display))); + gimp_canvas_canvas_boundary_set_image (GIMP_CANVAS_CANVAS_BOUNDARY (shell->canvas_boundary), + gimp_display_get_image (shell->display)); + if (window && gimp_image_window_get_active_shell (window) == shell) { GimpUIManager *manager = gimp_image_window_get_ui_manager (window); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-callbacks.c gimp-2.10.14+om/app/display/gimpdisplayshell-callbacks.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-callbacks.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-callbacks.c 2019-10-26 18:49:18.000000000 +0000 @@ -43,6 +43,7 @@ #include "gimpdisplayshell-scrollbars.h" #include "gimpdisplayshell-selection.h" #include "gimpdisplayshell-title.h" +#include "gimpdisplayshell-transform.h" #include "gimpdisplayxfer.h" #include "gimpimagewindow.h" #include "gimpnavigationeditor.h" @@ -206,9 +207,18 @@ center_horizontally = sw <= shell->disp_width; center_vertically = sh <= shell->disp_height; - gimp_display_shell_scroll_center_image (shell, - center_horizontally, - center_vertically); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + gimp_display_shell_scroll_center_image (shell, + center_horizontally, + center_vertically); + } + else + { + gimp_display_shell_scroll_center_content (shell, + center_horizontally, + center_vertically); + } /* This is basically the best we can do before we get an * API for storing the image offset at the start of an @@ -454,15 +464,26 @@ cairo_t *cr) { cairo_rectangle_list_t *clip_rectangles; - cairo_rectangle_int_t image_rect; + GeglRectangle image_rect; + GeglRectangle rotated_image_rect; + GeglRectangle canvas_rect; cairo_matrix_t matrix; + gdouble x1, y1; + gdouble x2, y2; - image_rect.x = - shell->offset_x; - image_rect.y = - shell->offset_y; - gimp_display_shell_scale_get_image_size (shell, - &image_rect.width, - &image_rect.height); - + gimp_display_shell_scale_get_image_unrotated_bounding_box ( + shell, + &image_rect.x, + &image_rect.y, + &image_rect.width, + &image_rect.height); + + gimp_display_shell_scale_get_image_unrotated_bounds ( + shell, + &canvas_rect.x, + &canvas_rect.y, + &canvas_rect.width, + &canvas_rect.height); /* the background has already been cleared by GdkWindow */ @@ -479,6 +500,25 @@ if (shell->rotate_transform) cairo_transform (cr, shell->rotate_transform); + if (shell->show_all) + { + cairo_save (cr); + + if (gimp_display_shell_get_padding_in_show_all (shell)) + { + cairo_rectangle (cr, + canvas_rect.x, + canvas_rect.y, + canvas_rect.width, + canvas_rect.height); + cairo_clip (cr); + } + + gimp_display_shell_draw_checkerboard (shell, cr); + + cairo_restore (cr); + } + cairo_rectangle (cr, image_rect.x, image_rect.y, @@ -486,25 +526,50 @@ image_rect.height); cairo_clip (cr); + gimp_display_shell_rotate_bounds (shell, + image_rect.x, + image_rect.y, + image_rect.x + image_rect.width, + image_rect.y + image_rect.height, + &x1, &y1, &x2, &y2); + + rotated_image_rect.x = floor (x1); + rotated_image_rect.y = floor (y1); + rotated_image_rect.width = ceil (x2) - rotated_image_rect.x; + rotated_image_rect.height = ceil (y2) - rotated_image_rect.y; + if (gdk_cairo_get_clip_rectangle (cr, NULL)) { gint i; - cairo_save (cr); - gimp_display_shell_draw_checkerboard (shell, cr); - cairo_restore (cr); - - cairo_set_matrix (cr, &matrix); + if (! shell->show_all) + { + cairo_save (cr); + gimp_display_shell_draw_checkerboard (shell, cr); + cairo_restore (cr); + } - for (i = 0; i < clip_rectangles->num_rectangles; i++) + if (shell->show_image) { - cairo_rectangle_t rect = clip_rectangles->rectangles[i]; + cairo_set_matrix (cr, &matrix); - gimp_display_shell_draw_image (shell, cr, - floor (rect.x), - floor (rect.y), - ceil (rect.width), - ceil (rect.height)); + for (i = 0; i < clip_rectangles->num_rectangles; i++) + { + cairo_rectangle_t clip_rect = clip_rectangles->rectangles[i]; + GeglRectangle rect; + + rect.x = floor (clip_rect.x); + rect.y = floor (clip_rect.y); + rect.width = ceil (clip_rect.x + clip_rect.width) - rect.x; + rect.height = ceil (clip_rect.y + clip_rect.height) - rect.y; + + if (gegl_rectangle_intersect (&rect, &rect, &rotated_image_rect)) + { + gimp_display_shell_draw_image (shell, cr, + rect.x, rect.y, + rect.width, rect.height); + } + } } } diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-dnd.c gimp-2.10.14+om/app/display/gimpdisplayshell-dnd.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-dnd.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-dnd.c 2019-10-26 18:49:18.000000000 +0000 @@ -179,7 +179,10 @@ gint x, y; gint width, height; - gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); + gimp_display_shell_untransform_viewport ( + shell, + ! gimp_display_shell_get_infinite_canvas (shell), + &x, &y, &width, &height); off_x = x + (width - item_width) / 2; off_y = y + (height - item_height) / 2; @@ -495,7 +498,10 @@ buffer = GIMP_BUFFER (viewable); - gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height); + gimp_display_shell_untransform_viewport ( + shell, + ! gimp_display_shell_get_infinite_canvas (shell), + &x, &y, &width, &height); /* FIXME: popup a menu for selecting "Paste Into" */ @@ -518,12 +524,11 @@ GList *list; gboolean open_as_layers; - /* If the app is already being torn down, shell->display might be NULL here. - * Play it safe. */ + /* If the app is already being torn down, shell->display might be + * NULL here. Play it safe. + */ if (! shell->display) - { - return; - } + return; image = gimp_display_get_image (shell->display); context = gimp_get_user_context (shell->display->gimp); @@ -532,6 +537,9 @@ open_as_layers = (image != NULL); + if (image) + g_object_ref (image); + for (list = uri_list; list; list = g_list_next (list)) { GFile *file = g_file_new_for_uri (list->data); @@ -543,6 +551,7 @@ { /* It seems as if GIMP is being torn down for quitting. Bail out. */ g_object_unref (file); + g_clear_object (&image); return; } @@ -558,11 +567,18 @@ if (new_layers) { - gint x, y; - gint width, height; - - gimp_display_shell_untransform_viewport (shell, &x, &y, - &width, &height); + gint x = 0; + gint y = 0; + gint width = gimp_image_get_width (image); + gint height = gimp_image_get_height (image); + + if (gimp_display_get_image (shell->display)) + { + gimp_display_shell_untransform_viewport ( + shell, + ! gimp_display_shell_get_infinite_canvas (shell), + &x, &y, &width, &height); + } gimp_image_add_layers (image, new_layers, GIMP_IMAGE_ACTIVE_PARENT, -1, @@ -601,13 +617,20 @@ gimp_widget_get_monitor (widget), &status, &error); - if (! image && status != GIMP_PDB_CANCEL) - warn = TRUE; + if (image) + { + g_object_ref (image); + } + else if (status != GIMP_PDB_CANCEL) + { + warn = TRUE; + } } /* Something above might have run a few rounds of the main loop. Check * that shell->display is still there, otherwise ignore this as the app - * is being torn down for quitting. */ + * is being torn down for quitting. + */ if (warn && shell->display) { gimp_message (shell->display->gimp, G_OBJECT (shell->display), @@ -622,6 +645,8 @@ if (image) gimp_display_shell_dnd_flush (shell, image); + + g_clear_object (&image); } static void diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-draw.c gimp-2.10.14+om/app/display/gimpdisplayshell-draw.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-draw.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-draw.c 2019-10-26 18:49:18.000000000 +0000 @@ -29,6 +29,7 @@ #include "core/gimp-cairo.h" #include "core/gimp-utils.h" +#include "core/gimpimage.h" #include "gimpcanvas.h" #include "gimpcanvas-style.h" @@ -41,6 +42,9 @@ #include "gimpdisplayshell-transform.h" #include "gimpdisplayxfer.h" +#ifdef GDK_WINDOWING_QUARTZ +#import +#endif /* #define GIMP_DISPLAY_RENDER_ENABLE_SCALING 1 */ @@ -84,9 +88,13 @@ gimp_display_shell_draw_checkerboard (GimpDisplayShell *shell, cairo_t *cr) { + GimpImage *image; + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); g_return_if_fail (cr != NULL); + image = gimp_display_get_image (shell->display); + if (G_UNLIKELY (! shell->checkerboard)) { GimpCheckSize check_size; @@ -111,7 +119,12 @@ } cairo_translate (cr, - shell->offset_x, - shell->offset_y); - cairo_set_source (cr, shell->checkerboard); + + if (gimp_image_get_component_visible (image, GIMP_CHANNEL_ALPHA)) + cairo_set_source (cr, shell->checkerboard); + else + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_paint (cr); } @@ -147,6 +160,17 @@ scale *= gdk_window_get_scale_factor ( gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell)))); +#elif defined(GDK_WINDOWING_QUARTZ) + /* gtk2/osx retina support */ + if ([ + [NSScreen mainScreen] + respondsToSelector: @selector(backingScaleFactor) + ]) { + for (NSScreen * screen in [NSScreen screens]) { + float s = [screen backingScaleFactor]; + if (s > scale) scale = s; + } + } #endif scale = MIN (scale, GIMP_DISPLAY_RENDER_MAX_SCALE); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-filter.c gimp-2.10.14+om/app/display/gimpdisplayshell-filter.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-filter.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-filter.c 2019-10-26 18:49:18.000000000 +0000 @@ -53,16 +53,12 @@ g_signal_handlers_disconnect_by_func (shell->filter_stack, gimp_display_shell_filter_changed, shell); - - g_object_unref (shell->filter_stack); } - shell->filter_stack = stack; + g_set_object (&shell->filter_stack, stack); if (shell->filter_stack) { - g_object_ref (shell->filter_stack); - g_signal_connect (shell->filter_stack, "changed", G_CALLBACK (gimp_display_shell_filter_changed), shell); @@ -90,42 +86,6 @@ return FALSE; } -GimpColorDisplayStack * -gimp_display_shell_filter_new (GimpDisplayShell *shell) -{ - g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL); - -#if 0 - /* disabled because we use gimpdisplayshell-profile now, keep - * the code around for reference. - */ - if (config->display_module) - { - GType type = g_type_from_name (config->display_module); - - if (g_type_is_a (type, GIMP_TYPE_COLOR_DISPLAY)) - { - GimpColorDisplay *display; - GimpColorDisplayStack *stack; - - display = g_object_new (type, - "color-config", config, - "color-managed", shell, - NULL); - - stack = gimp_color_display_stack_new (); - - gimp_color_display_stack_add (stack, display); - g_object_unref (display); - - return stack; - } - } -#endif - - return NULL; -} - /* private functions */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-filter.h gimp-2.10.14+om/app/display/gimpdisplayshell-filter.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-filter.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-filter.h 2019-10-26 18:49:18.000000000 +0000 @@ -24,8 +24,5 @@ gboolean gimp_display_shell_has_filter (GimpDisplayShell *shell); -GimpColorDisplayStack * - gimp_display_shell_filter_new (GimpDisplayShell *shell); - #endif /* __GIMP_DISPLAY_SHELL_FILTER_H__ */ diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell.h gimp-2.10.14+om/app/display/gimpdisplayshell.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell.h 2019-10-26 18:49:18.000000000 +0000 @@ -91,6 +91,10 @@ gboolean proximity; /* is a device in proximity */ + gboolean show_image; /* whether to show the image */ + + gboolean show_all; /* show the entire image */ + Selection *selection; /* Selection (marching ants) */ GList *children; @@ -120,6 +124,7 @@ GimpCanvasItem *grid; /* item proxy of the grid */ GimpCanvasItem *guides; /* item proxies of guides */ GimpCanvasItem *sample_points; /* item proxies of sample points */ + GimpCanvasItem *canvas_boundary; /* item for the cabvas boundary */ GimpCanvasItem *layer_boundary; /* item for the layer boundary */ GimpCanvasItem *tool_items; /* tools items, below the cursor */ GimpCanvasItem *cursor; /* item for the software cursor */ @@ -208,6 +213,8 @@ gdouble rotate_drag_angle; gboolean scaling; gpointer scroll_info; + gboolean layer_picking; + GimpLayer *picked_layer; GeglBuffer *mask; gint mask_offset_x; @@ -295,6 +302,24 @@ gint *width, gint *height); +void gimp_display_shell_set_show_image + (GimpDisplayShell *shell, + gboolean show_image); + +void gimp_display_shell_set_show_all (GimpDisplayShell *shell, + gboolean show_all); + +GimpPickable * gimp_display_shell_get_pickable (GimpDisplayShell *shell); +GimpPickable * gimp_display_shell_get_canvas_pickable + (GimpDisplayShell *shell); +GeglRectangle gimp_display_shell_get_bounding_box + (GimpDisplayShell *shell); +gboolean gimp_display_shell_get_infinite_canvas + (GimpDisplayShell *shell); + +void gimp_display_shell_update_priority_rect + (GimpDisplayShell *shell); + void gimp_display_shell_flush (GimpDisplayShell *shell, gboolean now); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-handlers.c gimp-2.10.14+om/app/display/gimpdisplayshell-handlers.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-handlers.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-handlers.c 2019-10-26 18:49:18.000000000 +0000 @@ -48,6 +48,7 @@ #include "widgets/gimpwidgets-utils.h" +#include "gimpcanvascanvasboundary.h" #include "gimpcanvasguide.h" #include "gimpcanvaslayerboundary.h" #include "gimpcanvaspath.h" @@ -89,6 +90,10 @@ static void gimp_display_shell_selection_invalidate_handler (GimpImage *image, GimpDisplayShell *shell); +static void gimp_display_shell_component_visibility_changed_handler + (GimpImage *image, + GimpChannelType channel, + GimpDisplayShell *shell); static void gimp_display_shell_size_changed_detailed_handler (GimpImage *image, gint previous_origin_x, @@ -120,6 +125,8 @@ GimpDisplayShell *shell); static void gimp_display_shell_invalidate_preview_handler (GimpImage *image, GimpDisplayShell *shell); +static void gimp_display_shell_mode_changed_handler (GimpImage *image, + GimpDisplayShell *shell); static void gimp_display_shell_precision_changed_handler (GimpImage *image, GimpDisplayShell *shell); static void gimp_display_shell_profile_changed_handler (GimpColorManaged *image, @@ -171,6 +178,9 @@ static void gimp_display_shell_color_config_notify_handler (GObject *config, GParamSpec *param_spec, GimpDisplayShell *shell); +static void gimp_display_shell_display_changed_handler (GimpContext *context, + GimpDisplay *display, + GimpDisplayShell *shell); /* public functions */ @@ -182,6 +192,7 @@ GimpContainer *vectors; GimpDisplayConfig *config; GimpColorConfig *color_config; + GimpContext *user_context; GList *list; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); @@ -196,6 +207,8 @@ config = shell->display->config; color_config = GIMP_CORE_CONFIG (config)->color_management; + user_context = gimp_get_user_context (shell->display->gimp); + g_signal_connect (image, "clean", G_CALLBACK (gimp_display_shell_clean_dirty_handler), shell); @@ -217,6 +230,9 @@ g_signal_connect (image, "selection-invalidate", G_CALLBACK (gimp_display_shell_selection_invalidate_handler), shell); + g_signal_connect (image, "component-visibility-changed", + G_CALLBACK (gimp_display_shell_component_visibility_changed_handler), + shell); g_signal_connect (image, "size-changed-detailed", G_CALLBACK (gimp_display_shell_size_changed_detailed_handler), shell); @@ -262,15 +278,15 @@ g_signal_connect (image, "invalidate-preview", G_CALLBACK (gimp_display_shell_invalidate_preview_handler), shell); + g_signal_connect (image, "mode-changed", + G_CALLBACK (gimp_display_shell_mode_changed_handler), + shell); g_signal_connect (image, "precision-changed", G_CALLBACK (gimp_display_shell_precision_changed_handler), shell); g_signal_connect (image, "profile-changed", G_CALLBACK (gimp_display_shell_profile_changed_handler), shell); - g_signal_connect (image, "precision-changed", - G_CALLBACK (gimp_display_shell_precision_changed_handler), - shell); g_signal_connect (image, "saved", G_CALLBACK (gimp_display_shell_saved_handler), shell); @@ -373,6 +389,10 @@ G_CALLBACK (gimp_display_shell_color_config_notify_handler), shell); + g_signal_connect (user_context, "display-changed", + G_CALLBACK (gimp_display_shell_display_changed_handler), + shell); + gimp_display_shell_active_vectors_handler (image, shell); gimp_display_shell_invalidate_preview_handler (image, shell); gimp_display_shell_quick_mask_changed_handler (image, shell); @@ -384,6 +404,16 @@ gimp_canvas_layer_boundary_set_layer (GIMP_CANVAS_LAYER_BOUNDARY (shell->layer_boundary), gimp_image_get_active_layer (image)); + + gimp_canvas_canvas_boundary_set_image (GIMP_CANVAS_CANVAS_BOUNDARY (shell->canvas_boundary), + image); + + if (shell->show_all) + { + gimp_image_inc_show_all_count (image); + + gimp_image_flush (image); + } } void @@ -393,6 +423,7 @@ GimpContainer *vectors; GimpDisplayConfig *config; GimpColorConfig *color_config; + GimpContext *user_context; GList *list; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); @@ -407,11 +438,20 @@ config = shell->display->config; color_config = GIMP_CORE_CONFIG (config)->color_management; + user_context = gimp_get_user_context (shell->display->gimp); + gimp_display_shell_icon_update_stop (shell); gimp_canvas_layer_boundary_set_layer (GIMP_CANVAS_LAYER_BOUNDARY (shell->layer_boundary), NULL); + gimp_canvas_canvas_boundary_set_image (GIMP_CANVAS_CANVAS_BOUNDARY (shell->canvas_boundary), + NULL); + + g_signal_handlers_disconnect_by_func (user_context, + gimp_display_shell_display_changed_handler, + shell); + g_signal_handlers_disconnect_by_func (color_config, gimp_display_shell_color_config_notify_handler, shell); @@ -483,6 +523,9 @@ gimp_display_shell_precision_changed_handler, shell); g_signal_handlers_disconnect_by_func (image, + gimp_display_shell_mode_changed_handler, + shell); + g_signal_handlers_disconnect_by_func (image, gimp_display_shell_invalidate_preview_handler, shell); @@ -527,6 +570,9 @@ gimp_display_shell_resolution_changed_handler, shell); g_signal_handlers_disconnect_by_func (image, + gimp_display_shell_component_visibility_changed_handler, + shell); + g_signal_handlers_disconnect_by_func (image, gimp_display_shell_size_changed_detailed_handler, shell); g_signal_handlers_disconnect_by_func (image, @@ -544,6 +590,13 @@ g_signal_handlers_disconnect_by_func (image, gimp_display_shell_clean_dirty_handler, shell); + + if (shell->show_all) + { + gimp_image_dec_show_all_count (image); + + gimp_image_flush (image); + } } @@ -774,6 +827,15 @@ } static void +gimp_display_shell_component_visibility_changed_handler (GimpImage *image, + GimpChannelType channel, + GimpDisplayShell *shell) +{ + if (channel == GIMP_CHANNEL_ALPHA && shell->show_all) + gimp_display_shell_expose_full (shell); +} + +static void gimp_display_shell_size_changed_detailed_handler (GimpImage *image, gint previous_origin_x, gint previous_origin_y, @@ -822,7 +884,11 @@ shell->offset_x + scaled_previous_origin_x, shell->offset_y + scaled_previous_origin_y); - gimp_display_shell_scroll_center_image (shell, horizontally, vertically); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + gimp_display_shell_scroll_center_image (shell, + horizontally, vertically); + } /* The above calls might not lead to a call to * gimp_display_shell_scroll_clamp_and_update() and @@ -846,6 +912,13 @@ } static void +gimp_display_shell_mode_changed_handler (GimpImage *image, + GimpDisplayShell *shell) +{ + gimp_display_shell_profile_update (shell); +} + +static void gimp_display_shell_precision_changed_handler (GimpImage *image, GimpDisplayShell *shell) { @@ -1155,3 +1228,12 @@ shell->color_config_set = FALSE; } } + +static void +gimp_display_shell_display_changed_handler (GimpContext *context, + GimpDisplay *display, + GimpDisplayShell *shell) +{ + if (shell->display == display) + gimp_display_shell_update_priority_rect (shell); +} diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-items.c gimp-2.10.14+om/app/display/gimpdisplayshell-items.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-items.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-items.c 2019-10-26 18:49:18.000000000 +0000 @@ -27,6 +27,7 @@ #include "display-types.h" +#include "gimpcanvascanvasboundary.h" #include "gimpcanvascursor.h" #include "gimpcanvasgrid.h" #include "gimpcanvaslayerboundary.h" @@ -84,6 +85,11 @@ gimp_display_shell_add_item (shell, shell->sample_points); g_object_unref (shell->sample_points); + shell->canvas_boundary = gimp_canvas_canvas_boundary_new (shell); + gimp_canvas_item_set_visible (shell->canvas_boundary, FALSE); + gimp_display_shell_add_item (shell, shell->canvas_boundary); + g_object_unref (shell->canvas_boundary); + shell->layer_boundary = gimp_canvas_layer_boundary_new (shell); gimp_canvas_item_set_visible (shell->layer_boundary, FALSE); gimp_display_shell_add_item (shell, shell->layer_boundary); @@ -122,14 +128,15 @@ g_clear_object (&shell->canvas_item); - shell->passe_partout = NULL; - shell->preview_items = NULL; - shell->vectors = NULL; - shell->grid = NULL; - shell->guides = NULL; - shell->sample_points = NULL; - shell->layer_boundary = NULL; - shell->tool_items = NULL; + shell->passe_partout = NULL; + shell->preview_items = NULL; + shell->vectors = NULL; + shell->grid = NULL; + shell->guides = NULL; + shell->sample_points = NULL; + shell->canvas_boundary = NULL; + shell->layer_boundary = NULL; + shell->tool_items = NULL; } if (shell->unrotated_item) diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-render.c gimp-2.10.14+om/app/display/gimpdisplayshell-render.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-render.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-render.c 2019-10-26 18:49:18.000000000 +0000 @@ -59,6 +59,7 @@ #ifdef USE_NODE_BLIT GeglNode *node; #endif + GeglAbyssPolicy abyss_policy; cairo_surface_t *xfer; gint xfer_src_x; gint xfer_src_y; @@ -74,13 +75,19 @@ g_return_if_fail (scale > 0.0); image = gimp_display_get_image (shell->display); - buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image)); + buffer = gimp_pickable_get_buffer ( + gimp_display_shell_get_pickable (shell)); #ifdef USE_NODE_BLIT node = gimp_projectable_get_graph (GIMP_PROJECTABLE (image)); gimp_projectable_begin_render (GIMP_PROJECTABLE (image)); #endif + if (shell->show_all) + abyss_policy = GEGL_ABYSS_NONE; + else + abyss_policy = GEGL_ABYSS_CLAMP; + xfer = gimp_display_xfer_get_surface (shell->xfer, w, h, &xfer_src_x, &xfer_src_y); @@ -134,7 +141,7 @@ GEGL_RECTANGLE (x, y, w, h), scale, gimp_projectable_get_format (GIMP_PROJECTABLE (image)), shell->profile_data, shell->profile_stride, - GEGL_ABYSS_CLAMP); + abyss_policy); #else gegl_node_blit (node, scale, GEGL_RECTANGLE (x, y, w, h), @@ -152,7 +159,7 @@ GEGL_RECTANGLE (x, y, w, h), scale, shell->filter_format, shell->filter_data, shell->filter_stride, - GEGL_ABYSS_CLAMP); + abyss_policy); #else gegl_node_blit (node, scale, GEGL_RECTANGLE (x, y, w, h), @@ -255,7 +262,7 @@ GEGL_RECTANGLE (0, 0, w, h), 1.0, babl_format ("cairo-ARGB32"), cairo_data, cairo_stride, - GEGL_ABYSS_CLAMP); + GEGL_ABYSS_NONE); } } else @@ -268,7 +275,7 @@ GEGL_RECTANGLE (x, y, w, h), scale, babl_format ("cairo-ARGB32"), cairo_data, cairo_stride, - GEGL_ABYSS_CLAMP); + abyss_policy); #else gegl_node_blit (node, scale, GEGL_RECTANGLE (x, y, w, h), diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-rotate.c gimp-2.10.14+om/app/display/gimpdisplayshell-rotate.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-rotate.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-rotate.c 2019-10-26 18:49:18.000000000 +0000 @@ -35,6 +35,9 @@ #include "gimpdisplayshell-transform.h" +#define ANGLE_EPSILON 1e-3 + + /* local function prototypes */ static void gimp_display_shell_save_viewport_center (GimpDisplayShell *shell, @@ -165,8 +168,12 @@ { g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); - g_free (shell->rotate_transform); - g_free (shell->rotate_untransform); + g_clear_pointer (&shell->rotate_transform, g_free); + g_clear_pointer (&shell->rotate_untransform, g_free); + + if (fabs (shell->rotate_angle) < ANGLE_EPSILON || + fabs (360.0 - shell->rotate_angle) < ANGLE_EPSILON) + shell->rotate_angle = 0.0; if ((shell->rotate_angle != 0.0 || shell->flip_horizontally || @@ -202,11 +209,6 @@ *shell->rotate_untransform = *shell->rotate_transform; cairo_matrix_invert (shell->rotate_untransform); } - else - { - shell->rotate_transform = NULL; - shell->rotate_untransform = NULL; - } } diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-rotate-dialog.c gimp-2.10.14+om/app/display/gimpdisplayshell-rotate-dialog.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-rotate-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-rotate-dialog.c 2019-04-07 11:38:14.000000000 +0000 @@ -157,7 +157,7 @@ data->rotate_adj = (GtkAdjustment *) gtk_adjustment_new (shell->rotate_angle, 0.0, 360.0, 1, 15, 0); - spin = gtk_spin_button_new (data->rotate_adj, 1.0, 2); + spin = gimp_spin_button_new (data->rotate_adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spin), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (spin), TRUE); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale.c gimp-2.10.14+om/app/display/gimpdisplayshell-scale.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scale.c 2019-10-26 18:49:18.000000000 +0000 @@ -275,6 +275,148 @@ } /** + * gimp_display_shell_scale_get_image_unrotated_bounds: + * @shell: + * @x: + * @y: + * @w: + * @h: + * + * Gets the screen-space boudning box of the image, after it has + * been scaled and scrolled, but before it has been rotated. + **/ +void +gimp_display_shell_scale_get_image_unrotated_bounds (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h) +{ + GimpImage *image; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + image = gimp_display_get_image (shell->display); + + if (x) *x = -shell->offset_x; + if (y) *y = -shell->offset_y; + if (w) *w = floor (gimp_image_get_width (image) * shell->scale_x); + if (h) *h = floor (gimp_image_get_height (image) * shell->scale_y); +} + +/** + * gimp_display_shell_scale_get_image_bounding_box: + * @shell: + * @x: + * @y: + * @w: + * @h: + * + * Gets the screen-space boudning box of the image content, after it has + * been transformed (i.e., scaled, rotated, and scrolled). + **/ +void +gimp_display_shell_scale_get_image_bounding_box (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h) +{ + GeglRectangle bounding_box; + gdouble x1, y1; + gdouble x2, y2; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + bounding_box = gimp_display_shell_get_bounding_box (shell); + + gimp_display_shell_transform_bounds (shell, + bounding_box.x, + bounding_box.y, + bounding_box.x + bounding_box.width, + bounding_box.y + bounding_box.height, + &x1, &y1, + &x2, &y2); + + if (! shell->show_all) + { + x1 = ceil (x1); + y1 = ceil (y1); + x2 = floor (x2); + y2 = floor (y2); + } + else + { + x1 = floor (x1); + y1 = floor (y1); + x2 = ceil (x2); + y2 = ceil (y2); + } + + if (x) *x = x1 + shell->offset_x; + if (y) *y = y1 + shell->offset_y; + if (w) *w = x2 - x1; + if (h) *h = y2 - y1; +} + +/** + * gimp_display_shell_scale_get_image_unrotated_bounding_box: + * @shell: + * @x: + * @y: + * @w: + * @h: + * + * Gets the screen-space boudning box of the image content, after it has + * been scaled and scrolled, but before it has been rotated. + **/ +void +gimp_display_shell_scale_get_image_unrotated_bounding_box (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h) +{ + GeglRectangle bounding_box; + gdouble x1, y1; + gdouble x2, y2; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + bounding_box = gimp_display_shell_get_bounding_box (shell); + + x1 = bounding_box.x * shell->scale_x - + shell->offset_x; + y1 = bounding_box.y * shell->scale_y - + shell->offset_y; + + x2 = (bounding_box.x + bounding_box.width) * shell->scale_x - + shell->offset_x; + y2 = (bounding_box.y + bounding_box.height) * shell->scale_y - + shell->offset_y; + + if (! shell->show_all) + { + x1 = ceil (x1); + y1 = ceil (y1); + x2 = floor (x2); + y2 = floor (y2); + } + else + { + x1 = floor (x1); + y1 = floor (y1); + x2 = ceil (x2); + y2 = ceil (y2); + } + + if (x) *x = x1; + if (y) *y = y1; + if (w) *w = x2 - x1; + if (h) *h = y2 - y1; +} + +/** * gimp_display_shell_scale_image_is_within_viewport: * @shell: * @@ -286,7 +428,6 @@ gboolean *horizontally, gboolean *vertically) { - gint sw, sh; gboolean horizontally_dummy, vertically_dummy; g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE); @@ -294,15 +435,25 @@ if (! horizontally) horizontally = &horizontally_dummy; if (! vertically) vertically = &vertically_dummy; - gimp_display_shell_scale_get_image_size (shell, &sw, &sh); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + gint sx, sy; + gint sw, sh; + + gimp_display_shell_scale_get_image_bounding_box (shell, + &sx, &sy, &sw, &sh); + + sx -= shell->offset_x; + sy -= shell->offset_y; - *horizontally = sw <= shell->disp_width && - shell->offset_x <= 0 && - shell->offset_x >= sw - shell->disp_width; - - *vertically = sh <= shell->disp_height && - shell->offset_y <= 0 && - shell->offset_y >= sh - shell->disp_height; + *horizontally = sx >= 0 && sx + sw <= shell->disp_width; + *vertically = sy >= 0 && sy + sh <= shell->disp_height; + } + else + { + *horizontally = FALSE; + *vertically = FALSE; + } return *vertically && *horizontally; } @@ -1001,22 +1152,37 @@ gimp_display_shell_scale_fit_or_fill (GimpDisplayShell *shell, gboolean fill) { - GimpImage *image; - gdouble image_x; - gdouble image_y; - gdouble image_width; - gdouble image_height; - gdouble current_scale; - gdouble zoom_factor; + GeglRectangle bounding_box; + gdouble image_x; + gdouble image_y; + gdouble image_width; + gdouble image_height; + gdouble current_scale; + gdouble zoom_factor; - image = gimp_display_get_image (shell->display); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + GimpImage *image = gimp_display_get_image (shell->display); + + bounding_box.x = 0; + bounding_box.y = 0; + bounding_box.width = gimp_image_get_width (image); + bounding_box.height = gimp_image_get_height (image); + } + else + { + bounding_box = gimp_display_shell_get_bounding_box (shell); + } gimp_display_shell_transform_bounds (shell, - 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image), - &image_x, &image_y, - &image_width, &image_height); + bounding_box.x, + bounding_box.y, + bounding_box.x + bounding_box.width, + bounding_box.y + bounding_box.height, + &image_x, + &image_y, + &image_width, + &image_height); image_width -= image_x; image_height -= image_y; @@ -1039,7 +1205,7 @@ zoom_factor * current_scale, GIMP_ZOOM_FOCUS_BEST_GUESS); - gimp_display_shell_scroll_center_image (shell, TRUE, TRUE); + gimp_display_shell_scroll_center_content (shell, TRUE, TRUE); } static gboolean @@ -1056,7 +1222,8 @@ if (! horizontally) horizontally = &horizontally_dummy; /* The image can only start to fit if we zoom out */ - if (new_scale > current_scale) + if (new_scale > current_scale || + gimp_display_shell_get_infinite_canvas (shell)) { *vertically = FALSE; *horizontally = FALSE; @@ -1117,16 +1284,19 @@ gboolean *horizontally, gboolean *vertically) { - gboolean local_horizontally; - gboolean local_vertically; - gint center_x = shell->disp_width / 2; - gint center_y = shell->disp_height / 2; + gboolean local_horizontally = FALSE; + gboolean local_vertically = FALSE; + gint center_x = shell->disp_width / 2; + gint center_y = shell->disp_height / 2; - local_horizontally = (x > center_x - ALMOST_CENTERED_THRESHOLD && - x < center_x + ALMOST_CENTERED_THRESHOLD); + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + local_horizontally = (x > center_x - ALMOST_CENTERED_THRESHOLD && + x < center_x + ALMOST_CENTERED_THRESHOLD); - local_vertically = (y > center_y - ALMOST_CENTERED_THRESHOLD && - y < center_y + ALMOST_CENTERED_THRESHOLD); + local_vertically = (y > center_y - ALMOST_CENTERED_THRESHOLD && + y < center_y + ALMOST_CENTERED_THRESHOLD); + } if (horizontally) *horizontally = local_horizontally; if (vertically) *vertically = local_vertically; diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale-dialog.c gimp-2.10.14+om/app/display/gimpdisplayshell-scale-dialog.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale-dialog.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scale-dialog.c 2019-04-07 11:38:14.000000000 +0000 @@ -166,7 +166,7 @@ data->num_adj = (GtkAdjustment *) gtk_adjustment_new (num, 1, 256, 1, 8, 0); - spin = gtk_spin_button_new (data->num_adj, 1.0, 0); + spin = gimp_spin_button_new (data->num_adj, 1.0, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (spin), TRUE); gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0); @@ -178,7 +178,7 @@ data->denom_adj = (GtkAdjustment *) gtk_adjustment_new (denom, 1, 256, 1, 8, 0); - spin = gtk_spin_button_new (data->denom_adj, 1.0, 0); + spin = gimp_spin_button_new (data->denom_adj, 1.0, 0); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (spin), TRUE); gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0); @@ -193,7 +193,7 @@ gtk_adjustment_new (fabs (shell->other_scale) * 100, 100.0 / 256.0, 25600.0, 10, 50, 0); - spin = gtk_spin_button_new (data->scale_adj, 1.0, 2); + spin = gimp_spin_button_new (data->scale_adj, 1.0, 2); gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spin), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (spin), TRUE); gtk_box_pack_start (GTK_BOX (hbox), spin, TRUE, TRUE, 0); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale.h gimp-2.10.14+om/app/display/gimpdisplayshell-scale.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scale.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scale.h 2019-10-26 18:49:18.000000000 +0000 @@ -34,6 +34,24 @@ gint *y, gint *w, gint *h); +void gimp_display_shell_scale_get_image_unrotated_bounds + (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h); +void gimp_display_shell_scale_get_image_bounding_box + (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h); +void gimp_display_shell_scale_get_image_unrotated_bounding_box + (GimpDisplayShell *shell, + gint *x, + gint *y, + gint *w, + gint *h); gboolean gimp_display_shell_scale_image_is_within_viewport (GimpDisplayShell *shell, gboolean *horizontally, diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scrollbars.c gimp-2.10.14+om/app/display/gimpdisplayshell-scrollbars.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scrollbars.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scrollbars.c 2019-10-26 18:49:18.000000000 +0000 @@ -93,6 +93,10 @@ { gint bounds_x; gint bounds_width; + gint bounding_box_x; + gint bounding_box_width; + gint x1; + gint x2; gdouble lower; gdouble upper; gdouble scale_x; @@ -103,17 +107,30 @@ return; gimp_display_shell_scale_get_image_bounds (shell, - &bounds_x, NULL, + &bounds_x, NULL, &bounds_width, NULL); - if (shell->disp_width > bounds_width) + if (! gimp_display_shell_get_infinite_canvas (shell)) { - bounds_x -= (shell->disp_width - bounds_width) / 2; - bounds_width = shell->disp_width; + bounding_box_x = bounds_x; + bounding_box_width = bounds_width; } + else + { + gimp_display_shell_scale_get_image_bounding_box ( + shell, + &bounding_box_x, NULL, + &bounding_box_width, NULL); + } + + x1 = bounding_box_x; + x2 = bounding_box_x + bounding_box_width; + + x1 = MIN (x1, bounds_x + bounds_width / 2 - shell->disp_width / 2); + x2 = MAX (x2, bounds_x + bounds_width / 2 + (shell->disp_width + 1) / 2); - lower = MIN (value, bounds_x); - upper = MAX (value + shell->disp_width, bounds_x + bounds_width); + lower = MIN (value, x1); + upper = MAX (value + shell->disp_width, x2); gimp_display_shell_get_rotated_scale (shell, &scale_x, NULL); @@ -137,6 +154,10 @@ { gint bounds_y; gint bounds_height; + gint bounding_box_y; + gint bounding_box_height; + gint y1; + gint y2; gdouble lower; gdouble upper; gdouble scale_y; @@ -150,14 +171,27 @@ NULL, &bounds_y, NULL, &bounds_height); - if (shell->disp_height > bounds_height) + if (! gimp_display_shell_get_infinite_canvas (shell)) { - bounds_y -= (shell->disp_height - bounds_height) / 2; - bounds_height = shell->disp_height; + bounding_box_y = bounds_y; + bounding_box_height = bounds_height; } + else + { + gimp_display_shell_scale_get_image_bounding_box ( + shell, + NULL, &bounding_box_y, + NULL, &bounding_box_height); + } + + y1 = bounding_box_y; + y2 = bounding_box_y + bounding_box_height; + + y1 = MIN (y1, bounds_y + bounds_height / 2 - shell->disp_height / 2); + y2 = MAX (y2, bounds_y + bounds_height / 2 + (shell->disp_height + 1) / 2); - lower = MIN (value, bounds_y); - upper = MAX (value + shell->disp_height, bounds_y + bounds_height); + lower = MIN (value, y1); + upper = MAX (value + shell->disp_height, y2); gimp_display_shell_get_rotated_scale (shell, NULL, &scale_y); diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scroll.c gimp-2.10.14+om/app/display/gimpdisplayshell-scroll.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scroll.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scroll.c 2019-10-26 18:49:18.000000000 +0000 @@ -160,83 +160,98 @@ if (image) { - gint bounds_x; - gint bounds_y; - gint bounds_width; - gint bounds_height; - gint min_offset_x; - gint max_offset_x; - gint min_offset_y; - gint max_offset_y; - gint offset_x; - gint offset_y; - - gimp_display_shell_rotate_update_transform (shell); - - gimp_display_shell_scale_get_image_bounds (shell, - &bounds_x, &bounds_y, - &bounds_width, &bounds_height); - - if (shell->disp_width < bounds_width) - { - min_offset_x = bounds_x - - shell->disp_width * OVERPAN_FACTOR; - max_offset_x = bounds_x + bounds_width - - shell->disp_width * (1.0 - OVERPAN_FACTOR); - } - else + if (! shell->show_all) { - gint overpan_amount; - - overpan_amount = shell->disp_width - - bounds_width * (1.0 - OVERPAN_FACTOR); + gint bounds_x; + gint bounds_y; + gint bounds_width; + gint bounds_height; + gint min_offset_x; + gint max_offset_x; + gint min_offset_y; + gint max_offset_y; + gint offset_x; + gint offset_y; - min_offset_x = bounds_x - - overpan_amount; - max_offset_x = bounds_x + bounds_width - shell->disp_width + - overpan_amount; - } + gimp_display_shell_rotate_update_transform (shell); - if (shell->disp_height < bounds_height) - { - min_offset_y = bounds_y - - shell->disp_height * OVERPAN_FACTOR; - max_offset_y = bounds_y + bounds_height - - shell->disp_height * (1.0 - OVERPAN_FACTOR); + gimp_display_shell_scale_get_image_bounds (shell, + &bounds_x, + &bounds_y, + &bounds_width, + &bounds_height); + + if (shell->disp_width < bounds_width) + { + min_offset_x = bounds_x - + shell->disp_width * OVERPAN_FACTOR; + max_offset_x = bounds_x + bounds_width - + shell->disp_width * (1.0 - OVERPAN_FACTOR); + } + else + { + gint overpan_amount; + + overpan_amount = shell->disp_width - + bounds_width * (1.0 - OVERPAN_FACTOR); + + min_offset_x = bounds_x - + overpan_amount; + max_offset_x = bounds_x + bounds_width - shell->disp_width + + overpan_amount; + } + + if (shell->disp_height < bounds_height) + { + min_offset_y = bounds_y - + shell->disp_height * OVERPAN_FACTOR; + max_offset_y = bounds_y + bounds_height - + shell->disp_height * (1.0 - OVERPAN_FACTOR); + } + else + { + gint overpan_amount; + + overpan_amount = shell->disp_height - + bounds_height * (1.0 - OVERPAN_FACTOR); + + min_offset_y = bounds_y - + overpan_amount; + max_offset_y = bounds_y + bounds_height + + overpan_amount - shell->disp_height; + } + + /* Clamp */ + + offset_x = CLAMP (shell->offset_x, min_offset_x, max_offset_x); + offset_y = CLAMP (shell->offset_y, min_offset_y, max_offset_y); + + if (offset_x != shell->offset_x || offset_y != shell->offset_y) + { + shell->offset_x = offset_x; + shell->offset_y = offset_y; + + gimp_display_shell_rotate_update_transform (shell); + } + + /* Set scrollbar stepper sensitiity */ + + gimp_display_shell_scrollbars_update_steppers (shell, + min_offset_x, + max_offset_x, + min_offset_y, + max_offset_y); } else { - gint overpan_amount; - - overpan_amount = shell->disp_height - - bounds_height * (1.0 - OVERPAN_FACTOR); - - min_offset_y = bounds_y - - overpan_amount; - max_offset_y = bounds_y + bounds_height + - overpan_amount - shell->disp_height; - } - - /* Clamp */ - - offset_x = CLAMP (shell->offset_x, min_offset_x, max_offset_x); - offset_y = CLAMP (shell->offset_y, min_offset_y, max_offset_y); - - if (offset_x != shell->offset_x || offset_y != shell->offset_y) - { - shell->offset_x = offset_x; - shell->offset_y = offset_y; + /* Set scrollbar stepper sensitiity */ - gimp_display_shell_rotate_update_transform (shell); + gimp_display_shell_scrollbars_update_steppers (shell, + G_MININT, + G_MAXINT, + G_MININT, + G_MAXINT); } - - /* Set scrollbar stepper sensitiity */ - - gimp_display_shell_scrollbars_update_steppers (shell, - min_offset_x, - max_offset_x, - min_offset_y, - max_offset_y); } else { @@ -278,32 +293,35 @@ *out_offset_x = in_offset_x; *out_offset_y = in_offset_y; - gimp_display_shell_scale_get_image_size (shell, &sw, &sh); - - if (in_offset_x < 0) + if (! shell->show_all) { - *out_offset_x = MAX (in_offset_x, - MIN (0, 0 - shell->offset_x)); - } - else if (in_offset_x > 0) - { - gint min_offset = sw - shell->disp_width; + gimp_display_shell_scale_get_image_size (shell, &sw, &sh); - *out_offset_x = MIN (in_offset_x, - MAX (0, min_offset - shell->offset_x)); - } + if (in_offset_x < 0) + { + *out_offset_x = MAX (in_offset_x, + MIN (0, 0 - shell->offset_x)); + } + else if (in_offset_x > 0) + { + gint min_offset = sw - shell->disp_width; - if (in_offset_y < 0) - { - *out_offset_y = MAX (in_offset_y, - MIN (0, 0 - shell->offset_y)); - } - else if (in_offset_y > 0) - { - gint min_offset = sh - shell->disp_height; + *out_offset_x = MIN (in_offset_x, + MAX (0, min_offset - shell->offset_x)); + } - *out_offset_y = MIN (in_offset_y, - MAX (0, min_offset - shell->offset_y)); + if (in_offset_y < 0) + { + *out_offset_y = MAX (in_offset_y, + MIN (0, 0 - shell->offset_y)); + } + else if (in_offset_y > 0) + { + gint min_offset = sh - shell->disp_height; + + *out_offset_y = MIN (in_offset_y, + MAX (0, min_offset - shell->offset_y)); + } } } @@ -382,6 +400,76 @@ if (horizontally) offset_x = center_x - shell->disp_width / 2 - shell->offset_x; + + if (vertically) + offset_y = center_y - shell->disp_height / 2 - shell->offset_y; + + gimp_display_shell_scroll (shell, offset_x, offset_y); +} + +/** + * gimp_display_shell_scroll_center_image: + * @shell: + * @horizontally: + * @vertically: + * + * Centers the image content in the display shell on the desired axes. + **/ +void +gimp_display_shell_scroll_center_content (GimpDisplayShell *shell, + gboolean horizontally, + gboolean vertically) +{ + gint content_x; + gint content_y; + gint content_width; + gint content_height; + gint center_x; + gint center_y; + gint offset_x = 0; + gint offset_y = 0; + + g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); + + if (! shell->display || + ! gimp_display_get_image (shell->display) || + (! vertically && ! horizontally)) + return; + + if (! gimp_display_shell_get_infinite_canvas (shell)) + { + gimp_display_shell_scale_get_image_bounds (shell, + &content_x, + &content_y, + &content_width, + &content_height); + } + else + { + gimp_display_shell_scale_get_image_bounding_box (shell, + &content_x, + &content_y, + &content_width, + &content_height); + } + + if (shell->disp_width > content_width) + { + content_x -= (shell->disp_width - content_width) / 2; + content_width = shell->disp_width; + } + + if (shell->disp_height > content_height) + { + content_y -= (shell->disp_height - content_height) / 2; + content_height = shell->disp_height; + } + + center_x = content_x + content_width / 2; + center_y = content_y + content_height / 2; + + if (horizontally) + offset_x = center_x - shell->disp_width / 2 - shell->offset_x; if (vertically) offset_y = center_y - shell->disp_height / 2 - shell->offset_y; diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scroll.h gimp-2.10.14+om/app/display/gimpdisplayshell-scroll.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-scroll.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-scroll.h 2019-10-26 18:49:18.000000000 +0000 @@ -40,6 +40,9 @@ void gimp_display_shell_scroll_center_image (GimpDisplayShell *shell, gboolean horizontally, gboolean vertically); +void gimp_display_shell_scroll_center_content (GimpDisplayShell *shell, + gboolean horizontally, + gboolean vertically); void gimp_display_shell_scroll_get_scaled_viewport (GimpDisplayShell *shell, gint *x, diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-tool-events.c gimp-2.10.14+om/app/display/gimpdisplayshell-tool-events.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-tool-events.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-tool-events.c 2019-04-07 11:38:14.000000000 +0000 @@ -32,6 +32,7 @@ #include "core/gimp-filter-history.h" #include "core/gimpcontext.h" #include "core/gimpimage.h" +#include "core/gimpimage-pick-item.h" #include "core/gimpitem.h" #include "widgets/gimpcontrollers.h" @@ -66,7 +67,9 @@ #include "gimpdisplayshell-transform.h" #include "gimpimagewindow.h" #include "gimpmotionbuffer.h" +#include "gimpstatusbar.h" +#include "gimp-intl.h" #include "gimp-log.h" @@ -1239,6 +1242,10 @@ return FALSE; } + if (gimp_display_shell_key_to_state (kevent->keyval) == GDK_MOD1_MASK) + /* Make sure the picked layer is reset. */ + shell->picked_layer = NULL; + switch (kevent->keyval) { case GDK_KEY_Left: @@ -1320,6 +1327,17 @@ active_tool = tool_manager_get_active (gimp); + if (gimp_display_shell_key_to_state (kevent->keyval) == GDK_MOD1_MASK && + shell->picked_layer) + { + GimpStatusbar *statusbar; + + statusbar = gimp_display_shell_get_statusbar (shell); + gimp_statusbar_pop_temp (statusbar); + + shell->picked_layer = NULL; + } + if ((state & GDK_BUTTON1_MASK) && (! shell->space_release_pending || (kevent->keyval != GDK_KEY_space && @@ -1537,13 +1555,57 @@ shell->rotating = (state & gimp_get_extend_selection_mask ()) ? TRUE : FALSE; shell->rotate_drag_angle = shell->rotate_angle; shell->scaling = (state & gimp_get_toggle_behavior_mask ()) ? TRUE : FALSE; + shell->layer_picking = (state & GDK_MOD1_MASK) ? TRUE : FALSE; if (shell->rotating) - gimp_display_shell_set_override_cursor (shell, - (GimpCursorType) GDK_EXCHANGE); + { + gimp_display_shell_set_override_cursor (shell, + (GimpCursorType) GDK_EXCHANGE); + } else if (shell->scaling) - gimp_display_shell_set_override_cursor (shell, - (GimpCursorType) GIMP_CURSOR_ZOOM); + { + gimp_display_shell_set_override_cursor (shell, + (GimpCursorType) GIMP_CURSOR_ZOOM); + } + else if (shell->layer_picking) + { + GimpImage *image = gimp_display_get_image (shell->display); + GimpLayer *layer; + GimpCoords image_coords; + GimpCoords display_coords; + guint32 time; + + gimp_display_shell_set_override_cursor (shell, + (GimpCursorType) GIMP_CURSOR_CROSSHAIR); + + gimp_display_shell_get_event_coords (shell, event, + &display_coords, + &state, &time); + gimp_display_shell_untransform_event_coords (shell, + &display_coords, &image_coords, + NULL); + layer = gimp_image_pick_layer (image, + (gint) image_coords.x, + (gint) image_coords.y, + shell->picked_layer); + + if (layer && ! gimp_image_get_floating_selection (image)) + { + if (layer != gimp_image_get_active_layer (image)) + { + GimpStatusbar *statusbar; + + gimp_image_set_active_layer (image, layer); + + statusbar = gimp_display_shell_get_statusbar (shell); + gimp_statusbar_push_temp (statusbar, GIMP_MESSAGE_INFO, + GIMP_ICON_LAYER, + _("Layer picked: '%s'"), + gimp_object_get_name (layer)); + } + shell->picked_layer = layer; + } + } else gimp_display_shell_set_override_cursor (shell, (GimpCursorType) GDK_FLEUR); @@ -1565,6 +1627,7 @@ shell->rotating = FALSE; shell->rotate_drag_angle = 0.0; shell->scaling = FALSE; + shell->layer_picking = FALSE; /* We may have ungrabbed the pointer when space was released while * mouse was down, to be able to catch a GDK_BUTTON_RELEASE event. @@ -1600,6 +1663,10 @@ shell->scroll_last_x - x, shell->scroll_last_y - y); } + else if (shell->layer_picking) + { + /* Do nothing. We only pick the layer on click. */ + } else { gimp_display_shell_scroll (shell, diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-transform.c gimp-2.10.14+om/app/display/gimpdisplayshell-transform.c --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-transform.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-transform.c 2019-10-26 18:49:18.000000000 +0000 @@ -956,6 +956,7 @@ /** * gimp_display_shell_untransform_viewport: * @shell: a #GimpDisplayShell + * @clip: whether to clip the result to the image bounds * @x: returns image x coordinate of display upper left corner * @y: returns image y coordinate of display upper left corner * @width: returns width of display measured in image coordinates @@ -966,13 +967,13 @@ **/ void gimp_display_shell_untransform_viewport (GimpDisplayShell *shell, + gboolean clip, gint *x, gint *y, gint *width, gint *height) { - GimpImage *image; - gdouble x1, y1, x2, y2; + gdouble x1, y1, x2, y2; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); @@ -987,19 +988,15 @@ x2 = ceil (x2); y2 = ceil (y2); - image = gimp_display_get_image (shell->display); - - if (x1 < 0) - x1 = 0; - - if (y1 < 0) - y1 = 0; - - if (x2 > gimp_image_get_width (image)) - x2 = gimp_image_get_width (image); - - if (y2 > gimp_image_get_height (image)) - y2 = gimp_image_get_height (image); + if (clip) + { + GimpImage *image = gimp_display_get_image (shell->display); + + x1 = MAX (x1, 0); + y1 = MAX (y1, 0); + x2 = MIN (x2, gimp_image_get_width (image)); + y2 = MIN (y2, gimp_image_get_height (image)); + } if (x) *x = x1; if (y) *y = y1; diff -Nru gimp-2.10.8+zorin2/app/display/gimpdisplayshell-transform.h gimp-2.10.14+om/app/display/gimpdisplayshell-transform.h --- gimp-2.10.8+zorin2/app/display/gimpdisplayshell-transform.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpdisplayshell-transform.h 2019-10-26 18:49:18.000000000 +0000 @@ -190,6 +190,7 @@ gdouble *ny2); void gimp_display_shell_untransform_viewport (GimpDisplayShell *shell, + gboolean clip, gint *x, gint *y, gint *width, diff -Nru gimp-2.10.8+zorin2/app/display/gimpimagewindow.c gimp-2.10.14+om/app/display/gimpimagewindow.c --- gimp-2.10.8+zorin2/app/display/gimpimagewindow.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpimagewindow.c 2019-10-26 18:49:18.000000000 +0000 @@ -78,6 +78,8 @@ #include "gimpstatusbar.h" #include "gimp-log.h" +#include "gimp-priorities.h" + #include "gimp-intl.h" @@ -397,7 +399,7 @@ window, G_CONNECT_SWAPPED); gtk_window_add_accel_group (GTK_WINDOW (window), - gtk_ui_manager_get_accel_group (GTK_UI_MANAGER (private->menubar_manager))); + gimp_ui_manager_get_accel_group (private->menubar_manager)); g_signal_connect (private->menubar_manager, "show-tooltip", G_CALLBACK (gimp_image_window_show_tooltip), @@ -415,9 +417,8 @@ /* Create the menubar */ #ifndef GDK_WINDOWING_QUARTZ - private->menubar = - gtk_ui_manager_get_widget (GTK_UI_MANAGER (private->menubar_manager), - "/image-menubar"); + private->menubar = gimp_ui_manager_get_widget (private->menubar_manager, + "/image-menubar"); #endif /* !GDK_WINDOWING_QUARTZ */ if (private->menubar) { @@ -1464,15 +1465,13 @@ gboolean grow_only) { GimpDisplayShell *active_shell; - GimpImage *image; GtkWidget *widget; GtkAllocation allocation; GdkScreen *screen; GdkRectangle rect; gint monitor; gint disp_width, disp_height; - gdouble x, y; - gdouble width, height; + gint width, height; gint max_auto_width, max_auto_height; gint border_width, border_height; gboolean resize = FALSE; @@ -1489,8 +1488,6 @@ if (!active_shell) return; - image = gimp_display_get_image (active_shell->display); - widget = GTK_WIDGET (window); screen = gtk_widget_get_screen (widget); @@ -1500,15 +1497,17 @@ gtk_widget_get_window (widget)); gdk_screen_get_monitor_workarea (screen, monitor, &rect); - gimp_display_shell_transform_bounds (active_shell, - 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image), - &x, &y, - &width, &height); - - width = ceil (width - x); - height = ceil (height - y); + if (! gimp_display_shell_get_infinite_canvas (active_shell)) + { + gimp_display_shell_scale_get_image_size (active_shell, + &width, &height); + } + else + { + gimp_display_shell_scale_get_image_bounding_box (active_shell, + NULL, NULL, + &width, &height); + } disp_width = active_shell->disp_width; disp_height = active_shell->disp_height; @@ -1611,7 +1610,7 @@ * GimpDisplayShell::configure_event(). */ /* FIXME multiple shells */ - gimp_display_shell_scroll_center_image (active_shell, TRUE, TRUE); + gimp_display_shell_scroll_center_content (active_shell, TRUE, TRUE); } static GtkWidget * @@ -1924,8 +1923,10 @@ if (! private->update_ui_manager_idle_id) { private->update_ui_manager_idle_id = - g_idle_add ((GSourceFunc) gimp_image_window_update_ui_manager_idle, - window); + g_idle_add_full (GIMP_PRIORITY_IMAGE_WINDOW_UPDATE_UI_MANAGER_IDLE, + (GSourceFunc) gimp_image_window_update_ui_manager_idle, + window, + NULL); } } diff -Nru gimp-2.10.8+zorin2/app/display/gimpnavigationeditor.c gimp-2.10.14+om/app/display/gimpnavigationeditor.c --- gimp-2.10.8+zorin2/app/display/gimpnavigationeditor.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpnavigationeditor.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,6 +36,7 @@ #include "core/gimp.h" #include "core/gimpcontext.h" #include "core/gimpimage.h" +#include "core/gimpimageviewable.h" #include "widgets/gimpdocked.h" #include "widgets/gimphelp-ids.h" @@ -46,6 +47,7 @@ #include "gimpdisplay.h" #include "gimpdisplayshell.h" +#include "gimpdisplayshell-appearance.h" #include "gimpdisplayshell-scale.h" #include "gimpdisplayshell-scroll.h" #include "gimpdisplayshell-transform.h" @@ -57,46 +59,57 @@ #define UPDATE_DELAY 300 /* From GtkRange in GTK+ 2.22 */ -static void gimp_navigation_editor_docked_iface_init (GimpDockedInterface *iface); +static void gimp_navigation_editor_docked_iface_init (GimpDockedInterface *iface); -static void gimp_navigation_editor_dispose (GObject *object); +static void gimp_navigation_editor_dispose (GObject *object); -static void gimp_navigation_editor_set_context (GimpDocked *docked, - GimpContext *context); +static void gimp_navigation_editor_set_context (GimpDocked *docked, + GimpContext *context); -static GtkWidget * gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory, - GimpDisplayShell *shell); - -static void gimp_navigation_editor_set_shell (GimpNavigationEditor *editor, - GimpDisplayShell *shell); -static gboolean gimp_navigation_editor_button_release (GtkWidget *widget, - GdkEventButton *bevent, - GimpDisplayShell *shell); -static void gimp_navigation_editor_marker_changed (GimpNavigationView *view, - gdouble center_x, - gdouble center_y, - gdouble width, - gdouble height, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_zoom (GimpNavigationView *view, - GimpZoomType direction, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_scroll (GimpNavigationView *view, - GdkScrollDirection direction, - GimpNavigationEditor *editor); - -static void gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj, - GimpNavigationEditor *editor); - -static void gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_shell_rotated (GimpDisplayShell *shell, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell, - GimpNavigationEditor *editor); -static void gimp_navigation_editor_update_marker (GimpNavigationEditor *editor); +static GtkWidget * gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory, + GimpDisplayShell *shell); + +static void gimp_navigation_editor_set_shell (GimpNavigationEditor *editor, + GimpDisplayShell *shell); +static gboolean gimp_navigation_editor_button_release (GtkWidget *widget, + GdkEventButton *bevent, + GimpDisplayShell *shell); +static void gimp_navigation_editor_marker_changed (GimpNavigationView *view, + gdouble center_x, + gdouble center_y, + gdouble width, + gdouble height, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_zoom (GimpNavigationView *view, + GimpZoomType direction, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_scroll (GimpNavigationView *view, + GdkScrollDirection direction, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_shell_infinite_canvas_notify (GimpDisplayShell *shell, + const GParamSpec *pspec, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_rotated (GimpDisplayShell *shell, + GimpNavigationEditor *editor); +static void gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_viewable_size_changed (GimpViewable *viewable, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_options_show_canvas_notify (GimpDisplayOptions *options, + const GParamSpec *pspec, + GimpNavigationEditor *editor); + +static void gimp_navigation_editor_update_marker (GimpNavigationEditor *editor); G_DEFINE_TYPE_WITH_CODE (GimpNavigationEditor, gimp_navigation_editor, @@ -137,7 +150,7 @@ editor->view = gimp_view_new_by_types (NULL, GIMP_TYPE_NAVIGATION_VIEW, - GIMP_TYPE_IMAGE, + GIMP_TYPE_IMAGE_VIEWABLE, GIMP_VIEW_SIZE_MEDIUM, 0, TRUE); gtk_container_add (GTK_CONTAINER (frame), editor->view); gtk_widget_show (editor->view); @@ -179,7 +192,21 @@ { GimpDisplayShell *shell = NULL; - if (display) + if (display && gimp_display_get_image (display)) + shell = gimp_display_get_shell (display); + + gimp_navigation_editor_set_shell (editor, shell); +} + +static void +gimp_navigation_editor_image_chaged (GimpContext *context, + GimpImage *image, + GimpNavigationEditor *editor) +{ + GimpDisplay *display = gimp_context_get_display (context); + GimpDisplayShell *shell = NULL; + + if (display && image) shell = gimp_display_get_shell (display); gimp_navigation_editor_set_shell (editor, shell); @@ -197,6 +224,9 @@ g_signal_handlers_disconnect_by_func (editor->context, gimp_navigation_editor_display_changed, editor); + g_signal_handlers_disconnect_by_func (editor->context, + gimp_navigation_editor_image_chaged, + editor); } editor->context = context; @@ -206,6 +236,13 @@ g_signal_connect (context, "display-changed", G_CALLBACK (gimp_navigation_editor_display_changed), editor); + /* make sure to also call gimp_navigation_editor_set_shell() when the + * last image is closed, even though the display isn't changed, so that + * the editor is properly cleared. + */ + g_signal_connect (context, "image-changed", + G_CALLBACK (gimp_navigation_editor_image_chaged), + editor); display = gimp_context_get_display (context); } @@ -460,6 +497,9 @@ if (editor->shell) { g_signal_handlers_disconnect_by_func (editor->shell, + gimp_navigation_editor_shell_infinite_canvas_notify, + editor); + g_signal_handlers_disconnect_by_func (editor->shell, gimp_navigation_editor_shell_scaled, editor); g_signal_handlers_disconnect_by_func (editor->shell, @@ -471,6 +511,13 @@ g_signal_handlers_disconnect_by_func (editor->shell, gimp_navigation_editor_shell_reconnect, editor); + + g_signal_handlers_disconnect_by_func (editor->shell->options, + gimp_navigation_editor_options_show_canvas_notify, + editor); + g_signal_handlers_disconnect_by_func (editor->shell->fullscreen_options, + gimp_navigation_editor_options_show_canvas_notify, + editor); } else if (shell) { @@ -483,9 +530,24 @@ { GimpImage *image = gimp_display_get_image (shell->display); + g_clear_object (&editor->image_viewable); + + if (image) + { + editor->image_viewable = gimp_image_viewable_new (image); + + g_signal_connect ( + editor->image_viewable, "size-changed", + G_CALLBACK (gimp_navigation_editor_viewable_size_changed), + editor); + } + gimp_view_set_viewable (GIMP_VIEW (editor->view), - GIMP_VIEWABLE (image)); + GIMP_VIEWABLE (editor->image_viewable)); + g_signal_connect (editor->shell, "notify::infinite-canvas", + G_CALLBACK (gimp_navigation_editor_shell_infinite_canvas_notify), + editor); g_signal_connect (editor->shell, "scaled", G_CALLBACK (gimp_navigation_editor_shell_scaled), editor); @@ -499,12 +561,21 @@ G_CALLBACK (gimp_navigation_editor_shell_reconnect), editor); + g_signal_connect (editor->shell->options, "notify::show-canvas-boundary", + G_CALLBACK (gimp_navigation_editor_options_show_canvas_notify), + editor); + g_signal_connect (editor->shell->fullscreen_options, "notify::show-canvas-boundary", + G_CALLBACK (gimp_navigation_editor_options_show_canvas_notify), + editor); + gimp_navigation_editor_shell_scaled (editor->shell, editor); } else { gimp_view_set_viewable (GIMP_VIEW (editor->view), NULL); gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE); + + g_clear_object (&editor->image_viewable); } if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) @@ -533,11 +604,23 @@ gdouble height, GimpNavigationEditor *editor) { + GimpViewRenderer *renderer = GIMP_VIEW (editor->view)->renderer; + if (editor->shell) { if (gimp_display_get_image (editor->shell->display)) - gimp_display_shell_scroll_center_image_xy (editor->shell, - center_x, center_y); + { + GeglRectangle bounding_box; + + bounding_box = gimp_image_viewable_get_bounding_box ( + GIMP_IMAGE_VIEWABLE (renderer->viewable)); + + center_x += bounding_box.x; + center_y += bounding_box.y; + + gimp_display_shell_scroll_center_image_xy (editor->shell, + center_x, center_y); + } } } @@ -638,6 +721,18 @@ } static void +gimp_navigation_editor_shell_infinite_canvas_notify (GimpDisplayShell *shell, + const GParamSpec *pspec, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell, GimpNavigationEditor *editor) { @@ -699,13 +794,44 @@ } static void +gimp_navigation_editor_viewable_size_changed (GimpViewable *viewable, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); + + if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) + gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), + gimp_editor_get_popup_data (GIMP_EDITOR (editor))); +} + +static void +gimp_navigation_editor_options_show_canvas_notify (GimpDisplayOptions *options, + const GParamSpec *pspec, + GimpNavigationEditor *editor) +{ + gimp_navigation_editor_update_marker (editor); +} + +static void gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell, GimpNavigationEditor *editor) { GimpImage *image = gimp_display_get_image (shell->display); + g_clear_object (&editor->image_viewable); + + if (image) + { + editor->image_viewable = gimp_image_viewable_new (image); + + g_signal_connect ( + editor->image_viewable, "size-changed", + G_CALLBACK (gimp_navigation_editor_viewable_size_changed), + editor); + } + gimp_view_set_viewable (GIMP_VIEW (editor->view), - GIMP_VIEWABLE (image)); + GIMP_VIEWABLE (editor->image_viewable)); if (gimp_editor_get_ui_manager (GIMP_EDITOR (editor))) gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (editor)), @@ -724,19 +850,41 @@ if (renderer->viewable) { GimpNavigationView *view = GIMP_NAVIGATION_VIEW (editor->view); + GimpImage *image; + GeglRectangle bounding_box; gdouble x, y; gdouble w, h; + image = gimp_image_viewable_get_image ( + GIMP_IMAGE_VIEWABLE (renderer->viewable)); + + gimp_image_viewable_set_show_all ( + GIMP_IMAGE_VIEWABLE (renderer->viewable), + gimp_display_shell_get_infinite_canvas (shell)); + + bounding_box = gimp_image_viewable_get_bounding_box ( + GIMP_IMAGE_VIEWABLE (renderer->viewable)); + gimp_display_shell_scroll_get_viewport (shell, &x, &y, &w, &h); gimp_display_shell_untransform_xy_f (shell, shell->disp_width / 2, shell->disp_height / 2, &x, &y); + x -= bounding_box.x; + y -= bounding_box.y; + gimp_navigation_view_set_marker (view, x, y, w, h, shell->flip_horizontally, shell->flip_vertically, shell->rotate_angle); + + gimp_navigation_view_set_canvas ( + view, + gimp_display_shell_get_infinite_canvas (shell) && + gimp_display_shell_get_show_canvas (shell), + -bounding_box.x, -bounding_box.y, + gimp_image_get_width (image), gimp_image_get_height (image)); } } diff -Nru gimp-2.10.8+zorin2/app/display/gimpnavigationeditor.h gimp-2.10.14+om/app/display/gimpnavigationeditor.h --- gimp-2.10.8+zorin2/app/display/gimpnavigationeditor.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpnavigationeditor.h 2019-10-26 18:49:18.000000000 +0000 @@ -40,23 +40,25 @@ struct _GimpNavigationEditor { - GimpEditor parent_instance; + GimpEditor parent_instance; - GimpContext *context; - GimpDisplayShell *shell; + GimpContext *context; + GimpDisplayShell *shell; - GtkWidget *view; - GtkWidget *zoom_label; - GtkAdjustment *zoom_adjustment; - - GtkWidget *zoom_out_button; - GtkWidget *zoom_in_button; - GtkWidget *zoom_100_button; - GtkWidget *zoom_fit_in_button; - GtkWidget *zoom_fill_button; - GtkWidget *shrink_wrap_button; + GimpImageViewable *image_viewable; - guint scale_timeout; + GtkWidget *view; + GtkWidget *zoom_label; + GtkAdjustment *zoom_adjustment; + + GtkWidget *zoom_out_button; + GtkWidget *zoom_in_button; + GtkWidget *zoom_100_button; + GtkWidget *zoom_fit_in_button; + GtkWidget *zoom_fill_button; + GtkWidget *shrink_wrap_button; + + guint scale_timeout; }; struct _GimpNavigationEditorClass diff -Nru gimp-2.10.8+zorin2/app/display/gimpstatusbar.c gimp-2.10.14+om/app/display/gimpstatusbar.c --- gimp-2.10.8+zorin2/app/display/gimpstatusbar.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimpstatusbar.c 2019-04-07 11:38:14.000000000 +0000 @@ -235,6 +235,9 @@ statusbar->unit_combo = gimp_unit_combo_box_new_with_model (store); g_object_unref (store); + /* see issue #2642 */ + gtk_combo_box_set_wrap_width (GTK_COMBO_BOX (statusbar->unit_combo), 1); + gtk_widget_set_can_focus (statusbar->unit_combo, FALSE); g_object_set (statusbar->unit_combo, "focus-on-click", FALSE, NULL); gtk_box_pack_start (GTK_BOX (hbox), statusbar->unit_combo, FALSE, FALSE, 0); diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolcompass.c gimp-2.10.14+om/app/display/gimptoolcompass.c --- gimp-2.10.8+zorin2/app/display/gimptoolcompass.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolcompass.c 2019-04-07 11:38:14.000000000 +0000 @@ -77,7 +77,8 @@ PROP_X3, PROP_Y3, PROP_PIXEL_ANGLE, - PROP_UNIT_ANGLE + PROP_UNIT_ANGLE, + PROP_EFFECTIVE_ORIENTATION }; enum @@ -98,6 +99,7 @@ gdouble display_angle; gdouble pixel_angle; gdouble unit_angle; + GimpCompassOrientation effective_orientation; CompassFunction function; gdouble mouse_x; @@ -274,6 +276,12 @@ g_param_spec_double ("unit-angle", NULL, NULL, -G_PI, G_PI, 0.0, GIMP_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_EFFECTIVE_ORIENTATION, + g_param_spec_enum ("effective-orientation", NULL, NULL, + GIMP_TYPE_COMPASS_ORIENTATION, + GIMP_COMPASS_ORIENTATION_AUTO, + GIMP_PARAM_READABLE)); } static void @@ -362,6 +370,9 @@ switch (property_id) { + case PROP_ORIENTATION: + private->orientation = g_value_get_enum (value); + break; case PROP_N_POINTS: private->n_points = g_value_get_int (value); break; @@ -383,9 +394,6 @@ case PROP_Y3: private->y[2] = g_value_get_int (value); break; - case PROP_ORIENTATION: - private->orientation = g_value_get_enum (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -404,6 +412,9 @@ switch (property_id) { + case PROP_ORIENTATION: + g_value_set_enum (value, private->orientation); + break; case PROP_N_POINTS: g_value_set_int (value, private->n_points); break; @@ -425,15 +436,15 @@ case PROP_Y3: g_value_set_int (value, private->y[2]); break; - case PROP_ORIENTATION: - g_value_set_enum (value, private->orientation); - break; case PROP_PIXEL_ANGLE: g_value_set_double (value, private->pixel_angle); break; case PROP_UNIT_ANGLE: g_value_set_double (value, private->unit_angle); break; + case PROP_EFFECTIVE_ORIENTATION: + g_value_set_enum (value, private->effective_orientation); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -1086,6 +1097,8 @@ if (private->n_points == 3) { + orientation = GIMP_COMPASS_ORIENTATION_AUTO; + private->radius2.x = private->x[2] - private->x[0]; private->radius2.y = private->y[2] - private->y[0]; } @@ -1144,30 +1157,43 @@ return; } - else if (orientation == GIMP_COMPASS_ORIENTATION_AUTO && - fabs (private->display_angle) > G_PI / 4.0 + EPSILON) + else if (orientation == GIMP_COMPASS_ORIENTATION_AUTO) { - gimp_tool_compass_update_angle (compass, - GIMP_COMPASS_ORIENTATION_VERTICAL, - FALSE); + if (fabs (private->display_angle) <= G_PI / 4.0 + EPSILON) + { + orientation = GIMP_COMPASS_ORIENTATION_HORIZONTAL; + } + else + { + gimp_tool_compass_update_angle (compass, + GIMP_COMPASS_ORIENTATION_VERTICAL, + FALSE); - return; + return; + } } } - if (pixel_angle != private->pixel_angle) + if (fabs (pixel_angle - private->pixel_angle) > EPSILON) { private->pixel_angle = pixel_angle; g_object_notify (G_OBJECT (compass), "pixel-angle"); } - if (unit_angle != private->unit_angle) + if (fabs (unit_angle - private->unit_angle) > EPSILON) { private->unit_angle = unit_angle; g_object_notify (G_OBJECT (compass), "unit-angle"); } + + if (orientation != private->effective_orientation) + { + private->effective_orientation = orientation; + + g_object_notify (G_OBJECT (compass), "effective-orientation"); + } } diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolgui.c gimp-2.10.14+om/app/display/gimptoolgui.c --- gimp-2.10.8+zorin2/app/display/gimptoolgui.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolgui.c 2019-04-07 11:38:14.000000000 +0000 @@ -84,28 +84,30 @@ #define GET_PRIVATE(gui) ((GimpToolGuiPrivate *) gimp_tool_gui_get_instance_private ((GimpToolGui *) (gui))) -static void gimp_tool_gui_dispose (GObject *object); -static void gimp_tool_gui_finalize (GObject *object); +static void gimp_tool_gui_dispose (GObject *object); +static void gimp_tool_gui_finalize (GObject *object); -static void gimp_tool_gui_create_dialog (GimpToolGui *gui, - GdkScreen *screen, - gint monitor); -static void gimp_tool_gui_update_buttons (GimpToolGui *gui); -static void gimp_tool_gui_update_shell (GimpToolGui *gui); -static void gimp_tool_gui_update_viewable (GimpToolGui *gui); - -static void gimp_tool_gui_dialog_response (GtkWidget *dialog, - gint response_id, - GimpToolGui *gui); -static void gimp_tool_gui_canvas_resized (GtkWidget *canvas, - GtkAllocation *allocation, - GimpToolGui *gui); - -static ResponseEntry * response_entry_new (gint response_id, - const gchar *button_text); -static void response_entry_free (ResponseEntry *entry); -static ResponseEntry * response_entry_find (GList *entries, - gint response_id); +static void gimp_tool_gui_create_dialog (GimpToolGui *gui, + GdkScreen *screen, + gint monitor); +static void gimp_tool_gui_add_dialog_button (GimpToolGui *gui, + ResponseEntry *entry); +static void gimp_tool_gui_update_buttons (GimpToolGui *gui); +static void gimp_tool_gui_update_shell (GimpToolGui *gui); +static void gimp_tool_gui_update_viewable (GimpToolGui *gui); + +static void gimp_tool_gui_dialog_response (GtkWidget *dialog, + gint response_id, + GimpToolGui *gui); +static void gimp_tool_gui_canvas_resized (GtkWidget *canvas, + GtkAllocation *allocation, + GimpToolGui *gui); + +static ResponseEntry * response_entry_new (gint response_id, + const gchar *button_text); +static void response_entry_free (ResponseEntry *entry); +static ResponseEntry * response_entry_find (GList *entries, + gint response_id); G_DEFINE_TYPE_WITH_PRIVATE (GimpToolGui, gimp_tool_gui, GIMP_TYPE_OBJECT) @@ -225,7 +227,6 @@ GimpToolGui *gui; GimpToolGuiPrivate *private; va_list args; - const gchar *button_text; g_return_val_if_fail (GIMP_IS_TOOL_INFO (tool_info), NULL); @@ -254,16 +255,7 @@ va_start (args, overlay); - for (button_text = va_arg (args, const gchar *); - button_text; - button_text = va_arg (args, const gchar *)) - { - gint response_id = va_arg (args, gint); - - private->response_entries = g_list_append (private->response_entries, - response_entry_new (response_id, - button_text)); - } + gimp_tool_gui_add_buttons_valist (gui, args); va_end (args); @@ -638,6 +630,45 @@ } void +gimp_tool_gui_add_buttons_valist (GimpToolGui *gui, + va_list args) +{ + const gchar *button_text; + gint response_id; + + g_return_if_fail (GIMP_IS_TOOL_GUI (gui)); + + while ((button_text = va_arg (args, const gchar *))) + { + response_id = va_arg (args, gint); + + gimp_tool_gui_add_button (gui, button_text, response_id); + } +} + +void +gimp_tool_gui_add_button (GimpToolGui *gui, + const gchar *button_text, + gint response_id) +{ + GimpToolGuiPrivate *private; + ResponseEntry *entry; + + g_return_if_fail (GIMP_IS_TOOL_GUI (gui)); + g_return_if_fail (button_text != NULL); + + private = GET_PRIVATE (gui); + + entry = response_entry_new (response_id, button_text); + + private->response_entries = g_list_append (private->response_entries, + entry); + + if (private->dialog) + gimp_tool_gui_add_dialog_button (gui, entry); +} + +void gimp_tool_gui_set_default_response (GimpToolGui *gui, gint response_id) { @@ -678,7 +709,8 @@ entry = response_entry_find (private->response_entries, response_id); - g_return_if_fail (entry != NULL); + if (! entry) + return; entry->sensitive = sensitive; @@ -747,14 +779,7 @@ { ResponseEntry *entry = list->data; - gimp_overlay_dialog_add_button (GIMP_OVERLAY_DIALOG (private->dialog), - entry->button_text, - entry->response_id); - - if (! entry->sensitive) - gimp_overlay_dialog_set_response_sensitive (GIMP_OVERLAY_DIALOG (private->dialog), - entry->response_id, - FALSE); + gimp_tool_gui_add_dialog_button (gui, entry); } if (private->default_response != -1) @@ -781,14 +806,7 @@ { ResponseEntry *entry = list->data; - gimp_dialog_add_button (GIMP_DIALOG (private->dialog), - entry->button_text, - entry->response_id); - - if (! entry->sensitive) - gtk_dialog_set_response_sensitive (GTK_DIALOG (private->dialog), - entry->response_id, - FALSE); + gimp_tool_gui_add_dialog_button (gui, entry); } if (private->default_response != -1) @@ -818,6 +836,38 @@ } static void +gimp_tool_gui_add_dialog_button (GimpToolGui *gui, + ResponseEntry *entry) +{ + GimpToolGuiPrivate *private = GET_PRIVATE (gui); + + if (private->overlay) + { + gimp_overlay_dialog_add_button (GIMP_OVERLAY_DIALOG (private->dialog), + entry->button_text, + entry->response_id); + + if (! entry->sensitive) + { + gimp_overlay_dialog_set_response_sensitive ( + GIMP_OVERLAY_DIALOG (private->dialog), + entry->response_id, FALSE); + } + } + else + { + gimp_dialog_add_button (GIMP_DIALOG (private->dialog), + entry->button_text, + entry->response_id); + + if (! entry->sensitive) + gtk_dialog_set_response_sensitive (GTK_DIALOG (private->dialog), + entry->response_id, + FALSE); + } +} + +static void gimp_tool_gui_update_buttons (GimpToolGui *gui) { GimpToolGuiPrivate *private = GET_PRIVATE (gui); diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolgui.h gimp-2.10.14+om/app/display/gimptoolgui.h --- gimp-2.10.8+zorin2/app/display/gimptoolgui.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolgui.h 2019-04-07 11:38:14.000000000 +0000 @@ -97,6 +97,12 @@ gboolean focus_on_map); gboolean gimp_tool_gui_get_focus_on_map (GimpToolGui *gui); + +void gimp_tool_gui_add_buttons_valist (GimpToolGui *gui, + va_list args); +void gimp_tool_gui_add_button (GimpToolGui *gui, + const gchar *button_text, + gint response_id); void gimp_tool_gui_set_default_response (GimpToolGui *gui, gint response_id); void gimp_tool_gui_set_response_sensitive (GimpToolGui *gui, diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolpath.c gimp-2.10.14+om/app/display/gimptoolpath.c --- gimp-2.10.8+zorin2/app/display/gimptoolpath.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolpath.c 2019-04-07 11:38:14.000000000 +0000 @@ -37,6 +37,8 @@ #include "widgets/gimpwidgets-utils.h" +#include "tools/gimptools-utils.h" + #include "gimpcanvashandle.h" #include "gimpcanvasitem-utils.h" #include "gimpcanvasline.h" @@ -492,12 +494,18 @@ gimp_tool_path_check_writable (GimpToolPath *path) { GimpToolPathPrivate *private = path->private; + GimpToolWidget *widget = GIMP_TOOL_WIDGET (path); + GimpDisplayShell *shell = gimp_tool_widget_get_shell (widget); if (gimp_item_is_content_locked (GIMP_ITEM (private->vectors)) || gimp_item_is_position_locked (GIMP_ITEM (private->vectors))) { - gimp_tool_widget_set_status (GIMP_TOOL_WIDGET (path), - _("The active path is locked.")); + gimp_tool_widget_message_literal (GIMP_TOOL_WIDGET (path), + _("The active path is locked.")); + + /* FIXME: this should really be done by the tool */ + gimp_tools_blink_lock_box (shell->display->gimp, + GIMP_ITEM (private->vectors)); private->function = VECTORS_FINISHED; diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolpolygon.c gimp-2.10.14+om/app/display/gimptoolpolygon.c --- gimp-2.10.8+zorin2/app/display/gimptoolpolygon.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolpolygon.c 2019-06-12 16:43:38.000000000 +0000 @@ -37,6 +37,7 @@ #include "display-types.h" #include "core/gimp-utils.h" +#include "core/gimpmarshal.h" #include "widgets/gimpwidgets-utils.h" @@ -57,6 +58,13 @@ #define NO_CLICK_TIME_AVAILABLE 0 +enum +{ + CHANGE_COMPLETE, + LAST_SIGNAL +}; + + struct _GimpToolPolygonPrivate { /* Index of grabbed segment index. */ @@ -101,9 +109,6 @@ /* Is the polygon closed? */ gboolean polygon_closed; - /* The selection operation active when the tool was started */ - GimpChannelOps operation_at_start; - /* Whether or not to constrain the angle for newly created polygonal * segments. */ @@ -188,6 +193,8 @@ GimpToolCursorType *tool_cursor, GimpCursorModifier *modifier); +static void gimp_tool_polygon_change_complete (GimpToolPolygon *polygon); + static gint gimp_tool_polygon_get_segment_index (GimpToolPolygon *polygon, const GimpCoords *coords); @@ -197,6 +204,8 @@ #define parent_class gimp_tool_polygon_parent_class +static guint polygon_signals[LAST_SIGNAL] = { 0, }; + static const GimpVector2 vector2_zero = { 0.0, 0.0 }; @@ -222,6 +231,15 @@ widget_class->motion_modifier = gimp_tool_polygon_motion_modifier; widget_class->hover_modifier = gimp_tool_polygon_hover_modifier; widget_class->get_cursor = gimp_tool_polygon_get_cursor; + + polygon_signals[CHANGE_COMPLETE] = + g_signal_new ("change-complete", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpToolPolygonClass, change_complete), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -1134,6 +1152,8 @@ gimp_tool_polygon_revert_to_saved_state (polygon); priv->polygon_closed = TRUE; + + gimp_tool_polygon_change_complete (polygon); } priv->last_click_time = time; @@ -1155,6 +1175,8 @@ { priv->polygon_closed = TRUE; } + + gimp_tool_polygon_change_complete (polygon); break; case GIMP_BUTTON_RELEASE_CANCEL: @@ -1304,12 +1326,16 @@ gimp_tool_polygon_key_press (GimpToolWidget *widget, GdkEventKey *kevent) { - GimpToolPolygon *polygon = GIMP_TOOL_POLYGON (widget); + GimpToolPolygon *polygon = GIMP_TOOL_POLYGON (widget); + GimpToolPolygonPrivate *priv = polygon->private; switch (kevent->keyval) { case GDK_KEY_BackSpace: gimp_tool_polygon_remove_last_segment (polygon); + + if (priv->n_segment_indices > 0) + gimp_tool_polygon_change_complete (polygon); return TRUE; default: @@ -1385,6 +1411,12 @@ return FALSE; } +static void +gimp_tool_polygon_change_complete (GimpToolPolygon *polygon) +{ + g_signal_emit (polygon, polygon_signals[CHANGE_COMPLETE], 0); +} + static gint gimp_tool_polygon_get_segment_index (GimpToolPolygon *polygon, const GimpCoords *coords) @@ -1435,15 +1467,29 @@ NULL); } +gboolean +gimp_tool_polygon_is_closed (GimpToolPolygon *polygon) +{ + GimpToolPolygonPrivate *private; + + g_return_val_if_fail (GIMP_IS_TOOL_POLYGON (polygon), FALSE); + + private = polygon->private; + + return private->polygon_closed; +} + void gimp_tool_polygon_get_points (GimpToolPolygon *polygon, const GimpVector2 **points, gint *n_points) { - GimpToolPolygonPrivate *private = polygon->private; + GimpToolPolygonPrivate *private; + + g_return_if_fail (GIMP_IS_TOOL_POLYGON (polygon)); - g_return_if_fail (points != NULL && n_points != NULL); + private = polygon->private; - *points = private->points; - *n_points = private->n_points; + if (points) *points = private->points; + if (n_points) *n_points = private->n_points; } diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolpolygon.h gimp-2.10.14+om/app/display/gimptoolpolygon.h --- gimp-2.10.8+zorin2/app/display/gimptoolpolygon.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolpolygon.h 2019-06-12 16:43:38.000000000 +0000 @@ -47,6 +47,9 @@ struct _GimpToolPolygonClass { GimpToolWidgetClass parent_class; + + /* signals */ + void (* change_complete) (GimpToolPolygon *polygon); }; @@ -54,6 +57,7 @@ GimpToolWidget * gimp_tool_polygon_new (GimpDisplayShell *shell); +gboolean gimp_tool_polygon_is_closed (GimpToolPolygon *polygon); void gimp_tool_polygon_get_points (GimpToolPolygon *polygon, const GimpVector2 **points, gint *n_points); diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolrectangle.c gimp-2.10.14+om/app/display/gimptoolrectangle.c --- gimp-2.10.8+zorin2/app/display/gimptoolrectangle.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolrectangle.c 2019-10-27 17:12:44.000000000 +0000 @@ -222,12 +222,12 @@ /* Whether to draw round corners */ gboolean round_corners; - gboolean corner_radius; + gdouble corner_radius; /* The title for the statusbar coords */ gchar *status_title; - /* For saving in case of cancelation. */ + /* For saving in case of cancellation. */ gdouble saved_x1; gdouble saved_y1; gdouble saved_x2; @@ -556,7 +556,7 @@ g_object_class_install_property (object_class, PROP_CORNER_RADIUS, g_param_spec_double ("corner-radius", NULL, NULL, - 0.0, 1000.0, 5.0, + 0.0, 10000.0, 10.0, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT)); @@ -819,11 +819,7 @@ GimpToolRectangle *rectangle = GIMP_TOOL_RECTANGLE (object); GimpToolRectanglePrivate *private = rectangle->private; - if (private->status_title) - { - g_free (private->status_title); - private->status_title = NULL; - } + g_clear_pointer (&private->status_title, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -2727,7 +2723,7 @@ * * Adjust the rectangle to the new position specified by passed * coordinate, taking fixed_center into account, which means it - * expands the rectagle around the center point. + * expands the rectangle around the center point. */ static void gimp_tool_rectangle_apply_coord (GimpToolRectangle *rectangle, diff -Nru gimp-2.10.8+zorin2/app/display/gimptooltransformgrid.c gimp-2.10.14+om/app/display/gimptooltransformgrid.c --- gimp-2.10.8+zorin2/app/display/gimptooltransformgrid.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptooltransformgrid.c 2019-04-07 11:38:14.000000000 +0000 @@ -801,6 +801,17 @@ pos[3].x, pos[3].y); } +static gboolean +transform_grid_is_convex (GimpToolTransformGrid *grid) +{ + GimpToolTransformGridPrivate *private = grid->private; + + return gimp_transform_polygon_is_convex (private->tx1, private->ty1, + private->tx2, private->ty2, + private->tx3, private->ty3, + private->tx4, private->ty4); +} + static inline gboolean vectorisnull (GimpVector2 v) { @@ -876,11 +887,11 @@ length = norm (a) * norm (b); - angle = acos (dotprod (a, b)/length); + angle = acos (SAFE_CLAMP (dotprod (a, b) / length, -1.0, +1.0)); angle2 = b.y; b.y = -b.x; b.x = angle2; - angle2 = acos (dotprod (a, b)/length); + angle2 = acos (SAFE_CLAMP (dotprod (a, b) / length, -1.0, +1.0)); return ((angle2 > G_PI / 2.0) ? angle : 2.0 * G_PI - angle); } @@ -1309,16 +1320,29 @@ newpos[3].y = oldpos[3].y = private->prev_ty4; /* put center point in this array too */ - oldpos[4].x = (oldpos[0].x + oldpos[1].x + oldpos[2].x + oldpos[3].x) / 4.; - oldpos[4].y = (oldpos[0].y + oldpos[1].y + oldpos[2].y + oldpos[3].y) / 4.; + oldpos[4].x = private->prev_tcx; + oldpos[4].y = private->prev_tcy; d = vectorsubtract (cur, mouse); newpivot_x = &private->tpx; newpivot_y = &private->tpy; - pivot.x = private->prev_tpx; - pivot.y = private->prev_tpy; + if (private->use_pivot_handle) + { + pivot.x = private->prev_tpx; + pivot.y = private->prev_tpy; + } + else + { + /* when the transform grid doesn't use a pivot handle, use the center + * point as the pivot instead. + */ + pivot.x = private->prev_tcx; + pivot.y = private->prev_tcy; + + fixedpivot = TRUE; + } /* move */ if (handle == GIMP_TRANSFORM_HANDLE_CENTER) @@ -1726,12 +1750,6 @@ } } - for (i = 0; i < 4; i++) - { - *x[i] = newpos[i].x; - *y[i] = newpos[i].y; - } - /* this will have been set to TRUE if an operation used the pivot in * addition to being a user option */ @@ -1744,6 +1762,22 @@ pivot = vectoradd (pivot, delta); } + /* make sure the new coordinates are valid */ + for (i = 0; i < 4; i++) + { + if (! isfinite (newpos[i].x) || ! isfinite (newpos[i].y)) + return; + } + + if (! isfinite (pivot.x) || ! isfinite (pivot.y)) + return; + + for (i = 0; i < 4; i++) + { + *x[i] = newpos[i].x; + *y[i] = newpos[i].y; + } + /* set unconditionally: if options get toggled during operation, we * have to move pivot back */ @@ -2307,14 +2341,24 @@ private->tpx = private->pivot_x; private->tpy = private->pivot_y; - private->tcx = (private->tx1 + - private->tx2 + - private->tx3 + - private->tx4) / 4.0; - private->tcy = (private->ty1 + - private->ty2 + - private->ty3 + - private->ty4) / 4.0; + if (transform_grid_is_convex (grid)) + { + gimp_matrix3_transform_point (&private->transform, + (private->x1 + private->x2) / 2.0, + (private->y1 + private->y2) / 2.0, + &private->tcx, &private->tcy); + } + else + { + private->tcx = (private->tx1 + + private->tx2 + + private->tx3 + + private->tx4) / 4.0; + private->tcy = (private->ty1 + + private->ty2 + + private->ty3 + + private->ty4) / 4.0; + } } static void diff -Nru gimp-2.10.8+zorin2/app/display/gimptooltransformgrid.h gimp-2.10.14+om/app/display/gimptooltransformgrid.h --- gimp-2.10.8+zorin2/app/display/gimptooltransformgrid.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptooltransformgrid.h 2019-04-07 11:38:14.000000000 +0000 @@ -22,9 +22,14 @@ #define __GIMP_TOOL_TRANSFORM_GRID_H__ +#include "gimpcanvashandle.h" #include "gimptoolwidget.h" +#define GIMP_TOOL_TRANSFORM_GRID_MAX_HANDLE_SIZE \ + (1.5 * GIMP_CANVAS_HANDLE_SIZE_LARGE) + + typedef enum { GIMP_TRANSFORM_HANDLE_NONE, diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolwidget.c gimp-2.10.14+om/app/display/gimptoolwidget.c --- gimp-2.10.8+zorin2/app/display/gimptoolwidget.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolwidget.c 2019-04-07 11:38:14.000000000 +0000 @@ -20,6 +20,8 @@ #include "config.h" +#include + #include #include #include @@ -56,6 +58,7 @@ SNAP_OFFSETS, STATUS, STATUS_COORDS, + MESSAGE, FOCUS_CHANGED, LAST_SIGNAL }; @@ -71,6 +74,7 @@ gint snap_width; gint snap_height; + gboolean visible; gboolean focus; }; @@ -173,6 +177,16 @@ G_TYPE_DOUBLE, G_TYPE_STRING); + widget_signals[MESSAGE] = + g_signal_new ("message", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpToolWidgetClass, message), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + widget_signals[FOCUS_CHANGED] = g_signal_new ("focus-changed", G_TYPE_FROM_CLASS (klass), @@ -200,6 +214,8 @@ gimp_tool_widget_init (GimpToolWidget *widget) { widget->private = gimp_tool_widget_get_instance_private (widget); + + widget->private->visible = TRUE; } static void @@ -213,6 +229,8 @@ gimp_assert (GIMP_IS_DISPLAY_SHELL (private->shell)); private->item = gimp_canvas_group_new (private->shell); + + gimp_canvas_item_set_visible (private->item, private->visible); } static void @@ -339,6 +357,32 @@ } void +gimp_tool_widget_set_visible (GimpToolWidget *widget, + gboolean visible) +{ + g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); + + if (visible != widget->private->visible) + { + widget->private->visible = visible; + + if (widget->private->item) + gimp_canvas_item_set_visible (widget->private->item, visible); + + if (! visible) + gimp_tool_widget_set_status (widget, NULL); + } +} + +gboolean +gimp_tool_widget_get_visible (GimpToolWidget *widget) +{ + g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE); + + return widget->private->visible; +} + +void gimp_tool_widget_set_focus (GimpToolWidget *widget, gboolean focus) { @@ -450,6 +494,39 @@ } void +gimp_tool_widget_message (GimpToolWidget *widget, + const gchar *format, + ...) +{ + va_list args; + gchar *message; + + g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); + g_return_if_fail (format != NULL); + + va_start (args, format); + + message = g_strdup_vprintf (format, args); + + va_end (args); + + gimp_tool_widget_message_literal (widget, message); + + g_free (message); +} + +void +gimp_tool_widget_message_literal (GimpToolWidget *widget, + const gchar *message) +{ + g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); + g_return_if_fail (message != NULL); + + g_signal_emit (widget, widget_signals[MESSAGE], 0, + message); +} + +void gimp_tool_widget_add_item (GimpToolWidget *widget, GimpCanvasItem *item) { @@ -772,10 +849,14 @@ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), 0); g_return_val_if_fail (coords != NULL, 0); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press) - return GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press (widget, - coords, time, state, - press_type); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press) + { + return GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_press (widget, + coords, time, + state, + press_type); + } return 0; } @@ -790,10 +871,13 @@ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); g_return_if_fail (coords != NULL); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release (widget, - coords, time, state, - release_type); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->button_release (widget, + coords, time, state, + release_type); + } } void @@ -805,9 +889,12 @@ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); g_return_if_fail (coords != NULL); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion (widget, - coords, time, state); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion (widget, + coords, time, state); + } } GimpHit @@ -819,9 +906,13 @@ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), GIMP_HIT_NONE); g_return_val_if_fail (coords != NULL, GIMP_HIT_NONE); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit) - return GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit (widget, - coords, state, proximity); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit) + { + return GIMP_TOOL_WIDGET_GET_CLASS (widget)->hit (widget, + coords, state, + proximity); + } return GIMP_HIT_NONE; } @@ -835,9 +926,12 @@ g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); g_return_if_fail (coords != NULL); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover (widget, - coords, state, proximity); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover (widget, + coords, state, proximity); + } } void @@ -845,8 +939,11 @@ { g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify (widget); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->leave_notify (widget); + } } gboolean @@ -856,8 +953,11 @@ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE); g_return_val_if_fail (kevent != NULL, FALSE); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press) - return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press (widget, kevent); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press) + { + return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_press (widget, kevent); + } return FALSE; } @@ -869,8 +969,11 @@ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE); g_return_val_if_fail (kevent != NULL, FALSE); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release) - return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release (widget, kevent); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release) + { + return GIMP_TOOL_WIDGET_GET_CLASS (widget)->key_release (widget, kevent); + } return FALSE; } @@ -883,9 +986,12 @@ { g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier (widget, - key, press, state); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->motion_modifier (widget, + key, press, state); + } } void @@ -896,9 +1002,12 @@ { g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget)); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier) - GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier (widget, - key, press, state); + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier) + { + GIMP_TOOL_WIDGET_GET_CLASS (widget)->hover_modifier (widget, + key, press, state); + } } gboolean @@ -913,7 +1022,8 @@ g_return_val_if_fail (GIMP_IS_TOOL_WIDGET (widget), FALSE); g_return_val_if_fail (coords != NULL, FALSE); - if (GIMP_TOOL_WIDGET_GET_CLASS (widget)->get_cursor) + if (widget->private->visible && + GIMP_TOOL_WIDGET_GET_CLASS (widget)->get_cursor) { GimpCursorType my_cursor; GimpToolCursorType my_tool_cursor; diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolwidgetgroup.c gimp-2.10.14+om/app/display/gimptoolwidgetgroup.c --- gimp-2.10.8+zorin2/app/display/gimptoolwidgetgroup.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolwidgetgroup.c 2019-04-07 11:38:14.000000000 +0000 @@ -123,6 +123,9 @@ gdouble y, const gchar *help, GimpToolWidgetGroup *group); +static void gimp_tool_widget_group_child_message (GimpToolWidget *child, + const gchar *message, + GimpToolWidgetGroup *group); static void gimp_tool_widget_group_child_focus_changed (GimpToolWidget *child, GimpToolWidgetGroup *group); @@ -201,6 +204,9 @@ gimp_container_add_handler (priv->children, "status-coords", G_CALLBACK (gimp_tool_widget_group_child_status_coords), group); + gimp_container_add_handler (priv->children, "message", + G_CALLBACK (gimp_tool_widget_group_child_message), + group); gimp_container_add_handler (priv->children, "focus-changed", G_CALLBACK (gimp_tool_widget_group_child_focus_changed), group); @@ -597,6 +603,18 @@ } static void +gimp_tool_widget_group_child_message (GimpToolWidget *child, + const gchar *message, + GimpToolWidgetGroup *group) +{ + GimpToolWidgetGroupPrivate *priv = group->priv; + GimpToolWidget *widget = GIMP_TOOL_WIDGET (group); + + if (priv->focus_widget == child) + gimp_tool_widget_message_literal (widget, message); +} + +static void gimp_tool_widget_group_child_focus_changed (GimpToolWidget *child, GimpToolWidgetGroup *group) { diff -Nru gimp-2.10.8+zorin2/app/display/gimptoolwidget.h gimp-2.10.14+om/app/display/gimptoolwidget.h --- gimp-2.10.8+zorin2/app/display/gimptoolwidget.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/display/gimptoolwidget.h 2019-04-07 11:38:14.000000000 +0000 @@ -69,6 +69,8 @@ const gchar *separator, gdouble y, const gchar *help); + void (* message) (GimpToolWidget *widget, + const gchar *message); void (* focus_changed) (GimpToolWidget *widget); /* virtual functions */ @@ -125,6 +127,10 @@ GimpDisplayShell * gimp_tool_widget_get_shell (GimpToolWidget *widget); GimpCanvasItem * gimp_tool_widget_get_item (GimpToolWidget *widget); +void gimp_tool_widget_set_visible (GimpToolWidget *widget, + gboolean visible); +gboolean gimp_tool_widget_get_visible (GimpToolWidget *widget); + void gimp_tool_widget_set_focus (GimpToolWidget *widget, gboolean focus); gboolean gimp_tool_widget_get_focus (GimpToolWidget *widget); @@ -156,6 +162,12 @@ gdouble y, const gchar *help); +void gimp_tool_widget_message (GimpToolWidget *widget, + const gchar *format, + ...) G_GNUC_PRINTF (2, 3); +void gimp_tool_widget_message_literal (GimpToolWidget *widget, + const gchar *message); + /* for subclasses, to add and manage their items */ void gimp_tool_widget_add_item (GimpToolWidget *widget, diff -Nru gimp-2.10.8+zorin2/app/display/Makefile.am gimp-2.10.14+om/app/display/Makefile.am --- gimp-2.10.8+zorin2/app/display/Makefile.am 2018-07-04 11:00:26.000000000 +0000 +++ gimp-2.10.14+om/app/display/Makefile.am 2019-10-26 18:49:18.000000000 +0000 @@ -40,6 +40,8 @@ gimpcanvasboundary.h \ gimpcanvasbufferpreview.c \ gimpcanvasbufferpreview.h \ + gimpcanvascanvasboundary.c \ + gimpcanvascanvasboundary.h \ gimpcanvascorner.c \ gimpcanvascorner.h \ gimpcanvascursor.c \ diff -Nru gimp-2.10.8+zorin2/app/display/Makefile.in gimp-2.10.14+om/app/display/Makefile.in --- gimp-2.10.8+zorin2/app/display/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/display/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -124,7 +123,8 @@ am__objects_1 = display-enums.$(OBJEXT) am__objects_2 = gimpcanvas.$(OBJEXT) gimpcanvas-style.$(OBJEXT) \ gimpcanvasarc.$(OBJEXT) gimpcanvasboundary.$(OBJEXT) \ - gimpcanvasbufferpreview.$(OBJEXT) gimpcanvascorner.$(OBJEXT) \ + gimpcanvasbufferpreview.$(OBJEXT) \ + gimpcanvascanvasboundary.$(OBJEXT) gimpcanvascorner.$(OBJEXT) \ gimpcanvascursor.$(OBJEXT) gimpcanvasgrid.$(OBJEXT) \ gimpcanvasgroup.$(OBJEXT) gimpcanvasguide.$(OBJEXT) \ gimpcanvashandle.$(OBJEXT) gimpcanvasitem.$(OBJEXT) \ @@ -202,6 +202,7 @@ ./$(DEPDIR)/gimpcanvas-style.Po ./$(DEPDIR)/gimpcanvas.Po \ ./$(DEPDIR)/gimpcanvasarc.Po ./$(DEPDIR)/gimpcanvasboundary.Po \ ./$(DEPDIR)/gimpcanvasbufferpreview.Po \ + ./$(DEPDIR)/gimpcanvascanvasboundary.Po \ ./$(DEPDIR)/gimpcanvascorner.Po \ ./$(DEPDIR)/gimpcanvascursor.Po ./$(DEPDIR)/gimpcanvasgrid.Po \ ./$(DEPDIR)/gimpcanvasgroup.Po ./$(DEPDIR)/gimpcanvasguide.Po \ @@ -345,8 +346,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -476,7 +475,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -615,8 +613,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -775,6 +771,8 @@ gimpcanvasboundary.h \ gimpcanvasbufferpreview.c \ gimpcanvasbufferpreview.h \ + gimpcanvascanvasboundary.c \ + gimpcanvascanvasboundary.h \ gimpcanvascorner.c \ gimpcanvascorner.h \ gimpcanvascursor.c \ @@ -1002,6 +1000,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvasarc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvasboundary.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvasbufferpreview.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvascanvasboundary.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvascorner.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvascursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcanvasgrid.Po@am__quote@ # am--include-marker @@ -1248,6 +1247,7 @@ -rm -f ./$(DEPDIR)/gimpcanvasarc.Po -rm -f ./$(DEPDIR)/gimpcanvasboundary.Po -rm -f ./$(DEPDIR)/gimpcanvasbufferpreview.Po + -rm -f ./$(DEPDIR)/gimpcanvascanvasboundary.Po -rm -f ./$(DEPDIR)/gimpcanvascorner.Po -rm -f ./$(DEPDIR)/gimpcanvascursor.Po -rm -f ./$(DEPDIR)/gimpcanvasgrid.Po @@ -1379,6 +1379,7 @@ -rm -f ./$(DEPDIR)/gimpcanvasarc.Po -rm -f ./$(DEPDIR)/gimpcanvasboundary.Po -rm -f ./$(DEPDIR)/gimpcanvasbufferpreview.Po + -rm -f ./$(DEPDIR)/gimpcanvascanvasboundary.Po -rm -f ./$(DEPDIR)/gimpcanvascorner.Po -rm -f ./$(DEPDIR)/gimpcanvascursor.Po -rm -f ./$(DEPDIR)/gimpcanvasgrid.Po diff -Nru gimp-2.10.8+zorin2/app/file/file-open.c gimp-2.10.14+om/app/file/file-open.c --- gimp-2.10.8+zorin2/app/file/file-open.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/file/file-open.c 2019-10-26 18:49:18.000000000 +0000 @@ -84,6 +84,7 @@ GFile *local_file = NULL; gchar *path = NULL; gchar *entered_uri = NULL; + gboolean mounted = TRUE; GError *my_error = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); @@ -150,18 +151,27 @@ ! file_remote_mount_file (gimp, file, progress, &my_error)) { if (my_error) - g_propagate_error (error, my_error); + { + g_printerr ("%s: mounting remote volume failed, trying to download" + "the file: %s\n", + G_STRFUNC, my_error->message); + g_clear_error (&my_error); + + mounted = FALSE; + } else - *status = GIMP_PDB_CANCEL; + { + *status = GIMP_PDB_CANCEL; - return NULL; + return NULL; + } } - if (! file_proc || ! file_proc->handles_uri) + if (! file_proc || ! file_proc->handles_uri || ! mounted) { - path = g_file_get_path (file); + gchar *my_path = g_file_get_path (file); - if (! path) + if (! my_path) { local_file = file_remote_download_image (gimp, file, progress, &my_error); @@ -192,12 +202,22 @@ return NULL; } - path = g_file_get_path (local_file); + if (file_proc->handles_uri) + path = g_file_get_uri (local_file); + else + path = g_file_get_path (local_file); } + + g_free (my_path); } if (! path) - path = g_file_get_uri (file); + { + if (file_proc->handles_uri) + path = g_file_get_uri (file); + else + path = g_file_get_path (file); + } entered_uri = g_file_get_uri (entered_file); @@ -265,7 +285,7 @@ { if (error && ! *error) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, - _("%s plug-In could not open image"), + _("%s plug-in could not open image"), gimp_procedure_get_label (GIMP_PROCEDURE (file_proc))); } @@ -636,7 +656,8 @@ layer = gimp_image_merge_visible_layers (new_image, context, GIMP_CLIP_TO_IMAGE, - FALSE, FALSE); + FALSE, FALSE, + NULL); layers = g_list_prepend (NULL, layer); } @@ -752,9 +773,7 @@ * layers, this is needed in case something triggers projection or * image preview creation before all layers are loaded, see bug #767663. */ - gimp_image_invalidate (image, 0, 0, - gimp_image_get_width (image), - gimp_image_get_height (image)); + gimp_image_invalidate_all (image); /* Make sure all image states are up-to-date */ gimp_image_flush (image); diff -Nru gimp-2.10.8+zorin2/app/file/file-remote.c gimp-2.10.14+om/app/file/file-remote.c --- gimp-2.10.8+zorin2/app/file/file-remote.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/file/file-remote.c 2019-10-26 19:44:13.000000000 +0000 @@ -61,7 +61,7 @@ GimpProgress *progress; GCancellable *cancellable; gboolean cancel; - GTimeVal last_time; + gint64 last_time; } RemoteProgress; @@ -333,14 +333,12 @@ gpointer user_data) { RemoteProgress *progress = user_data; - GTimeVal now; + gint64 now; /* update the progress only up to 10 times a second */ - g_get_current_time (&now); + now = g_get_monotonic_time (); - if (progress->last_time.tv_sec && - ((now.tv_sec - progress->last_time.tv_sec) * 1000 + - (now.tv_usec - progress->last_time.tv_usec) / 1000) < 100) + if ((now - progress->last_time) / 1000 < 100) return; progress->last_time = now; diff -Nru gimp-2.10.8+zorin2/app/file/file-save.c gimp-2.10.14+om/app/file/file-save.c --- gimp-2.10.8+zorin2/app/file/file-save.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/file/file-save.c 2019-10-26 18:49:18.000000000 +0000 @@ -69,6 +69,7 @@ GFile *local_file = NULL; gchar *path = NULL; gchar *uri = NULL; + gboolean mounted = TRUE; gint32 image_ID; gint32 drawable_ID; GError *my_error = NULL; @@ -144,18 +145,27 @@ ! file_remote_mount_file (gimp, file, progress, &my_error)) { if (my_error) - g_propagate_error (error, my_error); + { + g_printerr ("%s: mounting remote volume failed, trying to upload" + "the file: %s\n", + G_STRFUNC, my_error->message); + g_clear_error (&my_error); + + mounted = FALSE; + } else - status = GIMP_PDB_CANCEL; + { + status = GIMP_PDB_CANCEL; - goto out; + goto out; + } } - if (! file_proc->handles_uri) + if (! file_proc->handles_uri || ! mounted) { - path = g_file_get_path (file); + gchar *my_path = g_file_get_path (file); - if (! path) + if (! my_path) { local_file = file_remote_upload_image_prepare (gimp, file, progress, &my_error); @@ -170,12 +180,22 @@ goto out; } - path = g_file_get_path (local_file); + if (file_proc->handles_uri) + path = g_file_get_uri (local_file); + else + path = g_file_get_path (local_file); } + + g_free (my_path); } if (! path) - path = g_file_get_uri (file); + { + if (file_proc->handles_uri) + path = g_file_get_uri (file); + else + path = g_file_get_path (file); + } uri = g_file_get_uri (file); diff -Nru gimp-2.10.8+zorin2/app/file/file-utils.c gimp-2.10.14+om/app/file/file-utils.c --- gimp-2.10.8+zorin2/app/file/file-utils.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/file/file-utils.c 2019-10-26 18:49:18.000000000 +0000 @@ -103,6 +103,18 @@ file = g_file_new_for_uri (filename); + if (! file) + { + /* Despite the docs says it never fails, it actually can on Windows. + * See issue #3093 (and glib#1819). + */ + g_set_error_literal (error, + G_CONVERT_ERROR, + G_CONVERT_ERROR_ILLEGAL_SEQUENCE, + _("Invalid character sequence in URI")); + return NULL; + } + /* check for prefixes like http or ftp */ if (gimp_plug_in_manager_file_procedure_find_by_prefix (gimp->plug_in_manager, GIMP_FILE_PROCEDURE_GROUP_OPEN, diff -Nru gimp-2.10.8+zorin2/app/file/Makefile.in gimp-2.10.14+om/app/file/Makefile.in --- gimp-2.10.8+zorin2/app/file/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/file/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -215,8 +214,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -346,7 +343,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -485,8 +481,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data.c gimp-2.10.14+om/app/file-data/file-data.c --- gimp-2.10.8+zorin2/app/file-data/file-data.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data.c 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,503 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" + +#include "core/core-types.h" + +#include "core/gimp.h" +#include "core/gimpparamspecs.h" + +#include "plug-in/gimppluginmanager.h" +#include "plug-in/gimppluginprocedure.h" + +#include "file-data.h" +#include "file-data-gbr.h" +#include "file-data-gih.h" +#include "file-data-pat.h" + +#include "gimp-intl.h" + + +void +file_data_init (Gimp *gimp) +{ + GimpPlugInProcedure *proc; + GFile *file; + GimpProcedure *procedure; + + g_return_if_fail (GIMP_IS_GIMP (gimp)); + + /* file-gbr-load */ + file = g_file_new_for_path ("file-gbr-load"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_gbr_load_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP brush")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-brush", + strlen ("gimp-brush") + 1); + gimp_plug_in_procedure_set_image_types (proc, NULL); + gimp_plug_in_procedure_set_file_proc (proc, "gbr, gbp", "", + "20, string, GIMP"); + gimp_plug_in_procedure_set_mime_types (proc, "image/gimp-x-gbr"); + gimp_plug_in_procedure_set_handles_uri (proc); + + gimp_object_set_static_name (GIMP_OBJECT (procedure), "file-gbr-load"); + gimp_procedure_set_static_strings (procedure, + "file-gbr-load", + "Loads GIMP brushes", + "Loads GIMP brushes (1 or 4 bpp " + "and old .gpb format)", + "Tim Newsome, Jens Lautenbacher, " + "Sven Neumann, Michael Natterer", + "Tim Newsome, Jens Lautenbacher, " + "Sven Neumann, Michael Natterer", + "1995-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + + gimp_procedure_add_return_value (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Output image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); + + /* file-gbr-save-internal */ + file = g_file_new_for_path ("file-gbr-save-internal"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_gbr_save_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP brush")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-brush", + strlen ("gimp-brush") + 1); + +#if 0 + /* do not register as file procedure */ + gimp_plug_in_procedure_set_image_types (proc, "RGB*, GRAY*, INDEXED*"); + gimp_plug_in_procedure_set_file_proc (proc, "gbr", "", NULL); + gimp_plug_in_procedure_set_mime_types (proc, "image/x-gimp-gbr"); + gimp_plug_in_procedure_set_handles_uri (proc); +#endif + + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "file-gbr-save-internal"); + gimp_procedure_set_static_strings (procedure, + "file-gbr-save-internal", + "Exports Gimp brush file (.GBR)", + "Exports Gimp brush file (.GBR)", + "Tim Newsome, Michael Natterer", + "Tim Newsome, Michael Natterer", + "1995-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "Drawable", + "Active drawable " + "of input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("spacing", + "spacing", + "Spacing of the brush", + 1, 1000, 10, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("name", + "name", + "The name of the " + "brush", + FALSE, FALSE, TRUE, + "GIMP Brush", + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); + + /* file-gih-load */ + file = g_file_new_for_path ("file-gih-load"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_gih_load_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP brush (animated)")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-brush", + strlen ("gimp-brush") + 1); + gimp_plug_in_procedure_set_image_types (proc, NULL); + gimp_plug_in_procedure_set_file_proc (proc, "gih", "", ""); + gimp_plug_in_procedure_set_mime_types (proc, "image/gimp-x-gih"); + gimp_plug_in_procedure_set_handles_uri (proc); + + gimp_object_set_static_name (GIMP_OBJECT (procedure), "file-gih-load"); + gimp_procedure_set_static_strings (procedure, + "file-gih-load", + "Loads GIMP animated brushes", + "This procedure loads a GIMP brush " + "pipe as an image.", + "Tor Lillqvist, Michael Natterer", + "Tor Lillqvist, Michael Natterer", + "1999-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + + gimp_procedure_add_return_value (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Output image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); + + /* file-gih-save-internal */ + file = g_file_new_for_path ("file-gih-save-internal"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_gih_save_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP brush (animated)")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-brush", + strlen ("gimp-brush") + 1); + +#if 0 + /* do not register as file procedure */ + gimp_plug_in_procedure_set_image_types (proc, "RGB*, GRAY*, INDEXED*"); + gimp_plug_in_procedure_set_file_proc (proc, "gih", "", NULL); + gimp_plug_in_procedure_set_mime_types (proc, "image/x-gimp-gih"); + gimp_plug_in_procedure_set_handles_uri (proc); +#endif + + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "file-gih-save-internal"); + gimp_procedure_set_static_strings (procedure, + "file-gih-save-internal", + "Exports Gimp animated brush file (.gih)", + "Exports Gimp animated brush file (.gih)", + "Tor Lillqvist, Michael Natterer", + "Tor Lillqvist, Michael Natterer", + "1999-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "Drawable", + "Active drawable " + "of input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("spacing", + "spacing", + "Spacing of the brush", + 1, 1000, 10, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("name", + "name", + "The name of the " + "brush", + FALSE, FALSE, TRUE, + "GIMP Brush", + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("params", + "params", + "The pipe's parameters", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); + + /* file-pat-load */ + file = g_file_new_for_path ("file-pat-load"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_pat_load_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP pattern")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-pattern", + strlen ("gimp-pattern") + 1); + gimp_plug_in_procedure_set_image_types (proc, NULL); + gimp_plug_in_procedure_set_file_proc (proc, "pat", "", + "20,string,GPAT"); + gimp_plug_in_procedure_set_mime_types (proc, "image/gimp-x-pat"); + gimp_plug_in_procedure_set_handles_uri (proc); + + gimp_object_set_static_name (GIMP_OBJECT (procedure), "file-pat-load"); + gimp_procedure_set_static_strings (procedure, + "file-pat-load", + "Loads GIMP patterns", + "Loads GIMP patterns", + "Tim Newsome, Michael Natterer", + "Tim Newsome, Michael Natterer", + "1997-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to load", + TRUE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Output image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); + + /* file-pat-save-internal */ + file = g_file_new_for_path ("file-pat-save-internal"); + procedure = gimp_plug_in_procedure_new (GIMP_PLUGIN, file); + g_object_unref (file); + + procedure->proc_type = GIMP_INTERNAL; + procedure->marshal_func = file_pat_save_invoker; + + proc = GIMP_PLUG_IN_PROCEDURE (procedure); + proc->menu_label = g_strdup (N_("GIMP pattern")); + gimp_plug_in_procedure_set_icon (proc, GIMP_ICON_TYPE_ICON_NAME, + (const guint8 *) "gimp-pattern", + strlen ("gimp-pattern") + 1); + +#if 0 + /* do not register as file procedure */ + gimp_plug_in_procedure_set_image_types (proc, "RGB*, GRAY*, INDEXED*"); + gimp_plug_in_procedure_set_file_proc (proc, "pat", "", NULL); + gimp_plug_in_procedure_set_mime_types (proc, "image/x-gimp-pat"); + gimp_plug_in_procedure_set_handles_uri (proc); +#endif + + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "file-pat-save-internal"); + gimp_procedure_set_static_strings (procedure, + "file-pat-save-internal", + "Exports Gimp pattern file (.PAT)", + "Exports Gimp pattern file (.PAT)", + "Tim Newsome, Michael Natterer", + "Tim Newsome, Michael Natterer", + "1995-2019", + NULL); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_int32 ("dummy-param", + "Dummy Param", + "Dummy parameter", + G_MININT32, G_MAXINT32, 0, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_image_id ("image", + "Image", + "Input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_drawable_id ("drawable", + "Drawable", + "Active drawable " + "of input image", + gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("uri", + "URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("raw-uri", + "Raw URI", + "The URI of the file " + "to export", + FALSE, FALSE, TRUE, + NULL, + GIMP_PARAM_READWRITE)); + + gimp_procedure_add_argument (procedure, + gimp_param_spec_string ("name", + "name", + "The name of the " + "pattern", + FALSE, FALSE, TRUE, + "GIMP Pattern", + GIMP_PARAM_READWRITE)); + + gimp_plug_in_manager_add_procedure (gimp->plug_in_manager, proc); + g_object_unref (procedure); +} + +void +file_data_exit (Gimp *gimp) +{ + g_return_if_fail (GIMP_IS_GIMP (gimp)); +} diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-gbr.c gimp-2.10.14+om/app/file-data/file-data-gbr.c --- gimp-2.10.8+zorin2/app/file-data/file-data-gbr.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-gbr.c 2019-06-12 16:43:38.000000000 +0000 @@ -0,0 +1,417 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpcolor/gimpcolor.h" + +#include "core/core-types.h" + +#include "core/gimp.h" +#include "core/gimpbrush.h" +#include "core/gimpbrush-load.h" +#include "core/gimpbrush-private.h" +#include "core/gimpdrawable.h" +#include "core/gimpimage.h" +#include "core/gimplayer-new.h" +#include "core/gimpimage-resize.h" +#include "core/gimpparamspecs.h" +#include "core/gimptempbuf.h" + +#include "pdb/gimpprocedure.h" + +#include "file-data-gbr.h" + +#include "gimp-intl.h" + + +/* local function prototypes */ + +static GimpImage * file_gbr_brush_to_image (Gimp *gimp, + GimpBrush *brush); +static GimpBrush * file_gbr_image_to_brush (GimpImage *image, + GimpDrawable *drawable, + const gchar *name, + gdouble spacing); + + +/* public functions */ + +GimpValueArray * +file_gbr_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image = NULL; + const gchar *uri; + GFile *file; + GInputStream *input; + GError *my_error = NULL; + + gimp_set_busy (gimp); + + uri = g_value_get_string (gimp_value_array_index (args, 1)); + file = g_file_new_for_uri (uri); + + input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); + + if (input) + { + GimpBrush *brush = gimp_brush_load_brush (context, file, input, error); + + if (brush) + { + image = file_gbr_brush_to_image (gimp, brush); + g_object_unref (brush); + } + + g_object_unref (input); + } + else + { + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for reading: "), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, image != NULL, + error ? *error : NULL); + + if (image) + gimp_value_set_image (gimp_value_array_index (return_vals, 1), image); + + gimp_unset_busy (gimp); + + return return_vals; +} + +GimpValueArray * +file_gbr_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image; + GimpDrawable *drawable; + GimpBrush *brush; + const gchar *uri; + const gchar *name; + GFile *file; + gint spacing; + gboolean success; + + gimp_set_busy (gimp); + + image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp); + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + uri = g_value_get_string (gimp_value_array_index (args, 3)); + spacing = g_value_get_int (gimp_value_array_index (args, 5)); + name = g_value_get_string (gimp_value_array_index (args, 6)); + + file = g_file_new_for_uri (uri); + + brush = file_gbr_image_to_brush (image, drawable, name, spacing); + + gimp_data_set_file (GIMP_DATA (brush), file, TRUE, TRUE); + + success = gimp_data_save (GIMP_DATA (brush), error); + + g_object_unref (brush); + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + gimp_unset_busy (gimp); + + return return_vals; +} + +GimpLayer * +file_gbr_brush_to_layer (GimpImage *image, + GimpBrush *brush) +{ + GimpLayer *layer; + const Babl *format; + gboolean alpha; + gint width; + gint height; + gint image_width; + gint image_height; + GimpTempBuf *mask; + GimpTempBuf *pixmap; + GeglBuffer *buffer; + + g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); + g_return_val_if_fail (GIMP_IS_BRUSH (brush), NULL); + + mask = gimp_brush_get_mask (brush); + pixmap = gimp_brush_get_pixmap (brush); + + if (pixmap) + alpha = TRUE; + else + alpha = FALSE; + + width = gimp_temp_buf_get_width (mask); + height = gimp_temp_buf_get_height (mask); + + image_width = gimp_image_get_width (image); + image_height = gimp_image_get_height (image); + + if (width > image_width || height > image_height) + { + gint new_width = MAX (image_width, width); + gint new_height = MAX (image_height, height); + + gimp_image_resize (image, gimp_get_user_context (image->gimp), + new_width, new_height, + (new_width - image_width) / 2, + (new_height - image_height) / 2, + NULL); + + image_width = new_width; + image_height = new_height; + } + + format = gimp_image_get_layer_format (image, alpha); + + layer = gimp_layer_new (image, width, height, format, + gimp_object_get_name (brush), + 1.0, GIMP_LAYER_MODE_NORMAL); + + gimp_item_set_offset (GIMP_ITEM (layer), + (image_width - width) / 2, + (image_height - height) / 2); + + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); + + if (pixmap) + { + guchar *pixmap_data; + guchar *mask_data; + guchar *p; + guchar *m; + gint i; + + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, width, height), 0, + babl_format ("R'G'B' u8"), + gimp_temp_buf_get_data (pixmap), GEGL_AUTO_ROWSTRIDE); + + pixmap_data = gegl_buffer_linear_open (buffer, NULL, NULL, NULL); + mask_data = gimp_temp_buf_get_data (mask); + + for (i = 0, p = pixmap_data, m = mask_data; + i < width * height; + i++, p += 4, m += 1) + { + p[3] = *m; + } + + gegl_buffer_linear_close (buffer, pixmap_data); + } + else + { + guchar *mask_data = gimp_temp_buf_get_data (mask); + gint i; + + for (i = 0; i < width * height; i++) + mask_data[i] = 255 - mask_data[i]; + + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, width, height), 0, + babl_format ("Y' u8"), + mask_data, GEGL_AUTO_ROWSTRIDE); + } + + return layer; +} + +GimpBrush * +file_gbr_drawable_to_brush (GimpDrawable *drawable, + const GeglRectangle *rect, + const gchar *name, + gdouble spacing) +{ + GimpBrush *brush; + GeglBuffer *buffer; + GimpTempBuf *mask; + GimpTempBuf *pixmap = NULL; + gint width; + gint height; + + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); + g_return_val_if_fail (rect != NULL, NULL); + + buffer = gimp_drawable_get_buffer (drawable); + width = rect->width; + height = rect->height; + + brush = g_object_new (GIMP_TYPE_BRUSH, + "name", name, + "mime-type", "image/x-gimp-gbr", + "spacing", spacing, + NULL); + + mask = gimp_temp_buf_new (width, height, babl_format ("Y u8")); + + if (gimp_drawable_is_gray (drawable)) + { + guchar *m = gimp_temp_buf_get_data (mask); + gint i; + + if (gimp_drawable_has_alpha (drawable)) + { + GeglBufferIterator *iter; + GimpRGB white; + + gimp_rgba_set_uchar (&white, 255, 255, 255, 255); + + iter = gegl_buffer_iterator_new (buffer, rect, 0, + babl_format ("Y'A u8"), + GEGL_ACCESS_READ, GEGL_ABYSS_NONE, + 1); + + while (gegl_buffer_iterator_next (iter)) + { + guint8 *data = (guint8 *) iter->items[0].data; + gint j; + + for (j = 0; j < iter->length; j++) + { + GimpRGB gray; + gint x, y; + gint dest; + + gimp_rgba_set_uchar (&gray, + data[0], data[0], data[0], + data[1]); + + gimp_rgb_composite (&gray, &white, + GIMP_RGB_COMPOSITE_BEHIND); + + x = iter->items[0].roi.x + j % iter->items[0].roi.width; + y = iter->items[0].roi.y + j / iter->items[0].roi.width; + + dest = y * width + x; + + gimp_rgba_get_uchar (&gray, &m[dest], NULL, NULL, NULL); + + data += 2; + } + } + } + else + { + gegl_buffer_get (buffer, rect, 1.0, + babl_format ("Y' u8"), m, + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + } + + /* invert */ + for (i = 0; i < width * height; i++) + m[i] = 255 - m[i]; + } + else + { + pixmap = gimp_temp_buf_new (width, height, babl_format ("R'G'B' u8")); + + gegl_buffer_get (buffer, rect, 1.0, + babl_format ("R'G'B' u8"), + gimp_temp_buf_get_data (pixmap), + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + + gegl_buffer_get (buffer, rect, 1.0, + babl_format ("A u8"), + gimp_temp_buf_get_data (mask), + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + } + + + brush->priv->mask = mask; + brush->priv->pixmap = pixmap; + + return brush; +} + + +/* private functions */ + +static GimpImage * +file_gbr_brush_to_image (Gimp *gimp, + GimpBrush *brush) +{ + GimpImage *image; + GimpLayer *layer; + const gchar *name; + GimpImageBaseType base_type; + gint width; + gint height; + GimpTempBuf *mask = gimp_brush_get_mask (brush); + GimpTempBuf *pixmap = gimp_brush_get_pixmap (brush); + GimpParasite *parasite; + + if (pixmap) + base_type = GIMP_RGB; + else + base_type = GIMP_GRAY; + + name = gimp_object_get_name (brush); + width = gimp_temp_buf_get_width (mask); + height = gimp_temp_buf_get_height (mask); + + image = gimp_image_new (gimp, width, height, base_type, + GIMP_PRECISION_U8_GAMMA); + + parasite = gimp_parasite_new ("gimp-brush-name", + GIMP_PARASITE_PERSISTENT, + strlen (name) + 1, name); + gimp_image_parasite_attach (image, parasite, FALSE); + gimp_parasite_free (parasite); + + layer = file_gbr_brush_to_layer (image, brush); + gimp_image_add_layer (image, layer, NULL, 0, FALSE); + + return image; +} + +static GimpBrush * +file_gbr_image_to_brush (GimpImage *image, + GimpDrawable *drawable, + const gchar *name, + gdouble spacing) +{ + gint width = gimp_item_get_width (GIMP_ITEM (drawable)); + gint height = gimp_item_get_height (GIMP_ITEM (drawable)); + + return file_gbr_drawable_to_brush (drawable, + GEGL_RECTANGLE (0, 0, width, height), + name, spacing); +} diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-gbr.h gimp-2.10.14+om/app/file-data/file-data-gbr.h --- gimp-2.10.8+zorin2/app/file-data/file-data-gbr.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-gbr.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,44 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FILE_DATA_GBR_H__ +#define __FILE_DATA_GBR_H__ + + +GimpValueArray * file_gbr_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + +GimpValueArray * file_gbr_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + +GimpLayer * file_gbr_brush_to_layer (GimpImage *image, + GimpBrush *brush); +GimpBrush * file_gbr_drawable_to_brush (GimpDrawable *drawable, + const GeglRectangle *rect, + const gchar *name, + gdouble spacing); + + +#endif /* __FILE_DATA_GBR_H__ */ diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-gih.c gimp-2.10.14+om/app/file-data/file-data-gih.c --- gimp-2.10.8+zorin2/app/file-data/file-data-gih.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-gih.c 2019-06-12 16:43:38.000000000 +0000 @@ -0,0 +1,346 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpbase/gimpparasiteio.h" +#include "libgimpcolor/gimpcolor.h" + +#include "core/core-types.h" + +#include "core/gimp.h" +#include "core/gimpbrushpipe.h" +#include "core/gimpbrushpipe-load.h" +#include "core/gimpbrush-private.h" +#include "core/gimpdrawable.h" +#include "core/gimpimage.h" +#include "core/gimplayer-new.h" +#include "core/gimpparamspecs.h" +#include "core/gimptempbuf.h" + +#include "pdb/gimpprocedure.h" + +#include "file-data-gbr.h" +#include "file-data-gih.h" + +#include "gimp-intl.h" + + +/* local function prototypes */ + +static GimpImage * file_gih_pipe_to_image (Gimp *gimp, + GimpBrushPipe *pipe); +static GimpBrushPipe * file_gih_image_to_pipe (GimpImage *image, + const gchar *name, + gdouble spacing, + const gchar *paramstring); + + +/* public functions */ + +GimpValueArray * +file_gih_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image = NULL; + const gchar *uri; + GFile *file; + GInputStream *input; + GError *my_error = NULL; + + gimp_set_busy (gimp); + + uri = g_value_get_string (gimp_value_array_index (args, 1)); + file = g_file_new_for_uri (uri); + + input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); + + if (input) + { + GList *list = gimp_brush_pipe_load (context, file, input, error); + + if (list) + { + GimpBrushPipe *pipe = list->data; + + g_list_free (list); + + image = file_gih_pipe_to_image (gimp, pipe); + g_object_unref (pipe); + } + + g_object_unref (input); + } + else + { + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for reading: "), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, image != NULL, + error ? *error : NULL); + + if (image) + gimp_value_set_image (gimp_value_array_index (return_vals, 1), image); + + gimp_unset_busy (gimp); + + return return_vals; +} + +GimpValueArray * +file_gih_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image; + GimpBrushPipe *pipe; + const gchar *uri; + const gchar *name; + const gchar *params; + GFile *file; + gint spacing; + gboolean success; + + gimp_set_busy (gimp); + + image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp); + uri = g_value_get_string (gimp_value_array_index (args, 3)); + spacing = g_value_get_int (gimp_value_array_index (args, 5)); + name = g_value_get_string (gimp_value_array_index (args, 6)); + params = g_value_get_string (gimp_value_array_index (args, 7)); + + file = g_file_new_for_uri (uri); + + pipe = file_gih_image_to_pipe (image, name, spacing, params); + + gimp_data_set_file (GIMP_DATA (pipe), file, TRUE, TRUE); + + success = gimp_data_save (GIMP_DATA (pipe), error); + + g_object_unref (pipe); + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + gimp_unset_busy (gimp); + + return return_vals; +} + + +/* private functions */ + +static GimpImage * +file_gih_pipe_to_image (Gimp *gimp, + GimpBrushPipe *pipe) +{ + GimpImage *image; + const gchar *name; + GimpImageBaseType base_type; + GimpParasite *parasite; + gchar spacing[8]; + gint i; + + if (gimp_brush_get_pixmap (pipe->current)) + base_type = GIMP_RGB; + else + base_type = GIMP_GRAY; + + name = gimp_object_get_name (pipe); + + image = gimp_image_new (gimp, 1, 1, base_type, + GIMP_PRECISION_U8_GAMMA); + + parasite = gimp_parasite_new ("gimp-brush-pipe-name", + GIMP_PARASITE_PERSISTENT, + strlen (name) + 1, name); + gimp_image_parasite_attach (image, parasite, FALSE); + gimp_parasite_free (parasite); + + g_snprintf (spacing, sizeof (spacing), "%d", + gimp_brush_get_spacing (GIMP_BRUSH (pipe))); + + parasite = gimp_parasite_new ("gimp-brush-pipe-spacing", + GIMP_PARASITE_PERSISTENT, + strlen (spacing) + 1, spacing); + gimp_image_parasite_attach (image, parasite, FALSE); + gimp_parasite_free (parasite); + + for (i = 0; i < pipe->n_brushes; i++) + { + GimpLayer *layer; + + layer = file_gbr_brush_to_layer (image, pipe->brushes[i]); + gimp_image_add_layer (image, layer, NULL, i, FALSE); + } + + if (pipe->params) + { + GimpPixPipeParams params; + gchar *paramstring; + + /* Since we do not (yet) load the pipe as described in the + * header, but use one layer per brush, we have to alter the + * paramstring before attaching it as a parasite. + * + * (this comment copied over from file-gih, whatever "as + * described in the header" means) -- mitch + */ + + gimp_pixpipe_params_init (¶ms); + gimp_pixpipe_params_parse (pipe->params, ¶ms); + + params.cellwidth = gimp_image_get_width (image); + params.cellheight = gimp_image_get_height (image); + params.cols = 1; + params.rows = 1; + + paramstring = gimp_pixpipe_params_build (¶ms); + if (paramstring) + { + parasite = gimp_parasite_new ("gimp-brush-pipe-parameters", + GIMP_PARASITE_PERSISTENT, + strlen (paramstring) + 1, + paramstring); + gimp_image_parasite_attach (image, parasite, FALSE); + gimp_parasite_free (parasite); + g_free (paramstring); + } + } + + return image; +} + +static GimpBrushPipe * +file_gih_image_to_pipe (GimpImage *image, + const gchar *name, + gdouble spacing, + const gchar *paramstring) +{ + GimpBrushPipe *pipe; + GimpPixPipeParams params; + GList *layers; + GList *list; + GList *brushes = NULL; + gint image_width; + gint image_height; + gint i; + + pipe = g_object_new (GIMP_TYPE_BRUSH_PIPE, + "name", name, + "mime-type", "image/x-gimp-gih", + "spacing", spacing, + NULL); + + gimp_pixpipe_params_init (¶ms); + gimp_pixpipe_params_parse (paramstring, ¶ms); + + image_width = gimp_image_get_width (image); + image_height = gimp_image_get_height (image); + + layers = gimp_image_get_layer_iter (image); + + for (list = layers; list; list = g_list_next (list)) + { + GimpLayer *layer = list->data; + gint width; + gint height; + gint offset_x; + gint offset_y; + gint row; + + width = gimp_item_get_width (GIMP_ITEM (layer)); + height = gimp_item_get_height (GIMP_ITEM (layer)); + + gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y); + + for (row = 0; row < params.rows; row++) + { + gint y, ynext; + gint thisy, thish; + gint col; + + y = (row * image_height) / params.rows; + ynext = ((row + 1) * image_height / params.rows); + + /* Assume layer is offset to positive direction in x and y. + * That's reasonable, as otherwise all of the layer + * won't be visible. + * thisy and thisx are in the drawable's coordinate space. + */ + thisy = MAX (0, y - offset_y); + thish = (ynext - offset_y) - thisy; + thish = MIN (thish, height - thisy); + + for (col = 0; col < params.cols; col++) + { + GimpBrush *brush; + gint x, xnext; + gint thisx, thisw; + + x = (col * image_width / params.cols); + xnext = ((col + 1) * image_width / params.cols); + thisx = MAX (0, x - offset_x); + thisw = (xnext - offset_x) - thisx; + thisw = MIN (thisw, width - thisx); + + brush = file_gbr_drawable_to_brush (GIMP_DRAWABLE (layer), + GEGL_RECTANGLE (thisx, thisy, + thisw, thish), + gimp_object_get_name (layer), + spacing); + + brushes = g_list_prepend (brushes, brush); + } + } + } + + brushes = g_list_reverse (brushes); + + pipe->n_brushes = g_list_length (brushes); + pipe->brushes = g_new0 (GimpBrush *, pipe->n_brushes); + + for (list = brushes, i = 0; list; list = g_list_next (list), i++) + pipe->brushes[i] = list->data; + + g_list_free (brushes); + + gimp_pixpipe_params_free (¶ms); + + gimp_brush_pipe_set_params (pipe, paramstring); + + return pipe; +} diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-gih.h gimp-2.10.14+om/app/file-data/file-data-gih.h --- gimp-2.10.8+zorin2/app/file-data/file-data-gih.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-gih.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,37 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FILE_DATA_GIH_H__ +#define __FILE_DATA_GIH_H__ + + +GimpValueArray * file_gih_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + +GimpValueArray * file_gih_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + + +#endif /* __FILE_DATA_GIH_H__ */ diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data.h gimp-2.10.14+om/app/file-data/file-data.h --- gimp-2.10.8+zorin2/app/file-data/file-data.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,26 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FILE_DATA_H__ +#define __FILE_DATA_H__ + + +void file_data_init (Gimp *gimp); +void file_data_exit (Gimp *gimp); + + +#endif /* __FILE_DATA_H__ */ diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-pat.c gimp-2.10.14+om/app/file-data/file-data-pat.c --- gimp-2.10.8+zorin2/app/file-data/file-data-pat.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-pat.c 2019-06-12 16:43:38.000000000 +0000 @@ -0,0 +1,263 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpbase/gimpbase.h" + +#include "core/core-types.h" + +#include "gegl/gimp-babl.h" + +#include "core/gimp.h" +#include "core/gimpdrawable.h" +#include "core/gimpimage.h" +#include "core/gimplayer-new.h" +#include "core/gimpparamspecs.h" +#include "core/gimppattern.h" +#include "core/gimppattern-load.h" +#include "core/gimptempbuf.h" + +#include "pdb/gimpprocedure.h" + +#include "file-data-pat.h" + +#include "gimp-intl.h" + + +/* local function prototypes */ + +static GimpImage * file_pat_pattern_to_image (Gimp *gimp, + GimpPattern *pattern); +static GimpPattern * file_pat_image_to_pattern (GimpImage *image, + GimpDrawable *drawable, + const gchar *name); + + +/* public functions */ + +GimpValueArray * +file_pat_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image = NULL; + const gchar *uri; + GFile *file; + GInputStream *input; + GError *my_error = NULL; + + gimp_set_busy (gimp); + + uri = g_value_get_string (gimp_value_array_index (args, 1)); + file = g_file_new_for_uri (uri); + + input = G_INPUT_STREAM (g_file_read (file, NULL, &my_error)); + + if (input) + { + GList *list = gimp_pattern_load (context, file, input, error); + + if (list) + { + GimpPattern *pattern = list->data; + + g_list_free (list); + + image = file_pat_pattern_to_image (gimp, pattern); + g_object_unref (pattern); + } + + g_object_unref (input); + } + else + { + g_propagate_prefixed_error (error, my_error, + _("Could not open '%s' for reading: "), + gimp_file_get_utf8_name (file)); + } + + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, image != NULL, + error ? *error : NULL); + + if (image) + gimp_value_set_image (gimp_value_array_index (return_vals, 1), image); + + gimp_unset_busy (gimp); + + return return_vals; +} + +GimpValueArray * +file_pat_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + GimpValueArray *return_vals; + GimpImage *image; + GimpDrawable *drawable; + GimpPattern *pattern; + const gchar *uri; + const gchar *name; + GFile *file; + gboolean success; + + gimp_set_busy (gimp); + + image = gimp_value_get_image (gimp_value_array_index (args, 1), gimp); + drawable = gimp_value_get_drawable (gimp_value_array_index (args, 2), gimp); + uri = g_value_get_string (gimp_value_array_index (args, 3)); + name = g_value_get_string (gimp_value_array_index (args, 5)); + + file = g_file_new_for_uri (uri); + + pattern = file_pat_image_to_pattern (image, drawable, name); + + gimp_data_set_file (GIMP_DATA (pattern), file, TRUE, TRUE); + + success = gimp_data_save (GIMP_DATA (pattern), error); + + g_object_unref (pattern); + g_object_unref (file); + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + gimp_unset_busy (gimp); + + return return_vals; +} + + +/* private functions */ + +static GimpImage * +file_pat_pattern_to_image (Gimp *gimp, + GimpPattern *pattern) +{ + GimpImage *image; + GimpLayer *layer; + const Babl *format; + const gchar *name; + GimpImageBaseType base_type; + gboolean alpha; + gint width; + gint height; + GimpTempBuf *mask = gimp_pattern_get_mask (pattern); + GeglBuffer *buffer; + GimpParasite *parasite; + + format = gimp_temp_buf_get_format (mask); + + switch (babl_format_get_bytes_per_pixel (format)) + { + case 1: + base_type = GIMP_GRAY; + alpha = FALSE; + break; + + case 2: + base_type = GIMP_GRAY; + alpha = TRUE; + break; + + case 3: + base_type = GIMP_RGB; + alpha = FALSE; + break; + + case 4: + base_type = GIMP_RGB; + alpha = TRUE; + break; + + default: + g_return_val_if_reached (NULL); + } + + name = gimp_object_get_name (pattern); + width = gimp_temp_buf_get_width (mask); + height = gimp_temp_buf_get_height (mask); + + image = gimp_image_new (gimp, width, height, base_type, + GIMP_PRECISION_U8_GAMMA); + + parasite = gimp_parasite_new ("gimp-pattern-name", + GIMP_PARASITE_PERSISTENT, + strlen (name) + 1, name); + gimp_image_parasite_attach (image, parasite, FALSE); + gimp_parasite_free (parasite); + + format = gimp_image_get_layer_format (image, alpha); + + layer = gimp_layer_new (image, width, height, format, name, + 1.0, GIMP_LAYER_MODE_NORMAL); + gimp_image_add_layer (image, layer, NULL, 0, FALSE); + + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); + + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, width, height), 0, + NULL, + gimp_temp_buf_get_data (mask), GEGL_AUTO_ROWSTRIDE); + + return image; +} + +static GimpPattern * +file_pat_image_to_pattern (GimpImage *image, + GimpDrawable *drawable, + const gchar *name) +{ + GimpPattern *pattern; + const Babl *format; + gint width; + gint height; + + format = gimp_babl_format (gimp_drawable_is_gray (drawable) ? + GIMP_GRAY : GIMP_RGB, + GIMP_PRECISION_U8_GAMMA, + gimp_drawable_has_alpha (drawable)); + + width = gimp_item_get_width (GIMP_ITEM (drawable)); + height = gimp_item_get_height (GIMP_ITEM (drawable)); + + pattern = g_object_new (GIMP_TYPE_PATTERN, + "name", name, + "mime-type", "image/x-gimp-pat", + NULL); + + pattern->mask = gimp_temp_buf_new (width, height, format); + + gegl_buffer_get (gimp_drawable_get_buffer (drawable), + GEGL_RECTANGLE (0, 0, width, height), 1.0, + format, gimp_temp_buf_get_data (pattern->mask), + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + + return pattern; +} diff -Nru gimp-2.10.8+zorin2/app/file-data/file-data-pat.h gimp-2.10.14+om/app/file-data/file-data-pat.h --- gimp-2.10.8+zorin2/app/file-data/file-data-pat.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/file-data-pat.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,37 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FILE_DATA_PAT_H__ +#define __FILE_DATA_PAT_H__ + + +GimpValueArray * file_pat_load_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + +GimpValueArray * file_pat_save_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error); + + +#endif /* __FILE_DATA_PAT_H__ */ diff -Nru gimp-2.10.8+zorin2/app/file-data/Makefile.am gimp-2.10.14+om/app/file-data/Makefile.am --- gimp-2.10.8+zorin2/app/file-data/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/Makefile.am 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,24 @@ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Gimp-File-Data\" \ + -I$(top_builddir) \ + -I$(top_srcdir) \ + -I$(top_builddir)/app \ + -I$(top_srcdir)/app \ + $(CAIRO_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(GDK_PIXBUF_CFLAGS) \ + -I$(includedir) + +noinst_LIBRARIES = libappfile-data.a + +libappfile_data_a_SOURCES = \ + file-data.c \ + file-data.h \ + file-data-gbr.c \ + file-data-gbr.h \ + file-data-gih.c \ + file-data-gih.h \ + file-data-pat.c \ + file-data-pat.h diff -Nru gimp-2.10.8+zorin2/app/file-data/Makefile.in gimp-2.10.14+om/app/file-data/Makefile.in --- gimp-2.10.8+zorin2/app/file-data/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/file-data/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -0,0 +1,932 @@ +# Makefile.in generated by automake 1.16.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = app/file-data +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4macros/gtk-doc.m4 \ + $(top_srcdir)/m4macros/intltool.m4 \ + $(top_srcdir)/m4macros/libtool.m4 \ + $(top_srcdir)/m4macros/ltoptions.m4 \ + $(top_srcdir)/m4macros/ltsugar.m4 \ + $(top_srcdir)/m4macros/ltversion.m4 \ + $(top_srcdir)/m4macros/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libappfile_data_a_AR = $(AR) $(ARFLAGS) +libappfile_data_a_LIBADD = +am_libappfile_data_a_OBJECTS = file-data.$(OBJEXT) \ + file-data-gbr.$(OBJEXT) file-data-gih.$(OBJEXT) \ + file-data-pat.$(OBJEXT) +libappfile_data_a_OBJECTS = $(am_libappfile_data_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/file-data-gbr.Po \ + ./$(DEPDIR)/file-data-gih.Po ./$(DEPDIR)/file-data-pat.Po \ + ./$(DEPDIR)/file-data.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libappfile_data_a_SOURCES) +DIST_SOURCES = $(libappfile_data_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GLIB_WIN_BUG_CFLAGS = @GLIB_WIN_BUG_CFLAGS@ +GLIB_WIN_BUG_LIBS = @GLIB_WIN_BUG_LIBS@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Gimp-File-Data\" \ + -I$(top_builddir) \ + -I$(top_srcdir) \ + -I$(top_builddir)/app \ + -I$(top_srcdir)/app \ + $(CAIRO_CFLAGS) \ + $(GEGL_CFLAGS) \ + $(GDK_PIXBUF_CFLAGS) \ + -I$(includedir) + +noinst_LIBRARIES = libappfile-data.a +libappfile_data_a_SOURCES = \ + file-data.c \ + file-data.h \ + file-data-gbr.c \ + file-data-gbr.h \ + file-data-gih.c \ + file-data-gih.h \ + file-data-pat.c \ + file-data-pat.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu app/file-data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu app/file-data/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libappfile-data.a: $(libappfile_data_a_OBJECTS) $(libappfile_data_a_DEPENDENCIES) $(EXTRA_libappfile_data_a_DEPENDENCIES) + $(AM_V_at)-rm -f libappfile-data.a + $(AM_V_AR)$(libappfile_data_a_AR) libappfile-data.a $(libappfile_data_a_OBJECTS) $(libappfile_data_a_LIBADD) + $(AM_V_at)$(RANLIB) libappfile-data.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-data-gbr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-data-gih.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-data-pat.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file-data.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/file-data-gbr.Po + -rm -f ./$(DEPDIR)/file-data-gih.Po + -rm -f ./$(DEPDIR)/file-data-pat.Po + -rm -f ./$(DEPDIR)/file-data.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/file-data-gbr.Po + -rm -f ./$(DEPDIR)/file-data-gih.Po + -rm -f ./$(DEPDIR)/file-data-pat.Po + -rm -f ./$(DEPDIR)/file-data.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru gimp-2.10.8+zorin2/app/gegl/gimpapplicator.c gimp-2.10.14+om/app/gegl/gimpapplicator.c --- gimp-2.10.8+zorin2/app/gegl/gimpapplicator.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimpapplicator.c 2019-04-07 11:38:14.000000000 +0000 @@ -104,9 +104,7 @@ } GimpApplicator * -gimp_applicator_new (GeglNode *parent, - gboolean use_split_preview, - gboolean use_result_cache) +gimp_applicator_new (GeglNode *parent) { GimpApplicator *applicator; @@ -148,40 +146,12 @@ "operation", "gegl:translate", NULL); - applicator->dup_apply_buffer_node = - gegl_node_new_child (applicator->node, - "operation", "gegl:copy-buffer", - NULL); - gegl_node_link_many (applicator->aux_node, applicator->apply_offset_node, - applicator->dup_apply_buffer_node, NULL); - if (use_split_preview) - { - applicator->preview_cache_node = - gegl_node_new_child (applicator->node, - "operation", "gegl:cache", - NULL); - - applicator->preview_crop_node = - gegl_node_new_child (applicator->node, - "operation", "gegl:nop", - NULL); - - gegl_node_link_many (applicator->dup_apply_buffer_node, - applicator->preview_cache_node, - applicator->preview_crop_node, - NULL); - gegl_node_connect_to (applicator->preview_crop_node, "output", - applicator->mode_node, "aux"); - } - else - { - gegl_node_connect_to (applicator->dup_apply_buffer_node, "output", - applicator->mode_node, "aux"); - } + gegl_node_connect_to (applicator->apply_offset_node, "output", + applicator->mode_node, "aux"); applicator->mask_node = gegl_node_new_child (applicator->node, @@ -203,26 +173,28 @@ "mask", applicator->affect, NULL); - if (use_result_cache) - { - applicator->output_cache_node = - gegl_node_new_child (applicator->node, - "operation", "gegl:cache", - NULL); + applicator->convert_format_node = + gegl_node_new_child (applicator->node, + "operation", "gegl:nop", + NULL); - gegl_node_link_many (applicator->input_node, - applicator->affect_node, - applicator->output_cache_node, - applicator->output_node, - NULL); - } - else - { - gegl_node_link_many (applicator->input_node, - applicator->affect_node, - applicator->output_node, - NULL); - } + applicator->cache_node = + gegl_node_new_child (applicator->node, + "operation", "gegl:nop", + NULL); + + applicator->crop_node = + gegl_node_new_child (applicator->node, + "operation", "gegl:nop", + NULL); + + gegl_node_link_many (applicator->input_node, + applicator->affect_node, + applicator->convert_format_node, + applicator->cache_node, + applicator->crop_node, + applicator->output_node, + NULL); gegl_node_connect_to (applicator->mode_node, "output", applicator->affect_node, "aux"); @@ -487,134 +459,86 @@ } } -gboolean gegl_buffer_list_valid_rectangles (GeglBuffer *buffer, - GeglRectangle **rectangles, - gint *n_rectangles); - void -gimp_applicator_set_preview (GimpApplicator *applicator, - gboolean enable, - const GeglRectangle *rect) +gimp_applicator_set_output_format (GimpApplicator *applicator, + const Babl *format) { g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); - g_return_if_fail (rect != NULL); - - if (! applicator->preview_cache_node) - return; - if (applicator->preview_enabled != enable || - applicator->preview_rect.x != rect->x || - applicator->preview_rect.y != rect->y || - applicator->preview_rect.width != rect->width || - applicator->preview_rect.height != rect->height) + if (applicator->output_format != format) { - if (enable) + if (format) { - if (! applicator->preview_enabled) + if (! applicator->output_format) { - gegl_node_set (applicator->preview_crop_node, - "operation", "gimp:compose-crop", - "x", rect->x, - "y", rect->y, - "width", rect->width, - "height", rect->height, + gegl_node_set (applicator->convert_format_node, + "operation", "gegl:convert-format", + "format", format, NULL); - - gegl_node_connect_to (applicator->input_node, "output", - applicator->preview_crop_node, "aux"); } else { - gegl_node_set (applicator->preview_crop_node, - "x", rect->x, - "y", rect->y, - "width", rect->width, - "height", rect->height, + gegl_node_set (applicator->convert_format_node, + "format", format, NULL); } } - else if (applicator->preview_enabled) + else { - GeglBuffer *cache; - - gegl_node_disconnect (applicator->preview_crop_node, "aux"); - gegl_node_set (applicator->preview_crop_node, + gegl_node_set (applicator->convert_format_node, "operation", "gegl:nop", NULL); - - /* when disabling the preview, preserve the cached result - * by processing it into the output cache, which only - * involves the mode and affect nodes. - */ - gegl_node_get (applicator->preview_cache_node, - "cache", &cache, - NULL); - - if (cache) - { - GeglRectangle *rectangles; - gint n_rectangles; - - if (gegl_buffer_list_valid_rectangles (cache, &rectangles, - &n_rectangles)) - { - gint i; - - for (i = 0; i < n_rectangles; i++) - gegl_node_blit (applicator->output_cache_node, 1.0, - &rectangles[i], - NULL, NULL, 0, GEGL_BLIT_DEFAULT); - - g_free (rectangles); - } - - g_object_unref (cache); - } } - applicator->preview_enabled = enable; - applicator->preview_rect = *rect; + applicator->output_format = format; } } -void -gimp_applicator_blit (GimpApplicator *applicator, - const GeglRectangle *rect) +const Babl * +gimp_applicator_get_output_format (GimpApplicator *applicator) { - g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); + g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), NULL); - gegl_node_blit (applicator->dest_node, 1.0, rect, - NULL, NULL, 0, GEGL_BLIT_DEFAULT); + return applicator->output_format; } -GeglBuffer * -gimp_applicator_dup_apply_buffer (GimpApplicator *applicator, - const GeglRectangle *rect) +void +gimp_applicator_set_cache (GimpApplicator *applicator, + gboolean enable) { - GeglBuffer *buffer; - GeglBuffer *shifted; - - g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), NULL); - g_return_val_if_fail (rect != NULL, NULL); - - buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect->width, rect->height), - babl_format ("RGBA float")); + g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); - shifted = g_object_new (GEGL_TYPE_BUFFER, - "source", buffer, - "shift-x", -rect->x, - "shift-y", -rect->y, - NULL); + if (applicator->cache_enabled != enable) + { + if (enable) + { + gegl_node_set (applicator->cache_node, + "operation", "gegl:cache", + NULL); + } + else + { + gegl_node_set (applicator->cache_node, + "operation", "gegl:nop", + NULL); + } - gegl_node_set (applicator->dup_apply_buffer_node, - "buffer", shifted, - NULL); + applicator->cache_enabled = enable; + } +} - g_object_unref (shifted); +gboolean +gimp_applicator_get_cache (GimpApplicator *applicator) +{ + g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), FALSE); - return buffer; + return applicator->cache_enabled; } +gboolean gegl_buffer_list_valid_rectangles (GeglBuffer *buffer, + GeglRectangle **rectangles, + gint *n_rectangles); + GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator, GeglRectangle **rectangles, @@ -624,18 +548,21 @@ g_return_val_if_fail (rectangles != NULL, NULL); g_return_val_if_fail (n_rectangles != NULL, NULL); - if (applicator->output_cache_node) + if (applicator->cache_enabled) { GeglBuffer *cache; - gegl_node_get (applicator->output_cache_node, + gegl_node_get (applicator->cache_node, "cache", &cache, NULL); if (cache) { - if (gegl_buffer_list_valid_rectangles (cache, rectangles, n_rectangles)) - return cache; + if (gegl_buffer_list_valid_rectangles (cache, + rectangles, n_rectangles)) + { + return cache; + } g_object_unref (cache); } @@ -643,3 +570,73 @@ return NULL; } + +void +gimp_applicator_set_crop (GimpApplicator *applicator, + const GeglRectangle *rect) +{ + g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); + + if (applicator->crop_enabled != (rect != NULL) || + (rect && ! gegl_rectangle_equal (&applicator->crop_rect, rect))) + { + if (rect) + { + if (! applicator->crop_enabled) + { + gegl_node_set (applicator->crop_node, + "operation", "gimp:compose-crop", + "x", rect->x, + "y", rect->y, + "width", rect->width, + "height", rect->height, + NULL); + + gegl_node_connect_to (applicator->input_node, "output", + applicator->crop_node, "aux"); + } + else + { + gegl_node_set (applicator->crop_node, + "x", rect->x, + "y", rect->y, + "width", rect->width, + "height", rect->height, + NULL); + } + + applicator->crop_enabled = TRUE; + applicator->crop_rect = *rect; + } + else + { + gegl_node_disconnect (applicator->crop_node, "aux"); + gegl_node_set (applicator->crop_node, + "operation", "gegl:nop", + NULL); + + applicator->crop_enabled = FALSE; + } + } +} + +const GeglRectangle * +gimp_applicator_get_crop (GimpApplicator *applicator) +{ + g_return_val_if_fail (GIMP_IS_APPLICATOR (applicator), NULL); + + if (applicator->crop_enabled) + return &applicator->crop_rect; + + return NULL; +} + +void +gimp_applicator_blit (GimpApplicator *applicator, + const GeglRectangle *rect) +{ + g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); + + gegl_node_blit (applicator->dest_node, 1.0, rect, + NULL, NULL, 0, GEGL_BLIT_DEFAULT); +} diff -Nru gimp-2.10.8+zorin2/app/gegl/gimpapplicator.h gimp-2.10.14+om/app/gegl/gimpapplicator.h --- gimp-2.10.8+zorin2/app/gegl/gimpapplicator.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimpapplicator.h 2019-04-07 11:38:14.000000000 +0000 @@ -48,13 +48,6 @@ gint apply_offset_y; GeglNode *apply_offset_node; - GeglNode *dup_apply_buffer_node; - - gboolean preview_enabled; - GeglRectangle preview_rect; - GeglNode *preview_cache_node; - GeglNode *preview_crop_node; - gdouble opacity; GimpLayerMode paint_mode; GimpLayerColorSpace blend_space; @@ -65,7 +58,15 @@ GimpComponentMask affect; GeglNode *affect_node; - GeglNode *output_cache_node; + const Babl *output_format; + GeglNode *convert_format_node; + + gboolean cache_enabled; + GeglNode *cache_node; + + gboolean crop_enabled; + GeglRectangle crop_rect; + GeglNode *crop_node; GeglBuffer *src_buffer; GeglNode *src_node; @@ -87,51 +88,54 @@ }; -GType gimp_applicator_get_type (void) G_GNUC_CONST; +GType gimp_applicator_get_type (void) G_GNUC_CONST; + +GimpApplicator * gimp_applicator_new (GeglNode *parent); + +void gimp_applicator_set_src_buffer (GimpApplicator *applicator, + GeglBuffer *dest_buffer); +void gimp_applicator_set_dest_buffer (GimpApplicator *applicator, + GeglBuffer *dest_buffer); + +void gimp_applicator_set_mask_buffer (GimpApplicator *applicator, + GeglBuffer *mask_buffer); +void gimp_applicator_set_mask_offset (GimpApplicator *applicator, + gint mask_offset_x, + gint mask_offset_y); + +void gimp_applicator_set_apply_buffer (GimpApplicator *applicator, + GeglBuffer *apply_buffer); +void gimp_applicator_set_apply_offset (GimpApplicator *applicator, + gint apply_offset_x, + gint apply_offset_y); + +void gimp_applicator_set_opacity (GimpApplicator *applicator, + gdouble opacity); +void gimp_applicator_set_mode (GimpApplicator *applicator, + GimpLayerMode paint_mode, + GimpLayerColorSpace blend_space, + GimpLayerColorSpace composite_space, + GimpLayerCompositeMode composite_mode); +void gimp_applicator_set_affect (GimpApplicator *applicator, + GimpComponentMask affect); + +void gimp_applicator_set_output_format (GimpApplicator *applicator, + const Babl *format); +const Babl * gimp_applicator_get_output_format (GimpApplicator *applicator); + +void gimp_applicator_set_cache (GimpApplicator *applicator, + gboolean enable); +gboolean gimp_applicator_get_cache (GimpApplicator *applicator); +GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator, + GeglRectangle **rectangles, + gint *n_rectangles); + +void gimp_applicator_set_crop (GimpApplicator *applicator, + const GeglRectangle *rect); +const GeglRectangle * gimp_applicator_get_crop (GimpApplicator *applicator); -GimpApplicator * gimp_applicator_new (GeglNode *parent, - gboolean use_split_preview, - gboolean use_result_cache); - -void gimp_applicator_set_src_buffer (GimpApplicator *applicator, - GeglBuffer *dest_buffer); -void gimp_applicator_set_dest_buffer (GimpApplicator *applicator, - GeglBuffer *dest_buffer); - -void gimp_applicator_set_mask_buffer (GimpApplicator *applicator, - GeglBuffer *mask_buffer); -void gimp_applicator_set_mask_offset (GimpApplicator *applicator, - gint mask_offset_x, - gint mask_offset_y); - -void gimp_applicator_set_apply_buffer (GimpApplicator *applicator, - GeglBuffer *apply_buffer); -void gimp_applicator_set_apply_offset (GimpApplicator *applicator, - gint apply_offset_x, - gint apply_offset_y); - -void gimp_applicator_set_opacity (GimpApplicator *applicator, - gdouble opacity); -void gimp_applicator_set_mode (GimpApplicator *applicator, - GimpLayerMode paint_mode, - GimpLayerColorSpace blend_space, - GimpLayerColorSpace composite_space, - GimpLayerCompositeMode composite_mode); -void gimp_applicator_set_affect (GimpApplicator *applicator, - GimpComponentMask affect); - -void gimp_applicator_set_preview (GimpApplicator *applicator, - gboolean enable, - const GeglRectangle *rect); - -void gimp_applicator_blit (GimpApplicator *applicator, - const GeglRectangle *rect); - -GeglBuffer * gimp_applicator_dup_apply_buffer (GimpApplicator *applicator, - const GeglRectangle *rect); -GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator *applicator, - GeglRectangle **rectangles, - gint *n_rectangles); +void gimp_applicator_blit (GimpApplicator *applicator, + const GeglRectangle *rect); #endif /* __GIMP_APPLICATOR_H__ */ diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-babl.c gimp-2.10.14+om/app/gegl/gimp-babl.c --- gimp-2.10.8+zorin2/app/gegl/gimp-babl.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-babl.c 2019-04-07 11:38:14.000000000 +0000 @@ -780,6 +780,25 @@ g_return_val_if_reached (FALSE); } +GimpComponentType +gimp_babl_is_bounded (GimpPrecision precision) +{ + switch (gimp_babl_component_type (precision)) + { + case GIMP_COMPONENT_TYPE_U8: + case GIMP_COMPONENT_TYPE_U16: + case GIMP_COMPONENT_TYPE_U32: + return TRUE; + + case GIMP_COMPONENT_TYPE_HALF: + case GIMP_COMPONENT_TYPE_FLOAT: + case GIMP_COMPONENT_TYPE_DOUBLE: + return FALSE; + } + + g_return_val_if_reached (FALSE); +} + const Babl * gimp_babl_format (GimpImageBaseType base_type, GimpPrecision precision, @@ -1266,6 +1285,32 @@ g_return_val_if_reached (NULL); } +const Babl * +gimp_babl_format_change_component_type (const Babl *format, + GimpComponentType component) +{ + g_return_val_if_fail (format != NULL, NULL); + + return gimp_babl_format (gimp_babl_format_get_base_type (format), + gimp_babl_precision ( + component, + gimp_babl_format_get_linear (format)), + babl_format_has_alpha (format)); +} + +const Babl * +gimp_babl_format_change_linear (const Babl *format, + gboolean linear) +{ + g_return_val_if_fail (format != NULL, NULL); + + return gimp_babl_format (gimp_babl_format_get_base_type (format), + gimp_babl_precision ( + gimp_babl_format_get_component_type (format), + linear), + babl_format_has_alpha (format)); +} + gchar ** gimp_babl_print_pixel (const Babl *format, gpointer pixel) diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-babl-compat.c gimp-2.10.14+om/app/gegl/gimp-babl-compat.c --- gimp-2.10.8+zorin2/app/gegl/gimp-babl-compat.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-babl-compat.c 2019-04-07 11:38:14.000000000 +0000 @@ -81,3 +81,13 @@ GIMP_PRECISION_U8_GAMMA, babl_format_has_alpha (format)); } + +const Babl * +gimp_babl_compat_u8_mask_format (const Babl *format) +{ + g_return_val_if_fail (format != NULL, NULL); + + return gimp_babl_format (gimp_babl_format_get_base_type (format), + GIMP_PRECISION_U8_LINEAR, + FALSE); +} diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-babl-compat.h gimp-2.10.14+om/app/gegl/gimp-babl-compat.h --- gimp-2.10.8+zorin2/app/gegl/gimp-babl-compat.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-babl-compat.h 2019-04-07 11:38:14.000000000 +0000 @@ -25,6 +25,7 @@ GimpImageType gimp_babl_format_get_image_type (const Babl *format); const Babl * gimp_babl_compat_u8_format (const Babl *format); +const Babl * gimp_babl_compat_u8_mask_format (const Babl *format); #endif /* __GIMP_BABL_COMPAT_H__ */ diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-babl.h gimp-2.10.14+om/app/gegl/gimp-babl.h --- gimp-2.10.8+zorin2/app/gegl/gimp-babl.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-babl.h 2019-04-07 11:38:14.000000000 +0000 @@ -22,35 +22,41 @@ #define __GIMP_BABL_H__ -void gimp_babl_init (void); -void gimp_babl_init_fishes (GimpInitStatusFunc status_callback); +void gimp_babl_init (void); +void gimp_babl_init_fishes (GimpInitStatusFunc status_callback); -const gchar * gimp_babl_format_get_description (const Babl *format); -GimpColorProfile * gimp_babl_format_get_color_profile (const Babl *format); +const gchar * gimp_babl_format_get_description (const Babl *format); +GimpColorProfile * gimp_babl_format_get_color_profile (const Babl *format); -GimpImageBaseType gimp_babl_format_get_base_type (const Babl *format); -GimpComponentType gimp_babl_format_get_component_type (const Babl *format); -GimpPrecision gimp_babl_format_get_precision (const Babl *format); -gboolean gimp_babl_format_get_linear (const Babl *format); - -GimpComponentType gimp_babl_component_type (GimpPrecision precision); -gboolean gimp_babl_linear (GimpPrecision precision); -GimpPrecision gimp_babl_precision (GimpComponentType component, - gboolean linear); - -gboolean gimp_babl_is_valid (GimpImageBaseType base_type, - GimpPrecision precision); - -const Babl * gimp_babl_format (GimpImageBaseType base_type, - GimpPrecision precision, - gboolean with_alpha); -const Babl * gimp_babl_mask_format (GimpPrecision precision); -const Babl * gimp_babl_component_format (GimpImageBaseType base_type, - GimpPrecision precision, - gint index); +GimpImageBaseType gimp_babl_format_get_base_type (const Babl *format); +GimpComponentType gimp_babl_format_get_component_type (const Babl *format); +GimpPrecision gimp_babl_format_get_precision (const Babl *format); +gboolean gimp_babl_format_get_linear (const Babl *format); + +GimpComponentType gimp_babl_component_type (GimpPrecision precision); +gboolean gimp_babl_linear (GimpPrecision precision); +GimpPrecision gimp_babl_precision (GimpComponentType component, + gboolean linear); + +gboolean gimp_babl_is_valid (GimpImageBaseType base_type, + GimpPrecision precision); +GimpComponentType gimp_babl_is_bounded (GimpPrecision precision); + +const Babl * gimp_babl_format (GimpImageBaseType base_type, + GimpPrecision precision, + gboolean with_alpha); +const Babl * gimp_babl_mask_format (GimpPrecision precision); +const Babl * gimp_babl_component_format (GimpImageBaseType base_type, + GimpPrecision precision, + gint index); + +const Babl * gimp_babl_format_change_component_type (const Babl *format, + GimpComponentType component); +const Babl * gimp_babl_format_change_linear (const Babl *format, + gboolean linear); -gchar ** gimp_babl_print_pixel (const Babl *format, - gpointer pixel); +gchar ** gimp_babl_print_pixel (const Babl *format, + gpointer pixel); #endif /* __GIMP_BABL_H__ */ diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-apply-operation.c gimp-2.10.14+om/app/gegl/gimp-gegl-apply-operation.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-apply-operation.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-apply-operation.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,6 +30,7 @@ #include "core/gimp-transform-utils.h" #include "core/gimp-utils.h" +#include "core/gimpchunkiterator.h" #include "core/gimpprogress.h" #include "gimp-gegl-apply-operation.h" @@ -38,6 +39,17 @@ #include "gimp-gegl-utils.h" +/* iteration interval when applying an operation interactively + * (with progress indication) + */ +#define APPLY_OPERATION_INTERACTIVE_INTERVAL (1.0 / 8.0) /* seconds */ + +/* iteration interval when applying an operation non-interactively + * (without progress indication) + */ +#define APPLY_OPERATION_NON_INTERACTIVE_INTERVAL 1.0 /* seconds */ + + void gimp_gegl_apply_operation (GeglBuffer *src_buffer, GimpProgress *progress, @@ -50,6 +62,7 @@ gimp_gegl_apply_cached_operation (src_buffer, progress, undo_desc, operation, + src_buffer != NULL, dest_buffer, dest_rect, crop_input, @@ -69,23 +82,27 @@ GimpProgress *progress, const gchar *undo_desc, GeglNode *operation, + gboolean connect_src_buffer, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, gboolean crop_input, GeglBuffer *cache, const GeglRectangle *valid_rects, gint n_valid_rects, - gboolean cancellable) + gboolean cancelable) { - GeglNode *gegl; - GeglNode *effect; - GeglNode *dest_node; - GeglNode *operation_src_node = NULL; - GeglRectangle rect = { 0, }; - GeglProcessor *processor = NULL; - gboolean progress_started = FALSE; - gdouble value; - gboolean cancel = FALSE; + GeglNode *gegl; + GeglNode *effect; + GeglNode *dest_node; + GeglNode *underlying_operation; + GeglNode *operation_src_node = NULL; + GeglBuffer *result_buffer; + GimpChunkIterator *iter; + cairo_region_t *region; + gboolean progress_started = FALSE; + gboolean cancel = FALSE; + gint all_pixels; + gint done_pixels; g_return_val_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer), FALSE); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE); @@ -95,14 +112,113 @@ g_return_val_if_fail (valid_rects == NULL || cache != NULL, FALSE); g_return_val_if_fail (valid_rects == NULL || n_valid_rects != 0, FALSE); - if (dest_rect) + if (! dest_rect) + dest_rect = gegl_buffer_get_extent (dest_buffer); + + if (progress) { - rect = *dest_rect; + if (gimp_progress_is_active (progress)) + { + if (undo_desc) + gimp_progress_set_text_literal (progress, undo_desc); + + progress_started = FALSE; + cancelable = FALSE; + } + else + { + gimp_progress_start (progress, cancelable, "%s", undo_desc); + + if (cancelable) + g_signal_connect (progress, "cancel", + G_CALLBACK (gimp_gegl_apply_operation_cancel), + &cancel); + + progress_started = TRUE; + } } else { - rect = *GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (dest_buffer), - gegl_buffer_get_height (dest_buffer)); + cancelable = FALSE; + } + + gegl_buffer_freeze_changed (dest_buffer); + + underlying_operation = gimp_gegl_node_get_underlying_operation (operation); + + result_buffer = dest_buffer; + + if (result_buffer == src_buffer && + ! (gimp_gegl_node_is_point_operation (underlying_operation) || + gimp_gegl_node_is_source_operation (underlying_operation))) + { + /* Write the result to a temporary buffer, instead of directly to + * dest_buffer, since reading and writing the same buffer doesn't + * generally work with non-point ops when working in chunks. + * + * See bug #701875. + */ + + if (cache) + { + /* If we have a cache, use it directly as the temporary result + * buffer, and skip copying the cached results to result_buffer + * below. Instead, the cached results are copied together with the + * newly rendered results in a single step at the end of processing. + */ + + g_warn_if_fail (cache != dest_buffer); + + result_buffer = g_object_ref (cache); + + cache = NULL; + } + else + { + result_buffer = gegl_buffer_new ( + dest_rect, gegl_buffer_get_format (dest_buffer)); + } + } + + all_pixels = dest_rect->width * dest_rect->height; + done_pixels = 0; + + region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) dest_rect); + + if (n_valid_rects > 0) + { + gint i; + + for (i = 0; i < n_valid_rects; i++) + { + GeglRectangle valid_rect; + + if (! gegl_rectangle_intersect (&valid_rect, + &valid_rects[i], dest_rect)) + { + continue; + } + + if (cache) + { + gimp_gegl_buffer_copy ( + cache, &valid_rect, GEGL_ABYSS_NONE, + result_buffer, &valid_rect); + } + + cairo_region_subtract_rectangle (region, + (cairo_rectangle_int_t *) + &valid_rect); + + done_pixels += valid_rect.width * valid_rect.height; + + if (progress) + { + gimp_progress_set_value (progress, + (gdouble) done_pixels / + (gdouble) all_pixels); + } + } } gegl = gegl_node_new (); @@ -112,24 +228,21 @@ effect = operation; - if (src_buffer) + if (connect_src_buffer || crop_input) { GeglNode *src_node; - /* dup() because reading and writing the same buffer doesn't - * work with area ops when using a processor. See bug #701875. - */ - if (progress && (src_buffer == dest_buffer)) - src_buffer = gegl_buffer_dup (src_buffer); - else - g_object_ref (src_buffer); + operation_src_node = gegl_node_get_producer (operation, "input", NULL); - src_node = gegl_node_new_child (gegl, - "operation", "gegl:buffer-source", - "buffer", src_buffer, - NULL); + src_node = operation_src_node; - g_object_unref (src_buffer); + if (connect_src_buffer) + { + src_node = gegl_node_new_child (gegl, + "operation", "gegl:buffer-source", + "buffer", src_buffer, + NULL); + } if (crop_input) { @@ -137,10 +250,10 @@ crop_node = gegl_node_new_child (gegl, "operation", "gegl:crop", - "x", (gdouble) rect.x, - "y", (gdouble) rect.y, - "width", (gdouble) rect.width, - "height", (gdouble) rect.height, + "x", (gdouble) dest_rect->x, + "y", (gdouble) dest_rect->y, + "width", (gdouble) dest_rect->width, + "height", (gdouble) dest_rect->height, NULL); gegl_node_connect_to (src_node, "output", @@ -149,8 +262,6 @@ src_node = crop_node; } - operation_src_node = gegl_node_get_producer (operation, "input", NULL); - if (! gegl_node_has_pad (operation, "input")) { effect = gegl_node_new_child (gegl, @@ -167,132 +278,81 @@ dest_node = gegl_node_new_child (gegl, "operation", "gegl:write-buffer", - "buffer", dest_buffer, + "buffer", result_buffer, NULL); gegl_node_connect_to (effect, "output", dest_node, "input"); - if (progress) - { - processor = gegl_node_new_processor (dest_node, &rect); - - if (gimp_progress_is_active (progress)) - { - if (undo_desc) - gimp_progress_set_text_literal (progress, undo_desc); + iter = gimp_chunk_iterator_new (region); - progress_started = FALSE; - cancellable = FALSE; - } - else - { - gimp_progress_start (progress, cancellable, "%s", undo_desc); - - if (cancellable) - g_signal_connect (progress, "cancel", - G_CALLBACK (gimp_gegl_apply_operation_cancel), - &cancel); - - progress_started = TRUE; - } + if (progress && + /* avoid the interactive iteration interval for area filters (or meta ops + * that potentially involve area filters), since their processing speed + * tends to be sensitive to the chunk size. + */ + ! gimp_gegl_node_is_area_filter_operation (underlying_operation)) + { + /* we use a shorter iteration interval for interactive use (when there's + * progress indication), to stay responsive. + */ + gimp_chunk_iterator_set_interval ( + iter, + APPLY_OPERATION_INTERACTIVE_INTERVAL); } - - if (cache) + else { - cairo_region_t *region; - gint all_pixels; - gint done_pixels = 0; - gint n_rects; - gint i; - - region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect); + /* we use a longer iteration interval for non-interactive use (when + * there's no progress indication), or when applying an area filter (see + * above), as this generally allows for faster processing. we don't + * avoid chunking altogether, since *some* chunking is still desirable to + * reduce the space needed for intermediate results. + */ + gimp_chunk_iterator_set_interval ( + iter, + APPLY_OPERATION_NON_INTERACTIVE_INTERVAL); + } - all_pixels = rect.width * rect.height; + while (gimp_chunk_iterator_next (iter)) + { + GeglRectangle render_rect; - for (i = 0; i < n_valid_rects; i++) + if (cancelable) { - gimp_gegl_buffer_copy (cache, valid_rects + i, GEGL_ABYSS_NONE, - dest_buffer, valid_rects + i); - - cairo_region_subtract_rectangle (region, - (cairo_rectangle_int_t *) - valid_rects + i); - - done_pixels += valid_rects[i].width * valid_rects[i].height; + while (! cancel && g_main_context_pending (NULL)) + g_main_context_iteration (NULL, FALSE); - if (progress) - gimp_progress_set_value (progress, - (gdouble) done_pixels / - (gdouble) all_pixels); + if (cancel) + break; } - n_rects = cairo_region_num_rectangles (region); - - for (i = 0; ! cancel && (i < n_rects); i++) + while (gimp_chunk_iterator_get_rect (iter, &render_rect)) { - cairo_rectangle_int_t render_rect; + gint rect_pixels = render_rect.width * render_rect.height; - cairo_region_get_rectangle (region, i, &render_rect); + gegl_node_blit (dest_node, 1.0, &render_rect, NULL, NULL, 0, + GEGL_BLIT_DEFAULT); - if (progress) - { - gint rect_pixels = render_rect.width * render_rect.height; - -#ifdef REUSE_PROCESSOR - gegl_processor_set_rectangle (processor, - (GeglRectangle *) &render_rect); -#else - g_object_unref (processor); - processor = gegl_node_new_processor (dest_node, - (GeglRectangle *) &render_rect); -#endif - - while (! cancel && gegl_processor_work (processor, &value)) - { - gimp_progress_set_value (progress, - ((gdouble) done_pixels + - value * rect_pixels) / - (gdouble) all_pixels); - - if (cancellable) - while (! cancel && g_main_context_pending (NULL)) - g_main_context_iteration (NULL, FALSE); - } - - done_pixels += rect_pixels; - } - else - { - gegl_node_blit (dest_node, 1.0, (GeglRectangle *) &render_rect, - NULL, NULL, 0, GEGL_BLIT_DEFAULT); - } + done_pixels += rect_pixels; } - cairo_region_destroy (region); - } - else - { if (progress) { - while (! cancel && gegl_processor_work (processor, &value)) - { - gimp_progress_set_value (progress, value); - - if (cancellable) - while (! cancel && g_main_context_pending (NULL)) - g_main_context_iteration (NULL, FALSE); - } - } - else - { - gegl_node_blit (dest_node, 1.0, &rect, - NULL, NULL, 0, GEGL_BLIT_DEFAULT); + gimp_progress_set_value (progress, + (gdouble) done_pixels / + (gdouble) all_pixels); } } - if (processor) - g_object_unref (processor); + if (result_buffer != dest_buffer) + { + gimp_gegl_buffer_copy (result_buffer, dest_rect, GEGL_ABYSS_NONE, + dest_buffer, dest_rect); + + g_object_unref (result_buffer); + } + + gegl_buffer_thaw_changed (dest_buffer); g_object_unref (gegl); @@ -306,7 +366,7 @@ { gimp_progress_end (progress); - if (cancellable) + if (cancelable) g_signal_handlers_disconnect_by_func (progress, gimp_gegl_apply_operation_cancel, &cancel); @@ -374,12 +434,20 @@ GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, gdouble radius_x, - gdouble radius_y) + gdouble radius_y, + gboolean edge_lock) { + GaussianBlurAbyssPolicy abyss_policy; + g_return_if_fail (GEGL_IS_BUFFER (src_buffer)); g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); g_return_if_fail (GEGL_IS_BUFFER (dest_buffer)); + if (edge_lock) + abyss_policy = GAUSSIAN_BLUR_ABYSS_CLAMP; + else + abyss_policy = GAUSSIAN_BLUR_ABYSS_NONE; + /* 3.5 is completely magic and picked to visually match the old * gaussian_blur_region() on a crappy laptop display */ @@ -387,7 +455,8 @@ progress, undo_desc, dest_buffer, dest_rect, radius_x / 3.5, - radius_y / 3.5); + radius_y / 3.5, + abyss_policy); } void @@ -558,13 +627,14 @@ } void -gimp_gegl_apply_gaussian_blur (GeglBuffer *src_buffer, - GimpProgress *progress, - const gchar *undo_desc, - GeglBuffer *dest_buffer, - const GeglRectangle *dest_rect, - gdouble std_dev_x, - gdouble std_dev_y) +gimp_gegl_apply_gaussian_blur (GeglBuffer *src_buffer, + GimpProgress *progress, + const gchar *undo_desc, + GeglBuffer *dest_buffer, + const GeglRectangle *dest_rect, + gdouble std_dev_x, + gdouble std_dev_y, + GaussianBlurAbyssPolicy abyss_policy) { GeglNode *node; @@ -573,9 +643,10 @@ g_return_if_fail (GEGL_IS_BUFFER (dest_buffer)); node = gegl_node_new_child (NULL, - "operation", "gegl:gaussian-blur", - "std-dev-x", std_dev_x, - "std-dev-y", std_dev_y, + "operation", "gegl:gaussian-blur", + "std-dev-x", std_dev_x, + "std-dev-y", std_dev_y, + "abyss-policy", abyss_policy, NULL); gimp_gegl_apply_operation (src_buffer, progress, undo_desc, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-apply-operation.h gimp-2.10.14+om/app/gegl/gimp-gegl-apply-operation.h --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-apply-operation.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-apply-operation.h 2019-10-26 18:49:18.000000000 +0000 @@ -38,6 +38,7 @@ GimpProgress *progress, const gchar *undo_desc, GeglNode *operation, + gboolean connect_src_buffer, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, gboolean crop_input, @@ -69,7 +70,8 @@ GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, gdouble radius_x, - gdouble radius_y); + gdouble radius_y, + gboolean edge_lock); void gimp_gegl_apply_border (GeglBuffer *src_buffer, GimpProgress *progress, @@ -104,13 +106,21 @@ GeglBuffer *dest_buffer, const GeglRectangle *dest_rect); +/* UGLY: private enum of gegl:gaussian-blur */ +typedef enum +{ + GAUSSIAN_BLUR_ABYSS_NONE, + GAUSSIAN_BLUR_ABYSS_CLAMP +} GaussianBlurAbyssPolicy; + void gimp_gegl_apply_gaussian_blur (GeglBuffer *src_buffer, GimpProgress *progress, const gchar *undo_desc, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect, gdouble std_dev_x, - gdouble std_dev_y); + gdouble std_dev_y, + GaussianBlurAbyssPolicy abyss_policy); void gimp_gegl_apply_invert_gamma (GeglBuffer *src_buffer, GimpProgress *progress, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl.c gimp-2.10.14+om/app/gegl/gimp-gegl.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl.c 2019-10-26 18:49:18.000000000 +0000 @@ -23,6 +23,8 @@ #include #include +#include "libgimpconfig/gimpconfig.h" + #include "gimp-gegl-types.h" #include "config/gimpgeglconfig.h" @@ -35,12 +37,18 @@ #include "gimp-babl.h" #include "gimp-gegl.h" +#include -static void gimp_gegl_notify_tile_cache_size (GimpGeglConfig *config); -static void gimp_gegl_notify_num_processors (GimpGeglConfig *config); -static void gimp_gegl_notify_use_opencl (GimpGeglConfig *config); -#include +static void gimp_gegl_notify_temp_path (GimpGeglConfig *config); +static void gimp_gegl_notify_swap_path (GimpGeglConfig *config); +static void gimp_gegl_notify_swap_compression (GimpGeglConfig *config); +static void gimp_gegl_notify_tile_cache_size (GimpGeglConfig *config); +static void gimp_gegl_notify_num_processors (GimpGeglConfig *config); +static void gimp_gegl_notify_use_opencl (GimpGeglConfig *config); + + +/* public functions */ void gimp_gegl_init (Gimp *gimp) @@ -51,14 +59,31 @@ config = GIMP_GEGL_CONFIG (gimp->config); + /* make sure temp and swap directories exist */ + gimp_gegl_notify_temp_path (config); + gimp_gegl_notify_swap_path (config); + g_object_set (gegl_config (), - "tile-cache-size", (guint64) config->tile_cache_size, - "threads", config->num_processors, - "use-opencl", config->use_opencl, + "swap-compression", config->swap_compression, + "tile-cache-size", (guint64) config->tile_cache_size, + "threads", config->num_processors, + "use-opencl", config->use_opencl, NULL); gimp_parallel_init (gimp); + g_signal_connect (config, "notify::temp-path", + G_CALLBACK (gimp_gegl_notify_temp_path), + NULL); + g_signal_connect (config, "notify::swap-path", + G_CALLBACK (gimp_gegl_notify_swap_path), + NULL); + g_signal_connect (config, "notify::swap-compression", + G_CALLBACK (gimp_gegl_notify_swap_compression), + NULL); + g_signal_connect (config, "notify::num-processors", + G_CALLBACK (gimp_gegl_notify_num_processors), + NULL); g_signal_connect (config, "notify::tile-cache-size", G_CALLBACK (gimp_gegl_notify_tile_cache_size), NULL); @@ -82,6 +107,45 @@ gimp_parallel_exit (gimp); } + +/* private functions */ + +static void +gimp_gegl_notify_temp_path (GimpGeglConfig *config) +{ + GFile *file = gimp_file_new_for_config_path (config->temp_path, NULL); + + if (! g_file_query_exists (file, NULL)) + g_file_make_directory_with_parents (file, NULL, NULL); + + g_object_unref (file); +} + +static void +gimp_gegl_notify_swap_path (GimpGeglConfig *config) +{ + GFile *file = gimp_file_new_for_config_path (config->swap_path, NULL); + gchar *path = g_file_get_path (file); + + if (! g_file_query_exists (file, NULL)) + g_file_make_directory_with_parents (file, NULL, NULL); + + g_object_set (gegl_config (), + "swap", path, + NULL); + + g_free (path); + g_object_unref (file); +} + +static void +gimp_gegl_notify_swap_compression (GimpGeglConfig *config) +{ + g_object_set (gegl_config (), + "swap-compression", config->swap_compression, + NULL); +} + static void gimp_gegl_notify_tile_cache_size (GimpGeglConfig *config) { diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-loops.cc gimp-2.10.14+om/app/gegl/gimp-gegl-loops.cc --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-loops.cc 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-loops.cc 2019-10-26 18:49:18.000000000 +0000 @@ -24,8 +24,8 @@ #include #include -#define GEGL_ITERATOR2_API #include +#include extern "C" { @@ -41,13 +41,12 @@ #include "gimp-gegl-loops-sse2.h" #include "core/gimp-atomic.h" -#include "core/gimp-parallel.h" #include "core/gimp-utils.h" #include "core/gimpprogress.h" -#define MIN_PARALLEL_SUB_SIZE 64 -#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE) +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) #define SHIFTED_AREA(dest, src) \ const GeglRectangle dest##_area_ = { \ @@ -65,25 +64,73 @@ GeglBuffer *dest_buffer, const GeglRectangle *dest_rect) { + GeglRectangle real_dest_rect; + g_return_if_fail (GEGL_IS_BUFFER (src_buffer)); g_return_if_fail (GEGL_IS_BUFFER (dest_buffer)); + if (! src_rect) + src_rect = gegl_buffer_get_extent (src_buffer); + + if (! dest_rect) + dest_rect = src_rect; + + real_dest_rect = *dest_rect; + real_dest_rect.width = src_rect->width; + real_dest_rect.height = src_rect->height; + + dest_rect = &real_dest_rect; + if (gegl_buffer_get_format (src_buffer) == gegl_buffer_get_format (dest_buffer)) { + gboolean skip_abyss = FALSE; + GeglRectangle src_abyss; + GeglRectangle dest_abyss; + + if (abyss_policy == GEGL_ABYSS_NONE) + { + src_abyss = *gegl_buffer_get_abyss (src_buffer); + dest_abyss = *gegl_buffer_get_abyss (dest_buffer); + + skip_abyss = ! (gegl_rectangle_contains (&src_abyss, src_rect) && + gegl_rectangle_contains (&dest_abyss, dest_rect)); + } + + if (skip_abyss) + { + if (src_buffer < dest_buffer) + { + gegl_tile_handler_lock (GEGL_TILE_HANDLER (src_buffer)); + gegl_tile_handler_lock (GEGL_TILE_HANDLER (dest_buffer)); + } + else + { + gegl_tile_handler_lock (GEGL_TILE_HANDLER (dest_buffer)); + gegl_tile_handler_lock (GEGL_TILE_HANDLER (src_buffer)); + } + + gegl_buffer_set_abyss (src_buffer, src_rect); + gegl_buffer_set_abyss (dest_buffer, dest_rect); + } + gegl_buffer_copy (src_buffer, src_rect, abyss_policy, dest_buffer, dest_rect); + + if (skip_abyss) + { + gegl_buffer_set_abyss (src_buffer, &src_abyss); + gegl_buffer_set_abyss (dest_buffer, &dest_abyss); + + gegl_tile_handler_unlock (GEGL_TILE_HANDLER (src_buffer)); + gegl_tile_handler_unlock (GEGL_TILE_HANDLER (dest_buffer)); + } } else { - if (! src_rect) - src_rect = gegl_buffer_get_extent (src_buffer); - - if (! dest_rect) - dest_rect = src_rect; - - gimp_parallel_distribute_area (src_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *src_area) + gegl_parallel_distribute_area ( + src_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *src_area) { SHIFTED_AREA (dest, src); @@ -94,6 +141,58 @@ } void +gimp_gegl_clear (GeglBuffer *buffer, + const GeglRectangle *rect) +{ + const Babl *format; + gint bpp; + gint n_components; + gint bpc; + gint alpha_offset; + + g_return_if_fail (GEGL_IS_BUFFER (buffer)); + + if (! rect) + rect = gegl_buffer_get_extent (buffer); + + format = gegl_buffer_get_format (buffer); + + if (! babl_format_has_alpha (format)) + return; + + bpp = babl_format_get_bytes_per_pixel (format); + n_components = babl_format_get_n_components (format); + bpc = bpp / n_components; + alpha_offset = (n_components - 1) * bpc; + + gegl_parallel_distribute_area ( + rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) + { + GeglBufferIterator *iter; + + iter = gegl_buffer_iterator_new (buffer, area, 0, format, + GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, + 1); + + while (gegl_buffer_iterator_next (iter)) + { + guint8 *data = (guint8 *) iter->items[0].data; + gint i; + + data += alpha_offset; + + for (i = 0; i < iter->length; i++) + { + memset (data, 0, bpc); + + data += bpp; + } + } + }); +} + +void gimp_gegl_convolve (GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dest_buffer, @@ -161,8 +260,9 @@ offset = 0.0; } - gimp_parallel_distribute_area (dest_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *dest_area) + gegl_parallel_distribute_area ( + dest_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *dest_area) { const gint components = src_components; const gint a_component = components - 1; @@ -313,8 +413,9 @@ if (! dest_rect) dest_rect = gegl_buffer_get_extent (dest_buffer); - gimp_parallel_distribute_area (src_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *src_area) + gegl_parallel_distribute_area ( + src_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *src_area) { GeglBufferIterator *iter; @@ -527,8 +628,10 @@ GeglAccessMode paint_buffer_access_mode = (brush_color ? GEGL_ACCESS_WRITE : GEGL_ACCESS_READWRITE); +#if COMPILE_SSE2_INTRINISICS gboolean sse2 = (gimp_cpu_accel_get_support () & GIMP_CPU_ACCEL_X86_SSE2); +#endif if (! accum_rect) accum_rect = gegl_buffer_get_extent (accum_buffer); @@ -548,8 +651,9 @@ brush_a *= brush_color_ptr[3]; } - gimp_parallel_distribute_area (accum_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *accum_area) + gegl_parallel_distribute_area ( + accum_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *accum_area) { GeglBufferIterator *iter; @@ -616,8 +720,9 @@ if (! dest_rect) dest_rect = gegl_buffer_get_extent (dest_buffer); - gimp_parallel_distribute_area (mask_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *mask_area) + gegl_parallel_distribute_area ( + mask_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *mask_area) { GeglBufferIterator *iter; @@ -661,8 +766,9 @@ if (! dest_rect) dest_rect = gegl_buffer_get_extent (dest_buffer); - gimp_parallel_distribute_area (mask_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *mask_area) + gegl_parallel_distribute_area ( + mask_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *mask_area) { GeglBufferIterator *iter; @@ -707,8 +813,9 @@ if (! dest_rect) dest_rect = gegl_buffer_get_extent (dest_buffer); - gimp_parallel_distribute_area (mask_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *mask_area) + gegl_parallel_distribute_area ( + mask_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *mask_area) { GeglBufferIterator *iter; @@ -754,132 +861,6 @@ } void -gimp_gegl_replace (GeglBuffer *top_buffer, - const GeglRectangle *top_rect, - GeglBuffer *bottom_buffer, - const GeglRectangle *bottom_rect, - GeglBuffer *mask_buffer, - const GeglRectangle *mask_rect, - GeglBuffer *dest_buffer, - const GeglRectangle *dest_rect, - gdouble opacity, - const gboolean *affect) -{ - if (! top_rect) - top_rect = gegl_buffer_get_extent (top_buffer); - - if (! bottom_rect) - bottom_rect = gegl_buffer_get_extent (bottom_buffer); - - if (! mask_rect) - mask_rect = gegl_buffer_get_extent (mask_buffer); - - if (! dest_rect) - dest_rect = gegl_buffer_get_extent (dest_buffer); - - gimp_parallel_distribute_area (top_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *top_area) - { - GeglBufferIterator *iter; - - SHIFTED_AREA (bottom, top); - SHIFTED_AREA (mask, top); - SHIFTED_AREA (dest, top); - - iter = gegl_buffer_iterator_new (top_buffer, top_area, 0, - babl_format ("RGBA float"), - GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 4); - - gegl_buffer_iterator_add (iter, bottom_buffer, bottom_area, 0, - babl_format ("RGBA float"), - GEGL_ACCESS_READ, GEGL_ABYSS_NONE); - - gegl_buffer_iterator_add (iter, mask_buffer, mask_area, 0, - babl_format ("Y float"), - GEGL_ACCESS_READ, GEGL_ABYSS_NONE); - - gegl_buffer_iterator_add (iter, dest_buffer, dest_area, 0, - babl_format ("RGBA float"), - GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); - - while (gegl_buffer_iterator_next (iter)) - { - const gfloat *top = (const gfloat *) iter->items[0].data; - const gfloat *bottom = (const gfloat *) iter->items[1].data; - const gfloat *mask = (const gfloat *) iter->items[2].data; - gfloat *dest = (gfloat *) iter->items[3].data; - gint count = iter->length; - - while (count--) - { - gint b; - gdouble mask_val = *mask * opacity; - - /* calculate new alpha first. */ - gfloat s1_a = bottom[3]; - gfloat s2_a = top[3]; - gdouble a_val = s1_a + mask_val * (s2_a - s1_a); - - if (a_val == 0.0) - { - /* In any case, write out versions of the blending - * function that result when combinations of s1_a, s2_a, - * and mask_val --> 0 (or mask_val -->1) - */ - - /* 1: s1_a, s2_a, AND mask_val all approach 0+: */ - /* 2: s1_a AND s2_a both approach 0+, regardless of mask_val: */ - if (s1_a + s2_a == 0.0) - { - for (b = 0; b < 3; b++) - { - gfloat new_val; - - new_val = bottom[b] + mask_val * (top[b] - bottom[b]); - - dest[b] = affect[b] ? new_val : bottom[b]; - } - } - - /* 3: mask_val AND s1_a both approach 0+, regardless of s2_a */ - else if (s1_a + mask_val == 0.0) - { - for (b = 0; b < 3; b++) - dest[b] = bottom[b]; - } - - /* 4: mask_val -->1 AND s2_a -->0, regardless of s1_a */ - else if (1.0 - mask_val + s2_a == 0.0) - { - for (b = 0; b < 3; b++) - dest[b] = affect[b] ? top[b] : bottom[b]; - } - } - else - { - gdouble a_recip = 1.0 / a_val; - - /* possible optimization: fold a_recip into s1_a and s2_a */ - for (b = 0; b < 3; b++) - { - gfloat new_val = a_recip * (bottom[b] * s1_a + mask_val * - (top[b] * s2_a - bottom[b] * s1_a)); - dest[b] = affect[b] ? new_val : bottom[b]; - } - } - - dest[3] = affect[3] ? a_val : s1_a; - - top += 4; - bottom += 4; - mask += 1; - dest += 4; - } - } - }); -} - -void gimp_gegl_index_to_mask (GeglBuffer *indexed_buffer, const GeglRectangle *indexed_rect, const Babl *indexed_format, @@ -893,8 +874,9 @@ if (! mask_rect) mask_rect = gegl_buffer_get_extent (mask_buffer); - gimp_parallel_distribute_area (indexed_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *indexed_area) + gegl_parallel_distribute_area ( + indexed_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *indexed_area) { GeglBufferIterator *iter; @@ -983,8 +965,9 @@ GIMP_TIMER_START (); - gimp_parallel_distribute_area (src_rect, MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *src_area) + gegl_parallel_distribute_area ( + src_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *src_area) { SHIFTED_AREA (dest, src); @@ -1042,8 +1025,9 @@ else roi = *rect; - gimp_parallel_distribute_area (&roi, MIN_PARALLEL_SUB_AREA, - [&] (const GeglRectangle *area) + gegl_parallel_distribute_area ( + &roi, PIXELS_PER_THREAD, + [&] (const GeglRectangle *area) { Sum *sum; GeglBufferIterator *iter; diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-loops.h gimp-2.10.14+om/app/gegl/gimp-gegl-loops.h --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-loops.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-loops.h 2019-04-07 11:38:14.000000000 +0000 @@ -28,6 +28,9 @@ GeglBuffer *dest_buffer, const GeglRectangle *dest_rect); +void gimp_gegl_clear (GeglBuffer *buffer, + const GeglRectangle *rect); + /* this is a pretty stupid port of concolve_region() that only works * on a linear source buffer */ @@ -78,17 +81,6 @@ gdouble opacity, gboolean stipple); -void gimp_gegl_replace (GeglBuffer *top_buffer, - const GeglRectangle *top_rect, - GeglBuffer *bottom_buffer, - const GeglRectangle *bottom_rect, - GeglBuffer *mask_buffer, - const GeglRectangle *mask_rect, - GeglBuffer *dest_buffer, - const GeglRectangle *dest_rect, - gdouble opacity, - const gboolean *affect); - void gimp_gegl_index_to_mask (GeglBuffer *indexed_buffer, const GeglRectangle *indexed_rect, const Babl *indexed_format, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask.c gimp-2.10.14+om/app/gegl/gimp-gegl-mask.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-mask.c 2019-10-26 18:49:18.000000000 +0000 @@ -17,7 +17,6 @@ #include "config.h" -#define GEGL_ITERATOR2_API #include #include "gimp-gegl-types.h" @@ -32,9 +31,12 @@ gint *x2, gint *y2) { - GeglBufferIterator *iter; - GeglRectangle *roi; - gint tx1, tx2, ty1, ty2; + GeglBufferIterator *iter; + const GeglRectangle *extent; + const GeglRectangle *roi; + const Babl *format; + gint bpp; + gint tx1, tx2, ty1, ty2; g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE); g_return_val_if_fail (x1 != NULL, FALSE); @@ -42,23 +44,26 @@ g_return_val_if_fail (x2 != NULL, FALSE); g_return_val_if_fail (y2 != NULL, FALSE); + extent = gegl_buffer_get_extent (buffer); + /* go through and calculate the bounds */ - tx1 = gegl_buffer_get_width (buffer); - ty1 = gegl_buffer_get_height (buffer); - tx2 = 0; - ty2 = 0; + tx1 = extent->x + extent->width; + ty1 = extent->y + extent->height; + tx2 = extent->x; + ty2 = extent->y; + + format = gegl_buffer_get_format (buffer); + bpp = babl_format_get_bytes_per_pixel (format); - iter = gegl_buffer_iterator_new (buffer, NULL, 0, babl_format ("Y float"), + iter = gegl_buffer_iterator_new (buffer, NULL, 0, format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1); roi = &iter->items[0].roi; while (gegl_buffer_iterator_next (iter)) { - gfloat *data = iter->items[0].data; - gfloat *data1 = data; - gint ex = roi->x + roi->width; - gint ey = roi->y + roi->height; - gint x, y; + const guint8 *data_u8 = iter->items[0].data; + gint ex = roi->x + roi->width; + gint ey = roi->y + roi->height; /* only check the pixels if this tile is not fully within the * currently computed bounds @@ -69,7 +74,8 @@ /* Check upper left and lower right corners to see if we can * avoid checking the rest of the pixels in this tile */ - if (data[0] && data[iter->length - 1]) + if (! gegl_memeq_zero (data_u8, bpp) && + ! gegl_memeq_zero (data_u8 + (iter->length - 1) * bpp, bpp)) { /* "ex/ey - 1" because the internal variables are the * right/bottom pixel of the mask's contents, not one @@ -84,27 +90,114 @@ } else { - for (y = roi->y; y < ey; y++, data1 += roi->width) + #define FIND_BOUNDS(bpp, type) \ + G_STMT_START \ + { \ + const type *data; \ + gint y; \ + \ + if ((guintptr) data_u8 % bpp) \ + goto generic; \ + \ + data = (const type *) data_u8; \ + \ + for (y = roi->y; y < ey; y++) \ + { \ + gint x1; \ + \ + for (x1 = 0; x1 < roi->width; x1++) \ + { \ + if (data[x1]) \ + { \ + gint x2; \ + gint x2_end = MAX (x1, tx2 - roi->x); \ + \ + for (x2 = roi->width - 1; x2 > x2_end; x2--) \ + { \ + if (data[x2]) \ + break; \ + } \ + \ + x1 += roi->x; \ + x2 += roi->x; \ + \ + if (x1 < tx1) tx1 = x1; \ + if (x2 > tx2) tx2 = x2; \ + \ + if (y < ty1) ty1 = y; \ + if (y > ty2) ty2 = y; \ + \ + break; \ + } \ + } \ + \ + data += roi->width; \ + } \ + } \ + G_STMT_END + + switch (bpp) { - for (x = roi->x, data = data1; x < ex; x++, data++) - { - if (*data) - { - gint minx = x; - gint maxx = x; - - for (; x < ex; x++, data++) - if (*data) - maxx = x; - - if (minx < tx1) tx1 = minx; - if (maxx > tx2) tx2 = maxx; - - if (y < ty1) ty1 = y; - if (y > ty2) ty2 = y; - } - } + case 1: + FIND_BOUNDS (1, guint8); + break; + + case 2: + FIND_BOUNDS (2, guint16); + break; + + case 4: + FIND_BOUNDS (4, guint32); + break; + + case 8: + FIND_BOUNDS (8, guint64); + break; + + default: + generic: + { + const guint8 *data = data_u8; + gint y; + + for (y = roi->y; y < ey; y++) + { + gint x1; + + for (x1 = 0; x1 < roi->width; x1++) + { + if (! gegl_memeq_zero (data + x1 * bpp, bpp)) + { + gint x2; + gint x2_end = MAX (x1, tx2 - roi->x); + + for (x2 = roi->width - 1; x2 > x2_end; x2--) + { + if (! gegl_memeq_zero (data + x2 * bpp, + bpp)) + { + break; + } + } + + x1 += roi->x; + x2 += roi->x; + + if (x1 < tx1) tx1 = x1; + if (x2 > tx2) tx2 = x2; + + if (y < ty1) ty1 = y; + if (y > ty2) ty2 = y; + } + } + + data += roi->width * bpp; + } + } + break; } + + #undef FIND_BOUNDS } } } @@ -135,25 +228,24 @@ gimp_gegl_mask_is_empty (GeglBuffer *buffer) { GeglBufferIterator *iter; + const Babl *format; + gint bpp; g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE); - iter = gegl_buffer_iterator_new (buffer, NULL, 0, babl_format ("Y float"), + format = gegl_buffer_get_format (buffer); + bpp = babl_format_get_bytes_per_pixel (format); + + iter = gegl_buffer_iterator_new (buffer, NULL, 0, format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE, 1); while (gegl_buffer_iterator_next (iter)) { - gfloat *data = iter->items[0].data; - gint i; - - for (i = 0; i < iter->length; i++) + if (! gegl_memeq_zero (iter->items[0].data, bpp * iter->length)) { - if (data[i]) - { - gegl_buffer_iterator_stop (iter); + gegl_buffer_iterator_stop (iter); - return FALSE; - } + return FALSE; } } diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.c gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,502 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include - -#include -#define GEGL_ITERATOR2_API -#include - -#include "libgimpbase/gimpbase.h" -#include "libgimpmath/gimpmath.h" - -#include "gimp-gegl-types.h" - -#include "gimp-babl.h" -#include "gimp-gegl-mask-combine.h" - - -gboolean -gimp_gegl_mask_combine_rect (GeglBuffer *mask, - GimpChannelOps op, - gint x, - gint y, - gint w, - gint h) -{ - GeglColor *color; - - g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); - - if (! gimp_rectangle_intersect (x, y, w, h, - 0, 0, - gegl_buffer_get_width (mask), - gegl_buffer_get_height (mask), - &x, &y, &w, &h)) - return FALSE; - - if (op == GIMP_CHANNEL_OP_ADD || op == GIMP_CHANNEL_OP_REPLACE) - color = gegl_color_new ("#fff"); - else - color = gegl_color_new ("#000"); - - gegl_buffer_set_color (mask, GEGL_RECTANGLE (x, y, w, h), color); - g_object_unref (color); - - return TRUE; -} - -/** - * gimp_gegl_mask_combine_ellipse: - * @mask: the channel with which to combine the ellipse - * @op: whether to replace, add to, or subtract from the current - * contents - * @x: x coordinate of upper left corner of ellipse - * @y: y coordinate of upper left corner of ellipse - * @w: width of ellipse bounding box - * @h: height of ellipse bounding box - * @antialias: if %TRUE, antialias the ellipse - * - * Mainly used for elliptical selections. If @op is - * %GIMP_CHANNEL_OP_REPLACE or %GIMP_CHANNEL_OP_ADD, sets pixels - * within the ellipse to 255. If @op is %GIMP_CHANNEL_OP_SUBTRACT, - * sets pixels within to zero. If @antialias is %TRUE, pixels that - * impinge on the edge of the ellipse are set to intermediate values, - * depending on how much they overlap. - **/ -gboolean -gimp_gegl_mask_combine_ellipse (GeglBuffer *mask, - GimpChannelOps op, - gint x, - gint y, - gint w, - gint h, - gboolean antialias) -{ - return gimp_gegl_mask_combine_ellipse_rect (mask, op, x, y, w, h, - w / 2.0, h / 2.0, antialias); -} - -static void -gimp_gegl_mask_combine_span (gfloat *data, - GimpChannelOps op, - gint x1, - gint x2, - gfloat value) -{ - if (x2 <= x1) - return; - - switch (op) - { - case GIMP_CHANNEL_OP_ADD: - case GIMP_CHANNEL_OP_REPLACE: - if (value == 1.0) - { - while (x1 < x2) - data[x1++] = 1.0; - } - else - { - while (x1 < x2) - { - const gfloat val = data[x1] + value; - data[x1++] = val > 1.0 ? 1.0 : val; - } - } - break; - - case GIMP_CHANNEL_OP_SUBTRACT: - if (value == 1.0) - { - while (x1 < x2) - data[x1++] = 0.0; - } - else - { - while (x1 < x2) - { - const gfloat val = data[x1] - value; - data[x1++] = val > 0.0 ? val : 0.0; - } - } - break; - - case GIMP_CHANNEL_OP_INTERSECT: - /* Should not happen */ - break; - } -} - -/** - * gimp_gegl_mask_combine_ellipse_rect: - * @mask: the channel with which to combine the elliptic rect - * @op: whether to replace, add to, or subtract from the current - * contents - * @x: x coordinate of upper left corner of bounding rect - * @y: y coordinate of upper left corner of bounding rect - * @w: width of bounding rect - * @h: height of bounding rect - * @a: elliptic a-constant applied to corners - * @b: elliptic b-constant applied to corners - * @antialias: if %TRUE, antialias the elliptic corners - * - * Used for rounded cornered rectangles and ellipses. If @op is - * %GIMP_CHANNEL_OP_REPLACE or %GIMP_CHANNEL_OP_ADD, sets pixels - * within the ellipse to 255. If @op is %GIMP_CHANNEL_OP_SUBTRACT, - * sets pixels within to zero. If @antialias is %TRUE, pixels that - * impinge on the edge of the ellipse are set to intermediate values, - * depending on how much they overlap. - **/ -gboolean -gimp_gegl_mask_combine_ellipse_rect (GeglBuffer *mask, - GimpChannelOps op, - gint x, - gint y, - gint w, - gint h, - gdouble a, - gdouble b, - gboolean antialias) -{ - GeglBufferIterator *iter; - GeglRectangle *roi; - gdouble a_sqr; - gdouble b_sqr; - gdouble ellipse_center_x; - gint x0, y0; - gint width, height; - - g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); - g_return_val_if_fail (a >= 0.0 && b >= 0.0, FALSE); - g_return_val_if_fail (op != GIMP_CHANNEL_OP_INTERSECT, FALSE); - - /* Make sure the elliptic corners fit into the rect */ - a = MIN (a, w / 2.0); - b = MIN (b, h / 2.0); - - a_sqr = SQR (a); - b_sqr = SQR (b); - - if (! gimp_rectangle_intersect (x, y, w, h, - 0, 0, - gegl_buffer_get_width (mask), - gegl_buffer_get_height (mask), - &x0, &y0, &width, &height)) - return FALSE; - - ellipse_center_x = x + a; - - iter = gegl_buffer_iterator_new (mask, - GEGL_RECTANGLE (x0, y0, width, height), 0, - babl_format ("Y float"), - GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 1); - roi = &iter->items[0].roi; - - while (gegl_buffer_iterator_next (iter)) - { - gfloat *data = iter->items[0].data; - gint py; - - for (py = roi->y; - py < roi->y + roi->height; - py++, data += roi->width) - { - const gint px = roi->x; - gdouble ellipse_center_y; - - if (py >= y + b && py < y + h - b) - { - /* we are on a row without rounded corners */ - gimp_gegl_mask_combine_span (data, op, 0, roi->width, 1.0); - continue; - } - - /* Match the ellipse center y with our current y */ - if (py < y + b) - { - ellipse_center_y = y + b; - } - else - { - ellipse_center_y = y + h - b; - } - - /* For a non-antialiased ellipse, use the normal equation - * for an ellipse with an arbitrary center - * (ellipse_center_x, ellipse_center_y). - */ - if (! antialias) - { - gdouble half_ellipse_width_at_y; - gint x_start; - gint x_end; - - half_ellipse_width_at_y = - sqrt (a_sqr - - a_sqr * SQR (py + 0.5f - ellipse_center_y) / b_sqr); - - x_start = ROUND (ellipse_center_x - half_ellipse_width_at_y); - x_end = ROUND (ellipse_center_x + w - 2 * a + - half_ellipse_width_at_y); - - gimp_gegl_mask_combine_span (data, op, - MAX (x_start - px, 0), - MIN (x_end - px, roi->width), 1.0); - } - else /* use antialiasing */ - { - /* algorithm changed 7-18-04, because the previous one - * did not work well for eccentric ellipses. The new - * algorithm measures the distance to the ellipse in the - * X and Y directions, and uses trigonometry to - * approximate the distance to the ellipse as the - * distance to the hypotenuse of a right triangle whose - * legs are the X and Y distances. (WES) - */ - const gfloat yi = ABS (py + 0.5 - ellipse_center_y); - gfloat last_val = -1; - gint x_start = px; - gint cur_x; - - for (cur_x = px; cur_x < (px + roi->width); cur_x++) - { - gfloat xj; - gfloat xdist; - gfloat ydist; - gfloat r; - gfloat dist; - gfloat val; - - if (cur_x < x + w / 2) - { - ellipse_center_x = x + a; - } - else - { - ellipse_center_x = x + w - a; - } - - xj = ABS (cur_x + 0.5 - ellipse_center_x); - - if (yi < b) - xdist = xj - a * sqrt (1 - SQR (yi) / b_sqr); - else - xdist = 1000.0; /* anything large will work */ - - if (xj < a) - ydist = yi - b * sqrt (1 - SQR (xj) / a_sqr); - else - ydist = 1000.0; /* anything large will work */ - - r = hypot (xdist, ydist); - - if (r < 0.001) - dist = 0.0; - else - dist = xdist * ydist / r; /* trig formula for distance to - * hypotenuse - */ - - if (xdist < 0.0) - dist *= -1; - - if (dist < -0.5) - val = 1.0; - else if (dist < 0.5) - val = (1.0 - (dist + 0.5)); - else - val = 0.0; - - if (last_val != val) - { - if (last_val != -1) - gimp_gegl_mask_combine_span (data, op, - MAX (x_start - px, 0), - MIN (cur_x - px, roi->width), - last_val); - - x_start = cur_x; - last_val = val; - } - - /* skip ahead if we are on the straight segment - * between rounded corners - */ - if (cur_x >= x + a && cur_x < x + w - a) - { - gimp_gegl_mask_combine_span (data, op, - MAX (x_start - px, 0), - MIN (cur_x - px, roi->width), - last_val); - - x_start = cur_x; - cur_x = x + w - a; - last_val = val = 1.0; - } - - /* Time to change center? */ - if (cur_x >= x + w / 2) - { - ellipse_center_x = x + w - a; - } - } - - gimp_gegl_mask_combine_span (data, op, - MAX (x_start - px, 0), - MIN (cur_x - px, roi->width), - last_val); - } - } - } - - return TRUE; -} - -gboolean -gimp_gegl_mask_combine_buffer (GeglBuffer *mask, - GeglBuffer *add_on, - GimpChannelOps op, - gint off_x, - gint off_y) -{ - GeglBufferIterator *iter; - GeglRectangle rect; - const Babl *mask_format; - const Babl *add_on_format; - gint x, y, w, h; - - g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); - g_return_val_if_fail (GEGL_IS_BUFFER (add_on), FALSE); - - if (! gimp_rectangle_intersect (off_x, off_y, - gegl_buffer_get_width (add_on), - gegl_buffer_get_height (add_on), - 0, 0, - gegl_buffer_get_width (mask), - gegl_buffer_get_height (mask), - &x, &y, &w, &h)) - return FALSE; - - rect.x = x; - rect.y = y; - rect.width = w; - rect.height = h; - - /* See below: this additional hack is only needed for the - * gimp-channel-combine-masks procedure, it's the only place that - * allows to combine arbitrary channels with each other. - */ - if (gimp_babl_format_get_linear (gegl_buffer_get_format (mask))) - mask_format = babl_format ("Y float"); - else - mask_format = babl_format ("Y' float"); - - iter = gegl_buffer_iterator_new (mask, &rect, 0, - mask_format, - GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE, 2); - - rect.x -= off_x; - rect.y -= off_y; - - /* This is a hack: all selections/layer masks/channels are always - * linear except for channels in 8-bit images. We don't want these - * "Y' u8" to be converted to "Y float" because that would cause a - * gamma canversion and give unexpected results for - * "add/subtract/etc channel from selection". Instead, use all - * channel values "as-is", which makes no differce except in the - * 8-bit case where we need it. - * - * See https://bugzilla.gnome.org/show_bug.cgi?id=791519 - */ - if (gimp_babl_format_get_linear (gegl_buffer_get_format (add_on))) - add_on_format = babl_format ("Y float"); - else - add_on_format = babl_format ("Y' float"); - - gegl_buffer_iterator_add (iter, add_on, &rect, 0, - add_on_format, - GEGL_ACCESS_READ, GEGL_ABYSS_NONE); - - switch (op) - { - case GIMP_CHANNEL_OP_ADD: - case GIMP_CHANNEL_OP_REPLACE: - while (gegl_buffer_iterator_next (iter)) - { - gfloat *mask_data = iter->items[0].data; - const gfloat *add_on_data = iter->items[1].data; - gint count = iter->length; - - while (count--) - { - const gfloat val = *mask_data + *add_on_data; - - *mask_data = CLAMP (val, 0.0, 1.0); - - add_on_data++; - mask_data++; - } - } - break; - - case GIMP_CHANNEL_OP_SUBTRACT: - while (gegl_buffer_iterator_next (iter)) - { - gfloat *mask_data = iter->items[0].data; - const gfloat *add_on_data = iter->items[1].data; - gint count = iter->length; - - while (count--) - { - if (*add_on_data > *mask_data) - *mask_data = 0.0; - else - *mask_data -= *add_on_data; - - add_on_data++; - mask_data++; - } - } - break; - - case GIMP_CHANNEL_OP_INTERSECT: - while (gegl_buffer_iterator_next (iter)) - { - gfloat *mask_data = iter->items[0].data; - const gfloat *add_on_data = iter->items[1].data; - gint count = iter->length; - - while (count--) - { - *mask_data = MIN (*mask_data, *add_on_data); - - add_on_data++; - mask_data++; - } - } - break; - - default: - g_warning ("%s: unknown operation type", G_STRFUNC); - break; - } - - return TRUE; -} diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.cc gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.cc --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.cc 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.cc 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,652 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +#include +#include + +#include "libgimpbase/gimpbase.h" +#include "libgimpmath/gimpmath.h" + +extern "C" +{ + +#include "gimp-gegl-types.h" + +#include "gimp-babl.h" +#include "gimp-gegl-loops.h" +#include "gimp-gegl-mask-combine.h" + + +#define EPSILON 1e-6 + +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) + + +gboolean +gimp_gegl_mask_combine_rect (GeglBuffer *mask, + GimpChannelOps op, + gint x, + gint y, + gint w, + gint h) +{ + GeglRectangle rect; + gfloat value; + + g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); + + if (! gegl_rectangle_intersect (&rect, + GEGL_RECTANGLE (x, y, w, h), + gegl_buffer_get_abyss (mask))) + { + return FALSE; + } + + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + case GIMP_CHANNEL_OP_ADD: + value = 1.0f; + break; + + case GIMP_CHANNEL_OP_SUBTRACT: + value = 0.0f; + break; + + case GIMP_CHANNEL_OP_INTERSECT: + return TRUE; + } + + gegl_buffer_set_color_from_pixel (mask, &rect, &value, + babl_format ("Y float")); + + return TRUE; +} + +gboolean +gimp_gegl_mask_combine_ellipse (GeglBuffer *mask, + GimpChannelOps op, + gint x, + gint y, + gint w, + gint h, + gboolean antialias) +{ + return gimp_gegl_mask_combine_ellipse_rect (mask, op, x, y, w, h, + w / 2.0, h / 2.0, antialias); +} + +gboolean +gimp_gegl_mask_combine_ellipse_rect (GeglBuffer *mask, + GimpChannelOps op, + gint x, + gint y, + gint w, + gint h, + gdouble rx, + gdouble ry, + gboolean antialias) +{ + GeglRectangle rect; + const Babl *format; + gint bpp; + gfloat one_f = 1.0f; + gpointer one; + gdouble cx; + gdouble cy; + gint left; + gint right; + gint top; + gint bottom; + + g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); + + if (rx <= EPSILON || ry <= EPSILON) + return gimp_gegl_mask_combine_rect (mask, op, x, y, w, h); + + left = x; + right = x + w; + top = y; + bottom = y + h; + + cx = (left + right) / 2.0; + cy = (top + bottom) / 2.0; + + rx = MIN (rx, w / 2.0); + ry = MIN (ry, h / 2.0); + + if (! gegl_rectangle_intersect (&rect, + GEGL_RECTANGLE (x, y, w, h), + gegl_buffer_get_abyss (mask))) + { + return FALSE; + } + + format = gegl_buffer_get_format (mask); + + if (antialias) + { + format = gimp_babl_format_change_component_type ( + format, GIMP_COMPONENT_TYPE_FLOAT); + } + + bpp = babl_format_get_bytes_per_pixel (format); + one = g_alloca (bpp); + + babl_process (babl_fish ("Y float", format), &one_f, one, 1); + + /* coordinate-system transforms. (x, y) coordinates are in the image + * coordinate-system, and (u, v) coordinates are in a coordinate-system + * aligned with the center of one of the elliptic corners, with the positive + * directions pointing away from the rectangle. when converting from (x, y) + * to (u, v), we use the closest elliptic corner. + */ + auto x_to_u = [=] (gdouble x) + { + if (x < cx) + return (left + rx) - x; + else + return x - (right - rx); + }; + + auto y_to_v = [=] (gdouble y) + { + if (y < cy) + return (top + ry) - y; + else + return y - (bottom - ry); + }; + + auto u_to_x_left = [=] (gdouble u) + { + return (left + rx) - u; + }; + + auto u_to_x_right = [=] (gdouble u) + { + return (right - rx) + u; + }; + + /* intersection of a horizontal line with the ellipse */ + auto v_to_u = [=] (gdouble v) + { + if (v > 0.0) + return sqrt (MAX (SQR (rx) - SQR (rx * v / ry), 0.0)); + else + return rx; + }; + + /* intersection of a vertical line with the ellipse */ + auto u_to_v = [=] (gdouble u) + { + if (u > 0.0) + return sqrt (MAX (SQR (ry) - SQR (ry * u / rx), 0.0)); + else + return ry; + }; + + /* signed, normalized distance of a point from the ellipse's circumference. + * the sign of the result determines if the point is inside (positive) or + * outside (negative) the ellipse. the result is normalized to the cross- + * section length of a pixel, in the direction of the closest point along the + * ellipse. + * + * we use the following method to approximate the distance: pass horizontal + * and vertical lines at the given point, P, and find their (positive) points + * of intersection with the ellipse, A and B. the segment AB is an + * approximation of the corresponding elliptic arc (see bug #147836). find + * the closest point, C, to P, along the segment AB. find the (positive) + * point of intersection, Q, of the line PC and the ellipse. Q is an + * approximation for the closest point to P along the ellipse, and the + * approximated distance is the distance from P to Q. + */ + auto ellipse_distance = [=] (gdouble u, + gdouble v) + { + gdouble du; + gdouble dv; + gdouble t; + gdouble a, b, c; + gdouble d; + + u = MAX (u, 0.0); + v = MAX (v, 0.0); + + du = v_to_u (v) - u; + dv = u_to_v (u) - v; + + t = SQR (du) / (SQR (du) + SQR (dv)); + + du *= 1.0 - t; + dv *= t; + + v *= rx / ry; + dv *= rx / ry; + + a = SQR (du) + SQR (dv); + b = u * du + v * dv; + c = SQR (u) + SQR (v) - SQR (rx); + + if (a <= EPSILON) + return 0.0; + + if (c < 0.0) + t = (-b + sqrt (MAX (SQR (b) - a * c, 0.0))) / a; + else + t = (-b - sqrt (MAX (SQR (b) - a * c, 0.0))) / a; + + dv *= ry / rx; + + d = sqrt (SQR (du * t) + SQR (dv * t)); + + if (c > 0.0) + d = -d; + + d /= sqrt (SQR (MIN (du / dv, dv / du)) + 1.0); + + return d; + }; + + /* anti-aliased value of a pixel */ + auto pixel_value = [=] (gint x, + gint y) + { + gdouble u = x_to_u (x + 0.5); + gdouble v = y_to_v (y + 0.5); + gdouble d = ellipse_distance (u, v); + + /* use the distance of the pixel's center from the ellipse to approximate + * the coverage + */ + d = CLAMP (0.5 + d, 0.0, 1.0); + + /* we're at the horizontal boundary of an elliptic corner */ + if (u < 0.5) + d = d * (0.5 + u) + (0.5 - u); + + /* we're at the vertical boundary of an elliptic corner */ + if (v < 0.5) + d = d * (0.5 + v) + (0.5 - v); + + /* opposite horizontal corners intersect the pixel */ + if (x == (right - 1) - (x - left)) + d = 2.0 * d - 1.0; + + /* opposite vertical corners intersect the pixel */ + if (y == (bottom - 1) - (y - top)) + d = 2.0 * d - 1.0; + + return d; + }; + + auto ellipse_range = [=] (gdouble y, + gdouble *x0, + gdouble *x1) + { + gdouble u = v_to_u (y_to_v (y)); + + *x0 = u_to_x_left (u); + *x1 = u_to_x_right (u); + }; + + auto fill0 = [=] (gpointer dest, + gint n) + { + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + case GIMP_CHANNEL_OP_INTERSECT: + memset (dest, 0, bpp * n); + break; + + case GIMP_CHANNEL_OP_ADD: + case GIMP_CHANNEL_OP_SUBTRACT: + break; + } + + return (gpointer) ((guint8 *) dest + bpp * n); + }; + + auto fill1 = [=] (gpointer dest, + gint n) + { + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + case GIMP_CHANNEL_OP_ADD: + gegl_memset_pattern (dest, one, bpp, n); + break; + + case GIMP_CHANNEL_OP_SUBTRACT: + memset (dest, 0, bpp * n); + break; + + case GIMP_CHANNEL_OP_INTERSECT: + break; + } + + return (gpointer) ((guint8 *) dest + bpp * n); + }; + + auto set = [=] (gpointer dest, + gfloat value) + { + gfloat *p = (gfloat *) dest; + + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + *p = value; + break; + + case GIMP_CHANNEL_OP_ADD: + *p = MIN (*p + value, 1.0); + break; + + case GIMP_CHANNEL_OP_SUBTRACT: + *p = MAX (*p - value, 0.0); + break; + + case GIMP_CHANNEL_OP_INTERSECT: + *p = MIN (*p, value); + break; + } + + return (gpointer) (p + 1); + }; + + gegl_parallel_distribute_area ( + &rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) + { + GeglBufferIterator *iter; + + iter = gegl_buffer_iterator_new ( + mask, area, 0, format, + op == GIMP_CHANNEL_OP_REPLACE ? GEGL_ACCESS_WRITE : + GEGL_ACCESS_READWRITE, + GEGL_ABYSS_NONE, 1); + + while (gegl_buffer_iterator_next (iter)) + { + const GeglRectangle *roi = &iter->items[0].roi; + gpointer d = iter->items[0].data; + gdouble tx0, ty0; + gdouble tx1, ty1; + gdouble x0; + gdouble x1; + gint y; + + /* tile bounds */ + tx0 = roi->x; + ty0 = roi->y; + + tx1 = roi->x + roi->width; + ty1 = roi->y + roi->height; + + if (! antialias) + { + tx0 += 0.5; + ty0 += 0.5; + + tx1 -= 0.5; + ty1 -= 0.5; + } + + /* if the tile is fully inside/outside the ellipse, fill it with 1/0, + * respectively, and skip the rest. + */ + ellipse_range (ty0, &x0, &x1); + + if (tx0 >= x0 && tx1 <= x1) + { + ellipse_range (ty1, &x0, &x1); + + if (tx0 >= x0 && tx1 <= x1) + { + fill1 (d, iter->length); + + continue; + } + } + else if (tx1 < x0 || tx0 > x1) + { + ellipse_range (ty1, &x0, &x1); + + if (tx1 < x0 || tx0 > x1) + { + if ((ty0 - cy) * (ty1 - cy) >= 0.0) + { + fill0 (d, iter->length); + + continue; + } + } + } + + for (y = roi->y; y < roi->y + roi->height; y++) + { + gint a, b; + + if (antialias) + { + gdouble v = y_to_v (y + 0.5); + gdouble u0 = v_to_u (v - 0.5); + gdouble u1 = v_to_u (v + 0.5); + gint x; + + a = floor (u_to_x_left (u0)) - roi->x; + a = CLAMP (a, 0, roi->width); + + b = ceil (u_to_x_left (u1)) - roi->x; + b = CLAMP (b, a, roi->width); + + d = fill0 (d, a); + + for (x = roi->x + a; x < roi->x + b; x++) + d = set (d, pixel_value (x, y)); + + a = floor (u_to_x_right (u1)) - roi->x; + a = CLAMP (a, b, roi->width); + + d = fill1 (d, a - b); + + b = ceil (u_to_x_right (u0)) - roi->x; + b = CLAMP (b, a, roi->width); + + for (x = roi->x + a; x < roi->x + b; x++) + d = set (d, pixel_value (x, y)); + + d = fill0 (d, roi->width - b); + } + else + { + ellipse_range (y + 0.5, &x0, &x1); + + a = ceil (x0 - 0.5) - roi->x; + a = CLAMP (a, 0, roi->width); + + b = floor (x1 + 0.5) - roi->x; + b = CLAMP (b, 0, roi->width); + + d = fill0 (d, a); + d = fill1 (d, b - a); + d = fill0 (d, roi->width - b); + } + } + } + }); + + return TRUE; +} + +gboolean +gimp_gegl_mask_combine_buffer (GeglBuffer *mask, + GeglBuffer *add_on, + GimpChannelOps op, + gint off_x, + gint off_y) +{ + GeglRectangle mask_rect; + GeglRectangle add_on_rect; + const Babl *mask_format; + const Babl *add_on_format; + + g_return_val_if_fail (GEGL_IS_BUFFER (mask), FALSE); + g_return_val_if_fail (GEGL_IS_BUFFER (add_on), FALSE); + + if (! gegl_rectangle_intersect (&mask_rect, + GEGL_RECTANGLE ( + off_x, off_y, + gegl_buffer_get_width (add_on), + gegl_buffer_get_height (add_on)), + gegl_buffer_get_abyss (mask))) + { + return FALSE; + } + + add_on_rect = mask_rect; + add_on_rect.x -= off_x; + add_on_rect.y -= off_y; + + mask_format = gegl_buffer_get_format (mask); + add_on_format = gegl_buffer_get_format (add_on); + + if (op == GIMP_CHANNEL_OP_REPLACE && + (gimp_babl_is_bounded (gimp_babl_format_get_precision (add_on_format)) || + gimp_babl_is_bounded (gimp_babl_format_get_precision (mask_format)))) + { + /* See below: this additional hack is only needed for the + * gimp-channel-combine-masks procedure, it's the only place that + * allows to combine arbitrary channels with each other. + */ + gegl_buffer_set_format ( + add_on, + gimp_babl_format_change_linear ( + add_on_format, gimp_babl_format_get_linear (mask_format))); + + gimp_gegl_buffer_copy (add_on, &add_on_rect, GEGL_ABYSS_NONE, + mask, &mask_rect); + + gegl_buffer_set_format (add_on, NULL); + + return TRUE; + } + + /* This is a hack: all selections/layer masks/channels are always + * linear except for channels in 8-bit images. We don't want these + * "Y' u8" to be converted to "Y float" because that would cause a + * gamma canversion and give unexpected results for + * "add/subtract/etc channel from selection". Instead, use all + * channel values "as-is", which makes no differce except in the + * 8-bit case where we need it. + * + * See https://bugzilla.gnome.org/show_bug.cgi?id=791519 + */ + mask_format = gimp_babl_format_change_component_type ( + mask_format, GIMP_COMPONENT_TYPE_FLOAT); + + add_on_format = gimp_babl_format_change_component_type ( + add_on_format, GIMP_COMPONENT_TYPE_FLOAT); + + gegl_parallel_distribute_area ( + &mask_rect, PIXELS_PER_THREAD, + [=] (const GeglRectangle *mask_area) + { + GeglBufferIterator *iter; + GeglRectangle add_on_area; + + add_on_area = *mask_area; + add_on_area.x -= off_x; + add_on_area.y -= off_y; + + iter = gegl_buffer_iterator_new (mask, mask_area, 0, + mask_format, + op == GIMP_CHANNEL_OP_REPLACE ? + GEGL_ACCESS_WRITE : + GEGL_ACCESS_READWRITE, + GEGL_ABYSS_NONE, 2); + + gegl_buffer_iterator_add (iter, add_on, &add_on_area, 0, + add_on_format, + GEGL_ACCESS_READ, GEGL_ABYSS_NONE); + + auto process = [=] (auto value) + { + while (gegl_buffer_iterator_next (iter)) + { + gfloat *mask_data = (gfloat *) iter->items[0].data; + const gfloat *add_on_data = (const gfloat *) iter->items[1].data; + gint count = iter->length; + + while (count--) + { + const gfloat val = value (mask_data, add_on_data); + + *mask_data = CLAMP (val, 0.0f, 1.0f); + + add_on_data++; + mask_data++; + } + } + }; + + switch (op) + { + case GIMP_CHANNEL_OP_REPLACE: + process ([] (const gfloat *mask, + const gfloat *add_on) + { + return *add_on; + }); + break; + + case GIMP_CHANNEL_OP_ADD: + process ([] (const gfloat *mask, + const gfloat *add_on) + { + return *mask + *add_on; + }); + break; + + case GIMP_CHANNEL_OP_SUBTRACT: + process ([] (const gfloat *mask, + const gfloat *add_on) + { + return *mask - *add_on; + }); + break; + + case GIMP_CHANNEL_OP_INTERSECT: + process ([] (const gfloat *mask, + const gfloat *add_on) + { + return MIN (*mask, *add_on); + }); + break; + } + }); + + return TRUE; +} + +} /* extern "C" */ diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.h gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.h --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-mask-combine.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-mask-combine.h 2019-04-07 11:38:14.000000000 +0000 @@ -38,8 +38,8 @@ gint y, gint w, gint h, - gdouble a, - gdouble b, + gdouble rx, + gdouble ry, gboolean antialias); gboolean gimp_gegl_mask_combine_buffer (GeglBuffer *mask, GeglBuffer *add_on, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-nodes.c gimp-2.10.14+om/app/gegl/gimp-gegl-nodes.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-nodes.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-nodes.c 2019-06-12 16:43:38.000000000 +0000 @@ -55,9 +55,17 @@ color = gegl_node_new_child (node, "operation", "gegl:color", "value", c, + "format", gimp_layer_mode_get_format ( + GIMP_LAYER_MODE_NORMAL, + GIMP_LAYER_COLOR_SPACE_AUTO, + composite_space, + GIMP_LAYER_COMPOSITE_AUTO, + NULL), NULL); g_object_unref (c); + gimp_gegl_node_set_underlying_operation (node, color); + mode = gegl_node_new_child (node, "operation", "gimp:normal", NULL); @@ -101,6 +109,8 @@ "value", opacity, NULL); + gimp_gegl_node_set_underlying_operation (node, opacity_node); + mask_source = gimp_gegl_add_buffer_source (node, mask, mask_offset_x, mask_offset_y); @@ -114,6 +124,22 @@ return node; } + +GeglNode * +gimp_gegl_create_transform_node (const GimpMatrix3 *matrix) +{ + GeglNode *node; + + g_return_val_if_fail (matrix != NULL, NULL); + + node = gegl_node_new_child (NULL, + "operation", "gegl:transform", + NULL); + + gimp_gegl_node_set_matrix (node, matrix); + + return node; +} GeglNode * gimp_gegl_add_buffer_source (GeglNode *parent, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-nodes.h gimp-2.10.14+om/app/gegl/gimp-gegl-nodes.h --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-nodes.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-nodes.h 2019-06-12 16:43:38.000000000 +0000 @@ -28,6 +28,8 @@ gint mask_offset_x, gint mask_offset_y, gdouble opacity); +GeglNode * gimp_gegl_create_transform_node (const GimpMatrix3 *matrix); + GeglNode * gimp_gegl_add_buffer_source (GeglNode *parent, GeglBuffer *buffer, gint offset_x, diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-utils.c gimp-2.10.14+om/app/gegl/gimp-gegl-utils.c --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-utils.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-utils.c 2019-10-26 18:49:18.000000000 +0000 @@ -29,6 +29,7 @@ #include "core/gimpprogress.h" +#include "gimp-gegl-loops.h" #include "gimp-gegl-utils.h" @@ -114,6 +115,58 @@ (GDestroyNotify) g_free); } +gboolean +gimp_gegl_node_is_source_operation (GeglNode *node) +{ + GeglOperation *operation; + + g_return_val_if_fail (GEGL_IS_NODE (node), FALSE); + + operation = gegl_node_get_gegl_operation (node); + + if (! operation) + return FALSE; + + return GEGL_IS_OPERATION_SOURCE (operation); +} + +gboolean +gimp_gegl_node_is_point_operation (GeglNode *node) +{ + GeglOperation *operation; + + g_return_val_if_fail (GEGL_IS_NODE (node), FALSE); + + operation = gegl_node_get_gegl_operation (node); + + if (! operation) + return FALSE; + + return GEGL_IS_OPERATION_POINT_RENDER (operation) || + GEGL_IS_OPERATION_POINT_FILTER (operation) || + GEGL_IS_OPERATION_POINT_COMPOSER (operation) || + GEGL_IS_OPERATION_POINT_COMPOSER3 (operation); +} + +gboolean +gimp_gegl_node_is_area_filter_operation (GeglNode *node) +{ + GeglOperation *operation; + + g_return_val_if_fail (GEGL_IS_NODE (node), FALSE); + + operation = gegl_node_get_gegl_operation (node); + + if (! operation) + return FALSE; + + return GEGL_IS_OPERATION_AREA_FILTER (operation) || + /* be conservative and return TRUE for meta ops, since they may + * involve an area op + */ + GEGL_IS_OPERATION_META (operation); +} + const Babl * gimp_gegl_node_get_format (GeglNode *node, const gchar *pad_name) @@ -139,6 +192,33 @@ return format; } +void +gimp_gegl_node_set_underlying_operation (GeglNode *node, + GeglNode *operation) +{ + g_return_if_fail (GEGL_IS_NODE (node)); + g_return_if_fail (operation == NULL || GEGL_IS_NODE (operation)); + + g_object_set_data (G_OBJECT (node), + "gimp-gegl-node-underlying-operation", operation); +} + +GeglNode * +gimp_gegl_node_get_underlying_operation (GeglNode *node) +{ + GeglNode *operation; + + g_return_val_if_fail (GEGL_IS_NODE (node), NULL); + + operation = g_object_get_data (G_OBJECT (node), + "gimp-gegl-node-underlying-operation"); + + if (operation) + return gimp_gegl_node_get_underlying_operation (operation); + else + return node; +} + gboolean gimp_gegl_param_spec_has_key (GParamSpec *pspec, const gchar *key, @@ -151,3 +231,95 @@ return FALSE; } + +GeglBuffer * +gimp_gegl_buffer_dup (GeglBuffer *buffer) +{ + GeglBuffer *new_buffer; + const GeglRectangle *extent; + const GeglRectangle *abyss; + GeglRectangle rect; + gint shift_x; + gint shift_y; + gint tile_width; + gint tile_height; + + g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); + + extent = gegl_buffer_get_extent (buffer); + abyss = gegl_buffer_get_abyss (buffer); + + g_object_get (buffer, + "shift-x", &shift_x, + "shift-y", &shift_y, + "tile-width", &tile_width, + "tile-height", &tile_height, + NULL); + + new_buffer = g_object_new (GEGL_TYPE_BUFFER, + "format", gegl_buffer_get_format (buffer), + "x", extent->x, + "y", extent->y, + "width", extent->width, + "height", extent->height, + "abyss-x", abyss->x, + "abyss-y", abyss->y, + "abyss-width", abyss->width, + "abyss-height", abyss->height, + "shift-x", shift_x, + "shift-y", shift_y, + "tile-width", tile_width, + "tile-height", tile_height, + NULL); + + gegl_rectangle_align_to_buffer (&rect, extent, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + gimp_gegl_buffer_copy (buffer, &rect, GEGL_ABYSS_NONE, + new_buffer, &rect); + + return new_buffer; +} + +gboolean +gimp_gegl_buffer_set_extent (GeglBuffer *buffer, + const GeglRectangle *extent) +{ + GeglRectangle aligned_old_extent; + GeglRectangle aligned_extent; + GeglRectangle old_extent_rem; + GeglRectangle diff_rects[4]; + gint n_diff_rects; + gint i; + + g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (extent != NULL, FALSE); + + gegl_rectangle_align_to_buffer (&aligned_old_extent, + gegl_buffer_get_extent (buffer), buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + gegl_rectangle_align_to_buffer (&aligned_extent, + extent, buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + n_diff_rects = gegl_rectangle_subtract (diff_rects, + &aligned_old_extent, + &aligned_extent); + + for (i = 0; i < n_diff_rects; i++) + gegl_buffer_clear (buffer, &diff_rects[i]); + + if (gegl_rectangle_intersect (&old_extent_rem, + gegl_buffer_get_extent (buffer), + &aligned_extent)) + { + n_diff_rects = gegl_rectangle_subtract (diff_rects, + &old_extent_rem, + extent); + + for (i = 0; i < n_diff_rects; i++) + gegl_buffer_clear (buffer, &diff_rects[i]); + } + + return gegl_buffer_set_extent (buffer, extent); +} diff -Nru gimp-2.10.8+zorin2/app/gegl/gimp-gegl-utils.h gimp-2.10.14+om/app/gegl/gimp-gegl-utils.h --- gimp-2.10.8+zorin2/app/gegl/gimp-gegl-utils.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimp-gegl-utils.h 2019-10-26 18:49:18.000000000 +0000 @@ -22,21 +22,34 @@ #define __GIMP_GEGL_UTILS_H__ -GType gimp_gegl_get_op_enum_type (const gchar *operation, - const gchar *property); +GType gimp_gegl_get_op_enum_type (const gchar *operation, + const gchar *property); -GeglColor * gimp_gegl_color_new (const GimpRGB *rgb); +GeglColor * gimp_gegl_color_new (const GimpRGB *rgb); -void gimp_gegl_progress_connect (GeglNode *node, - GimpProgress *progress, - const gchar *text); +void gimp_gegl_progress_connect (GeglNode *node, + GimpProgress *progress, + const gchar *text); -const Babl * gimp_gegl_node_get_format (GeglNode *node, - const gchar *pad_name); +gboolean gimp_gegl_node_is_source_operation (GeglNode *node); +gboolean gimp_gegl_node_is_point_operation (GeglNode *node); +gboolean gimp_gegl_node_is_area_filter_operation (GeglNode *node); -gboolean gimp_gegl_param_spec_has_key (GParamSpec *pspec, - const gchar *key, - const gchar *value); +const Babl * gimp_gegl_node_get_format (GeglNode *node, + const gchar *pad_name); + +void gimp_gegl_node_set_underlying_operation (GeglNode *node, + GeglNode *operation); +GeglNode * gimp_gegl_node_get_underlying_operation (GeglNode *node); + +gboolean gimp_gegl_param_spec_has_key (GParamSpec *pspec, + const gchar *key, + const gchar *value); + +GeglBuffer * gimp_gegl_buffer_dup (GeglBuffer *buffer); + +gboolean gimp_gegl_buffer_set_extent (GeglBuffer *buffer, + const GeglRectangle *extent); #endif /* __GIMP_GEGL_UTILS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/gegl/gimptilehandlervalidate.c gimp-2.10.14+om/app/gegl/gimptilehandlervalidate.c --- gimp-2.10.8+zorin2/app/gegl/gimptilehandlervalidate.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimptilehandlervalidate.c 2019-10-26 18:49:18.000000000 +0000 @@ -22,6 +22,8 @@ #include "gimp-gegl-types.h" +#include "gimp-gegl-loops.h" +#include "gimp-gegl-utils.h" #include "gimptilehandlervalidate.h" @@ -35,28 +37,33 @@ }; -static void gimp_tile_handler_validate_finalize (GObject *object); -static void gimp_tile_handler_validate_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_tile_handler_validate_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void gimp_tile_handler_validate_real_validate (GimpTileHandlerValidate *validate, - const GeglRectangle *rect, - const Babl *format, - gpointer dest_buf, - gint dest_stride); - -static gpointer gimp_tile_handler_validate_command (GeglTileSource *source, - GeglTileCommand command, - gint x, - gint y, - gint z, - gpointer data); +static void gimp_tile_handler_validate_finalize (GObject *object); +static void gimp_tile_handler_validate_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_tile_handler_validate_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_tile_handler_validate_real_begin_validate (GimpTileHandlerValidate *validate); +static void gimp_tile_handler_validate_real_end_validate (GimpTileHandlerValidate *validate); +static void gimp_tile_handler_validate_real_validate (GimpTileHandlerValidate *validate, + const GeglRectangle *rect, + const Babl *format, + gpointer dest_buf, + gint dest_stride); +static void gimp_tile_handler_validate_real_validate_buffer (GimpTileHandlerValidate *validate, + const GeglRectangle *rect, + GeglBuffer *buffer); + +static gpointer gimp_tile_handler_validate_command (GeglTileSource *source, + GeglTileCommand command, + gint x, + gint y, + gint z, + gpointer data); G_DEFINE_TYPE (GimpTileHandlerValidate, gimp_tile_handler_validate, @@ -74,7 +81,10 @@ object_class->set_property = gimp_tile_handler_validate_set_property; object_class->get_property = gimp_tile_handler_validate_get_property; + klass->begin_validate = gimp_tile_handler_validate_real_begin_validate; + klass->end_validate = gimp_tile_handler_validate_real_end_validate; klass->validate = gimp_tile_handler_validate_real_validate; + klass->validate_buffer = gimp_tile_handler_validate_real_validate_buffer; g_object_class_install_property (object_class, PROP_FORMAT, g_param_spec_pointer ("format", NULL, NULL, @@ -179,6 +189,18 @@ } static void +gimp_tile_handler_validate_real_begin_validate (GimpTileHandlerValidate *validate) +{ + validate->suspend_validate++; +} + +static void +gimp_tile_handler_validate_real_end_validate (GimpTileHandlerValidate *validate) +{ + validate->suspend_validate--; +} + +static void gimp_tile_handler_validate_real_validate (GimpTileHandlerValidate *validate, const GeglRectangle *rect, const Babl *format, @@ -198,19 +220,49 @@ GEGL_BLIT_DEFAULT); } +static void +gimp_tile_handler_validate_real_validate_buffer (GimpTileHandlerValidate *validate, + const GeglRectangle *rect, + GeglBuffer *buffer) +{ + GimpTileHandlerValidateClass *klass; + + klass = GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate); + + if (klass->validate == gimp_tile_handler_validate_real_validate) + { + gegl_node_blit_buffer (validate->graph, buffer, rect, 0, + GEGL_ABYSS_NONE); + } + else + { + const Babl *format = gegl_buffer_get_format (buffer); + gpointer data; + gint stride; + + data = gegl_buffer_linear_open (buffer, rect, &stride, format); + + klass->validate (validate, rect, format, data, stride); + + gegl_buffer_linear_close (buffer, data); + } +} + static GeglTile * -gimp_tile_handler_validate_validate (GeglTileSource *source, - GeglTile *tile, - gint x, - gint y) +gimp_tile_handler_validate_validate_tile (GeglTileSource *source, + gint x, + gint y) { GimpTileHandlerValidate *validate = GIMP_TILE_HANDLER_VALIDATE (source); + GeglTile *tile; cairo_rectangle_int_t tile_rect; + cairo_region_overlap_t overlap; if (validate->suspend_validate || cairo_region_is_empty (validate->dirty_region)) { - return tile; + return gegl_tile_handler_source_command (source, + GEGL_TILE_GET, x, y, 0, NULL); } tile_rect.x = x * validate->tile_width; @@ -218,95 +270,107 @@ tile_rect.width = validate->tile_width; tile_rect.height = validate->tile_height; - if (validate->whole_tile) + overlap = cairo_region_contains_rectangle (validate->dirty_region, + &tile_rect); + + if (overlap == CAIRO_REGION_OVERLAP_OUT) { - if (cairo_region_contains_rectangle (validate->dirty_region, &tile_rect) - != CAIRO_REGION_OVERLAP_OUT) - { - gint tile_bpp; - gint tile_stride; + return gegl_tile_handler_source_command (source, + GEGL_TILE_GET, x, y, 0, NULL); + } - if (! tile) - tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source), - x, y, 0); + if (overlap == CAIRO_REGION_OVERLAP_IN || validate->whole_tile) + { + gint tile_bpp; + gint tile_stride; - cairo_region_subtract_rectangle (validate->dirty_region, &tile_rect); + cairo_region_subtract_rectangle (validate->dirty_region, &tile_rect); - tile_bpp = babl_format_get_bytes_per_pixel (validate->format); - tile_stride = tile_bpp * validate->tile_width; + tile_bpp = babl_format_get_bytes_per_pixel (validate->format); + tile_stride = tile_bpp * validate->tile_width; - gegl_tile_lock (tile); + tile = gegl_tile_handler_get_source_tile (GEGL_TILE_HANDLER (source), + x, y, 0, FALSE); - GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->validate - (validate, - GEGL_RECTANGLE (tile_rect.x, - tile_rect.y, - tile_rect.width, - tile_rect.height), - validate->format, - gegl_tile_get_data (tile), - tile_stride); + gimp_tile_handler_validate_begin_validate (validate); - gegl_tile_unlock (tile); - } + gegl_tile_lock (tile); + + GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->validate + (validate, + GEGL_RECTANGLE (tile_rect.x, + tile_rect.y, + tile_rect.width, + tile_rect.height), + validate->format, + gegl_tile_get_data (tile), + tile_stride); + + gegl_tile_unlock (tile); + + gimp_tile_handler_validate_end_validate (validate); } else { - cairo_region_t *tile_region = cairo_region_copy (validate->dirty_region); + cairo_region_t *tile_region; + gint tile_bpp; + gint tile_stride; + gint n_rects; + gint i; + tile_region = cairo_region_copy (validate->dirty_region); cairo_region_intersect_rectangle (tile_region, &tile_rect); - if (! cairo_region_is_empty (tile_region)) - { - gint tile_bpp; - gint tile_stride; - gint n_rects; - gint i; + cairo_region_subtract_rectangle (validate->dirty_region, &tile_rect); - cairo_region_subtract_rectangle (validate->dirty_region, &tile_rect); + tile_bpp = babl_format_get_bytes_per_pixel (validate->format); + tile_stride = tile_bpp * validate->tile_width; - tile_bpp = babl_format_get_bytes_per_pixel (validate->format); - tile_stride = tile_bpp * validate->tile_width; + tile = gegl_tile_handler_source_command (source, + GEGL_TILE_GET, x, y, 0, NULL); - if (! tile) - { - tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source), - x, y, 0); + if (! tile) + { + tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source), + x, y, 0); - memset (gegl_tile_get_data (tile), - 0, tile_stride * validate->tile_height); - } + memset (gegl_tile_get_data (tile), + 0, tile_stride * validate->tile_height); + } - gegl_tile_lock (tile); + gimp_tile_handler_validate_begin_validate (validate); - n_rects = cairo_region_num_rectangles (tile_region); + gegl_tile_lock (tile); + + n_rects = cairo_region_num_rectangles (tile_region); #if 0 - g_printerr ("%d chunks\n", n_rects); + g_printerr ("%d chunks\n", n_rects); #endif - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t blit_rect; + for (i = 0; i < n_rects; i++) + { + cairo_rectangle_int_t blit_rect; - cairo_region_get_rectangle (tile_region, i, &blit_rect); + cairo_region_get_rectangle (tile_region, i, &blit_rect); - GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->validate - (validate, - GEGL_RECTANGLE (blit_rect.x, - blit_rect.y, - blit_rect.width, - blit_rect.height), - validate->format, - gegl_tile_get_data (tile) + - (blit_rect.y % validate->tile_height) * tile_stride + - (blit_rect.x % validate->tile_width) * tile_bpp, - tile_stride); - } - - gegl_tile_unlock (tile); + GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->validate + (validate, + GEGL_RECTANGLE (blit_rect.x, + blit_rect.y, + blit_rect.width, + blit_rect.height), + validate->format, + gegl_tile_get_data (tile) + + (blit_rect.y % validate->tile_height) * tile_stride + + (blit_rect.x % validate->tile_width) * tile_bpp, + tile_stride); } + gegl_tile_unlock (tile); + + gimp_tile_handler_validate_end_validate (validate); + cairo_region_destroy (tile_region); } @@ -321,14 +385,10 @@ gint z, gpointer data) { - gpointer retval; - - retval = gegl_tile_handler_source_command (source, command, x, y, z, data); - if (command == GEGL_TILE_GET && z == 0) - retval = gimp_tile_handler_validate_validate (source, retval, x, y); + return gimp_tile_handler_validate_validate_tile (source, x, y); - return retval; + return gegl_tile_handler_source_command (source, command, x, y, z, data); } @@ -416,6 +476,113 @@ } void +gimp_tile_handler_validate_begin_validate (GimpTileHandlerValidate *validate) +{ + g_return_if_fail (GIMP_IS_TILE_HANDLER_VALIDATE (validate)); + + if (validate->validating++ == 0) + GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->begin_validate (validate); +} + +void +gimp_tile_handler_validate_end_validate (GimpTileHandlerValidate *validate) +{ + g_return_if_fail (GIMP_IS_TILE_HANDLER_VALIDATE (validate)); + g_return_if_fail (validate->validating > 0); + + if (--validate->validating == 0) + GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate)->end_validate (validate); +} + +void +gimp_tile_handler_validate_validate (GimpTileHandlerValidate *validate, + GeglBuffer *buffer, + const GeglRectangle *rect, + gboolean intersect) +{ + GimpTileHandlerValidateClass *klass; + + g_return_if_fail (GIMP_IS_TILE_HANDLER_VALIDATE (validate)); + g_return_if_fail (gimp_tile_handler_validate_get_assigned (buffer) == + validate); + + klass = GIMP_TILE_HANDLER_VALIDATE_GET_CLASS (validate); + + if (intersect) + { + cairo_region_t *region = cairo_region_copy (validate->dirty_region); + + cairo_region_intersect_rectangle (region, + (const cairo_rectangle_int_t *) rect); + + if (! cairo_region_is_empty (region)) + { + gint n_rects; + gint i; + + gimp_tile_handler_validate_begin_validate (validate); + + n_rects = cairo_region_num_rectangles (region); + + for (i = 0; i < n_rects; i++) + { + cairo_rectangle_int_t blit_rect; + + cairo_region_get_rectangle (region, i, &blit_rect); + + klass->validate_buffer (validate, + (const GeglRectangle *) &blit_rect, + buffer); + } + + gimp_tile_handler_validate_end_validate (validate); + + cairo_region_subtract_rectangle ( + validate->dirty_region, + (const cairo_rectangle_int_t *) rect); + } + + cairo_region_destroy (region); + } + else + { + gimp_tile_handler_validate_begin_validate (validate); + + klass->validate_buffer (validate, rect, buffer); + + gimp_tile_handler_validate_end_validate (validate); + + cairo_region_subtract_rectangle ( + validate->dirty_region, + (const cairo_rectangle_int_t *) rect); + } +} + +gboolean +gimp_tile_handler_validate_buffer_set_extent (GeglBuffer *buffer, + const GeglRectangle *extent) +{ + GimpTileHandlerValidate *validate; + + g_return_val_if_fail (GEGL_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (extent != NULL, FALSE); + + validate = gimp_tile_handler_validate_get_assigned (buffer); + + g_return_val_if_fail (validate != NULL, FALSE); + + if (gimp_gegl_buffer_set_extent (buffer, extent)) + { + cairo_region_intersect_rectangle (validate->dirty_region, + (const cairo_rectangle_int_t *) extent); + + return TRUE; + } + + return FALSE; +} + +void gimp_tile_handler_validate_buffer_copy (GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dst_buffer, @@ -454,17 +621,32 @@ real_src_rect.width = CLAMP (real_src_rect.width, 0, real_dst_rect.width); real_src_rect.height = CLAMP (real_src_rect.height, 0, real_dst_rect.height); + /* temporarily remove the source buffer's validate handler, so that + * gegl_buffer_copy() can use fast tile copying, using the TILE_COPY command. + * currently, gegl only uses TILE_COPY when the source buffer has no user- + * provided tile handlers. + */ if (src_validate) - src_validate->suspend_validate++; + { + g_object_ref (src_validate); + + gimp_tile_handler_validate_unassign (src_validate, src_buffer); + } + dst_validate->suspend_validate++; - gegl_buffer_copy (src_buffer, &real_src_rect, GEGL_ABYSS_NONE, - dst_buffer, &real_dst_rect); + gimp_gegl_buffer_copy (src_buffer, &real_src_rect, GEGL_ABYSS_NONE, + dst_buffer, &real_dst_rect); - if (src_validate) - src_validate->suspend_validate--; dst_validate->suspend_validate--; + if (src_validate) + { + gimp_tile_handler_validate_assign (src_validate, src_buffer); + + g_object_unref (src_validate); + } + cairo_region_subtract_rectangle (dst_validate->dirty_region, (cairo_rectangle_int_t *) &real_dst_rect); diff -Nru gimp-2.10.8+zorin2/app/gegl/gimptilehandlervalidate.h gimp-2.10.14+om/app/gegl/gimptilehandlervalidate.h --- gimp-2.10.8+zorin2/app/gegl/gimptilehandlervalidate.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/gimptilehandlervalidate.h 2019-10-26 18:49:18.000000000 +0000 @@ -48,6 +48,7 @@ gint tile_width; gint tile_height; gboolean whole_tile; + gint validating; gint suspend_validate; }; @@ -55,33 +56,49 @@ { GeglTileHandlerClass parent_class; - void (* validate) (GimpTileHandlerValidate *validate, - const GeglRectangle *rect, - const Babl *format, - gpointer dest_buf, - gint dest_stride); + void (* begin_validate) (GimpTileHandlerValidate *validate); + void (* end_validate) (GimpTileHandlerValidate *validate); + void (* validate) (GimpTileHandlerValidate *validate, + const GeglRectangle *rect, + const Babl *format, + gpointer dest_buf, + gint dest_stride); + void (* validate_buffer) (GimpTileHandlerValidate *validate, + const GeglRectangle *rect, + GeglBuffer *buffer); }; -GType gimp_tile_handler_validate_get_type (void) G_GNUC_CONST; +GType gimp_tile_handler_validate_get_type (void) G_GNUC_CONST; -GeglTileHandler * gimp_tile_handler_validate_new (GeglNode *graph); +GeglTileHandler * gimp_tile_handler_validate_new (GeglNode *graph); -void gimp_tile_handler_validate_assign (GimpTileHandlerValidate *validate, - GeglBuffer *buffer); -void gimp_tile_handler_validate_unassign (GimpTileHandlerValidate *validate, - GeglBuffer *buffer); -GimpTileHandlerValidate * gimp_tile_handler_validate_get_assigned (GeglBuffer *buffer); - -void gimp_tile_handler_validate_invalidate (GimpTileHandlerValidate *validate, - const GeglRectangle *rect); -void gimp_tile_handler_validate_undo_invalidate (GimpTileHandlerValidate *validate, - const GeglRectangle *rect); - -void gimp_tile_handler_validate_buffer_copy (GeglBuffer *src_buffer, - const GeglRectangle *src_rect, - GeglBuffer *dst_buffer, - const GeglRectangle *dst_rect); +void gimp_tile_handler_validate_assign (GimpTileHandlerValidate *validate, + GeglBuffer *buffer); +void gimp_tile_handler_validate_unassign (GimpTileHandlerValidate *validate, + GeglBuffer *buffer); +GimpTileHandlerValidate * gimp_tile_handler_validate_get_assigned (GeglBuffer *buffer); + +void gimp_tile_handler_validate_invalidate (GimpTileHandlerValidate *validate, + const GeglRectangle *rect); +void gimp_tile_handler_validate_undo_invalidate (GimpTileHandlerValidate *validate, + const GeglRectangle *rect); + +void gimp_tile_handler_validate_begin_validate (GimpTileHandlerValidate *validate); +void gimp_tile_handler_validate_end_validate (GimpTileHandlerValidate *validate); + +void gimp_tile_handler_validate_validate (GimpTileHandlerValidate *validate, + GeglBuffer *buffer, + const GeglRectangle *rect, + gboolean intersect); + +gboolean gimp_tile_handler_validate_buffer_set_extent (GeglBuffer *buffer, + const GeglRectangle *extent); + +void gimp_tile_handler_validate_buffer_copy (GeglBuffer *src_buffer, + const GeglRectangle *src_rect, + GeglBuffer *dst_buffer, + const GeglRectangle *dst_rect); G_END_DECLS diff -Nru gimp-2.10.8+zorin2/app/gegl/Makefile.am gimp-2.10.14+om/app/gegl/Makefile.am --- gimp-2.10.8+zorin2/app/gegl/Makefile.am 2018-04-17 09:24:32.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/Makefile.am 2019-04-07 11:38:14.000000000 +0000 @@ -31,7 +31,7 @@ gimp-gegl-loops.h \ gimp-gegl-mask.c \ gimp-gegl-mask.h \ - gimp-gegl-mask-combine.c \ + gimp-gegl-mask-combine.cc \ gimp-gegl-mask-combine.h \ gimp-gegl-nodes.c \ gimp-gegl-nodes.h \ diff -Nru gimp-2.10.8+zorin2/app/gegl/Makefile.in gimp-2.10.14+om/app/gegl/Makefile.in --- gimp-2.10.8+zorin2/app/gegl/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/gegl/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -258,8 +257,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -389,7 +386,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -528,8 +524,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -683,7 +677,7 @@ gimp-gegl-loops.h \ gimp-gegl-mask.c \ gimp-gegl-mask.h \ - gimp-gegl-mask-combine.c \ + gimp-gegl-mask-combine.cc \ gimp-gegl-mask-combine.h \ gimp-gegl-nodes.c \ gimp-gegl-nodes.h \ diff -Nru gimp-2.10.8+zorin2/app/gimp-priorities.h gimp-2.10.14+om/app/gimp-priorities.h --- gimp-2.10.8+zorin2/app/gimp-priorities.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gimp-priorities.h 2019-04-07 11:38:14.000000000 +0000 @@ -28,7 +28,8 @@ /* #define GTK_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 20) */ /* a bit higher than projection construction */ -#define GIMP_PRIORITY_DISPLAY_SHELL_FILL_IDLE (G_PRIORITY_HIGH_IDLE + 21) +#define GIMP_PRIORITY_DISPLAY_SHELL_FILL_IDLE (G_PRIORITY_HIGH_IDLE + 21) +#define GIMP_PRIORITY_IMAGE_WINDOW_UPDATE_UI_MANAGER_IDLE (G_PRIORITY_HIGH_IDLE + 21) /* just a bit less than GDK_PRIORITY_REDRAW */ #define GIMP_PRIORITY_PROJECTION_IDLE (G_PRIORITY_HIGH_IDLE + 22) diff -Nru gimp-2.10.8+zorin2/app/gimp-version.c gimp-2.10.14+om/app/gimp-version.c --- gimp-2.10.8+zorin2/app/gimp-version.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gimp-version.c 2019-10-26 18:49:18.000000000 +0000 @@ -78,15 +78,31 @@ gchar *lib_versions; gchar *lib_version; gchar *temp; + gint babl_major_version; + gint babl_minor_version; + gint babl_micro_version; gint gegl_major_version; gint gegl_minor_version; gint gegl_micro_version; + babl_get_version (&babl_major_version, + &babl_minor_version, + &babl_micro_version); + + lib_versions = gimp_library_version ("babl", + BABL_MAJOR_VERSION, + BABL_MINOR_VERSION, + BABL_MICRO_VERSION, + babl_major_version, + babl_minor_version, + babl_micro_version, + localized); + gegl_get_version (&gegl_major_version, &gegl_minor_version, &gegl_micro_version); - lib_versions = gimp_library_version ("GEGL", + lib_version = gimp_library_version ("GEGL", GEGL_MAJOR_VERSION, GEGL_MINOR_VERSION, GEGL_MICRO_VERSION, @@ -95,6 +111,11 @@ gegl_micro_version, localized); + temp = g_strdup_printf ("%s\n%s", lib_versions, lib_version); + g_free (lib_versions); + g_free (lib_version); + lib_versions = temp; + lib_version = gimp_library_version ("GLib", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, diff -Nru gimp-2.10.8+zorin2/app/gui/gimpdbusservice-generated.c gimp-2.10.14+om/app/gui/gimpdbusservice-generated.c --- gimp-2.10.8+zorin2/app/gui/gimpdbusservice-generated.c 2018-11-08 14:58:37.000000000 +0000 +++ gimp-2.10.14+om/app/gui/gimpdbusservice-generated.c 2019-10-26 19:24:12.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Generated by gdbus-codegen 2.59.0 from dbus-service.xml. DO NOT EDIT. + * Generated by gdbus-codegen 2.62.0 from dbus-service.xml. DO NOT EDIT. * * The license of this code is the same as for the D-Bus interface description * it was derived from. @@ -39,7 +39,8 @@ { GDBusPropertyInfo parent_struct; const gchar *hyphen_name; - gboolean use_gvariant; + guint use_gvariant : 1; + guint emits_changed_signal : 1; } _ExtendedGDBusPropertyInfo; typedef struct @@ -608,7 +609,7 @@ /** * gimp_dbus_service_ui_call_open_finish: * @proxy: A #GimpDBusServiceUIProxy. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gimp_dbus_service_ui_call_open(). * @error: Return location for error or %NULL. * @@ -639,7 +640,7 @@ * gimp_dbus_service_ui_call_open_sync: * @proxy: A #GimpDBusServiceUIProxy. * @arg_uri: Argument to pass with the method invocation. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @cancellable: (nullable): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * @@ -712,7 +713,7 @@ /** * gimp_dbus_service_ui_call_open_as_new_finish: * @proxy: A #GimpDBusServiceUIProxy. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gimp_dbus_service_ui_call_open_as_new(). * @error: Return location for error or %NULL. * @@ -743,7 +744,7 @@ * gimp_dbus_service_ui_call_open_as_new_sync: * @proxy: A #GimpDBusServiceUIProxy. * @arg_uri: Argument to pass with the method invocation. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @cancellable: (nullable): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * @@ -819,7 +820,7 @@ /** * gimp_dbus_service_ui_call_batch_run_finish: * @proxy: A #GimpDBusServiceUIProxy. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to gimp_dbus_service_ui_call_batch_run(). * @error: Return location for error or %NULL. * @@ -851,7 +852,7 @@ * @proxy: A #GimpDBusServiceUIProxy. * @arg_interpreter: Argument to pass with the method invocation. * @arg_command: Argument to pass with the method invocation. - * @out_success: (out): Return location for return parameter or %NULL to ignore. + * @out_success: (out) (optional): Return location for return parameter or %NULL to ignore. * @cancellable: (nullable): A #GCancellable or %NULL. * @error: Return location for error or %NULL. * diff -Nru gimp-2.10.8+zorin2/app/gui/gimpdbusservice-generated.h gimp-2.10.14+om/app/gui/gimpdbusservice-generated.h --- gimp-2.10.8+zorin2/app/gui/gimpdbusservice-generated.h 2018-11-08 14:58:37.000000000 +0000 +++ gimp-2.10.14+om/app/gui/gimpdbusservice-generated.h 2019-10-26 19:24:12.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Generated by gdbus-codegen 2.59.0 from dbus-service.xml. DO NOT EDIT. + * Generated by gdbus-codegen 2.62.0 from dbus-service.xml. DO NOT EDIT. * * The license of this code is the same as for the D-Bus interface description * it was derived from. diff -Nru gimp-2.10.8+zorin2/app/gui/gui.c gimp-2.10.14+om/app/gui/gui.c --- gimp-2.10.8+zorin2/app/gui/gui.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gui/gui.c 2019-10-26 18:49:18.000000000 +0000 @@ -45,7 +45,11 @@ #include "display/gimpstatusbar.h" #include "tools/gimp-tools.h" +#include "tools/gimptool.h" +#include "tools/tool_manager.h" +#include "widgets/gimpaction.h" +#include "widgets/gimpactiongroup.h" #include "widgets/gimpaction-history.h" #include "widgets/gimpclipboard.h" #include "widgets/gimpcolorselectorpalette.h" @@ -560,7 +564,7 @@ { GtkWidget *item; - item = gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui_manager), action_path); + item = gimp_ui_manager_get_widget (ui_manager, action_path); if (GTK_IS_MENU_ITEM (item)) gtkosx_application_insert_app_menu_item (osx_app, GTK_WIDGET (item), index); @@ -635,12 +639,15 @@ osx_app = gtkosx_application_get (); - menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager), - "/image-menubar"); + menu = gimp_ui_manager_get_widget (image_ui_manager, + "/image-menubar"); if (GTK_IS_MENU_ITEM (menu)) menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu)); - gtkosx_application_set_menu_bar (osx_app, GTK_MENU_SHELL (menu)); + /* do not activate OSX menu if tests are running */ + if (!getenv("GIMP_TESTING_ABS_TOP_SRCDIR")) + gtkosx_application_set_menu_bar (osx_app, GTK_MENU_SHELL (menu)); + gtkosx_application_set_use_quartz_accelerators (osx_app, FALSE); gui_add_to_app_menu (image_ui_manager, osx_app, @@ -666,8 +673,8 @@ item = gtk_separator_menu_item_new (); gtkosx_application_insert_app_menu_item (osx_app, item, 8); - item = gtk_ui_manager_get_widget (GTK_UI_MANAGER (image_ui_manager), - "/image-menubar/File/file-quit"); + item = gimp_ui_manager_get_widget (image_ui_manager, + "/image-menubar/File/file-quit"); gtk_widget_hide (item); g_signal_connect (osx_app, "NSApplicationBlockTermination", @@ -732,7 +739,8 @@ gui_exit_callback (Gimp *gimp, gboolean force) { - GimpGuiConfig *gui_config = GIMP_GUI_CONFIG (gimp->config); + GimpGuiConfig *gui_config = GIMP_GUI_CONFIG (gimp->config); + GimpTool *active_tool; if (gimp->be_verbose) g_print ("EXIT: %s\n", G_STRFUNC); @@ -755,6 +763,15 @@ gui_unique_exit (); + /* If any modifier is set when quitting (typically when exiting with + * Ctrl-q for instance!), when serializing the tool options, it will + * save any alternate value instead of the main one. Make sure that + * any modifier is reset before saving options. + */ + active_tool = tool_manager_get_active (gimp); + if (active_tool && active_tool->focus_display) + gimp_tool_set_modifier_state (active_tool, 0, active_tool->focus_display); + if (gui_config->save_session_info) session_save (gimp, FALSE); @@ -1010,30 +1027,34 @@ GList *list; manager = gimp_ui_managers_from_name ("")->data; - for (list = gtk_ui_manager_get_action_groups (GTK_UI_MANAGER (manager)); + + for (list = gimp_ui_manager_get_action_groups (manager); list; list = g_list_next (list)) { - GtkActionGroup *group = list->data; - GList *actions = NULL; - GList *list2; + GimpActionGroup *group = list->data; + GList *actions = NULL; + GList *list2; + + actions = gimp_action_group_list_actions (group); - actions = gtk_action_group_list_actions (GTK_ACTION_GROUP (group)); for (list2 = actions; list2; list2 = g_list_next (list2)) { - const gchar *path; - GtkAction *action = list2->data; + GimpAction *action = list2->data; + const gchar *path = gimp_action_get_accel_path (action); - path = gtk_action_get_accel_path (action); if (g_strcmp0 (path, accel_path) == 0) { action_exists = TRUE; break; } } + g_list_free (actions); + if (action_exists) break; } + return action_exists; } diff -Nru gimp-2.10.8+zorin2/app/gui/gui-unique.c gimp-2.10.14+om/app/gui/gui-unique.c --- gimp-2.10.8+zorin2/app/gui/gui-unique.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gui/gui-unique.c 2019-10-26 18:49:18.000000000 +0000 @@ -36,6 +36,7 @@ #include "display/gimpdisplay.h" #include "display/gimpdisplayshell.h" +#include "display/gimpimagewindow.h" #include "file/file-open.h" @@ -166,6 +167,7 @@ if (unique_gimp) { COPYDATASTRUCT *copydata = (COPYDATASTRUCT *) lParam; + GimpObject *display; if (copydata->cbData > 0) { @@ -193,6 +195,11 @@ g_source_attach (source, NULL); g_source_unref (source); } + + /* Deiconify the window if minimized. */ + display = gimp_container_get_first_child (unique_gimp->displays); + if (display) + gimp_display_shell_present (gimp_display_get_shell (GIMP_DISPLAY (display))); } return TRUE; diff -Nru gimp-2.10.8+zorin2/app/gui/Makefile.in gimp-2.10.14+om/app/gui/Makefile.in --- gimp-2.10.8+zorin2/app/gui/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/gui/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -222,8 +221,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -353,7 +350,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -492,8 +488,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/gui/themes.c gimp-2.10.14+om/app/gui/themes.c --- gimp-2.10.8+zorin2/app/gui/themes.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/gui/themes.c 2019-04-07 11:38:14.000000000 +0000 @@ -296,60 +296,99 @@ } else { - GFile *theme_dir = themes_get_theme_dir (gimp, theme_name); - GFile *gtkrc_theme; - GFile *gtkrc_user; - gchar *esc_gtkrc_theme; - gchar *esc_gtkrc_user; - gchar *tmp; + GFile *theme_dir = themes_get_theme_dir (gimp, theme_name); + GFile *gtkrc_user; + GSList *gtkrc_files = NULL; + GSList *iter; if (theme_dir) { - gtkrc_theme = g_file_get_child (theme_dir, "gtkrc"); + gtkrc_files = g_slist_prepend ( + gtkrc_files, + g_file_get_child (theme_dir, "gtkrc")); } else { /* get the hardcoded default theme gtkrc */ - gtkrc_theme = g_file_new_for_path (gimp_gtkrc ()); + gtkrc_files = g_slist_prepend ( + gtkrc_files, + g_file_new_for_path (gimp_gtkrc ())); } - gtkrc_user = gimp_directory_file ("gtkrc", NULL); + gtkrc_files = g_slist_prepend ( + gtkrc_files, + gimp_sysconf_directory_file ("gtkrc", NULL)); + + gtkrc_user = gimp_directory_file ("gtkrc", NULL); + gtkrc_files = g_slist_prepend ( + gtkrc_files, + gtkrc_user); + + gtkrc_files = g_slist_reverse (gtkrc_files); + + g_output_stream_printf ( + output, NULL, NULL, &error, + "# GIMP themerc\n" + "#\n" + "# This file is written on GIMP startup and on every theme change.\n" + "# It is NOT supposed to be edited manually. Edit your personal\n" + "# gtkrc file instead (%s).\n" + "\n", + gimp_file_get_utf8_name (gtkrc_user)); - tmp = g_file_get_path (gtkrc_theme); - esc_gtkrc_theme = g_strescape (tmp, NULL); - g_free (tmp); - - tmp = g_file_get_path (gtkrc_user); - esc_gtkrc_user = g_strescape (tmp, NULL); - g_free (tmp); - - if (! g_output_stream_printf - (output, NULL, NULL, &error, - "# GIMP themerc\n" - "#\n" - "# This file is written on GIMP startup and on every theme change.\n" - "# It is NOT supposed to be edited manually. Edit your personal\n" - "# gtkrc file instead (%s).\n" - "\n" - "include \"%s\"\n" - "include \"%s\"\n" - "\n" - "# end of themerc\n", - gimp_file_get_utf8_name (gtkrc_user), - esc_gtkrc_theme, - esc_gtkrc_user) || - ! g_output_stream_close (output, NULL, &error)) + for (iter = gtkrc_files; ! error && iter; iter = g_slist_next (iter)) { + GFile *file = iter->data; + + if (g_file_query_exists (file, NULL)) + { + gchar *path; + gchar *esc_path; + + path = g_file_get_path (file); + esc_path = g_strescape (path, NULL); + g_free (path); + + g_output_stream_printf ( + output, NULL, NULL, &error, + "include \"%s\"\n", + esc_path); + + g_free (esc_path); + } + } + + if (! error) + { + g_output_stream_printf ( + output, NULL, NULL, &error, + "\n" + "# end of themerc\n"); + } + + if (error) + { + GCancellable *cancellable = g_cancellable_new (); + gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR, _("Error writing '%s': %s"), gimp_file_get_utf8_name (themerc), error->message); g_clear_error (&error); + + /* Cancel the overwrite initiated by g_file_replace(). */ + g_cancellable_cancel (cancellable); + g_output_stream_close (output, cancellable, NULL); + g_object_unref (cancellable); + } + else if (! g_output_stream_close (output, NULL, &error)) + { + gimp_message (gimp, NULL, GIMP_MESSAGE_ERROR, + _("Error closing '%s': %s"), + gimp_file_get_utf8_name (themerc), error->message); + g_clear_error (&error); } - g_free (esc_gtkrc_theme); - g_free (esc_gtkrc_user); - g_object_unref (gtkrc_theme); - g_object_unref (gtkrc_user); + g_slist_free_full (gtkrc_files, g_object_unref); g_object_unref (output); } diff -Nru gimp-2.10.8+zorin2/app/main.c gimp-2.10.14+om/app/main.c --- gimp-2.10.8+zorin2/app/main.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/main.c 2019-06-12 16:43:38.000000000 +0000 @@ -53,6 +53,7 @@ #include "config/gimpconfig-dump.h" #include "core/gimp.h" +#include "core/gimpbacktrace.h" #include "pdb/gimppdb.h" #include "pdb/gimpprocedure.h" @@ -324,6 +325,12 @@ argv = __argv; #endif + /* Initialize GimpBacktrace early on. In particular, we want the + * Windows backend to catch the SET_THREAD_NAME exceptions of newly + * created threads. + */ + gimp_backtrace_init (); + /* Start signal handlers early. */ gimp_init_signal_handlers (&backtrace_file); diff -Nru gimp-2.10.8+zorin2/app/Makefile.am gimp-2.10.14+om/app/Makefile.am --- gimp-2.10.8+zorin2/app/Makefile.am 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/Makefile.am 2019-06-12 16:43:38.000000000 +0000 @@ -1,5 +1,11 @@ ## Process this file with automake to produce Makefile.in +if PLATFORM_OSX +xobjective_c = "-xobjective-c" +xobjective_cxx = "-xobjective-c++" +xnone = "-xnone" +endif + libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la @@ -22,6 +28,7 @@ plug-in \ xcf \ file \ + file-data \ pdb \ widgets \ propgui \ @@ -92,6 +99,9 @@ # for GimpBacktrace libdbghelp = -ldbghelp +# for I_RpcExceptionFilter() +librpcrt4 = -lrpcrt4 + if HAVE_EXCHNDL exchndl = -lexchndl endif @@ -100,7 +110,7 @@ libm = -lm endif -if USE_BINRELOC +if ENABLE_RELOCATABLE_RESOURCES munix = -Wl,-rpath '-Wl,$$ORIGIN/../lib' endif @@ -125,6 +135,7 @@ $(LCMS_CFLAGS) \ $(GEXIV2_CFLAGS) \ $(psapi_cflags) \ + $(xobjective_c) \ -I$(includedir) \ -I$(builddir)/gui @@ -152,6 +163,7 @@ vectors/libappvectors.a \ core/libappcore.a \ file/libappfile.a \ + file-data/libappfile-data.a \ text/libapptext.a \ paint/libapppaint.a \ operations/libappoperations.a \ @@ -187,7 +199,8 @@ $(libm) \ $(libdl) \ $(libpsapi) \ - $(libdbghelp) + $(libdbghelp) \ + $(librpcrt4) gimp_@GIMP_APP_VERSION@_LDFLAGS = \ $(AM_LDFLAGS) \ diff -Nru gimp-2.10.8+zorin2/app/Makefile.in gimp-2.10.14+om/app/Makefile.in --- gimp-2.10.8+zorin2/app/Makefile.in 2018-11-08 16:17:37.000000000 +0000 +++ gimp-2.10.14+om/app/Makefile.in 2019-10-27 17:12:52.000000000 +0000 @@ -111,7 +111,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -144,8 +143,8 @@ am__DEPENDENCIES_2 = xcf/libappxcf.a pdb/libappinternal-procs.a \ pdb/libapppdb.a plug-in/libappplug-in.a \ vectors/libappvectors.a core/libappcore.a file/libappfile.a \ - text/libapptext.a paint/libapppaint.a \ - operations/libappoperations.a \ + file-data/libappfile-data.a text/libapptext.a \ + paint/libapppaint.a operations/libappoperations.a \ operations/layer-modes/libapplayermodes.a \ operations/layer-modes-legacy/libapplayermodeslegacy.a \ gegl/libappgegl.a config/libappconfig.a $(libgimpconfig) \ @@ -161,7 +160,7 @@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) gimp_@GIMP_APP_VERSION@_DEPENDENCIES = gui/libappgui.a \ menus/libappmenus.a actions/libappactions.a \ dialogs/libappdialogs.a tools/libapptools.a \ @@ -346,8 +345,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -477,7 +474,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -616,8 +612,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -740,6 +734,9 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +@PLATFORM_OSX_TRUE@xobjective_c = "-xobjective-c" +@PLATFORM_OSX_TRUE@xobjective_cxx = "-xobjective-c++" +@PLATFORM_OSX_TRUE@xnone = "-xnone" libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la @@ -762,6 +759,7 @@ plug-in \ xcf \ file \ + file-data \ pdb \ widgets \ propgui \ @@ -815,9 +813,12 @@ # for GimpBacktrace @OS_WIN32_TRUE@libdbghelp = -ldbghelp + +# for I_RpcExceptionFilter() +@OS_WIN32_TRUE@librpcrt4 = -lrpcrt4 @HAVE_EXCHNDL_TRUE@@OS_WIN32_TRUE@exchndl = -lexchndl @OS_WIN32_FALSE@libm = -lm -@USE_BINRELOC_TRUE@munix = -Wl,-rpath '-Wl,$$ORIGIN/../lib' +@ENABLE_RELOCATABLE_RESOURCES_TRUE@munix = -Wl,-rpath '-Wl,$$ORIGIN/../lib' @HAVE_WINDRES_TRUE@GIMPAPPRC = $(top_builddir)/build/windows/gimp.rc @HAVE_WINDRES_TRUE@GIMPRC = gimp-$(GIMP_APP_VERSION).rc.o @HAVE_WINDRES_TRUE@GIMPCONSOLERC = gimp-console-$(GIMP_APP_VERSION).rc.o @@ -836,6 +837,7 @@ $(LCMS_CFLAGS) \ $(GEXIV2_CFLAGS) \ $(psapi_cflags) \ + $(xobjective_c) \ -I$(includedir) \ -I$(builddir)/gui @@ -864,6 +866,7 @@ vectors/libappvectors.a \ core/libappcore.a \ file/libappfile.a \ + file-data/libappfile-data.a \ text/libapptext.a \ paint/libapppaint.a \ operations/libappoperations.a \ @@ -899,7 +902,8 @@ $(libm) \ $(libdl) \ $(libpsapi) \ - $(libdbghelp) + $(libdbghelp) \ + $(librpcrt4) gimp_@GIMP_APP_VERSION@_LDFLAGS = \ $(AM_LDFLAGS) \ diff -Nru gimp-2.10.8+zorin2/app/menus/file-menu.c gimp-2.10.14+om/app/menus/file-menu.c --- gimp-2.10.8+zorin2/app/menus/file-menu.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/file-menu.c 2019-10-26 18:49:18.000000000 +0000 @@ -30,6 +30,7 @@ #include "core/gimpviewable.h" #include "widgets/gimpaction.h" +#include "widgets/gimpactionimpl.h" #include "widgets/gimpuimanager.h" #include "file-menu.h" @@ -47,19 +48,16 @@ file_menu_setup (GimpUIManager *manager, const gchar *ui_path) { - GtkUIManager *ui_manager; - gint n_entries; - guint merge_id; - gint i; + gint n_entries; + guint merge_id; + gint i; g_return_if_fail (GIMP_IS_UI_MANAGER (manager)); g_return_if_fail (ui_path != NULL); - ui_manager = GTK_UI_MANAGER (manager); - n_entries = GIMP_GUI_CONFIG (manager->gimp->config)->last_opened_size; - merge_id = gtk_ui_manager_new_merge_id (ui_manager); + merge_id = gimp_ui_manager_new_merge_id (manager); for (i = 0; i < n_entries; i++) { @@ -71,18 +69,18 @@ action_name = g_strdup_printf ("file-open-recent-%02d", i + 1); action_path = g_strdup_printf ("%s/File/Open Recent/Files", ui_path); - gtk_ui_manager_add_ui (ui_manager, merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); full_path = g_strconcat (action_path, "/", action_name, NULL); - widget = gtk_ui_manager_get_widget (ui_manager, full_path); + widget = gimp_ui_manager_get_widget (manager, full_path); if (widget) { - GtkAction *action; + GimpAction *action; action = gimp_ui_manager_find_action (manager, "file", action_name); @@ -105,15 +103,16 @@ GtkTooltip *tooltip, GimpAction *action) { - gchar *text; + GimpActionImpl *impl = GIMP_ACTION_IMPL (action); + gchar *text; text = gtk_widget_get_tooltip_text (widget); gtk_tooltip_set_text (tooltip, text); g_free (text); gtk_tooltip_set_icon (tooltip, - gimp_viewable_get_pixbuf (action->viewable, - action->context, + gimp_viewable_get_pixbuf (impl->viewable, + impl->context, GIMP_THUMB_SIZE_NORMAL, GIMP_THUMB_SIZE_NORMAL)); diff -Nru gimp-2.10.8+zorin2/app/menus/filters-menu.c gimp-2.10.14+om/app/menus/filters-menu.c --- gimp-2.10.8+zorin2/app/menus/filters-menu.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/filters-menu.c 2019-10-26 18:49:18.000000000 +0000 @@ -42,7 +42,7 @@ g_return_if_fail (GIMP_IS_UI_MANAGER (manager)); g_return_if_fail (ui_path != NULL); - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); for (i = 0; i < gimp_filter_history_size (manager->gimp); i++) { @@ -53,10 +53,10 @@ action_path = g_strdup_printf ("%s/Filters/Recently Used/Filters", ui_path); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (action_name); g_free (action_path); diff -Nru gimp-2.10.8+zorin2/app/menus/Makefile.in gimp-2.10.14+om/app/menus/Makefile.in --- gimp-2.10.8+zorin2/app/menus/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/menus/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -220,8 +219,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -351,7 +348,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -490,8 +486,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/menus/plug-in-menus.c gimp-2.10.14+om/app/menus/plug-in-menus.c --- gimp-2.10.8+zorin2/app/menus/plug-in-menus.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/plug-in-menus.c 2019-10-26 18:49:18.000000000 +0000 @@ -97,7 +97,7 @@ plug_in_manager = manager->gimp->plug_in_manager; - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); for (i = 0; i < manager->gimp->config->filter_history_size; i++) { @@ -108,10 +108,10 @@ action_path = g_strdup_printf ("%s/Filters/Recently Used/Plug-ins", ui_path); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (action_name); g_free (action_path); @@ -266,8 +266,7 @@ g_free (merge_key); if (merge_id) - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), - merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); break; } @@ -404,7 +403,7 @@ if (! merge_id) { - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), merge_key, GUINT_TO_POINTER (merge_id)); } @@ -416,7 +415,7 @@ if (! menu_merge_id) { - menu_merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + menu_merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), "plug-in-menu-merge-id", GUINT_TO_POINTER (menu_merge_id)); } @@ -435,12 +434,12 @@ GIMP_LOG (MENUS, "adding menu item for '%s' (@ %s)", gimp_object_get_name (proc), action_path); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, - gimp_object_get_name (proc), - gimp_object_get_name (proc), - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, + gimp_object_get_name (proc), + gimp_object_get_name (proc), + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (action_path); g_free (path); @@ -494,7 +493,7 @@ action_path = g_strdup_printf ("%s%s", ui_path, strchr (menu_path, '/')); - if (! gtk_ui_manager_get_widget (GTK_UI_MANAGER (manager), action_path)) + if (! gimp_ui_manager_get_widget (manager, action_path)) { gchar *parent_menu_path = g_strdup (menu_path); gchar *parent_action_path = NULL; @@ -517,26 +516,25 @@ action_path = g_strdup_printf ("%s/%s", parent_action_path, menu_item_name); - if (! gtk_ui_manager_get_widget (GTK_UI_MANAGER (manager), - action_path)) + if (! gimp_ui_manager_get_widget (manager, action_path)) { GIMP_LOG (MENUS, "adding menu '%s' at path '%s' for action '%s'", menu_item_name, action_path, menu_path); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - parent_action_path, menu_item_name, - menu_path, - GTK_UI_MANAGER_MENU, - FALSE); - - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, "Menus", NULL, - GTK_UI_MANAGER_PLACEHOLDER, - FALSE); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, "Separator", NULL, - GTK_UI_MANAGER_SEPARATOR, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + parent_action_path, menu_item_name, + menu_path, + GTK_UI_MANAGER_MENU, + FALSE); + + gimp_ui_manager_add_ui (manager, merge_id, + action_path, "Menus", NULL, + GTK_UI_MANAGER_PLACEHOLDER, + FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, "Separator", NULL, + GTK_UI_MANAGER_SEPARATOR, + FALSE); } g_free (parent_action_path); @@ -556,8 +554,7 @@ { gchar *placeholder_path = g_strdup_printf ("%s/%s", action_path, "Menus"); - if (gtk_ui_manager_get_widget (GTK_UI_MANAGER (manager), - placeholder_path)) + if (gimp_ui_manager_get_widget (manager, placeholder_path)) { g_free (action_path); diff -Nru gimp-2.10.8+zorin2/app/menus/tool-options-menu.c gimp-2.10.14+om/app/menus/tool-options-menu.c --- gimp-2.10.8+zorin2/app/menus/tool-options-menu.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/tool-options-menu.c 2019-10-26 18:49:18.000000000 +0000 @@ -80,12 +80,12 @@ if (merge_id) { - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); g_object_set_data (G_OBJECT (manager), "tool-options-merge-id", GINT_TO_POINTER (0)); - gtk_ui_manager_ensure_update (GTK_UI_MANAGER (manager)); + gimp_ui_manager_ensure_update (manager); } } @@ -104,7 +104,7 @@ if (! tool_info->presets) return; - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), "tool-options-merge-id", GUINT_TO_POINTER (merge_id)); @@ -125,7 +125,7 @@ "Delete", "delete", tool_info->presets); - gtk_ui_manager_ensure_update (GTK_UI_MANAGER (manager)); + gimp_ui_manager_ensure_update (manager); } static void @@ -150,10 +150,10 @@ which_action, i); path = g_strdup_printf ("%s/%s", ui_path, menu_path); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (action_name); g_free (path); diff -Nru gimp-2.10.8+zorin2/app/menus/window-menu.c gimp-2.10.14+om/app/menus/window-menu.c --- gimp-2.10.8+zorin2/app/menus/window-menu.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/window-menu.c 2019-10-26 18:49:18.000000000 +0000 @@ -87,15 +87,14 @@ GdkDisplay *display, GimpUIManager *manager) { - GtkUIManager *ui_manager = GTK_UI_MANAGER (manager); - const gchar *group_name; - const gchar *ui_path; - const gchar *display_name; - gchar *action_path; - gchar *merge_key; - guint merge_id; - gint n_screens; - gint i; + const gchar *group_name; + const gchar *ui_path; + const gchar *display_name; + gchar *action_path; + gchar *merge_key; + guint merge_id; + gint n_screens; + gint i; group_name = g_object_get_data (G_OBJECT (manager), "move-to-screen-group-name"); @@ -110,7 +109,7 @@ merge_key = g_strdup_printf ("%s-display-merge-id", display_name); - merge_id = gtk_ui_manager_new_merge_id (ui_manager); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), merge_key, GUINT_TO_POINTER (merge_id)); @@ -131,10 +130,10 @@ group_name, screen_name); g_free (screen_name); - gtk_ui_manager_add_ui (ui_manager, merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (action_name); } @@ -165,5 +164,5 @@ g_free (merge_key); if (merge_id) - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); } diff -Nru gimp-2.10.8+zorin2/app/menus/windows-menu.c gimp-2.10.14+om/app/menus/windows-menu.c --- gimp-2.10.8+zorin2/app/menus/windows-menu.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/menus/windows-menu.c 2019-10-26 18:49:18.000000000 +0000 @@ -33,6 +33,7 @@ #include "core/gimpviewable.h" #include "widgets/gimpaction.h" +#include "widgets/gimpactionimpl.h" #include "widgets/gimpdialogfactory.h" #include "widgets/gimpdock.h" #include "widgets/gimpdockwindow.h" @@ -178,7 +179,7 @@ merge_key)); if (merge_id) - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); g_object_set_data (G_OBJECT (manager), merge_key, NULL); @@ -205,7 +206,7 @@ * the same ones may simply cancel the effect of the removal, hence * losing the menu reordering. */ - gtk_ui_manager_ensure_update (GTK_UI_MANAGER (manager)); + gimp_ui_manager_ensure_update (manager); for (i = new_index; i < n_display; i++) { @@ -243,24 +244,23 @@ action_name = gimp_display_get_action_name (display); action_path = g_strdup_printf ("%s/Windows/Images", ui_path); - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), merge_key, GUINT_TO_POINTER (merge_id)); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); full_path = g_strconcat (action_path, "/", action_name, NULL); - widget = gtk_ui_manager_get_widget (GTK_UI_MANAGER (manager), - full_path); + widget = gimp_ui_manager_get_widget (manager, full_path); if (widget) { - GtkAction *action; + GimpAction *action; action = gimp_ui_manager_find_action (manager, "windows", action_name); @@ -301,15 +301,15 @@ ui_path); merge_key = windows_menu_dock_window_to_merge_id (dock_window); - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), merge_key, GUINT_TO_POINTER (merge_id)); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - FALSE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + FALSE); g_free (merge_key); g_free (action_path); @@ -325,7 +325,7 @@ guint merge_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (manager), merge_key)); if (merge_id) - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); g_object_set_data (G_OBJECT (manager), merge_key, NULL); @@ -360,15 +360,15 @@ action_path = g_strdup_printf ("%s/Windows/Recently Closed Docks", ui_path); merge_key = g_strdup_printf ("windows-recent-%04d-merge-id", info_id); - merge_id = gtk_ui_manager_new_merge_id (GTK_UI_MANAGER (manager)); + merge_id = gimp_ui_manager_new_merge_id (manager); g_object_set_data (G_OBJECT (manager), merge_key, GUINT_TO_POINTER (merge_id)); - gtk_ui_manager_add_ui (GTK_UI_MANAGER (manager), merge_id, - action_path, action_name, action_name, - GTK_UI_MANAGER_MENUITEM, - TRUE); + gimp_ui_manager_add_ui (manager, merge_id, + action_path, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, + TRUE); g_free (merge_key); g_free (action_path); @@ -393,7 +393,7 @@ merge_key)); if (merge_id) - gtk_ui_manager_remove_ui (GTK_UI_MANAGER (manager), merge_id); + gimp_ui_manager_remove_ui (manager, merge_id); g_object_set_data (G_OBJECT (manager), merge_key, NULL); @@ -408,12 +408,16 @@ GtkTooltip *tooltip, GimpAction *action) { - GimpImage *image = GIMP_IMAGE (action->viewable); - gchar *text; - gdouble xres; - gdouble yres; - gint width; - gint height; + GimpActionImpl *impl = GIMP_ACTION_IMPL (action); + GimpImage *image = GIMP_IMAGE (impl->viewable); + gchar *text; + gdouble xres; + gdouble yres; + gint width; + gint height; + + if (! image) + return FALSE; text = gtk_widget_get_tooltip_text (widget); gtk_tooltip_set_text (tooltip, text); @@ -428,8 +432,8 @@ &width, &height, NULL); gtk_tooltip_set_icon (tooltip, - gimp_viewable_get_pixbuf (action->viewable, - action->context, + gimp_viewable_get_pixbuf (impl->viewable, + impl->context, width, height)); return TRUE; diff -Nru gimp-2.10.8+zorin2/app/operations/gimpcurvesconfig.c gimp-2.10.14+om/app/operations/gimpcurvesconfig.c --- gimp-2.10.8+zorin2/app/operations/gimpcurvesconfig.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpcurvesconfig.c 2019-06-12 16:43:38.000000000 +0000 @@ -402,13 +402,10 @@ gimp_data_freeze (GIMP_DATA (curve)); gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH); - gimp_curve_set_n_points (curve, n_points); - - /* unset the last point */ - gimp_curve_set_point (curve, curve->n_points - 1, -1.0, -1.0); + gimp_curve_clear_points (curve); for (i = 0; i < n_points; i++) - gimp_curve_set_point (curve, i, + gimp_curve_add_point (curve, (gdouble) points[i * 2], (gdouble) points[i * 2 + 1]); @@ -598,18 +595,18 @@ gimp_data_freeze (GIMP_DATA (curve)); gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH); - gimp_curve_set_n_points (curve, GIMP_CURVE_N_CRUFT_POINTS); - - gimp_curve_reset (curve, FALSE); + gimp_curve_clear_points (curve); for (j = 0; j < GIMP_CURVE_N_CRUFT_POINTS; j++) { - if (index[i][j] < 0 || value[i][j] < 0) - gimp_curve_set_point (curve, j, -1.0, -1.0); - else - gimp_curve_set_point (curve, j, - (gdouble) index[i][j] / 255.0, - (gdouble) value[i][j] / 255.0); + gdouble x; + gdouble y; + + x = (gdouble) index[i][j] / 255.0; + y = (gdouble) value[i][j] / 255.0; + + if (x >= 0.0) + gimp_curve_add_point (curve, x, y); } gimp_data_thaw (GIMP_DATA (curve)); @@ -643,53 +640,39 @@ GimpCurve *curve = config->curve[i]; gint j; - if (curve->curve_type == GIMP_CURVE_FREE) + if (curve->curve_type == GIMP_CURVE_SMOOTH) { - gint n_points; - - for (j = 0; j < curve->n_points; j++) - { - curve->points[j].x = -1; - curve->points[j].y = -1; - } - - /* pick some points from the curve and make them control - * points - */ - n_points = CLAMP (9, curve->n_points / 2, curve->n_points); - - for (j = 0; j < n_points; j++) - { - gint sample = j * (curve->n_samples - 1) / (n_points - 1); - gint point = j * (curve->n_points - 1) / (n_points - 1); + g_object_ref (curve); + } + else + { + curve = GIMP_CURVE (gimp_data_duplicate (GIMP_DATA (curve))); - curve->points[point].x = ((gdouble) sample / - (gdouble) (curve->n_samples - 1)); - curve->points[point].y = curve->samples[sample]; - } + gimp_curve_set_curve_type (curve, GIMP_CURVE_SMOOTH); } - for (j = 0; j < curve->n_points; j++) + for (j = 0; j < GIMP_CURVE_N_CRUFT_POINTS; j++) { - /* don't use gimp_curve_get_point() because that doesn't - * work when the curve type is GIMP_CURVE_FREE - */ - gdouble x = curve->points[j].x; - gdouble y = curve->points[j].y; + gint x = -1; + gint y = -1; - if (x < 0.0 || y < 0.0) - { - g_string_append_printf (string, "%d %d ", -1, -1); - } - else + if (j < gimp_curve_get_n_points (curve)) { - g_string_append_printf (string, "%d %d ", - (gint) (x * 255.999), - (gint) (y * 255.999)); + gdouble point_x; + gdouble point_y; + + gimp_curve_get_point (curve, j, &point_x, &point_y); + + x = floor (point_x * 255.999); + y = floor (point_y * 255.999); } + + g_string_append_printf (string, "%d %d ", x, y); } g_string_append_printf (string, "\n"); + + g_object_unref (curve); } if (! g_output_stream_write_all (output, string->str, string->len, diff -Nru gimp-2.10.8+zorin2/app/operations/gimplevelsconfig.c gimp-2.10.14+om/app/operations/gimplevelsconfig.c --- gimp-2.10.8+zorin2/app/operations/gimplevelsconfig.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimplevelsconfig.c 2019-10-26 18:49:18.000000000 +0000 @@ -696,17 +696,14 @@ channel++) { GimpCurve *curve = curves->curve[channel]; - const gint n_points = gimp_curve_get_n_points (curve); static const gint n = 8; - gint point = -1; gdouble gamma = config->gamma[channel]; gdouble delta_in; gdouble delta_out; gdouble x, y; /* clear the points set by default */ - gimp_curve_set_point (curve, 0, -1, -1); - gimp_curve_set_point (curve, n_points - 1, -1, -1); + gimp_curve_clear_points (curve); delta_in = config->high_input[channel] - config->low_input[channel]; delta_out = config->high_output[channel] - config->low_output[channel]; @@ -714,8 +711,7 @@ x = config->low_input[channel]; y = config->low_output[channel]; - point = CLAMP (n_points * x, point + 1, n_points - 1 - n); - gimp_curve_set_point (curve, point, x, y); + gimp_curve_add_point (curve, x, y); if (delta_out != 0 && gamma != 1.0) { @@ -755,8 +751,7 @@ x = config->low_input[channel] + dx; y = config->low_output[channel] + delta_out * gimp_operation_levels_map_input (config, channel, x); - point = CLAMP (n_points * x, point + 1, n_points - 1 - n + i); - gimp_curve_set_point (curve, point, x, y); + gimp_curve_add_point (curve, x, y); } } else @@ -792,8 +787,7 @@ y = config->low_output[channel] + dy; x = config->low_input[channel] + delta_in * gimp_operation_levels_map_input (config_inv, channel, y); - point = CLAMP (n_points * x, point + 1, n_points - 1 - n + i); - gimp_curve_set_point (curve, point, x, y); + gimp_curve_add_point (curve, x, y); } g_object_unref (config_inv); @@ -803,8 +797,7 @@ x = config->high_input[channel]; y = config->high_output[channel]; - point = CLAMP (n_points * x, point + 1, n_points - 1); - gimp_curve_set_point (curve, point, x, y); + gimp_curve_add_point (curve, x, y); } return curves; @@ -943,8 +936,8 @@ (gint) (config->high_input[i] * 255.999), (gint) (config->low_output[i] * 255.999), (gint) (config->high_output[i] * 255.999), - g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", - config->gamma[i])); + g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, + config->gamma[i])); } if (! g_output_stream_write_all (output, string->str, string->len, diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationbuffersourcevalidate.c gimp-2.10.14+om/app/operations/gimpoperationbuffersourcevalidate.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationbuffersourcevalidate.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationbuffersourcevalidate.c 2019-10-26 18:49:18.000000000 +0000 @@ -18,17 +18,12 @@ * along with this program. If not, see . */ -#define GEGL_ITERATOR2_API #include "config.h" #include #include #include -#include "libgimpcolor/gimpcolor.h" -#include "libgimpconfig/gimpconfig.h" -#include "libgimpmath/gimpmath.h" - #include "operations-types.h" #include "gegl/gimptilehandlervalidate.h" @@ -87,7 +82,7 @@ operation_class->process = gimp_operation_buffer_source_validate_process; operation_class->threaded = FALSE; - operation_class->no_cache = TRUE; + operation_class->cache_policy = GEGL_CACHE_POLICY_NEVER; gegl_operation_class_set_keys (operation_class, "name", "gimp:buffer-source-validate", @@ -240,89 +235,17 @@ if (validate_handler) { - gint n_threads; + GeglRectangle rect; - g_object_get (gegl_config (), - "threads", &n_threads, - NULL); - - /* the main reason to validate the buffer during processing is to - * avoid threading issues. skip validation if not using - * multithreading. - */ - if (n_threads > 1) - { - gint shift_x; - gint shift_y; - gint tile_width; - gint tile_height; - cairo_rectangle_int_t rect; - cairo_region_overlap_t overlap; - - g_object_get (buffer_source_validate->buffer, - "shift-x", &shift_x, - "shift-y", &shift_y, - "tile-width", &tile_width, - "tile-height", &tile_height, - NULL); - - /* align the rectangle to the tile grid */ - rect.x = (gint) floor ((gdouble) (result->x + shift_x) / tile_width) * tile_width; - rect.y = (gint) floor ((gdouble) (result->y + shift_y) / tile_height) * tile_height; - rect.width = (gint) ceil ((gdouble) (result->x + result->width + shift_x) / tile_width) * tile_width - rect.x; - rect.height = (gint) ceil ((gdouble) (result->y + result->height + shift_y) / tile_height) * tile_height - rect.y; - - /* check if the rectangle interescts with the dirty region */ - overlap = cairo_region_contains_rectangle (validate_handler->dirty_region, - &rect); - - if (overlap != CAIRO_REGION_OVERLAP_OUT) - { - GeglBufferIterator *iter; - - /* if the rectangle is not entirely within the dirty - * region ... - */ - if (overlap == CAIRO_REGION_OVERLAP_PART) - { - cairo_region_t *region; - cairo_rectangle_int_t intersection; - - /* ... intersect it with region and use the result's - * bounds - */ - region = cairo_region_copy (validate_handler->dirty_region); - - cairo_region_intersect_rectangle (region, &rect); - cairo_region_get_extents (region, &intersection); - - cairo_region_destroy (region); - - /* realign the rectangle to the tile grid */ - rect.x = (gint) floor ((gdouble) (intersection.x ) / tile_width) * tile_width; - rect.y = (gint) floor ((gdouble) (intersection.y ) / tile_height) * tile_height; - rect.width = (gint) ceil ((gdouble) (intersection.x + intersection.width ) / tile_width) * tile_width - rect.x; - rect.height = (gint) ceil ((gdouble) (intersection.y + intersection.height) / tile_height) * tile_height - rect.y; - } - - rect.x -= shift_x; - rect.y -= shift_y; - - /* iterate over the rectangle -- this implicitly causes - * validation - */ - iter = gegl_buffer_iterator_new (buffer, - GEGL_RECTANGLE (rect.x, - rect.y, - rect.width, - rect.height), - level, NULL, - GEGL_BUFFER_READ, - GEGL_ABYSS_NONE, 1); - - while (gegl_buffer_iterator_next (iter)); - } - } + /* align the rectangle to the tile grid */ + gegl_rectangle_align_to_buffer ( + &rect, result, buffer_source_validate->buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + gimp_tile_handler_validate_validate (validate_handler, + buffer_source_validate->buffer, + &rect, + TRUE); } gegl_operation_context_set_object (context, "output", G_OBJECT (buffer)); diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationcagecoefcalc.c gimp-2.10.14+om/app/operations/gimpoperationcagecoefcalc.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationcagecoefcalc.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationcagecoefcalc.c 2019-04-07 11:38:14.000000000 +0000 @@ -20,7 +20,6 @@ #include "config.h" #include -#define GEGL_ITERATOR2_API #include #include "libgimpmath/gimpmath.h" @@ -72,7 +71,7 @@ operation_class->prepare = gimp_operation_cage_coef_calc_prepare; operation_class->get_bounding_box = gimp_operation_cage_coef_calc_get_bounding_box; - operation_class->no_cache = FALSE; + operation_class->cache_policy = GEGL_CACHE_POLICY_ALWAYS; operation_class->get_cached_region = NULL; source_class->process = gimp_operation_cage_coef_calc_process; diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationcagetransform.c gimp-2.10.14+om/app/operations/gimpoperationcagetransform.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationcagetransform.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationcagetransform.c 2019-10-26 18:49:18.000000000 +0000 @@ -20,7 +20,6 @@ #include "config.h" #include -#define GEGL_ITERATOR2_API #include #include @@ -109,7 +108,6 @@ operation_class->get_required_for_output = gimp_operation_cage_transform_get_required_for_output; operation_class->get_cached_region = gimp_operation_cage_transform_get_cached_region; - operation_class->no_cache = FALSE; operation_class->get_bounding_box = gimp_operation_cage_transform_get_bounding_box; /* XXX Temporarily disable multi-threading on this operation because * it is much faster when single-threaded. See bug 787663. @@ -273,8 +271,8 @@ } if (!output_set) { - output[0] = x; - output[1] = y; + output[0] = x + 0.5; + output[1] = y + 0.5; } output += 2; @@ -387,8 +385,7 @@ gint recursion_depth, gfloat *coords) { - GeglRectangle rect = { 0, 0, 1, 1 }; - gint xmin, xmax, ymin, ymax; + gint xmin, xmax, ymin, ymax, x, y; /* Stop recursion if all 3 vertices of the triangle are outside the * ROI (left/right or above/below). @@ -407,20 +404,24 @@ p2_d.y < roi->y && p3_d.y < roi->y) return; - xmin = xmax = p1_d.x; - ymin = ymax = p1_d.y; + xmin = xmax = lrint (p1_d.x); + ymin = ymax = lrint (p1_d.y); - if (xmin > p2_d.x) xmin = p2_d.x; - if (xmin > p3_d.x) xmin = p3_d.x; - - if (xmax < p2_d.x) xmax = p2_d.x; - if (xmax < p3_d.x) xmax = p3_d.x; - - if (ymin > p2_d.y) ymin = p2_d.y; - if (ymin > p3_d.y) ymin = p3_d.y; - - if (ymax < p2_d.y) ymax = p2_d.y; - if (ymax < p3_d.y) ymax = p3_d.y; + x = lrint (p2_d.x); + xmin = MIN (x, xmin); + xmax = MAX (x, xmax); + + x = lrint (p3_d.x); + xmin = MIN (x, xmin); + xmax = MAX (x, xmax); + + y = lrint (p2_d.y); + ymin = MIN (y, ymin); + ymax = MAX (y, ymax); + + y = lrint (p3_d.y); + ymin = MIN (y, ymin); + ymax = MAX (y, ymax); /* test if there is no more pixel in the triangle */ if (xmin == xmax || ymin == ymax) @@ -440,11 +441,8 @@ { gdouble a, b, c, denom, x, y; - rect.x = xmax; - rect.y = ymax; - - x = (gdouble) xmax; - y = (gdouble) ymax; + x = (gdouble) xmin + 0.5; + y = (gdouble) ymin + 0.5; denom = (p2_d.x - p1_d.x) * p3_d.y + (p1_d.x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * p1_d.y; a = ((p2_d.x - x) * p3_d.y + (x - p3_d.x) * p2_d.y + (p3_d.x - p2_d.x) * y) / denom; @@ -456,6 +454,12 @@ */ if ((a > 0 && b > 0 && c > 0) || (a < 0 && b < 0 && c < 0)) { + GeglRectangle rect = { 0, 0, 1, 1 }; + gfloat coords[2]; + + rect.x = xmin; + rect.y = ymin; + coords[0] = (a * p1_s.x + b * p2_s.x + c * p3_s.x); coords[1] = (a * p1_s.y + b * p2_s.y + c * p3_s.y); diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationcomposecrop.c gimp-2.10.14+om/app/operations/gimpoperationcomposecrop.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationcomposecrop.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationcomposecrop.c 2019-10-26 18:49:18.000000000 +0000 @@ -99,14 +99,14 @@ g_param_spec_int ("x", "x", "x", - 0, G_MAXINT, 0, + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_Y, g_param_spec_int ("y", "y", "y", - 0, G_MAXINT, 0, + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_WIDTH, diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationequalize.c gimp-2.10.14+om/app/operations/gimpoperationequalize.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationequalize.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationequalize.c 2019-10-26 18:49:18.000000000 +0000 @@ -172,8 +172,8 @@ pixels = gimp_histogram_get_count (self->histogram, GIMP_HISTOGRAM_VALUE, 0, n_bins - 1); - if (gimp_histogram_n_channels (self->histogram) == 1 || - gimp_histogram_n_channels (self->histogram) == 2) + if (gimp_histogram_n_components (self->histogram) == 1 || + gimp_histogram_n_components (self->histogram) == 2) max = 1; else max = 3; diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationfillsource.c gimp-2.10.14+om/app/operations/gimpoperationfillsource.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationfillsource.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationfillsource.c 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,254 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationfillsource.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "operations-types.h" + +#include "core/gimpdrawable.h" +#include "core/gimpfilloptions.h" + +#include "gimpoperationfillsource.h" + + +enum +{ + PROP_0, + PROP_OPTIONS, + PROP_DRAWABLE, + PROP_PATTERN_OFFSET_X, + PROP_PATTERN_OFFSET_Y, +}; + + +static void gimp_operation_fill_source_dispose (GObject *object); +static void gimp_operation_fill_source_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_operation_fill_source_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static GeglRectangle gimp_operation_fill_source_get_bounding_box (GeglOperation *operation); +static void gimp_operation_fill_source_prepare (GeglOperation *operation); +static gboolean gimp_operation_fill_source_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_pad, + const GeglRectangle *result, + gint level); + + +G_DEFINE_TYPE (GimpOperationFillSource, gimp_operation_fill_source, + GEGL_TYPE_OPERATION_SOURCE) + +#define parent_class gimp_operation_fill_source_parent_class + + +static void +gimp_operation_fill_source_class_init (GimpOperationFillSourceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); + + object_class->dispose = gimp_operation_fill_source_dispose; + object_class->set_property = gimp_operation_fill_source_set_property; + object_class->get_property = gimp_operation_fill_source_get_property; + + operation_class->get_bounding_box = gimp_operation_fill_source_get_bounding_box; + operation_class->prepare = gimp_operation_fill_source_prepare; + operation_class->process = gimp_operation_fill_source_process; + + operation_class->threaded = FALSE; + operation_class->cache_policy = GEGL_CACHE_POLICY_NEVER; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:fill-source", + "categories", "gimp", + "description", "GIMP Fill Source operation", + NULL); + + g_object_class_install_property (object_class, PROP_OPTIONS, + g_param_spec_object ("options", + "Options", + "Fill options", + GIMP_TYPE_FILL_OPTIONS, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_DRAWABLE, + g_param_spec_object ("drawable", + "Drawable", + "Fill drawable", + GIMP_TYPE_DRAWABLE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_PATTERN_OFFSET_X, + g_param_spec_int ("pattern-offset-x", + "Pattern X-offset", + "Pattern X-offset", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_PATTERN_OFFSET_Y, + g_param_spec_int ("pattern-offset-y", + "Pattern Y-offset", + "Pattern Y-offset", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +gimp_operation_fill_source_init (GimpOperationFillSource *self) +{ +} + +static void +gimp_operation_fill_source_dispose (GObject *object) +{ + GimpOperationFillSource *fill_source = GIMP_OPERATION_FILL_SOURCE (object); + + g_clear_object (&fill_source->options); + g_clear_object (&fill_source->drawable); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_operation_fill_source_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpOperationFillSource *fill_source = GIMP_OPERATION_FILL_SOURCE (object); + + switch (property_id) + { + case PROP_OPTIONS: + g_value_set_object (value, fill_source->options); + break; + + case PROP_DRAWABLE: + g_value_set_object (value, fill_source->drawable); + break; + + case PROP_PATTERN_OFFSET_X: + g_value_set_int (value, fill_source->pattern_offset_x); + break; + + case PROP_PATTERN_OFFSET_Y: + g_value_set_int (value, fill_source->pattern_offset_y); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_operation_fill_source_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpOperationFillSource *fill_source = GIMP_OPERATION_FILL_SOURCE (object); + + switch (property_id) + { + case PROP_OPTIONS: + g_set_object (&fill_source->options, g_value_get_object (value)); + break; + + case PROP_DRAWABLE: + g_set_object (&fill_source->drawable, g_value_get_object (value)); + break; + + case PROP_PATTERN_OFFSET_X: + fill_source->pattern_offset_x = g_value_get_int (value); + break; + + case PROP_PATTERN_OFFSET_Y: + fill_source->pattern_offset_y = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static GeglRectangle +gimp_operation_fill_source_get_bounding_box (GeglOperation *operation) +{ + return gegl_rectangle_infinite_plane (); +} + +static void +gimp_operation_fill_source_prepare (GeglOperation *operation) +{ + GimpOperationFillSource *fill_source = GIMP_OPERATION_FILL_SOURCE (operation); + const Babl *format = NULL; + + if (fill_source->options && fill_source->drawable) + { + format = gimp_fill_options_get_format (fill_source->options, + fill_source->drawable); + } + + gegl_operation_set_format (operation, "output", format); +} + +static gboolean +gimp_operation_fill_source_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_pad, + const GeglRectangle *result, + gint level) +{ + GimpOperationFillSource *fill_source = GIMP_OPERATION_FILL_SOURCE (operation); + + if (fill_source->options && fill_source->drawable) + { + GeglBuffer *buffer; + GeglRectangle rect; + + gegl_rectangle_align_to_buffer ( + &rect, result, + gimp_drawable_get_buffer (fill_source->drawable), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + buffer = gimp_fill_options_create_buffer (fill_source->options, + fill_source->drawable, + &rect, + fill_source->pattern_offset_x, + fill_source->pattern_offset_y); + + gegl_operation_context_take_object (context, "output", G_OBJECT (buffer)); + } + + return TRUE; +} diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationfillsource.h gimp-2.10.14+om/app/operations/gimpoperationfillsource.h --- gimp-2.10.8+zorin2/app/operations/gimpoperationfillsource.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationfillsource.h 2019-04-07 11:38:14.000000000 +0000 @@ -0,0 +1,55 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationfillsource.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_OPERATION_FILL_SOURCE_H__ +#define __GIMP_OPERATION_FILL_SOURCE_H__ + + +#define GIMP_TYPE_OPERATION_FILL_SOURCE (gimp_operation_fill_source_get_type ()) +#define GIMP_OPERATION_FILL_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_FILL_SOURCE, GimpOperationFillSource)) +#define GIMP_OPERATION_FILL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_FILL_SOURCE, GimpOperationFillSourceClass)) +#define GIMP_IS_OPERATION_FILL_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_FILL_SOURCE)) +#define GIMP_IS_OPERATION_FILL_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_FILL_SOURCE)) +#define GIMP_OPERATION_FILL_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_FILL_SOURCE, GimpOperationFillSourceClass)) + + +typedef struct _GimpOperationFillSource GimpOperationFillSource; +typedef struct _GimpOperationFillSourceClass GimpOperationFillSourceClass; + +struct _GimpOperationFillSource +{ + GeglOperationSource parent_instance; + + GimpFillOptions *options; + GimpDrawable *drawable; + gint pattern_offset_x; + gint pattern_offset_y; +}; + +struct _GimpOperationFillSourceClass +{ + GeglOperationSourceClass parent_class; +}; + + +GType gimp_operation_fill_source_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_OPERATION_FILL_SOURCE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationgradient.c gimp-2.10.14+om/app/operations/gimpoperationgradient.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationgradient.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationgradient.c 2019-10-26 18:49:18.000000000 +0000 @@ -23,7 +23,6 @@ #include "config.h" #include -#define GEGL_ITERATOR2_API #include #include @@ -81,11 +80,9 @@ typedef struct { - GeglBuffer *buffer; - gfloat *row_data; - gint roi_x; - gint width; - GRand *dither_rand; + gfloat *data; + GeglRectangle roi; + GRand *dither_rand; } PutPixelData; @@ -142,12 +139,15 @@ gboolean clockwise); static gdouble gradient_calc_shapeburst_angular_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y); static gdouble gradient_calc_shapeburst_spherical_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y); static gdouble gradient_calc_shapeburst_dimpled_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y); @@ -161,6 +161,10 @@ GimpRGB *color, gpointer put_pixel_data); +static void gradient_dither_pixel (GimpRGB *color, + GRand *dither_rand, + gfloat *dest); + static gboolean gimp_operation_gradient_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, @@ -773,6 +777,8 @@ gdouble ang; double r; + offset = offset / 100.0; + ang0 = atan2 (axis[0], axis[1]) + G_PI; ang1 = atan2 (x, y) + G_PI; @@ -796,28 +802,48 @@ static gdouble gradient_calc_shapeburst_angular_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y) { gfloat value; + offset = offset / 100.0; + gegl_sampler_get (dist_sampler, x, y, NULL, &value, GEGL_ABYSS_NONE); value = 1.0 - value; + if (value < offset) + value = 0.0; + else if (offset == 1.0) + value = (value >= 1.0) ? 1.0 : 0.0; + else + value = (value - offset) / (1.0 - offset); + return value; } static gdouble gradient_calc_shapeburst_spherical_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y) { gfloat value; + offset = 1.0 - offset / 100.0; + gegl_sampler_get (dist_sampler, x, y, NULL, &value, GEGL_ABYSS_NONE); + if (value > offset) + value = 1.0; + else if (offset == 0.0) + value = (value <= 0.0) ? 0.0 : 1.0; + else + value = value / offset; + value = 1.0 - sin (0.5 * G_PI * value); return value; @@ -826,13 +852,23 @@ static gdouble gradient_calc_shapeburst_dimpled_factor (GeglSampler *dist_sampler, + gdouble offset, gdouble x, gdouble y) { gfloat value; + offset = 1.0 - offset / 100.0; + gegl_sampler_get (dist_sampler, x, y, NULL, &value, GEGL_ABYSS_NONE); + if (value > offset) + value = 1.0; + else if (offset == 0.0) + value = (value <= 0.0) ? 0.0 : 1.0; + else + value = value / offset; + value = cos (0.5 * G_PI * value); return value; @@ -892,16 +928,19 @@ case GIMP_GRADIENT_SHAPEBURST_ANGULAR: factor = gradient_calc_shapeburst_angular_factor (rbd->dist_sampler, + rbd->offset, x, y); break; case GIMP_GRADIENT_SHAPEBURST_SPHERICAL: factor = gradient_calc_shapeburst_spherical_factor (rbd->dist_sampler, + rbd->offset, x, y); break; case GIMP_GRADIENT_SHAPEBURST_DIMPLED: factor = gradient_calc_shapeburst_dimpled_factor (rbd->dist_sampler, + rbd->offset, x, y); break; @@ -983,27 +1022,14 @@ gpointer put_pixel_data) { PutPixelData *ppd = put_pixel_data; - const gint index = x - ppd->roi_x; - gfloat *dest = ppd->row_data + 4 * index; + const gint index = (y - ppd->roi.y) * ppd->roi.width + (x - ppd->roi.x); + gfloat *dest = ppd->data + 4 * index; if (ppd->dither_rand) { - gfloat r, g, b, a; - gint i = g_rand_int (ppd->dither_rand); + gradient_dither_pixel (color, ppd->dither_rand, dest); - r = color->r + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - g = color->g + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - b = color->b + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - - if (color->a > 0.0 && color->a < 1.0) - a = color->a + (gdouble) (i & 0xff) / 256.0 / 256.0; - else - a = color->a; - - *dest++ = MAX (r, 0.0); - *dest++ = MAX (g, 0.0); - *dest++ = MAX (b, 0.0); - *dest++ = MAX (a, 0.0); + dest += 4; } else { @@ -1012,12 +1038,31 @@ *dest++ = color->b; *dest++ = color->a; } +} + +static void +gradient_dither_pixel (GimpRGB *color, + GRand *dither_rand, + gfloat *dest) +{ + gfloat r, g, b, a; + guint i; + + i = g_rand_int (dither_rand); + + r = color->r + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8; + g = color->g + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8; + b = color->b + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; i >>= 8; + + if (color->a > 0.0 && color->a < 1.0) + a = color->a + (gdouble) (i & 0xff) / 256.0 / 256.0 - 0.5 / 256.0; + else + a = color->a; - /* Paint whole row if we are on the rightmost pixel */ - if (index == (ppd->width - 1)) - gegl_buffer_set (ppd->buffer, GEGL_RECTANGLE (ppd->roi_x, y, ppd->width, 1), - 0, babl_format ("R'G'B'A float"), ppd->row_data, - GEGL_AUTO_ROWSTRIDE); + *dest++ = CLAMP (r, 0.0, 1.0); + *dest++ = CLAMP (g, 0.0, 1.0); + *dest++ = CLAMP (b, 0.0, 1.0); + *dest++ = CLAMP (a, 0.0, 1.0); } static gboolean @@ -1036,6 +1081,10 @@ RenderBlendData rbd = { 0, }; + GeglBufferIterator *iter; + GeglRectangle *roi; + GRand *dither_rand = NULL; + if (! self->gradient) return TRUE; @@ -1098,45 +1147,38 @@ /* Render the gradient! */ + iter = gegl_buffer_iterator_new (output, result, 0, + babl_format ("R'G'B'A float"), + GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1); + roi = &iter->items[0].roi; + + if (self->dither) + dither_rand = g_rand_new (); + if (self->supersample) { - PutPixelData ppd = { 0, }; + PutPixelData ppd; + + ppd.dither_rand = dither_rand; - ppd.buffer = output; - ppd.row_data = g_malloc (sizeof (float) * 4 * result->width); - ppd.roi_x = result->x; - ppd.width = result->width; - if (self->dither) - ppd.dither_rand = g_rand_new (); - - gimp_adaptive_supersample_area (result->x, result->y, - result->x + result->width - 1, - result->y + result->height - 1, - self->supersample_depth, - self->supersample_threshold, - gradient_render_pixel, &rbd, - gradient_put_pixel, &ppd, - NULL, - NULL); - - if (self->dither) - g_rand_free (ppd.dither_rand); - g_free (ppd.row_data); + while (gegl_buffer_iterator_next (iter)) + { + ppd.data = iter->items[0].data; + ppd.roi = *roi; + + gimp_adaptive_supersample_area (roi->x, roi->y, + roi->x + roi->width - 1, + roi->y + roi->height - 1, + self->supersample_depth, + self->supersample_threshold, + gradient_render_pixel, &rbd, + gradient_put_pixel, &ppd, + NULL, + NULL); + } } else { - GeglBufferIterator *iter; - GeglRectangle *roi; - GRand *seed = NULL; - - iter = gegl_buffer_iterator_new (output, result, 0, - babl_format ("R'G'B'A float"), - GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1); - roi = &iter->items[0].roi; - - if (self->dither) - seed = g_rand_new (); - while (gegl_buffer_iterator_next (iter)) { gfloat *dest = iter->items[0].data; @@ -1144,35 +1186,18 @@ gint endy = roi->y + roi->height; gint x, y; - if (seed) + if (dither_rand) { - GRand *dither_rand = g_rand_new_with_seed (g_rand_int (seed)); - for (y = roi->y; y < endy; y++) for (x = roi->x; x < endx; x++) { GimpRGB color = { 0.0, 0.0, 0.0, 1.0 }; - gfloat r, g, b, a; - gint i = g_rand_int (dither_rand); gradient_render_pixel (x, y, &color, &rbd); + gradient_dither_pixel (&color, dither_rand, dest); - r = color.r + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - g = color.g + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - b = color.b + (gdouble) (i & 0xff) / 256.0 / 256.0; i >>= 8; - - if (color.a > 0.0 && color.a < 1.0) - a = color.a + (gdouble) (i & 0xff) / 256.0 / 256.0; - else - a = color.a; - - *dest++ = MAX (r, 0.0); - *dest++ = MAX (g, 0.0); - *dest++ = MAX (b, 0.0); - *dest++ = MAX (a, 0.0); + dest += 4; } - - g_rand_free (dither_rand); } else { @@ -1190,11 +1215,11 @@ } } } - - if (self->dither) - g_rand_free (seed); } + if (self->dither) + g_rand_free (dither_rand); + g_clear_object (&rbd.dist_sampler); return TRUE; diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationlevels.c gimp-2.10.14+om/app/operations/gimpoperationlevels.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationlevels.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationlevels.c 2019-06-12 16:43:38.000000000 +0000 @@ -201,7 +201,7 @@ else value = (value - config->low_input[channel]); - if (config->gamma[channel] != 0.0) + if (config->gamma[channel] != 0.0 && value > 0.0) value = pow (value, 1.0 / config->gamma[channel]); return value; diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.c gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +0,0 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * gimpoperationmaskcomponents.c - * Copyright (C) 2012 Michael Natterer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#include - -#include "operations-types.h" - -#include "gimpoperationmaskcomponents.h" - - -enum -{ - PROP_0, - PROP_MASK -}; - - -static void gimp_operation_mask_components_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); -static void gimp_operation_mask_components_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static void gimp_operation_mask_components_prepare (GeglOperation *operation); -static gboolean gimp_operation_mask_components_parent_process (GeglOperation *operation, - GeglOperationContext *context, - const gchar *output_prop, - const GeglRectangle *result, - gint level); -static gboolean gimp_operation_mask_components_process (GeglOperation *operation, - void *in_buf, - void *aux_buf, - void *out_buf, - glong samples, - const GeglRectangle *roi, - gint level); - - -G_DEFINE_TYPE (GimpOperationMaskComponents, gimp_operation_mask_components, - GEGL_TYPE_OPERATION_POINT_COMPOSER) - -#define parent_class gimp_operation_mask_components_parent_class - - -static void -gimp_operation_mask_components_class_init (GimpOperationMaskComponentsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); - GeglOperationPointComposerClass *point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); - - object_class->set_property = gimp_operation_mask_components_set_property; - object_class->get_property = gimp_operation_mask_components_get_property; - - gegl_operation_class_set_keys (operation_class, - "name", "gimp:mask-components", - "categories", "gimp", - "description", "Selectively pick components from src or aux", - NULL); - - operation_class->prepare = gimp_operation_mask_components_prepare; - //operation_class->process = gimp_operation_mask_components_parent_process; - - point_class->process = gimp_operation_mask_components_process; - - g_object_class_install_property (object_class, PROP_MASK, - g_param_spec_flags ("mask", - "Mask", - "The component mask", - GIMP_TYPE_COMPONENT_MASK, - GIMP_COMPONENT_MASK_ALL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); -} - -static void -gimp_operation_mask_components_init (GimpOperationMaskComponents *self) -{ -} - -static void -gimp_operation_mask_components_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object); - - switch (property_id) - { - case PROP_MASK: - g_value_set_flags (value, self->mask); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gimp_operation_mask_components_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object); - - switch (property_id) - { - case PROP_MASK: - self->mask = g_value_get_flags (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gimp_operation_mask_components_prepare (GeglOperation *operation) -{ - const Babl *format = gegl_operation_get_source_format (operation, "input"); - - if (format) - { - const Babl *model = babl_format_get_model (format); - - if (model == babl_model ("R'G'B'A")) - format = babl_format ("R'G'B'A float"); - else - format = babl_format ("RGBA float"); - } - else - { - format = babl_format ("RGBA float"); - } - - gegl_operation_set_format (operation, "input", format); - gegl_operation_set_format (operation, "aux", format); - gegl_operation_set_format (operation, "output", format); -} - -static gboolean -gimp_operation_mask_components_parent_process (GeglOperation *operation, - GeglOperationContext *context, - const gchar *output_prop, - const GeglRectangle *result, - gint level) -{ - GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation); -#if 0 - if (self->mask == 0) - { - GObject *input = gegl_operation_context_get_object (context, "input"); - - gegl_operation_context_set_object (context, "output", input); - - return TRUE; - } - else if (self->mask == GIMP_COMPONENT_MASK_ALL) - { - GObject *aux = gegl_operation_context_get_object (context, "aux"); - - gegl_operation_context_set_object (context, "output", aux); - - return TRUE; - } -#endif - return GEGL_OPERATION_CLASS (parent_class)->process (operation, context, - output_prop, result, - level); -} - -static gboolean -gimp_operation_mask_components_process (GeglOperation *operation, - void *in_buf, - void *aux_buf, - void *out_buf, - glong samples, - const GeglRectangle *roi, - gint level) -{ - GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation); - gfloat *src = in_buf; - gfloat *aux = aux_buf; - gfloat *dest = out_buf; - GimpComponentMask mask = self->mask; - static const gfloat nothing[] = { 0.0, 0.0, 0.0, 1.0 }; - -#if 0 - if (self->mask == 0) - { - if (in_buf != out_buf) - memcpy (out_buf, in_buf, sizeof (float) * 4 * samples); - } - else if (self->mask == GIMP_COMPONENT_MASK_ALL && aux_buf) - { - if (aux_buf != out_buf) - memcpy (out_buf, aux_buf, sizeof (float) * 4 * samples); - } - else -#endif - { - if (! aux) - aux = (gfloat *) nothing; - - while (samples--) - { - dest[RED] = (mask & GIMP_COMPONENT_MASK_RED) ? aux[RED] : src[RED]; - dest[GREEN] = (mask & GIMP_COMPONENT_MASK_GREEN) ? aux[GREEN] : src[GREEN]; - dest[BLUE] = (mask & GIMP_COMPONENT_MASK_BLUE) ? aux[BLUE] : src[BLUE]; - dest[ALPHA] = (mask & GIMP_COMPONENT_MASK_ALPHA) ? aux[ALPHA] : src[ALPHA]; - - src += 4; - - if (aux_buf) - aux += 4; - - dest += 4; - } - } - - return TRUE; -} diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.cc gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.cc --- gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.cc 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.cc 2019-10-26 18:49:18.000000000 +0000 @@ -0,0 +1,586 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationmaskcomponents.c + * Copyright (C) 2012 Michael Natterer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include + +extern "C" +{ + +#include "operations-types.h" + +#include "gimpoperationmaskcomponents.h" + +} /* extern "C" */ + + +enum +{ + PROP_0, + PROP_MASK, + PROP_ALPHA +}; + + +static void gimp_operation_mask_components_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_operation_mask_components_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void gimp_operation_mask_components_prepare (GeglOperation *operation); +static GeglRectangle gimp_operation_mask_components_get_bounding_box (GeglOperation *operation); +static gboolean gimp_operation_mask_components_parent_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_prop, + const GeglRectangle *result, + gint level); + +static gboolean gimp_operation_mask_components_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + + +G_DEFINE_TYPE (GimpOperationMaskComponents, gimp_operation_mask_components, + GEGL_TYPE_OPERATION_POINT_COMPOSER) + +#define parent_class gimp_operation_mask_components_parent_class + + +static void +gimp_operation_mask_components_class_init (GimpOperationMaskComponentsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); + GeglOperationPointComposerClass *point_class = GEGL_OPERATION_POINT_COMPOSER_CLASS (klass); + + object_class->set_property = gimp_operation_mask_components_set_property; + object_class->get_property = gimp_operation_mask_components_get_property; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:mask-components", + "categories", "gimp", + "description", "Selectively pick components from src or aux", + NULL); + + operation_class->prepare = gimp_operation_mask_components_prepare; + operation_class->get_bounding_box = gimp_operation_mask_components_get_bounding_box; + operation_class->process = gimp_operation_mask_components_parent_process; + + point_class->process = gimp_operation_mask_components_process; + + g_object_class_install_property (object_class, PROP_MASK, + g_param_spec_flags ("mask", + "Mask", + "The component mask", + GIMP_TYPE_COMPONENT_MASK, + GIMP_COMPONENT_MASK_ALL, + (GParamFlags) ( + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT))); + + g_object_class_install_property (object_class, PROP_ALPHA, + g_param_spec_double ("alpha", + "Alpha", + "The masked-in alpha value when there's no aux input", + -G_MAXDOUBLE, + G_MAXDOUBLE, + 0.0, + (GParamFlags) ( + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT))); +} + +static void +gimp_operation_mask_components_init (GimpOperationMaskComponents *self) +{ +} + +static void +gimp_operation_mask_components_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object); + + switch (property_id) + { + case PROP_MASK: + g_value_set_flags (value, self->mask); + break; + + case PROP_ALPHA: + g_value_set_double (value, self->alpha); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_operation_mask_components_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (object); + + switch (property_id) + { + case PROP_MASK: + self->mask = (GimpComponentMask) g_value_get_flags (value); + break; + + case PROP_ALPHA: + self->alpha = g_value_get_double (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static guint32 +get_alpha_value (const Babl *format, + gfloat alpha) +{ + switch (babl_format_get_bytes_per_pixel (format)) + { + #define DEF_CASE(bpp, type) \ + case bpp: \ + { \ + type alpha_value; \ + \ + babl_process ( \ + babl_fish (babl_format_n (babl_type ("float"), 1), \ + babl_format_n (babl_format_get_type (format, 0), 1)), \ + &alpha, &alpha_value, 1); \ + \ + return alpha_value; \ + } + + DEF_CASE ( 4, guint8) + DEF_CASE ( 8, guint16) + DEF_CASE (16, guint32) + + #undef DEF_CASE + + default: + g_return_val_if_reached (0); + } +} + +template +struct ProcessGeneric +{ + static void + process (gconstpointer in_buf, + gconstpointer aux_buf, + gpointer out_buf, + gint n, + GimpComponentMask mask, + T alpha_value) + { + T *out = (T *) out_buf; + gint i; + gint c; + + if (aux_buf) + { + const T *in[4]; + + for (c = 0; c < 4; c++) + { + if (mask & (1 << c)) + in[c] = (const T *) aux_buf + c; + else + in[c] = (const T *) in_buf + c; + } + + for (i = 0; i < n; i++) + { + for (c = 0; c < 4; c++) + { + out[c] = *in[c]; + + in[c] += 4; + } + + out += 4; + } + } + else + { + const T *in = (const T*) in_buf; + + for (i = 0; i < n; i++) + { + for (c = 0; c < 3; c++) + { + if (mask & (1 << c)) + out[c] = 0; + else + out[c] = in[c]; + } + + if (mask & (1 << 3)) + out[3] = alpha_value; + else + out[3] = in[3]; + + in += 4; + out += 4; + } + } + } +}; + +template +struct Process : ProcessGeneric +{ +}; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + +template <> +struct Process +{ + static void + process (gconstpointer in_buf, + gconstpointer aux_buf, + gpointer out_buf, + gint n, + GimpComponentMask mask, + guint8 alpha_value) + { + const guint32 *in; + guint32 *out; + guint32 in_mask = 0; + gint i; + gint c; + + if (((guintptr) in_buf | (guintptr) aux_buf | (guintptr) out_buf) % 4) + { + ProcessGeneric::process (in_buf, aux_buf, out_buf, n, + mask, alpha_value); + + return; + } + + in = (const guint32 *) in_buf; + out = (guint32 *) out_buf; + + for (c = 0; c < 4; c++) + { + if (! (mask & (1 << c))) + in_mask |= 0xff << (8 * c); + } + + if (aux_buf) + { + const guint32 *aux = (const guint32 *) aux_buf; + guint32 aux_mask = ~in_mask; + + for (i = 0; i < n; i++) + { + *out = (*in & in_mask) | (*aux & aux_mask); + + in++; + aux++; + out++; + } + } + else + { + if (! (mask & GIMP_COMPONENT_MASK_ALPHA) || ! alpha_value) + { + for (i = 0; i < n; i++) + { + *out = *in & in_mask; + + in++; + out++; + } + } + else + { + guint32 alpha_mask = alpha_value << 24; + + for (i = 0; i < n; i++) + { + *out = (*in & in_mask) | alpha_mask; + + in++; + out++; + } + } + } + } +}; + +#endif /* G_BYTE_ORDER == G_LITTLE_ENDIAN */ + +template +static gboolean +gimp_operation_mask_components_process (GimpOperationMaskComponents *self, + void *in_buf, + void *aux_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + Process::process (in_buf, aux_buf, out_buf, samples, + self->mask, self->alpha_value); + + return TRUE; +} + +static void +gimp_operation_mask_components_prepare (GeglOperation *operation) +{ + GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation); + const Babl *format; + + format = gimp_operation_mask_components_get_format ( + gegl_operation_get_source_format (operation, "input")); + + gegl_operation_set_format (operation, "input", format); + gegl_operation_set_format (operation, "aux", format); + gegl_operation_set_format (operation, "output", format); + + if (format != self->format) + { + self->format = format; + + self->alpha_value = get_alpha_value (format, self->alpha); + + switch (babl_format_get_bytes_per_pixel (format)) + { + case 4: + self->process = (gpointer) + gimp_operation_mask_components_process; + break; + + case 8: + self->process = (gpointer) + gimp_operation_mask_components_process; + break; + + case 16: + self->process = (gpointer) + gimp_operation_mask_components_process; + break; + + default: + g_return_if_reached (); + } + } +} + +static GeglRectangle +gimp_operation_mask_components_get_bounding_box (GeglOperation *operation) +{ + GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation); + GeglRectangle *in_rect; + GeglRectangle *aux_rect; + GeglRectangle result = {}; + + in_rect = gegl_operation_source_get_bounding_box (operation, "input"); + aux_rect = gegl_operation_source_get_bounding_box (operation, "aux"); + + if (self->mask == 0) + { + if (in_rect) + return *in_rect; + } + else if (self->mask == GIMP_COMPONENT_MASK_ALL) + { + if (aux_rect) + return *aux_rect; + } + + if (in_rect) + gegl_rectangle_bounding_box (&result, &result, in_rect); + + if (aux_rect) + gegl_rectangle_bounding_box (&result, &result, aux_rect); + + return result; +} + +static gboolean +gimp_operation_mask_components_parent_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_prop, + const GeglRectangle *result, + gint level) +{ + GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation); + + if (self->mask == 0) + { + GObject *input = gegl_operation_context_get_object (context, "input"); + + gegl_operation_context_set_object (context, "output", input); + + return TRUE; + } + else if (self->mask == GIMP_COMPONENT_MASK_ALL) + { + GObject *aux = gegl_operation_context_get_object (context, "aux"); + + /* when there's no aux and the alpha component is masked-in, we set the + * result's alpha component to the value of the "alpha" property; if it + * doesn't equal 0, we can't forward an empty aux. + */ + if (aux || ! self->alpha_value) + { + gegl_operation_context_set_object (context, "output", aux); + + return TRUE; + } + } + + return GEGL_OPERATION_CLASS (parent_class)->process (operation, context, + output_prop, result, + level); +} + +static gboolean +gimp_operation_mask_components_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + typedef gboolean (* ProcessFunc) (GimpOperationMaskComponents *self, + void *in_buf, + void *aux_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + + GimpOperationMaskComponents *self = (GimpOperationMaskComponents *) operation; + + return ((ProcessFunc) self->process) (self, + in_buf, aux_buf, out_buf, samples, + roi, level); +} + +const Babl * +gimp_operation_mask_components_get_format (const Babl *input_format) +{ + const Babl *format = NULL; + + if (input_format) + { + const Babl *model = babl_format_get_model (input_format); + const gchar *model_name = babl_get_name (model); + const Babl *type = babl_format_get_type (input_format, 0); + const gchar *type_name = babl_get_name (type); + + if (! strcmp (model_name, "Y") || + ! strcmp (model_name, "YA") || + ! strcmp (model_name, "RGB") || + ! strcmp (model_name, "RGBA")) + { + if (! strcmp (type_name, "u8")) + format = babl_format ("RGBA u8"); + else if (! strcmp (type_name, "u16")) + format = babl_format ("RGBA u16"); + else if (! strcmp (type_name, "u32")) + format = babl_format ("RGBA u32"); + else if (! strcmp (type_name, "half")) + format = babl_format ("RGBA half"); + else if (! strcmp (type_name, "float")) + format = babl_format ("RGBA float"); + } + else if (! strcmp (model_name, "Y'") || + ! strcmp (model_name, "Y'A") || + ! strcmp (model_name, "R'G'B'") || + ! strcmp (model_name, "R'G'B'A") || + babl_format_is_palette (input_format)) + { + if (! strcmp (type_name, "u8")) + format = babl_format ("R'G'B'A u8"); + else if (! strcmp (type_name, "u16")) + format = babl_format ("R'G'B'A u16"); + else if (! strcmp (type_name, "u32")) + format = babl_format ("R'G'B'A u32"); + else if (! strcmp (type_name, "half")) + format = babl_format ("R'G'B'A half"); + else if (! strcmp (type_name, "float")) + format = babl_format ("R'G'B'A float"); + } + } + + if (! format) + format = babl_format ("RGBA float"); + + return format; +} + +void +gimp_operation_mask_components_process (const Babl *format, + gconstpointer in, + gconstpointer aux, + gpointer out, + gint n, + GimpComponentMask mask) +{ + g_return_if_fail (format != NULL); + g_return_if_fail (in != NULL); + g_return_if_fail (out != NULL); + g_return_if_fail (n >= 0); + + switch (babl_format_get_bytes_per_pixel (format)) + { + case 4: + Process::process (in, aux, out, n, mask, 0); + break; + + case 8: + Process::process (in, aux, out, n, mask, 0); + break; + + case 16: + Process::process (in, aux, out, n, mask, 0); + break; + + default: + g_return_if_reached (); + } +} diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.h gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.h --- gimp-2.10.8+zorin2/app/operations/gimpoperationmaskcomponents.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationmaskcomponents.h 2019-06-12 16:43:38.000000000 +0000 @@ -40,6 +40,11 @@ GeglOperationPointComposer parent_instance; GimpComponentMask mask; + gdouble alpha; + + guint32 alpha_value; + gpointer process; + const Babl *format; }; struct _GimpOperationMaskComponentsClass @@ -48,7 +53,16 @@ }; -GType gimp_operation_mask_components_get_type (void) G_GNUC_CONST; +GType gimp_operation_mask_components_get_type (void) G_GNUC_CONST; + +const Babl * gimp_operation_mask_components_get_format (const Babl *input_format); + +void gimp_operation_mask_components_process (const Babl *format, + gconstpointer in, + gconstpointer aux, + gpointer out, + gint n, + GimpComponentMask mask); #endif /* __GIMP_OPERATION_MASK_COMPONENTS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationoffset.c gimp-2.10.14+om/app/operations/gimpoperationoffset.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationoffset.c 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationoffset.c 2019-06-12 16:43:38.000000000 +0000 @@ -0,0 +1,497 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationoffset.c + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#include +#include +#include + +#include "operations-types.h" + +#include "gegl/gimp-gegl-loops.h" +#include "gegl/gimp-gegl-utils.h" + +#include "core/gimpcontext.h" + +#include "gimpoperationoffset.h" + +#include "gimp-intl.h" + + +enum +{ + PROP_0, + PROP_CONTEXT, + PROP_TYPE, + PROP_X, + PROP_Y +}; + + +static void gimp_operation_offset_dispose (GObject *object); +static void gimp_operation_offset_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gimp_operation_offset_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static GeglRectangle gimp_operation_offset_get_required_for_output (GeglOperation *operation, + const gchar *input_pad, + const GeglRectangle *output_roi); +static GeglRectangle gimp_operation_offset_get_invalidated_by_change (GeglOperation *operation, + const gchar *input_pad, + const GeglRectangle *input_roi); +static void gimp_operation_offset_prepare (GeglOperation *operation); +static gboolean gimp_operation_offset_parent_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_pad, + const GeglRectangle *result, + gint level); + +static gboolean gimp_operation_offset_process (GeglOperation *operation, + GeglBuffer *input, + GeglBuffer *output, + const GeglRectangle *roi, + gint level); + +static void gimp_operation_offset_get_offset (GimpOperationOffset *offset, + gboolean invert, + gint *x, + gint *y); +static void gimp_operation_offset_get_rect (GimpOperationOffset *offset, + gboolean invert, + const GeglRectangle *roi, + GeglRectangle *rect); + + +G_DEFINE_TYPE (GimpOperationOffset, gimp_operation_offset, + GEGL_TYPE_OPERATION_FILTER) + +#define parent_class gimp_operation_offset_parent_class + + +static void +gimp_operation_offset_class_init (GimpOperationOffsetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass); + GeglOperationFilterClass *filter_class = GEGL_OPERATION_FILTER_CLASS (klass); + + object_class->dispose = gimp_operation_offset_dispose; + object_class->set_property = gimp_operation_offset_set_property; + object_class->get_property = gimp_operation_offset_get_property; + + operation_class->get_required_for_output = gimp_operation_offset_get_required_for_output; + operation_class->get_invalidated_by_change = gimp_operation_offset_get_invalidated_by_change; + operation_class->prepare = gimp_operation_offset_prepare; + operation_class->process = gimp_operation_offset_parent_process; + + operation_class->threaded = FALSE; + operation_class->cache_policy = GEGL_CACHE_POLICY_NEVER; + + filter_class->process = gimp_operation_offset_process; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:offset", + "categories", "transform", + "description", _("Shift the pixels, optionally wrapping them at the borders"), + NULL); + + g_object_class_install_property (object_class, PROP_CONTEXT, + g_param_spec_object ("context", + "Context", + "A GimpContext", + GIMP_TYPE_CONTEXT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_TYPE, + g_param_spec_enum ("type", + "Type", + "Offset type", + GIMP_TYPE_OFFSET_TYPE, + GIMP_OFFSET_WRAP_AROUND, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_X, + g_param_spec_int ("x", + "X Offset", + "X offset", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, PROP_Y, + g_param_spec_int ("y", + "Y Offset", + "Y offset", + G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +gimp_operation_offset_init (GimpOperationOffset *self) +{ +} + +static void +gimp_operation_offset_dispose (GObject *object) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (object); + + g_clear_object (&offset->context); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_operation_offset_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (object); + + switch (property_id) + { + case PROP_CONTEXT: + g_value_set_object (value, offset->context); + break; + + case PROP_TYPE: + g_value_set_enum (value, offset->type); + break; + + case PROP_X: + g_value_set_int (value, offset->x); + break; + + case PROP_Y: + g_value_set_int (value, offset->y); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_operation_offset_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (object); + + switch (property_id) + { + case PROP_CONTEXT: + g_set_object (&offset->context, g_value_get_object (value)); + break; + + case PROP_TYPE: + offset->type = g_value_get_enum (value); + break; + + case PROP_X: + offset->x = g_value_get_int (value); + break; + + case PROP_Y: + offset->y = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static GeglRectangle +gimp_operation_offset_get_required_for_output (GeglOperation *operation, + const gchar *input_pad, + const GeglRectangle *output_roi) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (operation); + GeglRectangle rect; + + gimp_operation_offset_get_rect (offset, TRUE, output_roi, &rect); + + return rect; +} + +static GeglRectangle +gimp_operation_offset_get_invalidated_by_change (GeglOperation *operation, + const gchar *input_pad, + const GeglRectangle *input_roi) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (operation); + GeglRectangle rect; + + gimp_operation_offset_get_rect (offset, FALSE, input_roi, &rect); + + return rect; +} + +static void +gimp_operation_offset_prepare (GeglOperation *operation) +{ + const Babl *format; + + format = gegl_operation_get_source_format (operation, "input"); + + if (! format) + format = babl_format ("RGBA float"); + + gegl_operation_set_format (operation, "input", format); + gegl_operation_set_format (operation, "output", format); +} + +static gboolean +gimp_operation_offset_parent_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_pad, + const GeglRectangle *result, + gint level) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (operation); + GObject *input; + gint x; + gint y; + + input = gegl_operation_context_get_object (context, "input"); + + gimp_operation_offset_get_offset (offset, FALSE, &x, &y); + + if (x == 0 && y == 0) + { + gegl_operation_context_set_object (context, "output", input); + + return TRUE; + } + else if (offset->type == GIMP_OFFSET_TRANSPARENT || + (offset->type == GIMP_OFFSET_BACKGROUND && + ! offset->context)) + { + GObject *output = NULL; + + if (input) + { + GeglRectangle bounds; + GeglRectangle extent; + + bounds = gegl_operation_get_bounding_box (GEGL_OPERATION (offset)); + + extent = *gegl_buffer_get_extent (GEGL_BUFFER (input)); + + extent.x += x; + extent.y += y; + + if (gegl_rectangle_intersect (&extent, &extent, &bounds)) + { + output = g_object_new (GEGL_TYPE_BUFFER, + "source", input, + "x", extent.x, + "y", extent.y, + "width", extent.width, + "height", extent.height, + "shift-x", -x, + "shift-y", -y, + NULL); + + if (gegl_object_get_has_forked (input)) + gegl_object_set_has_forked (output); + } + } + + gegl_operation_context_take_object (context, "output", output); + + return TRUE; + } + + return GEGL_OPERATION_CLASS (parent_class)->process (operation, context, + output_pad, result, + level); +} + +static gboolean +gimp_operation_offset_process (GeglOperation *operation, + GeglBuffer *input, + GeglBuffer *output, + const GeglRectangle *roi, + gint level) +{ + GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (operation); + GeglColor *color = NULL; + GeglRectangle bounds; + gint x; + gint y; + gint i; + + bounds = gegl_operation_get_bounding_box (GEGL_OPERATION (offset)); + + gimp_operation_offset_get_offset (offset, FALSE, &x, &y); + + if (offset->type == GIMP_OFFSET_BACKGROUND && offset->context) + { + GimpRGB bg; + + gimp_context_get_background (offset->context, &bg); + + color = gimp_gegl_color_new (&bg); + } + + for (i = 0; i < 4; i++) + { + GeglRectangle offset_bounds = bounds; + gint offset_x = x; + gint offset_y = y; + + if (i & 1) + offset_x += x < 0 ? bounds.width : -bounds.width; + if (i & 2) + offset_y += y < 0 ? bounds.height : -bounds.height; + + offset_bounds.x += offset_x; + offset_bounds.y += offset_y; + + if (gegl_rectangle_intersect (&offset_bounds, &offset_bounds, roi)) + { + if (i == 0 || offset->type == GIMP_OFFSET_WRAP_AROUND) + { + GeglRectangle offset_roi = offset_bounds; + + offset_roi.x -= offset_x; + offset_roi.y -= offset_y; + + gimp_gegl_buffer_copy (input, &offset_roi, GEGL_ABYSS_NONE, + output, &offset_bounds); + } + else if (color) + { + gegl_buffer_set_color (output, &offset_bounds, color); + } + } + } + + g_clear_object (&color); + + return TRUE; +} + +static void +gimp_operation_offset_get_offset (GimpOperationOffset *offset, + gboolean invert, + gint *x, + gint *y) +{ + GeglRectangle bounds; + + bounds = gegl_operation_get_bounding_box (GEGL_OPERATION (offset)); + + if (gegl_rectangle_is_empty (&bounds)) + { + *x = 0; + *y = 0; + + return; + } + + *x = offset->x; + *y = offset->y; + + if (invert) + { + *x = -*x; + *y = -*y; + } + + if (offset->type == GIMP_OFFSET_WRAP_AROUND) + { + *x %= bounds.width; + + if (*x < 0) + *x += bounds.width; + + *y %= bounds.height; + + if (*y < 0) + *y += bounds.height; + } + else + { + *x = CLAMP (*x, -bounds.width, +bounds.width); + *y = CLAMP (*y, -bounds.height, +bounds.height); + } +} + +static void +gimp_operation_offset_get_rect (GimpOperationOffset *offset, + gboolean invert, + const GeglRectangle *roi, + GeglRectangle *rect) +{ + GeglRectangle bounds; + gint x; + gint y; + + bounds = gegl_operation_get_bounding_box (GEGL_OPERATION (offset)); + + if (gegl_rectangle_is_empty (&bounds)) + { + rect->x = 0; + rect->y = 0; + rect->width = 0; + rect->height = 0; + + return; + } + + gimp_operation_offset_get_offset (offset, invert, &x, &y); + + *rect = *roi; + + rect->x += x; + rect->y += y; + + if (offset->type == GIMP_OFFSET_WRAP_AROUND) + { + if (rect->x + rect->width > bounds.x + bounds.width) + { + rect->x = bounds.x; + rect->width = bounds.width; + } + + if (rect->y + rect->height > bounds.y + bounds.height) + { + rect->y = bounds.y; + rect->height = bounds.height; + } + } + + gegl_rectangle_intersect (rect, rect, &bounds); +} diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationoffset.h gimp-2.10.14+om/app/operations/gimpoperationoffset.h --- gimp-2.10.8+zorin2/app/operations/gimpoperationoffset.h 1970-01-01 00:00:00.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationoffset.h 2019-06-12 16:43:38.000000000 +0000 @@ -0,0 +1,55 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationoffset.h + * Copyright (C) 2019 Ell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_OPERATION_OFFSET_H__ +#define __GIMP_OPERATION_OFFSET_H__ + + +#define GIMP_TYPE_OPERATION_OFFSET (gimp_operation_offset_get_type ()) +#define GIMP_OPERATION_OFFSET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_OFFSET, GimpOperationOffset)) +#define GIMP_OPERATION_OFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_OFFSET, GimpOperationOffsetClass)) +#define GIMP_IS_OPERATION_OFFSET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_OFFSET)) +#define GIMP_IS_OPERATION_OFFSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_OFFSET)) +#define GIMP_OPERATION_OFFSET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_OFFSET, GimpOperationOffsetClass)) + + +typedef struct _GimpOperationOffset GimpOperationOffset; +typedef struct _GimpOperationOffsetClass GimpOperationOffsetClass; + +struct _GimpOperationOffset +{ + GeglOperationFilter parent_instance; + + GimpContext *context; + GimpOffsetType type; + gint x; + gint y; +}; + +struct _GimpOperationOffsetClass +{ + GeglOperationFilterClass parent_class; +}; + + +GType gimp_operation_offset_get_type (void) G_GNUC_CONST; + + +#endif /* __GIMP_OPERATION_OFFSET_H__ */ diff -Nru gimp-2.10.8+zorin2/app/operations/gimp-operations.c gimp-2.10.14+om/app/operations/gimp-operations.c --- gimp-2.10.8+zorin2/app/operations/gimp-operations.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimp-operations.c 2019-06-12 16:43:38.000000000 +0000 @@ -36,11 +36,13 @@ #include "gimpoperationcagetransform.h" #include "gimpoperationcomposecrop.h" #include "gimpoperationequalize.h" +#include "gimpoperationfillsource.h" #include "gimpoperationflood.h" #include "gimpoperationgradient.h" #include "gimpoperationgrow.h" #include "gimpoperationhistogramsink.h" #include "gimpoperationmaskcomponents.h" +#include "gimpoperationoffset.h" #include "gimpoperationprofiletransform.h" #include "gimpoperationscalarmultiply.h" #include "gimpoperationsemiflatten.h" @@ -129,11 +131,13 @@ g_type_class_ref (GIMP_TYPE_OPERATION_CAGE_TRANSFORM); g_type_class_ref (GIMP_TYPE_OPERATION_COMPOSE_CROP); g_type_class_ref (GIMP_TYPE_OPERATION_EQUALIZE); + g_type_class_ref (GIMP_TYPE_OPERATION_FILL_SOURCE); g_type_class_ref (GIMP_TYPE_OPERATION_FLOOD); g_type_class_ref (GIMP_TYPE_OPERATION_GRADIENT); g_type_class_ref (GIMP_TYPE_OPERATION_GROW); g_type_class_ref (GIMP_TYPE_OPERATION_HISTOGRAM_SINK); g_type_class_ref (GIMP_TYPE_OPERATION_MASK_COMPONENTS); + g_type_class_ref (GIMP_TYPE_OPERATION_OFFSET); g_type_class_ref (GIMP_TYPE_OPERATION_PROFILE_TRANSFORM); g_type_class_ref (GIMP_TYPE_OPERATION_SCALAR_MULTIPLY); g_type_class_ref (GIMP_TYPE_OPERATION_SEMI_FLATTEN); diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationsemiflatten.c gimp-2.10.14+om/app/operations/gimpoperationsemiflatten.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationsemiflatten.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationsemiflatten.c 2019-04-07 11:38:14.000000000 +0000 @@ -92,8 +92,8 @@ g_object_class_install_property (object_class, PROP_COLOR, gimp_param_spec_rgb ("color", - "Color", - "The color", + _("Color"), + _("The color"), FALSE, &white, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); diff -Nru gimp-2.10.8+zorin2/app/operations/gimpoperationthresholdalpha.c gimp-2.10.14+om/app/operations/gimpoperationthresholdalpha.c --- gimp-2.10.8+zorin2/app/operations/gimpoperationthresholdalpha.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/gimpoperationthresholdalpha.c 2019-04-07 11:38:14.000000000 +0000 @@ -87,8 +87,8 @@ g_object_class_install_property (object_class, PROP_VALUE, g_param_spec_double ("value", - "Value", - "The alpha value", + _("Value"), + _("The alpha value"), 0.0, 1.0, 0.5, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimp-layer-modes.c gimp-2.10.14+om/app/operations/layer-modes/gimp-layer-modes.c --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimp-layer-modes.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimp-layer-modes.c 2019-06-12 16:43:38.000000000 +0000 @@ -60,7 +60,8 @@ .flags = GIMP_LAYER_MODE_FLAG_LEGACY | GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | - GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE, + GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, @@ -70,8 +71,9 @@ { GIMP_LAYER_MODE_DISSOLVE, .op_name = "gimp:dissolve", - .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | - GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE, + .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION @@ -84,8 +86,7 @@ GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE, - .context = GIMP_LAYER_MODE_CONTEXT_PAINT | - GIMP_LAYER_MODE_CONTEXT_FADE, + .context = GIMP_LAYER_MODE_CONTEXT_PAINT, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL @@ -366,8 +367,7 @@ GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_SUBTRACTIVE, - .context = GIMP_LAYER_MODE_CONTEXT_PAINT | - GIMP_LAYER_MODE_CONTEXT_FADE, + .context = GIMP_LAYER_MODE_CONTEXT_PAINT, .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, .composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL, @@ -436,7 +436,8 @@ { GIMP_LAYER_MODE_NORMAL, .op_name = "gimp:normal", - .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE, + .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, @@ -447,8 +448,7 @@ .op_name = "gimp:behind", .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE, - .context = GIMP_LAYER_MODE_CONTEXT_PAINT | - GIMP_LAYER_MODE_CONTEXT_FADE, + .context = GIMP_LAYER_MODE_CONTEXT_PAINT, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR @@ -775,7 +775,8 @@ .op_name = "gimp:erase", .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_SUBTRACTIVE | - GIMP_LAYER_MODE_FLAG_ALPHA_ONLY, + GIMP_LAYER_MODE_FLAG_ALPHA_ONLY | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, .composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, @@ -785,7 +786,8 @@ { GIMP_LAYER_MODE_MERGE, .op_name = "gimp:merge", - .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE, + .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, @@ -798,7 +800,8 @@ .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_SUBTRACTIVE | - GIMP_LAYER_MODE_FLAG_ALPHA_ONLY, + GIMP_LAYER_MODE_FLAG_ALPHA_ONLY | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_ALL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP, .composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP @@ -807,8 +810,9 @@ { GIMP_LAYER_MODE_PASS_THROUGH, .op_name = "gimp:pass-through", - .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | - GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE, + .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .context = GIMP_LAYER_MODE_CONTEXT_GROUP, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR @@ -817,8 +821,8 @@ { GIMP_LAYER_MODE_REPLACE, .op_name = "gimp:replace", - .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE, - .context = GIMP_LAYER_MODE_CONTEXT_FADE, + .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | + GIMP_LAYER_MODE_FLAG_TRIVIAL, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_space = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR @@ -830,7 +834,6 @@ .flags = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE | GIMP_LAYER_MODE_FLAG_ALPHA_ONLY, - .context = GIMP_LAYER_MODE_CONTEXT_FADE, .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION, .composite_mode = GIMP_LAYER_COMPOSITE_UNION } @@ -1189,6 +1192,17 @@ return (info->flags & GIMP_LAYER_MODE_FLAG_ALPHA_ONLY) != 0; } +gboolean +gimp_layer_mode_is_trivial (GimpLayerMode mode) +{ + const GimpLayerModeInfo *info = gimp_layer_mode_info (mode); + + if (! info) + return FALSE; + + return (info->flags & GIMP_LAYER_MODE_FLAG_TRIVIAL) != 0; +} + GimpLayerColorSpace gimp_layer_mode_get_blend_space (GimpLayerMode mode) { @@ -1409,11 +1423,14 @@ } const Babl * -gimp_layer_mode_get_format (GimpLayerMode mode, - GimpLayerColorSpace composite_space, - GimpLayerColorSpace blend_space, - const Babl *preferred_format) +gimp_layer_mode_get_format (GimpLayerMode mode, + GimpLayerColorSpace blend_space, + GimpLayerColorSpace composite_space, + GimpLayerCompositeMode composite_mode, + const Babl *preferred_format) { + GimpLayerCompositeRegion composite_region; + /* for now, all modes perform i/o in the composite space. */ (void) mode; (void) blend_space; @@ -1421,6 +1438,32 @@ if (composite_space == GIMP_LAYER_COLOR_SPACE_AUTO) composite_space = gimp_layer_mode_get_composite_space (mode); + if (composite_mode == GIMP_LAYER_COMPOSITE_AUTO) + composite_mode = gimp_layer_mode_get_composite_mode (mode); + + composite_region = gimp_layer_mode_get_included_region (mode, composite_mode); + + if (gimp_layer_mode_is_alpha_only (mode)) + { + if (composite_region != GIMP_LAYER_COMPOSITE_REGION_UNION) + { + /* alpha-only layer modes don't combine colors in non-union composite + * modes, hence we can disregard the composite space. + */ + composite_space = GIMP_LAYER_COLOR_SPACE_AUTO; + } + } + else if (gimp_layer_mode_is_trivial (mode)) + { + if (! (composite_region & GIMP_LAYER_COMPOSITE_REGION_DESTINATION)) + { + /* trivial layer modes don't combine colors when only the source + * region is included, hence we can disregard the composite space. + */ + composite_space = GIMP_LAYER_COLOR_SPACE_AUTO; + } + } + switch (composite_space) { case GIMP_LAYER_COLOR_SPACE_AUTO: diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimp-layer-modes.h gimp-2.10.14+om/app/operations/layer-modes/gimp-layer-modes.h --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimp-layer-modes.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimp-layer-modes.h 2019-06-12 16:43:38.000000000 +0000 @@ -33,6 +33,7 @@ gboolean gimp_layer_mode_is_subtractive (GimpLayerMode mode); gboolean gimp_layer_mode_is_alpha_only (GimpLayerMode mode); +gboolean gimp_layer_mode_is_trivial (GimpLayerMode mode); GimpLayerColorSpace gimp_layer_mode_get_blend_space (GimpLayerMode mode); GimpLayerColorSpace gimp_layer_mode_get_composite_space (GimpLayerMode mode); @@ -60,8 +61,9 @@ GimpLayerMode *new_mode); const Babl * gimp_layer_mode_get_format (GimpLayerMode mode, - GimpLayerColorSpace composite_space, GimpLayerColorSpace blend_space, + GimpLayerColorSpace composite_space, + GimpLayerCompositeMode composite_mode, const Babl *preferred_format); GimpLayerCompositeRegion gimp_layer_mode_get_included_region (GimpLayerMode mode, diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode-blend.c gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode-blend.c --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode-blend.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode-blend.c 2019-06-12 16:43:38.000000000 +0000 @@ -80,10 +80,11 @@ void /* aka linear_dodge */ -gimp_operation_layer_mode_blend_addition (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_addition (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -104,10 +105,11 @@ } void -gimp_operation_layer_mode_blend_burn (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_burn (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -128,10 +130,11 @@ } void -gimp_operation_layer_mode_blend_darken_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_darken_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -152,10 +155,11 @@ } void -gimp_operation_layer_mode_blend_difference (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_difference (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -176,10 +180,11 @@ } void -gimp_operation_layer_mode_blend_divide (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_divide (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -200,10 +205,11 @@ } void -gimp_operation_layer_mode_blend_dodge (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_dodge (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -224,10 +230,11 @@ } void -gimp_operation_layer_mode_blend_exclusion (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_exclusion (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -248,10 +255,11 @@ } void -gimp_operation_layer_mode_blend_grain_extract (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_grain_extract (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -272,10 +280,11 @@ } void -gimp_operation_layer_mode_blend_grain_merge (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_grain_merge (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -296,10 +305,11 @@ } void -gimp_operation_layer_mode_blend_hard_mix (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hard_mix (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -320,10 +330,11 @@ } void -gimp_operation_layer_mode_blend_hardlight (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hardlight (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -358,10 +369,11 @@ } void -gimp_operation_layer_mode_blend_hsl_color (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hsl_color (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -422,10 +434,11 @@ } void -gimp_operation_layer_mode_blend_hsv_hue (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hsv_hue (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -477,10 +490,11 @@ } void -gimp_operation_layer_mode_blend_hsv_saturation (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hsv_saturation (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -531,10 +545,11 @@ } void -gimp_operation_layer_mode_blend_hsv_value (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_hsv_value (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -574,10 +589,11 @@ } void -gimp_operation_layer_mode_blend_lch_chroma (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_lch_chroma (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -616,10 +632,11 @@ } void -gimp_operation_layer_mode_blend_lch_color (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_lch_color (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -639,10 +656,11 @@ } void -gimp_operation_layer_mode_blend_lch_hue (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_lch_hue (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -681,10 +699,11 @@ } void -gimp_operation_layer_mode_blend_lch_lightness (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_lch_lightness (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -704,10 +723,11 @@ } void -gimp_operation_layer_mode_blend_lighten_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_lighten_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -728,10 +748,11 @@ } void -gimp_operation_layer_mode_blend_linear_burn (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_linear_burn (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -754,10 +775,11 @@ /* added according to: http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html */ void -gimp_operation_layer_mode_blend_linear_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_linear_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -787,10 +809,11 @@ } void -gimp_operation_layer_mode_blend_luma_darken_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_luma_darken_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -824,10 +847,11 @@ } void -gimp_operation_layer_mode_blend_luma_lighten_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_luma_lighten_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -861,25 +885,33 @@ } void -gimp_operation_layer_mode_blend_luminance (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) -{ - gfloat layer_Y[samples], *layer_Y_p; - gfloat in_Y[samples], *in_Y_p; +gimp_operation_layer_mode_blend_luminance (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) +{ + static const Babl *fish; + gfloat *scratch; + gfloat *in_Y; + gfloat *layer_Y; + + if (! fish) + fish = babl_fish ("RGBA float", "Y float"); + + scratch = gegl_scratch_new (gfloat, 2 * samples); - babl_process (babl_fish ("RGBA float", "Y float"), layer, layer_Y, samples); - babl_process (babl_fish ("RGBA float", "Y float"), in, in_Y, samples); + in_Y = scratch; + layer_Y = scratch + samples; - layer_Y_p = &layer_Y[0]; - in_Y_p = &in_Y[0]; + babl_process (fish, in, in_Y, samples); + babl_process (fish, layer, layer_Y, samples); while (samples--) { if (layer[ALPHA] != 0.0f && in[ALPHA] != 0.0f) { - gfloat ratio = safe_div (layer_Y_p[0], in_Y_p[0]); + gfloat ratio = safe_div (layer_Y[0], in_Y[0]); gint c; for (c = 0; c < 3; c ++) @@ -888,19 +920,22 @@ comp[ALPHA] = layer[ALPHA]; - comp += 4; - in += 4; - layer += 4; - in_Y_p ++; - layer_Y_p ++; + comp += 4; + in += 4; + layer += 4; + in_Y ++; + layer_Y ++; } + + gegl_scratch_free (scratch); } void -gimp_operation_layer_mode_blend_multiply (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_multiply (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -921,10 +956,11 @@ } void -gimp_operation_layer_mode_blend_overlay (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_overlay (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -955,10 +991,11 @@ /* added according to: http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html */ void -gimp_operation_layer_mode_blend_pin_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_pin_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -988,10 +1025,11 @@ } void -gimp_operation_layer_mode_blend_screen (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_screen (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -1012,10 +1050,11 @@ } void -gimp_operation_layer_mode_blend_softlight (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_softlight (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -1041,10 +1080,11 @@ } void -gimp_operation_layer_mode_blend_subtract (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_subtract (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -1067,10 +1107,11 @@ /* added according to: http://www.simplefilter.de/en/basics/mixmods.html */ void -gimp_operation_layer_mode_blend_vivid_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_vivid_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { @@ -1115,10 +1156,11 @@ void -gimp_operation_layer_mode_blend_color_erase (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples) +gimp_operation_layer_mode_blend_color_erase (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples) { while (samples--) { diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode-blend.h gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode-blend.h --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode-blend.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode-blend.h 2019-06-12 16:43:38.000000000 +0000 @@ -26,142 +26,175 @@ /* nonsubtractive blend functions */ -void gimp_operation_layer_mode_blend_addition (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_burn (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_darken_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_difference (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_divide (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_dodge (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_exclusion (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_grain_extract (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_grain_merge (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hard_mix (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hardlight (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hsl_color (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hsv_hue (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hsv_saturation (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_hsv_value (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_lch_chroma (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_lch_color (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_lch_hue (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_lch_lightness (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_lighten_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_linear_burn (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_linear_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_luma_darken_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_luma_lighten_only (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_luminance (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_multiply (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_overlay (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_pin_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_screen (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_softlight (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_subtract (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); -void gimp_operation_layer_mode_blend_vivid_light (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); +void gimp_operation_layer_mode_blend_addition (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_burn (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_darken_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_difference (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_divide (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_dodge (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_exclusion (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_grain_extract (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_grain_merge (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hard_mix (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hardlight (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hsl_color (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hsv_hue (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hsv_saturation (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_hsv_value (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_lch_chroma (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_lch_color (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_lch_hue (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_lch_lightness (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_lighten_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_linear_burn (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_linear_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_luma_darken_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_luma_lighten_only (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_luminance (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_multiply (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_overlay (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_pin_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_screen (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_softlight (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_subtract (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); +void gimp_operation_layer_mode_blend_vivid_light (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); /* subtractive blend functions */ -void gimp_operation_layer_mode_blend_color_erase (const gfloat *in, - const gfloat *layer, - gfloat *comp, - gint samples); +void gimp_operation_layer_mode_blend_color_erase (GeglOperation *operation, + const gfloat *in, + const gfloat *layer, + gfloat *comp, + gint samples); #endif /* __GIMP_OPERATION_LAYER_MODE_BLEND_H__ */ diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode.c gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode.c --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationlayermode.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimpoperationlayermode.c 2019-10-26 18:49:18.000000000 +0000 @@ -68,48 +68,49 @@ gint samples); -static void gimp_operation_layer_mode_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_operation_layer_mode_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void gimp_operation_layer_mode_prepare (GeglOperation *operation); -static gboolean gimp_operation_layer_mode_parent_process (GeglOperation *operation, - GeglOperationContext *context, - const gchar *output_prop, - const GeglRectangle *result, - gint level); - -static gboolean gimp_operation_layer_mode_process (GeglOperation *operation, - void *in, - void *layer, - void *mask, - void *out, - glong samples, - const GeglRectangle *roi, - gint level); - -static gboolean gimp_operation_layer_mode_real_process (GeglOperation *operation, - void *in, - void *layer, - void *mask, - void *out, - glong samples, - const GeglRectangle *roi, - gint level); - -static gboolean process_last_node (GeglOperation *operation, - void *in, - void *layer, - void *mask, - void *out, - glong samples, - const GeglRectangle *roi, - gint level); +static void gimp_operation_layer_mode_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_operation_layer_mode_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_operation_layer_mode_prepare (GeglOperation *operation); +static GeglRectangle gimp_operation_layer_mode_get_bounding_box (GeglOperation *operation); +static gboolean gimp_operation_layer_mode_parent_process (GeglOperation *operation, + GeglOperationContext *context, + const gchar *output_prop, + const GeglRectangle *result, + gint level); + +static gboolean gimp_operation_layer_mode_process (GeglOperation *operation, + void *in, + void *layer, + void *mask, + void *out, + glong samples, + const GeglRectangle *roi, + gint level); + +static gboolean gimp_operation_layer_mode_real_process (GeglOperation *operation, + void *in, + void *layer, + void *mask, + void *out, + glong samples, + const GeglRectangle *roi, + gint level); + +static gboolean process_last_node (GeglOperation *operation, + void *in, + void *layer, + void *mask, + void *out, + glong samples, + const GeglRectangle *roi, + gint level); G_DEFINE_TYPE (GimpOperationLayerMode, gimp_operation_layer_mode, @@ -141,16 +142,17 @@ gegl_operation_class_set_keys (operation_class, "name", "gimp:layer-mode", NULL); - object_class->set_property = gimp_operation_layer_mode_set_property; - object_class->get_property = gimp_operation_layer_mode_get_property; + object_class->set_property = gimp_operation_layer_mode_set_property; + object_class->get_property = gimp_operation_layer_mode_get_property; - operation_class->prepare = gimp_operation_layer_mode_prepare; - operation_class->process = gimp_operation_layer_mode_parent_process; + operation_class->prepare = gimp_operation_layer_mode_prepare; + operation_class->get_bounding_box = gimp_operation_layer_mode_get_bounding_box; + operation_class->process = gimp_operation_layer_mode_parent_process; - point_composer3_class->process = gimp_operation_layer_mode_process; + point_composer3_class->process = gimp_operation_layer_mode_process; - klass->process = gimp_operation_layer_mode_real_process; - klass->get_affected_region = NULL; + klass->process = gimp_operation_layer_mode_real_process; + klass->get_affected_region = NULL; g_object_class_install_property (object_class, PROP_LAYER_MODE, g_param_spec_enum ("layer-mode", @@ -359,8 +361,9 @@ } format = gimp_layer_mode_get_format (self->layer_mode, - self->composite_space, self->blend_space, + self->composite_space, + self->composite_mode, preferred_format); gegl_operation_set_format (operation, "input", format); @@ -369,6 +372,57 @@ gegl_operation_set_format (operation, "aux2", babl_format ("Y float")); } +static GeglRectangle +gimp_operation_layer_mode_get_bounding_box (GeglOperation *op) +{ + GimpOperationLayerMode *self = (gpointer) op; + GeglRectangle *in_rect; + GeglRectangle *aux_rect; + GeglRectangle *aux2_rect; + GeglRectangle src_rect = {}; + GeglRectangle dst_rect = {}; + GeglRectangle result; + GimpLayerCompositeRegion included_region; + + in_rect = gegl_operation_source_get_bounding_box (op, "input"); + aux_rect = gegl_operation_source_get_bounding_box (op, "aux"); + aux2_rect = gegl_operation_source_get_bounding_box (op, "aux2"); + + if (in_rect) + dst_rect = *in_rect; + + if (aux_rect) + { + src_rect = *aux_rect; + + if (aux2_rect) + gegl_rectangle_intersect (&src_rect, &src_rect, aux2_rect); + } + + if (self->is_last_node) + { + included_region = GIMP_LAYER_COMPOSITE_REGION_SOURCE; + } + else + { + included_region = gimp_layer_mode_get_included_region (self->layer_mode, + self->composite_mode); + } + + if (self->opacity == 0.0) + included_region &= ~GIMP_LAYER_COMPOSITE_REGION_SOURCE; + + gegl_rectangle_intersect (&result, &src_rect, &dst_rect); + + if (included_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE) + gegl_rectangle_bounding_box (&result, &result, &src_rect); + + if (included_region & GIMP_LAYER_COMPOSITE_REGION_DESTINATION) + gegl_rectangle_bounding_box (&result, &result, &dst_rect); + + return result; +} + static gboolean gimp_operation_layer_mode_parent_process (GeglOperation *operation, GeglOperationContext *context, @@ -677,7 +731,7 @@ babl_process (composite_to_blend_fish, layer + first, blend_layer + first, count); - blend_function (blend_in + first, blend_layer + first, + blend_function (operation, blend_in + first, blend_layer + first, blend_out + first, count); babl_process (blend_to_composite_fish, @@ -702,7 +756,7 @@ blend_out = g_alloca (sizeof (gfloat) * 4 * samples); } - blend_function (blend_in, blend_layer, blend_out, samples); + blend_function (operation, blend_in, blend_layer, blend_out, samples); } if (! gimp_layer_mode_is_subtractive (layer_mode->layer_mode)) diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationpassthrough.c gimp-2.10.14+om/app/operations/layer-modes/gimpoperationpassthrough.c --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationpassthrough.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimpoperationpassthrough.c 2019-04-07 11:38:14.000000000 +0000 @@ -25,22 +25,12 @@ #include "../operations-types.h" -#include "gimp-layer-modes.h" #include "gimpoperationpassthrough.h" -static gboolean gimp_operation_pass_through_parent_process (GeglOperation *operation, - GeglOperationContext *context, - const gchar *output_prop, - const GeglRectangle *result, - gint level); - - G_DEFINE_TYPE (GimpOperationPassThrough, gimp_operation_pass_through, GIMP_TYPE_OPERATION_REPLACE) -#define parent_class gimp_operation_pass_through_parent_class - static void gimp_operation_pass_through_class_init (GimpOperationPassThroughClass *klass) @@ -53,8 +43,6 @@ "description", "GIMP pass through mode operation", NULL); - operation_class->process = gimp_operation_pass_through_parent_process; - /* don't use REPLACE mode's specialized get_affected_region(); PASS_THROUGH * behaves like an ordinary layer mode here. */ @@ -65,42 +53,3 @@ gimp_operation_pass_through_init (GimpOperationPassThrough *self) { } - -static gboolean -gimp_operation_pass_through_parent_process (GeglOperation *operation, - GeglOperationContext *context, - const gchar *output_prop, - const GeglRectangle *result, - gint level) -{ - GimpOperationLayerMode *layer_mode = (gpointer) operation; - - /* if the layer's opacity is 100%, it has no mask, and its composite mode - * contains "aux" (the latter should always be the case for pass through - * mode,) we can just pass "aux" directly as output. note that the same - * optimization would more generally apply to REPLACE mode, save for the fact - * that when both the backdrop and the layer have a pixel with 0% alpha, we - * want to maintain the color value of the backdrop, not the layer; since, - * for pass through groups, the layer is already composited against the - * backdrop, such pixels will have the same color value for both the backdrop - * and the layer. - */ - if (layer_mode->opacity == 1.0 && - ! gegl_operation_context_get_object (context, "aux2") && - (gimp_layer_mode_get_included_region (layer_mode->layer_mode, - layer_mode->real_composite_mode) & - GIMP_LAYER_COMPOSITE_REGION_SOURCE)) - { - GObject *aux; - - aux = gegl_operation_context_get_object (context, "aux"); - - gegl_operation_context_set_object (context, "output", aux); - - return TRUE; - } - - return GEGL_OPERATION_CLASS (parent_class)->process (operation, context, - output_prop, result, - level); -} diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationreplace.c gimp-2.10.14+om/app/operations/layer-modes/gimpoperationreplace.c --- gimp-2.10.8+zorin2/app/operations/layer-modes/gimpoperationreplace.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/gimpoperationreplace.c 2019-10-26 18:49:18.000000000 +0000 @@ -20,13 +20,23 @@ #include "config.h" +#include + #include #include "../operations-types.h" +#include "gimp-layer-modes.h" #include "gimpoperationreplace.h" +static GeglRectangle gimp_operation_replace_get_bounding_box (GeglOperation *op); +static gboolean gimp_operation_replace_parent_process (GeglOperation *op, + GeglOperationContext *context, + const gchar *output_prop, + const GeglRectangle *result, + gint level); + static gboolean gimp_operation_replace_process (GeglOperation *op, void *in, void *layer, @@ -41,6 +51,8 @@ G_DEFINE_TYPE (GimpOperationReplace, gimp_operation_replace, GIMP_TYPE_OPERATION_LAYER_MODE) +#define parent_class gimp_operation_replace_parent_class + static void gimp_operation_replace_class_init (GimpOperationReplaceClass *klass) @@ -53,6 +65,9 @@ "description", "GIMP replace mode operation", NULL); + operation_class->get_bounding_box = gimp_operation_replace_get_bounding_box; + operation_class->process = gimp_operation_replace_parent_process; + layer_mode_class->process = gimp_operation_replace_process; layer_mode_class->get_affected_region = gimp_operation_replace_get_affected_region; } @@ -62,6 +77,94 @@ { } +static GeglRectangle +gimp_operation_replace_get_bounding_box (GeglOperation *op) +{ + GimpOperationLayerMode *self = (gpointer) op; + GeglRectangle *in_rect; + GeglRectangle *aux_rect; + GeglRectangle *aux2_rect; + GeglRectangle src_rect = {}; + GeglRectangle dst_rect = {}; + GeglRectangle result; + GimpLayerCompositeRegion included_region; + + in_rect = gegl_operation_source_get_bounding_box (op, "input"); + aux_rect = gegl_operation_source_get_bounding_box (op, "aux"); + aux2_rect = gegl_operation_source_get_bounding_box (op, "aux2"); + + if (in_rect) + dst_rect = *in_rect; + + if (aux_rect) + { + src_rect = *aux_rect; + + if (aux2_rect) + gegl_rectangle_intersect (&src_rect, &src_rect, aux2_rect); + } + + if (self->is_last_node) + { + included_region = GIMP_LAYER_COMPOSITE_REGION_SOURCE; + } + else + { + included_region = gimp_layer_mode_get_included_region (self->layer_mode, + self->composite_mode); + } + + if (self->opacity == 0.0) + included_region &= ~GIMP_LAYER_COMPOSITE_REGION_SOURCE; + else if (self->opacity == 1.0 && ! aux2_rect) + included_region &= ~GIMP_LAYER_COMPOSITE_REGION_DESTINATION; + + gegl_rectangle_intersect (&result, &src_rect, &dst_rect); + + if (included_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE) + gegl_rectangle_bounding_box (&result, &result, &src_rect); + + if (included_region & GIMP_LAYER_COMPOSITE_REGION_DESTINATION) + gegl_rectangle_bounding_box (&result, &result, &dst_rect); + + return result; +} + +static gboolean +gimp_operation_replace_parent_process (GeglOperation *op, + GeglOperationContext *context, + const gchar *output_prop, + const GeglRectangle *result, + gint level) +{ + GimpOperationLayerMode *layer_mode = (gpointer) op; + + /* if the layer's opacity is 100%, it has no mask, and its composite mode + * contains "aux" (the latter should always be the case in practice, + * currently,) we can just pass "aux" directly as output. + */ + if (layer_mode->opacity == 1.0 && + ! gegl_operation_context_get_object (context, "aux2") && + (gimp_layer_mode_get_included_region (layer_mode->layer_mode, + layer_mode->real_composite_mode) & + GIMP_LAYER_COMPOSITE_REGION_SOURCE)) + { + GObject *aux; + + aux = gegl_operation_context_get_object (context, "aux"); + + gegl_operation_context_set_object (context, "output", aux); + + return TRUE; + } + /* the opposite case, where the opacity is 0%, is handled by + * GimpOperationLayerMode. + */ + + return GEGL_OPERATION_CLASS (parent_class)->process (op, context, output_prop, + result, level); +} + static gboolean gimp_operation_replace_process (GeglOperation *op, void *in_p, @@ -88,6 +191,7 @@ { gfloat opacity_value = opacity; gfloat new_alpha; + gfloat ratio; gint b; if (has_mask) @@ -95,18 +199,13 @@ new_alpha = (layer[ALPHA] - in[ALPHA]) * opacity_value + in[ALPHA]; + ratio = opacity_value; + if (new_alpha) - { - gfloat ratio = opacity_value * layer[ALPHA] / new_alpha; + ratio *= layer[ALPHA] / new_alpha; - for (b = RED; b < ALPHA; b++) - out[b] = (layer[b] - in[b]) * ratio + in[b]; - } - else - { - for (b = RED; b < ALPHA; b++) - out[b] = in[b]; - } + for (b = RED; b < ALPHA; b++) + out[b] = (layer[b] - in[b]) * ratio + in[b]; out[ALPHA] = new_alpha; @@ -136,8 +235,8 @@ out[ALPHA] = new_alpha; - in += 4; - out += 4; + in += 4; + out += 4; if (has_mask) mask++; @@ -156,16 +255,8 @@ new_alpha = layer[ALPHA] * opacity_value; - if (new_alpha) - { - for (b = RED; b < ALPHA; b++) - out[b] = layer[b]; - } - else - { - for (b = RED; b < ALPHA; b++) - out[b] = in[b]; - } + for (b = RED; b < ALPHA; b++) + out[b] = layer[b]; out[ALPHA] = new_alpha; @@ -179,18 +270,7 @@ break; case GIMP_LAYER_COMPOSITE_INTERSECTION: - while (samples--) - { - gint b; - - for (b = RED; b < ALPHA; b++) - out[b] = in[b]; - - out[ALPHA] = 0.0f; - - in += 4; - out += 4; - } + memset (out, 0, 4 * samples * sizeof (gfloat)); break; } diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes/Makefile.in gimp-2.10.14+om/app/operations/layer-modes/Makefile.in --- gimp-2.10.8+zorin2/app/operations/layer-modes/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -261,8 +260,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -392,7 +389,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -531,8 +527,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/operations/layer-modes-legacy/Makefile.in gimp-2.10.14+om/app/operations/layer-modes-legacy/Makefile.in --- gimp-2.10.8+zorin2/app/operations/layer-modes-legacy/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/operations/layer-modes-legacy/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -248,8 +247,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -379,7 +376,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -518,8 +514,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/operations/Makefile.am gimp-2.10.14+om/app/operations/Makefile.am --- gimp-2.10.8+zorin2/app/operations/Makefile.am 2018-04-17 09:24:32.000000000 +0000 +++ gimp-2.10.14+om/app/operations/Makefile.am 2019-06-12 16:43:38.000000000 +0000 @@ -52,6 +52,8 @@ gimpoperationcomposecrop.h \ gimpoperationequalize.c \ gimpoperationequalize.h \ + gimpoperationfillsource.c \ + gimpoperationfillsource.h \ gimpoperationflood.c \ gimpoperationflood.h \ gimpoperationgradient.c \ @@ -60,8 +62,10 @@ gimpoperationgrow.h \ gimpoperationhistogramsink.c \ gimpoperationhistogramsink.h \ - gimpoperationmaskcomponents.c \ + gimpoperationmaskcomponents.cc \ gimpoperationmaskcomponents.h \ + gimpoperationoffset.c \ + gimpoperationoffset.h \ gimpoperationprofiletransform.c \ gimpoperationprofiletransform.h \ gimpoperationscalarmultiply.c \ diff -Nru gimp-2.10.8+zorin2/app/operations/Makefile.in gimp-2.10.14+om/app/operations/Makefile.in --- gimp-2.10.8+zorin2/app/operations/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/operations/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -103,7 +103,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -132,10 +131,12 @@ gimpoperationcagecoefcalc.$(OBJEXT) \ gimpoperationcagetransform.$(OBJEXT) \ gimpoperationcomposecrop.$(OBJEXT) \ - gimpoperationequalize.$(OBJEXT) gimpoperationflood.$(OBJEXT) \ + gimpoperationequalize.$(OBJEXT) \ + gimpoperationfillsource.$(OBJEXT) gimpoperationflood.$(OBJEXT) \ gimpoperationgradient.$(OBJEXT) gimpoperationgrow.$(OBJEXT) \ gimpoperationhistogramsink.$(OBJEXT) \ gimpoperationmaskcomponents.$(OBJEXT) \ + gimpoperationoffset.$(OBJEXT) \ gimpoperationprofiletransform.$(OBJEXT) \ gimpoperationscalarmultiply.$(OBJEXT) \ gimpoperationsemiflatten.$(OBJEXT) \ @@ -185,6 +186,7 @@ ./$(DEPDIR)/gimpoperationcurves.Po \ ./$(DEPDIR)/gimpoperationdesaturate.Po \ ./$(DEPDIR)/gimpoperationequalize.Po \ + ./$(DEPDIR)/gimpoperationfillsource.Po \ ./$(DEPDIR)/gimpoperationflood.Po \ ./$(DEPDIR)/gimpoperationgradient.Po \ ./$(DEPDIR)/gimpoperationgrow.Po \ @@ -192,6 +194,7 @@ ./$(DEPDIR)/gimpoperationhuesaturation.Po \ ./$(DEPDIR)/gimpoperationlevels.Po \ ./$(DEPDIR)/gimpoperationmaskcomponents.Po \ + ./$(DEPDIR)/gimpoperationoffset.Po \ ./$(DEPDIR)/gimpoperationpointfilter.Po \ ./$(DEPDIR)/gimpoperationposterize.Po \ ./$(DEPDIR)/gimpoperationprofiletransform.Po \ @@ -225,6 +228,24 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = SOURCES = $(libappoperations_a_SOURCES) DIST_SOURCES = $(libappoperations_a_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ @@ -317,8 +338,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -448,7 +467,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -587,8 +605,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ @@ -763,6 +779,8 @@ gimpoperationcomposecrop.h \ gimpoperationequalize.c \ gimpoperationequalize.h \ + gimpoperationfillsource.c \ + gimpoperationfillsource.h \ gimpoperationflood.c \ gimpoperationflood.h \ gimpoperationgradient.c \ @@ -771,8 +789,10 @@ gimpoperationgrow.h \ gimpoperationhistogramsink.c \ gimpoperationhistogramsink.h \ - gimpoperationmaskcomponents.c \ + gimpoperationmaskcomponents.cc \ gimpoperationmaskcomponents.h \ + gimpoperationoffset.c \ + gimpoperationoffset.h \ gimpoperationprofiletransform.c \ gimpoperationprofiletransform.h \ gimpoperationscalarmultiply.c \ @@ -822,7 +842,7 @@ all: all-recursive .SUFFIXES: -.SUFFIXES: .c .lo .o .obj +.SUFFIXES: .c .cc .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -886,6 +906,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationcurves.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationdesaturate.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationequalize.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationfillsource.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationflood.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationgradient.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationgrow.Po@am__quote@ # am--include-marker @@ -893,6 +914,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationhuesaturation.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationlevels.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationmaskcomponents.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationoffset.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationpointfilter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationposterize.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpoperationprofiletransform.Po@am__quote@ # am--include-marker @@ -931,6 +953,27 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< +.cc.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + mostlyclean-libtool: -rm -f *.lo @@ -1155,6 +1198,7 @@ -rm -f ./$(DEPDIR)/gimpoperationcurves.Po -rm -f ./$(DEPDIR)/gimpoperationdesaturate.Po -rm -f ./$(DEPDIR)/gimpoperationequalize.Po + -rm -f ./$(DEPDIR)/gimpoperationfillsource.Po -rm -f ./$(DEPDIR)/gimpoperationflood.Po -rm -f ./$(DEPDIR)/gimpoperationgradient.Po -rm -f ./$(DEPDIR)/gimpoperationgrow.Po @@ -1162,6 +1206,7 @@ -rm -f ./$(DEPDIR)/gimpoperationhuesaturation.Po -rm -f ./$(DEPDIR)/gimpoperationlevels.Po -rm -f ./$(DEPDIR)/gimpoperationmaskcomponents.Po + -rm -f ./$(DEPDIR)/gimpoperationoffset.Po -rm -f ./$(DEPDIR)/gimpoperationpointfilter.Po -rm -f ./$(DEPDIR)/gimpoperationposterize.Po -rm -f ./$(DEPDIR)/gimpoperationprofiletransform.Po @@ -1236,6 +1281,7 @@ -rm -f ./$(DEPDIR)/gimpoperationcurves.Po -rm -f ./$(DEPDIR)/gimpoperationdesaturate.Po -rm -f ./$(DEPDIR)/gimpoperationequalize.Po + -rm -f ./$(DEPDIR)/gimpoperationfillsource.Po -rm -f ./$(DEPDIR)/gimpoperationflood.Po -rm -f ./$(DEPDIR)/gimpoperationgradient.Po -rm -f ./$(DEPDIR)/gimpoperationgrow.Po @@ -1243,6 +1289,7 @@ -rm -f ./$(DEPDIR)/gimpoperationhuesaturation.Po -rm -f ./$(DEPDIR)/gimpoperationlevels.Po -rm -f ./$(DEPDIR)/gimpoperationmaskcomponents.Po + -rm -f ./$(DEPDIR)/gimpoperationoffset.Po -rm -f ./$(DEPDIR)/gimpoperationpointfilter.Po -rm -f ./$(DEPDIR)/gimpoperationposterize.Po -rm -f ./$(DEPDIR)/gimpoperationprofiletransform.Po diff -Nru gimp-2.10.8+zorin2/app/operations/operations-enums.c gimp-2.10.14+om/app/operations/operations-enums.c --- gimp-2.10.8+zorin2/app/operations/operations-enums.c 2018-11-08 14:48:25.000000000 +0000 +++ gimp-2.10.14+om/app/operations/operations-enums.c 2019-10-26 19:21:18.000000000 +0000 @@ -338,7 +338,6 @@ { GIMP_LAYER_MODE_CONTEXT_LAYER, "GIMP_LAYER_MODE_CONTEXT_LAYER", "layer" }, { GIMP_LAYER_MODE_CONTEXT_GROUP, "GIMP_LAYER_MODE_CONTEXT_GROUP", "group" }, { GIMP_LAYER_MODE_CONTEXT_PAINT, "GIMP_LAYER_MODE_CONTEXT_PAINT", "paint" }, - { GIMP_LAYER_MODE_CONTEXT_FADE, "GIMP_LAYER_MODE_CONTEXT_FADE", "fade" }, { GIMP_LAYER_MODE_CONTEXT_ALL, "GIMP_LAYER_MODE_CONTEXT_ALL", "all" }, { 0, NULL, NULL } }; @@ -348,7 +347,6 @@ { GIMP_LAYER_MODE_CONTEXT_LAYER, "GIMP_LAYER_MODE_CONTEXT_LAYER", NULL }, { GIMP_LAYER_MODE_CONTEXT_GROUP, "GIMP_LAYER_MODE_CONTEXT_GROUP", NULL }, { GIMP_LAYER_MODE_CONTEXT_PAINT, "GIMP_LAYER_MODE_CONTEXT_PAINT", NULL }, - { GIMP_LAYER_MODE_CONTEXT_FADE, "GIMP_LAYER_MODE_CONTEXT_FADE", NULL }, { GIMP_LAYER_MODE_CONTEXT_ALL, "GIMP_LAYER_MODE_CONTEXT_ALL", NULL }, { 0, NULL, NULL } }; diff -Nru gimp-2.10.8+zorin2/app/operations/operations-enums.h gimp-2.10.14+om/app/operations/operations-enums.h --- gimp-2.10.8+zorin2/app/operations/operations-enums.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/operations-enums.h 2019-01-03 14:13:22.000000000 +0000 @@ -153,12 +153,10 @@ GIMP_LAYER_MODE_CONTEXT_LAYER = 1 << 0, GIMP_LAYER_MODE_CONTEXT_GROUP = 1 << 1, GIMP_LAYER_MODE_CONTEXT_PAINT = 1 << 2, - GIMP_LAYER_MODE_CONTEXT_FADE = 1 << 3, GIMP_LAYER_MODE_CONTEXT_ALL = (GIMP_LAYER_MODE_CONTEXT_LAYER | GIMP_LAYER_MODE_CONTEXT_GROUP | - GIMP_LAYER_MODE_CONTEXT_PAINT | - GIMP_LAYER_MODE_CONTEXT_FADE) + GIMP_LAYER_MODE_CONTEXT_PAINT) } GimpLayerModeContext; @@ -182,7 +180,8 @@ GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE = 1 << 2, GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE = 1 << 3, GIMP_LAYER_MODE_FLAG_SUBTRACTIVE = 1 << 4, - GIMP_LAYER_MODE_FLAG_ALPHA_ONLY = 1 << 5 + GIMP_LAYER_MODE_FLAG_ALPHA_ONLY = 1 << 5, + GIMP_LAYER_MODE_FLAG_TRIVIAL = 1 << 6 } GimpLayerModeFlags; diff -Nru gimp-2.10.8+zorin2/app/operations/operations-types.h gimp-2.10.14+om/app/operations/operations-types.h --- gimp-2.10.8+zorin2/app/operations/operations-types.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/operations/operations-types.h 2019-06-12 16:43:38.000000000 +0000 @@ -64,7 +64,8 @@ const GeglRectangle *roi, gint level); -typedef void (* GimpLayerModeBlendFunc) (const gfloat *in, +typedef void (* GimpLayerModeBlendFunc) (GeglOperation *operation, + const gfloat *in, const gfloat *layer, gfloat *out, gint samples); diff -Nru gimp-2.10.8+zorin2/app/operations/tests/Makefile.in gimp-2.10.14+om/app/operations/tests/Makefile.in --- gimp-2.10.8+zorin2/app/operations/tests/Makefile.in 2018-11-08 16:17:38.000000000 +0000 +++ gimp-2.10.14+om/app/operations/tests/Makefile.in 2019-10-27 17:12:53.000000000 +0000 @@ -105,7 +105,6 @@ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ - $(top_srcdir)/m4macros/binreloc.m4 \ $(top_srcdir)/m4macros/detectcflags.m4 \ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -159,8 +158,6 @@ BABL_CFLAGS = @BABL_CFLAGS@ BABL_LIBS = @BABL_LIBS@ BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ -BINRELOC_CFLAGS = @BINRELOC_CFLAGS@ -BINRELOC_LIBS = @BINRELOC_LIBS@ BUG_REPORT_URL = @BUG_REPORT_URL@ BUILD_EXEEXT = @BUILD_EXEEXT@ BUILD_OBJEXT = @BUILD_OBJEXT@ @@ -290,7 +287,6 @@ GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ -GTK_WIN32_RECOMMENDED_VERSION = @GTK_WIN32_RECOMMENDED_VERSION@ GUDEV_CFLAGS = @GUDEV_CFLAGS@ GUDEV_LIBS = @GUDEV_LIBS@ HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ @@ -429,8 +425,6 @@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ -RECOMMENDED_WIN32_GTK_CFLAGS = @RECOMMENDED_WIN32_GTK_CFLAGS@ -RECOMMENDED_WIN32_GTK_LIBS = @RECOMMENDED_WIN32_GTK_LIBS@ RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ RT_LIBS = @RT_LIBS@ SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ diff -Nru gimp-2.10.8+zorin2/app/paint/gimpbrushcore.c gimp-2.10.14+om/app/paint/gimpbrushcore.c --- gimp-2.10.8+zorin2/app/paint/gimpbrushcore.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpbrushcore.c 2019-06-12 16:43:38.000000000 +0000 @@ -20,7 +20,6 @@ #include #include -#define GEGL_ITERATOR2_API #include #include "libgimpmath/gimpmath.h" @@ -30,6 +29,7 @@ #include "operations/layer-modes/gimp-layer-modes.h" #include "gegl/gimp-babl.h" +#include "gegl/gimp-gegl-loops.h" #include "core/gimpbrush-header.h" #include "core/gimpbrushgenerated.h" @@ -39,6 +39,7 @@ #include "core/gimperror.h" #include "core/gimpimage.h" #include "core/gimpmarshal.h" +#include "core/gimpsymmetry.h" #include "core/gimptempbuf.h" #include "gimpbrushcore.h" @@ -99,27 +100,16 @@ static void gimp_brush_core_real_set_dynamics (GimpBrushCore *core, GimpDynamics *dynamics); +static gdouble gimp_brush_core_get_angle (GimpBrushCore *core); +static gboolean gimp_brush_core_get_reflect (GimpBrushCore *core); + static const GimpTempBuf * gimp_brush_core_transform_mask (GimpBrushCore *core, - GimpBrush *brush, - GeglNode *op); -static const GimpTempBuf * - gimp_brush_core_transform_pixmap (GimpBrushCore *core, - GimpBrush *brush, - GeglNode *op); + GimpBrush *brush); static void gimp_brush_core_invalidate_cache (GimpBrush *brush, GimpBrushCore *core); -/* brush pipe utility functions */ -static void gimp_brush_core_paint_line_pixmap_mask (const Babl *fish, - const GimpTempBuf *pixmap_mask, - const GimpTempBuf *brush_mask, - gfloat *d, - gint x, - gint y, - gint width); - G_DEFINE_TYPE (GimpBrushCore, gimp_brush_core, GIMP_TYPE_PAINT_CORE) @@ -180,10 +170,14 @@ core->dynamics = NULL; core->spacing = 1.0; core->scale = 1.0; - core->angle = 1.0; + core->angle = 0.0; + core->reflect = FALSE; core->hardness = 1.0; core->aspect_ratio = 0.0; + core->symmetry_angle = 0.0; + core->symmetry_reflect = FALSE; + core->pressure_brush = NULL; core->last_solid_brush_mask = NULL; @@ -393,6 +387,8 @@ drawable, paint_options, coords); + + gimp_brush_core_eval_transform_symmetry (core, NULL, 0); } core->spacing = paint_options->brush_spacing; @@ -806,7 +802,8 @@ gimp_brush_transform_size (core->brush, core->scale, core->aspect_ratio, - core->angle, core->reflect, + gimp_brush_core_get_angle (core), + gimp_brush_core_get_reflect (core), &brush_width, &brush_height); if (paint_width) @@ -829,12 +826,16 @@ /* configure the canvas buffer */ if ((x2 - x1) && (y2 - y1)) { - GimpTempBuf *temp_buf; - const Babl *format; + GimpTempBuf *temp_buf; + const Babl *format; + GimpLayerCompositeMode composite_mode; + + composite_mode = gimp_layer_mode_get_paint_composite_mode (paint_mode); format = gimp_layer_mode_get_format (paint_mode, GIMP_LAYER_COLOR_SPACE_AUTO, GIMP_LAYER_COLOR_SPACE_AUTO, + composite_mode, gimp_drawable_get_format (drawable)); if (paint_core->paint_buffer && @@ -848,14 +849,14 @@ return paint_core->paint_buffer; } + g_clear_object (&paint_core->paint_buffer); + temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1), format); *paint_buffer_x = x1; *paint_buffer_y = y1; - g_clear_object (&paint_core->paint_buffer); - paint_core->paint_buffer = gimp_temp_buf_create_buffer (temp_buf); gimp_temp_buf_unref (temp_buf); @@ -930,12 +931,11 @@ GimpLayerMode paint_mode, GimpBrushApplicationMode brush_hardness, gdouble dynamic_force, - GimpPaintApplicationMode mode, - GeglNode *op) + GimpPaintApplicationMode mode) { const GimpTempBuf *brush_mask; - brush_mask = gimp_brush_core_get_brush_mask (core, coords, op, + brush_mask = gimp_brush_core_get_brush_mask (core, coords, brush_hardness, dynamic_force); @@ -975,12 +975,11 @@ gdouble image_opacity, GimpBrushApplicationMode brush_hardness, gdouble dynamic_force, - GimpPaintApplicationMode mode, - GeglNode *op) + GimpPaintApplicationMode mode) { const GimpTempBuf *brush_mask; - brush_mask = gimp_brush_core_get_brush_mask (core, coords, op, + brush_mask = gimp_brush_core_get_brush_mask (core, coords, brush_hardness, dynamic_force); @@ -1027,10 +1026,33 @@ * LOCAL FUNCTION DEFINITIONS * ************************************************************/ +static gdouble +gimp_brush_core_get_angle (GimpBrushCore *core) +{ + gdouble angle = core->angle; + + if (core->reflect) + angle -= core->symmetry_angle; + else + angle += core->symmetry_angle; + + angle = fmod (angle, 1.0); + + if (angle < 0.0) + angle += 1.0; + + return angle; +} + +static gboolean +gimp_brush_core_get_reflect (GimpBrushCore *core) +{ + return core->reflect ^ core->symmetry_reflect; +} + static const GimpTempBuf * gimp_brush_core_transform_mask (GimpBrushCore *core, - GimpBrush *brush, - GeglNode *op) + GimpBrush *brush) { const GimpTempBuf *mask; @@ -1038,11 +1060,10 @@ return NULL; mask = gimp_brush_transform_mask (brush, - op, core->scale, core->aspect_ratio, - core->angle, - core->reflect, + gimp_brush_core_get_angle (core), + gimp_brush_core_get_reflect (core), core->hardness); if (mask == core->transform_brush) @@ -1055,37 +1076,9 @@ return core->transform_brush; } -static const GimpTempBuf * -gimp_brush_core_transform_pixmap (GimpBrushCore *core, - GimpBrush *brush, - GeglNode *op) -{ - const GimpTempBuf *pixmap; - - if (core->scale <= 0.0) - return NULL; - - pixmap = gimp_brush_transform_pixmap (brush, - op, - core->scale, - core->aspect_ratio, - core->angle, - core->reflect, - core->hardness); - - if (pixmap == core->transform_pixmap) - return pixmap; - - core->transform_pixmap = pixmap; - core->subsample_cache_invalid = TRUE; - - return core->transform_pixmap; -} - const GimpTempBuf * gimp_brush_core_get_brush_mask (GimpBrushCore *core, const GimpCoords *coords, - GeglNode *op, GimpBrushApplicationMode brush_hardness, gdouble dynamic_force) { @@ -1094,7 +1087,7 @@ if (dynamic_force <= 0.0) return NULL; - mask = gimp_brush_core_transform_mask (core, core->brush, op); + mask = gimp_brush_core_transform_mask (core, core->brush); if (! mask) return NULL; @@ -1124,6 +1117,30 @@ g_return_val_if_reached (NULL); } +const GimpTempBuf * +gimp_brush_core_get_brush_pixmap (GimpBrushCore *core) +{ + const GimpTempBuf *pixmap; + + if (core->scale <= 0.0) + return NULL; + + pixmap = gimp_brush_transform_pixmap (core->brush, + core->scale, + core->aspect_ratio, + gimp_brush_core_get_angle (core), + gimp_brush_core_get_reflect (core), + core->hardness); + + if (pixmap == core->transform_pixmap) + return pixmap; + + core->transform_pixmap = pixmap; + core->subsample_cache_invalid = TRUE; + + return core->transform_pixmap; +} + void gimp_brush_core_eval_transform_dynamics (GimpBrushCore *core, GimpDrawable *drawable, @@ -1222,196 +1239,106 @@ } } +void +gimp_brush_core_eval_transform_symmetry (GimpBrushCore *core, + GimpSymmetry *symmetry, + gint stroke) +{ + g_return_if_fail (GIMP_IS_BRUSH_CORE (core)); + g_return_if_fail (symmetry == NULL || GIMP_IS_SYMMETRY (symmetry)); -/**************************************************/ -/* Brush pipe utility functions */ -/**************************************************/ + core->symmetry_angle = 0.0; + core->symmetry_reflect = FALSE; + + if (symmetry) + { + gimp_symmetry_get_transform (symmetry, + stroke, + &core->symmetry_angle, + &core->symmetry_reflect); + + core->symmetry_angle /= 360.0; + } +} void -gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core, - GimpDrawable *drawable, - const GimpCoords *coords, - GeglNode *op, - GeglBuffer *area, - gint area_x, - gint area_y, - GimpBrushApplicationMode mode) -{ - GeglBufferIterator *iter; - GeglRectangle *roi; - gint ulx; - gint uly; - gint offsetx; - gint offsety; - const GimpTempBuf *pixmap_mask; - const GimpTempBuf *brush_mask; - const Babl *area_format; - const Babl *pixmap_format; - const Babl *fish = NULL; +gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core, + GimpDrawable *drawable, + const GimpCoords *coords, + GeglBuffer *area, + gint area_x, + gint area_y, + gboolean apply_mask) +{ + const GimpTempBuf *pixmap; + GeglBuffer *pixmap_buffer; + const GimpTempBuf *mask; + GeglBuffer *mask_buffer; + gint area_width; + gint area_height; + gint ul_x; + gint ul_y; + gint offset_x; + gint offset_y; g_return_if_fail (GIMP_IS_BRUSH (core->brush)); g_return_if_fail (gimp_brush_get_pixmap (core->brush) != NULL); - /* scale the brushes */ - pixmap_mask = gimp_brush_core_transform_pixmap (core, core->brush, op); + /* scale the brush */ + pixmap = gimp_brush_core_get_brush_pixmap (core); - if (! pixmap_mask) + if (! pixmap) return; - if (mode != GIMP_BRUSH_HARD) - brush_mask = gimp_brush_core_transform_mask (core, core->brush, op); + if (apply_mask) + mask = gimp_brush_core_transform_mask (core, core->brush); else - brush_mask = NULL; + mask = NULL; /* Calculate upper left corner of brush as in * gimp_paint_core_get_paint_area. Ugly to have to do this here, too. */ - ulx = (gint) floor (coords->x) - (gimp_temp_buf_get_width (pixmap_mask) >> 1); - uly = (gint) floor (coords->y) - (gimp_temp_buf_get_height (pixmap_mask) >> 1); + ul_x = (gint) floor (coords->x) - (gimp_temp_buf_get_width (pixmap) >> 1); + ul_y = (gint) floor (coords->y) - (gimp_temp_buf_get_height (pixmap) >> 1); /* Not sure why this is necessary, but empirically the code does * not work without it for even-sided brushes. See bug #166622. */ - if (gimp_temp_buf_get_width (pixmap_mask) % 2 == 0) - ulx += ROUND (coords->x) - floor (coords->x); - if (gimp_temp_buf_get_height (pixmap_mask) % 2 == 0) - uly += ROUND (coords->y) - floor (coords->y); - - offsetx = area_x - ulx; - offsety = area_y - uly; - - area_format = gegl_buffer_get_format (area); - pixmap_format = gimp_temp_buf_get_format (pixmap_mask); - - iter = gegl_buffer_iterator_new (area, NULL, 0, area_format, - GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 1); - - if (mode == GIMP_BRUSH_SOFT && brush_mask) - { - GimpImageBaseType pixmap_base_type; - GimpPrecision pixmap_precision; - - pixmap_base_type = gimp_babl_format_get_base_type (pixmap_format); - pixmap_precision = gimp_babl_format_get_precision (pixmap_format); - - fish = babl_fish (gimp_babl_format (pixmap_base_type, pixmap_precision, - TRUE), - area_format); - } - else - { - fish = babl_fish (pixmap_format, area_format); - - brush_mask = NULL; - } - - roi = &iter->items[0].roi; - - while (gegl_buffer_iterator_next (iter)) - { - gfloat *d = iter->items[0].data; - gint y; - - for (y = 0; y < roi->height; y++) - { - gimp_brush_core_paint_line_pixmap_mask (fish, - pixmap_mask, brush_mask, - d, offsetx, y + offsety, - roi->width); - d += roi->width * 4; - } - } -} - -static void -gimp_brush_core_paint_line_pixmap_mask (const Babl *fish, - const GimpTempBuf *pixmap_mask, - const GimpTempBuf *brush_mask, - gfloat *d, - gint x, - gint y, - gint width) -{ - const Babl *pixmap_format; - gint pixmap_bytes; - gint pixmap_width; - gint pixmap_height; - guchar *b; - - pixmap_width = gimp_temp_buf_get_width (pixmap_mask); - pixmap_height = gimp_temp_buf_get_height (pixmap_mask); - - /* Make sure x, y are positive */ - x %= pixmap_width; - if (x < 0) - x += pixmap_width; - - y %= pixmap_height; - if (y < 0) - y += pixmap_height; - - pixmap_format = gimp_temp_buf_get_format (pixmap_mask); - pixmap_bytes = babl_format_get_bytes_per_pixel (pixmap_format); - - /* Point to the appropriate scanline */ - b = (gimp_temp_buf_get_data (pixmap_mask) + - y * pixmap_width * pixmap_bytes); - - if (brush_mask) - { - const guchar *mask = (gimp_temp_buf_get_data (brush_mask) + - y * pixmap_width); - guchar *line_buf = g_alloca (width * (pixmap_bytes + 1)); - guchar *l = line_buf; - gint i; - - g_return_if_fail (gimp_temp_buf_get_width (brush_mask) == pixmap_width); - g_return_if_fail (gimp_temp_buf_get_height (brush_mask) == pixmap_height); - - /* put the source pixmap's pixels, plus the mask's alpha, into - * one line, so we can use one single call to babl_process() to - * convert the entire line - */ - - for (i = 0; i < width; i++) - { - gint p_bytes = pixmap_bytes; - guchar *p = b + x * p_bytes; - - while (p_bytes--) - *l++ = *p++; - - *l++ = mask[x++]; - - if (x == pixmap_width) - x = 0; - } - - babl_process (fish, line_buf, d, width); - } - else - { - guchar *line_buf = g_alloca (width * (pixmap_bytes)); - guchar *l = line_buf; - gint i; - - /* put the source pixmap's pixels into one line, so we can use - * one single call to babl_process() to convert the entire line - */ - for (i = 0; i < width; i++) - { - gint p_bytes = pixmap_bytes; - guchar *p = b + x * p_bytes; - - while (p_bytes--) - *l++ = *p++; - - x++; - - if (x == pixmap_width) - x = 0; - } + if (gimp_temp_buf_get_width (pixmap) % 2 == 0) + ul_x += ROUND (coords->x) - floor (coords->x); + if (gimp_temp_buf_get_height (pixmap) % 2 == 0) + ul_y += ROUND (coords->y) - floor (coords->y); + + offset_x = area_x - ul_x; + offset_y = area_y - ul_y; + + area_width = gegl_buffer_get_width (area); + area_height = gegl_buffer_get_height (area); + + pixmap_buffer = gimp_temp_buf_create_buffer (pixmap); + + gimp_gegl_buffer_copy (pixmap_buffer, + GEGL_RECTANGLE (offset_x, offset_y, + area_width, area_height), + GEGL_ABYSS_NONE, + area, + GEGL_RECTANGLE (0, 0, + area_width, area_height)); + + g_object_unref (pixmap_buffer); + + if (mask) + { + mask_buffer = gimp_temp_buf_create_buffer (mask); + + gimp_gegl_apply_mask (mask_buffer, + GEGL_RECTANGLE (offset_x, offset_y, + area_width, area_height), + area, + GEGL_RECTANGLE (0, 0, + area_width, area_height), + 1.0); - babl_process (fish, line_buf, d, width); + g_object_unref (mask_buffer); } } diff -Nru gimp-2.10.8+zorin2/app/paint/gimpbrushcore.h gimp-2.10.14+om/app/paint/gimpbrushcore.h --- gimp-2.10.8+zorin2/app/paint/gimpbrushcore.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpbrushcore.h 2019-06-12 16:43:38.000000000 +0000 @@ -51,6 +51,9 @@ gboolean reflect; gdouble hardness; + gdouble symmetry_angle; + gboolean symmetry_reflect; + /* brush buffers */ GimpTempBuf *pressure_brush; @@ -108,8 +111,7 @@ GimpLayerMode paint_mode, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode, - GeglNode *op); + GimpPaintApplicationMode mode); void gimp_brush_core_replace_canvas (GimpBrushCore *core, GimpDrawable *drawable, const GimpCoords *coords, @@ -117,31 +119,34 @@ gdouble image_opacity, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness, - GimpPaintApplicationMode mode, - GeglNode *op); + GimpPaintApplicationMode mode); void gimp_brush_core_color_area_with_pixmap (GimpBrushCore *core, GimpDrawable *drawable, const GimpCoords *coords, - GeglNode *op, GeglBuffer *area, gint area_x, gint area_y, - GimpBrushApplicationMode mode); + gboolean apply_mask); const GimpTempBuf * gimp_brush_core_get_brush_mask (GimpBrushCore *core, const GimpCoords *coords, - GeglNode *op, GimpBrushApplicationMode brush_hardness, gdouble dynamic_hardness); +const GimpTempBuf * gimp_brush_core_get_brush_pixmap + (GimpBrushCore *core); void gimp_brush_core_eval_transform_dynamics - (GimpBrushCore *paint_core, + (GimpBrushCore *core, GimpDrawable *drawable, GimpPaintOptions *paint_options, const GimpCoords *coords); +void gimp_brush_core_eval_transform_symmetry + (GimpBrushCore *core, + GimpSymmetry *symmetry, + gint stroke); #endif /* __GIMP_BRUSH_CORE_H__ */ diff -Nru gimp-2.10.8+zorin2/app/paint/gimpbrushcore-kernels.h gimp-2.10.14+om/app/paint/gimpbrushcore-kernels.h --- gimp-2.10.8+zorin2/app/paint/gimpbrushcore-kernels.h 2009-06-15 18:13:14.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpbrushcore-kernels.h 2019-04-07 11:38:14.000000000 +0000 @@ -7,50 +7,110 @@ #ifndef __GIMP_BRUSH_CORE_KERNELS_H__ #define __GIMP_BRUSH_CORE_KERNELS_H__ + #define KERNEL_WIDTH 3 #define KERNEL_HEIGHT 3 #define KERNEL_SUBSAMPLE 4 -#define KERNEL_SUM 256 -/* Brush pixel subsampling kernels */ -static const int subsample[5][5][9] = +#ifdef __cplusplus + +template +struct Kernel; + +template <> +struct Kernel { + using value_type = guchar; + using kernel_type = guint; + using accum_type = gulong; + + static constexpr kernel_type + coeff (kernel_type x) { - { 64, 64, 0, 64, 64, 0, 0, 0, 0, }, - { 25, 103, 0, 25, 103, 0, 0, 0, 0, }, - { 0, 128, 0, 0, 128, 0, 0, 0, 0, }, - { 0, 103, 25, 0, 103, 25, 0, 0, 0, }, - { 0, 64, 64, 0, 64, 64, 0, 0, 0, } - }, - { - { 25, 25, 0, 103, 103, 0, 0, 0, 0, }, - { 6, 44, 0, 44, 162, 0, 0, 0, 0, }, - { 0, 50, 0, 0, 206, 0, 0, 0, 0, }, - { 0, 44, 6, 0, 162, 44, 0, 0, 0, }, - { 0, 25, 25, 0, 103, 103, 0, 0, 0, } - }, + return x; + } + + static constexpr value_type + round (accum_type x) { - { 0, 0, 0, 128, 128, 0, 0, 0, 0, }, - { 0, 0, 0, 50, 206, 0, 0, 0, 0, }, - { 0, 0, 0, 0, 256, 0, 0, 0, 0, }, - { 0, 0, 0, 0, 206, 50, 0, 0, 0, }, - { 0, 0, 0, 0, 128, 128, 0, 0, 0, } - }, + return (x + 128) / 256; + } +}; + +template <> +struct Kernel +{ + using value_type = gfloat; + using kernel_type = gfloat; + using accum_type = gfloat; + + static constexpr kernel_type + coeff (kernel_type x) { - { 0, 0, 0, 103, 103, 0, 25, 25, 0, }, - { 0, 0, 0, 44, 162, 0, 6, 44, 0, }, - { 0, 0, 0, 0, 206, 0, 0, 50, 0, }, - { 0, 0, 0, 0, 162, 44, 0, 44, 6, }, - { 0, 0, 0, 0, 103, 103, 0, 25, 25, } - }, + return x / 256.0f; + } + + static constexpr value_type + round (accum_type x) { - { 0, 0, 0, 64, 64, 0, 64, 64, 0, }, - { 0, 0, 0, 25, 103, 0, 25, 103, 0, }, - { 0, 0, 0, 0, 128, 0, 0, 128, 0, }, - { 0, 0, 0, 0, 103, 25, 0, 103, 25, }, - { 0, 0, 0, 0, 64, 64, 0, 64, 64, } + return x; } }; + +/* Brush pixel subsampling kernels */ +template +struct Subsample : Kernel +{ + #define C(x) (Subsample::coeff (x)) + + static constexpr typename Subsample::kernel_type kernel[5][5][9] = + { + { + { C( 64), C( 64), C( 0), C( 64), C( 64), C( 0), C( 0), C( 0), C( 0), }, + { C( 25), C(103), C( 0), C( 25), C(103), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C(128), C( 0), C( 0), C(128), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C(103), C( 25), C( 0), C(103), C( 25), C( 0), C( 0), C( 0), }, + { C( 0), C( 64), C( 64), C( 0), C( 64), C( 64), C( 0), C( 0), C( 0), } + }, + { + { C( 25), C( 25), C( 0), C(103), C(103), C( 0), C( 0), C( 0), C( 0), }, + { C( 6), C( 44), C( 0), C( 44), C(162), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C( 50), C( 0), C( 0), C(206), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C( 44), C( 6), C( 0), C(162), C( 44), C( 0), C( 0), C( 0), }, + { C( 0), C( 25), C( 25), C( 0), C(103), C(103), C( 0), C( 0), C( 0), } + }, + { + { C( 0), C( 0), C( 0), C(128), C(128), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C( 0), C( 0), C( 50), C(206), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(256), C( 0), C( 0), C( 0), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(206), C( 50), C( 0), C( 0), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(128), C(128), C( 0), C( 0), C( 0), } + }, + { + { C( 0), C( 0), C( 0), C(103), C(103), C( 0), C( 25), C( 25), C( 0), }, + { C( 0), C( 0), C( 0), C( 44), C(162), C( 0), C( 6), C( 44), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(206), C( 0), C( 0), C( 50), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(162), C( 44), C( 0), C( 44), C( 6), }, + { C( 0), C( 0), C( 0), C( 0), C(103), C(103), C( 0), C( 25), C( 25), } + }, + { + { C( 0), C( 0), C( 0), C( 64), C( 64), C( 0), C( 64), C( 64), C( 0), }, + { C( 0), C( 0), C( 0), C( 25), C(103), C( 0), C( 25), C(103), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(128), C( 0), C( 0), C(128), C( 0), }, + { C( 0), C( 0), C( 0), C( 0), C(103), C( 25), C( 0), C(103), C( 25), }, + { C( 0), C( 0), C( 0), C( 0), C( 64), C( 64), C( 0), C( 64), C( 64), } + } + }; + + #undef C +}; + +template +constexpr typename Subsample::kernel_type Subsample::kernel[5][5][9]; + +#endif /* __cplusplus */ + + #endif /* __GIMP_BRUSH_CORE_KERNELS_H__ */ diff -Nru gimp-2.10.8+zorin2/app/paint/gimpbrushcore-loops.cc gimp-2.10.14+om/app/paint/gimpbrushcore-loops.cc --- gimp-2.10.8+zorin2/app/paint/gimpbrushcore-loops.cc 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpbrushcore-loops.cc 2019-10-26 18:49:18.000000000 +0000 @@ -29,129 +29,126 @@ #include "paint-types.h" -#include "core/gimp-parallel.h" #include "core/gimptempbuf.h" #include "gimpbrushcore.h" #include "gimpbrushcore-loops.h" -#include "gimpbrushcore-kernels.h" +} /* extern "C" */ -#define MIN_PARALLEL_SUB_SIZE 64 -#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE) +#include "gimpbrushcore-kernels.h" -static inline void -rotate_pointers (gulong **p, - guint32 n) -{ - guint32 i; - gulong *tmp; +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) - tmp = p[0]; - - for (i = 0; i < n-1; i++) - p[i] = p[i+1]; +#define EPSILON 1e-6 - p[i] = tmp; -} -const GimpTempBuf * -gimp_brush_core_subsample_mask (GimpBrushCore *core, - const GimpTempBuf *mask, - gdouble x, - gdouble y) +static void +clear_edges (GimpTempBuf *buf, + gint top, + gint bottom, + gint left, + gint right) { - GimpTempBuf *dest; - gdouble left; - gint index1; - gint index2; - gint dest_offset_x = 0; - gint dest_offset_y = 0; - const gint *kernel; - gint mask_width = gimp_temp_buf_get_width (mask); - gint mask_height = gimp_temp_buf_get_height (mask); - gint dest_width; - gint dest_height; - - left = x - floor (x); - index1 = (gint) (left * (gdouble) (KERNEL_SUBSAMPLE + 1)); + guchar *data; + const Babl *format = gimp_temp_buf_get_format (buf); + gint bpp = babl_format_get_bytes_per_pixel (format); + gint width = gimp_temp_buf_get_width (buf); + gint height = gimp_temp_buf_get_height (buf); - left = y - floor (y); - index2 = (gint) (left * (gdouble) (KERNEL_SUBSAMPLE + 1)); - - - if ((mask_width % 2) == 0) + if (top + bottom >= height || left + right >= width) { - index1 += KERNEL_SUBSAMPLE >> 1; + gimp_temp_buf_data_clear (buf); - if (index1 > KERNEL_SUBSAMPLE) - { - index1 -= KERNEL_SUBSAMPLE + 1; - dest_offset_x = 1; - } + return; } - if ((mask_height % 2) == 0) + data = gimp_temp_buf_get_data (buf); + + memset (data, 0, (top * width + left) * bpp); + + if (left + right) { - index2 += KERNEL_SUBSAMPLE >> 1; + gint stride = width * bpp; + gint size = (left + right) * bpp; + gint y; - if (index2 > KERNEL_SUBSAMPLE) + data = gimp_temp_buf_get_data (buf) + + ((top + 1) * width - right) * bpp; + + for (y = top; y < height - bottom - 1; y++) { - index2 -= KERNEL_SUBSAMPLE + 1; - dest_offset_y = 1; + memset (data, 0, size); + + data += stride; } } - kernel = subsample[index2][index1]; + data = gimp_temp_buf_get_data (buf) + + ((height - bottom) * width - right) * bpp; - if (mask == core->last_subsample_brush_mask && - ! core->subsample_cache_invalid) - { - if (core->subsample_brushes[index2][index1]) - return core->subsample_brushes[index2][index1]; - } - else - { - gint i, j; - - for (i = 0; i < KERNEL_SUBSAMPLE + 1; i++) - for (j = 0; j < KERNEL_SUBSAMPLE + 1; j++) - g_clear_pointer (&core->subsample_brushes[i][j], gimp_temp_buf_unref); + memset (data, 0, (bottom * width + right) * bpp); +} - core->last_subsample_brush_mask = mask; - core->subsample_cache_invalid = FALSE; - } +template +static inline void +rotate_pointers (T **p, + gint n) +{ + T *tmp; + gint i; - dest = gimp_temp_buf_new (mask_width + 2, - mask_height + 2, - gimp_temp_buf_get_format (mask)); - gimp_temp_buf_data_clear (dest); + tmp = p[0]; - dest_width = gimp_temp_buf_get_width (dest); - dest_height = gimp_temp_buf_get_height (dest); + for (i = 0; i < n - 1; i++) + p[i] = p[i + 1]; - core->subsample_brushes[index2][index1] = dest; + p[i] = tmp; +} - gimp_parallel_distribute_range (mask_height, MIN_PARALLEL_SUB_SIZE, - [=] (gint y, gint height) - { - const guchar *m; - guchar *d; - const gint *k; - gint y0; - gint i, j; - gint r, s; - gint offs; - gulong *accum[KERNEL_HEIGHT]; +template +static void +gimp_brush_core_subsample_mask_impl (const GimpTempBuf *mask, + GimpTempBuf *dest, + gint dest_offset_x, + gint dest_offset_y, + gint index1, + gint index2) +{ + using value_type = typename Subsample::value_type; + using kernel_type = typename Subsample::kernel_type; + using accum_type = typename Subsample::accum_type; + + Subsample subsample; + const kernel_type *kernel = subsample.kernel[index2][index1]; + gint mask_width = gimp_temp_buf_get_width (mask); + gint mask_height = gimp_temp_buf_get_height (mask); + gint dest_width = gimp_temp_buf_get_width (dest); + gint dest_height = gimp_temp_buf_get_height (dest); + + gegl_parallel_distribute_range ( + mask_height, PIXELS_PER_THREAD / mask_width, + [=] (gint y, gint height) + { + const value_type *m; + value_type *d; + const kernel_type *k; + gint y0; + gint i, j; + gint r, s; + gint offs; + accum_type *accum[KERNEL_HEIGHT]; /* Allocate and initialize the accum buffer */ for (i = 0; i < KERNEL_HEIGHT ; i++) - accum[i] = g_new0 (gulong, dest_width + 1); + accum[i] = gegl_scratch_new0 (accum_type, dest_width + 1); y0 = MAX (y - (KERNEL_HEIGHT - 1), 0); - m = gimp_temp_buf_get_data (mask) + y0 * mask_width; + m = (const value_type *) gimp_temp_buf_get_data (mask) + + y0 * mask_width; for (i = y0; i < y; i++) { @@ -187,13 +184,15 @@ } /* store the accum buffer into the destination mask */ - d = gimp_temp_buf_get_data (dest) + (i + dest_offset_y) * dest_width; + d = (value_type *) gimp_temp_buf_get_data (dest) + + (i + dest_offset_y) * dest_width; for (j = 0; j < dest_width; j++) - *d++ = (accum[0][j] + 127) / KERNEL_SUM; + *d++ = subsample.round (accum[0][j]); rotate_pointers (accum, KERNEL_HEIGHT); - memset (accum[KERNEL_HEIGHT - 1], 0, sizeof (gulong) * dest_width); + memset (accum[KERNEL_HEIGHT - 1], 0, + sizeof (accum_type) * dest_width); } if (y + height == mask_height) @@ -201,71 +200,170 @@ /* store the rest of the accum buffer into the dest mask */ while (i + dest_offset_y < dest_height) { - d = gimp_temp_buf_get_data (dest) + (i + dest_offset_y) * dest_width; + d = (value_type *) gimp_temp_buf_get_data (dest) + + (i + dest_offset_y) * dest_width; for (j = 0; j < dest_width; j++) - *d++ = (accum[0][j] + (KERNEL_SUM / 2)) / KERNEL_SUM; + *d++ = subsample.round (accum[0][j]); rotate_pointers (accum, KERNEL_HEIGHT); i++; } } - for (i = 0; i < KERNEL_HEIGHT ; i++) - g_free (accum[i]); + for (i = KERNEL_HEIGHT - 1; i >= 0; i--) + gegl_scratch_free (accum[i]); }); +} + +const GimpTempBuf * +gimp_brush_core_subsample_mask (GimpBrushCore *core, + const GimpTempBuf *mask, + gdouble x, + gdouble y) +{ + GimpTempBuf *dest; + const Babl *mask_format; + gdouble left; + gint index1; + gint index2; + gint dest_offset_x = 0; + gint dest_offset_y = 0; + gint mask_width = gimp_temp_buf_get_width (mask); + gint mask_height = gimp_temp_buf_get_height (mask); + + left = x - floor (x); + index1 = (gint) (left * (gdouble) (KERNEL_SUBSAMPLE + 1)); + + left = y - floor (y); + index2 = (gint) (left * (gdouble) (KERNEL_SUBSAMPLE + 1)); + + if ((mask_width % 2) == 0) + { + index1 += KERNEL_SUBSAMPLE >> 1; + + if (index1 > KERNEL_SUBSAMPLE) + { + index1 -= KERNEL_SUBSAMPLE + 1; + dest_offset_x = 1; + } + } + + if ((mask_height % 2) == 0) + { + index2 += KERNEL_SUBSAMPLE >> 1; + + if (index2 > KERNEL_SUBSAMPLE) + { + index2 -= KERNEL_SUBSAMPLE + 1; + dest_offset_y = 1; + } + } + + if (mask == core->last_subsample_brush_mask && + ! core->subsample_cache_invalid) + { + if (core->subsample_brushes[index2][index1]) + return core->subsample_brushes[index2][index1]; + } + else + { + gint i, j; + + for (i = 0; i < KERNEL_SUBSAMPLE + 1; i++) + for (j = 0; j < KERNEL_SUBSAMPLE + 1; j++) + g_clear_pointer (&core->subsample_brushes[i][j], gimp_temp_buf_unref); + + core->last_subsample_brush_mask = mask; + core->subsample_cache_invalid = FALSE; + } + + mask_format = gimp_temp_buf_get_format (mask); + + dest = gimp_temp_buf_new (mask_width + 2, + mask_height + 2, + mask_format); + clear_edges (dest, dest_offset_y, 0, 0, 0); + + core->subsample_brushes[index2][index1] = dest; + + if (mask_format == babl_format ("Y u8")) + { + gimp_brush_core_subsample_mask_impl (mask, dest, + dest_offset_x, dest_offset_y, + index1, index2); + } + else if (mask_format == babl_format ("Y float")) + { + gimp_brush_core_subsample_mask_impl (mask, dest, + dest_offset_x, dest_offset_y, + index1, index2); + } + else + { + g_warn_if_reached (); + } return dest; } -/* #define FANCY_PRESSURE */ - -const GimpTempBuf * -gimp_brush_core_pressurize_mask (GimpBrushCore *core, - const GimpTempBuf *brush_mask, - gdouble x, - gdouble y, - gdouble pressure) +/* The simple pressure profile + * + * It is: I'(I) = MIN (2 * pressure * I, 1) + */ +class SimplePressure { - static guchar mapi[256]; - const GimpTempBuf *subsample_mask; - gint i; + gfloat scale; - /* Get the raw subsampled mask */ - subsample_mask = gimp_brush_core_subsample_mask (core, - brush_mask, - x, y); +public: + SimplePressure (gdouble pressure) + { + scale = 2.0 * pressure; + } - /* Special case pressure = 0.5 */ - if ((gint) (pressure * 100 + 0.5) == 50) - return subsample_mask; + guchar + operator () (guchar x) const + { + gint v = RINT (scale * x); - g_clear_pointer (&core->pressure_brush, gimp_temp_buf_unref); + return MIN (v, 255); + } - core->pressure_brush = - gimp_temp_buf_new (gimp_temp_buf_get_width (brush_mask) + 2, - gimp_temp_buf_get_height (brush_mask) + 2, - gimp_temp_buf_get_format (brush_mask)); - gimp_temp_buf_data_clear (core->pressure_brush); + gfloat + operator () (gfloat x) const + { + gfloat v = scale * x; -#ifdef FANCY_PRESSURE + return MIN (v, 1.0f); + } + + template + T + operator () (T x) const = delete; +}; + +/* The fancy pressure profile + * + * It is: I'(I) = tanh (20 * (pressure - 0.5) * I) : pressure > 0.5 + * I'(I) = 1 - tanh (20 * (0.5 - pressure) * (1 - I)) : pressure < 0.5 + * + * It looks like: + * + * low pressure medium pressure high pressure + * + * | / -- + * | / / + * / / | + * -- / | + */ +class FancyPressure +{ + gfloat map[257]; - /* Create the pressure profile - * - * It is: I'(I) = tanh (20 * (pressure - 0.5) * I) : pressure > 0.5 - * I'(I) = 1 - tanh (20 * (0.5 - pressure) * (1 - I)) : pressure < 0.5 - * - * It looks like: - * - * low pressure medium pressure high pressure - * - * | / -- - * | / / - * / / | - * -- / | - */ +public: + FancyPressure (gdouble pressure) { - gdouble map[256]; - gdouble ds, s, c; + gdouble ds, s, c; + gint i; ds = (pressure - 0.5) * (20.0 / 256.0); s = 0; @@ -281,7 +379,7 @@ } for (i = 0; i < 256; i++) - mapi[i] = (gint) (255 * map[i] / map[255]); + map[i] = map[i] / map[255]; } else { @@ -294,53 +392,182 @@ c += s * ds; } - for (i = 0; i < 256; i++) - mapi[i] = (gint) (255 * (1 - map[i] / map[0])); + for (i = 255; i >= 0; i--) + map[i] = 1.0f - map[i] / map[0]; } + + map[256] = map[255]; } -#else /* ! FANCY_PRESSURE */ + guchar + operator () (guchar x) const + { + return RINT (255.0f * map[x]); + } + gfloat + operator () (gfloat x) const { - gdouble j, k; + gint i; + gfloat f; - j = pressure + pressure; - k = 0; + x *= 255.0f; - for (i = 0; i < 256; i++) - { - if (k > 255) - mapi[i] = 255; - else - mapi[i] = (guchar) k; + i = floorf (x); + f = x - i; - k += j; - } + return map[i] + (map[i + 1] - map[i]) * f; } -#endif /* FANCY_PRESSURE */ + template + T + operator () (T x) const = delete; +}; - /* Now convert the brush */ +template +class CachedPressure +{ + T map[T (~0) + 1]; - gimp_parallel_distribute_range (gimp_temp_buf_get_width (subsample_mask) * - gimp_temp_buf_get_height (subsample_mask), - MIN_PARALLEL_SUB_AREA, - [=] (gint offset, gint size) - { - const guchar *source; - guchar *dest; - gint i; +public: + template + CachedPressure (Pressure pressure) + { + gint i; + + for (i = 0; i < (gint) G_N_ELEMENTS (map); i++) + map[i] = pressure (T (i)); + } + + T + operator () (T x) const + { + return map[x]; + } + + template + U + operator () (U x) const = delete; +}; + +template +void +gimp_brush_core_pressurize_mask_impl (const GimpTempBuf *mask, + GimpTempBuf *dest, + Pressure pressure) +{ + gegl_parallel_distribute_range ( + gimp_temp_buf_get_width (mask) * gimp_temp_buf_get_height (mask), + PIXELS_PER_THREAD, + [=] (gint offset, gint size) + { + const T *m; + T *d; + gint i; - source = gimp_temp_buf_get_data (subsample_mask) + offset; - dest = gimp_temp_buf_get_data (core->pressure_brush) + offset; + m = (const T *) gimp_temp_buf_get_data (mask) + offset; + d = ( T *) gimp_temp_buf_get_data (dest) + offset; for (i = 0; i < size; i++) - *dest++ = mapi[(*source++)]; + *d++ = pressure (*m++); }); +} + +/* #define FANCY_PRESSURE */ + +const GimpTempBuf * +gimp_brush_core_pressurize_mask (GimpBrushCore *core, + const GimpTempBuf *brush_mask, + gdouble x, + gdouble y, + gdouble pressure) +{ + const GimpTempBuf *subsample_mask; + const Babl *subsample_mask_format; + + /* Get the raw subsampled mask */ + subsample_mask = gimp_brush_core_subsample_mask (core, + brush_mask, + x, y); + + /* Special case pressure = 0.5 */ + if (fabs (pressure - 0.5) <= EPSILON) + return subsample_mask; + + g_clear_pointer (&core->pressure_brush, gimp_temp_buf_unref); + + subsample_mask_format = gimp_temp_buf_get_format (subsample_mask); + + core->pressure_brush = + gimp_temp_buf_new (gimp_temp_buf_get_width (brush_mask) + 2, + gimp_temp_buf_get_height (brush_mask) + 2, + subsample_mask_format); + +#ifdef FANCY_PRESSURE + using Pressure = FancyPressure; +#else + using Pressure = SimplePressure; +#endif + + if (subsample_mask_format == babl_format ("Y u8")) + { + gimp_brush_core_pressurize_mask_impl (subsample_mask, + core->pressure_brush, + CachedPressure ( + Pressure (pressure))); + } + else if (subsample_mask_format == babl_format ("Y float")) + { + gimp_brush_core_pressurize_mask_impl (subsample_mask, + core->pressure_brush, + Pressure (pressure)); + } + else + { + g_warn_if_reached (); + } return core->pressure_brush; } +template +static void +gimp_brush_core_solidify_mask_impl (const GimpTempBuf *mask, + GimpTempBuf *dest, + gint dest_offset_x, + gint dest_offset_y) +{ + gint mask_width = gimp_temp_buf_get_width (mask); + gint mask_height = gimp_temp_buf_get_height (mask); + gint dest_width = gimp_temp_buf_get_width (dest); + + gegl_parallel_distribute_area ( + GEGL_RECTANGLE (0, 0, mask_width, mask_height), + PIXELS_PER_THREAD, + [=] (const GeglRectangle *area) + { + const T *m; + gfloat *d; + gint i, j; + + m = (const T *) gimp_temp_buf_get_data (mask) + + area->y * mask_width + area->x; + d = ((gfloat *) gimp_temp_buf_get_data (dest) + + ((dest_offset_y + 1 + area->y) * dest_width + + (dest_offset_x + 1 + area->x))); + + for (i = 0; i < area->height; i++) + { + for (j = 0; j < area->width; j++) + *d++ = (*m++) ? 1.0 : 0.0; + + m += mask_width - area->width; + d += dest_width - area->width; + } + }); +} + const GimpTempBuf * gimp_brush_core_solidify_mask (GimpBrushCore *core, const GimpTempBuf *brush_mask, @@ -348,6 +575,7 @@ gdouble y) { GimpTempBuf *dest; + const Babl *brush_mask_format; gint dest_offset_x = 0; gint dest_offset_y = 0; gint brush_mask_width = gimp_temp_buf_get_width (brush_mask); @@ -355,8 +583,8 @@ if ((brush_mask_width % 2) == 0) { - while (x < 0) - x += brush_mask_width; + if (x < 0.0) + x = fmod (x, brush_mask_width) + brush_mask_width; if ((x - floor (x)) >= 0.5) dest_offset_x++; @@ -364,8 +592,8 @@ if ((brush_mask_height % 2) == 0) { - while (y < 0) - y += brush_mask_height; + if (y < 0.0) + y = fmod (y, brush_mask_height) + brush_mask_height; if ((y - floor (y)) >= 0.5) dest_offset_y++; @@ -389,41 +617,31 @@ core->solid_cache_invalid = FALSE; } + brush_mask_format = gimp_temp_buf_get_format (brush_mask); + dest = gimp_temp_buf_new (brush_mask_width + 2, brush_mask_height + 2, babl_format ("Y float")); - gimp_temp_buf_data_clear (dest); + clear_edges (dest, + 1 + dest_offset_y, 1 - dest_offset_y, + 1 + dest_offset_x, 1 - dest_offset_x); core->solid_brushes[dest_offset_y][dest_offset_x] = dest; - gimp_parallel_distribute_area (GEGL_RECTANGLE (0, - 0, - brush_mask_width, - brush_mask_height), - MIN_PARALLEL_SUB_AREA, - [=] (const GeglRectangle *area) - { - const guchar *m; - gfloat *d; - gint i, j; - - m = gimp_temp_buf_get_data (brush_mask) + - area->y * brush_mask_width + area->x; - d = ((gfloat *) gimp_temp_buf_get_data (dest) + - ((dest_offset_y + 1 + area->y) * gimp_temp_buf_get_width (dest) + - (dest_offset_x + 1 + area->x))); - - for (i = 0; i < area->height; i++) - { - for (j = 0; j < area->width; j++) - *d++ = (*m++) ? 1.0 : 0.0; - - m += brush_mask_width - area->width; - d += brush_mask_width + 2 - area->width; - } - }); + if (brush_mask_format == babl_format ("Y u8")) + { + gimp_brush_core_solidify_mask_impl (brush_mask, dest, + dest_offset_x, dest_offset_y); + } + else if (brush_mask_format == babl_format ("Y float")) + { + gimp_brush_core_solidify_mask_impl (brush_mask, dest, + dest_offset_x, dest_offset_y); + } + else + { + g_warn_if_reached (); + } return dest; } - -} /* extern "C" */ diff -Nru gimp-2.10.8+zorin2/app/paint/gimpclone.c gimp-2.10.14+om/app/paint/gimpclone.c --- gimp-2.10.8+zorin2/app/paint/gimpclone.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpclone.c 2019-06-12 16:43:38.000000000 +0000 @@ -27,6 +27,7 @@ #include "paint-types.h" +#include "gegl/gimp-gegl-apply-operation.h" #include "gegl/gimp-gegl-loops.h" #include "core/gimp.h" @@ -168,35 +169,28 @@ if (gimp_source_core_use_source (source_core, source_options)) { - gimp_gegl_buffer_copy (src_buffer, - GEGL_RECTANGLE (src_rect->x, - src_rect->y, - paint_area_width, - paint_area_height), - GEGL_ABYSS_NONE, - paint_buffer, - GEGL_RECTANGLE (paint_area_offset_x, - paint_area_offset_y, - 0, 0)); - if (op) + if (! op) { - GeglNode *graph, *source, *target; - - graph = gegl_node_new (); - source = gegl_node_new_child (graph, - "operation", "gegl:buffer-source", - "buffer", paint_buffer, - NULL); - gegl_node_add_child (graph, op); - target = gegl_node_new_child (graph, - "operation", "gegl:write-buffer", - "buffer", paint_buffer, - NULL); - - gegl_node_link_many (source, op, target, NULL); - gegl_node_process (target); - - g_object_unref (graph); + gimp_gegl_buffer_copy (src_buffer, + GEGL_RECTANGLE (src_rect->x, + src_rect->y, + paint_area_width, + paint_area_height), + GEGL_ABYSS_NONE, + paint_buffer, + GEGL_RECTANGLE (paint_area_offset_x, + paint_area_offset_y, + 0, 0)); + } + else + { + gimp_gegl_apply_operation (src_buffer, NULL, NULL, op, + paint_buffer, + GEGL_RECTANGLE (paint_area_offset_x, + paint_area_offset_y, + paint_area_width, + paint_area_height), + FALSE); } } else if (options->clone_type == GIMP_CLONE_PATTERN) @@ -251,8 +245,7 @@ */ source_options->align_mode == GIMP_SOURCE_ALIGN_FIXED ? - GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT, - NULL); + GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT); } static gboolean diff -Nru gimp-2.10.8+zorin2/app/paint/gimpconvolve.c gimp-2.10.14+om/app/paint/gimpconvolve.c --- gimp-2.10.8+zorin2/app/paint/gimpconvolve.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpconvolve.c 2019-06-12 16:43:38.000000000 +0000 @@ -139,7 +139,6 @@ gdouble opacity; gdouble rate; const GimpCoords *coords; - GeglNode *op; gint paint_width, paint_height; gint n_strokes; gint i; @@ -165,6 +164,8 @@ { coords = gimp_symmetry_get_coords (sym, i); + gimp_brush_core_eval_transform_symmetry (brush_core, sym, i); + paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable, paint_options, GIMP_LAYER_MODE_NORMAL, @@ -176,10 +177,6 @@ if (! paint_buffer) continue; - op = gimp_symmetry_get_operation (sym, i, - paint_width, - paint_height); - rate = (options->rate * gimp_dynamics_get_linear_value (dynamics, GIMP_DYNAMICS_OUTPUT_RATE, @@ -228,7 +225,7 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), 1.0, - GIMP_PAINT_INCREMENTAL, op); + GIMP_PAINT_INCREMENTAL); } } diff -Nru gimp-2.10.8+zorin2/app/paint/gimpdodgeburn.c gimp-2.10.14+om/app/paint/gimpdodgeburn.c --- gimp-2.10.8+zorin2/app/paint/gimpdodgeburn.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpdodgeburn.c 2019-06-12 16:43:38.000000000 +0000 @@ -112,10 +112,12 @@ GimpPaintOptions *paint_options, GimpSymmetry *sym) { - GimpDodgeBurnOptions *options = GIMP_DODGE_BURN_OPTIONS (paint_options); - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); + GimpDodgeBurnOptions *options = GIMP_DODGE_BURN_OPTIONS (paint_options); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GeglBuffer *src_buffer; GeglBuffer *paint_buffer; gint paint_buffer_x; gint paint_buffer_y; @@ -123,7 +125,6 @@ gdouble opacity; gdouble force; const GimpCoords *coords; - GeglNode *op; gint paint_width, paint_height; gint n_strokes; gint i; @@ -140,7 +141,12 @@ if (opacity == 0.0) return; - gimp_brush_core_eval_transform_dynamics (GIMP_BRUSH_CORE (paint_core), + if (paint_options->application_mode == GIMP_PAINT_CONSTANT) + src_buffer = gimp_paint_core_get_orig_image (paint_core); + else + src_buffer = gimp_drawable_get_buffer (drawable); + + gimp_brush_core_eval_transform_dynamics (brush_core, drawable, paint_options, coords); @@ -149,6 +155,8 @@ { coords = gimp_symmetry_get_coords (sym, i); + gimp_brush_core_eval_transform_symmetry (brush_core, sym, i); + paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable, paint_options, GIMP_LAYER_MODE_NORMAL, @@ -160,12 +168,8 @@ if (! paint_buffer) continue; - op = gimp_symmetry_get_operation (sym, i, - paint_width, - paint_height); - /* DodgeBurn the region */ - gimp_gegl_dodgeburn (gimp_paint_core_get_orig_image (paint_core), + gimp_gegl_dodgeburn (src_buffer, GEGL_RECTANGLE (paint_buffer_x, paint_buffer_y, gegl_buffer_get_width (paint_buffer), @@ -192,6 +196,6 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), force, - GIMP_PAINT_CONSTANT, op); + paint_options->application_mode); } } diff -Nru gimp-2.10.8+zorin2/app/paint/gimperaser.c gimp-2.10.14+om/app/paint/gimperaser.c --- gimp-2.10.8+zorin2/app/paint/gimperaser.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimperaser.c 2019-10-26 18:49:18.000000000 +0000 @@ -38,19 +38,22 @@ #include "gimp-intl.h" -static void gimp_eraser_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym, - GimpPaintState paint_state, - guint32 time); -static void gimp_eraser_motion (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym); +static gboolean gimp_eraser_get_color_history_color (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpRGB *color); +static void gimp_eraser_get_paint_params (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + gdouble grad_point, + GimpLayerMode *paint_mode, + GimpPaintApplicationMode *paint_appl_mode, + const GimpTempBuf **paint_pixmap, + GimpRGB *paint_color); -G_DEFINE_TYPE (GimpEraser, gimp_eraser, GIMP_TYPE_BRUSH_CORE) +G_DEFINE_TYPE (GimpEraser, gimp_eraser, GIMP_TYPE_PAINTBRUSH) void @@ -68,12 +71,10 @@ static void gimp_eraser_class_init (GimpEraserClass *klass) { - GimpPaintCoreClass *paint_core_class = GIMP_PAINT_CORE_CLASS (klass); - GimpBrushCoreClass *brush_core_class = GIMP_BRUSH_CORE_CLASS (klass); + GimpPaintbrushClass *paintbrush_class = GIMP_PAINTBRUSH_CLASS (klass); - paint_core_class->paint = gimp_eraser_paint; - - brush_core_class->handles_changing_brush = TRUE; + paintbrush_class->get_color_history_color = gimp_eraser_get_color_history_color; + paintbrush_class->get_paint_params = gimp_eraser_get_paint_params; } static void @@ -81,137 +82,49 @@ { } -static void -gimp_eraser_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym, - GimpPaintState paint_state, - guint32 time) +static gboolean +gimp_eraser_get_color_history_color (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpRGB *color) { - switch (paint_state) + /* Erasing on a drawable without alpha is equivalent to + * drawing with background color. So let's save history. + */ + if (! gimp_drawable_has_alpha (drawable)) { - case GIMP_PAINT_STATE_INIT: - { - if (! gimp_drawable_has_alpha (drawable)) - { - /* Erasing on a drawable without alpha is equivalent to - * drawing with background color. So let's save history. - */ - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpRGB background; - - gimp_context_get_background (context, &background); - gimp_palettes_add_color_history (context->gimp, - &background); - - } - } - break; - case GIMP_PAINT_STATE_MOTION: - gimp_eraser_motion (paint_core, drawable, paint_options, sym); - break; + GimpContext *context = GIMP_CONTEXT (paint_options); + + gimp_context_get_background (context, color); - default: - break; + return TRUE; } + + return FALSE; } static void -gimp_eraser_motion (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym) +gimp_eraser_get_paint_params (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + gdouble grad_point, + GimpLayerMode *paint_mode, + GimpPaintApplicationMode *paint_appl_mode, + const GimpTempBuf **paint_pixmap, + GimpRGB *paint_color) { - GimpEraserOptions *options = GIMP_ERASER_OPTIONS (paint_options); - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); - gdouble fade_point; - gdouble opacity; - GimpLayerMode paint_mode; - GeglBuffer *paint_buffer; - gint paint_buffer_x; - gint paint_buffer_y; - GimpRGB background; - GeglColor *color; - gdouble force; - const GimpCoords *coords; - GeglNode *op; - gint n_strokes; - gint paint_width, paint_height; - gint i; - - fade_point = gimp_paint_options_get_fade (paint_options, image, - paint_core->pixel_dist); - - coords = gimp_symmetry_get_origin (sym); - opacity = gimp_dynamics_get_linear_value (dynamics, - GIMP_DYNAMICS_OUTPUT_OPACITY, - coords, - paint_options, - fade_point); - if (opacity == 0.0) - return; + GimpEraserOptions *options = GIMP_ERASER_OPTIONS (paint_options); + GimpContext *context = GIMP_CONTEXT (paint_options); - gimp_context_get_background (context, &background); + gimp_context_get_background (context, paint_color); gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable), - &background, &background); - color = gimp_gegl_color_new (&background); + paint_color, paint_color); if (options->anti_erase) - paint_mode = GIMP_LAYER_MODE_ANTI_ERASE; + *paint_mode = GIMP_LAYER_MODE_ANTI_ERASE; else if (gimp_drawable_has_alpha (drawable)) - paint_mode = GIMP_LAYER_MODE_ERASE; + *paint_mode = GIMP_LAYER_MODE_ERASE; else - paint_mode = GIMP_LAYER_MODE_NORMAL_LEGACY; - - gimp_brush_core_eval_transform_dynamics (GIMP_BRUSH_CORE (paint_core), - drawable, - paint_options, - coords); - - n_strokes = gimp_symmetry_get_size (sym); - for (i = 0; i < n_strokes; i++) - { - coords = gimp_symmetry_get_coords (sym, i); - - if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE)) - force = gimp_dynamics_get_linear_value (dynamics, - GIMP_DYNAMICS_OUTPUT_FORCE, - coords, - paint_options, - fade_point); - else - force = paint_options->brush_force; - - - paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable, - paint_options, - paint_mode, - coords, - &paint_buffer_x, - &paint_buffer_y, - &paint_width, - &paint_height); - if (! paint_buffer) - continue; - - op = gimp_symmetry_get_operation (sym, i, - paint_width, - paint_height); - - gegl_buffer_set_color (paint_buffer, NULL, color); - - gimp_brush_core_paste_canvas (GIMP_BRUSH_CORE (paint_core), drawable, - coords, - MIN (opacity, GIMP_OPACITY_OPAQUE), - gimp_context_get_opacity (context), - paint_mode, - gimp_paint_options_get_brush_mode (paint_options), - force, - paint_options->application_mode, op); - } - - g_object_unref (color); + *paint_mode = GIMP_LAYER_MODE_NORMAL_LEGACY; } diff -Nru gimp-2.10.8+zorin2/app/paint/gimperaser.h gimp-2.10.14+om/app/paint/gimperaser.h --- gimp-2.10.8+zorin2/app/paint/gimperaser.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimperaser.h 2019-06-12 16:43:38.000000000 +0000 @@ -19,7 +19,7 @@ #define __GIMP_ERASER_H__ -#include "gimpbrushcore.h" +#include "gimppaintbrush.h" #define GIMP_TYPE_ERASER (gimp_eraser_get_type ()) @@ -34,12 +34,12 @@ struct _GimpEraser { - GimpBrushCore parent_instance; + GimpPaintbrush parent_instance; }; struct _GimpEraserClass { - GimpBrushCoreClass parent_class; + GimpPaintbrushClass parent_class; }; diff -Nru gimp-2.10.8+zorin2/app/paint/gimpheal.c gimp-2.10.14+om/app/paint/gimpheal.c --- gimp-2.10.8+zorin2/app/paint/gimpheal.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpheal.c 2019-06-12 16:43:38.000000000 +0000 @@ -25,7 +25,6 @@ #include #include -#define GEGL_ITERATOR2_API #include #include "libgimpbase/gimpbase.h" @@ -33,6 +32,7 @@ #include "paint-types.h" +#include "gegl/gimp-gegl-apply-operation.h" #include "gegl/gimp-gegl-loops.h" #include "core/gimpbrush.h" @@ -512,17 +512,21 @@ gint paint_area_width, gint paint_area_height) { - GimpPaintCore *paint_core = GIMP_PAINT_CORE (source_core); - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; - GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpPaintCore *paint_core = GIMP_PAINT_CORE (source_core); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpSourceOptions *src_options = GIMP_SOURCE_OPTIONS (paint_options); + GimpDynamics *dynamics = GIMP_BRUSH_CORE (paint_core)->dynamics; + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); GeglBuffer *src_copy; GeglBuffer *mask_buffer; + GimpPickable *dest_pickable; const GimpTempBuf *mask_buf; gdouble fade_point; gdouble force; gint mask_off_x; gint mask_off_y; + gint dest_pickable_off_x; + gint dest_pickable_off_y; fade_point = gimp_paint_options_get_fade (paint_options, image, paint_core->pixel_dist); @@ -537,7 +541,7 @@ force = paint_options->brush_force; mask_buf = gimp_brush_core_get_brush_mask (GIMP_BRUSH_CORE (source_core), - coords, op, + coords, GIMP_BRUSH_HARD, force); @@ -556,19 +560,43 @@ } /* heal should work in perceptual space, use R'G'B' instead of RGB */ - src_copy = gegl_buffer_new (GEGL_RECTANGLE (0, 0, + src_copy = gegl_buffer_new (GEGL_RECTANGLE (paint_area_offset_x, + paint_area_offset_y, src_rect->width, src_rect->height), babl_format ("R'G'B'A float")); - gimp_gegl_buffer_copy (src_buffer, src_rect, GEGL_ABYSS_NONE, - src_copy, - GEGL_RECTANGLE (0, 0, - src_rect->width, - src_rect->height)); + if (! op) + { + gimp_gegl_buffer_copy (src_buffer, src_rect, GEGL_ABYSS_NONE, + src_copy, gegl_buffer_get_extent (src_copy)); + } + else + { + gimp_gegl_apply_operation (src_buffer, NULL, NULL, op, + src_copy, gegl_buffer_get_extent (src_copy), + FALSE); + } + + if (src_options->sample_merged) + { + dest_pickable = GIMP_PICKABLE (image); - gimp_gegl_buffer_copy (gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (paint_buffer_x, paint_buffer_y, + gimp_item_get_offset (GIMP_ITEM (drawable), + &dest_pickable_off_x, + &dest_pickable_off_y); + } + else + { + dest_pickable = GIMP_PICKABLE (drawable); + + dest_pickable_off_x = 0; + dest_pickable_off_y = 0; + } + + gimp_gegl_buffer_copy (gimp_pickable_get_buffer (dest_pickable), + GEGL_RECTANGLE (paint_buffer_x + dest_pickable_off_x, + paint_buffer_y + dest_pickable_off_y, gegl_buffer_get_width (paint_buffer), gegl_buffer_get_height (paint_buffer)), GEGL_ABYSS_NONE, @@ -589,31 +617,7 @@ mask_off_y = (y < 0) ? -y : 0; } - if (op) - { - GeglNode *graph, *source, *target; - - graph = gegl_node_new (); - source = gegl_node_new_child (graph, - "operation", "gegl:buffer-source", - "buffer", src_copy, - NULL); - gegl_node_add_child (graph, op); - target = gegl_node_new_child (graph, - "operation", "gegl:write-buffer", - "buffer", src_copy, - NULL); - - gegl_node_link_many (source, op, target, NULL); - gegl_node_process (target); - - g_object_unref (graph); - } - - gimp_heal (src_copy, - GEGL_RECTANGLE (0, 0, - gegl_buffer_get_width (src_copy), - gegl_buffer_get_height (src_copy)), + gimp_heal (src_copy, gegl_buffer_get_extent (src_copy), paint_buffer, GEGL_RECTANGLE (paint_area_offset_x, paint_area_offset_y, @@ -634,5 +638,5 @@ gimp_context_get_opacity (context), gimp_paint_options_get_brush_mode (paint_options), force, - GIMP_PAINT_INCREMENTAL, NULL); + GIMP_PAINT_INCREMENTAL); } diff -Nru gimp-2.10.8+zorin2/app/paint/gimpink.c gimp-2.10.14+om/app/paint/gimpink.c --- gimp-2.10.8+zorin2/app/paint/gimpink.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpink.c 2019-06-12 16:43:38.000000000 +0000 @@ -20,7 +20,6 @@ #include #include -#define GEGL_ITERATOR2_API #include #include "libgimpmath/gimpmath.h" @@ -52,44 +51,45 @@ /* local function prototypes */ -static void gimp_ink_finalize (GObject *object); +static void gimp_ink_finalize (GObject *object); -static void gimp_ink_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym, - GimpPaintState paint_state, - guint32 time); -static GeglBuffer * gimp_ink_get_paint_buffer (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpLayerMode paint_mode, - const GimpCoords *coords, - gint *paint_buffer_x, - gint *paint_buffer_y, - gint *paint_width, - gint *paint_height); -static GimpUndo * gimp_ink_push_undo (GimpPaintCore *core, - GimpImage *image, - const gchar *undo_desc); - -static void gimp_ink_motion (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym, - guint32 time); - -static GimpBlob * ink_pen_ellipse (GimpInkOptions *options, - gdouble x_center, - gdouble y_center, - gdouble pressure, - gdouble xtilt, - gdouble ytilt, - gdouble velocity); - -static void render_blob (GeglBuffer *buffer, - GeglRectangle *rect, - GimpBlob *blob); +static void gimp_ink_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + GimpPaintState paint_state, + guint32 time); +static GeglBuffer * gimp_ink_get_paint_buffer (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpLayerMode paint_mode, + const GimpCoords *coords, + gint *paint_buffer_x, + gint *paint_buffer_y, + gint *paint_width, + gint *paint_height); +static GimpUndo * gimp_ink_push_undo (GimpPaintCore *core, + GimpImage *image, + const gchar *undo_desc); + +static void gimp_ink_motion (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + guint32 time); + +static GimpBlob * ink_pen_ellipse (GimpInkOptions *options, + gdouble x_center, + gdouble y_center, + gdouble pressure, + gdouble xtilt, + gdouble ytilt, + gdouble velocity, + const GimpMatrix3 *transform); + +static void render_blob (GeglBuffer *buffer, + GeglRectangle *rect, + GimpBlob *blob); G_DEFINE_TYPE (GimpInk, gimp_ink, GIMP_TYPE_PAINT_CORE) @@ -259,12 +259,16 @@ /* configure the canvas buffer */ if ((x2 - x1) && (y2 - y1)) { - GimpTempBuf *temp_buf; - const Babl *format; + GimpTempBuf *temp_buf; + const Babl *format; + GimpLayerCompositeMode composite_mode; + + composite_mode = gimp_layer_mode_get_paint_composite_mode (paint_mode); format = gimp_layer_mode_get_format (paint_mode, GIMP_LAYER_COLOR_SPACE_AUTO, GIMP_LAYER_COLOR_SPACE_AUTO, + composite_mode, gimp_drawable_get_format (drawable)); temp_buf = gimp_temp_buf_new ((x2 - x1), (y2 - y1), @@ -340,15 +344,20 @@ for (i = 0; i < n_strokes; i++) { + GimpMatrix3 transform; + coords = gimp_symmetry_get_coords (sym, i); + gimp_symmetry_get_matrix (sym, i, &transform); + last_blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, - 100); + 100, + &transform); ink->last_blobs = g_list_prepend (ink->last_blobs, last_blob); @@ -364,17 +373,22 @@ { for (i = 0; i < n_strokes; i++) { - GimpBlob *blob; - GimpBlob *blob_union = NULL; + GimpBlob *blob; + GimpBlob *blob_union = NULL; + GimpMatrix3 transform; coords = gimp_symmetry_get_coords (sym, i); + + gimp_symmetry_get_matrix (sym, i, &transform); + blob = ink_pen_ellipse (options, coords->x, coords->y, coords->pressure, coords->xtilt, coords->ytilt, - coords->velocity * 100); + coords->velocity * 100, + &transform); last_blob = g_list_nth_data (ink->last_blobs, i); blob_union = gimp_blob_convex_union (last_blob, blob); @@ -443,13 +457,14 @@ } static GimpBlob * -ink_pen_ellipse (GimpInkOptions *options, - gdouble x_center, - gdouble y_center, - gdouble pressure, - gdouble xtilt, - gdouble ytilt, - gdouble velocity) +ink_pen_ellipse (GimpInkOptions *options, + gdouble x_center, + gdouble y_center, + gdouble pressure, + gdouble xtilt, + gdouble ytilt, + gdouble velocity, + const GimpMatrix3 *transform) { GimpBlobFunc blob_function; gdouble size; @@ -525,10 +540,14 @@ } else { - tsin = sin (options->blob_angle); tcos = cos (options->blob_angle); + tsin = sin (options->blob_angle); } + gimp_matrix3_transform_point (transform, + tcos, tsin, + &tcos, &tsin); + aspect = CLAMP (aspect, 1.0, 10.0); radmin = MAX (1.0, SUBSAMPLE * size / aspect); diff -Nru gimp-2.10.8+zorin2/app/paint/gimpmybrushsurface.c gimp-2.10.14+om/app/paint/gimpmybrushsurface.c --- gimp-2.10.8+zorin2/app/paint/gimpmybrushsurface.c 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimpmybrushsurface.c 2019-01-03 14:13:22.000000000 +0000 @@ -16,7 +16,6 @@ */ #include "config.h" -#define GEGL_ITERATOR2_API #include #include diff -Nru gimp-2.10.8+zorin2/app/paint/gimppaintbrush.c gimp-2.10.14+om/app/paint/gimppaintbrush.c --- gimp-2.10.8+zorin2/app/paint/gimppaintbrush.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimppaintbrush.c 2019-10-26 18:49:18.000000000 +0000 @@ -46,12 +46,26 @@ #include "gimp-intl.h" -static void gimp_paintbrush_paint (GimpPaintCore *paint_core, - GimpDrawable *drawable, - GimpPaintOptions *paint_options, - GimpSymmetry *sym, - GimpPaintState paint_state, - guint32 time); +static void gimp_paintbrush_paint (GimpPaintCore *paint_core, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + GimpPaintState paint_state, + guint32 time); + +static gboolean gimp_paintbrush_real_get_color_history_color (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpRGB *color); +static void gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + gdouble grad_point, + GimpLayerMode *paint_mode, + GimpPaintApplicationMode *paint_appl_mode, + const GimpTempBuf **paint_pixmap, + GimpRGB *paint_color); G_DEFINE_TYPE (GimpPaintbrush, gimp_paintbrush, GIMP_TYPE_BRUSH_CORE) @@ -78,6 +92,9 @@ paint_core_class->paint = gimp_paintbrush_paint; brush_core_class->handles_changing_brush = TRUE; + + klass->get_color_history_color = gimp_paintbrush_real_get_color_history_color; + klass->get_paint_params = gimp_paintbrush_real_get_paint_params; } static void @@ -93,24 +110,21 @@ GimpPaintState paint_state, guint32 time) { + GimpPaintbrush *paintbrush = GIMP_PAINTBRUSH (paint_core); + switch (paint_state) { case GIMP_PAINT_STATE_INIT: { - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); - GimpDynamics *dynamics = gimp_context_get_dynamics (context); + GimpRGB color; - if (! gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_COLOR) && - (! brush_core->brush || ! gimp_brush_get_pixmap (brush_core->brush))) + if (GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color && + GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_color_history_color ( + paintbrush, drawable, paint_options, &color)) { - /* We don't save gradient color history and pixmap brushes - * have no color to save. - */ - GimpRGB foreground; + GimpContext *context = GIMP_CONTEXT (paint_options); - gimp_context_get_foreground (context, &foreground); - gimp_palettes_add_color_history (context->gimp, &foreground); + gimp_palettes_add_color_history (context->gimp, &color); } } break; @@ -120,11 +134,95 @@ sym, GIMP_OPACITY_OPAQUE); break; - default: + case GIMP_PAINT_STATE_FINISH: + { + if (paintbrush->paint_buffer) + { + g_object_remove_weak_pointer ( + G_OBJECT (paintbrush->paint_buffer), + (gpointer) &paintbrush->paint_buffer); + + paintbrush->paint_buffer = NULL; + } + + g_clear_pointer (&paintbrush->paint_pixmap, gimp_temp_buf_unref); + } break; } } +static gboolean +gimp_paintbrush_real_get_color_history_color (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpRGB *color) +{ + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paintbrush); + GimpDynamics *dynamics = gimp_context_get_dynamics (context); + + /* We don't save gradient color history and pixmap brushes + * have no color to save. + */ + if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_COLOR) || + (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))) + { + return FALSE; + } + + gimp_context_get_foreground (context, color); + + return TRUE; +} + +static void +gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + gdouble grad_point, + GimpLayerMode *paint_mode, + GimpPaintApplicationMode *paint_appl_mode, + const GimpTempBuf **paint_pixmap, + GimpRGB *paint_color) +{ + GimpPaintCore *paint_core = GIMP_PAINT_CORE (paintbrush); + GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paintbrush); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + + *paint_mode = gimp_context_get_paint_mode (context); + + if (gimp_paint_options_get_gradient_color (paint_options, image, + grad_point, + paint_core->pixel_dist, + paint_color)) + { + /* optionally take the color from the current gradient */ + gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable), + paint_color, paint_color); + + *paint_appl_mode = GIMP_PAINT_INCREMENTAL; + } + else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush)) + { + /* otherwise check if the brush has a pixmap and use that to + * color the area + */ + *paint_pixmap = gimp_brush_core_get_brush_pixmap (brush_core); + + *paint_appl_mode = GIMP_PAINT_INCREMENTAL; + } + else + { + /* otherwise fill the area with the foreground color */ + gimp_context_get_foreground (context, paint_color); + + gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable), + paint_color, paint_color); + } +} + void _gimp_paintbrush_motion (GimpPaintCore *paint_core, GimpDrawable *drawable, @@ -132,25 +230,17 @@ GimpSymmetry *sym, gdouble opacity) { - GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); - GimpContext *context = GIMP_CONTEXT (paint_options); - GimpDynamics *dynamics = brush_core->dynamics; - GimpImage *image; - GimpLayerMode paint_mode; - GimpRGB gradient_color; - GeglBuffer *paint_buffer; - gint paint_buffer_x; - gint paint_buffer_y; - GimpPaintApplicationMode paint_appl_mode; - gdouble fade_point; - gdouble grad_point; - gdouble force; - const GimpCoords *coords; - GeglNode *op; - gint n_strokes; - gint i; - - image = gimp_item_get_image (GIMP_ITEM (drawable)); + GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paint_core); + GimpPaintbrush *paintbrush = GIMP_PAINTBRUSH (paint_core); + GimpContext *context = GIMP_CONTEXT (paint_options); + GimpDynamics *dynamics = brush_core->dynamics; + GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); + gdouble fade_point; + gdouble grad_point; + gdouble force; + const GimpCoords *coords; + gint n_strokes; + gint i; fade_point = gimp_paint_options_get_fade (paint_options, image, paint_core->pixel_dist); @@ -165,15 +255,6 @@ if (opacity == 0.0) return; - paint_appl_mode = paint_options->application_mode; - - grad_point = gimp_dynamics_get_linear_value (dynamics, - GIMP_DYNAMICS_OUTPUT_COLOR, - coords, - paint_options, - fade_point); - - if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush) { gimp_brush_core_eval_transform_dynamics (brush_core, @@ -182,15 +263,41 @@ coords); } - paint_mode = gimp_context_get_paint_mode (context); + grad_point = gimp_dynamics_get_linear_value (dynamics, + GIMP_DYNAMICS_OUTPUT_COLOR, + coords, + paint_options, + fade_point); n_strokes = gimp_symmetry_get_size (sym); for (i = 0; i < n_strokes; i++) { - gint paint_width, paint_height; + GimpLayerMode paint_mode; + GimpPaintApplicationMode paint_appl_mode; + GeglBuffer *paint_buffer; + gint paint_buffer_x; + gint paint_buffer_y; + const GimpTempBuf *paint_pixmap = NULL; + GimpRGB paint_color; + gint paint_width, paint_height; + + paint_appl_mode = paint_options->application_mode; + + GIMP_PAINTBRUSH_GET_CLASS (paintbrush)->get_paint_params (paintbrush, + drawable, + paint_options, + sym, + grad_point, + &paint_mode, + &paint_appl_mode, + &paint_pixmap, + &paint_color); coords = gimp_symmetry_get_coords (sym, i); + if (GIMP_BRUSH_CORE_GET_CLASS (brush_core)->handles_transforming_brush) + gimp_brush_core_eval_transform_symmetry (brush_core, sym, i); + paint_buffer = gimp_paint_core_get_paint_buffer (paint_core, drawable, paint_options, paint_mode, @@ -202,56 +309,68 @@ if (! paint_buffer) continue; - op = gimp_symmetry_get_operation (sym, i, - paint_width, - paint_height); - if (gimp_paint_options_get_gradient_color (paint_options, image, - grad_point, - paint_core->pixel_dist, - &gradient_color)) + if (! paint_pixmap) { - /* optionally take the color from the current gradient */ - - GeglColor *color; - - opacity *= gradient_color.a; - gimp_rgb_set_alpha (&gradient_color, GIMP_OPACITY_OPAQUE); - - color = gimp_gegl_color_new (&gradient_color); - - gegl_buffer_set_color (paint_buffer, NULL, color); - g_object_unref (color); - - paint_appl_mode = GIMP_PAINT_INCREMENTAL; + opacity *= paint_color.a; + gimp_rgb_set_alpha (&paint_color, GIMP_OPACITY_OPAQUE); } - else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush)) - { - /* otherwise check if the brush has a pixmap and use that to - * color the area - */ - gimp_brush_core_color_area_with_pixmap (brush_core, drawable, - coords, op, - paint_buffer, - paint_buffer_x, - paint_buffer_y, - gimp_paint_options_get_brush_mode (paint_options)); - paint_appl_mode = GIMP_PAINT_INCREMENTAL; - } - else + /* fill the paint buffer. we can skip this step when reusing the + * previous paint buffer, if the paint color/pixmap hasn't changed + * (unless using an applicator, which currently modifies the paint buffer + * in-place). + */ + if (paint_core->applicator || + paint_buffer != paintbrush->paint_buffer || + paint_pixmap != paintbrush->paint_pixmap || + (! paint_pixmap && (gimp_rgba_distance (&paint_color, + &paintbrush->paint_color)))) { - /* otherwise fill the area with the foreground color */ + if (paint_buffer != paintbrush->paint_buffer) + { + if (paintbrush->paint_buffer) + { + g_object_remove_weak_pointer ( + G_OBJECT (paintbrush->paint_buffer), + (gpointer) &paintbrush->paint_buffer); + } + + paintbrush->paint_buffer = paint_buffer; + + g_object_add_weak_pointer ( + G_OBJECT (paintbrush->paint_buffer), + (gpointer) &paintbrush->paint_buffer); + } + + if (paint_pixmap != paintbrush->paint_pixmap) + { + g_clear_pointer (&paintbrush->paint_pixmap, gimp_temp_buf_unref); + + if (paint_pixmap) + paintbrush->paint_pixmap = gimp_temp_buf_ref (paint_pixmap); + } + + paintbrush->paint_color = paint_color; + + if (paint_pixmap) + { + gimp_brush_core_color_area_with_pixmap (brush_core, drawable, + coords, + paint_buffer, + paint_buffer_x, + paint_buffer_y, + FALSE); + } + else + { + GeglColor *color; - GimpRGB foreground; - GeglColor *color; + color = gimp_gegl_color_new (&paint_color); - gimp_context_get_foreground (context, &foreground); - gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable), - &foreground, &foreground); - color = gimp_gegl_color_new (&foreground); + gegl_buffer_set_color (paint_buffer, NULL, color); - gegl_buffer_set_color (paint_buffer, NULL, color); - g_object_unref (color); + g_object_unref (color); + } } if (gimp_dynamics_is_output_enabled (dynamics, GIMP_DYNAMICS_OUTPUT_FORCE)) @@ -271,6 +390,6 @@ paint_mode, gimp_paint_options_get_brush_mode (paint_options), force, - paint_appl_mode, op); + paint_appl_mode); } } diff -Nru gimp-2.10.8+zorin2/app/paint/gimppaintbrush.h gimp-2.10.14+om/app/paint/gimppaintbrush.h --- gimp-2.10.8+zorin2/app/paint/gimppaintbrush.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimppaintbrush.h 2019-10-26 18:49:18.000000000 +0000 @@ -34,12 +34,31 @@ struct _GimpPaintbrush { - GimpBrushCore parent_instance; + GimpBrushCore parent_instance; + + GeglBuffer *paint_buffer; + const GimpTempBuf *paint_pixmap; + GimpRGB paint_color; }; struct _GimpPaintbrushClass { GimpBrushCoreClass parent_class; + + /* virtual functions */ + gboolean (* get_color_history_color) (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpRGB *color); + void (* get_paint_params) (GimpPaintbrush *paintbrush, + GimpDrawable *drawable, + GimpPaintOptions *paint_options, + GimpSymmetry *sym, + gdouble grad_point, + GimpLayerMode *paint_mode, + GimpPaintApplicationMode *paint_appl_mode, + const GimpTempBuf **paint_pixmap, + GimpRGB *paint_color); }; diff -Nru gimp-2.10.8+zorin2/app/paint/gimppaintcore.c gimp-2.10.14+om/app/paint/gimppaintcore.c --- gimp-2.10.8+zorin2/app/paint/gimppaintcore.c 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimppaintcore.c 2019-10-26 18:49:18.000000000 +0000 @@ -391,16 +391,22 @@ if (core->undo_buffer) g_object_unref (core->undo_buffer); - core->undo_buffer = gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); + core->undo_buffer = gimp_gegl_buffer_dup (gimp_drawable_get_buffer (drawable)); + + /* Set the image pickable */ + if (! core->show_all) + core->image_pickable = GIMP_PICKABLE (image); + else + core->image_pickable = GIMP_PICKABLE (gimp_image_get_projection (image)); /* Allocate the saved proj structure */ g_clear_object (&core->saved_proj_buffer); if (core->use_saved_proj) { - GeglBuffer *buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image)); + GeglBuffer *buffer = gimp_pickable_get_buffer (core->image_pickable); - core->saved_proj_buffer = gegl_buffer_dup (buffer); + core->saved_proj_buffer = gimp_gegl_buffer_dup (buffer); } /* Allocate the canvas blocks structure */ @@ -444,7 +450,7 @@ if (paint_options->use_applicator) { - core->applicator = gimp_applicator_new (NULL, FALSE, FALSE); + core->applicator = gimp_applicator_new (NULL); if (core->mask_buffer) { @@ -460,27 +466,6 @@ gimp_applicator_set_dest_buffer (core->applicator, gimp_drawable_get_buffer (drawable)); } - else - { - g_clear_object (&core->comp_buffer); - - /* Allocate the scratch buffer if there's a component mask */ - if (gimp_drawable_get_active_mask (drawable) != GIMP_COMPONENT_MASK_ALL) - { - const Babl *format; - - if (gimp_drawable_get_linear (drawable)) - format = babl_format ("RGBA float"); - else - format = babl_format ("R'G'B'A float"); - - core->comp_buffer = - gegl_buffer_new (GEGL_RECTANGLE (0, 0, - gimp_item_get_width (item), - gimp_item_get_height (item)), - format); - } - } /* Freeze the drawable preview so that it isn't constantly updated. */ gimp_viewable_preview_freeze (GIMP_VIEWABLE (drawable)); @@ -508,7 +493,6 @@ } g_clear_object (&core->mask_buffer); - g_clear_object (&core->comp_buffer); image = gimp_item_get_image (GIMP_ITEM (drawable)); @@ -523,38 +507,43 @@ if (push_undo) { - GeglBuffer *buffer; - gint x, y, width, height; + GeglBuffer *buffer; + GeglRectangle rect; gimp_rectangle_intersect (core->x1, core->y1, core->x2 - core->x1, core->y2 - core->y1, 0, 0, gimp_item_get_width (GIMP_ITEM (drawable)), gimp_item_get_height (GIMP_ITEM (drawable)), - &x, &y, &width, &height); + &rect.x, &rect.y, &rect.width, &rect.height); + + gegl_rectangle_align_to_buffer (&rect, &rect, core->undo_buffer, + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_PAINT, core->undo_desc); GIMP_PAINT_CORE_GET_CLASS (core)->push_undo (core, image, NULL); - buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), + buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, rect.width, rect.height), gimp_drawable_get_format (drawable)); gimp_gegl_buffer_copy (core->undo_buffer, - GEGL_RECTANGLE (x, y, width, height), + &rect, GEGL_ABYSS_NONE, buffer, GEGL_RECTANGLE (0, 0, 0, 0)); gimp_drawable_push_undo (drawable, NULL, - buffer, x, y, width, height); + buffer, rect.x, rect.y, rect.width, rect.height); g_object_unref (buffer); gimp_image_undo_group_end (image); } + core->image_pickable = NULL; + g_clear_object (&core->undo_buffer); g_clear_object (&core->saved_proj_buffer); @@ -586,11 +575,18 @@ gimp_item_get_height (GIMP_ITEM (drawable)), &x, &y, &width, &height)) { + GeglRectangle rect; + + gegl_rectangle_align_to_buffer (&rect, + GEGL_RECTANGLE (x, y, width, height), + gimp_drawable_get_buffer (drawable), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + gimp_gegl_buffer_copy (core->undo_buffer, - GEGL_RECTANGLE (x, y, width, height), + &rect, GEGL_ABYSS_NONE, gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (x, y, width, height)); + &rect); } g_clear_object (&core->undo_buffer); @@ -632,6 +628,23 @@ } void +gimp_paint_core_set_show_all (GimpPaintCore *core, + gboolean show_all) +{ + g_return_if_fail (GIMP_IS_PAINT_CORE (core)); + + core->show_all = show_all; +} + +gboolean +gimp_paint_core_get_show_all (GimpPaintCore *core) +{ + g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), FALSE); + + return core->show_all; +} + +void gimp_paint_core_set_current_coords (GimpPaintCore *core, const GimpCoords *coords) { @@ -755,6 +768,15 @@ return paint_buffer; } +GimpPickable * +gimp_paint_core_get_image_pickable (GimpPaintCore *core) +{ + g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL); + g_return_val_if_fail (core->image_pickable != NULL, NULL); + + return core->image_pickable; +} + GeglBuffer * gimp_paint_core_get_orig_image (GimpPaintCore *core) { @@ -784,13 +806,17 @@ GimpLayerMode paint_mode, GimpPaintApplicationMode mode) { - gint width = gegl_buffer_get_width (core->paint_buffer); - gint height = gegl_buffer_get_height (core->paint_buffer); + gint width = gegl_buffer_get_width (core->paint_buffer); + gint height = gegl_buffer_get_height (core->paint_buffer); + GimpComponentMask affect = gimp_drawable_get_active_mask (drawable); + + if (! affect) + return; if (core->applicator) { /* If the mode is CONSTANT: - * combine the canvas buf, the paint mask to the canvas buffer + * combine the canvas buffer and the paint mask to the paint buffer */ if (mode == GIMP_PAINT_CONSTANT) { @@ -799,9 +825,8 @@ */ if (paint_mask != NULL) { - GimpTempBuf *modified_mask = gimp_temp_buf_copy (paint_mask); - GeglBuffer *paint_mask_buffer = - gimp_temp_buf_create_buffer ((GimpTempBuf *) modified_mask); + GeglBuffer *paint_mask_buffer = + gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, @@ -815,7 +840,6 @@ GIMP_IS_AIRBRUSH (core)); g_object_unref (paint_mask_buffer); - gimp_temp_buf_unref (modified_mask); } gimp_gegl_apply_mask (core->canvas_buffer, @@ -830,7 +854,7 @@ core->undo_buffer); } /* Otherwise: - * combine the canvas buf and the paint mask to the canvas buf + * combine the paint mask to the paint buffer directly */ else { @@ -881,10 +905,7 @@ if (! params.paint_buf) return; - if (core->comp_buffer) - params.dest_buffer = core->comp_buffer; - else - params.dest_buffer = gimp_drawable_get_buffer (drawable); + params.dest_buffer = gimp_drawable_get_buffer (drawable); if (mode == GIMP_PAINT_CONSTANT) { @@ -902,11 +923,11 @@ params.stipple = GIMP_IS_AIRBRUSH (core); params.paint_opacity = paint_opacity; - algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_COMBINE_PAINT_MASK_TO_CANVAS_MASK; + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_COMBINE_PAINT_MASK_TO_CANVAS_BUFFER; } /* Write canvas_buffer to paint_buf */ - algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_PAINT_BUF_ALPHA; + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_CANVAS_BUFFER_TO_COMP_MASK; /* undo buf -> paint_buf -> dest_buffer */ params.src_buffer = core->undo_buffer; @@ -921,13 +942,10 @@ params.paint_mask_offset_y = paint_mask_offset_y; params.paint_opacity = paint_opacity; - algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_PAINT_MASK_TO_PAINT_BUFFER; + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_PAINT_MASK_TO_COMP_MASK; /* dest_buffer -> paint_buf -> dest_buffer */ - if (core->comp_buffer) - params.src_buffer = gimp_drawable_get_buffer (drawable); - else - params.src_buffer = params.dest_buffer; + params.src_buffer = params.dest_buffer; } params.mask_buffer = core->mask_buffer; @@ -938,20 +956,14 @@ algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_DO_LAYER_BLEND; - gimp_paint_core_loops_process (¶ms, algorithms); - - if (core->comp_buffer) + if (affect != GIMP_COMPONENT_MASK_ALL) { - mask_components_onto (params.src_buffer, - core->comp_buffer, - gimp_drawable_get_buffer (drawable), - GEGL_RECTANGLE (core->paint_buffer_x, - core->paint_buffer_y, - width, - height), - gimp_drawable_get_active_mask (drawable), - gimp_drawable_get_linear (drawable)); + params.affect = affect; + + algorithms |= GIMP_PAINT_CORE_LOOPS_ALGORITHM_MASK_COMPONENTS; } + + gimp_paint_core_loops_process (¶ms, algorithms); } /* Update the undo extents */ @@ -985,9 +997,8 @@ gdouble image_opacity, GimpPaintApplicationMode mode) { - GeglRectangle mask_rect; - GeglBuffer *paint_mask_buffer; - gint width, height; + gint width, height; + GimpComponentMask affect; if (! gimp_drawable_has_alpha (drawable)) { @@ -1005,73 +1016,151 @@ width = gegl_buffer_get_width (core->paint_buffer); height = gegl_buffer_get_height (core->paint_buffer); - if (mode == GIMP_PAINT_CONSTANT && + affect = gimp_drawable_get_active_mask (drawable); - /* Some tools (ink) paint the mask to paint_core->canvas_buffer - * directly. Don't need to copy it in this case. - */ - paint_mask != NULL) + if (! affect) + return; + + if (core->applicator) { - if (core->applicator) + GeglRectangle mask_rect; + GeglBuffer *mask_buffer; + + /* If the mode is CONSTANT: + * combine the paint mask to the canvas buffer, and use it as the mask + * buffer + */ + if (mode == GIMP_PAINT_CONSTANT) { - paint_mask_buffer = - gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); + /* Some tools (ink) paint the mask to paint_core->canvas_buffer + * directly. Don't need to copy it in this case. + */ + if (paint_mask != NULL) + { + GeglBuffer *paint_mask_buffer = + gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); - /* combine the paint mask and the canvas buffer */ - gimp_gegl_combine_mask_weird (paint_mask_buffer, - GEGL_RECTANGLE (paint_mask_offset_x, - paint_mask_offset_y, - width, height), - core->canvas_buffer, - GEGL_RECTANGLE (core->paint_buffer_x, - core->paint_buffer_y, - width, height), - paint_opacity, - GIMP_IS_AIRBRUSH (core)); + gimp_gegl_combine_mask_weird (paint_mask_buffer, + GEGL_RECTANGLE (paint_mask_offset_x, + paint_mask_offset_y, + width, height), + core->canvas_buffer, + GEGL_RECTANGLE (core->paint_buffer_x, + core->paint_buffer_y, + width, height), + paint_opacity, + GIMP_IS_AIRBRUSH (core)); - g_object_unref (paint_mask_buffer); + g_object_unref (paint_mask_buffer); + } + + mask_buffer = g_object_ref (core->canvas_buffer); + mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, + core->paint_buffer_y, + width, height); + + gimp_applicator_set_src_buffer (core->applicator, + core->undo_buffer); } + /* Otherwise: + * use the paint mask as the mask buffer directly + */ else { - /* Mix paint mask and canvas_buffer */ - combine_paint_mask_to_canvas_mask (paint_mask, - paint_mask_offset_x, - paint_mask_offset_y, - core->canvas_buffer, - core->paint_buffer_x, - core->paint_buffer_y, - paint_opacity, - GIMP_IS_AIRBRUSH (core)); + mask_buffer = + gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); + mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x, + paint_mask_offset_y, + width, height); + + gimp_applicator_set_src_buffer (core->applicator, + gimp_drawable_get_buffer (drawable)); + } + + if (core->mask_buffer) + { + GeglBuffer *combined_mask_buffer; + GeglRectangle combined_mask_rect; + GeglRectangle aligned_combined_mask_rect; + + combined_mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, + core->paint_buffer_y, + width, height); + + gegl_rectangle_align_to_buffer ( + &aligned_combined_mask_rect, &combined_mask_rect, + gimp_drawable_get_buffer (drawable), + GEGL_RECTANGLE_ALIGNMENT_SUPERSET); + + combined_mask_buffer = gegl_buffer_new (&aligned_combined_mask_rect, + babl_format ("Y float")); + + gimp_gegl_buffer_copy ( + core->mask_buffer, + GEGL_RECTANGLE (aligned_combined_mask_rect.x - + core->mask_x_offset, + aligned_combined_mask_rect.y - + core->mask_y_offset, + aligned_combined_mask_rect.width, + aligned_combined_mask_rect.height), + GEGL_ABYSS_NONE, + combined_mask_buffer, + &aligned_combined_mask_rect); + + gimp_gegl_combine_mask (mask_buffer, &mask_rect, + combined_mask_buffer, &combined_mask_rect, + 1.0); + + g_object_unref (mask_buffer); + + mask_buffer = combined_mask_buffer; + mask_rect = combined_mask_rect; } - /* initialize the maskPR from the canvas buffer */ - paint_mask_buffer = g_object_ref (core->canvas_buffer); + gimp_applicator_set_mask_buffer (core->applicator, mask_buffer); + gimp_applicator_set_mask_offset (core->applicator, + core->paint_buffer_x - mask_rect.x, + core->paint_buffer_y - mask_rect.y); + + gimp_applicator_set_apply_buffer (core->applicator, + core->paint_buffer); + gimp_applicator_set_apply_offset (core->applicator, + core->paint_buffer_x, + core->paint_buffer_y); + + gimp_applicator_set_opacity (core->applicator, image_opacity); + gimp_applicator_set_mode (core->applicator, GIMP_LAYER_MODE_REPLACE, + GIMP_LAYER_COLOR_SPACE_AUTO, + GIMP_LAYER_COLOR_SPACE_AUTO, + gimp_layer_mode_get_paint_composite_mode ( + GIMP_LAYER_MODE_REPLACE)); + + /* apply the paint area to the image */ + gimp_applicator_blit (core->applicator, + GEGL_RECTANGLE (core->paint_buffer_x, + core->paint_buffer_y, + width, height)); + + gimp_applicator_set_mask_buffer (core->applicator, core->mask_buffer); + gimp_applicator_set_mask_offset (core->applicator, + core->mask_x_offset, + core->mask_y_offset); - mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, - core->paint_buffer_y, - width, height); + g_object_unref (mask_buffer); } else { - paint_mask_buffer = - gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); - - mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x, - paint_mask_offset_y, - width, height); + gimp_paint_core_paste (core, paint_mask, + paint_mask_offset_x, + paint_mask_offset_y, + drawable, + paint_opacity, + image_opacity, + GIMP_LAYER_MODE_REPLACE, + mode); + return; } - /* apply the paint area to the image */ - gimp_drawable_replace_buffer (drawable, core->paint_buffer, - GEGL_RECTANGLE (0, 0, width, height), - FALSE, NULL, - image_opacity, - paint_mask_buffer, &mask_rect, - core->paint_buffer_x, - core->paint_buffer_y); - - g_object_unref (paint_mask_buffer); - /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); diff -Nru gimp-2.10.8+zorin2/app/paint/gimppaintcore.h gimp-2.10.14+om/app/paint/gimppaintcore.h --- gimp-2.10.8+zorin2/app/paint/gimppaintcore.h 2018-08-19 16:47:18.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimppaintcore.h 2019-10-26 18:49:18.000000000 +0000 @@ -34,42 +34,45 @@ struct _GimpPaintCore { - GimpObject parent_instance; + GimpObject parent_instance; - gint ID; /* unique instance ID */ + gint ID; /* unique instance ID */ - gchar *undo_desc; /* undo description */ + gchar *undo_desc; /* undo description */ - GimpCoords start_coords; /* the last stroke's endpoint for undo */ + gboolean show_all; /* whether working in show-all mode */ - GimpCoords cur_coords; /* current coords */ - GimpCoords last_coords; /* last coords */ + GimpCoords start_coords; /* the last stroke's endpoint for undo */ - GimpVector2 last_paint; /* last point that was painted */ + GimpCoords cur_coords; /* current coords */ + GimpCoords last_coords; /* last coords */ - gdouble distance; /* distance traveled by brush */ - gdouble pixel_dist; /* distance in pixels */ + GimpVector2 last_paint; /* last point that was painted */ - gint x1, y1; /* undo extents in image coords */ - gint x2, y2; /* undo extents in image coords */ + gdouble distance; /* distance traveled by brush */ + gdouble pixel_dist; /* distance in pixels */ - gboolean use_saved_proj; /* keep the unmodified proj around */ + gint x1, y1; /* undo extents in image coords */ + gint x2, y2; /* undo extents in image coords */ - GeglBuffer *undo_buffer; /* pixels which have been modified */ - GeglBuffer *saved_proj_buffer; /* proj tiles which have been modified */ - GeglBuffer *canvas_buffer; /* the buffer to paint the mask to */ - GeglBuffer *comp_buffer; /* scratch buffer used when masking components */ - GeglBuffer *paint_buffer; /* the buffer to paint pixels to */ - gint paint_buffer_x; - gint paint_buffer_y; + gboolean use_saved_proj; /* keep the unmodified proj around */ - GeglBuffer *mask_buffer; /* the target drawable's mask */ - gint mask_x_offset; - gint mask_y_offset; + GimpPickable *image_pickable; /* the image pickable */ + + GeglBuffer *undo_buffer; /* pixels which have been modified */ + GeglBuffer *saved_proj_buffer; /* proj tiles which have been modified */ + GeglBuffer *canvas_buffer; /* the buffer to paint the mask to */ + GeglBuffer *paint_buffer; /* the buffer to paint pixels to */ + gint paint_buffer_x; + gint paint_buffer_y; + + GeglBuffer *mask_buffer; /* the target drawable's mask */ + gint mask_x_offset; + gint mask_y_offset; GimpApplicator *applicator; - GArray *stroke_buffer; + GArray *stroke_buffer; }; struct _GimpPaintCoreClass @@ -147,6 +150,10 @@ const GimpCoords *coords, guint32 time); +void gimp_paint_core_set_show_all (GimpPaintCore *core, + gboolean show_all); +gboolean gimp_paint_core_get_show_all (GimpPaintCore *core); + void gimp_paint_core_set_current_coords (GimpPaintCore *core, const GimpCoords *coords); void gimp_paint_core_get_current_coords (GimpPaintCore *core, @@ -177,6 +184,8 @@ gint *paint_width, gint *paint_height); +GimpPickable * gimp_paint_core_get_image_pickable (GimpPaintCore *core); + GeglBuffer * gimp_paint_core_get_orig_image (GimpPaintCore *core); GeglBuffer * gimp_paint_core_get_orig_proj (GimpPaintCore *core); diff -Nru gimp-2.10.8+zorin2/app/paint/gimppaintcore-loops.cc gimp-2.10.14+om/app/paint/gimppaintcore-loops.cc --- gimp-2.10.8+zorin2/app/paint/gimppaintcore-loops.cc 2018-11-08 13:58:41.000000000 +0000 +++ gimp-2.10.14+om/app/paint/gimppaintcore-loops.cc 2019-06-12 16:43:38.000000000 +0000 @@ -16,7 +16,6 @@ */ #include "config.h" -#define GEGL_ITERATOR2_API #include #include @@ -27,9 +26,10 @@ #include "operations/layer-modes/gimp-layer-modes.h" -#include "core/gimp-parallel.h" #include "core/gimptempbuf.h" +#include "operations/gimpoperationmaskcomponents.h" + #include "operations/layer-modes/gimpoperationlayermode.h" #include "gimppaintcore-loops.h" @@ -37,8 +37,8 @@ } /* extern "C" */ -#define MIN_PARALLEL_SUB_SIZE 64 -#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE) +#define PIXELS_PER_THREAD \ + (/* each thread costs as much as */ 64.0 * 64.0 /* pixels */) /* In order to avoid iterating over the same region of the same buffers @@ -97,9 +97,15 @@ enum { - ALGORITHM_PAINT_BUF = 1u << 31, - ALGORITHM_PAINT_MASK = 1u << 30, - ALGORITHM_STIPPLE = 1u << 29 + ALGORITHM_PAINT_BUF = 1u << 31, + ALGORITHM_PAINT_MASK = 1u << 30, + ALGORITHM_STIPPLE = 1u << 29, + ALGORITHM_COMP_MASK = 1u << 28, + ALGORITHM_TEMP_COMP_MASK = 1u << 27, + ALGORITHM_COMP_BUFFER = 1u << 26, + ALGORITHM_TEMP_COMP_BUFFER = 1u << 25, + ALGORITHM_CANVAS_BUFFER_ITERATOR = 1u << 24, + ALGORITHM_MASK_BUFFER_ITERATOR = 1u << 23 }; @@ -232,18 +238,13 @@ * Algorithms that redefine 'filter' should bitwise-OR their filter with that * of their base class. */ - static constexpr guint filter = 0; + static constexpr guint filter = 0; - /* See CanvasBufferIterator. */ - static constexpr gint canvas_buffer_iterator = -1; - static constexpr GeglAccessMode canvas_buffer_access = {}; - - /* The current number of iterators used by the hierarchy. Algorithms should - * use the 'n_iterators' value of their base class as the base-index for - * their iterators, and redefine 'n_iterators' by adding the number of + /* The current maximal number of iterators used by the hierarchy. Algorithms + * should redefine 'max_n_iterators' by adding the maximal number of * iterators they use to this value. */ - static constexpr gint n_iterators = 0; + static constexpr gint max_n_iterators = 0; /* Non-static data members should be initialized in the constructor, and * should not be further modified. @@ -334,6 +335,41 @@ gint y) const { } + + /* The 'finalize_step()' function is called once per chunk after its + * processing is done, and should finalize any chunk-specific resources of + * the state object. + * + * 'params' is the same parameter struct passed to the constructor. 'state' + * is the state object. + * + * An algorithm that overrides this function should call the + * 'finalize_step()' function of its base class after performing its own + * finalization, using the same arguments. + */ + template + void + finalize_step (const GimpPaintCoreLoopsParams *params, + State *state) const + { + } + + /* The 'finalize()' function is called once per state object after processing + * is done, and should finalize the state object. + * + * 'params' is the same parameter struct passed to the constructor. 'state' + * is the state object. + * + * An algorithm that overrides this function should call the 'finalize()' + * function of its base class after performing its own finalization, using + * the same arguments. + */ + template + void + finalize (const GimpPaintCoreLoopsParams *params, + State *state) const + { + } }; @@ -342,12 +378,17 @@ * A class template implementing a simple dispatch function object, which adds * an algorithm to the hierarchy unconditionally. 'AlgorithmTemplate' is the * alogithm class template (usually a helper class, rather than an actual - * algorithm), and 'Mask' is the dispatch function mask, as described in - * 'dispatch()'. + * algorithm), 'Mask' is the dispatch function mask, as described in + * 'dispatch()', and 'Dependencies' is a list of (types of) dispatch functions + * the algorithm depends on. + * + * Before adding the algorithm to the hierarchy, the hierarchy is augmented by + * dispatching through the list of dependencies, in order. */ template