app, libgimp, pdb: new GimpVectorLoadProcedure class.

It's still basic but will help to share code for support of various vector-able
formats, such as the logic for dimensioning them, but also the generated GUI.

Not only this, but we are paving the way for the link layers (though it'll be
after GIMP 3, we want plug-in procedures' API to stay stable) by giving a way
for a plug-in procedure to advertize a vector format support. This way, the core
will know when a source file is vector and can be directly reloaded at any
target size (right now, in my MR for link layers, the list of "vector" formats
is hardcoded, which is not reliable).
This commit is contained in:
Jehan 2024-04-22 23:11:37 +02:00
parent c363991cad
commit 768f871bc7
17 changed files with 692 additions and 2 deletions

View File

@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 784 procedures registered total */
/* 785 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View File

@ -1045,6 +1045,38 @@ pdb_set_file_proc_handles_raw_invoker (GimpProcedure *procedure,
error ? *error : NULL);
}
static GimpValueArray *
pdb_set_file_proc_handles_vector_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
const gchar *procedure_name;
procedure_name = g_value_get_string (gimp_value_array_index (args, 0));
if (success)
{
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in &&
gimp_pdb_is_canonical_procedure (procedure_name, error))
{
success = gimp_plug_in_set_file_proc_handles_vector (plug_in,
procedure_name,
error);
}
else
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GimpValueArray *
pdb_set_file_proc_thumbnail_loader_invoker (GimpProcedure *procedure,
Gimp *gimp,
@ -2093,6 +2125,30 @@ register_pdb_procs (GimpPDB *pdb)
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-pdb-set-file-proc-handles-vector
*/
procedure = gimp_procedure_new (pdb_set_file_proc_handles_vector_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-pdb-set-file-proc-handles-vector");
gimp_procedure_set_static_help (procedure,
"Registers a load handler procedure as handling vector formats.",
"Registers a file handler procedure as handling vector image formats. Use this procedure only to register a GimpVectorLoadProcedure, calling it on any other handler will generate an error.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",
"Jehan",
"2024");
gimp_procedure_add_argument (procedure,
gimp_param_spec_string ("procedure-name",
"procedure name",
"The name of the vector load procedure.",
FALSE, FALSE, TRUE,
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-pdb-set-file-proc-thumbnail-loader
*/

View File

@ -542,11 +542,95 @@ gimp_plug_in_set_file_proc_handles_raw (GimpPlugIn *plug_in,
return FALSE;
}
if (proc->handles_vector)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_FAILED,
"Plug-in \"%s\"\n(%s)\n"
"attempted to register 'handles raw' "
"for procedure \"%s\" which already 'handles vector'.\n"
"It cannot handle both.",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
proc_name);
return FALSE;
}
gimp_plug_in_procedure_set_handles_raw (proc);
return TRUE;
}
gboolean
gimp_plug_in_set_file_proc_handles_vector (GimpPlugIn *plug_in,
const gchar *proc_name,
GError **error)
{
GimpPlugInProcedure *proc;
GimpProcedure *procedure;
g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
g_return_val_if_fail (proc_name != NULL, FALSE);
proc = gimp_plug_in_proc_find (plug_in, proc_name);
if (! proc)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_PROCEDURE_NOT_FOUND,
"Plug-in \"%s\"\n(%s)\n"
"attempted to register 'handles vector' "
"for procedure \"%s\".\n"
"It has however not installed that procedure. "
"This is not allowed.",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
proc_name);
return FALSE;
}
procedure = GIMP_PROCEDURE (proc);
if (procedure->num_args < 4 ||
procedure->num_values < 1 ||
! GIMP_IS_PARAM_SPEC_RUN_MODE (procedure->args[0]) ||
! GIMP_IS_PARAM_SPEC_FILE (procedure->args[1]) ||
! G_IS_PARAM_SPEC_INT (procedure->args[2]) ||
! G_IS_PARAM_SPEC_INT (procedure->args[3]) ||
! GIMP_IS_PARAM_SPEC_IMAGE (procedure->values[0]))
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_FAILED,
"Plug-in \"%s\"\n(%s)\n"
"attempted to register procedure \"%s\" "
"as a vector load procedure which does not take the "
"standard load procedure procedure arguments: "
"(GimpRunMode, file, int, int) -> (image)",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
proc_name);
return FALSE;
}
if (proc->handles_raw)
{
g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_FAILED,
"Plug-in \"%s\"\n(%s)\n"
"attempted to register 'handles vector' "
"for procedure \"%s\" which already 'handles raw'.\n"
"It cannot handle both.",
gimp_object_get_name (plug_in),
gimp_file_get_utf8_name (plug_in->file),
proc_name);
return FALSE;
}
gimp_plug_in_procedure_set_handles_vector (proc);
return TRUE;
}
gboolean
gimp_plug_in_set_file_proc_thumb_loader (GimpPlugIn *plug_in,
const gchar *proc_name,

View File

@ -81,6 +81,9 @@ gboolean gimp_plug_in_set_file_proc_handles_remote (GimpPlugIn *plug_in,
gboolean gimp_plug_in_set_file_proc_handles_raw (GimpPlugIn *plug_in,
const gchar *proc_name,
GError **error);
gboolean gimp_plug_in_set_file_proc_handles_vector (GimpPlugIn *plug_in,
const gchar *proc_name,
GError **error);
gboolean gimp_plug_in_set_file_proc_thumb_loader (GimpPlugIn *plug_in,
const gchar *proc_name,
const gchar *thumb_proc,

View File

@ -1252,6 +1252,14 @@ gimp_plug_in_procedure_set_handles_raw (GimpPlugInProcedure *proc)
proc->handles_raw = TRUE;
}
void
gimp_plug_in_procedure_set_handles_vector (GimpPlugInProcedure *proc)
{
g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
proc->handles_vector = TRUE;
}
void
gimp_plug_in_procedure_set_thumb_loader (GimpPlugInProcedure *proc,
const gchar *thumb_loader)

View File

@ -64,6 +64,7 @@ struct _GimpPlugInProcedure
gchar *mime_types;
gboolean handles_remote;
gboolean handles_raw;
gboolean handles_vector;
gboolean batch_interpreter;
gchar *batch_interpreter_name;
GSList *extensions_list;
@ -136,6 +137,7 @@ void gimp_plug_in_procedure_set_mime_types (GimpPlugInProcedure *pro
const gchar *mime_ypes);
void gimp_plug_in_procedure_set_handles_remote(GimpPlugInProcedure *proc);
void gimp_plug_in_procedure_set_handles_raw (GimpPlugInProcedure *proc);
void gimp_plug_in_procedure_set_handles_vector (GimpPlugInProcedure *proc);
void gimp_plug_in_procedure_set_thumb_loader (GimpPlugInProcedure *proc,
const gchar *thumbnailer);
void gimp_plug_in_procedure_set_batch_interpreter (GimpPlugInProcedure *proc,

View File

@ -40,7 +40,7 @@
#include "gimp-intl.h"
#define PLUG_IN_RC_FILE_VERSION 13
#define PLUG_IN_RC_FILE_VERSION 14
/*
@ -92,6 +92,7 @@ enum
MIME_TYPES,
HANDLES_REMOTE,
HANDLES_RAW,
HANDLES_VECTOR,
THUMB_LOADER,
BATCH_INTERPRETER,
};
@ -162,6 +163,8 @@ plug_in_rc_parse (Gimp *gimp,
"handles-remote", GINT_TO_POINTER (HANDLES_REMOTE));
g_scanner_scope_add_symbol (scanner, LOAD_PROC,
"handles-raw", GINT_TO_POINTER (HANDLES_RAW));
g_scanner_scope_add_symbol (scanner, LOAD_PROC,
"handles-vector", GINT_TO_POINTER (HANDLES_VECTOR));
g_scanner_scope_add_symbol (scanner, LOAD_PROC,
"thumb-loader", GINT_TO_POINTER (THUMB_LOADER));
@ -717,6 +720,10 @@ plug_in_file_or_batch_proc_deserialize (GScanner *scanner,
gimp_plug_in_procedure_set_handles_raw (proc);
break;
case HANDLES_VECTOR:
gimp_plug_in_procedure_set_handles_vector (proc);
break;
case THUMB_LOADER:
{
gchar *thumb_loader;
@ -1408,6 +1415,12 @@ plug_in_rc_write (GSList *plug_in_defs,
gimp_config_writer_close (writer);
}
if (proc->handles_vector)
{
gimp_config_writer_open (writer, "handles-vector");
gimp_config_writer_close (writer);
}
if (proc->thumb_loader)
{
gimp_config_writer_open (writer, "thumb-loader");

View File

@ -884,6 +884,8 @@ EXPORTS
gimp_tile_height
gimp_tile_width
gimp_user_time
gimp_vector_load_procedure_get_type
gimp_vector_load_procedure_new
gimp_vectors_bezier_stroke_conicto
gimp_vectors_bezier_stroke_cubicto
gimp_vectors_bezier_stroke_lineto

View File

@ -66,6 +66,7 @@
#include <libgimp/gimpselection.h>
#include <libgimp/gimptextlayer.h>
#include <libgimp/gimpthumbnailprocedure.h>
#include <libgimp/gimpvectorloadprocedure.h>
#include <libgimp/gimpvectors.h>
/* Resources and their widgets. Order important. */

View File

@ -372,6 +372,9 @@ gimp_load_procedure_new (GimpPlugIn *plug_in,
*
* Registers a load procedure as capable of handling raw digital camera loads.
*
* Note that you cannot call this function on [Class@VectorLoadProcedure]
* subclass objects.
*
* Since: 3.0
**/
void

View File

@ -105,6 +105,8 @@ void gimp_load_procedure_set_thumbnail_loader (GimpLoadProcedure *pro
const gchar *thumbnail_proc);
const gchar * gimp_load_procedure_get_thumbnail_loader (GimpLoadProcedure *procedure);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GimpLoadProcedure, g_object_unref);
G_END_DECLS

View File

@ -1090,6 +1090,43 @@ _gimp_pdb_set_file_proc_handles_raw (const gchar *procedure_name)
return success;
}
/**
* _gimp_pdb_set_file_proc_handles_vector:
* @procedure_name: The name of the vector load procedure.
*
* Registers a load handler procedure as handling vector formats.
*
* Registers a file handler procedure as handling vector image formats.
* Use this procedure only to register a GimpVectorLoadProcedure,
* calling it on any other handler will generate an error.
*
* Returns: TRUE on success.
*
* Since: 3.0
**/
gboolean
_gimp_pdb_set_file_proc_handles_vector (const gchar *procedure_name)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
G_TYPE_STRING, procedure_name,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-pdb-set-file-proc-handles-vector",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}
/**
* _gimp_pdb_set_file_proc_thumbnail_loader:
* @load_proc: The name of the file load procedure.

View File

@ -94,6 +94,7 @@ G_GNUC_INTERNAL gboolean _gimp_pdb_set_file_proc_mime_types (const gcha
const gchar *mime_types);
G_GNUC_INTERNAL gboolean _gimp_pdb_set_file_proc_handles_remote (const gchar *procedure_name);
G_GNUC_INTERNAL gboolean _gimp_pdb_set_file_proc_handles_raw (const gchar *procedure_name);
G_GNUC_INTERNAL gboolean _gimp_pdb_set_file_proc_handles_vector (const gchar *procedure_name);
G_GNUC_INTERNAL gboolean _gimp_pdb_set_file_proc_thumbnail_loader (const gchar *load_proc,
const gchar *thumb_proc);
G_GNUC_INTERNAL gboolean _gimp_pdb_set_batch_interpreter (const gchar *procedure_name,

View File

@ -0,0 +1,333 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorloadprocedure.c
* Copyright (C) 2024 Jehan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gimp.h"
#include "libgimpbase/gimpwire.h" /* FIXME kill this include */
#include "gimpvectorloadprocedure.h"
#include "gimppdb_pdb.h"
#include "gimpplugin-private.h"
#include "gimpprocedureconfig-private.h"
#include "libgimp-intl.h"
/**
* GimpVectorLoadProcedure:
*
* A [class@Procedure] subclass that makes it easier to write load procedures
* for vector image formats.
*
* It automatically adds the standard arguments:
* ([enum@RunMode], [iface@Gio.File], int width, int height)
*
* and the standard return value: ( [class@Image] )
*
* It is possible to add additional arguments.
*
* 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
* additionally added arguments but also the arguments added by this class.
*/
struct _GimpVectorLoadProcedure
{
GimpLoadProcedure parent_instance;
GimpRunVectorLoadFunc run_func;
gpointer run_data;
GDestroyNotify run_data_destroy;
};
static void gimp_vector_load_procedure_constructed (GObject *object);
static void gimp_vector_load_procedure_finalize (GObject *object);
static void gimp_vector_load_procedure_install (GimpProcedure *procedure);
static GimpValueArray * gimp_vector_load_procedure_run (GimpProcedure *procedure,
const GimpValueArray *args);
G_DEFINE_FINAL_TYPE (GimpVectorLoadProcedure, gimp_vector_load_procedure, GIMP_TYPE_LOAD_PROCEDURE)
#define parent_class gimp_vector_load_procedure_parent_class
static void
gimp_vector_load_procedure_class_init (GimpVectorLoadProcedureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpProcedureClass *procedure_class = GIMP_PROCEDURE_CLASS (klass);
object_class->constructed = gimp_vector_load_procedure_constructed;
object_class->finalize = gimp_vector_load_procedure_finalize;
procedure_class->install = gimp_vector_load_procedure_install;
procedure_class->run = gimp_vector_load_procedure_run;
}
static void
gimp_vector_load_procedure_init (GimpVectorLoadProcedure *procedure)
{
}
static void
gimp_vector_load_procedure_constructed (GObject *object)
{
GimpProcedure *procedure = GIMP_PROCEDURE (object);
G_OBJECT_CLASS (parent_class)->constructed (object);
GIMP_PROC_ARG_INT (procedure, "width",
"_Width (pixels)",
"Width (in pixels) to load the image in. "
"(0 for the corresponding width per native ratio)",
0, GIMP_MAX_IMAGE_SIZE, 0,
GIMP_PARAM_READWRITE);
GIMP_PROC_ARG_INT (procedure, "height",
"_Height (pixels)",
"Height (in pixels) to load the image in. "
"(0 for the corresponding height per native ratio)",
0, GIMP_MAX_IMAGE_SIZE, 0,
GIMP_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "keep-ratio",
_("_Keep aspect ratio"),
_("Force dimensions with aspect ratio"),
TRUE,
G_PARAM_READWRITE);
GIMP_PROC_ARG_BOOLEAN (procedure, "prefer-native-dimensions",
_("_Prefer native dimensions"),
_("Load and use dimensions from source file"),
FALSE,
G_PARAM_READWRITE);
/* Note: the "pixel-density" is saved in pixels per inch. "physical-unit"
* property is only there for display.
*/
GIMP_PROC_AUX_ARG_DOUBLE (procedure, "pixel-density",
_("Resolu_tion"),
_("Pixel Density: number of pixels per physical unit"),
1.0, 5000.0, 300.0,
G_PARAM_READWRITE);
GIMP_PROC_AUX_ARG_INT (procedure, "physical-unit",
_("Unit"),
_("Physical unit"),
GIMP_UNIT_INCH, GIMP_UNIT_PICA, GIMP_UNIT_INCH,
G_PARAM_READWRITE);
}
static void
gimp_vector_load_procedure_finalize (GObject *object)
{
GimpVectorLoadProcedure *procedure = GIMP_VECTOR_LOAD_PROCEDURE (object);
if (procedure->run_data_destroy)
procedure->run_data_destroy (procedure->run_data);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gimp_vector_load_procedure_install (GimpProcedure *procedure)
{
GIMP_PROCEDURE_CLASS (parent_class)->install (procedure);
_gimp_pdb_set_file_proc_handles_vector (gimp_procedure_get_name (procedure));
}
static GimpValueArray *
gimp_vector_load_procedure_run (GimpProcedure *procedure,
const GimpValueArray *args)
{
GimpPlugIn *plug_in;
GimpVectorLoadProcedure *load_proc = GIMP_VECTOR_LOAD_PROCEDURE (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;
GimpRunMode run_mode;
GFile *file;
gint width;
gint height;
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++);
remaining = gimp_value_array_new (gimp_value_array_length (args) - arg_offset);
for (i = 2 /*arg_offset*/; i < gimp_value_array_length (args); i++)
{
GValue *value = gimp_value_array_index (args, i);
gimp_value_array_append (remaining, value);
}
config = gimp_procedure_create_config (procedure);
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);
}
else
{
flags = GIMP_METADATA_LOAD_NONE;
}
if (metadata == NULL)
metadata = gimp_metadata_new ();
_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);
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 (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. "
"This is a bug in the plug-in code. Contact the plug-in developer."));
gimp_value_array_unref (return_values);
return_values = gimp_procedure_new_return_values (procedure, status, error);
}
else
{
image = GIMP_VALUES_GET_IMAGE (return_values, 1);
}
}
if (image != NULL && metadata != NULL && flags != GIMP_METADATA_LOAD_NONE)
gimp_image_metadata_load_finish (image, NULL, metadata, flags);
/* This is debug printing to help plug-in developers figure out best
* practices.
*/
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 "
"by plug-in, it MUST NOT do that!\n", G_STRFUNC);
g_object_unref (config);
g_clear_object (&metadata);
gimp_value_array_unref (remaining);
return return_values;
}
/* public functions */
/**
* gimp_vector_load_procedure_new:
* @plug_in: a #GimpPlugIn.
* @name: the new procedure's name.
* @proc_type: the new procedure's #GimpPDBProcType.
* @run_func: the run function for the new procedure.
* @run_data: user data passed to @run_func.
* @run_data_destroy: (nullable): free function for @run_data, or %NULL.
*
* Creates a new load procedure named @name which will call @run_func
* when invoked.
*
* See gimp_procedure_new() for information about @proc_type.
*
* Returns: (transfer full): a new #GimpProcedure.
*
* Since: 3.0
**/
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)
{
GimpVectorLoadProcedure *procedure;
g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL);
g_return_val_if_fail (gimp_is_canonical_identifier (name), NULL);
g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_INTERNAL, NULL);
g_return_val_if_fail (proc_type != GIMP_PDB_PROC_TYPE_EXTENSION, NULL);
g_return_val_if_fail (run_func != NULL, NULL);
procedure = g_object_new (GIMP_TYPE_VECTOR_LOAD_PROCEDURE,
"plug-in", plug_in,
"name", name,
"procedure-type", proc_type,
NULL);
procedure->run_func = run_func;
procedure->run_data = run_data;
procedure->run_data_destroy = run_data_destroy;
return GIMP_PROCEDURE (procedure);
}

View File

@ -0,0 +1,106 @@
/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpvectorloadprocedure.h
* Copyright (C) 2024 Jehan
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#ifndef __GIMP_VECTOR_LOAD_PROCEDURE_H__
#define __GIMP_VECTOR_LOAD_PROCEDURE_H__
#include <libgimp/gimpfileprocedure.h>
G_BEGIN_DECLS
/* For information look into the C source or the html documentation */
/**
* GimpRunVectorLoadFunc:
* @procedure: the [class@Gimp.Procedure] that runs.
* @run_mode: the [enum@RunMode].
* @file: the [class@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.
* @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().
*
* The load function is run during the lifetime of the GIMP session, each time a
* plug-in load procedure is called.
*
* You are expected to read @file and create a [class@Gimp.Image] out of its
* data. This image will be the first return value.
* @metadata will be filled from metadata from @file if our infrastructure
* supports this format. You may tweak this object, for instance adding metadata
* specific to the format. You can also edit @flags if you need to filter out
* some specific common fields. For instance, it is customary to remove a
* colorspace field with [const@MetadataLoadFlags] when a profile was added.
*
* Regarding returned image dimensions:
*
* 1. If @width or @height is 0 or negative, the actual value will be computed
* so that ratio is preserved. If @prefer_native_dimension is %FALSE, at
* least one of the 2 dimensions should be strictly positive.
* 2. If @preserve_ratio is %TRUE, then @width and @height are considered as a
* max size in their respective dimension. I.e. that the resulting image will
* be at most @widthx@height while preserving original ratio. @preserve_ratio
* is implied when any of the dimension is 0 or negative.
* 3. If @prefer_native_dimension is %TRUE, and if the image has some kind of
* native size (if the format has such metadata or it can be computed), it
* will be used rather than @widthx@height. Note that if both dimensions are
* 0 or negative, even if @prefer_native_dimension is TRUE yet the procedure
* cannot determine native dimensions, then maybe a dialog could be popped
* up (if implemented), unless the @run_mode is [enum@RunMode.NONINTERACTIVE].
*
* Returns: (transfer full): the @procedure's return values.
*
* Since: 3.0
**/
typedef GimpValueArray * (* GimpRunVectorLoadFunc) (GimpProcedure *procedure,
GimpRunMode run_mode,
GFile *file,
gint width,
gint height,
gboolean preserve_ratio,
gboolean prefer_native_dimension,
GimpMetadata *metadata,
GimpMetadataLoadFlags *flags,
GimpProcedureConfig *config,
gpointer run_data);
#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)
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);
G_END_DECLS
#endif /* __GIMP_VECTOR_LOAD_PROCEDURE_H__ */

View File

@ -203,6 +203,7 @@ libgimp_sources_introspectable = [
'gimptextlayer.c',
'gimpthumbnailprocedure.c',
'gimpvectors.c',
'gimpvectorloadprocedure.c',
gimpenums,
pdb_wrappers_sources,
]

View File

@ -1113,6 +1113,43 @@ CODE
);
}
sub pdb_set_file_proc_handles_vector {
$blurb = 'Registers a load handler procedure as handling vector formats.';
$help = <<'HELP';
Registers a file handler procedure as handling vector image formats.
Use this procedure only to register a GimpVectorLoadProcedure,
calling it on any other handler will generate an error.
HELP
&jehan_pdb_misc('2024', '3.0');
$lib_private = 1;
@inargs = (
{ name => 'procedure_name', type => 'string', non_empty => 1,
desc => "The name of the vector load procedure." }
);
%invoke = (
code => <<'CODE'
{
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
if (plug_in &&
gimp_pdb_is_canonical_procedure (procedure_name, error))
{
success = gimp_plug_in_set_file_proc_handles_vector (plug_in,
procedure_name,
error);
}
else
success = FALSE;
}
CODE
);
}
sub pdb_set_file_proc_thumbnail_loader {
$blurb = 'Associates a thumbnail loader with a file load procedure.';
@ -1351,6 +1388,7 @@ CODE
pdb_set_file_proc_mime_types
pdb_set_file_proc_handles_remote
pdb_set_file_proc_handles_raw
pdb_set_file_proc_handles_vector
pdb_set_file_proc_thumbnail_loader
pdb_set_batch_interpreter
pdb_get_data