libgimp, plug-ins: GimpVectorLoadProcedureDialog will have thumbnail and…

… native dimensions/ratio display by default.

Also adding gimp_vector_load_procedure_extract_dimensions() public
function allowing plug-ins to query the native size or ratio of a vector
file.
This commit is contained in:
Jehan 2024-06-08 18:37:38 +02:00
parent a4bb3a48a2
commit 221bdd61c6
9 changed files with 317 additions and 316 deletions

View File

@ -884,6 +884,7 @@ EXPORTS
gimp_tile_height
gimp_tile_width
gimp_user_time
gimp_vector_load_procedure_extract_dimensions
gimp_vector_load_procedure_get_type
gimp_vector_load_procedure_new
gimp_vectors_bezier_stroke_conicto

View File

@ -51,7 +51,7 @@
*
* When invoked via [method@Procedure.run], it unpacks these standard
* arguments and calls @run_func which is a [callback@RunImageFunc]. The
* [class@ProcedureConfig] of [callback@GimpRunVectorLoadFunc] contains
* [class@ProcedureConfig] of [callback@Gimp.RunVectorLoadFunc] contains
* additionally added arguments but also the arguments added by this class.
*/
@ -527,3 +527,79 @@ gimp_vector_load_procedure_new (GimpPlugIn *plug_in,
return GIMP_PROCEDURE (procedure);
}
/**
* gimp_vector_load_procedure_extract_dimensions:
* @procedure: the associated #GimpVectorLoadProcedure.
* @file: a [iface@Gio.File] which can be processed by @procedure.
* @data: (out): the returned dimension data.
* @error: (out): the #GError in case of error.
*
* Extracts native or suggested dimensions from @file, which must be a vector
* file in the right format supported by @procedure. It is considered a
* programming error to pass a file of invalid format.
*
* Returns: %TRUE if dimensions could be extracted.
*/
gboolean
gimp_vector_load_procedure_extract_dimensions (GimpVectorLoadProcedure *procedure,
GFile *file,
GimpVectorLoadData *data,
GError **error)
{
gboolean extract_success = FALSE;
g_return_val_if_fail (GIMP_IS_VECTOR_LOAD_PROCEDURE (procedure), FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (procedure->extract_func)
{
gchar *mimetype = NULL;
GimpMetadata *metadata = NULL;
gpointer data_for_run = NULL;
GDestroyNotify data_for_run_destroy = NULL;
mimetype = (gchar *) gimp_file_procedure_get_mime_types (GIMP_FILE_PROCEDURE (procedure));
if (mimetype != NULL)
{
char *delim;
mimetype = g_strdup (mimetype);
mimetype = g_strstrip (mimetype);
delim = strstr (mimetype, ",");
if (delim)
*delim = '\0';
/* Though docs only writes about the list being comma-separated, our
* code apparently also split by spaces.
*/
delim = strstr (mimetype, " ");
if (delim)
*delim = '\0';
delim = strstr (mimetype, "\t");
if (delim)
*delim = '\0';
metadata = gimp_metadata_load_from_file (file, NULL);
g_free (mimetype);
}
if (metadata == NULL)
metadata = gimp_metadata_new ();
extract_success = procedure->extract_func (GIMP_PROCEDURE (procedure),
GIMP_RUN_NONINTERACTIVE,
file, metadata, NULL,
data, &data_for_run, &data_for_run_destroy,
procedure->extract_data, error);
if (data_for_run_destroy)
data_for_run_destroy (data_for_run);
g_clear_object (&metadata);
}
return extract_success;
}

View File

@ -108,7 +108,7 @@ typedef GimpValueArray * (* GimpRunVectorLoadFunc) (GimpProcedure
* @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.
* @config: (nullable): 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].
@ -138,7 +138,13 @@ typedef GimpValueArray * (* GimpRunVectorLoadFunc) (GimpProcedure
* 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
* run and %error is passed as the main run error.
*
* Note: when @procedure is run, the original arguments will be passed as
* @config. Nevertheless it may happen that this function is called with a %NULL
* @config, in particular when [method@VectorLoadProcedure.extract_dimensions] is
* called. In such a case, the callback is expected to return whatever can be
* considered "best judgement" defaults.
*
* Returns: %TRUE if any information could be extracted from @file.
*
@ -162,15 +168,20 @@ 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,
GimpExtractVectorFunc extract_func,
gpointer extract_data,
GDestroyNotify extract_data_destroy,
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);
gboolean gimp_vector_load_procedure_extract_dimensions (GimpVectorLoadProcedure *procedure,
GFile *file,
GimpVectorLoadData *data,
GError **error);
G_END_DECLS

View File

@ -35,18 +35,22 @@
struct _GimpVectorLoadProcedureDialogPrivate
{
/* TODO: add thumbnail support from the file. */
GFile *file;
GFile *file;
GimpVectorLoadData *extracted_data;
};
static void gimp_vector_load_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
GimpProcedure *procedure,
GimpProcedureConfig *config,
GList *properties);
static void gimp_vector_load_procedure_dialog_fill_start (GimpProcedureDialog *dialog,
GimpProcedure *procedure,
GimpProcedureConfig *config);
static void gimp_vector_load_procedure_dialog_fill_start (GimpProcedureDialog *dialog,
GimpProcedure *procedure,
GimpProcedureConfig *config);
static void gimp_vector_load_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
GimpProcedure *procedure,
GimpProcedureConfig *config,
GList *properties);
static void gimp_vector_load_procedure_dialog_preview_allocate (GtkWidget *gtk_image,
GtkAllocation *allocation,
GimpVectorLoadProcedureDialog *dialog);
G_DEFINE_TYPE_WITH_PRIVATE (GimpVectorLoadProcedureDialog, gimp_vector_load_procedure_dialog, GIMP_TYPE_PROCEDURE_DIALOG)
@ -56,9 +60,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (GimpVectorLoadProcedureDialog, gimp_vector_load_proc
static void
gimp_vector_load_procedure_dialog_class_init (GimpVectorLoadProcedureDialogClass *klass)
{
GimpProcedureDialogClass *proc_dialog_class;
proc_dialog_class = GIMP_PROCEDURE_DIALOG_CLASS (klass);
GimpProcedureDialogClass *proc_dialog_class = GIMP_PROCEDURE_DIALOG_CLASS (klass);
proc_dialog_class->fill_start = gimp_vector_load_procedure_dialog_fill_start;
proc_dialog_class->fill_list = gimp_vector_load_procedure_dialog_fill_list;
@ -77,19 +79,127 @@ gimp_vector_load_procedure_dialog_fill_start (GimpProcedureDialog *dialog,
GimpProcedure *procedure,
GimpProcedureConfig *config)
{
GtkWidget *content_area;
GtkWidget *res_entry;
GimpVectorLoadProcedureDialog *vector_dialog = GIMP_VECTOR_LOAD_PROCEDURE_DIALOG (dialog);
GtkWidget *content_area;
GtkWidget *top_hbox;
GtkWidget *main_vbox;
GtkWidget *res_entry;
GtkWidget *label;
gchar *text = NULL;
gchar *markup = NULL;
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_pack_start (GTK_BOX (content_area), main_vbox, FALSE, FALSE, 0);
gtk_widget_show (main_vbox);
top_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_box_pack_start (GTK_BOX (main_vbox), top_hbox, FALSE, FALSE, 0);
gtk_widget_show (top_hbox);
/* Resolution */
res_entry = gimp_prop_resolution_entry_new (G_OBJECT (config),
"width", "height", "pixel-density",
"physical-unit");
gtk_box_pack_start (GTK_BOX (content_area), res_entry, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (top_hbox), res_entry, FALSE, FALSE, 0);
gtk_widget_show (res_entry);
/* Preview */
if (vector_dialog->priv->file)
{
GtkWidget *image;
image = gtk_image_new ();
g_signal_connect (image, "size-allocate",
G_CALLBACK (gimp_vector_load_procedure_dialog_preview_allocate),
dialog);
gtk_box_pack_start (GTK_BOX (top_hbox), image, FALSE, FALSE, 0);
gtk_widget_show (image);
}
if (vector_dialog->priv->extracted_data)
{
if (vector_dialog->priv->extracted_data->exact_width && vector_dialog->priv->extracted_data->exact_height)
{
/* TRANSLATORS: the %s is a vector format name, e.g. "SVG" or "PDF",
* followed by 2D dimensions with unit, e.g. "200 inch x 400 inch"
*/
text = g_strdup_printf (_("Source %s file size: %%.%df %s × %%.%df %s"),
gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure)),
gimp_unit_get_digits (vector_dialog->priv->extracted_data->width_unit),
gimp_unit_get_abbreviation (vector_dialog->priv->extracted_data->width_unit),
gimp_unit_get_digits (vector_dialog->priv->extracted_data->height_unit),
gimp_unit_get_abbreviation (vector_dialog->priv->extracted_data->height_unit));
markup = g_strdup_printf (text, vector_dialog->priv->extracted_data->width, vector_dialog->priv->extracted_data->height);
}
else if (vector_dialog->priv->extracted_data->correct_ratio)
{
gdouble ratio_width = 0.0;
gint ratio_width_digits = 0;
gdouble ratio_height = 0.0;
gint ratio_height_digits = 0;
if (vector_dialog->priv->extracted_data->width_unit == vector_dialog->priv->extracted_data->height_unit)
{
ratio_width = vector_dialog->priv->extracted_data->width;
ratio_height = vector_dialog->priv->extracted_data->height;
if (vector_dialog->priv->extracted_data->width_unit == GIMP_UNIT_PIXEL ||
vector_dialog->priv->extracted_data->width_unit == GIMP_UNIT_PERCENT)
ratio_width_digits = ratio_height_digits = 0;
else
ratio_width_digits = ratio_height_digits = gimp_unit_get_digits (vector_dialog->priv->extracted_data->width_unit);
}
else if (vector_dialog->priv->extracted_data->width_unit != GIMP_UNIT_PIXEL && vector_dialog->priv->extracted_data->height_unit != GIMP_UNIT_PIXEL &&
vector_dialog->priv->extracted_data->width_unit != GIMP_UNIT_PERCENT && vector_dialog->priv->extracted_data->height_unit != GIMP_UNIT_PERCENT)
{
ratio_width = vector_dialog->priv->extracted_data->width / gimp_unit_get_factor (vector_dialog->priv->extracted_data->width_unit);
ratio_height = vector_dialog->priv->extracted_data->height / gimp_unit_get_factor (vector_dialog->priv->extracted_data->height_unit);
ratio_width_digits = ratio_height_digits = gimp_unit_get_digits (GIMP_UNIT_INCH);
}
if (ratio_width != 0.0 && ratio_height != 0.0)
{
/* TRANSLATOR: the %s is a vector format name, e.g. "SVG" or "PDF". */
text = g_strdup_printf (_("Source %s file's aspect ratio: %%.%df × %%.%df"),
gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure)),
ratio_width_digits, ratio_height_digits);
markup = g_strdup_printf (text, ratio_width, ratio_height);
}
}
else if (vector_dialog->priv->extracted_data->width != 0.0 && vector_dialog->priv->extracted_data->height != 0.0)
{
text = g_strdup_printf (_("Approximated source %s file size: %%.%df %s × %%.%df %s"),
gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure)),
gimp_unit_get_digits (vector_dialog->priv->extracted_data->width_unit),
gimp_unit_get_abbreviation (vector_dialog->priv->extracted_data->width_unit),
gimp_unit_get_digits (vector_dialog->priv->extracted_data->height_unit),
gimp_unit_get_abbreviation (vector_dialog->priv->extracted_data->height_unit));
markup = g_strdup_printf (text, vector_dialog->priv->extracted_data->width, vector_dialog->priv->extracted_data->height);
}
}
if (markup == NULL)
{
/* TRANSLATOR: the %s is a vector format name, e.g. "SVG" or "PDF". */
text = g_strdup_printf (_("The source %s file does not specify a size!"),
gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure)));
markup = g_strdup_printf ("<i>%s</i>", text);
}
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), markup);
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER);
gtk_box_pack_start (GTK_BOX (main_vbox), label, TRUE, TRUE, 4);
gtk_widget_show (label);
g_free (text);
g_free (markup);
GIMP_PROCEDURE_DIALOG_CLASS (parent_class)->fill_start (dialog, procedure, config);
}
@ -122,13 +232,77 @@ gimp_vector_load_procedure_dialog_fill_list (GimpProcedureDialog *dialog,
g_list_free (properties2);
}
static void
gimp_vector_load_procedure_dialog_preview_allocate (GtkWidget *gtk_image,
GtkAllocation *allocation,
GimpVectorLoadProcedureDialog *dialog)
{
if (dialog->priv->file)
{
GimpProcedure *procedure = NULL;
GimpValueArray *retval;
GimpPDBStatusType status;
g_object_get (dialog, "procedure", &procedure, NULL);
retval = gimp_procedure_run (procedure,
"file", dialog->priv->file,
"width", allocation->height,
"height", allocation->height,
"keep-ratio", TRUE,
NULL);
status = g_value_get_enum (gimp_value_array_index (retval, 0));
if (status == GIMP_PDB_SUCCESS)
{
GimpImage *image;
GdkPixbuf *preview;
image = g_value_get_object (gimp_value_array_index (retval, 1));
preview = gimp_image_get_thumbnail (image,
gimp_image_get_width (image),
gimp_image_get_height (image),
GIMP_PIXBUF_SMALL_CHECKS);
gtk_image_set_from_pixbuf (GTK_IMAGE (gtk_image), preview);
gimp_image_delete (image);
}
gimp_value_array_unref (retval);
}
}
/* Public Functions */
/**
* gimp_vector_load_procedure_dialog_new:
* @procedure: the associated #GimpVectorLoadProcedure.
* @config: a #GimpProcedureConfig from which properties will be
* turned into widgets.
* @extracted_data: (nullable): the extracted dimensions of the file to load.
* @file: (nullable): a [iface@Gio.File] to load the preview from.
*
* Creates a new dialog for @procedure using widgets generated from
* properties of @config.
*
* @file must be the same vector file which was passed to the
* [callback@Gimp.RunVectorLoadFunc] implementation for your plug-in. If you pass any
* other file, then the preview may be wrong or not showing at all. And it is
* considered a programming error.
*
* As for all #GtkWindow, the returned #GimpProcedureDialog object is
* owned by GTK and its initial reference is stored in an internal list
* of top-level windows. To delete the dialog, call
* gtk_widget_destroy().
*
* Returns: (transfer none): the newly created #GimpVectorLoadProcedureDialog.
*/
GtkWidget *
gimp_vector_load_procedure_dialog_new (GimpVectorLoadProcedure *procedure,
GimpProcedureConfig *config,
GimpVectorLoadData *extracted_data,
GFile *file)
{
GtkWidget *dialog;
@ -141,7 +315,7 @@ gimp_vector_load_procedure_dialog_new (GimpVectorLoadProcedure *procedure,
g_return_val_if_fail (GIMP_IS_PROCEDURE_CONFIG (config), NULL);
g_return_val_if_fail (gimp_procedure_config_get_procedure (config) ==
GIMP_PROCEDURE (procedure), NULL);
/*g_return_val_if_fail (G_IS_FILE (file), NULL);*/
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
format_name = gimp_file_procedure_get_format_name (GIMP_FILE_PROCEDURE (procedure));
if (! format_name)
@ -170,6 +344,7 @@ gimp_vector_load_procedure_dialog_new (GimpVectorLoadProcedure *procedure,
"use-header-bar", use_header_bar,
NULL);
GIMP_VECTOR_LOAD_PROCEDURE_DIALOG (dialog)->priv->file = file;
GIMP_VECTOR_LOAD_PROCEDURE_DIALOG (dialog)->priv->extracted_data = extracted_data;
g_free (title);
return dialog;

View File

@ -68,6 +68,7 @@ GType gimp_vector_load_procedure_dialog_get_type (void) G_GNUC_CO
GtkWidget * gimp_vector_load_procedure_dialog_new (GimpVectorLoadProcedure *procedure,
GimpProcedureConfig *config,
GimpVectorLoadData *extracted_data,
GFile *file);

View File

@ -120,6 +120,7 @@ static GimpImage * load_image (PopplerDocument *doc,
static GimpPDBStatusType load_dialog (PopplerDocument *doc,
PdfSelectedPages *pages,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GimpProcedureConfig *config);
@ -371,7 +372,7 @@ pdf_load (GimpProcedure *procedure,
}
else if (run_mode == GIMP_RUN_INTERACTIVE)
{
status = load_dialog (doc, &pages, procedure, config);
status = load_dialog (doc, &pages, extracted_data, procedure, config);
}
else if (run_mode == GIMP_RUN_NONINTERACTIVE)
{
@ -1036,6 +1037,7 @@ white_background_toggled (GtkToggleButton *widget,
static GimpPDBStatusType
load_dialog (PopplerDocument *doc,
PdfSelectedPages *pages,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GimpProcedureConfig *config)
{
@ -1060,7 +1062,7 @@ load_dialog (PopplerDocument *doc,
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
GIMP_PROCEDURE_CONFIG (config),
NULL);
&extracted_data, NULL);
g_object_get (config,
"target", &target,

View File

@ -281,10 +281,11 @@ static void dither_grey (const guchar *grey,
/* Dialog-handling */
static gint32 count_ps_pages (GFile *file);
static gboolean load_dialog (GFile *file,
GimpProcedure *procedure,
GObject *config);
static gint32 count_ps_pages (GFile *file);
static gboolean load_dialog (GFile *file,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GObject *config);
typedef struct
@ -663,7 +664,7 @@ ps_load (GimpProcedure *procedure,
switch (run_mode)
{
case GIMP_RUN_INTERACTIVE:
if (! load_dialog (file, procedure, G_OBJECT (config)))
if (! load_dialog (file, extracted_data, procedure, G_OBJECT (config)))
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CANCEL,
NULL);
@ -3767,9 +3768,10 @@ count_ps_pages (GFile *file)
}
static gboolean
load_dialog (GFile *file,
GimpProcedure *procedure,
GObject *config)
load_dialog (GFile *file,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GObject *config)
{
GtkWidget *dialog;
GtkWidget *hbox;
@ -3786,7 +3788,7 @@ load_dialog (GFile *file,
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
GIMP_PROCEDURE_CONFIG (config),
NULL);
&extracted_data, NULL);
gimp_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
GTK_RESPONSE_OK,

View File

@ -778,85 +778,15 @@ load_dialog (GFile *file,
GimpVectorLoadData extracted_data,
GError **load_error)
{
GtkWidget *dialog;
GtkWidget *frame;
GtkWidget *main_hbox;
GtkWidget *vbox;
GtkWidget *image;
GdkPixbuf *preview;
GtkWidget *label;
gboolean run;
GError *error = NULL;
preview = load_rsvg_pixbuf (handle,
SVG_PREVIEW_SIZE, SVG_PREVIEW_SIZE, SVG_DEFAULT_RESOLUTION,
&error);
if (! preview)
{
/* Do not rely on librsvg setting GError on failure! */
g_set_error (load_error,
error ? error->domain : 0, error ? error->code : 0,
_("Could not open '%s' for reading: %s"),
gimp_file_get_utf8_name (file),
error ? error->message : _("Unknown reason"));
g_clear_error (&error);
return GIMP_PDB_EXECUTION_ERROR;
}
GtkWidget *dialog;
gboolean run;
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),
NULL);
main_hbox = gimp_procedure_dialog_fill_box (GIMP_PROCEDURE_DIALOG (dialog),
"main-hbox", "paths", NULL);
gtk_orientable_set_orientation (GTK_ORIENTABLE (main_hbox), GTK_ORIENTATION_HORIZONTAL);
/* The SVG preview */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0);
gtk_widget_show (vbox);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
image = gtk_image_new_from_pixbuf (preview);
gtk_container_add (GTK_CONTAINER (frame), image);
gtk_widget_show (image);
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);
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);
&extracted_data, file);
gimp_procedure_dialog_fill (GIMP_PROCEDURE_DIALOG (dialog), NULL);
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
gtk_widget_destroy (dialog);

View File

@ -117,11 +117,9 @@ static gboolean load_wmf_size (GFile *file,
float *height,
gboolean *guessed);
static gboolean load_dialog (GFile *file,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GimpProcedureConfig *config);
static WmfPixbuf * wmf_get_pixbuf (GFile *file,
gint *width,
gint *height);
static guchar * wmf_load_file (GFile *file,
gint requested_width,
gint requested_height,
@ -273,7 +271,7 @@ wmf_load (GimpProcedure *procedure,
gegl_init (NULL, NULL);
if (run_mode == GIMP_RUN_INTERACTIVE && ! load_dialog (file, procedure, config))
if (run_mode == GIMP_RUN_INTERACTIVE && ! load_dialog (file, extracted_data, procedure, config))
return gimp_procedure_new_return_values (procedure,
GIMP_PDB_CANCEL,
NULL);
@ -356,9 +354,6 @@ wmf_load_thumb (GimpProcedure *procedure,
}
static GtkWidget *size_label = NULL;
/* This function retrieves the pixel size from a WMF file. */
static gboolean
load_wmf_size (GFile *file,
@ -425,20 +420,6 @@ load_wmf_size (GFile *file,
if (guessed)
*guessed = TRUE;
if (size_label)
gtk_label_set_text (GTK_LABEL (size_label),
_("WMF file does not\nspecify a size!"));
}
else
{
if (size_label)
{
gchar *text = g_strdup_printf (_("%.4f × %.4f"), *width, *height);
gtk_label_set_text (GTK_LABEL (size_label), text);
g_free (text);
}
}
return success;
@ -447,36 +428,20 @@ load_wmf_size (GFile *file,
/* User interface */
static void
wmf_preview_callback (GtkWidget *widget,
GtkAllocation *allocation,
WmfPixbuf *pixbuf)
{
gimp_preview_area_draw (GIMP_PREVIEW_AREA (widget),
0, 0, pixbuf->width, pixbuf->height,
GIMP_RGBA_IMAGE,
pixbuf->pixels, pixbuf->width * 4);
}
static gboolean
load_dialog (GFile *file,
GimpVectorLoadData extracted_data,
GimpProcedure *procedure,
GimpProcedureConfig *config)
{
GtkWidget *dialog;
GtkWidget *content_area;
GtkWidget *vbox;
GtkWidget *frame;
GtkWidget *image;
WmfPixbuf *pixbuf;
gboolean run = FALSE;
WmfLoadVals vals;
GtkWidget *dialog;
gboolean run = FALSE;
gimp_ui_init (PLUG_IN_BINARY);
dialog = gimp_vector_load_procedure_dialog_new (GIMP_VECTOR_LOAD_PROCEDURE (procedure),
GIMP_PROCEDURE_CONFIG (config),
NULL);
&extracted_data, file);
/* TODO: in the old version, there used to be X and Y ratio fields which could
* be constrained/linked (or not) and would sync back and forth with the
@ -484,42 +449,8 @@ load_dialog (GFile *file,
* such UI when editing dimensions with options in GimpResolutionEntry?
*/
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
/* The WMF preview */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
gtk_box_reorder_child (GTK_BOX (content_area), vbox, 0);
gtk_widget_show (vbox);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
vals.width = - WMF_PREVIEW_SIZE;
vals.height = - WMF_PREVIEW_SIZE;
pixbuf = wmf_get_pixbuf (file, &vals.width, &vals.height);
image = gimp_preview_area_new ();
gtk_widget_set_size_request (image, vals.width, vals.height);
gtk_container_add (GTK_CONTAINER (frame), image);
gtk_widget_show (image);
g_signal_connect (image, "size-allocate",
G_CALLBACK (wmf_preview_callback),
pixbuf);
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);
/* Run the dialog. */
run = gimp_procedure_dialog_run (GIMP_PROCEDURE_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (pixbuf->pixels);
g_free (pixbuf);
return run;
}
@ -564,134 +495,6 @@ pixbuf_gd_convert (const gint *gd_pixels,
return pixels;
}
static WmfPixbuf *
wmf_get_pixbuf (GFile *file,
gint *width,
gint *height)
{
WmfPixbuf *pixbuf = NULL;
GMappedFile *mapped;
guchar *pixels = NULL;
/* the bits we need to decode the WMF via libwmf2's GD layer */
wmf_error_t err;
gulong flags;
wmf_gd_t *ddata = NULL;
wmfAPI *API = NULL;
wmfAPI_Options api_options;
guint file_width;
guint file_height;
wmfD_Rect bbox;
gint *gd_pixels = NULL;
char* wmffontdirs[2] = { NULL, NULL };
mapped = g_mapped_file_new (g_file_peek_path (file), FALSE, NULL);
if (! mapped)
return NULL;
flags = WMF_OPT_IGNORE_NONFATAL | WMF_OPT_FUNCTION;
api_options.function = wmf_gd_function;
#ifdef ENABLE_RELOCATABLE_RESOURCES
wmffontdirs[0] = g_build_filename (gimp_installation_directory (),
"share/libwmf/fonts", NULL);
flags |= WMF_OPT_FONTDIRS;
api_options.fontdirs = wmffontdirs;
#endif
err = wmf_api_create (&API, flags, &api_options);
if (wmffontdirs[0])
g_free (wmffontdirs[0]);
if (err != wmf_E_None)
goto _wmf_error;
ddata = WMF_GD_GetData (API);
ddata->type = wmf_gd_image;
err = wmf_mem_open (API,
(guchar *) g_mapped_file_get_contents (mapped),
g_mapped_file_get_length (mapped));
if (err != wmf_E_None)
goto _wmf_error;
err = wmf_scan (API, 0, &bbox);
if (err != wmf_E_None)
goto _wmf_error;
err = wmf_display_size (API, &file_width, &file_height,
WMF_DEFAULT_RESOLUTION, WMF_DEFAULT_RESOLUTION);
if (err != wmf_E_None || file_width <= 0 || file_height <= 0)
goto _wmf_error;
if (!*width || !*height)
goto _wmf_error;
/* either both arguments negative or none */
if ((*width * *height) < 0)
goto _wmf_error;
ddata->bbox = bbox;
if (*width > 0)
{
ddata->width = *width;
ddata->height = *height;
}
else
{
gdouble w = file_width;
gdouble h = file_height;
gdouble aspect = ((gdouble) *width) / (gdouble) *height;
if (aspect > (w / h))
{
ddata->height = abs (*height);
ddata->width = (gdouble) abs (*width) * (w / h) + 0.5;
}
else
{
ddata->width = abs (*width);
ddata->height = (gdouble) abs (*height) / (w / h) + 0.5;
}
}
err = wmf_play (API, 0, &bbox);
if (err != wmf_E_None)
goto _wmf_error;
if (ddata->gd_image != NULL)
gd_pixels = wmf_gd_image_pixels (ddata->gd_image);
if (gd_pixels == NULL)
goto _wmf_error;
pixels = pixbuf_gd_convert (gd_pixels, ddata->width, ddata->height);
if (pixels == NULL)
goto _wmf_error;
*width = ddata->width;
*height = ddata->height;
_wmf_error:
if (API)
{
wmf_mem_close (API);
wmf_api_destroy (API);
}
g_mapped_file_unref (mapped);
if (pixels)
{
pixbuf = g_new0 (WmfPixbuf, 1);
pixbuf->pixels = pixels;
pixbuf->width = *width;
pixbuf->height = *height;
}
return pixbuf;
}
static guchar *
wmf_load_file (GFile *file,
gint requested_width,