/** * gimp_image_scale_check: * @image: A #GimpImage. * @new_width: The new width. * @new_height: The new height. * @max_memsize: The maximum new memory size. * @new_memsize: The new memory size. * * Inventory the layer list in image and check that it may be * scaled to @new_height and @new_width without problems. * * Return value: #GIMP_IMAGE_SCALE_OK if scaling the image will shrink none * of its layers completely away, and the new image size * is smaller than @max_memsize. * #GIMP_IMAGE_SCALE_TOO_SMALL if scaling would remove some * existing layers. * #GIMP_IMAGE_SCALE_TOO_BIG if the new image size would * exceed the maximum specified in the preferences. **/ GimpImageScaleCheckType gimp_image_scale_check (GimpImage *image, gint new_width, gint new_height, gint64 max_memsize, gint64 *new_memsize) { GList *all_layers; GList *list; gint64 current_size; gint64 undo_size; gint64 redo_size; gint64 new_size; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_IMAGE_SCALE_TOO_SMALL); g_return_val_if_fail (new_memsize != NULL, GIMP_IMAGE_SCALE_TOO_SMALL); current_size = gimp_object_get_memsize (GIMP_OBJECT (image), NULL); new_size = gimp_image_estimate_memsize (image, gimp_image_get_component_type (image), new_width, new_height); undo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_undo_stack (image)), NULL); redo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_redo_stack (image)), NULL); current_size -= undo_size + redo_size; new_size -= undo_size + redo_size; GIMP_LOG (IMAGE_SCALE, "old_size = %"G_GINT64_FORMAT" new_size = %"G_GINT64_FORMAT, current_size, new_size); *new_memsize = new_size; if (new_size > current_size && new_size > max_memsize) return GIMP_IMAGE_SCALE_TOO_BIG; all_layers = gimp_image_get_layer_list (image); for (list = all_layers; list; list = g_list_next (list)) { GimpItem *item = list->data; /* group layers are updated automatically */ if (gimp_viewable_get_children (GIMP_VIEWABLE (item))) continue; if (! gimp_item_check_scaling (item, new_width, new_height)) { g_list_free (all_layers); return GIMP_IMAGE_SCALE_TOO_SMALL; } } g_list_free (all_layers); return GIMP_IMAGE_SCALE_OK; }
static void gimp_rectangle_select_tool_button_release (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonReleaseType release_type, GimpDisplay *display) { GimpRectangleSelectTool *rect_sel_tool; GimpRectangleSelectToolPrivate *priv; GimpImage *image; rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool); image = gimp_display_get_image (tool->display); gimp_tool_control_halt (tool->control); gimp_tool_pop_status (tool, display); gimp_display_shell_set_show_selection (gimp_display_get_shell (display), priv->saved_show_selection); /* * if the user has not moved the mouse, we need to redo the operation * that was undone on button press. */ if (release_type == GIMP_BUTTON_RELEASE_CLICK) { GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image); GimpUndo *redo = gimp_undo_stack_peek (redo_stack); if (redo && priv->redo == redo) { /* prevent this from halting the tool */ gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_redo (image); priv->redo = NULL; gimp_tool_control_pop_preserve (tool->control); } } gimp_rectangle_tool_button_release (tool, coords, time, state, release_type, display); if (release_type == GIMP_BUTTON_RELEASE_CANCEL) { if (priv->redo) { /* prevent this from halting the tool */ gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_redo (image); gimp_tool_control_pop_preserve (tool->control); } priv->use_saved_op = TRUE; /* is this correct? */ } priv->redo = NULL; }
static void gimp_rectangle_select_tool_button_press (GimpTool *tool, const GimpCoords *coords, guint32 time, GdkModifierType state, GimpButtonPressType press_type, GimpDisplay *display) { GimpRectangleTool *rectangle; GimpRectangleSelectTool *rect_sel_tool; GimpDisplayShell *shell; GimpRectangleSelectToolPrivate *priv; GimpRectangleFunction function; rectangle = GIMP_RECTANGLE_TOOL (tool); rect_sel_tool = GIMP_RECTANGLE_SELECT_TOOL (tool); shell = gimp_display_get_shell (display); priv = GIMP_RECTANGLE_SELECT_TOOL_GET_PRIVATE (rect_sel_tool); if (tool->display && display != tool->display) { gimp_rectangle_tool_cancel (GIMP_RECTANGLE_TOOL (tool)); } if (gimp_selection_tool_start_edit (GIMP_SELECTION_TOOL (tool), display, coords)) { /* In some cases we want to finish the rectangle select tool * and hand over responsability to the selection tool */ gimp_rectangle_tool_execute (rectangle); gimp_rectangle_tool_control (tool, GIMP_TOOL_ACTION_HALT, display); gimp_rectangle_select_tool_update_option_defaults (rect_sel_tool, TRUE); return; } gimp_tool_control_activate (tool->control); priv->saved_show_selection = gimp_display_shell_get_show_selection (shell); /* if the shift or ctrl keys are down, we don't want to adjust, we * want to create a new rectangle, regardless of pointer loc */ if (state & (gimp_get_extend_selection_mask () | gimp_get_modify_selection_mask ())) { gimp_rectangle_tool_set_function (rectangle, GIMP_RECTANGLE_TOOL_CREATING); } gimp_rectangle_tool_button_press (tool, coords, time, state, display); priv->press_x = coords->x; priv->press_y = coords->y; /* if we have an existing rectangle in the current display, then * we have already "executed", and need to undo at this point, * unless the user has done something in the meantime */ function = gimp_rectangle_tool_get_function (rectangle); if (function == GIMP_RECTANGLE_TOOL_CREATING) { priv->use_saved_op = FALSE; } else { GimpImage *image = gimp_display_get_image (tool->display); GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image); GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image); GimpUndo *undo; GimpChannelOps operation; undo = gimp_undo_stack_peek (undo_stack); if (undo && priv->undo == undo) { /* prevent this change from halting the tool */ gimp_tool_control_push_preserve (tool->control, TRUE); gimp_image_undo (image); gimp_tool_control_pop_preserve (tool->control); /* we will need to redo if the user cancels or executes */ priv->redo = gimp_undo_stack_peek (redo_stack); } /* if the operation is "Replace", turn off the marching ants, because they are confusing */ operation = gimp_rectangle_select_tool_get_operation (rect_sel_tool); if (operation == GIMP_CHANNEL_OP_REPLACE) gimp_display_shell_set_show_selection (shell, FALSE); } priv->undo = NULL; }
void edit_actions_update (GimpActionGroup *group, gpointer data) { GimpImage *image = action_data_get_image (data); GimpDisplay *display = action_data_get_display (data); 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) { drawable = gimp_image_get_active_drawable (image); if (drawable) { writable = ! gimp_item_is_content_locked (GIMP_ITEM (drawable)); if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) children = TRUE; } undo_enabled = gimp_image_undo_is_enabled (image); if (undo_enabled) { GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image); GimpUndoStack *redo_stack = gimp_image_get_redo_stack (image); GimpUndo *undo = gimp_undo_stack_peek (undo_stack); GimpUndo *redo = gimp_undo_stack_peek (redo_stack); const gchar *tool_undo = NULL; const gchar *tool_redo = NULL; if (display) { tool_undo = tool_manager_get_undo_desc_active (image->gimp, display); tool_redo = tool_manager_get_redo_desc_active (image->gimp, display); } if (tool_undo) undo_name = g_strdup_printf (_("_Undo %s"), tool_undo); else if (undo) undo_name = g_strdup_printf (_("_Undo %s"), gimp_object_get_name (undo)); if (tool_redo) redo_name = g_strdup_printf (_("_Redo %s"), tool_redo); 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)); } } } #define SET_LABEL(action,label) \ gimp_action_group_set_action_label (group, action, (label)) #define SET_SENSITIVE(action,condition) \ gimp_action_group_set_action_sensitive (group, action, (condition) != 0) 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); SET_SENSITIVE ("edit-copy-visible", image); SET_SENSITIVE ("edit-paste", !image || (!drawable || (writable && !children))); SET_SENSITIVE ("edit-paste-as-new-layer", image); SET_SENSITIVE ("edit-paste-into", image && (!drawable || (writable && !children))); SET_SENSITIVE ("edit-named-cut", writable && !children); SET_SENSITIVE ("edit-named-copy", drawable); SET_SENSITIVE ("edit-named-copy-visible", drawable); SET_SENSITIVE ("edit-named-paste", TRUE); SET_SENSITIVE ("edit-clear", writable && !children); SET_SENSITIVE ("edit-fill-fg", writable && !children); SET_SENSITIVE ("edit-fill-bg", writable && !children); SET_SENSITIVE ("edit-fill-pattern", writable && !children); #undef SET_LABEL #undef SET_SENSITIVE }
static void gimp_image_prop_view_update (GimpImagePropView *view) { GimpImage *image = view->image; GimpImageBaseType type; GimpPrecision precision; GimpUnit unit; gdouble unit_factor; gint unit_digits; const gchar *desc; gchar format_buf[32]; gchar buf[256]; gdouble xres; gdouble yres; gimp_image_get_resolution (image, &xres, &yres); /* pixel size */ g_snprintf (buf, sizeof (buf), ngettext ("%d × %d pixel", "%d × %d pixels", gimp_image_get_height (image)), gimp_image_get_width (image), gimp_image_get_height (image)); gtk_label_set_text (GTK_LABEL (view->pixel_size_label), buf); /* print size */ unit = gimp_get_default_unit (); unit_digits = gimp_unit_get_digits (unit); g_snprintf (format_buf, sizeof (format_buf), "%%.%df × %%.%df %s", unit_digits + 1, unit_digits + 1, gimp_unit_get_plural (unit)); g_snprintf (buf, sizeof (buf), format_buf, gimp_pixels_to_units (gimp_image_get_width (image), unit, xres), gimp_pixels_to_units (gimp_image_get_height (image), unit, yres)); gtk_label_set_text (GTK_LABEL (view->print_size_label), buf); /* resolution */ unit = gimp_image_get_unit (image); unit_factor = gimp_unit_get_factor (unit); g_snprintf (format_buf, sizeof (format_buf), _("pixels/%s"), gimp_unit_get_abbreviation (unit)); g_snprintf (buf, sizeof (buf), _("%g × %g %s"), xres / unit_factor, yres / unit_factor, unit == GIMP_UNIT_INCH ? _("ppi") : format_buf); gtk_label_set_text (GTK_LABEL (view->resolution_label), buf); /* color type */ type = gimp_image_get_base_type (image); gimp_enum_get_value (GIMP_TYPE_IMAGE_BASE_TYPE, type, NULL, NULL, &desc, NULL); switch (type) { case GIMP_RGB: case GIMP_GRAY: g_snprintf (buf, sizeof (buf), "%s", desc); break; case GIMP_INDEXED: g_snprintf (buf, sizeof (buf), "%s (%d %s)", desc, gimp_image_get_colormap_size (image), _("colors")); break; } gtk_label_set_text (GTK_LABEL (view->colorspace_label), buf); /* precision */ precision = gimp_image_get_precision (image); gimp_enum_get_value (GIMP_TYPE_PRECISION, precision, NULL, NULL, &desc, NULL); gtk_label_set_text (GTK_LABEL (view->precision_label), desc); /* size in memory */ gimp_image_prop_view_label_set_memsize (view->memsize_label, GIMP_OBJECT (image)); /* undo / redo */ gimp_image_prop_view_label_set_undo (view->undo_label, gimp_image_get_undo_stack (image)); gimp_image_prop_view_label_set_undo (view->redo_label, gimp_image_get_redo_stack (image)); /* number of layers */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_width (image) * gimp_image_get_height (image)); gtk_label_set_text (GTK_LABEL (view->pixels_label), buf); /* number of layers */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_layers (image)); gtk_label_set_text (GTK_LABEL (view->layers_label), buf); /* number of channels */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_channels (image)); gtk_label_set_text (GTK_LABEL (view->channels_label), buf); /* number of vectors */ g_snprintf (buf, sizeof (buf), "%d", gimp_image_get_n_vectors (image)); gtk_label_set_text (GTK_LABEL (view->vectors_label), buf); }
void edit_undo_clear_cmd_callback (GtkAction *action, gpointer data) { GimpImage *image; GimpUndoStack *undo_stack; GimpUndoStack *redo_stack; GtkWidget *widget; GtkWidget *dialog; gchar *size; gint64 memsize; gint64 guisize; return_if_no_image (image, data); return_if_no_widget (widget, data); dialog = gimp_message_dialog_new (_("Clear Undo History"), GIMP_STOCK_WARNING, widget, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, gimp_standard_help_func, GIMP_HELP_EDIT_UNDO_CLEAR, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CLEAR, GTK_RESPONSE_OK, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); g_signal_connect_object (gtk_widget_get_toplevel (widget), "unmap", G_CALLBACK (gtk_widget_destroy), dialog, G_CONNECT_SWAPPED); g_signal_connect_object (image, "disconnect", G_CALLBACK (gtk_widget_destroy), dialog, G_CONNECT_SWAPPED); gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("Really clear image's undo history?")); undo_stack = gimp_image_get_undo_stack (image); redo_stack = gimp_image_get_redo_stack (image); memsize = gimp_object_get_memsize (GIMP_OBJECT (undo_stack), &guisize); memsize += guisize; memsize += gimp_object_get_memsize (GIMP_OBJECT (redo_stack), &guisize); memsize += guisize; size = g_format_size (memsize); gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("Clearing the undo history of this " "image will gain %s of memory."), size); g_free (size); if (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK) { gimp_image_undo_disable (image); gimp_image_undo_enable (image); gimp_image_flush (image); } gtk_widget_destroy (dialog); }
/** * gimp_image_scale_check: * @image: A #GimpImage. * @new_width: The new width. * @new_height: The new height. * @max_memsize: The maximum new memory size. * @new_memsize: The new memory size. * * Inventory the layer list in image and check that it may be * scaled to @new_height and @new_width without problems. * * Return value: #GIMP_IMAGE_SCALE_OK if scaling the image will shrink none * of its layers completely away, and the new image size * is smaller than @max_memsize. * #GIMP_IMAGE_SCALE_TOO_SMALL if scaling would remove some * existing layers. * #GIMP_IMAGE_SCALE_TOO_BIG if the new image size would * exceed the maximum specified in the preferences. **/ GimpImageScaleCheckType gimp_image_scale_check (const GimpImage *image, gint new_width, gint new_height, gint64 max_memsize, gint64 *new_memsize) { GList *drawables; GList *all_layers; GList *list; gint64 current_size; gint64 scalable_size; gint64 scaled_size; gint64 undo_size; gint64 redo_size; gint64 fixed_size; gint64 new_size; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_IMAGE_SCALE_TOO_SMALL); g_return_val_if_fail (new_memsize != NULL, GIMP_IMAGE_SCALE_TOO_SMALL); current_size = gimp_object_get_memsize (GIMP_OBJECT (image), NULL); /* the part of the image's memsize that scales linearly with the image */ drawables = gimp_image_item_list_get_list (image, NULL, GIMP_ITEM_TYPE_LAYERS | GIMP_ITEM_TYPE_CHANNELS, GIMP_ITEM_SET_ALL); gimp_image_item_list_filter (NULL, drawables, TRUE, FALSE); drawables = g_list_prepend (drawables, gimp_image_get_mask (image)); scalable_size = 0; scaled_size = 0; for (list = drawables; list; list = g_list_next (list)) { GimpDrawable *drawable = list->data; gdouble width = gimp_item_get_width (GIMP_ITEM (drawable)); gdouble height = gimp_item_get_height (GIMP_ITEM (drawable)); scalable_size += gimp_drawable_estimate_memsize (drawable, width, height); scaled_size += gimp_drawable_estimate_memsize (drawable, width * new_width / gimp_image_get_width (image), height * new_height / gimp_image_get_height (image)); } g_list_free (drawables); scalable_size += gimp_projection_estimate_memsize (gimp_image_get_base_type (image), gimp_image_get_precision (image), gimp_image_get_width (image), gimp_image_get_height (image)); scaled_size += gimp_projection_estimate_memsize (gimp_image_get_base_type (image), gimp_image_get_precision (image), new_width, new_height); GIMP_LOG (IMAGE_SCALE, "scalable_size = %"G_GINT64_FORMAT" scaled_size = %"G_GINT64_FORMAT, scalable_size, scaled_size); undo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_undo_stack (image)), NULL); redo_size = gimp_object_get_memsize (GIMP_OBJECT (gimp_image_get_redo_stack (image)), NULL); /* the fixed part of the image's memsize w/o any undo information */ fixed_size = current_size - undo_size - redo_size - scalable_size; /* calculate the new size, which is: */ new_size = (fixed_size + /* the fixed part */ scaled_size); /* plus the part that scales... */ GIMP_LOG (IMAGE_SCALE, "old_size = %"G_GINT64_FORMAT" new_size = %"G_GINT64_FORMAT, current_size - undo_size - redo_size, new_size); *new_memsize = new_size; if (new_size > current_size && new_size > max_memsize) return GIMP_IMAGE_SCALE_TOO_BIG; all_layers = gimp_image_get_layer_list (image); for (list = all_layers; list; list = g_list_next (list)) { GimpItem *item = list->data; /* group layers are updated automatically */ if (gimp_viewable_get_children (GIMP_VIEWABLE (item))) continue; if (! gimp_item_check_scaling (item, new_width, new_height)) { g_list_free (all_layers); return GIMP_IMAGE_SCALE_TOO_SMALL; } } g_list_free (all_layers); return GIMP_IMAGE_SCALE_OK; }