mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-10-06 01:12:40 +02:00
Compare commits
5 Commits
5099a13987
...
wip/Jehan/
Author | SHA1 | Date | |
---|---|---|---|
|
86f009446c | ||
|
0d8f413b57 | ||
|
cb6b602172 | ||
|
d142478e4b | ||
|
4a04570f11 |
@@ -841,7 +841,7 @@ file_revert_confirm_response (GtkWidget *dialog,
|
||||
|
||||
new_image = file_open_image (gimp, gimp_get_user_context (gimp),
|
||||
GIMP_PROGRESS (display),
|
||||
file, FALSE, NULL,
|
||||
file, 0, 0, FALSE, NULL,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
&status, NULL, &error);
|
||||
|
||||
|
@@ -506,8 +506,9 @@ gimp_imagefile_create_thumbnail (GimpImagefile *imagefile,
|
||||
}
|
||||
|
||||
image = file_open_image (private->gimp, context, progress,
|
||||
private->file,
|
||||
FALSE, NULL, GIMP_RUN_NONINTERACTIVE,
|
||||
private->file, size, size,
|
||||
FALSE, NULL,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
&status, &mime_type, error);
|
||||
|
||||
if (image)
|
||||
|
@@ -71,6 +71,8 @@ file_open_image (Gimp *gimp,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
GFile *file,
|
||||
gint vector_width,
|
||||
gint vector_height,
|
||||
gboolean as_new,
|
||||
GimpPlugInProcedure *file_proc,
|
||||
GimpRunMode run_mode,
|
||||
@@ -204,13 +206,30 @@ file_open_image (Gimp *gimp,
|
||||
if (progress)
|
||||
g_object_add_weak_pointer (G_OBJECT (progress), (gpointer) &progress);
|
||||
|
||||
return_vals =
|
||||
gimp_pdb_execute_procedure_by_name (gimp->pdb,
|
||||
context, progress, error,
|
||||
gimp_object_get_name (file_proc),
|
||||
GIMP_TYPE_RUN_MODE, run_mode,
|
||||
G_TYPE_FILE, file,
|
||||
G_TYPE_NONE);
|
||||
if (file_proc->handles_vector)
|
||||
{
|
||||
return_vals =
|
||||
gimp_pdb_execute_procedure_by_name (gimp->pdb,
|
||||
context, progress, error,
|
||||
gimp_object_get_name (file_proc),
|
||||
GIMP_TYPE_RUN_MODE, run_mode,
|
||||
G_TYPE_FILE, file,
|
||||
G_TYPE_INT, vector_width,
|
||||
G_TYPE_INT, vector_height,
|
||||
G_TYPE_BOOLEAN, TRUE,
|
||||
G_TYPE_BOOLEAN, vector_width && vector_height ? FALSE : TRUE,
|
||||
G_TYPE_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return_vals =
|
||||
gimp_pdb_execute_procedure_by_name (gimp->pdb,
|
||||
context, progress, error,
|
||||
gimp_object_get_name (file_proc),
|
||||
GIMP_TYPE_RUN_MODE, run_mode,
|
||||
G_TYPE_FILE, file,
|
||||
G_TYPE_NONE);
|
||||
}
|
||||
|
||||
if (progress)
|
||||
g_object_remove_weak_pointer (G_OBJECT (progress), (gpointer) &progress);
|
||||
@@ -504,7 +523,7 @@ file_open_with_proc_and_display (Gimp *gimp,
|
||||
run_mode = GIMP_RUN_NONINTERACTIVE;
|
||||
|
||||
image = file_open_image (gimp, context, progress,
|
||||
file,
|
||||
file, 0, 0,
|
||||
as_new,
|
||||
file_proc,
|
||||
run_mode,
|
||||
@@ -604,7 +623,10 @@ file_open_layers (Gimp *gimp,
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
new_image = file_open_image (gimp, context, progress,
|
||||
file, FALSE,
|
||||
file,
|
||||
gimp_image_get_width (dest_image),
|
||||
gimp_image_get_height (dest_image),
|
||||
FALSE,
|
||||
file_proc,
|
||||
run_mode,
|
||||
status, &mime_type, error);
|
||||
|
@@ -25,6 +25,8 @@ GimpImage * file_open_image (Gimp *gimp,
|
||||
GimpContext *context,
|
||||
GimpProgress *progress,
|
||||
GFile *file,
|
||||
gint vector_width,
|
||||
gint vector_height,
|
||||
gboolean as_new,
|
||||
GimpPlugInProcedure *file_proc,
|
||||
GimpRunMode run_mode,
|
||||
|
@@ -118,6 +118,7 @@ opened_xcf_file_files (gconstpointer data)
|
||||
gimp_get_user_context (gimp),
|
||||
NULL /*progress*/,
|
||||
file,
|
||||
0, 0, /* vector width, height */
|
||||
FALSE /*as_new*/,
|
||||
NULL /*file_proc*/,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
@@ -158,6 +159,7 @@ imported_file_files (gconstpointer data)
|
||||
gimp_get_user_context (gimp),
|
||||
NULL /*progress*/,
|
||||
file,
|
||||
0, 0, /* vector width, height */
|
||||
FALSE /*as_new*/,
|
||||
NULL /*file_proc*/,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
@@ -206,6 +208,7 @@ saved_imported_file_files (gconstpointer data)
|
||||
gimp_get_user_context (gimp),
|
||||
NULL /*progress*/,
|
||||
import_file,
|
||||
0, 0, /* vector width, height */
|
||||
FALSE /*as_new*/,
|
||||
NULL /*file_proc*/,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
@@ -313,6 +316,7 @@ clear_import_file_after_export (gconstpointer data)
|
||||
gimp_get_user_context (gimp),
|
||||
NULL /*progress*/,
|
||||
file,
|
||||
0, 0, /* vector width, height */
|
||||
FALSE /*as_new*/,
|
||||
NULL /*file_proc*/,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
|
@@ -278,6 +278,7 @@ gimp_test_load_image (Gimp *gimp,
|
||||
gimp_get_user_context (gimp),
|
||||
NULL /*progress*/,
|
||||
file,
|
||||
0, 0, /* vector width, height */
|
||||
FALSE /*as_new*/,
|
||||
proc,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
|
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "gimp.h"
|
||||
|
||||
#include "libgimpbase/gimpwire.h" /* FIXME kill this include */
|
||||
@@ -32,6 +34,8 @@
|
||||
#include "libgimp-intl.h"
|
||||
|
||||
|
||||
#define GIMP_VECTOR_LOAD_DEFAULT_PIXEL_DENSITY 300.0
|
||||
|
||||
/**
|
||||
* GimpVectorLoadProcedure:
|
||||
*
|
||||
@@ -59,6 +63,10 @@ struct _GimpVectorLoadProcedure
|
||||
GimpRunVectorLoadFunc run_func;
|
||||
gpointer run_data;
|
||||
GDestroyNotify run_data_destroy;
|
||||
|
||||
GimpExtractVectorFunc extract_func;
|
||||
gpointer extract_data;
|
||||
GDestroyNotify extract_data_destroy;
|
||||
};
|
||||
|
||||
static void gimp_vector_load_procedure_constructed (GObject *object);
|
||||
@@ -130,7 +138,8 @@ gimp_vector_load_procedure_constructed (GObject *object)
|
||||
GIMP_PROC_AUX_ARG_DOUBLE (procedure, "pixel-density",
|
||||
_("Resolu_tion"),
|
||||
_("Pixel Density: number of pixels per physical unit"),
|
||||
1.0, 5000.0, 300.0,
|
||||
GIMP_MIN_RESOLUTION, GIMP_MAX_RESOLUTION,
|
||||
GIMP_VECTOR_LOAD_DEFAULT_PIXEL_DENSITY,
|
||||
G_PARAM_READWRITE);
|
||||
GIMP_PROC_AUX_ARG_INT (procedure, "physical-unit",
|
||||
_("Unit"),
|
||||
@@ -147,6 +156,9 @@ gimp_vector_load_procedure_finalize (GObject *object)
|
||||
if (procedure->run_data_destroy)
|
||||
procedure->run_data_destroy (procedure->run_data);
|
||||
|
||||
if (procedure->extract_data_destroy)
|
||||
procedure->extract_data_destroy (procedure->extract_data);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -167,26 +179,31 @@ gimp_vector_load_procedure_run (GimpProcedure *procedure,
|
||||
GimpValueArray *remaining;
|
||||
GimpValueArray *return_values;
|
||||
GimpProcedureConfig *config;
|
||||
GimpImage *image = NULL;
|
||||
GimpMetadata *metadata = NULL;
|
||||
gchar *mimetype = NULL;
|
||||
GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;
|
||||
GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR;
|
||||
GimpImage *image = NULL;
|
||||
GimpMetadata *metadata = NULL;
|
||||
gchar *mimetype = NULL;
|
||||
GError *error = NULL;
|
||||
GimpVectorLoadData extracted_dimensions = { 0 };
|
||||
gpointer data_for_run = NULL;
|
||||
GDestroyNotify data_for_run_destroy = NULL;
|
||||
GimpMetadataLoadFlags flags = GIMP_METADATA_LOAD_ALL;
|
||||
GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR;
|
||||
GimpRunMode run_mode;
|
||||
GFile *file;
|
||||
gint width;
|
||||
gint height;
|
||||
gdouble resolution;
|
||||
gint arg_offset = 0;
|
||||
gint i;
|
||||
|
||||
run_mode = GIMP_VALUES_GET_ENUM (args, arg_offset++);
|
||||
file = GIMP_VALUES_GET_FILE (args, arg_offset++);
|
||||
width = GIMP_VALUES_GET_INT (args, arg_offset++);
|
||||
height = GIMP_VALUES_GET_INT (args, arg_offset++);
|
||||
width = GIMP_VALUES_GET_INT (args, arg_offset);
|
||||
height = GIMP_VALUES_GET_INT (args, arg_offset + 1);
|
||||
|
||||
remaining = gimp_value_array_new (gimp_value_array_length (args) - arg_offset);
|
||||
|
||||
for (i = 2 /*arg_offset*/; i < gimp_value_array_length (args); i++)
|
||||
for (i = arg_offset; i < gimp_value_array_length (args); i++)
|
||||
{
|
||||
GValue *value = gimp_value_array_index (args, i);
|
||||
|
||||
@@ -228,28 +245,201 @@ gimp_vector_load_procedure_run (GimpProcedure *procedure,
|
||||
|
||||
_gimp_procedure_config_begin_run (config, image, run_mode, remaining);
|
||||
|
||||
return_values = load_proc->run_func (procedure,
|
||||
run_mode,
|
||||
file, width, height,
|
||||
TRUE, TRUE,
|
||||
metadata, &flags,
|
||||
config,
|
||||
load_proc->run_data);
|
||||
g_object_get (config, "pixel-density", &resolution, NULL);
|
||||
|
||||
if (return_values != NULL &&
|
||||
gimp_value_array_length (return_values) > 0 &&
|
||||
G_VALUE_HOLDS_ENUM (gimp_value_array_index (return_values, 0)))
|
||||
status = GIMP_VALUES_GET_ENUM (return_values, 0);
|
||||
if (load_proc->extract_func)
|
||||
{
|
||||
gboolean extract_success;
|
||||
|
||||
extract_success = load_proc->extract_func (procedure, run_mode, file, metadata, config,
|
||||
&extracted_dimensions,
|
||||
&data_for_run, &data_for_run_destroy,
|
||||
load_proc->run_data, &error);
|
||||
|
||||
if (extract_success)
|
||||
{
|
||||
gdouble default_pixel_width = 0.0;
|
||||
gdouble default_pixel_height = 0.0;
|
||||
gdouble default_resolution = GIMP_VECTOR_LOAD_DEFAULT_PIXEL_DENSITY;
|
||||
gdouble res_pixel_width = 0.0;
|
||||
gdouble res_pixel_height = 0.0;
|
||||
gboolean keep_ratio = TRUE;
|
||||
gboolean prefer_native_dimension = FALSE;
|
||||
|
||||
g_object_get (config,
|
||||
"keep-ratio", &keep_ratio,
|
||||
"prefer-native-dimensions", &prefer_native_dimension,
|
||||
NULL);
|
||||
|
||||
if (extracted_dimensions.width != 0 && extracted_dimensions.height != 0)
|
||||
{
|
||||
if (extracted_dimensions.pixel_density > 0.0 &&
|
||||
extracted_dimensions.density_unit != GIMP_UNIT_PERCENT &&
|
||||
extracted_dimensions.density_unit != GIMP_UNIT_PIXEL)
|
||||
{
|
||||
if (extracted_dimensions.density_unit == GIMP_UNIT_INCH)
|
||||
{
|
||||
resolution = extracted_dimensions.pixel_density;
|
||||
}
|
||||
else
|
||||
{
|
||||
resolution = extracted_dimensions.pixel_density / gimp_unit_get_factor (extracted_dimensions.density_unit);
|
||||
}
|
||||
|
||||
default_resolution = resolution;
|
||||
}
|
||||
|
||||
if (extracted_dimensions.width_unit == GIMP_UNIT_PIXEL ||
|
||||
/* This is kinda bogus, but it at least gives ratio data. */
|
||||
extracted_dimensions.width_unit == GIMP_UNIT_PERCENT)
|
||||
{
|
||||
default_pixel_width = extracted_dimensions.width;
|
||||
res_pixel_width = (gint) default_pixel_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble default_inch_width;
|
||||
|
||||
default_inch_width = extracted_dimensions.width / gimp_unit_get_factor (extracted_dimensions.width_unit);
|
||||
|
||||
default_pixel_width = default_inch_width * default_resolution;
|
||||
res_pixel_width = (gint) ceil (default_inch_width * resolution);
|
||||
}
|
||||
|
||||
if (extracted_dimensions.height_unit == GIMP_UNIT_PIXEL ||
|
||||
extracted_dimensions.height_unit == GIMP_UNIT_PERCENT)
|
||||
{
|
||||
default_pixel_height = extracted_dimensions.height;
|
||||
res_pixel_height = (gint) default_pixel_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble default_inch_height;
|
||||
|
||||
default_inch_height = extracted_dimensions.height / gimp_unit_get_factor (extracted_dimensions.height_unit);
|
||||
|
||||
default_pixel_height = default_inch_height * default_resolution;
|
||||
res_pixel_height = (gint) ceil (default_inch_height * resolution);
|
||||
}
|
||||
}
|
||||
|
||||
if (default_pixel_width != 0.0 && default_pixel_height != 0.0)
|
||||
{
|
||||
GParamSpec *spec;
|
||||
|
||||
if (prefer_native_dimension || (width == 0 && height == 0))
|
||||
{
|
||||
width = (gint) ceil (res_pixel_width);
|
||||
height = (gint) ceil (res_pixel_height);
|
||||
}
|
||||
else if (keep_ratio || width == 0 || height == 0)
|
||||
{
|
||||
gdouble ratio;
|
||||
|
||||
ratio = default_pixel_width / default_pixel_height;
|
||||
|
||||
if (width == 0)
|
||||
width = (gint) ceil (ratio * height);
|
||||
else if (height == 0)
|
||||
height = (gint) ceil (width / ratio);
|
||||
else if (ratio * height <= width)
|
||||
width = (gint) ceil (ratio * height);
|
||||
else
|
||||
height = (gint) ceil (width / ratio);
|
||||
}
|
||||
|
||||
spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), "width");
|
||||
G_PARAM_SPEC_INT (spec)->default_value = (gint) ceil (default_pixel_width);
|
||||
|
||||
spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), "height");
|
||||
G_PARAM_SPEC_INT (spec)->default_value = (gint) ceil (default_pixel_height);
|
||||
|
||||
if (default_resolution != 0.0)
|
||||
{
|
||||
spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), "pixel-density");
|
||||
G_PARAM_SPEC_DOUBLE (spec)->default_value = default_resolution;
|
||||
}
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
/* If width or height are still 0, something was very wrong. */
|
||||
g_set_error_literal (&error, GIMP_PLUG_IN_ERROR, 0,
|
||||
_("dimensions could neither be extracted nor computed "
|
||||
"from the vector image's data."));
|
||||
}
|
||||
}
|
||||
|
||||
g_prefix_error_literal (&error, _("Vector image loading plug-in failed: "));
|
||||
}
|
||||
|
||||
/* One or both dimensions are still zero at this point. */
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
{
|
||||
/* These values are utter-bogus but we just some value to start and
|
||||
* let people select proper values in the interactive dialog.
|
||||
*/
|
||||
if (width != 0)
|
||||
height = width;
|
||||
else if (height != 0)
|
||||
width = width;
|
||||
else
|
||||
width = height = 500;
|
||||
}
|
||||
else if (! error)
|
||||
{
|
||||
/* Except for interactive case where we can always ask interactively,
|
||||
* non-interactive (including "with-last-vals") require valid values.
|
||||
*/
|
||||
g_set_error_literal (&error, GIMP_PLUG_IN_ERROR, 0,
|
||||
_("Dimensions cannot be 0 and no native dimensions "
|
||||
"could be extracted from the vector image."));
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
return_values = gimp_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_set (config,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"pixel-density", resolution,
|
||||
NULL);
|
||||
/* In future, when we'll have vector layers, a vector load proc should be
|
||||
* able to advertize when it can return a vector layer, and when so, we
|
||||
* can even bypass the dialog (by running non-interactively) and just use
|
||||
* the defaults, unless it's all bogus.
|
||||
*/
|
||||
return_values = load_proc->run_func (procedure,
|
||||
run_mode,
|
||||
file, width, height,
|
||||
extracted_dimensions,
|
||||
metadata, &flags,
|
||||
config,
|
||||
data_for_run,
|
||||
load_proc->run_data);
|
||||
|
||||
if (return_values != NULL &&
|
||||
gimp_value_array_length (return_values) > 0 &&
|
||||
G_VALUE_HOLDS_ENUM (gimp_value_array_index (return_values, 0)))
|
||||
status = GIMP_VALUES_GET_ENUM (return_values, 0);
|
||||
}
|
||||
|
||||
_gimp_procedure_config_end_run (config, status);
|
||||
|
||||
if (data_for_run_destroy)
|
||||
data_for_run_destroy (data_for_run);
|
||||
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
if (gimp_value_array_length (return_values) < 2 ||
|
||||
! GIMP_VALUE_HOLDS_IMAGE (gimp_value_array_index (return_values, 1)))
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
status = GIMP_PDB_EXECUTION_ERROR;
|
||||
g_set_error (&error, GIMP_PLUG_IN_ERROR, 0,
|
||||
_("This file loading plug-in returned SUCCESS as a status without an image. "
|
||||
@@ -272,7 +462,7 @@ gimp_vector_load_procedure_run (GimpProcedure *procedure,
|
||||
plug_in = gimp_procedure_get_plug_in (procedure);
|
||||
if (G_OBJECT (config)->ref_count > 1 &&
|
||||
_gimp_plug_in_manage_memory_manually (plug_in))
|
||||
g_printerr ("%s: ERROR: the GimpSaveProcedureConfig object was refed "
|
||||
g_printerr ("%s: ERROR: the GimpProcedureConfig object was refed "
|
||||
"by plug-in, it MUST NOT do that!\n", G_STRFUNC);
|
||||
|
||||
g_object_unref (config);
|
||||
@@ -307,6 +497,9 @@ GimpProcedure *
|
||||
gimp_vector_load_procedure_new (GimpPlugIn *plug_in,
|
||||
const gchar *name,
|
||||
GimpPDBProcType proc_type,
|
||||
GimpExtractVectorFunc extract_func,
|
||||
gpointer extract_data,
|
||||
GDestroyNotify extract_data_destroy,
|
||||
GimpRunVectorLoadFunc run_func,
|
||||
gpointer run_data,
|
||||
GDestroyNotify run_data_destroy)
|
||||
@@ -325,9 +518,12 @@ gimp_vector_load_procedure_new (GimpPlugIn *plug_in,
|
||||
"procedure-type", proc_type,
|
||||
NULL);
|
||||
|
||||
procedure->run_func = run_func;
|
||||
procedure->run_data = run_data;
|
||||
procedure->run_data_destroy = run_data_destroy;
|
||||
procedure->run_func = run_func;
|
||||
procedure->run_data = run_data;
|
||||
procedure->run_data_destroy = run_data_destroy;
|
||||
procedure->extract_func = extract_func;
|
||||
procedure->extract_data = extract_data;
|
||||
procedure->extract_data_destroy = extract_data_destroy;
|
||||
|
||||
return GIMP_PROCEDURE (procedure);
|
||||
}
|
||||
|
@@ -29,6 +29,23 @@ G_BEGIN_DECLS
|
||||
/* For information look into the C source or the html documentation */
|
||||
|
||||
|
||||
typedef struct _GimpVectorLoadData
|
||||
{
|
||||
gdouble width;
|
||||
GimpUnit width_unit;
|
||||
gboolean exact_width;
|
||||
|
||||
gdouble height;
|
||||
GimpUnit height_unit;
|
||||
gboolean exact_height;
|
||||
|
||||
gboolean correct_ratio;
|
||||
|
||||
gdouble pixel_density;
|
||||
GimpUnit density_unit;
|
||||
gboolean exact_density;
|
||||
} GimpVectorLoadData;
|
||||
|
||||
/**
|
||||
* GimpRunVectorLoadFunc:
|
||||
* @procedure: the [class@Gimp.Procedure] that runs.
|
||||
@@ -36,12 +53,12 @@ G_BEGIN_DECLS
|
||||
* @file: the [iface@Gio.File] to load from.
|
||||
* @width: the desired width in pixel for the created image.
|
||||
* @height: the desired height in pixel for the created image.
|
||||
* @keep_ratio: whether dimension ratio should be preserved.
|
||||
* @prefer_native_dimension: whether native dimension should override widthxheight.
|
||||
* @extracted_data: dimensions returned by [callback@ExtractVectorFunc].
|
||||
* @metadata: the [class@Gimp.Metadata] which will be added to the new image.
|
||||
* @flags: (inout): flags to filter which metadata will be added..
|
||||
* @config: the @procedure's remaining arguments.
|
||||
* @run_data: (closure): the run_data given in gimp_vector_load_procedure_new().
|
||||
* @data_from_extract: (closure): @data_for_run returned by [callback@ExtractVectorFunc].
|
||||
* @run_data: (closure): @run_data given in gimp_vector_load_procedure_new().
|
||||
*
|
||||
* The load function is run during the lifetime of the GIMP session, each time a
|
||||
* plug-in load procedure is called.
|
||||
@@ -79,13 +96,65 @@ typedef GimpValueArray * (* GimpRunVectorLoadFunc) (GimpProcedure
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean keep_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data);
|
||||
|
||||
/**
|
||||
* GimpExtractVectorFunc:
|
||||
* @procedure: the [class@Gimp.Procedure].
|
||||
* @run_mode: the [enum@RunMode].
|
||||
* @metadata: the [class@Gimp.Metadata] which will be added to the new image.
|
||||
* @config: the @procedure's remaining arguments.
|
||||
* @file: the [iface@Gio.File] to load from.
|
||||
* @extracted_data: (out): dimensions and pixel density extracted from @file.
|
||||
* @data_for_run: (out) (nullable): will be passed as @data_from_extract in [callback@RunVectorLoadFunc].
|
||||
* @data_for_run_destroy: (out) (nullable) (destroy data_for_run): the free function for @data_for_run.
|
||||
* @extract_data: (closure): the @extract_data given in [func@vector_load_procedure_new].
|
||||
* @error: (out): error to be filled when @file cannot be loaded.
|
||||
*
|
||||
* Loading a vector image happens in 2 steps:
|
||||
*
|
||||
* 1. this function is first run to determine which size should be actually requested.
|
||||
* 2. [callback@RunVectorLoadFunc] is called with the suggested @width and @height.
|
||||
*
|
||||
* This function is run during the lifetime of the GIMP session, as the first
|
||||
* step above. It should extract the maximum of information from the source
|
||||
* document to help GIMP take appropriate decisions for default values and also
|
||||
* for displaying relevant information in the load dialog (if necessary).
|
||||
*
|
||||
* The best case scenario is to be able to extract proper dimensions (@width and
|
||||
* @height) with valid units supported by GIMP. If not possible, returning
|
||||
* already processed dimensions then setting @exact_width and @exact_height to
|
||||
* %FALSE in @extracted_data is also an option. If all you can get are no-unit
|
||||
* dimensions, set them with %GIMP_UNIT_PIXEL and %correct_ratio to %TRUE to at
|
||||
* least give a valid ratio as a default.
|
||||
*
|
||||
* If there is no way to extract any valid default dimensions, not even a ratio,
|
||||
* then return %FALSE but leave %error as %NULL. [callback@RunVectorLoadFunc]
|
||||
* will still be called but default values might be bogus.
|
||||
* If the return value is %FALSE and %error is set, it means that the file is
|
||||
* invalid and cannot even be loaded. Thus [callback@RunVectorLoadFunc] won't be
|
||||
* run and %error
|
||||
*
|
||||
* Returns: %TRUE if any information could be extracted from @file.
|
||||
*
|
||||
* Since: 3.0
|
||||
**/
|
||||
typedef gboolean (* GimpExtractVectorFunc) (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_data,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error);
|
||||
|
||||
|
||||
#define GIMP_TYPE_VECTOR_LOAD_PROCEDURE (gimp_vector_load_procedure_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GimpVectorLoadProcedure, gimp_vector_load_procedure, GIMP, VECTOR_LOAD_PROCEDURE, GimpLoadProcedure)
|
||||
@@ -93,12 +162,15 @@ G_DECLARE_FINAL_TYPE (GimpVectorLoadProcedure, gimp_vector_load_procedure, GIMP,
|
||||
typedef struct _GimpVectorLoadProcedure GimpVectorLoadProcedure;
|
||||
|
||||
|
||||
GimpProcedure * gimp_vector_load_procedure_new (GimpPlugIn *plug_in,
|
||||
const gchar *name,
|
||||
GimpPDBProcType proc_type,
|
||||
GimpRunVectorLoadFunc run_func,
|
||||
gpointer run_data,
|
||||
GDestroyNotify run_data_destroy);
|
||||
GimpProcedure * gimp_vector_load_procedure_new (GimpPlugIn *plug_in,
|
||||
const gchar *name,
|
||||
GimpPDBProcType proc_type,
|
||||
GimpExtractVectorFunc extract_func,
|
||||
gpointer extract_data,
|
||||
GDestroyNotify extract_data_destroy,
|
||||
GimpRunVectorLoadFunc run_func,
|
||||
gpointer run_data,
|
||||
GDestroyNotify run_data_destroy);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -351,6 +351,7 @@ libgimp = library('gimp-'+ gimp_api_version,
|
||||
gegl,
|
||||
gexiv2,
|
||||
drmingw,
|
||||
math,
|
||||
pango,
|
||||
pangoft2,
|
||||
],
|
||||
|
@@ -79,16 +79,26 @@ static GList * pdf_query_procedures (GimpPlugIn *plug_in);
|
||||
static GimpProcedure * pdf_create_procedure (GimpPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static gboolean pdf_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error);
|
||||
static GimpValueArray * pdf_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data);
|
||||
static GimpValueArray * pdf_load_thumb (GimpProcedure *procedure,
|
||||
GFile *file,
|
||||
@@ -116,6 +126,8 @@ static GimpPDBStatusType load_dialog (PopplerDocument *doc,
|
||||
static PopplerDocument * open_document (GFile *file,
|
||||
const gchar *PDF_password,
|
||||
GimpRunMode run_mode,
|
||||
gdouble *width,
|
||||
gdouble *height,
|
||||
GError **error);
|
||||
|
||||
static cairo_surface_t * get_thumb_surface (PopplerDocument *doc,
|
||||
@@ -178,6 +190,7 @@ pdf_create_procedure (GimpPlugIn *plug_in,
|
||||
{
|
||||
procedure = gimp_vector_load_procedure_new (plug_in, name,
|
||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
||||
pdf_extract, NULL, NULL,
|
||||
pdf_load, NULL, NULL);
|
||||
|
||||
gimp_procedure_set_menu_label (procedure, _("Portable Document Format"));
|
||||
@@ -289,40 +302,69 @@ pdf_create_procedure (GimpPlugIn *plug_in,
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pdf_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error)
|
||||
{
|
||||
PopplerDocument *doc = NULL;
|
||||
gchar *password = NULL;
|
||||
gdouble width = 0.0;
|
||||
gdouble height = 0.0;
|
||||
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
g_object_get (config, "password", &password, NULL);
|
||||
doc = open_document (file, password, run_mode,
|
||||
&width, &height, error);
|
||||
g_free (password);
|
||||
if (doc == NULL)
|
||||
return FALSE;
|
||||
|
||||
extracted_dimensions->width = width;
|
||||
extracted_dimensions->height = height;
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_POINT;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_POINT;
|
||||
extracted_dimensions->exact_width = TRUE;
|
||||
extracted_dimensions->exact_height = TRUE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
|
||||
*data_for_run = doc;
|
||||
*data_for_run_destroy = g_object_unref;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
pdf_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
GimpImage *image = NULL;
|
||||
PopplerDocument *doc = NULL;
|
||||
PopplerDocument *doc = POPPLER_DOCUMENT (data_from_extract);
|
||||
PdfSelectedPages pages = { 0, NULL };
|
||||
GError *error = NULL;
|
||||
gchar *password;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
g_object_get (config,
|
||||
"password", &password,
|
||||
NULL);
|
||||
doc = open_document (file,
|
||||
password,
|
||||
run_mode, &error);
|
||||
g_free (password);
|
||||
|
||||
if (doc == NULL)
|
||||
{
|
||||
status = GIMP_PDB_EXECUTION_ERROR;
|
||||
@@ -426,9 +468,6 @@ pdf_load (GimpProcedure *procedure,
|
||||
status = GIMP_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
||||
if (doc)
|
||||
g_object_unref (doc);
|
||||
|
||||
g_free (pages.pages);
|
||||
|
||||
return_vals = gimp_procedure_new_return_values (procedure, status, error);
|
||||
@@ -457,10 +496,8 @@ pdf_load_thumb (GimpProcedure *procedure,
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
doc = open_document (file,
|
||||
NULL,
|
||||
GIMP_RUN_NONINTERACTIVE,
|
||||
&error);
|
||||
doc = open_document (file, NULL, GIMP_RUN_NONINTERACTIVE,
|
||||
NULL, NULL, &error);
|
||||
|
||||
if (doc)
|
||||
{
|
||||
@@ -523,6 +560,8 @@ static PopplerDocument *
|
||||
open_document (GFile *file,
|
||||
const gchar *PDF_password,
|
||||
GimpRunMode run_mode,
|
||||
gdouble *width,
|
||||
gdouble *height,
|
||||
GError **load_error)
|
||||
{
|
||||
PopplerDocument *doc;
|
||||
@@ -596,6 +635,24 @@ open_document (GFile *file,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (width && height)
|
||||
{
|
||||
gint n_pages;
|
||||
|
||||
n_pages = poppler_document_get_n_pages (doc);
|
||||
for (gint i = 0; i < n_pages; i++)
|
||||
{
|
||||
PopplerPage *page;
|
||||
|
||||
page = poppler_document_get_page (doc, i);
|
||||
poppler_page_get_size (page, width, height);
|
||||
g_object_unref (page);
|
||||
|
||||
/* Only check the first page for the whole document size. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -1000,30 +1057,6 @@ load_dialog (PopplerDocument *doc,
|
||||
gboolean white_background;
|
||||
|
||||
n_pages = poppler_document_get_n_pages (doc);
|
||||
for (i = 0; i < n_pages; i++)
|
||||
{
|
||||
PopplerPage *page;
|
||||
gdouble width;
|
||||
gdouble height;
|
||||
gdouble ppi;
|
||||
|
||||
page = poppler_document_get_page (doc, i);
|
||||
poppler_page_get_size (page, &width, &height);
|
||||
g_object_unref (page);
|
||||
|
||||
width /= gimp_unit_get_factor (GIMP_UNIT_POINT);
|
||||
height /= gimp_unit_get_factor (GIMP_UNIT_POINT);
|
||||
g_object_get (config,
|
||||
"pixel-density", &ppi,
|
||||
NULL);
|
||||
g_object_set (config,
|
||||
"width", (gint) ceil (width * ppi),
|
||||
"height", (gint) ceil (height * ppi),
|
||||
NULL);
|
||||
|
||||
/* Only check the first page for the whole document size. */
|
||||
break;
|
||||
}
|
||||
|
||||
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
|
||||
GIMP_PROCEDURE_CONFIG (config),
|
||||
|
@@ -129,16 +129,26 @@ static GList * ps_query_procedures (GimpPlugIn *plug_in);
|
||||
static GimpProcedure * ps_create_procedure (GimpPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static gboolean ps_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error);
|
||||
static GimpValueArray * ps_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data);
|
||||
static GimpValueArray * ps_load_thumb (GimpProcedure *procedure,
|
||||
GFile *file,
|
||||
@@ -231,6 +241,14 @@ static gint get_bbox (GFile *file,
|
||||
gint *x1,
|
||||
gint *y1);
|
||||
|
||||
static gboolean ps_read_header (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
gboolean *is_pdf,
|
||||
gboolean *is_epsf,
|
||||
gint *bbox_x0,
|
||||
gint *bbox_y0,
|
||||
gint *bbox_x1,
|
||||
gint *bbox_y1);
|
||||
static FILE * ps_open (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
gint *llx,
|
||||
@@ -242,6 +260,10 @@ static FILE * ps_open (GFile *file,
|
||||
|
||||
static void ps_close (FILE *ifp,
|
||||
gchar *tmp_filename);
|
||||
static gint read_pnmraw_type (FILE *ifp,
|
||||
gint *width,
|
||||
gint *height,
|
||||
gint *maxval);
|
||||
|
||||
static gboolean skip_ps (FILE *ifp);
|
||||
|
||||
@@ -332,6 +354,7 @@ ps_create_procedure (GimpPlugIn *plug_in,
|
||||
{
|
||||
procedure = gimp_vector_load_procedure_new (plug_in, name,
|
||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
||||
ps_extract, NULL, NULL,
|
||||
ps_load, NULL, NULL);
|
||||
|
||||
if (! strcmp (name, LOAD_PS_PROC))
|
||||
@@ -569,17 +592,58 @@ ps_create_procedure (GimpPlugIn *plug_in,
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ps_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error)
|
||||
{
|
||||
gboolean has_bbox;
|
||||
gboolean is_pdf;
|
||||
gboolean is_epsf;
|
||||
gint bbox_x0 = 0;
|
||||
gint bbox_y0 = 0;
|
||||
gint bbox_x1 = 0;
|
||||
gint bbox_y1 = 0;
|
||||
|
||||
has_bbox = ps_read_header (file, NULL, &is_pdf, &is_epsf,
|
||||
&bbox_x0, &bbox_y0, &bbox_x1, &bbox_y1);
|
||||
|
||||
if (has_bbox)
|
||||
{
|
||||
extracted_dimensions->width = (gdouble) bbox_x1 - bbox_x0;
|
||||
extracted_dimensions->height = (gdouble) bbox_y1 - bbox_y0;
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_POINT;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_POINT;
|
||||
extracted_dimensions->exact_width = TRUE;
|
||||
extracted_dimensions->exact_height = TRUE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
ps_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
@@ -1067,7 +1131,6 @@ load_image (GFile *file,
|
||||
gint width;
|
||||
gint height;
|
||||
gdouble resolution;
|
||||
gboolean use_bbox;
|
||||
gchar *pnm_type = NULL;
|
||||
gchar *text_alpha = NULL;
|
||||
gchar *graphics_alpha = NULL;
|
||||
@@ -1088,7 +1151,6 @@ load_image (GFile *file,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
"pages", &pages,
|
||||
"check-bbox", &use_bbox,
|
||||
"coloring", &pnm_type,
|
||||
"text-alpha-bits", &text_alpha,
|
||||
"graphic-alpha-bits", &graphics_alpha,
|
||||
@@ -1102,7 +1164,6 @@ load_image (GFile *file,
|
||||
#ifdef PS_DEBUG
|
||||
g_print ("load_image:\n resolution = %f\n", resolution);
|
||||
g_print (" %dx%d pixels\n", width, height);
|
||||
g_print (" BoundingBox: %d\n", use_bbox);
|
||||
g_print (" Coloring: %s\n", pnm_type);
|
||||
g_print (" TextAlphaBits: %s\n", text_alpha);
|
||||
g_print (" GraphicsAlphaBits: %s\n", graphics_alpha);
|
||||
@@ -1787,70 +1848,37 @@ get_bbox (GFile *file,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Open the PostScript file. On failure, NULL is returned. */
|
||||
/* The filepointer returned will give a PNM-file generated */
|
||||
/* by the PostScript-interpreter. */
|
||||
static FILE *
|
||||
ps_open (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
gint *llx,
|
||||
gint *lly,
|
||||
gint *urx,
|
||||
gint *ury,
|
||||
gboolean *is_epsf,
|
||||
gchar **tmp_filename)
|
||||
static gboolean
|
||||
ps_read_header (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
gboolean *is_pdf,
|
||||
gboolean *is_epsf,
|
||||
gint *bbox_x0,
|
||||
gint *bbox_y0,
|
||||
gint *bbox_x1,
|
||||
gint *bbox_y1)
|
||||
{
|
||||
const gchar *filename;
|
||||
const gchar *driver;
|
||||
GPtrArray *cmdA;
|
||||
gchar **pcmdA;
|
||||
FILE *fd_popen = NULL;
|
||||
FILE *eps_file;
|
||||
gint width, height;
|
||||
gdouble resolution;
|
||||
gboolean use_bbox;
|
||||
gint pnm_type = 0;
|
||||
gint text_alpha = 0;
|
||||
gint graphics_alpha = 0;
|
||||
gint x0, y0, x1, y1;
|
||||
gint offx = 0;
|
||||
gint offy = 0;
|
||||
gboolean is_pdf;
|
||||
gboolean maybe_epsf = FALSE;
|
||||
int code;
|
||||
void *instance = NULL;
|
||||
FILE *eps_file;
|
||||
const gchar *filename;
|
||||
gboolean use_bbox = TRUE;
|
||||
gboolean maybe_epsf = FALSE;
|
||||
gboolean has_bbox = FALSE;
|
||||
|
||||
if (config)
|
||||
{
|
||||
g_object_get (config,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
"pixel-density", &resolution,
|
||||
"check-bbox", &use_bbox,
|
||||
NULL);
|
||||
pnm_type = gimp_procedure_config_get_choice_id (config, "coloring");
|
||||
text_alpha = gimp_procedure_config_get_choice_id (config, "text-alpha-bits");
|
||||
graphics_alpha = gimp_procedure_config_get_choice_id (config, "graphic-alpha-bits");
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 256;
|
||||
height = 256;
|
||||
resolution = 256.0 / 4.0;
|
||||
}
|
||||
|
||||
*llx = *lly = 0;
|
||||
*urx = width - 1;
|
||||
*ury = height - 1;
|
||||
g_object_get (config, "check-bbox", &use_bbox, NULL);
|
||||
|
||||
/* Check if the file is a PDF. For PDF, we can't set geometry */
|
||||
is_pdf = FALSE;
|
||||
*is_pdf = FALSE;
|
||||
|
||||
/* Check if it is a EPS-file */
|
||||
*is_epsf = FALSE;
|
||||
|
||||
filename = gimp_file_get_utf8_name (file);
|
||||
*bbox_x0 = 0.0;
|
||||
*bbox_y0 = 0.0;
|
||||
*bbox_x1 = 0.0;
|
||||
*bbox_y1 = 0.0;
|
||||
|
||||
filename = gimp_file_get_utf8_name (file);
|
||||
eps_file = g_fopen (filename, "rb");
|
||||
|
||||
if (eps_file)
|
||||
@@ -1858,13 +1886,13 @@ ps_open (GFile *file,
|
||||
gchar hdr[512];
|
||||
|
||||
fread (hdr, 1, sizeof(hdr), eps_file);
|
||||
is_pdf = (strncmp (hdr, "%PDF", 4) == 0);
|
||||
*is_pdf = (strncmp (hdr, "%PDF", 4) == 0);
|
||||
|
||||
if (!is_pdf) /* Check for EPSF */
|
||||
if (!*is_pdf) /* Check for EPSF */
|
||||
{
|
||||
char *adobe, *epsf;
|
||||
int ds = 0;
|
||||
static unsigned char doseps[5] = { 0xc5, 0xd0, 0xd3, 0xc6, 0 };
|
||||
char *adobe, *epsf;
|
||||
int ds = 0;
|
||||
static unsigned char doseps[5] = { 0xc5, 0xd0, 0xd3, 0xc6, 0 };
|
||||
|
||||
hdr[sizeof(hdr)-1] = '\0';
|
||||
adobe = strstr (hdr, "PS-Adobe-");
|
||||
@@ -1888,31 +1916,97 @@ ps_open (GFile *file,
|
||||
fclose (eps_file);
|
||||
}
|
||||
|
||||
if ((!is_pdf) && (use_bbox)) /* Try the BoundingBox ? */
|
||||
if ((!*is_pdf) && (use_bbox)) /* Try the BoundingBox ? */
|
||||
{
|
||||
if (get_bbox (file, &x0, &y0, &x1, &y1) == 0)
|
||||
if (get_bbox (file, bbox_x0, bbox_y0, bbox_x1, bbox_y1) == 0)
|
||||
{
|
||||
if (maybe_epsf && ((x0 < 0) || (y0 < 0)))
|
||||
*is_epsf = 1;
|
||||
has_bbox = TRUE;
|
||||
|
||||
if (*is_epsf) /* Handle negative BoundingBox for EPSF */
|
||||
{
|
||||
offx = -x0; x1 += offx; x0 += offx;
|
||||
offy = -y0; y1 += offy; y0 += offy;
|
||||
}
|
||||
if ((x0 >= 0) && (y0 >= 0) && (x1 > x0) && (y1 > y0))
|
||||
{
|
||||
*llx = (int)((x0/72.0) * resolution + 0.0001);
|
||||
*lly = (int)((y0/72.0) * resolution + 0.0001);
|
||||
/* Use upper bbox values as image size */
|
||||
width = (int)((x1/72.0) * resolution + 0.5);
|
||||
height = (int)((y1/72.0) * resolution + 0.5);
|
||||
/* Pixel coordinates must be one less */
|
||||
*urx = width - 1;
|
||||
*ury = height - 1;
|
||||
if (*urx < *llx) *urx = *llx;
|
||||
if (*ury < *lly) *ury = *lly;
|
||||
}
|
||||
if (maybe_epsf && ((bbox_x0 < 0) || (bbox_y0 < 0)))
|
||||
*is_epsf = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return has_bbox;
|
||||
}
|
||||
|
||||
/* Open the PostScript file. On failure, NULL is returned. */
|
||||
/* The filepointer returned will give a PNM-file generated */
|
||||
/* by the PostScript-interpreter. */
|
||||
static FILE *
|
||||
ps_open (GFile *file,
|
||||
GimpProcedureConfig *config,
|
||||
gint *llx,
|
||||
gint *lly,
|
||||
gint *urx,
|
||||
gint *ury,
|
||||
gboolean *is_epsf,
|
||||
gchar **tmp_filename)
|
||||
{
|
||||
const gchar *driver;
|
||||
GPtrArray *cmdA;
|
||||
gchar **pcmdA;
|
||||
FILE *fd_popen = NULL;
|
||||
gint width, height;
|
||||
gdouble resolution;
|
||||
gint pnm_type = 0;
|
||||
gint text_alpha = 0;
|
||||
gint graphics_alpha = 0;
|
||||
gboolean has_bbox;
|
||||
gint bbox_x0 = 0;
|
||||
gint bbox_y0 = 0;
|
||||
gint bbox_x1 = 0;
|
||||
gint bbox_y1 = 0;
|
||||
gint offx = 0;
|
||||
gint offy = 0;
|
||||
gboolean is_pdf;
|
||||
int code;
|
||||
void *instance = NULL;
|
||||
|
||||
if (config)
|
||||
{
|
||||
g_object_get (config,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
"pixel-density", &resolution,
|
||||
NULL);
|
||||
pnm_type = gimp_procedure_config_get_choice_id (config, "coloring");
|
||||
text_alpha = gimp_procedure_config_get_choice_id (config, "text-alpha-bits");
|
||||
graphics_alpha = gimp_procedure_config_get_choice_id (config, "graphic-alpha-bits");
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 256;
|
||||
height = 256;
|
||||
resolution = 256.0 / 4.0;
|
||||
}
|
||||
|
||||
*llx = *lly = 0;
|
||||
*urx = width - 1;
|
||||
*ury = height - 1;
|
||||
|
||||
has_bbox = ps_read_header (file, config, &is_pdf, is_epsf, &bbox_x0, &bbox_y0, &bbox_x1, &bbox_y1);
|
||||
|
||||
if (has_bbox)
|
||||
{
|
||||
if (*is_epsf) /* Handle negative BoundingBox for EPSF */
|
||||
{
|
||||
offx = -bbox_x0; bbox_x1 += offx; bbox_x0 += offx;
|
||||
offy = -bbox_y0; bbox_y1 += offy; bbox_y0 += offy;
|
||||
}
|
||||
|
||||
if (bbox_x0 >= 0 && bbox_y0 >= 0 && bbox_x1 > bbox_x0 && bbox_y1 > bbox_y0)
|
||||
{
|
||||
*llx = (int) (bbox_x0 / 72.0 * resolution + 0.0001);
|
||||
*lly = (int) (bbox_y0 / 72.0 * resolution + 0.0001);
|
||||
/* Use upper bbox values as image size */
|
||||
width = (int) (bbox_x1 / 72.0 * resolution + 0.5);
|
||||
height = (int) (bbox_y1 / 72.0 * resolution + 0.5);
|
||||
/* Pixel coordinates must be one less */
|
||||
*urx = width - 1;
|
||||
*ury = height - 1;
|
||||
if (*urx < *llx) *urx = *llx;
|
||||
if (*ury < *lly) *ury = *lly;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1995,7 +2089,7 @@ ps_open (GFile *file,
|
||||
|
||||
/* input file name */
|
||||
g_ptr_array_add (cmdA, g_strdup ("-f"));
|
||||
g_ptr_array_add (cmdA, g_strdup (filename));
|
||||
g_ptr_array_add (cmdA, g_strdup (gimp_file_get_utf8_name (file)));
|
||||
|
||||
if (*is_epsf)
|
||||
{
|
||||
|
@@ -35,7 +35,6 @@
|
||||
|
||||
|
||||
#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"
|
||||
@@ -75,44 +74,44 @@ static GList * svg_query_procedures (GimpPlugIn *plug_in);
|
||||
static GimpProcedure * svg_create_procedure (GimpPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static gboolean svg_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error);
|
||||
static GimpValueArray * svg_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer run_data);
|
||||
static GimpValueArray * svg_load_thumb (GimpProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data);
|
||||
|
||||
static GimpImage * load_image (GFile *file,
|
||||
RsvgHandle *handle,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble resolution,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
GError **error);
|
||||
static GdkPixbuf * load_rsvg_pixbuf (GFile *file,
|
||||
static GdkPixbuf * load_rsvg_pixbuf (RsvgHandle *handle,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble resolution,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
gboolean *allow_retry,
|
||||
GError **error);
|
||||
static gboolean load_rsvg_size (GFile *file,
|
||||
SvgLoadVals *vals,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
GError **error);
|
||||
static GimpPDBStatusType load_dialog (GFile *file,
|
||||
RsvgHandle *handle,
|
||||
GimpProcedure *procedure,
|
||||
GimpProcedureConfig *config,
|
||||
RsvgHandleFlags *rsvg_flags,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GError **error);
|
||||
|
||||
static void svg_destroy_surface (guchar *pixels,
|
||||
@@ -146,7 +145,6 @@ svg_query_procedures (GimpPlugIn *plug_in)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
||||
list = g_list_append (list, g_strdup (LOAD_THUMB_PROC));
|
||||
list = g_list_append (list, g_strdup (LOAD_PROC));
|
||||
|
||||
return list;
|
||||
@@ -162,6 +160,7 @@ svg_create_procedure (GimpPlugIn *plug_in,
|
||||
{
|
||||
procedure = gimp_vector_load_procedure_new (plug_in, name,
|
||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
||||
svg_extract, NULL, NULL,
|
||||
svg_load, NULL, NULL);
|
||||
|
||||
gimp_procedure_set_menu_label (procedure, _("SVG image"));
|
||||
@@ -185,9 +184,6 @@ svg_create_procedure (GimpPlugIn *plug_in,
|
||||
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_PROC_ARG_CHOICE (procedure, "paths",
|
||||
_("_Paths"),
|
||||
_("Whether and how to import paths so that they can be used with the path tool"),
|
||||
@@ -197,43 +193,279 @@ svg_create_procedure (GimpPlugIn *plug_in,
|
||||
NULL),
|
||||
"no-import", G_PARAM_READWRITE);
|
||||
}
|
||||
else if (! strcmp (name, LOAD_THUMB_PROC))
|
||||
{
|
||||
procedure = gimp_thumbnail_procedure_new (plug_in, name,
|
||||
GIMP_PDB_PROC_TYPE_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);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static GimpUnit
|
||||
svg_rsvg_unit_to_gimp_unit (RsvgUnit unit)
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case RSVG_UNIT_PERCENT:
|
||||
return GIMP_UNIT_PERCENT;
|
||||
case RSVG_UNIT_PX:
|
||||
return GIMP_UNIT_PIXEL;
|
||||
case RSVG_UNIT_IN:
|
||||
return GIMP_UNIT_INCH;
|
||||
case RSVG_UNIT_MM:
|
||||
return GIMP_UNIT_MM;
|
||||
case RSVG_UNIT_PT:
|
||||
return GIMP_UNIT_POINT;
|
||||
case RSVG_UNIT_PC:
|
||||
return GIMP_UNIT_PICA;
|
||||
case RSVG_UNIT_CM:
|
||||
case RSVG_UNIT_EM:
|
||||
case RSVG_UNIT_EX:
|
||||
/*case RSVG_UNIT_CH:*/
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
svg_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error)
|
||||
{
|
||||
RsvgHandle *handle;
|
||||
#if LIBRSVG_CHECK_VERSION(2, 46, 0)
|
||||
gboolean out_has_width;
|
||||
RsvgLength out_width;
|
||||
gboolean out_has_height;
|
||||
RsvgLength out_height;
|
||||
gboolean out_has_viewbox;
|
||||
RsvgRectangle out_viewbox;
|
||||
#endif
|
||||
#if ! LIBRSVG_CHECK_VERSION(2, 52, 0)
|
||||
RsvgDimensionData dim;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (extracted_dimensions != NULL, FALSE);
|
||||
g_return_val_if_fail (data_for_run_destroy != NULL && *data_for_run_destroy == NULL, FALSE);
|
||||
g_return_val_if_fail (data_for_run != NULL && *data_for_run == NULL, FALSE);
|
||||
g_return_val_if_fail (error != NULL && *error == NULL, FALSE);
|
||||
|
||||
handle = rsvg_handle_new_from_gfile_sync (file, RSVG_HANDLE_FLAGS_NONE, NULL, error);
|
||||
|
||||
if (! handle)
|
||||
{
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_hbox;
|
||||
GtkWidget *label;
|
||||
gchar *text;
|
||||
gboolean retry;
|
||||
|
||||
/* We need to ask explicitly before using the "unlimited" size
|
||||
* option (XML_PARSE_HUGE in libxml) because it is considered
|
||||
* unsafe, possibly consumming too much memory with malicious XML
|
||||
* files.
|
||||
*/
|
||||
dialog = gimp_dialog_new (_("Disable safety size limits?"),
|
||||
PLUG_IN_ROLE,
|
||||
NULL, 0,
|
||||
gimp_standard_help_func, LOAD_PROC,
|
||||
|
||||
_("_No"), GTK_RESPONSE_NO,
|
||||
_("_Yes"), GTK_RESPONSE_YES,
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
gimp_window_set_transient (GTK_WINDOW (dialog));
|
||||
|
||||
main_hbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
main_hbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (main_hbox);
|
||||
|
||||
/* Unfortunately the error returned by librsvg is unclear. While
|
||||
* libxml explicitly returns a "parser error : internal error:
|
||||
* Huge input lookup", librsvg does not seem to relay this error.
|
||||
* It sends a further parsing error, false positive provoked by
|
||||
* the huge input error.
|
||||
* If we were able to single out the huge data error, we could
|
||||
* just directly return from the plug-in as a failure run in other
|
||||
* cases. Instead of this, we need to ask each and every time, in
|
||||
* case it might be the huge data error.
|
||||
*/
|
||||
label = gtk_label_new (_("A parsing error occurred.\n"
|
||||
"Disabling safety limits may help. "
|
||||
"Malicious SVG files may use this to consume too much memory."));
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD);
|
||||
gtk_label_set_max_width_chars (GTK_LABEL (label), 80);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = gtk_label_new (NULL);
|
||||
text = g_strdup_printf ("<b>%s</b>",
|
||||
_("For security reasons, this should only be used for trusted input!"));
|
||||
gtk_label_set_markup (GTK_LABEL (label), text);
|
||||
g_free (text);
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = gtk_label_new (_("Retry without limits preventing to parse huge data?"));
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
retry = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_YES);
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
if (retry)
|
||||
{
|
||||
g_clear_error (error);
|
||||
handle = rsvg_handle_new_from_gfile_sync (file, RSVG_HANDLE_FLAG_UNLIMITED, NULL, error);
|
||||
}
|
||||
}
|
||||
|
||||
if (! handle)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* SVG has no pixel density information */
|
||||
extracted_dimensions->exact_density = TRUE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
|
||||
#if LIBRSVG_CHECK_VERSION(2, 46, 0)
|
||||
rsvg_handle_get_intrinsic_dimensions (handle,
|
||||
&out_has_width, &out_width,
|
||||
&out_has_height, &out_height,
|
||||
&out_has_viewbox, &out_viewbox);
|
||||
|
||||
if (out_has_width && out_has_height)
|
||||
{
|
||||
/* "width" and "height" present: the viewbox has no importance (it's only
|
||||
* a coordinate remapping.
|
||||
*/
|
||||
if (svg_rsvg_unit_to_gimp_unit (out_width.unit) != -1 &&
|
||||
svg_rsvg_unit_to_gimp_unit (out_height.unit) != -1)
|
||||
{
|
||||
/* Best case scenario: we know all these units. */
|
||||
extracted_dimensions->width = out_width.length;
|
||||
extracted_dimensions->width_unit = svg_rsvg_unit_to_gimp_unit (out_width.unit);
|
||||
extracted_dimensions->height = out_height.length;
|
||||
extracted_dimensions->height_unit = svg_rsvg_unit_to_gimp_unit (out_height.unit);
|
||||
|
||||
extracted_dimensions->exact_width = TRUE;
|
||||
extracted_dimensions->exact_height = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ideally we let GIMP handle the transformation, but for cases where
|
||||
* we don't know how, we let rsvg make a computation to pixel for us.
|
||||
*/
|
||||
#if LIBRSVG_CHECK_VERSION(2, 52, 0)
|
||||
if (rsvg_handle_get_intrinsic_size_in_pixels (handle,
|
||||
&extracted_dimensions->width,
|
||||
&extracted_dimensions->height))
|
||||
{
|
||||
extracted_dimensions->width_unit = *height_unit = GIMP_UNIT_PIXEL;
|
||||
extracted_dimensions->exact_width = FALSE;
|
||||
extracted_dimensions->exact_height = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Honestly at this point, setting 300 PPI is random. */
|
||||
rsvg_handle_set_dpi (handle, 300.0);
|
||||
if (rsvg_handle_get_intrinsic_size_in_pixels (handle
|
||||
&extracted_dimensions->width,
|
||||
&extracted_dimensions->height))
|
||||
{
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_PERCENT;
|
||||
}
|
||||
else if (out_width.unit == out_height.unit)
|
||||
{
|
||||
/* Odd case which should likely never happen as we have width,
|
||||
* height and a (fake) pixel density. Just in case though.
|
||||
*/
|
||||
extracted_dimensions->width = out_width.length;
|
||||
extracted_dimensions->height = out_height.length;
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_PERCENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Should even less happen! */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rsvg_handle_get_dimensions (handle, &dim);
|
||||
extracted_dimensions->width = (gdouble) dim.width;
|
||||
extracted_dimensions->height = (gdouble) dim.height;
|
||||
extracted_dimensions->exact_width = FALSE;
|
||||
extracted_dimensions->exact_height = FALSE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (out_has_viewbox)
|
||||
{
|
||||
/* Only a viewbox, so dimensions have a ratio, but no units. */
|
||||
extracted_dimensions->width = out_width.length;
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->exact_width = FALSE;
|
||||
extracted_dimensions->height = out_height.length;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->exact_height = FALSE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Neither width nor viewbox. Nothing can be determined. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#else
|
||||
rsvg_handle_get_dimensions (handle, &dim);
|
||||
extracted_dimensions->width = (gdouble) dim.width;
|
||||
extracted_dimensions->height = (gdouble) dim.height;
|
||||
extracted_dimensions->exact_width = FALSE;
|
||||
extracted_dimensions->exact_height = FALSE;
|
||||
extracted_dimensions->correct_ratio = TRUE;
|
||||
#endif
|
||||
|
||||
*data_for_run = handle;
|
||||
*data_for_run_destroy = g_object_unref;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
svg_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
GimpImage *image;
|
||||
GError *error = NULL;
|
||||
RsvgHandleFlags rsvg_flags = RSVG_HANDLE_FLAGS_NONE;
|
||||
GimpPDBStatusType status;
|
||||
gchar *import_paths;
|
||||
gdouble resolution;
|
||||
@@ -242,7 +474,8 @@ svg_load (GimpProcedure *procedure,
|
||||
|
||||
if (run_mode == GIMP_RUN_INTERACTIVE)
|
||||
{
|
||||
status = load_dialog (file, procedure, config, &rsvg_flags, &error);
|
||||
status = load_dialog (file, RSVG_HANDLE (data_from_extract),
|
||||
procedure, config, extracted_data, &error);
|
||||
if (status != GIMP_PDB_SUCCESS)
|
||||
return gimp_procedure_new_return_values (procedure, status, error);
|
||||
}
|
||||
@@ -252,7 +485,8 @@ svg_load (GimpProcedure *procedure,
|
||||
"height", &height,
|
||||
"pixel-density", &resolution,
|
||||
NULL);
|
||||
image = load_image (file, width, height, resolution, rsvg_flags, &error);
|
||||
image = load_image (file, RSVG_HANDLE (data_from_extract),
|
||||
width, height, resolution, &error);
|
||||
|
||||
if (! image)
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
@@ -282,76 +516,12 @@ svg_load (GimpProcedure *procedure,
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
svg_load_thumb (GimpProcedure *procedure,
|
||||
GFile *file,
|
||||
gint size,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer run_data)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
GimpImage *image;
|
||||
gint width = 0;
|
||||
gint height = 0;
|
||||
gint thumb_width = 0;
|
||||
gint thumb_height = 0;
|
||||
GError *error = NULL;
|
||||
SvgLoadVals vals =
|
||||
{
|
||||
SVG_DEFAULT_RESOLUTION,
|
||||
SVG_PREVIEW_SIZE,
|
||||
SVG_PREVIEW_SIZE,
|
||||
};
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
if (load_rsvg_size (file, &vals, RSVG_HANDLE_FLAGS_NONE, NULL))
|
||||
{
|
||||
width = vals.width;
|
||||
height = vals.height;
|
||||
if (width > height)
|
||||
{
|
||||
thumb_width = size;
|
||||
thumb_height = size * height / width;
|
||||
}
|
||||
else
|
||||
{
|
||||
thumb_width = size * width / height;
|
||||
thumb_height = size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thumb_width = size;
|
||||
thumb_height = size;
|
||||
}
|
||||
|
||||
image = load_image (file, thumb_width, thumb_height, SVG_DEFAULT_RESOLUTION, RSVG_HANDLE_FLAGS_NONE, &error);
|
||||
|
||||
if (! image)
|
||||
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_VALUES_SET_IMAGE (return_vals, 1, image);
|
||||
GIMP_VALUES_SET_INT (return_vals, 2, width);
|
||||
GIMP_VALUES_SET_INT (return_vals, 3, height);
|
||||
|
||||
gimp_value_array_truncate (return_vals, 4);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
||||
static GimpImage *
|
||||
load_image (GFile *file,
|
||||
RsvgHandle *handle,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble resolution,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
GError **load_error)
|
||||
{
|
||||
GimpImage *image;
|
||||
@@ -359,7 +529,7 @@ load_image (GFile *file,
|
||||
GdkPixbuf *pixbuf;
|
||||
GError *error = NULL;
|
||||
|
||||
pixbuf = load_rsvg_pixbuf (file, width, height, resolution, rsvg_flags, NULL, &error);
|
||||
pixbuf = load_rsvg_pixbuf (handle, width, height, resolution, &error);
|
||||
|
||||
if (! pixbuf)
|
||||
{
|
||||
@@ -459,16 +629,13 @@ load_set_size_callback (gint *width,
|
||||
|
||||
/* This function renders a pixbuf from an SVG file according to vals. */
|
||||
static GdkPixbuf *
|
||||
load_rsvg_pixbuf (GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble resolution,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
gboolean *allow_retry,
|
||||
GError **error)
|
||||
load_rsvg_pixbuf (RsvgHandle *handle,
|
||||
gint width,
|
||||
gint height,
|
||||
gdouble resolution,
|
||||
GError **error)
|
||||
{
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
RsvgHandle *handle;
|
||||
|
||||
#if LIBRSVG_CHECK_VERSION(2, 46, 0)
|
||||
cairo_surface_t *surface = NULL;
|
||||
@@ -480,17 +647,7 @@ load_rsvg_pixbuf (GFile *file,
|
||||
SvgLoadVals vals;
|
||||
#endif
|
||||
|
||||
handle = rsvg_handle_new_from_gfile_sync (file, rsvg_flags, NULL, error);
|
||||
|
||||
if (! handle)
|
||||
{
|
||||
/* The "huge data" error will be seen from the handle creation
|
||||
* already. No need to retry when the error occurs later.
|
||||
*/
|
||||
if (allow_retry)
|
||||
*allow_retry = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
g_return_val_if_fail (handle, NULL);
|
||||
|
||||
rsvg_handle_set_dpi (handle, resolution);
|
||||
#if LIBRSVG_CHECK_VERSION(2, 46, 0)
|
||||
@@ -531,79 +688,9 @@ load_rsvg_pixbuf (GFile *file,
|
||||
pixbuf = rsvg_handle_get_pixbuf (handle);
|
||||
#endif
|
||||
|
||||
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 (GFile *file,
|
||||
SvgLoadVals *vals,
|
||||
RsvgHandleFlags rsvg_flags,
|
||||
GError **error)
|
||||
{
|
||||
RsvgHandle *handle;
|
||||
gboolean has_size;
|
||||
gdouble width, height;
|
||||
#if ! LIBRSVG_CHECK_VERSION(2, 52, 0)
|
||||
RsvgDimensionData dim;
|
||||
#endif
|
||||
|
||||
handle = rsvg_handle_new_from_gfile_sync (file, rsvg_flags, NULL, error);
|
||||
|
||||
if (! handle)
|
||||
return FALSE;
|
||||
|
||||
rsvg_handle_set_dpi (handle, vals->resolution);
|
||||
|
||||
#if LIBRSVG_CHECK_VERSION(2, 52, 0)
|
||||
rsvg_handle_get_intrinsic_size_in_pixels (handle, &width, &height);
|
||||
#else
|
||||
rsvg_handle_get_dimensions (handle, &dim);
|
||||
width = (gdouble) dim.width;
|
||||
height = (gdouble) dim.height;
|
||||
#endif
|
||||
|
||||
if (width > 0.0 && height > 0.0)
|
||||
{
|
||||
vals->width = ceil (width);
|
||||
vals->height = ceil (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 */
|
||||
|
||||
@@ -684,9 +771,10 @@ load_dialog_set_ratio (gdouble x,
|
||||
|
||||
static GimpPDBStatusType
|
||||
load_dialog (GFile *file,
|
||||
RsvgHandle *handle,
|
||||
GimpProcedure *procedure,
|
||||
GimpProcedureConfig *config,
|
||||
RsvgHandleFlags *rsvg_flags,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GError **load_error)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
@@ -698,94 +786,10 @@ load_dialog (GFile *file,
|
||||
GtkWidget *label;
|
||||
gboolean run;
|
||||
GError *error = NULL;
|
||||
gchar *text;
|
||||
gboolean allow_retry = FALSE;
|
||||
SvgLoadVals vals =
|
||||
{
|
||||
SVG_DEFAULT_RESOLUTION,
|
||||
SVG_PREVIEW_SIZE,
|
||||
SVG_PREVIEW_SIZE,
|
||||
};
|
||||
|
||||
preview = load_rsvg_pixbuf (file, SVG_PREVIEW_SIZE, SVG_PREVIEW_SIZE, SVG_DEFAULT_RESOLUTION,
|
||||
*rsvg_flags, &allow_retry, &error);
|
||||
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
if (! preview && *rsvg_flags == RSVG_HANDLE_FLAGS_NONE && allow_retry)
|
||||
{
|
||||
/* We need to ask explicitly before using the "unlimited" size
|
||||
* option (XML_PARSE_HUGE in libxml) because it is considered
|
||||
* unsafe, possibly consumming too much memory with malicious XML
|
||||
* files.
|
||||
*/
|
||||
dialog = gimp_dialog_new (_("Disable safety size limits?"),
|
||||
PLUG_IN_ROLE,
|
||||
NULL, 0,
|
||||
gimp_standard_help_func, LOAD_PROC,
|
||||
|
||||
_("_No"), GTK_RESPONSE_NO,
|
||||
_("_Yes"), GTK_RESPONSE_YES,
|
||||
|
||||
NULL);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_NO);
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
gimp_window_set_transient (GTK_WINDOW (dialog));
|
||||
|
||||
main_hbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
|
||||
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
main_hbox, TRUE, TRUE, 0);
|
||||
gtk_widget_show (main_hbox);
|
||||
|
||||
/* Unfortunately the error returned by librsvg is unclear. While
|
||||
* libxml explicitly returns a "parser error : internal error:
|
||||
* Huge input lookup", librsvg does not seem to relay this error.
|
||||
* It sends a further parsing error, false positive provoked by
|
||||
* the huge input error.
|
||||
* If we were able to single out the huge data error, we could
|
||||
* just directly return from the plug-in as a failure run in other
|
||||
* cases. Instead of this, we need to ask each and every time, in
|
||||
* case it might be the huge data error.
|
||||
*/
|
||||
label = gtk_label_new (_("A parsing error occurred.\n"
|
||||
"Disabling safety limits may help. "
|
||||
"Malicious SVG files may use this to consume too much memory."));
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
|
||||
gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD);
|
||||
gtk_label_set_max_width_chars (GTK_LABEL (label), 80);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = gtk_label_new (NULL);
|
||||
text = g_strdup_printf ("<b>%s</b>",
|
||||
_("For security reasons, this should only be used for trusted input!"));
|
||||
gtk_label_set_markup (GTK_LABEL (label), text);
|
||||
g_free (text);
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
label = gtk_label_new (_("Retry without limits preventing to parse huge data?"));
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_box_pack_start (GTK_BOX (main_hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_YES);
|
||||
gtk_widget_destroy (dialog);
|
||||
|
||||
if (run)
|
||||
{
|
||||
*rsvg_flags = RSVG_HANDLE_FLAG_UNLIMITED;
|
||||
g_clear_error (&error);
|
||||
preview = load_rsvg_pixbuf (file, SVG_PREVIEW_SIZE, SVG_PREVIEW_SIZE, SVG_DEFAULT_RESOLUTION,
|
||||
*rsvg_flags, NULL, &error);
|
||||
}
|
||||
}
|
||||
preview = load_rsvg_pixbuf (handle,
|
||||
SVG_PREVIEW_SIZE, SVG_PREVIEW_SIZE, SVG_DEFAULT_RESOLUTION,
|
||||
&error);
|
||||
|
||||
if (! preview)
|
||||
{
|
||||
@@ -800,6 +804,8 @@ load_dialog (GFile *file,
|
||||
return GIMP_PDB_EXECUTION_ERROR;
|
||||
}
|
||||
|
||||
gimp_ui_init (PLUG_IN_BINARY);
|
||||
|
||||
/* Scalable Vector Graphics is SVG, should perhaps not be translated */
|
||||
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
|
||||
GIMP_PROCEDURE_CONFIG (config),
|
||||
@@ -823,19 +829,30 @@ load_dialog (GFile *file,
|
||||
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);
|
||||
label = gtk_label_new (NULL);
|
||||
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 4);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* query the initial size after the size label is created */
|
||||
g_object_get (config, "pixel-density", &vals.resolution, NULL);
|
||||
|
||||
load_rsvg_size (file, &vals, *rsvg_flags, NULL);
|
||||
g_object_set (config,
|
||||
"width", vals.width,
|
||||
"height", vals.height,
|
||||
NULL);
|
||||
if (extracted_data.width >= 0.0 &&
|
||||
extracted_data.height >= 0.0 &&
|
||||
extracted_data.width_unit != GIMP_UNIT_PERCENT &&
|
||||
extracted_data.height_unit != GIMP_UNIT_PERCENT)
|
||||
{
|
||||
/* TRANSLATORS: these are 2D dimensions with unit, e.g. "200 inch x 400 inch" */
|
||||
gchar *text = g_strdup_printf (_("%.4f %s × %.4f %s"),
|
||||
extracted_data.width,
|
||||
gimp_unit_get_abbreviation (extracted_data.width_unit),
|
||||
extracted_data.height,
|
||||
gimp_unit_get_abbreviation (extracted_data.height_unit));
|
||||
gtk_label_set_text (GTK_LABEL (label), text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (label),
|
||||
_("SVG file does not\nspecify a size!"));
|
||||
}
|
||||
|
||||
/* Complete the dialog. */
|
||||
gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), "main-hbox", NULL);
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#define PLUG_IN_ROLE "gimp-file-wmf"
|
||||
|
||||
#define WMF_DEFAULT_RESOLUTION 300.0
|
||||
#define WMF_DEFAULT_SIZE 500
|
||||
#define WMF_DEFAULT_SIZE 500.0
|
||||
#define WMF_PREVIEW_SIZE 128
|
||||
|
||||
|
||||
@@ -80,16 +80,26 @@ static GList * wmf_query_procedures (GimpPlugIn *plug_in);
|
||||
static GimpProcedure * wmf_create_procedure (GimpPlugIn *plug_in,
|
||||
const gchar *name);
|
||||
|
||||
static gboolean wmf_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error);
|
||||
static GimpValueArray * wmf_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data);
|
||||
static GimpValueArray * wmf_load_thumb (GimpProcedure *procedure,
|
||||
GFile *file,
|
||||
@@ -103,7 +113,9 @@ static GimpImage * load_image (GFile *file,
|
||||
gdouble resolution,
|
||||
GError **error);
|
||||
static gboolean load_wmf_size (GFile *file,
|
||||
WmfLoadVals *vals);
|
||||
float *width,
|
||||
float *height,
|
||||
gboolean *guessed);
|
||||
static gboolean load_dialog (GFile *file,
|
||||
GimpProcedure *procedure,
|
||||
GimpProcedureConfig *config);
|
||||
@@ -161,6 +173,7 @@ wmf_create_procedure (GimpPlugIn *plug_in,
|
||||
{
|
||||
procedure = gimp_vector_load_procedure_new (plug_in, name,
|
||||
GIMP_PDB_PROC_TYPE_PLUGIN,
|
||||
wmf_extract, NULL, NULL,
|
||||
wmf_load, NULL, NULL);
|
||||
|
||||
gimp_procedure_set_menu_label (procedure, _("Microsoft WMF file"));
|
||||
@@ -205,17 +218,52 @@ wmf_create_procedure (GimpPlugIn *plug_in,
|
||||
return procedure;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wmf_extract (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
GimpMetadata *metadata,
|
||||
GimpProcedureConfig *config,
|
||||
GimpVectorLoadData *extracted_dimensions,
|
||||
gpointer *data_for_run,
|
||||
GDestroyNotify *data_for_run_destroy,
|
||||
gpointer extract_data,
|
||||
GError **error)
|
||||
{
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
gboolean guessed = FALSE;
|
||||
|
||||
if (! load_wmf_size (file, &width, &height, &guessed))
|
||||
{
|
||||
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
||||
_("Could not open '%s' for reading AA"),
|
||||
gimp_file_get_utf8_name (file));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extracted_dimensions->width = width;
|
||||
extracted_dimensions->width_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->exact_width = guessed ? FALSE : TRUE;
|
||||
extracted_dimensions->height = height;
|
||||
extracted_dimensions->height_unit = GIMP_UNIT_PERCENT;
|
||||
extracted_dimensions->exact_height = guessed ? FALSE : TRUE;
|
||||
extracted_dimensions->correct_ratio = guessed ? FALSE : TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GimpValueArray *
|
||||
wmf_load (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GFile *file,
|
||||
gint width,
|
||||
gint height,
|
||||
gboolean preserve_ratio,
|
||||
gboolean prefer_native_dimension,
|
||||
GimpVectorLoadData extracted_data,
|
||||
GimpMetadata *metadata,
|
||||
GimpMetadataLoadFlags *flags,
|
||||
GimpProcedureConfig *config,
|
||||
gpointer data_from_extract,
|
||||
gpointer run_data)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
@@ -260,29 +308,24 @@ wmf_load_thumb (GimpProcedure *procedure,
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
GimpImage *image;
|
||||
gint width = 0;
|
||||
gint height = 0;
|
||||
GError *error = NULL;
|
||||
WmfLoadVals load_vals = { WMF_DEFAULT_RESOLUTION, 0, 0, };
|
||||
float width = 0;
|
||||
float height = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
gegl_init (NULL, NULL);
|
||||
|
||||
if (load_wmf_size (file, &load_vals) &&
|
||||
load_vals.width > 0 &&
|
||||
load_vals.height > 0)
|
||||
if (load_wmf_size (file, &width, &height, NULL) &&
|
||||
width > 0 && height > 0)
|
||||
{
|
||||
width = load_vals.width;
|
||||
height = load_vals.height;
|
||||
|
||||
if ((gdouble) load_vals.width > (gdouble) load_vals.height)
|
||||
if (width > height)
|
||||
{
|
||||
load_vals.height *= (size / (gdouble) load_vals.width);
|
||||
load_vals.width = size;
|
||||
height *= (size / width);
|
||||
width = (float) size;
|
||||
}
|
||||
else
|
||||
{
|
||||
load_vals.width *= size / (gdouble) load_vals.height;
|
||||
load_vals.height = size;
|
||||
width *= size / height;
|
||||
height = (float) size;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -292,7 +335,7 @@ wmf_load_thumb (GimpProcedure *procedure,
|
||||
NULL);
|
||||
}
|
||||
|
||||
image = load_image (file, load_vals.width, load_vals.height, load_vals.resolution, &error);
|
||||
image = load_image (file, width, height, WMF_DEFAULT_RESOLUTION, &error);
|
||||
|
||||
if (! image)
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
@@ -319,7 +362,9 @@ static GtkWidget *size_label = NULL;
|
||||
/* This function retrieves the pixel size from a WMF file. */
|
||||
static gboolean
|
||||
load_wmf_size (GFile *file,
|
||||
WmfLoadVals *vals)
|
||||
float *width,
|
||||
float *height,
|
||||
gboolean *guessed)
|
||||
{
|
||||
GMappedFile *mapped;
|
||||
/* the bits we need to decode the WMF via libwmf2's GD layer */
|
||||
@@ -329,8 +374,6 @@ load_wmf_size (GFile *file,
|
||||
wmfAPI *API = NULL;
|
||||
wmfAPI_Options api_options;
|
||||
wmfD_Rect bbox;
|
||||
guint width = -1;
|
||||
guint height = -1;
|
||||
gboolean success = TRUE;
|
||||
char* wmffontdirs[2] = { NULL, NULL };
|
||||
|
||||
@@ -368,18 +411,20 @@ load_wmf_size (GFile *file,
|
||||
if (err != wmf_E_None)
|
||||
success = FALSE;
|
||||
|
||||
err = wmf_display_size (API, &width, &height,
|
||||
vals->resolution, vals->resolution);
|
||||
if (err != wmf_E_None || width <= 0 || height <= 0)
|
||||
err = wmf_size (API, width, height);
|
||||
if (err != wmf_E_None || *width <= 0.0f || *height <= 0.0f)
|
||||
success = FALSE;
|
||||
|
||||
wmf_mem_close (API);
|
||||
g_mapped_file_unref (mapped);
|
||||
|
||||
if (width < 1 || height < 1)
|
||||
if (*width <= 0.0f || *height <= 0.0f)
|
||||
{
|
||||
width = WMF_DEFAULT_SIZE;
|
||||
height = WMF_DEFAULT_SIZE;
|
||||
*width = WMF_DEFAULT_SIZE;
|
||||
*height = WMF_DEFAULT_SIZE;
|
||||
|
||||
if (guessed)
|
||||
*guessed = TRUE;
|
||||
|
||||
if (size_label)
|
||||
gtk_label_set_text (GTK_LABEL (size_label),
|
||||
@@ -389,16 +434,13 @@ load_wmf_size (GFile *file,
|
||||
{
|
||||
if (size_label)
|
||||
{
|
||||
gchar *text = g_strdup_printf (_("%d × %d"), width, height);
|
||||
gchar *text = g_strdup_printf (_("%.4f × %.4f"), *width, *height);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (size_label), text);
|
||||
g_free (text);
|
||||
}
|
||||
}
|
||||
|
||||
vals->width = width;
|
||||
vals->height = height;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -472,14 +514,6 @@ load_dialog (GFile *file,
|
||||
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 */
|
||||
g_object_get (config, "pixel-density", &vals.resolution, NULL);
|
||||
load_wmf_size (file, &vals);
|
||||
g_object_set (config,
|
||||
"width", vals.width,
|
||||
"height", vals.height,
|
||||
NULL);
|
||||
|
||||
/* Run the dialog. */
|
||||
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
|
||||
|
||||
|
Reference in New Issue
Block a user