plug-ins: port file-svg to GimpPlugIn

This commit is contained in:
Michael Natterer 2019-08-18 23:47:03 +02:00
parent 1e49befef3
commit 64920f01eb
1 changed files with 299 additions and 223 deletions

View File

@ -53,6 +53,57 @@ typedef struct
gboolean merge;
} SvgLoadVals;
typedef struct _Svg Svg;
typedef struct _SvgClass SvgClass;
struct _Svg
{
GimpPlugIn parent_instance;
};
struct _SvgClass
{
GimpPlugInClass parent_class;
};
#define SVG_TYPE (svg_get_type ())
#define SVG (obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SVG_TYPE, Svg))
GType svg_get_type (void) G_GNUC_CONST;
static GList * svg_query_procedures (GimpPlugIn *plug_in);
static GimpProcedure * svg_create_procedure (GimpPlugIn *plug_in,
const gchar *name);
static GimpValueArray * svg_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data);
static GimpValueArray * svg_load_thumb (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data);
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 gboolean load_dialog (const gchar *filename,
GError **error);
G_DEFINE_TYPE (Svg, svg, GIMP_TYPE_PLUG_IN)
GIMP_MAIN (SVG_TYPE)
static SvgLoadVals load_vals =
{
SVG_DEFAULT_RESOLUTION,
@ -63,250 +114,275 @@ static SvgLoadVals load_vals =
};
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)
svg_class_init (SvgClass *klass)
{
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" }
};
GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS (klass);
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);
plug_in_class->query_procedures = svg_query_procedures;
plug_in_class->create_procedure = svg_create_procedure;
}
static void
run (const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals)
svg_init (Svg *svg)
{
static GimpParam values[4];
GimpRunMode run_mode;
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GError *error = NULL;
}
static GList *
svg_query_procedures (GimpPlugIn *plug_in)
{
GList *list = NULL;
list = g_list_append (list, g_strdup (LOAD_PROC));
list = g_list_append (list, g_strdup (LOAD_THUMB_PROC));
return list;
}
static GimpProcedure *
svg_create_procedure (GimpPlugIn *plug_in,
const gchar *name)
{
GimpProcedure *procedure = NULL;
if (! strcmp (name, LOAD_PROC))
{
procedure = gimp_load_procedure_new (plug_in, name, GIMP_PLUGIN,
svg_load, NULL, NULL);
gimp_procedure_set_menu_label (procedure, N_("SVG image"));
gimp_procedure_set_documentation (procedure,
"Loads files in the SVG file format",
"Renders SVG files to raster graphics "
"using librsvg.",
name);
gimp_procedure_set_attribution (procedure,
"Dom Lachowicz, Sven Neumann",
"Dom Lachowicz <cinamod@hotmail.com>",
SVG_VERSION);
gimp_file_procedure_set_mime_types (GIMP_FILE_PROCEDURE (procedure),
"image/svg+xml");
gimp_file_procedure_set_extensions (GIMP_FILE_PROCEDURE (procedure),
"svg");
gimp_file_procedure_set_magics (GIMP_FILE_PROCEDURE (procedure),
"0,string,<?xml,0,string,<svg");
gimp_load_procedure_set_thumbnail_loader (GIMP_LOAD_PROCEDURE (procedure),
LOAD_THUMB_PROC);
gimp_procedure_add_argument (procedure,
g_param_spec_double ("resolution",
"Resolution",
"Resolution to use for "
"rendering the SVG",
GIMP_MIN_RESOLUTION,
GIMP_MAX_RESOLUTION,
90,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("width",
"Width",
"Width (in pixels) to load "
"the SVG in. "
"(0 for original width, "
"a negative width to "
"specify a maximum width)",
-GIMP_MAX_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("height",
"Height",
"Height (in pixels) to load "
"the SVG in. "
"(0 for original heght, "
"a negative width to "
"specify a maximum height)",
-GIMP_MAX_IMAGE_SIZE,
GIMP_MAX_IMAGE_SIZE, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("paths",
"Paths",
"(0) don't import paths, "
"(1) paths individually, "
"(2) paths merged",
0, 2, 0,
GIMP_PARAM_READWRITE));
}
else if (! strcmp (name, LOAD_THUMB_PROC))
{
procedure = gimp_procedure_new (plug_in, name, GIMP_PLUGIN,
svg_load_thumb, NULL, NULL);
gimp_procedure_set_documentation (procedure,
"Generates a thumbnail of an SVG image",
"Renders a thumbnail of an SVG file "
"using librsvg.",
name);
gimp_procedure_set_attribution (procedure,
"Dom Lachowicz, Sven Neumann",
"Dom Lachowicz <cinamod@hotmail.com>",
SVG_VERSION);
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("filename",
"Filename",
"Name of the file "
"to load",
FALSE, TRUE, FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("thumb-size",
"Thumb Size",
"Preferred thumbnail size",
16, 2014, 256,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_image_id ("image",
"Image",
"Thumbnail image",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("image-width",
"Image width",
"Width of the "
"full-sized image",
1, GIMP_MAX_IMAGE_SIZE, 1,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("image-height",
"Image height",
"Height of the "
"full-sized image",
1, GIMP_MAX_IMAGE_SIZE, 1,
GIMP_PARAM_READWRITE));
}
return procedure;
}
static GimpValueArray *
svg_load (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
const GimpValueArray *args,
gpointer run_data)
{
GimpValueArray *return_vals;
gchar *filename;
gint32 image_id;
GError *error = NULL;
INIT_I18N ();
gegl_init (NULL, NULL);
run_mode = param[0].data.d_int32;
filename = g_file_get_path (file);
*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)
switch (run_mode)
{
case GIMP_RUN_NONINTERACTIVE:
load_vals.resolution = g_value_get_double (gimp_value_array_index (args, 0));
load_vals.width = g_value_get_int (gimp_value_array_index (args, 1));
load_vals.height = g_value_get_int (gimp_value_array_index (args, 2));
load_vals.import = g_value_get_int (gimp_value_array_index (args, 3)) != FALSE;
load_vals.merge = g_value_get_int (gimp_value_array_index (args, 3)) == 2;
break;
case GIMP_RUN_INTERACTIVE:
gimp_get_data (LOAD_PROC, &load_vals);
if (! load_dialog (filename, &error))
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CANCEL,
NULL);
break;
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));
}
case GIMP_RUN_WITH_LAST_VALS:
gimp_get_data (LOAD_PROC, &load_vals);
break;
}
else if (strcmp (name, LOAD_THUMB_PROC) == 0)
image_id = load_image (filename, &error);
if (image_id < 1)
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_EXECUTION_ERROR,
error);
if (load_vals.import)
{
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;
gint32 *vectors;
gint num_vectors;
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;
}
}
gimp_vectors_import_from_file (image_id, filename,
load_vals.merge, TRUE,
&num_vectors, &vectors);
if (num_vectors > 0)
g_free (vectors);
}
else
if (run_mode != GIMP_RUN_NONINTERACTIVE)
gimp_set_data (LOAD_PROC, &load_vals, sizeof (load_vals));
g_free (filename);
return_vals = gimp_procedure_new_return_values (procedure,
GIMP_PDB_SUCCESS,
NULL);
gimp_value_set_image_id (gimp_value_array_index (return_vals, 1),
image_id);
return return_vals;
}
static GimpValueArray *
svg_load_thumb (GimpProcedure *procedure,
const GimpValueArray *args,
gpointer run_data)
{
GimpValueArray *return_vals;
const gchar *filename;
gint width = 0;
gint height = 0;
gint32 image_id;
GError *error = NULL;
INIT_I18N ();
gegl_init (NULL, NULL);
filename = g_value_get_string (gimp_value_array_index (args, 0));
if (load_rsvg_size (filename, &load_vals, NULL))
{
status = GIMP_PDB_CALLING_ERROR;
width = load_vals.width;
height = load_vals.height;
}
if (status != GIMP_PDB_SUCCESS && error)
{
*nreturn_vals = 2;
values[1].type = GIMP_PDB_STRING;
values[1].data.d_string = error->message;
}
load_vals.resolution = SVG_DEFAULT_RESOLUTION;
load_vals.width = - g_value_get_int (gimp_value_array_index (args, 1));
load_vals.height = - g_value_get_int (gimp_value_array_index (args, 1));
values[0].data.d_status = status;
image_id = load_image (filename, &error);
if (image_id < 1)
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_EXECUTION_ERROR,
error);
return_vals = gimp_procedure_new_return_values (procedure,
GIMP_PDB_SUCCESS,
NULL);
gimp_value_set_image_id (gimp_value_array_index (return_vals, 1), image_id);
g_value_set_int (gimp_value_array_index (return_vals, 2), width);
g_value_set_int (gimp_value_array_index (return_vals, 3), height);
return return_vals;
}
static gint32
@ -610,7 +686,7 @@ load_dialog_set_ratio (gdouble x,
g_signal_handlers_unblock_by_func (yadj, load_dialog_ratio_callback, NULL);
}
static GimpPDBStatusType
static gboolean
load_dialog (const gchar *filename,
GError **load_error)
{
@ -898,5 +974,5 @@ load_dialog (const gchar *filename,
gtk_widget_destroy (dialog);
return run ? GIMP_PDB_SUCCESS : GIMP_PDB_CANCEL;
return run;
}