diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
commit | 5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch) | |
tree | cbffb45144febf451e54061db2b21395faf94bfe /plug-ins/common/file-svg.c | |
parent | Initial commit. (diff) | |
download | gimp-upstream.tar.xz gimp-upstream.zip |
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | plug-ins/common/file-svg.c | 914 |
1 files changed, 914 insertions, 0 deletions
diff --git a/plug-ins/common/file-svg.c b/plug-ins/common/file-svg.c new file mode 100644 index 0000000..6786bee --- /dev/null +++ b/plug-ins/common/file-svg.c @@ -0,0 +1,914 @@ +/* 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 <https://www.gnu.org/licenses/>. + */ + +/* SVG loader plug-in + * (C) Copyright 2003 Dom Lachowicz <cinamod@hotmail.com> + * + * Largely rewritten in September 2003 by Sven Neumann <sven@gimp.org> + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> + +#include <librsvg/rsvg.h> + +#include "libgimp/gimp.h" +#include "libgimp/gimpui.h" + +#include "libgimp/stdplugins-intl.h" + + +#define LOAD_PROC "file-svg-load" +#define LOAD_THUMB_PROC "file-svg-load-thumb" +#define PLUG_IN_BINARY "file-svg" +#define PLUG_IN_ROLE "gimp-file-svg" +#define SVG_VERSION "2.5.0" +#define SVG_DEFAULT_RESOLUTION 90.0 +#define SVG_DEFAULT_SIZE 500 +#define SVG_PREVIEW_SIZE 128 + + +typedef struct +{ + gdouble resolution; + gint width; + gint height; + gboolean import; + gboolean merge; +} SvgLoadVals; + +static SvgLoadVals load_vals = +{ + SVG_DEFAULT_RESOLUTION, + 0, + 0, + FALSE, + FALSE +}; + + +static void query (void); +static void run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); + +static gint32 load_image (const gchar *filename, + GError **error); +static GdkPixbuf * load_rsvg_pixbuf (const gchar *filename, + SvgLoadVals *vals, + GError **error); +static gboolean load_rsvg_size (const gchar *filename, + SvgLoadVals *vals, + GError **error); +static GimpPDBStatusType load_dialog (const gchar *filename, + GError **error); + + +const GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, + NULL, + query, + run, +}; + +MAIN () + + +static void +query (void) +{ + static const GimpParamDef load_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_STRING, "filename", "The name of the file to load" }, + { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }, + { GIMP_PDB_FLOAT, "resolution", + "Resolution to use for rendering the SVG (defaults to 90 dpi)" }, + { GIMP_PDB_INT32, "width", + "Width (in pixels) to load the SVG in. " + "(0 for original width, a negative width to specify a maximum width)" }, + { GIMP_PDB_INT32, "height", + "Height (in pixels) to load the SVG in. " + "(0 for original height, a negative width to specify a maximum height)"}, + { GIMP_PDB_INT32, "paths", + "Whether to not import paths (0), import paths individually (1) " + "or merge all imported paths (2)" } + }; + static const GimpParamDef load_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Output image" } + }; + + static const GimpParamDef thumb_args[] = + { + { GIMP_PDB_STRING, "filename", "The name of the file to load" }, + { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" } + }; + static const GimpParamDef thumb_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Thumbnail image" }, + { GIMP_PDB_INT32, "image-width", "Width of full-sized image" }, + { GIMP_PDB_INT32, "image-height", "Height of full-sized image" } + }; + + gimp_install_procedure (LOAD_PROC, + "Loads files in the SVG file format", + "Renders SVG files to raster graphics using librsvg.", + "Dom Lachowicz, Sven Neumann", + "Dom Lachowicz <cinamod@hotmail.com>", + SVG_VERSION, + N_("SVG image"), + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (load_args), + G_N_ELEMENTS (load_return_vals), + load_args, load_return_vals); + + gimp_register_file_handler_mime (LOAD_PROC, "image/svg+xml"); + gimp_register_magic_load_handler (LOAD_PROC, + "svg", "", + "0,string,<?xml,0,string,<svg"); + + gimp_install_procedure (LOAD_THUMB_PROC, + "Generates a thumbnail of an SVG image", + "Renders a thumbnail of an SVG file using librsvg.", + "Dom Lachowicz, Sven Neumann", + "Dom Lachowicz <cinamod@hotmail.com>", + SVG_VERSION, + NULL, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (thumb_args), + G_N_ELEMENTS (thumb_return_vals), + thumb_args, thumb_return_vals); + + gimp_register_thumbnail_loader (LOAD_PROC, LOAD_THUMB_PROC); +} + +static void +run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[4]; + GimpRunMode run_mode; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GError *error = NULL; + + INIT_I18N (); + + run_mode = param[0].data.d_int32; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; + + if (strcmp (name, LOAD_PROC) == 0) + { + gimp_get_data (LOAD_PROC, &load_vals); + + switch (run_mode) + { + case GIMP_RUN_NONINTERACTIVE: + if (nparams > 3) load_vals.resolution = param[3].data.d_float; + if (nparams > 4) load_vals.width = param[4].data.d_int32; + if (nparams > 5) load_vals.height = param[5].data.d_int32; + if (nparams > 6) + { + load_vals.import = param[6].data.d_int32 != FALSE; + load_vals.merge = param[6].data.d_int32 > TRUE; + } + break; + + case GIMP_RUN_INTERACTIVE: + status = load_dialog (param[1].data.d_string, &error); + break; + + case GIMP_RUN_WITH_LAST_VALS: + break; + } + + /* Don't clamp this; insane values are probably not meant to be + * used as resolution anyway. + */ + if (load_vals.resolution < GIMP_MIN_RESOLUTION || + load_vals.resolution > GIMP_MAX_RESOLUTION) + { + load_vals.resolution = SVG_DEFAULT_RESOLUTION; + } + + if (status == GIMP_PDB_SUCCESS) + { + const gchar *filename = param[1].data.d_string; + gint32 image_ID = load_image (filename, &error); + + if (image_ID != -1) + { + if (load_vals.import) + { + gint32 *vectors; + gint num_vectors; + + gimp_vectors_import_from_file (image_ID, filename, + load_vals.merge, TRUE, + &num_vectors, &vectors); + if (num_vectors > 0) + g_free (vectors); + } + + *nreturn_vals = 2; + + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + } + else + { + status = GIMP_PDB_EXECUTION_ERROR; + } + + gimp_set_data (LOAD_PROC, &load_vals, sizeof (load_vals)); + } + } + else if (strcmp (name, LOAD_THUMB_PROC) == 0) + { + if (nparams < 2) + { + status = GIMP_PDB_CALLING_ERROR; + } + else + { + const gchar *filename = param[0].data.d_string; + gint width = 0; + gint height = 0; + gint32 image_ID; + + if (load_rsvg_size (filename, &load_vals, NULL)) + { + width = load_vals.width; + height = load_vals.height; + } + + load_vals.resolution = SVG_DEFAULT_RESOLUTION; + load_vals.width = - param[1].data.d_int32; + load_vals.height = - param[1].data.d_int32; + + image_ID = load_image (filename, &error); + + if (image_ID != -1) + { + *nreturn_vals = 4; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + values[2].type = GIMP_PDB_INT32; + values[2].data.d_int32 = width; + values[3].type = GIMP_PDB_INT32; + values[3].data.d_int32 = height; + } + else + { + status = GIMP_PDB_EXECUTION_ERROR; + } + } + } + else + { + status = GIMP_PDB_CALLING_ERROR; + } + + if (status != GIMP_PDB_SUCCESS && error) + { + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = error->message; + } + + values[0].data.d_status = status; +} + +static gint32 +load_image (const gchar *filename, + GError **load_error) +{ + gint32 image; + gint32 layer; + GdkPixbuf *pixbuf; + gint width; + gint height; + GError *error = NULL; + + pixbuf = load_rsvg_pixbuf (filename, &load_vals, &error); + + if (! pixbuf) + { + /* Do not rely on librsvg setting GError on failure! */ + g_set_error (load_error, + error ? error->domain : 0, error ? error->code : 0, + _("Could not open '%s' for reading: %s"), + gimp_filename_to_utf8 (filename), + error ? error->message : _("Unknown reason")); + g_clear_error (&error); + + return -1; + } + + gimp_progress_init (_("Rendering SVG")); + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + + image = gimp_image_new (width, height, GIMP_RGB); + gimp_image_undo_disable (image); + + gimp_image_set_filename (image, filename); + gimp_image_set_resolution (image, + load_vals.resolution, load_vals.resolution); + + layer = gimp_layer_new_from_pixbuf (image, _("Rendered SVG"), pixbuf, + 100, + gimp_image_get_default_new_layer_mode (image), + 0.0, 1.0); + gimp_image_insert_layer (image, layer, -1, 0); + + gimp_image_undo_enable (image); + + return image; +} + +/* This is the callback used from load_rsvg_pixbuf(). */ +static void +load_set_size_callback (gint *width, + gint *height, + gpointer data) +{ + SvgLoadVals *vals = data; + + if (*width < 1 || *height < 1) + { + *width = SVG_DEFAULT_SIZE; + *height = SVG_DEFAULT_SIZE; + } + + if (!vals->width || !vals->height) + return; + + /* either both arguments negative or none */ + if ((vals->width * vals->height) < 0) + return; + + if (vals->width > 0) + { + *width = vals->width; + *height = vals->height; + } + else + { + gdouble w = *width; + gdouble h = *height; + gdouble aspect = (gdouble) vals->width / (gdouble) vals->height; + + if (aspect > (w / h)) + { + *height = abs (vals->height); + *width = (gdouble) abs (vals->width) * (w / h) + 0.5; + } + else + { + *width = abs (vals->width); + *height = (gdouble) abs (vals->height) / (w / h) + 0.5; + } + + vals->width = *width; + vals->height = *height; + } +} + +/* This function renders a pixbuf from an SVG file according to vals. */ +static GdkPixbuf * +load_rsvg_pixbuf (const gchar *filename, + SvgLoadVals *vals, + GError **error) +{ + GdkPixbuf *pixbuf = NULL; + RsvgHandle *handle; + GFile *file; + + file = g_file_new_for_path (filename); + + handle = rsvg_handle_new_from_gfile_sync (file, RSVG_HANDLE_FLAGS_NONE, NULL, error); + + g_object_unref (file); + + if (!handle) + { + return NULL; + } + + rsvg_handle_set_dpi (handle, vals->resolution); + rsvg_handle_set_size_callback (handle, load_set_size_callback, vals, NULL); + + pixbuf = rsvg_handle_get_pixbuf (handle); + + g_object_unref (handle); + + return pixbuf; +} + +static GtkWidget *size_label = NULL; + +/* This function retrieves the pixel size from an SVG file. */ +static gboolean +load_rsvg_size (const gchar *filename, + SvgLoadVals *vals, + GError **error) +{ + RsvgHandle *handle; + GFile *file; + RsvgDimensionData dim; + gboolean has_size; + + file = g_file_new_for_path (filename); + + handle = rsvg_handle_new_from_gfile_sync (file, RSVG_HANDLE_FLAGS_NONE, NULL, error); + + g_object_unref (file); + + if (!handle) + { + return FALSE; + } + + rsvg_handle_set_dpi (handle, vals->resolution); + + rsvg_handle_get_dimensions (handle, &dim); + + if (dim.width > 0 && dim.height > 0) + { + vals->width = dim.width; + vals->height = dim.height; + has_size = TRUE; + } + else + { + vals->width = SVG_DEFAULT_SIZE; + vals->height = SVG_DEFAULT_SIZE; + has_size = FALSE; + } + + if (size_label) + { + if (has_size) + { + gchar *text = g_strdup_printf (_("%d × %d"), + vals->width, vals->height); + gtk_label_set_text (GTK_LABEL (size_label), text); + g_free (text); + } + else + { + gtk_label_set_text (GTK_LABEL (size_label), + _("SVG file does not\nspecify a size!")); + } + } + + g_object_unref (handle); + + if (vals->width < 1) vals->width = 1; + if (vals->height < 1) vals->height = 1; + + return TRUE; +} + + +/* User interface */ + +static GimpSizeEntry *size = NULL; +static GtkAdjustment *xadj = NULL; +static GtkAdjustment *yadj = NULL; +static GtkWidget *constrain = NULL; +static gdouble ratio_x = 1.0; +static gdouble ratio_y = 1.0; +static gint svg_width = 0; +static gint svg_height = 0; + +static void load_dialog_set_ratio (gdouble x, + gdouble y); + + +static void +load_dialog_size_callback (GtkWidget *widget, + gpointer data) +{ + if (gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (constrain))) + { + gdouble x = gimp_size_entry_get_refval (size, 0) / (gdouble) svg_width; + gdouble y = gimp_size_entry_get_refval (size, 1) / (gdouble) svg_height; + + if (x != ratio_x) + { + load_dialog_set_ratio (x, x); + } + else if (y != ratio_y) + { + load_dialog_set_ratio (y, y); + } + } +} + +static void +load_dialog_ratio_callback (GtkAdjustment *adj, + gpointer data) +{ + gdouble x = gtk_adjustment_get_value (xadj); + gdouble y = gtk_adjustment_get_value (yadj); + + if (gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (constrain))) + { + if (x != ratio_x) + y = x; + else + x = y; + } + + load_dialog_set_ratio (x, y); +} + +static void +load_dialog_resolution_callback (GimpSizeEntry *res, + const gchar *filename) +{ + SvgLoadVals vals = { 0.0, 0, 0 }; + + load_vals.resolution = vals.resolution = gimp_size_entry_get_refval (res, 0); + + if (!load_rsvg_size (filename, &vals, NULL)) + return; + + g_signal_handlers_block_by_func (size, load_dialog_size_callback, NULL); + + gimp_size_entry_set_resolution (size, 0, load_vals.resolution, FALSE); + gimp_size_entry_set_resolution (size, 1, load_vals.resolution, FALSE); + + g_signal_handlers_unblock_by_func (size, load_dialog_size_callback, NULL); + + if (gimp_size_entry_get_unit (size) != GIMP_UNIT_PIXEL) + { + ratio_x = gimp_size_entry_get_refval (size, 0) / vals.width; + ratio_y = gimp_size_entry_get_refval (size, 1) / vals.height; + } + + svg_width = vals.width; + svg_height = vals.height; + + load_dialog_set_ratio (ratio_x, ratio_y); +} + +static void +load_dialog_set_ratio (gdouble x, + gdouble y) +{ + ratio_x = x; + ratio_y = y; + + g_signal_handlers_block_by_func (size, load_dialog_size_callback, NULL); + + gimp_size_entry_set_refval (size, 0, svg_width * x); + gimp_size_entry_set_refval (size, 1, svg_height * y); + + g_signal_handlers_unblock_by_func (size, load_dialog_size_callback, NULL); + + g_signal_handlers_block_by_func (xadj, load_dialog_ratio_callback, NULL); + g_signal_handlers_block_by_func (yadj, load_dialog_ratio_callback, NULL); + + gtk_adjustment_set_value (xadj, x); + gtk_adjustment_set_value (yadj, y); + + g_signal_handlers_unblock_by_func (xadj, load_dialog_ratio_callback, NULL); + g_signal_handlers_unblock_by_func (yadj, load_dialog_ratio_callback, NULL); +} + +static GimpPDBStatusType +load_dialog (const gchar *filename, + GError **load_error) +{ + GtkWidget *dialog; + GtkWidget *frame; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *image; + GdkPixbuf *preview; + GtkWidget *table; + GtkWidget *table2; + GtkWidget *abox; + GtkWidget *res; + GtkWidget *label; + GtkWidget *spinbutton; + GtkWidget *toggle; + GtkWidget *toggle2; + GtkAdjustment *adj; + gboolean run; + GError *error = NULL; + SvgLoadVals vals = + { + SVG_DEFAULT_RESOLUTION, + - SVG_PREVIEW_SIZE, + - SVG_PREVIEW_SIZE + }; + + preview = load_rsvg_pixbuf (filename, &vals, &error); + + if (! preview) + { + /* Do not rely on librsvg setting GError on failure! */ + g_set_error (load_error, + error ? error->domain : 0, error ? error->code : 0, + _("Could not open '%s' for reading: %s"), + gimp_filename_to_utf8 (filename), + error ? error->message : _("Unknown reason")); + g_clear_error (&error); + + return GIMP_PDB_EXECUTION_ERROR; + } + + gimp_ui_init (PLUG_IN_BINARY, FALSE); + + /* Scalable Vector Graphics is SVG, should perhaps not be translated */ + dialog = gimp_dialog_new (_("Render Scalable Vector Graphics"), + PLUG_IN_ROLE, + NULL, 0, + gimp_standard_help_func, LOAD_PROC, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), 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); + + gimp_window_set_transient (GTK_WINDOW (dialog)); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), + hbox, TRUE, TRUE, 0); + gtk_widget_show (hbox); + + /* The SVG preview */ + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + abox = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), abox, FALSE, FALSE, 0); + gtk_widget_show (abox); + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (abox), frame); + gtk_widget_show (frame); + + image = gtk_image_new_from_pixbuf (preview); + gtk_container_add (GTK_CONTAINER (frame), image); + gtk_widget_show (image); + + size_label = gtk_label_new (NULL); + gtk_label_set_justify (GTK_LABEL (size_label), GTK_JUSTIFY_CENTER); + gtk_box_pack_start (GTK_BOX (vbox), size_label, TRUE, TRUE, 4); + gtk_widget_show (size_label); + + /* query the initial size after the size label is created */ + vals.resolution = load_vals.resolution; + + load_rsvg_size (filename, &vals, NULL); + + svg_width = vals.width; + svg_height = vals.height; + + table = gtk_table_new (7, 3, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2); + gtk_table_set_row_spacing (GTK_TABLE (table), 2, 2); + gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0); + gtk_widget_show (table); + + /* Width and Height */ + label = gtk_label_new (_("Width:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + label = gtk_label_new (_("Height:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (hbox); + + adj = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0); + spinbutton = gimp_spin_button_new (adj, 1.0, 2); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); + gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0); + gtk_widget_show (spinbutton); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (hbox); + + size = GIMP_SIZE_ENTRY (gimp_size_entry_new (1, GIMP_UNIT_PIXEL, "%a", + TRUE, FALSE, FALSE, 10, + GIMP_SIZE_ENTRY_UPDATE_SIZE)); + gtk_table_set_col_spacing (GTK_TABLE (size), 1, 6); + + gimp_size_entry_add_field (size, GTK_SPIN_BUTTON (spinbutton), NULL); + + gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (size), FALSE, FALSE, 0); + gtk_widget_show (GTK_WIDGET (size)); + + gimp_size_entry_set_refval_boundaries (size, 0, + GIMP_MIN_IMAGE_SIZE, + GIMP_MAX_IMAGE_SIZE); + gimp_size_entry_set_refval_boundaries (size, 1, + GIMP_MIN_IMAGE_SIZE, + GIMP_MAX_IMAGE_SIZE); + + gimp_size_entry_set_refval (size, 0, svg_width); + gimp_size_entry_set_refval (size, 1, svg_height); + + gimp_size_entry_set_resolution (size, 0, load_vals.resolution, FALSE); + gimp_size_entry_set_resolution (size, 1, load_vals.resolution, FALSE); + + g_signal_connect (size, "value-changed", + G_CALLBACK (load_dialog_size_callback), + NULL); + + /* Scale ratio */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 2, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (hbox); + + table2 = gtk_table_new (2, 2, FALSE); + gtk_table_set_col_spacing (GTK_TABLE (table2), 0, 2); + gtk_table_set_row_spacing (GTK_TABLE (table2), 0, 4); + gtk_box_pack_start (GTK_BOX (hbox), table2, FALSE, FALSE, 0); + + xadj = (GtkAdjustment *) + gtk_adjustment_new (ratio_x, + (gdouble) GIMP_MIN_IMAGE_SIZE / (gdouble) svg_width, + (gdouble) GIMP_MAX_IMAGE_SIZE / (gdouble) svg_width, + 0.01, 0.1, 0); + spinbutton = gimp_spin_button_new (xadj, 0.01, 4); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); + gtk_table_attach_defaults (GTK_TABLE (table2), spinbutton, 0, 1, 0, 1); + gtk_widget_show (spinbutton); + + g_signal_connect (xadj, "value-changed", + G_CALLBACK (load_dialog_ratio_callback), + NULL); + + label = gtk_label_new_with_mnemonic (_("_X ratio:")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + yadj = (GtkAdjustment *) + gtk_adjustment_new (ratio_y, + (gdouble) GIMP_MIN_IMAGE_SIZE / (gdouble) svg_height, + (gdouble) GIMP_MAX_IMAGE_SIZE / (gdouble) svg_height, + 0.01, 0.1, 0); + spinbutton = gimp_spin_button_new (yadj, 0.01, 4); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + gtk_entry_set_width_chars (GTK_ENTRY (spinbutton), 10); + gtk_table_attach_defaults (GTK_TABLE (table2), spinbutton, 0, 1, 1, 2); + gtk_widget_show (spinbutton); + + g_signal_connect (yadj, "value-changed", + G_CALLBACK (load_dialog_ratio_callback), + NULL); + + label = gtk_label_new_with_mnemonic (_("_Y ratio:")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + /* the constrain ratio chainbutton */ + constrain = gimp_chain_button_new (GIMP_CHAIN_RIGHT); + gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (constrain), TRUE); + gtk_table_attach_defaults (GTK_TABLE (table2), constrain, 1, 2, 0, 2); + gtk_widget_show (constrain); + + gimp_help_set_help_data (GIMP_CHAIN_BUTTON (constrain)->button, + _("Constrain aspect ratio"), NULL); + + gtk_widget_show (table2); + + /* Resolution */ + label = gtk_label_new (_("Resolution:")); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (label); + + res = gimp_size_entry_new (1, GIMP_UNIT_INCH, _("pixels/%a"), + FALSE, FALSE, FALSE, 10, + GIMP_SIZE_ENTRY_UPDATE_RESOLUTION); + gtk_table_set_col_spacing (GTK_TABLE (res), 1, 6); + + gtk_table_attach (GTK_TABLE (table), res, 1, 2, 4, 5, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (res); + + /* don't let the resolution become too small, librsvg tends to + crash with very small resolutions */ + gimp_size_entry_set_refval_boundaries (GIMP_SIZE_ENTRY (res), 0, + 5.0, GIMP_MAX_RESOLUTION); + gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (res), 0, load_vals.resolution); + + g_signal_connect (res, "value-changed", + G_CALLBACK (load_dialog_resolution_callback), + (gpointer) filename); + + /* Path Import */ + toggle = gtk_check_button_new_with_mnemonic (_("Import _paths")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), load_vals.import); + gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 5, 6, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (toggle); + + gimp_help_set_help_data (toggle, + _("Import path elements of the SVG so they " + "can be used with the GIMP path tool"), + NULL); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &load_vals.import); + + toggle2 = gtk_check_button_new_with_mnemonic (_("Merge imported paths")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle2), load_vals.merge); + gtk_table_attach (GTK_TABLE (table), toggle2, 0, 2, 6, 7, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (toggle2); + + g_signal_connect (toggle2, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &load_vals.merge); + + g_object_bind_property (toggle, "active", + toggle2, "sensitive", + G_BINDING_SYNC_CREATE); + + gtk_widget_show (dialog); + + run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK); + + if (run) + { + load_vals.width = ROUND (gimp_size_entry_get_refval (size, 0)); + load_vals.height = ROUND (gimp_size_entry_get_refval (size, 1)); + } + + gtk_widget_destroy (dialog); + + return run ? GIMP_PDB_SUCCESS : GIMP_PDB_CANCEL; +} |