1
1
mirror of https://gitlab.gnome.org/GNOME/gimp.git synced 2025-10-06 01:12:40 +02:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Jehan
86f009446c plug-ins: port file-pdf-load to the new GimpVectorLoadProcedure logic. 2024-04-30 20:56:29 +02:00
Jehan
0d8f413b57 libgimp: "Reset to Factory Defaults" resets to extracted size.
The bogus 0×0 default values for width×height properties are only because we
don't know the real native size of the image. Once we have computed it, we can
change the param spec defaults, so that hitting "Reset to Factory Defaults" sets
width, height and resolution to the actual file's default values (if resolution
is not a metadata in the format, which is apparently the case for all vector
formats we currently support, then 300.0 stays the default resolution).
2024-04-30 20:56:29 +02:00
Jehan
cb6b602172 plug-ins: port file-ps to new GimpVectorLoadProcedure logic. 2024-04-30 20:56:29 +02:00
Jehan
d142478e4b plug-ins: port to the updated GimpVectorLoadProcedure logic. 2024-04-30 20:56:29 +02:00
Jehan
4a04570f11 app, libgimp, plug-ins: improve GimpVectorLoadProcedure workflow.
I'm moving the logic of choosing a correct default for width/height by adding an
"extract dimensions" callback in the procedure. The logic is that every vector
format out there should likely have metadata either for pixel dimensions or
physical dimensions, or at the very least for no-unit dimensions (ratio only).

Vector load procedures will have to implement only the extraction of such data
in a callback called by GIMP but not how to act upon them, so that we have a
common logic for all vector images.

I am implementing this callback first in the SVG plug-in, moving all the code
to extract dimensions (and improving it) in this callback.

Also I am deleting "file-svg-load-thumb" procedure. I could simply reimplement
it using the same code, but it looks to me like this is very useless for vector
formats to have a specific thumbnail procedure (unless it were to use very
specific metadata for faster result). This is vector data, just ask it directly
at the proper bounding box size.
2024-04-30 20:56:29 +02:00
13 changed files with 1003 additions and 526 deletions

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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

View File

@@ -351,6 +351,7 @@ libgimp = library('gimp-'+ gimp_api_version,
gegl,
gexiv2,
drmingw,
math,
pango,
pangoft2,
],

View File

@@ -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),

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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));