/** * 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_image_prop_view_label_set_memsize (GtkWidget *label, GimpObject *object) { gchar *str = g_format_size (gimp_object_get_memsize (object, NULL)); gtk_label_set_text (GTK_LABEL (label), str); g_free (str); }
static gint64 gimp_undo_stack_get_memsize (GimpObject *object, gint64 *gui_size) { GimpUndoStack *stack = GIMP_UNDO_STACK (object); gint64 memsize = 0; memsize += gimp_object_get_memsize (GIMP_OBJECT (stack->undos), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_item_get_memsize (GimpObject *object, gint64 *gui_size) { GimpItem *item = GIMP_ITEM (object); gint64 memsize = 0; memsize += gimp_object_get_memsize (GIMP_OBJECT (item->parasites), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_text_layer_get_memsize (GimpObject *object, gint64 *gui_size) { GimpTextLayer *text_layer = GIMP_TEXT_LAYER (object); gint64 memsize = 0; memsize += gimp_object_get_memsize (GIMP_OBJECT (text_layer->text), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_text_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpTextUndo *undo = GIMP_TEXT_UNDO (object); gint64 memsize = 0; memsize += gimp_g_value_get_memsize (undo->value); memsize += gimp_object_get_memsize (GIMP_OBJECT (undo->text), NULL); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
void debug_mem_profile_cmd_callback (GtkAction *action, gpointer data) { extern gboolean gimp_debug_memsize; Gimp *gimp; return_if_no_gimp (gimp, data); gimp_debug_memsize = TRUE; gimp_object_get_memsize (GIMP_OBJECT (gimp), NULL); gimp_debug_memsize = FALSE; }
static gint64 gimp_channel_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpItemUndo *item_undo = GIMP_ITEM_UNDO (object); gint64 memsize = 0; if (! gimp_item_is_attached (item_undo->item)) memsize += gimp_object_get_memsize (GIMP_OBJECT (item_undo->item), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_vectors_mod_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpVectorsModUndo *vectors_mod_undo = GIMP_VECTORS_MOD_UNDO (object); gint64 memsize = 0; if (vectors_mod_undo->vectors) memsize += gimp_object_get_memsize (GIMP_OBJECT (vectors_mod_undo->vectors), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_layer_mask_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpLayerMaskUndo *layer_mask_undo = GIMP_LAYER_MASK_UNDO (object); GimpLayer *layer = GIMP_LAYER (GIMP_ITEM_UNDO (object)->item); gint64 memsize = 0; /* don't use !gimp_item_is_attached() here */ if (gimp_layer_get_mask (layer) != layer_mask_undo->layer_mask) memsize += gimp_object_get_memsize (GIMP_OBJECT (layer_mask_undo->layer_mask), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_vectors_get_memsize (GimpObject *object, gint64 *gui_size) { GimpVectors *vectors; GList *list; gint64 memsize = 0; vectors = GIMP_VECTORS (object); for (list = vectors->strokes; list; list = g_list_next (list)) memsize += (gimp_object_get_memsize (GIMP_OBJECT (list->data), gui_size) + sizeof (GList)); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_image_undo_get_memsize (GimpObject *object, gint64 *gui_size) { GimpImageUndo *image_undo = GIMP_IMAGE_UNDO (object); gint64 memsize = 0; if (image_undo->colormap) memsize += GIMP_IMAGE_COLORMAP_SIZE; memsize += gimp_object_get_memsize (GIMP_OBJECT (image_undo->grid), gui_size); memsize += gimp_string_get_memsize (image_undo->parasite_name); memsize += gimp_parasite_get_memsize (image_undo->parasite, gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_brush_pipe_get_memsize (GimpObject *object, gint64 *gui_size) { GimpBrushPipe *pipe = GIMP_BRUSH_PIPE (object); gint64 memsize = 0; gint i; memsize += pipe->dimension * (sizeof (gint) /* rank */ + sizeof (gint) /* stride */ + sizeof (PipeSelectModes)); for (i = 0; i < pipe->n_brushes; i++) memsize += gimp_object_get_memsize (GIMP_OBJECT (pipe->brushes[i]), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static gint64 gimp_list_get_memsize (GimpObject *object, gint64 *gui_size) { GimpList *list = GIMP_LIST (object); gint64 memsize = 0; memsize += (gimp_container_num_children (GIMP_CONTAINER (list)) * sizeof (GList)); if (gimp_container_policy (GIMP_CONTAINER (list)) == GIMP_CONTAINER_POLICY_STRONG) { GList *glist; for (glist = list->list; glist; glist = g_list_next (glist)) memsize += gimp_object_get_memsize (GIMP_OBJECT (glist->data), gui_size); } return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
static void gimp_image_prop_view_label_set_undo (GtkWidget *label, GimpUndoStack *stack) { gint steps = gimp_undo_stack_get_depth (stack); if (steps > 0) { GimpObject *object = GIMP_OBJECT (stack); gchar *str; gchar buf[256]; str = g_format_size (gimp_object_get_memsize (object, NULL)); g_snprintf (buf, sizeof (buf), "%d (%s)", steps, str); g_free (str); gtk_label_set_text (GTK_LABEL (label), buf); } else { /* no undo (or redo) steps available */ gtk_label_set_text (GTK_LABEL (label), _("None")); } }
/** * 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; }
static gint64 gimp_get_memsize (GimpObject *object, gint64 *gui_size) { Gimp *gimp = GIMP (object); gint64 memsize = 0; memsize += gimp_g_list_get_memsize (gimp->user_units, 0 /* FIXME */); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->parasites), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->paint_info_list), gui_size); memsize += gimp_g_object_get_memsize (G_OBJECT (gimp->module_db)); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->plug_in_manager), gui_size); memsize += gimp_g_list_get_memsize_foreach (gimp->filter_history, (GimpMemsizeFunc) gimp_object_get_memsize, gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_table), 0); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->item_table), 0); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->displays), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->global_buffer), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->named_buffers), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->fonts), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->brush_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->dynamics_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->mybrush_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->pattern_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->gradient_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->palette_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_preset_factory), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tag_cache), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->pdb), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->tool_info_list), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->standard_tool_info), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->documents), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->templates), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->image_new_last_template), gui_size); memsize += gimp_g_list_get_memsize (gimp->context_list, 0); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->default_context), gui_size); memsize += gimp_object_get_memsize (GIMP_OBJECT (gimp->user_context), gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); }
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); }
static gboolean gimp_view_button_press_event (GtkWidget *widget, GdkEventButton *bevent) { GimpView *view = GIMP_VIEW (widget); #ifdef DEBUG_MEMSIZE if (bevent->type == GDK_BUTTON_PRESS && bevent->button == 2) { gimp_debug_memsize = TRUE; gimp_object_get_memsize (GIMP_OBJECT (view->viewable), NULL); gimp_debug_memsize = FALSE; } #endif /* DEBUG_MEMSIZE */ if (! view->clickable && ! view->show_popup) return FALSE; if (! gtk_widget_get_realized (widget)) return FALSE; if (bevent->type == GDK_BUTTON_PRESS) { if (gdk_event_triggers_context_menu ((GdkEvent *) bevent)) { view->press_state = 0; g_signal_emit (widget, view_signals[CONTEXT], 0); } else if (bevent->button == 1) { gtk_grab_add (widget); view->has_grab = TRUE; view->press_state = bevent->state; if (view->show_popup && view->viewable) { gimp_view_popup_show (widget, bevent, view->renderer->context, view->viewable, view->renderer->width, view->renderer->height, view->renderer->dot_for_dot); } } else { view->press_state = 0; if (bevent->button == 2) gimp_view_popup_show (widget, bevent, view->renderer->context, view->viewable, view->renderer->width, view->renderer->height, view->renderer->dot_for_dot); return FALSE; } } else if (bevent->type == GDK_2BUTTON_PRESS) { if (bevent->button == 1) g_signal_emit (widget, view_signals[DOUBLE_CLICKED], 0); } return view->eat_button_events ? TRUE : FALSE; }
static void gimp_display_shell_format_title (GimpDisplayShell *shell, gchar *title, gint title_len, const gchar *format) { Gimp *gimp; GimpImage *image; gint num, denom; gint i = 0; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); image = shell->display->image; gimp = image->gimp; gimp_zoom_model_get_fraction (shell->zoom, &num, &denom); while (i < title_len && *format) { switch (*format) { case '%': format++; switch (*format) { case 0: /* format string ends within %-sequence, print literal '%' */ case '%': title[i++] = '%'; break; case 'f': /* pruned filename */ { const gchar *uri = gimp_image_get_uri (image); gchar *basename; basename = file_utils_uri_display_basename (uri); i += print (title, title_len, i, "%s", basename); g_free (basename); } break; case 'F': /* full filename */ { gchar *filename; const gchar *uri = gimp_image_get_uri (image); filename = file_utils_uri_display_name (uri); i += print (title, title_len, i, "%s", filename); g_free (filename); } break; case 'p': /* PDB id */ i += print (title, title_len, i, "%d", gimp_image_get_ID (image)); break; case 'i': /* instance */ i += print (title, title_len, i, "%d", shell->display->instance); break; case 't': /* type */ { const gchar *image_type_str = NULL; gboolean empty = gimp_image_is_empty (image); switch (gimp_image_base_type (image)) { case GIMP_RGB: image_type_str = empty ? _("RGB-empty") : _("RGB"); break; case GIMP_GRAY: image_type_str = empty ? _("grayscale-empty") : _("grayscale"); break; case GIMP_INDEXED: image_type_str = empty ? _("indexed-empty") : _("indexed"); break; default: g_assert_not_reached (); break; } i += print (title, title_len, i, "%s", image_type_str); } break; case 's': /* user source zoom factor */ i += print (title, title_len, i, "%d", denom); break; case 'd': /* user destination zoom factor */ i += print (title, title_len, i, "%d", num); break; case 'z': /* user zoom factor (percentage) */ { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); i += print (title, title_len, i, scale >= 0.15 ? "%.0f" : "%.2f", 100.0 * scale); } break; case 'D': /* dirty flag */ if (format[1] == 0) { /* format string ends within %D-sequence, print literal '%D' */ i += print (title, title_len, i, "%%D"); break; } if (image->dirty) title[i++] = format[1]; format++; break; case 'C': /* clean flag */ if (format[1] == 0) { /* format string ends within %C-sequence, print literal '%C' */ i += print (title, title_len, i, "%%C"); break; } if (! image->dirty) title[i++] = format[1]; format++; break; case 'B': /* dirty flag (long) */ if (image->dirty) i += print (title, title_len, i, "%s", _("(modified)")); break; case 'A': /* clean flag (long) */ if (! image->dirty) i += print (title, title_len, i, "%s", _("(clean)")); break; case 'm': /* memory used by image */ { GimpObject *object = GIMP_OBJECT (image); gchar *str; str = gimp_memsize_to_string (gimp_object_get_memsize (object, NULL)); i += print (title, title_len, i, "%s", str); g_free (str); } break; case 'l': /* number of layers */ i += print (title, title_len, i, "%d", gimp_container_num_children (image->layers)); break; case 'L': /* number of layers (long) */ { gint num = gimp_container_num_children (image->layers); i += print (title, title_len, i, ngettext ("%d layer", "%d layers", num), num); } break; case 'n': /* active drawable name */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%s", gimp_object_get_name (GIMP_OBJECT (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'P': /* active drawable PDB id */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%d", gimp_item_get_ID (GIMP_ITEM (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'W': /* width in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->width * _gimp_unit_get_factor (gimp, shell->unit) / image->xresolution)); break; } /* else fallthru */ case 'w': /* width in pixels */ i += print (title, title_len, i, "%d", image->width); break; case 'H': /* height in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->height * _gimp_unit_get_factor (gimp, shell->unit) / image->yresolution)); break; } /* else fallthru */ case 'h': /* height in pixels */ i += print (title, title_len, i, "%d", image->height); break; case 'u': /* unit symbol */ i += print (title, title_len, i, "%s", _gimp_unit_get_symbol (gimp, shell->unit)); break; case 'U': /* unit abbreviation */ i += print (title, title_len, i, "%s", _gimp_unit_get_abbreviation (gimp, shell->unit)); break; /* Other cool things to be added: * %r = xresolution * %R = yresolution * %ø = image's fractal dimension * %þ = the answer to everything */ default: /* format string contains unknown %-sequence, print it literally */ i += print (title, title_len, i, "%%%c", *format); break; } break; default: title[i++] = *format; break; } format++; } title[MIN (i, title_len - 1)] = '\0'; }
static gint gimp_display_shell_format_title (GimpDisplayShell *shell, gchar *title, gint title_len, const gchar *format) { GimpImage *image; gint num, denom; gint i = 0; g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0); image = gimp_display_get_image (shell->display); if (! image) { title[0] = '\n'; return 0; } gimp_zoom_model_get_fraction (shell->zoom, &num, &denom); while (i < title_len && *format) { switch (*format) { case '%': format++; switch (*format) { case 0: /* format string ends within %-sequence, print literal '%' */ case '%': title[i++] = '%'; break; case 'f': /* base filename */ i += print (title, title_len, i, "%s", gimp_image_get_display_name (image)); break; case 'F': /* full filename */ i += print (title, title_len, i, "%s", gimp_image_get_display_path (image)); break; case 'p': /* PDB id */ i += print (title, title_len, i, "%d", gimp_image_get_ID (image)); break; case 'i': /* instance */ i += print (title, title_len, i, "%d", gimp_display_get_instance (shell->display)); break; case 't': /* image type */ i += print (title, title_len, i, "%s %s", gimp_display_shell_title_image_type (image), gimp_display_shell_title_image_precision (image)); break; case 'T': /* drawable type */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); const Babl *format = gimp_drawable_get_format (drawable); if (drawable) i += print (title, title_len, i, "%s", gimp_babl_get_description (format)); } break; case 's': /* user source zoom factor */ i += print (title, title_len, i, "%d", denom); break; case 'd': /* user destination zoom factor */ i += print (title, title_len, i, "%d", num); break; case 'z': /* user zoom factor (percentage) */ { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); i += print (title, title_len, i, scale >= 0.15 ? "%.0f" : "%.2f", 100.0 * scale); } break; case 'D': /* dirty flag */ if (format[1] == 0) { /* format string ends within %D-sequence, print literal '%D' */ i += print (title, title_len, i, "%%D"); break; } if (gimp_image_is_dirty (image)) title[i++] = format[1]; format++; break; case 'C': /* clean flag */ if (format[1] == 0) { /* format string ends within %C-sequence, print literal '%C' */ i += print (title, title_len, i, "%%C"); break; } if (! gimp_image_is_dirty (image)) title[i++] = format[1]; format++; break; case 'B': /* dirty flag (long) */ if (gimp_image_is_dirty (image)) i += print (title, title_len, i, "%s", _("(modified)")); break; case 'A': /* clean flag (long) */ if (! gimp_image_is_dirty (image)) i += print (title, title_len, i, "%s", _("(clean)")); break; case 'm': /* memory used by image */ { GimpObject *object = GIMP_OBJECT (image); gchar *str; str = g_format_size (gimp_object_get_memsize (object, NULL)); i += print (title, title_len, i, "%s", str); g_free (str); } break; case 'M': /* image size in megapixels */ i += print (title, title_len, i, "%.1f", (gdouble) gimp_image_get_width (image) * (gdouble) gimp_image_get_height (image) / 1000000.0); break; case 'l': /* number of layers */ i += print (title, title_len, i, "%d", gimp_image_get_n_layers (image)); break; case 'L': /* number of layers (long) */ { gint num = gimp_image_get_n_layers (image); i += print (title, title_len, i, ngettext ("%d layer", "%d layers", num), num); } break; case 'n': /* active drawable name */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) { gchar *desc; desc = gimp_viewable_get_description (GIMP_VIEWABLE (drawable), NULL); i += print (title, title_len, i, "%s", desc); g_free (desc); } else { i += print (title, title_len, i, "%s", _("(none)")); } } break; case 'P': /* active drawable PDB id */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%d", gimp_item_get_ID (GIMP_ITEM (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'W': /* width in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gdouble xres; gdouble yres; gchar unit_format[8]; gimp_image_get_resolution (image, &xres, &yres); g_snprintf (unit_format, sizeof (unit_format), "%%.%df", gimp_unit_get_digits (shell->unit) + 1); i += print (title, title_len, i, unit_format, gimp_pixels_to_units (gimp_image_get_width (image), shell->unit, xres)); break; } /* else fallthru */ case 'w': /* width in pixels */ i += print (title, title_len, i, "%d", gimp_image_get_width (image)); break; case 'H': /* height in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gdouble xres; gdouble yres; gchar unit_format[8]; gimp_image_get_resolution (image, &xres, &yres); g_snprintf (unit_format, sizeof (unit_format), "%%.%df", gimp_unit_get_digits (shell->unit) + 1); i += print (title, title_len, i, unit_format, gimp_pixels_to_units (gimp_image_get_height (image), shell->unit, yres)); break; } /* else fallthru */ case 'h': /* height in pixels */ i += print (title, title_len, i, "%d", gimp_image_get_height (image)); break; case 'u': /* unit symbol */ i += print (title, title_len, i, "%s", gimp_unit_get_symbol (shell->unit)); break; case 'U': /* unit abbreviation */ i += print (title, title_len, i, "%s", gimp_unit_get_abbreviation (shell->unit)); break; /* Other cool things to be added: * %r = xresolution * %R = yresolution * %ø = image's fractal dimension * %þ = the answer to everything */ default: /* format string contains unknown %-sequence, print it literally */ i += print (title, title_len, i, "%%%c", *format); break; } break; default: title[i++] = *format; break; } format++; } title[MIN (i, title_len - 1)] = '\0'; return i; }